Reactos
at master 352 lines 12 kB view raw
1/* 2 * PROJECT: ReactOS API tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Test for NtWriteFile 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8#include "precomp.h" 9 10static 11BOOL 12Is64BitSystem(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#ifdef _WIN64 35#define IsWow64() FALSE 36#else 37#define IsWow64() Is64BitSystem() 38#endif 39 40static 41ULONG 42SizeOfMdl(VOID) 43{ 44 return Is64BitSystem() ? 48 : 28; 45} 46 47static 48ULONG 49SizeOfSector(VOID) 50{ 51 BOOL Ret; 52 ULONG SectorSize; 53 54 /* FIXME: Would be better to actually open systemroot */ 55 Ret = GetDiskFreeSpaceW(NULL, NULL, &SectorSize, NULL, NULL); 56 ok(Ret != FALSE, "GetDiskFreeSpaceW failed: %lx\n", GetLastError()); 57 if (!Ret) 58 { 59 SectorSize = 4096; /* On failure, assume max size */ 60 } 61 62 return SectorSize; 63} 64 65START_TEST(NtWriteFile) 66{ 67 NTSTATUS Status; 68 HANDLE FileHandle; 69 UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\ntdll-apitest-NtWriteFile-test.bin"); 70 PVOID Buffer; 71 SIZE_T BufferSize; 72 LARGE_INTEGER ByteOffset; 73 OBJECT_ATTRIBUTES ObjectAttributes; 74 IO_STATUS_BLOCK IoStatus; 75 FILE_DISPOSITION_INFORMATION DispositionInfo; 76 ULONG TooLargeDataSize = (MAXUSHORT + 1 - SizeOfMdl()) / sizeof(ULONG_PTR) * PAGE_SIZE; // 0x3FF9000 on x86 77 ULONG LargeMdlMaxDataSize = TooLargeDataSize - PAGE_SIZE; 78 79 trace("System is %d bits, Size of MDL: %lu\n", Is64BitSystem() ? 64 : 32, SizeOfMdl()); 80 trace("Max MDL data size: 0x%lx bytes\n", LargeMdlMaxDataSize); 81 82 ByteOffset.QuadPart = 0; 83 84 Buffer = NULL; 85 BufferSize = TooLargeDataSize; 86 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 87 &Buffer, 88 0, 89 &BufferSize, 90 MEM_RESERVE | MEM_COMMIT, 91 PAGE_READONLY); 92 if (!NT_SUCCESS(Status)) 93 { 94 skip("Failed to allocate memory, status %lx\n", Status); 95 return; 96 } 97 98 InitializeObjectAttributes(&ObjectAttributes, 99 &FileName, 100 OBJ_CASE_INSENSITIVE, 101 NULL, 102 NULL); 103 Status = NtCreateFile(&FileHandle, 104 FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 105 &ObjectAttributes, 106 &IoStatus, 107 NULL, 108 0, 109 0, 110 FILE_SUPERSEDE, 111 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | 112 FILE_NO_INTERMEDIATE_BUFFERING, 113 NULL, 114 0); 115 ok_hex(Status, STATUS_SUCCESS); 116 117 /* non-cached, max size -- succeeds */ 118 Status = NtWriteFile(FileHandle, 119 NULL, 120 NULL, 121 NULL, 122 &IoStatus, 123 Buffer, 124 LargeMdlMaxDataSize - PAGE_SIZE, 125 &ByteOffset, 126 NULL); 127 ok_hex(Status, STATUS_SUCCESS); 128 129 /* non-cached, max size -- succeeds */ 130 Status = NtWriteFile(FileHandle, 131 NULL, 132 NULL, 133 NULL, 134 &IoStatus, 135 Buffer, 136 LargeMdlMaxDataSize, 137 &ByteOffset, 138 NULL); 139 ok_hex(Status, STATUS_SUCCESS); 140 141 /* non-cached, too large -- fails to allocate MDL 142 * Note: this returns STATUS_SUCCESS on Vista+ -- higher MDL size limit */ 143 Status = NtWriteFile(FileHandle, 144 NULL, 145 NULL, 146 NULL, 147 &IoStatus, 148 Buffer, 149 LargeMdlMaxDataSize + PAGE_SIZE, 150 &ByteOffset, 151 NULL); 152 if (GetNTVersion() >= _WIN32_WINNT_VISTA) 153 ok_hex(Status, STATUS_SUCCESS); 154 else 155 ok_hex(Status, STATUS_INSUFFICIENT_RESOURCES); 156 157 /* Invalid buffer address */ 158 Status = NtWriteFile(FileHandle, 159 NULL, 160 NULL, 161 NULL, 162 &IoStatus, 163 LongToPtr(-1), 164 PAGE_SIZE, 165 &ByteOffset, 166 NULL); 167 ok_hex(Status, IsWow64() ? STATUS_INVALID_PARAMETER : STATUS_ACCESS_VIOLATION); // Different to NtReadFile 168 169 /* Buffer probing fails */ 170 Status = NtWriteFile(FileHandle, 171 NULL, 172 NULL, 173 NULL, 174 &IoStatus, 175 Buffer, 176 2 * LargeMdlMaxDataSize, 177 &ByteOffset, 178 NULL); 179 ok_hex(Status, Is64BitSystem() ? STATUS_INVALID_USER_BUFFER: STATUS_INSUFFICIENT_RESOURCES); // Different to NtReadFile 180 181 /* non-cached, unaligned -- fails with invalid parameter */ 182 Status = NtWriteFile(FileHandle, 183 NULL, 184 NULL, 185 NULL, 186 &IoStatus, 187 Buffer, 188 LargeMdlMaxDataSize + 1, 189 &ByteOffset, 190 NULL); 191 ok_hex(Status, STATUS_INVALID_PARAMETER); 192 193 DispositionInfo.DeleteFile = TRUE; 194 Status = NtSetInformationFile(FileHandle, 195 &IoStatus, 196 &DispositionInfo, 197 sizeof(DispositionInfo), 198 FileDispositionInformation); 199 ok_hex(Status, STATUS_SUCCESS); 200 Status = NtClose(FileHandle); 201 ok_hex(Status, STATUS_SUCCESS); 202 203 Status = NtCreateFile(&FileHandle, 204 FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 205 &ObjectAttributes, 206 &IoStatus, 207 NULL, 208 0, 209 0, 210 FILE_SUPERSEDE, 211 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 212 NULL, 213 0); 214 ok_hex(Status, STATUS_SUCCESS); 215 216 /* cached: succeeds with arbitrary length */ 217 Status = NtWriteFile(FileHandle, 218 NULL, 219 NULL, 220 NULL, 221 &IoStatus, 222 Buffer, 223 LargeMdlMaxDataSize, 224 &ByteOffset, 225 NULL); 226 ok_hex(Status, STATUS_SUCCESS); 227 228 Status = NtWriteFile(FileHandle, 229 NULL, 230 NULL, 231 NULL, 232 &IoStatus, 233 Buffer, 234 LargeMdlMaxDataSize + 1, 235 &ByteOffset, 236 NULL); 237 ok_hex(Status, STATUS_SUCCESS); 238 239 Status = NtWriteFile(FileHandle, 240 NULL, 241 NULL, 242 NULL, 243 &IoStatus, 244 Buffer, 245 TooLargeDataSize, 246 &ByteOffset, 247 NULL); 248 ok_hex(Status, STATUS_SUCCESS); 249 250 DispositionInfo.DeleteFile = TRUE; 251 Status = NtSetInformationFile(FileHandle, 252 &IoStatus, 253 &DispositionInfo, 254 sizeof(DispositionInfo), 255 FileDispositionInformation); 256 ok_hex(Status, STATUS_SUCCESS); 257 Status = NtClose(FileHandle); 258 ok_hex(Status, STATUS_SUCCESS); 259 260 Status = NtFreeVirtualMemory(NtCurrentProcess(), 261 &Buffer, 262 &BufferSize, 263 MEM_RELEASE); 264 ok_hex(Status, STATUS_SUCCESS); 265 266 /* Now, testing aligned/non aligned writes */ 267 268 BufferSize = SizeOfSector(); 269 trace("Sector is %ld bytes\n", BufferSize); 270 271 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 272 &Buffer, 273 0, 274 &BufferSize, 275 MEM_RESERVE | MEM_COMMIT, 276 PAGE_READONLY); 277 if (!NT_SUCCESS(Status)) 278 { 279 skip("Failed to allocate memory, status %lx\n", Status); 280 return; 281 } 282 283 Status = NtCreateFile(&FileHandle, 284 FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 285 &ObjectAttributes, 286 &IoStatus, 287 NULL, 288 0, 289 0, 290 FILE_SUPERSEDE, 291 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | 292 FILE_NO_INTERMEDIATE_BUFFERING | 293 FILE_WRITE_THROUGH, 294 NULL, 295 0); 296 ok_hex(Status, STATUS_SUCCESS); 297 298 /* non-cached, broken length -- fails with invalid parameter */ 299 ByteOffset.QuadPart = 0; 300 Status = NtWriteFile(FileHandle, 301 NULL, 302 NULL, 303 NULL, 304 &IoStatus, 305 Buffer, 306 4, 307 &ByteOffset, 308 NULL); 309 ok_hex(Status, STATUS_INVALID_PARAMETER); 310 311 /* non-cached, broken offset -- fails with invalid parameter */ 312 ByteOffset.QuadPart = 4; 313 Status = NtWriteFile(FileHandle, 314 NULL, 315 NULL, 316 NULL, 317 &IoStatus, 318 Buffer, 319 BufferSize, 320 &ByteOffset, 321 NULL); 322 ok_hex(Status, STATUS_INVALID_PARAMETER); 323 324 /* non-cached, good length and offset -- succeeds */ 325 ByteOffset.QuadPart = 0; 326 Status = NtWriteFile(FileHandle, 327 NULL, 328 NULL, 329 NULL, 330 &IoStatus, 331 Buffer, 332 BufferSize, 333 &ByteOffset, 334 NULL); 335 ok_hex(Status, STATUS_SUCCESS); 336 337 DispositionInfo.DeleteFile = TRUE; 338 Status = NtSetInformationFile(FileHandle, 339 &IoStatus, 340 &DispositionInfo, 341 sizeof(DispositionInfo), 342 FileDispositionInformation); 343 ok_hex(Status, STATUS_SUCCESS); 344 Status = NtClose(FileHandle); 345 ok_hex(Status, STATUS_SUCCESS); 346 347 Status = NtFreeVirtualMemory(NtCurrentProcess(), 348 &Buffer, 349 &BufferSize, 350 MEM_RELEASE); 351 ok_hex(Status, STATUS_SUCCESS); 352}