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