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