1383e4e71c917dc6675b650316a996e2c9465714
[reactos.git] / modules / rostests / apitests / ntdll / NtWriteFile.c
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 /* Now, testing aligned/non aligned writes */
216 BufferSize = 4096; /* We assume max sector size */
217 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
218 &Buffer,
219 0,
220 &BufferSize,
221 MEM_RESERVE | MEM_COMMIT,
222 PAGE_READONLY);
223 if (!NT_SUCCESS(Status))
224 {
225 skip("Failed to allocate memory, status %lx\n", Status);
226 return;
227 }
228
229 Status = NtCreateFile(&FileHandle,
230 FILE_WRITE_DATA | DELETE | SYNCHRONIZE,
231 &ObjectAttributes,
232 &IoStatus,
233 NULL,
234 0,
235 0,
236 FILE_SUPERSEDE,
237 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
238 FILE_NO_INTERMEDIATE_BUFFERING |
239 FILE_WRITE_THROUGH,
240 NULL,
241 0);
242 ok_hex(Status, STATUS_SUCCESS);
243
244 /* non-cached, broken length -- fails with invalid parameter */
245 ByteOffset.QuadPart = 0;
246 Status = NtWriteFile(FileHandle,
247 NULL,
248 NULL,
249 NULL,
250 &IoStatus,
251 Buffer,
252 4,
253 &ByteOffset,
254 NULL);
255 ok_hex(Status, STATUS_INVALID_PARAMETER);
256
257 /* non-cached, broken offset -- fails with invalid parameter */
258 ByteOffset.QuadPart = 4;
259 Status = NtWriteFile(FileHandle,
260 NULL,
261 NULL,
262 NULL,
263 &IoStatus,
264 Buffer,
265 BufferSize,
266 &ByteOffset,
267 NULL);
268 ok_hex(Status, STATUS_INVALID_PARAMETER);
269
270 /* non-cached, good length and offset -- succeeds */
271 ByteOffset.QuadPart = 0;
272 Status = NtWriteFile(FileHandle,
273 NULL,
274 NULL,
275 NULL,
276 &IoStatus,
277 Buffer,
278 BufferSize,
279 &ByteOffset,
280 NULL);
281 ok_hex(Status, STATUS_SUCCESS);
282
283 DispositionInfo.DeleteFile = TRUE;
284 Status = NtSetInformationFile(FileHandle,
285 &IoStatus,
286 &DispositionInfo,
287 sizeof(DispositionInfo),
288 FileDispositionInformation);
289 ok_hex(Status, STATUS_SUCCESS);
290 Status = NtClose(FileHandle);
291 ok_hex(Status, STATUS_SUCCESS);
292
293 Status = NtFreeVirtualMemory(NtCurrentProcess(),
294 &Buffer,
295 &BufferSize,
296 MEM_RELEASE);
297 ok_hex(Status, STATUS_SUCCESS);
298 }