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 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(NtWriteFile) 42 { 43 NTSTATUS Status; 44 HANDLE FileHandle; 45 UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\ntdll-apitest-NtWriteFile-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_READONLY); 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_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 /* non-cached, max size -- succeeds */ 94 Status = NtWriteFile(FileHandle, 95 NULL, 96 NULL, 97 NULL, 98 &IoStatus, 99 Buffer, 100 LargeMdlMaxDataSize - PAGE_SIZE, 101 &ByteOffset, 102 NULL); 103 ok_hex(Status, STATUS_SUCCESS); 104 105 /* non-cached, max size -- succeeds */ 106 Status = NtWriteFile(FileHandle, 107 NULL, 108 NULL, 109 NULL, 110 &IoStatus, 111 Buffer, 112 LargeMdlMaxDataSize, 113 &ByteOffset, 114 NULL); 115 ok_hex(Status, STATUS_SUCCESS); 116 117 /* non-cached, too large -- fails to allocate MDL 118 * Note: this returns STATUS_SUCCESS on Win7 -- higher MDL size limit */ 119 Status = NtWriteFile(FileHandle, 120 NULL, 121 NULL, 122 NULL, 123 &IoStatus, 124 Buffer, 125 LargeMdlMaxDataSize + PAGE_SIZE, 126 &ByteOffset, 127 NULL); 128 ok_hex(Status, STATUS_INSUFFICIENT_RESOURCES); 129 130 /* non-cached, unaligned -- fails with invalid parameter */ 131 Status = NtWriteFile(FileHandle, 132 NULL, 133 NULL, 134 NULL, 135 &IoStatus, 136 Buffer, 137 LargeMdlMaxDataSize + 1, 138 &ByteOffset, 139 NULL); 140 ok_hex(Status, STATUS_INVALID_PARAMETER); 141 142 DispositionInfo.DeleteFile = TRUE; 143 Status = NtSetInformationFile(FileHandle, 144 &IoStatus, 145 &DispositionInfo, 146 sizeof(DispositionInfo), 147 FileDispositionInformation); 148 ok_hex(Status, STATUS_SUCCESS); 149 Status = NtClose(FileHandle); 150 ok_hex(Status, STATUS_SUCCESS); 151 152 Status = NtCreateFile(&FileHandle, 153 FILE_WRITE_DATA | DELETE | SYNCHRONIZE, 154 &ObjectAttributes, 155 &IoStatus, 156 NULL, 157 0, 158 0, 159 FILE_SUPERSEDE, 160 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 161 NULL, 162 0); 163 ok_hex(Status, STATUS_SUCCESS); 164 165 /* cached: succeeds with arbitrary length */ 166 Status = NtWriteFile(FileHandle, 167 NULL, 168 NULL, 169 NULL, 170 &IoStatus, 171 Buffer, 172 LargeMdlMaxDataSize, 173 &ByteOffset, 174 NULL); 175 ok_hex(Status, STATUS_SUCCESS); 176 177 Status = NtWriteFile(FileHandle, 178 NULL, 179 NULL, 180 NULL, 181 &IoStatus, 182 Buffer, 183 LargeMdlMaxDataSize + 1, 184 &ByteOffset, 185 NULL); 186 ok_hex(Status, STATUS_SUCCESS); 187 188 Status = NtWriteFile(FileHandle, 189 NULL, 190 NULL, 191 NULL, 192 &IoStatus, 193 Buffer, 194 TooLargeDataSize, 195 &ByteOffset, 196 NULL); 197 ok_hex(Status, STATUS_SUCCESS); 198 199 DispositionInfo.DeleteFile = TRUE; 200 Status = NtSetInformationFile(FileHandle, 201 &IoStatus, 202 &DispositionInfo, 203 sizeof(DispositionInfo), 204 FileDispositionInformation); 205 ok_hex(Status, STATUS_SUCCESS); 206 Status = NtClose(FileHandle); 207 ok_hex(Status, STATUS_SUCCESS); 208 209 Status = NtFreeVirtualMemory(NtCurrentProcess(), 210 &Buffer, 211 &BufferSize, 212 MEM_RELEASE); 213 ok_hex(Status, STATUS_SUCCESS); 214 } 215