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