[KMTESTS:MM]
[reactos.git] / 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 <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 }