0acc7cf574d286ebe72468ae2ab0c7b405ae1f9a
[reactos.git] / rostests / winetests / ntdll / file.c
1 /* Unit test suite for Ntdll file functions
2 *
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
6 * Copyright 2011 Dmitry Timoshkov
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 *
22 * NOTES
23 * We use function pointers here as there is no import library for NTDLL on
24 * windows.
25 */
26
27 #include <stdio.h>
28 #include <stdarg.h>
29
30 #include "ntstatus.h"
31 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
32 * definition errors when we get to winnt.h
33 */
34 #define WIN32_NO_STATUS
35
36 #include "wine/test.h"
37 #include "wine/winternl.h"
38 #include "winuser.h"
39 #include "wine/winioctl.h"
40
41 /* FIXME */
42 typedef struct _REPARSE_DATA_BUFFER {
43 ULONG ReparseTag;
44 USHORT ReparseDataLength;
45 USHORT Reserved;
46 _ANONYMOUS_UNION union {
47 struct {
48 USHORT SubstituteNameOffset;
49 USHORT SubstituteNameLength;
50 USHORT PrintNameOffset;
51 USHORT PrintNameLength;
52 ULONG Flags;
53 WCHAR PathBuffer[1];
54 } SymbolicLinkReparseBuffer;
55 struct {
56 USHORT SubstituteNameOffset;
57 USHORT SubstituteNameLength;
58 USHORT PrintNameOffset;
59 USHORT PrintNameLength;
60 WCHAR PathBuffer[1];
61 } MountPointReparseBuffer;
62 struct {
63 UCHAR DataBuffer[1];
64 } GenericReparseBuffer;
65 } DUMMYUNIONNAME;
66 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
67
68 #ifndef IO_COMPLETION_ALL_ACCESS
69 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
70 #endif
71
72 static BOOL (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
73 static UINT (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
74
75 static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
76 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
77 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
78 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
79
80 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
81 ULONG, ULONG, ULONG, PLARGE_INTEGER );
82 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
83 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
84 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
85 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
86 PIO_APC_ROUTINE apc, void* apc_user,
87 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
88 PLARGE_INTEGER offset, PULONG key);
89 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
90 PIO_APC_ROUTINE apc, void* apc_user,
91 PIO_STATUS_BLOCK io_status,
92 const void* buffer, ULONG length,
93 PLARGE_INTEGER offset, PULONG key);
94 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
95 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
96 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
97
98 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
99 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
100 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
101 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
102 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
103 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
104 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
105 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
106 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
107 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
108
109 static inline BOOL is_signaled( HANDLE obj )
110 {
111 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
112 }
113
114 static const char* debugstr_longlong(ULONGLONG ll)
115 {
116 static char str[17];
117 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
118 sprintf(str, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
119 else
120 sprintf(str, "%lx", (unsigned long)ll);
121 return str;
122 }
123
124 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
125 #define TEST_BUF_LEN 3
126
127 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
128 {
129 *read = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
130 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
131 ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
132
133 *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
134 ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
135
136 return TRUE;
137 }
138
139 static HANDLE create_temp_file( ULONG flags )
140 {
141 char path[MAX_PATH], buffer[MAX_PATH];
142 HANDLE handle;
143
144 GetTempPathA( MAX_PATH, path );
145 GetTempFileNameA( path, "foo", 0, buffer );
146 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
147 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
148 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
149 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
150 }
151
152 #define CVALUE_FIRST 0xfffabbcc
153 #define CKEY_FIRST 0x1030341
154 #define CKEY_SECOND 0x132E46
155
156 static ULONG_PTR completionKey;
157 static IO_STATUS_BLOCK ioSb;
158 static ULONG_PTR completionValue;
159
160 static ULONG get_pending_msgs(HANDLE h)
161 {
162 NTSTATUS res;
163 ULONG a, req;
164
165 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
166 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
167 if (res != STATUS_SUCCESS) return -1;
168 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
169 return a;
170 }
171
172 static BOOL get_msg(HANDLE h)
173 {
174 LARGE_INTEGER timeout = {{-10000000*3}};
175 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
176 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
177 if (res != STATUS_SUCCESS)
178 {
179 completionKey = completionValue = 0;
180 memset(&ioSb, 0, sizeof(ioSb));
181 return FALSE;
182 }
183 return TRUE;
184 }
185
186
187 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
188 {
189 int *count = arg;
190
191 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
192 iosb, U(*iosb).Status, iosb->Information );
193 (*count)++;
194 ok( !reserved, "reserved is not 0: %x\n", reserved );
195 }
196
197 static void create_file_test(void)
198 {
199 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
200 '\\','f','a','i','l','i','n','g',0};
201 static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
202 static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
203 NTSTATUS status;
204 HANDLE dir, file;
205 WCHAR path[MAX_PATH];
206 OBJECT_ATTRIBUTES attr;
207 IO_STATUS_BLOCK io;
208 UNICODE_STRING nameW;
209
210 GetCurrentDirectoryW( MAX_PATH, path );
211 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
212 attr.Length = sizeof(attr);
213 attr.RootDirectory = 0;
214 attr.ObjectName = &nameW;
215 attr.Attributes = OBJ_CASE_INSENSITIVE;
216 attr.SecurityDescriptor = NULL;
217 attr.SecurityQualityOfService = NULL;
218
219 /* try various open modes and options on directories */
220 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
221 FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
222 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
223 CloseHandle( dir );
224
225 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
226 FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
227 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
228 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
229
230 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
231 FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
232 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
233 CloseHandle( dir );
234
235 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
236 FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
237 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
238
239 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
240 FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
241 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
242
243 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
244 FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
245 ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
246
247 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
248 FILE_OPEN, 0, NULL, 0 );
249 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
250 CloseHandle( dir );
251
252 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
253 FILE_CREATE, 0, NULL, 0 );
254 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
255 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
256
257 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
258 FILE_OPEN_IF, 0, NULL, 0 );
259 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
260 CloseHandle( dir );
261
262 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
263 FILE_SUPERSEDE, 0, NULL, 0 );
264 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
265 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
266
267 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
268 FILE_OVERWRITE, 0, NULL, 0 );
269 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
270 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
271
272 status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
273 FILE_OVERWRITE_IF, 0, NULL, 0 );
274 ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
275 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
276
277 pRtlFreeUnicodeString( &nameW );
278
279 pRtlInitUnicodeString( &nameW, systemrootW );
280 attr.Length = sizeof(attr);
281 attr.RootDirectory = NULL;
282 attr.ObjectName = &nameW;
283 attr.Attributes = OBJ_CASE_INSENSITIVE;
284 attr.SecurityDescriptor = NULL;
285 attr.SecurityQualityOfService = NULL;
286 dir = NULL;
287 status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
288 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
289 todo_wine
290 ok( status == STATUS_INVALID_PARAMETER,
291 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
292
293 /* Invalid chars in file/dirnames */
294 pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
295 attr.ObjectName = &nameW;
296 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
297 FILE_SHARE_READ, FILE_CREATE,
298 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
299 ok(status == STATUS_OBJECT_NAME_INVALID,
300 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
301
302 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
303 0, FILE_CREATE,
304 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
305 ok(status == STATUS_OBJECT_NAME_INVALID,
306 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
307 pRtlFreeUnicodeString(&nameW);
308
309 pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
310 attr.ObjectName = &nameW;
311 status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
312 FILE_SHARE_READ, FILE_CREATE,
313 FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
314 ok(status == STATUS_OBJECT_NAME_INVALID,
315 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
316
317 status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
318 0, FILE_CREATE,
319 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
320 ok(status == STATUS_OBJECT_NAME_INVALID,
321 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
322 pRtlFreeUnicodeString(&nameW);
323 }
324
325 static void open_file_test(void)
326 {
327 NTSTATUS status;
328 HANDLE dir, root, handle;
329 WCHAR path[MAX_PATH];
330 BYTE data[1024];
331 OBJECT_ATTRIBUTES attr;
332 IO_STATUS_BLOCK io;
333 UNICODE_STRING nameW;
334 UINT i, len;
335 BOOL restart = TRUE;
336
337 len = GetWindowsDirectoryW( path, MAX_PATH );
338 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
339 attr.Length = sizeof(attr);
340 attr.RootDirectory = 0;
341 attr.ObjectName = &nameW;
342 attr.Attributes = OBJ_CASE_INSENSITIVE;
343 attr.SecurityDescriptor = NULL;
344 attr.SecurityQualityOfService = NULL;
345 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
346 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
347 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
348 pRtlFreeUnicodeString( &nameW );
349
350 path[3] = 0; /* root of the drive */
351 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
352 status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
353 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
354 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
355 pRtlFreeUnicodeString( &nameW );
356
357 /* test opening system dir with RootDirectory set to windows dir */
358 GetSystemDirectoryW( path, MAX_PATH );
359 while (path[len] == '\\') len++;
360 nameW.Buffer = path + len;
361 nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
362 attr.RootDirectory = dir;
363 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
364 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
365 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
366 CloseHandle( handle );
367
368 /* try uppercase name */
369 for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
370 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
371 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
372 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
373 CloseHandle( handle );
374
375 /* try with leading backslash */
376 nameW.Buffer--;
377 nameW.Length += sizeof(WCHAR);
378 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
379 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
380 ok( status == STATUS_INVALID_PARAMETER ||
381 status == STATUS_OBJECT_NAME_INVALID ||
382 status == STATUS_OBJECT_PATH_SYNTAX_BAD,
383 "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
384 if (!status) CloseHandle( handle );
385
386 /* try with empty name */
387 nameW.Length = 0;
388 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
389 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
390 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
391 CloseHandle( handle );
392
393 /* try open by file id */
394
395 while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
396 FileIdBothDirectoryInformation, TRUE, NULL, restart ))
397 {
398 FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
399
400 restart = FALSE;
401
402 if (!info->FileId.QuadPart) continue;
403
404 nameW.Buffer = (WCHAR *)&info->FileId;
405 nameW.Length = sizeof(info->FileId);
406 info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
407 attr.RootDirectory = dir;
408 /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
409 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
410 FILE_SHARE_READ,
411 FILE_OPEN_BY_FILE_ID |
412 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
413 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
414 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
415 if (status == STATUS_NOT_IMPLEMENTED)
416 {
417 win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
418 break;
419 }
420 if (status == STATUS_SHARING_VIOLATION)
421 trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
422 if (!status)
423 {
424 BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
425
426 if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
427 {
428 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
429
430 /* check that it's the same file/directory */
431
432 /* don't check the size for directories */
433 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
434 ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
435 "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
436
437 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
438 "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
439 }
440 CloseHandle( handle );
441
442 /* try same thing from drive root */
443 attr.RootDirectory = root;
444 status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
445 FILE_SHARE_READ|FILE_SHARE_WRITE,
446 FILE_OPEN_BY_FILE_ID |
447 ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
448 ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
449 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
450 if (!status) CloseHandle( handle );
451 }
452 }
453
454 CloseHandle( dir );
455 CloseHandle( root );
456 }
457
458 static void delete_file_test(void)
459 {
460 NTSTATUS ret;
461 OBJECT_ATTRIBUTES attr;
462 UNICODE_STRING nameW;
463 WCHAR pathW[MAX_PATH];
464 WCHAR pathsubW[MAX_PATH];
465 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
466 static const WCHAR subdirW[] = {'\\','s','u','b',0};
467
468 ret = GetTempPathW(MAX_PATH, pathW);
469 if (!ret)
470 {
471 ok(0, "couldn't get temp dir\n");
472 return;
473 }
474 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
475 {
476 ok(0, "MAX_PATH exceeded in constructing paths\n");
477 return;
478 }
479
480 lstrcatW(pathW, testdirW);
481 lstrcpyW(pathsubW, pathW);
482 lstrcatW(pathsubW, subdirW);
483
484 ret = CreateDirectoryW(pathW, NULL);
485 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
486 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
487 {
488 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
489 return;
490 }
491
492 attr.Length = sizeof(attr);
493 attr.RootDirectory = 0;
494 attr.Attributes = OBJ_CASE_INSENSITIVE;
495 attr.ObjectName = &nameW;
496 attr.SecurityDescriptor = NULL;
497 attr.SecurityQualityOfService = NULL;
498
499 /* test NtDeleteFile on an empty directory */
500 ret = pNtDeleteFile(&attr);
501 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
502 ret = RemoveDirectoryW(pathW);
503 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
504
505 /* test NtDeleteFile on a non-empty directory */
506 ret = CreateDirectoryW(pathW, NULL);
507 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
508 ret = CreateDirectoryW(pathsubW, NULL);
509 ok(ret == TRUE, "couldn't create directory subdir\n");
510 ret = pNtDeleteFile(&attr);
511 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
512 ret = RemoveDirectoryW(pathsubW);
513 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
514 ret = RemoveDirectoryW(pathW);
515 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
516
517 pRtlFreeUnicodeString( &nameW );
518 }
519
520 static void read_file_test(void)
521 {
522 const char text[] = "foobar";
523 HANDLE handle, read, write;
524 NTSTATUS status;
525 IO_STATUS_BLOCK iosb, iosb2;
526 DWORD written;
527 int apc_count = 0;
528 char buffer[128];
529 LARGE_INTEGER offset;
530 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
531 BOOL ret;
532
533 buffer[0] = 1;
534
535 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
536
537 /* try read with no data */
538 U(iosb).Status = 0xdeadbabe;
539 iosb.Information = 0xdeadbeef;
540 ok( is_signaled( read ), "read handle is not signaled\n" );
541 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
542 ok( status == STATUS_PENDING, "wrong status %x\n", status );
543 ok( !is_signaled( read ), "read handle is signaled\n" );
544 ok( !is_signaled( event ), "event is signaled\n" );
545 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
546 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
547 ok( !apc_count, "apc was called\n" );
548 ret = WriteFile( write, buffer, 1, &written, NULL );
549 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
550 /* iosb updated here by async i/o */
551 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
552 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
553 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
554 ok( !is_signaled( read ), "read handle is signaled\n" );
555 ok( is_signaled( event ), "event is not signaled\n" );
556 ok( !apc_count, "apc was called\n" );
557 apc_count = 0;
558 SleepEx( 1, FALSE ); /* non-alertable sleep */
559 ok( !apc_count, "apc was called\n" );
560 SleepEx( 1, TRUE ); /* alertable sleep */
561 ok( apc_count == 1, "apc not called\n" );
562
563 /* with no event, the pipe handle itself gets signaled */
564 apc_count = 0;
565 U(iosb).Status = 0xdeadbabe;
566 iosb.Information = 0xdeadbeef;
567 ok( !is_signaled( read ), "read handle is not signaled\n" );
568 status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
569 ok( status == STATUS_PENDING, "wrong status %x\n", status );
570 ok( !is_signaled( read ), "read handle is signaled\n" );
571 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
572 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
573 ok( !apc_count, "apc was called\n" );
574 ret = WriteFile( write, buffer, 1, &written, NULL );
575 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
576 /* iosb updated here by async i/o */
577 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
578 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
579 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
580 ok( is_signaled( read ), "read handle is signaled\n" );
581 ok( !apc_count, "apc was called\n" );
582 apc_count = 0;
583 SleepEx( 1, FALSE ); /* non-alertable sleep */
584 ok( !apc_count, "apc was called\n" );
585 SleepEx( 1, TRUE ); /* alertable sleep */
586 ok( apc_count == 1, "apc not called\n" );
587
588 /* now read with data ready */
589 apc_count = 0;
590 U(iosb).Status = 0xdeadbabe;
591 iosb.Information = 0xdeadbeef;
592 ResetEvent( event );
593 ret = WriteFile( write, buffer, 1, &written, NULL );
594 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
595 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
596 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
597 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
598 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
599 ok( is_signaled( event ), "event is not signaled\n" );
600 ok( !apc_count, "apc was called\n" );
601 SleepEx( 1, FALSE ); /* non-alertable sleep */
602 ok( !apc_count, "apc was called\n" );
603 SleepEx( 1, TRUE ); /* alertable sleep */
604 ok( apc_count == 1, "apc not called\n" );
605
606 /* try read with no data */
607 apc_count = 0;
608 U(iosb).Status = 0xdeadbabe;
609 iosb.Information = 0xdeadbeef;
610 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
611 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
612 ok( status == STATUS_PENDING, "wrong status %x\n", status );
613 ok( !is_signaled( event ), "event is signaled\n" );
614 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
615 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
616 ok( !apc_count, "apc was called\n" );
617 ret = WriteFile( write, buffer, 1, &written, NULL );
618 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
619 /* partial read is good enough */
620 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
621 ok( is_signaled( event ), "event is signaled\n" );
622 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
623 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
624 ok( !apc_count, "apc was called\n" );
625 SleepEx( 1, TRUE ); /* alertable sleep */
626 ok( apc_count == 1, "apc was not called\n" );
627
628 /* read from disconnected pipe */
629 apc_count = 0;
630 U(iosb).Status = 0xdeadbabe;
631 iosb.Information = 0xdeadbeef;
632 CloseHandle( write );
633 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
634 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
635 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
636 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
637 ok( !is_signaled( event ), "event is signaled\n" );
638 ok( !apc_count, "apc was called\n" );
639 SleepEx( 1, TRUE ); /* alertable sleep */
640 ok( !apc_count, "apc was called\n" );
641 CloseHandle( read );
642
643 /* read from closed handle */
644 apc_count = 0;
645 U(iosb).Status = 0xdeadbabe;
646 iosb.Information = 0xdeadbeef;
647 SetEvent( event );
648 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
649 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
650 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
651 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
652 ok( is_signaled( event ), "event is signaled\n" ); /* not reset on invalid handle */
653 ok( !apc_count, "apc was called\n" );
654 SleepEx( 1, TRUE ); /* alertable sleep */
655 ok( !apc_count, "apc was called\n" );
656
657 /* disconnect while async read is in progress */
658 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
659 apc_count = 0;
660 U(iosb).Status = 0xdeadbabe;
661 iosb.Information = 0xdeadbeef;
662 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
663 ok( status == STATUS_PENDING, "wrong status %x\n", status );
664 ok( !is_signaled( event ), "event is signaled\n" );
665 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
666 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
667 ok( !apc_count, "apc was called\n" );
668 CloseHandle( write );
669 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
670 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
671 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
672 ok( is_signaled( event ), "event is signaled\n" );
673 ok( !apc_count, "apc was called\n" );
674 SleepEx( 1, TRUE ); /* alertable sleep */
675 ok( apc_count == 1, "apc was not called\n" );
676 CloseHandle( read );
677
678 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
679 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
680 ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
681
682 apc_count = 0;
683 U(iosb).Status = 0xdeadbabe;
684 iosb.Information = 0xdeadbeef;
685 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
686 ok( status == STATUS_PENDING, "wrong status %x\n", status );
687 ok( !is_signaled( event ), "event is signaled\n" );
688 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
689 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
690 ok( !apc_count, "apc was called\n" );
691 /* Cancel by other handle */
692 status = pNtCancelIoFile( read, &iosb2 );
693 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
694 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
695 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
696 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
697 ok( is_signaled( event ), "event is signaled\n" );
698 ok( !apc_count, "apc was called\n" );
699 SleepEx( 1, TRUE ); /* alertable sleep */
700 ok( apc_count == 1, "apc was not called\n" );
701
702 apc_count = 0;
703 U(iosb).Status = 0xdeadbabe;
704 iosb.Information = 0xdeadbeef;
705 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
706 ok( status == STATUS_PENDING, "wrong status %x\n", status );
707 ok( !is_signaled( event ), "event is signaled\n" );
708 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
709 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
710 ok( !apc_count, "apc was called\n" );
711 /* Close queued handle */
712 CloseHandle( read );
713 SleepEx( 1, TRUE ); /* alertable sleep */
714 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
715 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
716 status = pNtCancelIoFile( read, &iosb2 );
717 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
718 status = pNtCancelIoFile( handle, &iosb2 );
719 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
720 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
721 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
722 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
723 ok( is_signaled( event ), "event is signaled\n" );
724 ok( !apc_count, "apc was called\n" );
725 SleepEx( 1, TRUE ); /* alertable sleep */
726 ok( apc_count == 1, "apc was not called\n" );
727 CloseHandle( handle );
728 CloseHandle( write );
729
730 if (pNtCancelIoFileEx)
731 {
732 /* Basic Cancel Ex */
733 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
734
735 apc_count = 0;
736 U(iosb).Status = 0xdeadbabe;
737 iosb.Information = 0xdeadbeef;
738 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
739 ok( status == STATUS_PENDING, "wrong status %x\n", status );
740 ok( !is_signaled( event ), "event is signaled\n" );
741 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
742 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
743 ok( !apc_count, "apc was called\n" );
744 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
745 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
746 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
747 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
748 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
749 ok( is_signaled( event ), "event is signaled\n" );
750 ok( !apc_count, "apc was called\n" );
751 SleepEx( 1, TRUE ); /* alertable sleep */
752 ok( apc_count == 1, "apc was not called\n" );
753
754 /* Duplicate iosb */
755 apc_count = 0;
756 U(iosb).Status = 0xdeadbabe;
757 iosb.Information = 0xdeadbeef;
758 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
759 ok( status == STATUS_PENDING, "wrong status %x\n", status );
760 ok( !is_signaled( event ), "event is signaled\n" );
761 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
762 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
763 ok( !apc_count, "apc was called\n" );
764 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
765 ok( status == STATUS_PENDING, "wrong status %x\n", status );
766 ok( !is_signaled( event ), "event is signaled\n" );
767 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
768 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
769 ok( !apc_count, "apc was called\n" );
770 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
771 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
772 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
773 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
774 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
775 ok( is_signaled( event ), "event is signaled\n" );
776 ok( !apc_count, "apc was called\n" );
777 SleepEx( 1, TRUE ); /* alertable sleep */
778 ok( apc_count == 2, "apc was not called\n" );
779
780 CloseHandle( read );
781 CloseHandle( write );
782 }
783
784 /* now try a real file */
785 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
786 apc_count = 0;
787 U(iosb).Status = 0xdeadbabe;
788 iosb.Information = 0xdeadbeef;
789 offset.QuadPart = 0;
790 ResetEvent( event );
791 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
792 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
793 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
794 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
795 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
796 ok( is_signaled( event ), "event is signaled\n" );
797 ok( !apc_count, "apc was called\n" );
798 SleepEx( 1, TRUE ); /* alertable sleep */
799 ok( apc_count == 1, "apc was not called\n" );
800
801 apc_count = 0;
802 U(iosb).Status = 0xdeadbabe;
803 iosb.Information = 0xdeadbeef;
804 offset.QuadPart = 0;
805 ResetEvent( event );
806 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
807 ok( status == STATUS_SUCCESS ||
808 status == STATUS_PENDING, /* vista */
809 "wrong status %x\n", status );
810 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
811 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
812 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
813 ok( is_signaled( event ), "event is signaled\n" );
814 ok( !apc_count, "apc was called\n" );
815 SleepEx( 1, TRUE ); /* alertable sleep */
816 ok( apc_count == 1, "apc was not called\n" );
817
818 /* read beyond eof */
819 apc_count = 0;
820 U(iosb).Status = 0xdeadbabe;
821 iosb.Information = 0xdeadbeef;
822 offset.QuadPart = strlen(text) + 2;
823 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
824 ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
825 if (status == STATUS_PENDING) /* vista */
826 {
827 WaitForSingleObject( event, 1000 );
828 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
829 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
830 ok( is_signaled( event ), "event is signaled\n" );
831 ok( !apc_count, "apc was called\n" );
832 SleepEx( 1, TRUE ); /* alertable sleep */
833 ok( apc_count == 1, "apc was not called\n" );
834 }
835 CloseHandle( handle );
836
837 /* now a non-overlapped file */
838 if (!(handle = create_temp_file(0))) return;
839 apc_count = 0;
840 U(iosb).Status = 0xdeadbabe;
841 iosb.Information = 0xdeadbeef;
842 offset.QuadPart = 0;
843 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
844 ok( status == STATUS_END_OF_FILE ||
845 status == STATUS_SUCCESS ||
846 status == STATUS_PENDING, /* vista */
847 "wrong status %x\n", status );
848 if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
849 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
850 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
851 ok( is_signaled( event ), "event is signaled\n" );
852 ok( !apc_count, "apc was called\n" );
853 SleepEx( 1, TRUE ); /* alertable sleep */
854 ok( apc_count == 1, "apc was not called\n" );
855
856 apc_count = 0;
857 U(iosb).Status = 0xdeadbabe;
858 iosb.Information = 0xdeadbeef;
859 offset.QuadPart = 0;
860 ResetEvent( event );
861 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
862 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
863 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
864 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
865 ok( is_signaled( event ), "event is signaled\n" );
866 ok( !apc_count, "apc was called\n" );
867 SleepEx( 1, TRUE ); /* alertable sleep */
868 todo_wine ok( !apc_count, "apc was called\n" );
869
870 /* read beyond eof */
871 apc_count = 0;
872 U(iosb).Status = 0xdeadbabe;
873 iosb.Information = 0xdeadbeef;
874 offset.QuadPart = strlen(text) + 2;
875 ResetEvent( event );
876 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
877 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
878 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
879 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
880 ok( is_signaled( event ), "event is not signaled\n" );
881 ok( !apc_count, "apc was called\n" );
882 SleepEx( 1, TRUE ); /* alertable sleep */
883 ok( !apc_count, "apc was called\n" );
884
885 CloseHandle( handle );
886
887 CloseHandle( event );
888 }
889
890 static void append_file_test(void)
891 {
892 static const char text[6] = "foobar";
893 HANDLE handle;
894 NTSTATUS status;
895 IO_STATUS_BLOCK iosb;
896 LARGE_INTEGER offset;
897 char path[MAX_PATH], buffer[MAX_PATH], buf[16];
898 DWORD ret;
899
900 GetTempPathA( MAX_PATH, path );
901 GetTempFileNameA( path, "foo", 0, buffer );
902
903 handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
904 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
905
906 U(iosb).Status = -1;
907 iosb.Information = -1;
908 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
909 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
910 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
911 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
912
913 CloseHandle(handle);
914
915 /* It is possible to open a file with only FILE_APPEND_DATA access flags.
916 It matches the O_WRONLY|O_APPEND open() posix behavior */
917 handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
918 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
919
920 U(iosb).Status = -1;
921 iosb.Information = -1;
922 offset.QuadPart = 1;
923 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
924 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
925 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
926 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
927
928 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
929 ok(ret == 4, "expected 4, got %u\n", ret);
930
931 U(iosb).Status = -1;
932 iosb.Information = -1;
933 offset.QuadPart = 3;
934 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
935 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
936 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
937 ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
938
939 ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
940 ok(ret == 6, "expected 6, got %u\n", ret);
941
942 CloseHandle(handle);
943
944 handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
945 ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
946
947 memset(buf, 0, sizeof(buf));
948 U(iosb).Status = -1;
949 iosb.Information = -1;
950 offset.QuadPart = 0;
951 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
952 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
953 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
954 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
955 buf[6] = 0;
956 ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
957
958 U(iosb).Status = -1;
959 iosb.Information = -1;
960 offset.QuadPart = 0;
961 status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
962 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
963 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
964 ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
965
966 memset(buf, 0, sizeof(buf));
967 U(iosb).Status = -1;
968 iosb.Information = -1;
969 offset.QuadPart = 0;
970 status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
971 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
972 ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
973 ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
974 buf[6] = 0;
975 ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
976
977 CloseHandle(handle);
978 DeleteFileA(buffer);
979 }
980
981 static void nt_mailslot_test(void)
982 {
983 HANDLE hslot;
984 ACCESS_MASK DesiredAccess;
985 OBJECT_ATTRIBUTES attr;
986
987 ULONG CreateOptions;
988 ULONG MailslotQuota;
989 ULONG MaxMessageSize;
990 LARGE_INTEGER TimeOut;
991 IO_STATUS_BLOCK IoStatusBlock;
992 NTSTATUS rc;
993 UNICODE_STRING str;
994 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
995 'R',':','\\','F','R','E','D','\0' };
996
997 TimeOut.QuadPart = -1;
998
999 pRtlInitUnicodeString(&str, buffer1);
1000 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1001 CreateOptions = MailslotQuota = MaxMessageSize = 0;
1002 DesiredAccess = GENERIC_READ;
1003
1004 /*
1005 * Check for NULL pointer handling
1006 */
1007 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
1008 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1009 &TimeOut);
1010 ok( rc == STATUS_ACCESS_VIOLATION ||
1011 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1012 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
1013
1014 /*
1015 * Test to see if the Timeout can be NULL
1016 */
1017 hslot = (HANDLE)0xdeadbeef;
1018 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1019 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1020 NULL);
1021 ok( rc == STATUS_SUCCESS ||
1022 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
1023 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
1024 ok( hslot != 0, "Handle is invalid\n");
1025
1026 if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
1027
1028 /*
1029 * Test that the length field is checked properly
1030 */
1031 attr.Length = 0;
1032 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1033 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1034 &TimeOut);
1035 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1036
1037 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1038
1039 attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
1040 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1041 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1042 &TimeOut);
1043 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
1044
1045 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1046
1047 /*
1048 * Test handling of a NULL unicode string in ObjectName
1049 */
1050 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1051 attr.ObjectName = NULL;
1052 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1053 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1054 &TimeOut);
1055 ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
1056 rc == STATUS_INVALID_PARAMETER,
1057 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
1058
1059 if (rc == STATUS_SUCCESS) pNtClose(hslot);
1060
1061 /*
1062 * Test a valid call
1063 */
1064 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
1065 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
1066 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
1067 &TimeOut);
1068 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
1069 ok( hslot != 0, "Handle is invalid\n");
1070
1071 rc = pNtClose(hslot);
1072 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
1073 }
1074
1075 static void test_iocp_setcompletion(HANDLE h)
1076 {
1077 NTSTATUS res;
1078 ULONG count;
1079 SIZE_T size = 3;
1080
1081 if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
1082
1083 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
1084 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
1085
1086 count = get_pending_msgs(h);
1087 ok( count == 1, "Unexpected msg count: %d\n", count );
1088
1089 if (get_msg(h))
1090 {
1091 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
1092 ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
1093 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1094 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
1095 }
1096
1097 count = get_pending_msgs(h);
1098 ok( !count, "Unexpected msg count: %d\n", count );
1099 }
1100
1101 static void test_iocp_fileio(HANDLE h)
1102 {
1103 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
1104
1105 IO_STATUS_BLOCK iosb;
1106 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
1107 HANDLE hPipeSrv, hPipeClt;
1108 NTSTATUS res;
1109
1110 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1111 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1112 if (hPipeSrv != INVALID_HANDLE_VALUE )
1113 {
1114 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1115 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1116 if (hPipeClt != INVALID_HANDLE_VALUE)
1117 {
1118 U(iosb).Status = 0xdeadbeef;
1119 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1120 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
1121 ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
1122 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
1123 CloseHandle(hPipeClt);
1124 }
1125 CloseHandle( hPipeSrv );
1126 }
1127
1128 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1129 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1130 if (hPipeSrv == INVALID_HANDLE_VALUE )
1131 return;
1132
1133 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1134 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1135 if (hPipeClt != INVALID_HANDLE_VALUE)
1136 {
1137 OVERLAPPED o = {0,};
1138 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1139 DWORD read;
1140 long count;
1141
1142 U(iosb).Status = 0xdeadbeef;
1143 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1144 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1145 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1146
1147 memset( send_buf, 0, TEST_BUF_LEN );
1148 memset( recv_buf, 0xde, TEST_BUF_LEN );
1149 count = get_pending_msgs(h);
1150 ok( !count, "Unexpected msg count: %ld\n", count );
1151 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1152 count = get_pending_msgs(h);
1153 ok( !count, "Unexpected msg count: %ld\n", count );
1154 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1155
1156 if (get_msg(h))
1157 {
1158 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1159 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1160 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1161 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1162 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1163 }
1164 count = get_pending_msgs(h);
1165 ok( !count, "Unexpected msg count: %ld\n", count );
1166
1167 memset( send_buf, 0, TEST_BUF_LEN );
1168 memset( recv_buf, 0xde, TEST_BUF_LEN );
1169 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1170 count = get_pending_msgs(h);
1171 ok( !count, "Unexpected msg count: %ld\n", count );
1172 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1173 count = get_pending_msgs(h);
1174 ok( count == 1, "Unexpected msg count: %ld\n", count );
1175 if (get_msg(h))
1176 {
1177 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1178 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1179 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1180 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1181 ok( !memcmp( send_buf, recv_buf, 2 ), "Receive buffer (%x %x) did not match send buffer (%x %x)\n", recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
1182 }
1183
1184 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1185 CloseHandle( hPipeSrv );
1186 count = get_pending_msgs(h);
1187 ok( count == 1, "Unexpected msg count: %ld\n", count );
1188 if (get_msg(h))
1189 {
1190 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1191 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1192 /* wine sends wrong status here */
1193 todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1194 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1195 }
1196 }
1197
1198 CloseHandle( hPipeClt );
1199
1200 /* test associating a completion port with a handle after an async is queued */
1201 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1202 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1203 if (hPipeSrv == INVALID_HANDLE_VALUE )
1204 return;
1205 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1206 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1207 if (hPipeClt != INVALID_HANDLE_VALUE)
1208 {
1209 OVERLAPPED o = {0,};
1210 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1211 DWORD read;
1212 long count;
1213
1214 memset( send_buf, 0, TEST_BUF_LEN );
1215 memset( recv_buf, 0xde, TEST_BUF_LEN );
1216 count = get_pending_msgs(h);
1217 ok( !count, "Unexpected msg count: %ld\n", count );
1218 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1219
1220 U(iosb).Status = 0xdeadbeef;
1221 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1222 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1223 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1224 count = get_pending_msgs(h);
1225 ok( !count, "Unexpected msg count: %ld\n", count );
1226
1227 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1228
1229 if (get_msg(h))
1230 {
1231 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1232 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1233 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1234 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1235 ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
1236 }
1237 count = get_pending_msgs(h);
1238 ok( !count, "Unexpected msg count: %ld\n", count );
1239 }
1240
1241 CloseHandle( hPipeSrv );
1242 CloseHandle( hPipeClt );
1243 }
1244
1245 static void test_file_full_size_information(void)
1246 {
1247 IO_STATUS_BLOCK io;
1248 FILE_FS_FULL_SIZE_INFORMATION ffsi;
1249 FILE_FS_SIZE_INFORMATION fsi;
1250 HANDLE h;
1251 NTSTATUS res;
1252
1253 if(!(h = create_temp_file(0))) return ;
1254
1255 memset(&ffsi,0,sizeof(ffsi));
1256 memset(&fsi,0,sizeof(fsi));
1257
1258 /* Assume No Quota Settings configured on Wine Testbot */
1259 res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1260 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1261 res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1262 ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1263
1264 /* Test for FileFsSizeInformation */
1265 ok(fsi.TotalAllocationUnits.QuadPart > 0,
1266 "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1267 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1268 ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1269 "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1270 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1271
1272 /* Assume file system is NTFS */
1273 ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1274 ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1275
1276 ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1277 "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1278 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1279 ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1280 "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1281 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1282 ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1283 "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1284 debugstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1285 ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1286 "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1287 debugstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1288 debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1289 ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1290 "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1291 debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1292 debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1293
1294 /* Assume file system is NTFS */
1295 ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1296 ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1297
1298 CloseHandle( h );
1299 }
1300
1301 static void test_file_basic_information(void)
1302 {
1303 IO_STATUS_BLOCK io;
1304 FILE_BASIC_INFORMATION fbi;
1305 HANDLE h;
1306 int res;
1307 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1308
1309 if (!(h = create_temp_file(0))) return;
1310
1311 /* Check default first */
1312 memset(&fbi, 0, sizeof(fbi));
1313 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1314 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1315 ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1316 "attribute %x not expected\n", fbi.FileAttributes );
1317
1318 /* Then SYSTEM */
1319 /* Clear fbi to avoid setting times */
1320 memset(&fbi, 0, sizeof(fbi));
1321 fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1322 U(io).Status = 0xdeadbeef;
1323 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1324 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1325 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1326
1327 memset(&fbi, 0, sizeof(fbi));
1328 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1329 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1330 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes );
1331
1332 /* Then HIDDEN */
1333 memset(&fbi, 0, sizeof(fbi));
1334 fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1335 U(io).Status = 0xdeadbeef;
1336 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1337 ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1338 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1339
1340 memset(&fbi, 0, sizeof(fbi));
1341 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1342 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1343 ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes );
1344
1345 /* Check NORMAL last of all (to make sure we can clear attributes) */
1346 memset(&fbi, 0, sizeof(fbi));
1347 fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1348 U(io).Status = 0xdeadbeef;
1349 res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1350 ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1351 ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1352
1353 memset(&fbi, 0, sizeof(fbi));
1354 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1355 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1356 todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1357
1358 CloseHandle( h );
1359 }
1360
1361 static void test_file_all_information(void)
1362 {
1363 IO_STATUS_BLOCK io;
1364 /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1365 * buffer at the end. Vista objects with STATUS_BUFFER_OVERFLOW if you
1366 * don't leave enough room there.
1367 */
1368 struct {
1369 FILE_ALL_INFORMATION fai;
1370 WCHAR buf[256];
1371 } fai_buf;
1372 HANDLE h;
1373 int res;
1374 int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1375
1376 if (!(h = create_temp_file(0))) return;
1377
1378 /* Check default first */
1379 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1380 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1381 ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1382 "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1383
1384 /* Then SYSTEM */
1385 /* Clear fbi to avoid setting times */
1386 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1387 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1388 U(io).Status = 0xdeadbeef;
1389 res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1390 ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1391 todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1392 U(io).Status = 0xdeadbeef;
1393 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1394 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1395 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1396
1397 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1398 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1399 ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1400 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1401
1402 /* Then HIDDEN */
1403 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1404 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1405 U(io).Status = 0xdeadbeef;
1406 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1407 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1408 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1409
1410 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1411 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1412 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1413 ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
1414
1415 /* Check NORMAL last of all (to make sure we can clear attributes) */
1416 memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1417 fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1418 U(io).Status = 0xdeadbeef;
1419 res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1420 ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1421 ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1422
1423 memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1424 res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1425 ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1426 todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not FILE_ATTRIBUTE_NORMAL\n", fai_buf.fai.BasicInformation.FileAttributes );
1427
1428 CloseHandle( h );
1429 }
1430
1431 static void test_file_both_information(void)
1432 {
1433 IO_STATUS_BLOCK io;
1434 FILE_BOTH_DIR_INFORMATION fbi;
1435 HANDLE h;
1436 int res;
1437
1438 if (!(h = create_temp_file(0))) return;
1439
1440 memset(&fbi, 0, sizeof(fbi));
1441 res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
1442 ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
1443
1444 CloseHandle( h );
1445 }
1446
1447 static void test_file_disposition_information(void)
1448 {
1449 char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
1450 DWORD dirpos;
1451 HANDLE handle, handle2, mapping;
1452 NTSTATUS res;
1453 IO_STATUS_BLOCK io;
1454 FILE_DISPOSITION_INFORMATION fdi;
1455 BOOL fileDeleted;
1456 void *ptr;
1457
1458 GetTempPathA( MAX_PATH, tmp_path );
1459
1460 /* cannot set disposition on file not opened with delete access */
1461 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1462 handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1463 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1464 res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1465 ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
1466 fdi.DoDeleteFile = TRUE;
1467 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1468 ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
1469 CloseHandle( handle );
1470 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1471 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1472 DeleteFileA( buffer );
1473
1474 /* can set disposition on file opened with proper access */
1475 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1476 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1477 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1478 fdi.DoDeleteFile = TRUE;
1479 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1480 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1481 CloseHandle( handle );
1482 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1483 ok( fileDeleted, "File should have been deleted\n" );
1484 DeleteFileA( buffer );
1485
1486 /* cannot set disposition on readonly file */
1487 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1488 DeleteFileA( buffer );
1489 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1490 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1491 fdi.DoDeleteFile = TRUE;
1492 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1493 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1494 CloseHandle( handle );
1495 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1496 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1497 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
1498 DeleteFileA( buffer );
1499
1500 /* cannot set disposition on readonly file */
1501 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1502 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1503 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1504 fdi.DoDeleteFile = TRUE;
1505 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1506 todo_wine
1507 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1508 CloseHandle( handle );
1509 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1510 todo_wine
1511 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1512 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
1513 DeleteFileA( buffer );
1514
1515 /* cannot set disposition on readonly file */
1516 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1517 DeleteFileA( buffer );
1518 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1519 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1520 fdi.DoDeleteFile = TRUE;
1521 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1522 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1523 CloseHandle( handle );
1524 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1525 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1526 SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
1527 DeleteFileA( buffer );
1528
1529 /* can set disposition on file and then reset it */
1530 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1531 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1532 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1533 fdi.DoDeleteFile = TRUE;
1534 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1535 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1536 fdi.DoDeleteFile = FALSE;
1537 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1538 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1539 CloseHandle( handle );
1540 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1541 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1542 DeleteFileA( buffer );
1543
1544 /* Delete-on-close flag doesn't change file disposition until a handle is closed */
1545 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1546 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
1547 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1548 fdi.DoDeleteFile = FALSE;
1549 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1550 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1551 CloseHandle( handle );
1552 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1553 ok( fileDeleted, "File should have been deleted\n" );
1554 DeleteFileA( buffer );
1555
1556 /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
1557 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1558 handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
1559 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1560 ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
1561 CloseHandle( handle );
1562 fdi.DoDeleteFile = FALSE;
1563 res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
1564 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1565 CloseHandle( handle2 );
1566 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1567 ok( fileDeleted, "File should have been deleted\n" );
1568 DeleteFileA( buffer );
1569
1570 /* can set disposition on a directory opened with proper access */
1571 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1572 DeleteFileA( buffer );
1573 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1574 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1575 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1576 fdi.DoDeleteFile = TRUE;
1577 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1578 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1579 CloseHandle( handle );
1580 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1581 ok( fileDeleted, "Directory should have been deleted\n" );
1582 RemoveDirectoryA( buffer );
1583
1584 /* RemoveDirectory sets directory disposition and it can be undone */
1585 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1586 DeleteFileA( buffer );
1587 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1588 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1589 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1590 RemoveDirectoryA( buffer );
1591 fdi.DoDeleteFile = FALSE;
1592 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1593 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1594 CloseHandle( handle );
1595 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1596 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
1597 RemoveDirectoryA( buffer );
1598
1599 /* cannot set disposition on a non-empty directory */
1600 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1601 DeleteFileA( buffer );
1602 ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
1603 handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1604 ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
1605 dirpos = lstrlenA( buffer );
1606 lstrcpyA( buffer + dirpos, "\\tst" );
1607 handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1608 CloseHandle( handle2 );
1609 fdi.DoDeleteFile = TRUE;
1610 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1611 todo_wine
1612 ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
1613 DeleteFileA( buffer );
1614 buffer[dirpos] = '\0';
1615 CloseHandle( handle );
1616 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1617 todo_wine
1618 ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
1619 RemoveDirectoryA( buffer );
1620
1621 /* cannot set disposition on file with file mapping opened */
1622 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1623 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1624 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1625 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
1626 ok( mapping != NULL, "failed to create file mapping\n");
1627 fdi.DoDeleteFile = TRUE;
1628 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1629 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1630 CloseHandle( handle );
1631 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1632 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1633 CloseHandle( mapping );
1634 DeleteFileA( buffer );
1635
1636 /* can set disposition on file with file mapping closed */
1637 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1638 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1639 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1640 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
1641 ok( mapping != NULL, "failed to create file mapping\n");
1642 CloseHandle( mapping );
1643 fdi.DoDeleteFile = TRUE;
1644 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1645 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1646 CloseHandle( handle );
1647 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1648 ok( fileDeleted, "File should have been deleted\n" );
1649 DeleteFileA( buffer );
1650
1651 /* cannot set disposition on file which is mapped to memory */
1652 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1653 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1654 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1655 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
1656 ok( mapping != NULL, "failed to create file mapping\n");
1657 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1658 ok( ptr != NULL, "MapViewOfFile failed\n");
1659 CloseHandle( mapping );
1660 fdi.DoDeleteFile = TRUE;
1661 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1662 ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
1663 CloseHandle( handle );
1664 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1665 ok( !fileDeleted, "File shouldn't have been deleted\n" );
1666 UnmapViewOfFile( ptr );
1667 DeleteFileA( buffer );
1668
1669 /* can set disposition on file which is mapped to memory and unmapped again */
1670 GetTempFileNameA( tmp_path, "dis", 0, buffer );
1671 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
1672 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
1673 mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
1674 ok( mapping != NULL, "failed to create file mapping\n");
1675 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
1676 ok( ptr != NULL, "MapViewOfFile failed\n");
1677 CloseHandle( mapping );
1678 UnmapViewOfFile( ptr );
1679 fdi.DoDeleteFile = TRUE;
1680 res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
1681 ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
1682 CloseHandle( handle );
1683 fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1684 ok( fileDeleted, "File should have been deleted\n" );
1685 DeleteFileA( buffer );
1686 }
1687
1688 static void test_iocompletion(void)
1689 {
1690 HANDLE h = INVALID_HANDLE_VALUE;
1691 NTSTATUS res;
1692
1693 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
1694
1695 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
1696 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
1697
1698 if ( h && h != INVALID_HANDLE_VALUE)
1699 {
1700 test_iocp_setcompletion(h);
1701 test_iocp_fileio(h);
1702 pNtClose(h);
1703 }
1704 }
1705
1706 static void test_file_name_information(void)
1707 {
1708 WCHAR *file_name, *volume_prefix, *expected;
1709 FILE_NAME_INFORMATION *info;
1710 ULONG old_redir = 1, tmp;
1711 UINT file_name_size;
1712 IO_STATUS_BLOCK io;
1713 UINT info_size;
1714 HRESULT hr;
1715 HANDLE h;
1716 UINT len;
1717
1718 /* GetVolumePathName is not present before w2k */
1719 if (!pGetVolumePathNameW) {
1720 win_skip("GetVolumePathNameW not found\n");
1721 return;
1722 }
1723
1724 file_name_size = GetSystemDirectoryW( NULL, 0 );
1725 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1726 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1727 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1728
1729 len = GetSystemDirectoryW( file_name, file_name_size );
1730 ok(len == file_name_size - 1,
1731 "GetSystemDirectoryW returned %u, expected %u.\n",
1732 len, file_name_size - 1);
1733
1734 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1735 ok(len, "GetVolumePathNameW failed.\n");
1736
1737 len = lstrlenW( volume_prefix );
1738 if (len && volume_prefix[len - 1] == '\\') --len;
1739 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1740 expected[file_name_size - len - 1] = '\0';
1741
1742 /* A bit more than we actually need, but it keeps the calculation simple. */
1743 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1744 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1745
1746 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1747 h = CreateFileW( file_name, GENERIC_READ,
1748 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1749 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1750 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1751 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1752
1753 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
1754 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
1755
1756 memset( info, 0xcc, info_size );
1757 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
1758 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1759 hr, STATUS_BUFFER_OVERFLOW);
1760 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1761 U(io).Status, STATUS_BUFFER_OVERFLOW);
1762 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1763 ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1764 ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1765 "info->FileName[1] is %p, expected %p.\n",
1766 CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1767 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1768
1769 memset( info, 0xcc, info_size );
1770 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1771 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1772 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1773 ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1774 ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1775 info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1776 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1777 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1778 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1779 ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1780 "io.Information is %lu, expected %u.\n",
1781 io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1782
1783 CloseHandle( h );
1784 HeapFree( GetProcessHeap(), 0, info );
1785 HeapFree( GetProcessHeap(), 0, expected );
1786 HeapFree( GetProcessHeap(), 0, volume_prefix );
1787
1788 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1789 {
1790 skip("Not running on WoW64, skipping test.\n");
1791 HeapFree( GetProcessHeap(), 0, file_name );
1792 return;
1793 }
1794
1795 h = CreateFileW( file_name, GENERIC_READ,
1796 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1797 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1798 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1799 HeapFree( GetProcessHeap(), 0, file_name );
1800
1801 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1802 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1803 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1804
1805 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1806 ok(len == file_name_size - 1,
1807 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1808 len, file_name_size - 1);
1809
1810 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1811 ok(len, "GetVolumePathNameW failed.\n");
1812
1813 len = lstrlenW( volume_prefix );
1814 if (len && volume_prefix[len - 1] == '\\') --len;
1815 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1816 expected[file_name_size - len - 1] = '\0';
1817
1818 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1819 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1820
1821 memset( info, 0xcc, info_size );
1822 hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1823 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1824 info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1825 ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1826 wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1827
1828 CloseHandle( h );
1829 HeapFree( GetProcessHeap(), 0, info );
1830 HeapFree( GetProcessHeap(), 0, expected );
1831 HeapFree( GetProcessHeap(), 0, volume_prefix );
1832 HeapFree( GetProcessHeap(), 0, file_name );
1833 }
1834
1835 static void test_file_all_name_information(void)
1836 {
1837 WCHAR *file_name, *volume_prefix, *expected;
1838 FILE_ALL_INFORMATION *info;
1839 ULONG old_redir = 1, tmp;
1840 UINT file_name_size;
1841 IO_STATUS_BLOCK io;
1842 UINT info_size;
1843 HRESULT hr;
1844 HANDLE h;
1845 UINT len;
1846
1847 /* GetVolumePathName is not present before w2k */
1848 if (!pGetVolumePathNameW) {
1849 win_skip("GetVolumePathNameW not found\n");
1850 return;
1851 }
1852
1853 file_name_size = GetSystemDirectoryW( NULL, 0 );
1854 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1855 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1856 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1857
1858 len = GetSystemDirectoryW( file_name, file_name_size );
1859 ok(len == file_name_size - 1,
1860 "GetSystemDirectoryW returned %u, expected %u.\n",
1861 len, file_name_size - 1);
1862
1863 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1864 ok(len, "GetVolumePathNameW failed.\n");
1865
1866 len = lstrlenW( volume_prefix );
1867 if (len && volume_prefix[len - 1] == '\\') --len;
1868 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1869 expected[file_name_size - len - 1] = '\0';
1870
1871 /* A bit more than we actually need, but it keeps the calculation simple. */
1872 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1873 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1874
1875 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1876 h = CreateFileW( file_name, GENERIC_READ,
1877 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1878 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1879 if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1880 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1881
1882 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
1883 ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
1884 hr, STATUS_INFO_LENGTH_MISMATCH);
1885
1886 memset( info, 0xcc, info_size );
1887 hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
1888 ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1889 hr, STATUS_BUFFER_OVERFLOW);
1890 ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1891 U(io).Status, STATUS_BUFFER_OVERFLOW);
1892 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1893 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1894 ok(info->NameInformation.FileName[2] == 0xcccc,
1895 "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
1896 ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1897 "info->NameInformation.FileName[1] is %p, expected %p.\n",
1898 CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1899 ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1900
1901 memset( info, 0xcc, info_size );
1902 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1903 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1904 ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1905 ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1906 "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1907 ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
1908 "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1909 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
1910 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1911 ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
1912 "info->NameInformation.FileName is %s, expected %s.\n",
1913 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1914 ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
1915 + info->NameInformation.FileNameLength,
1916 "io.Information is %lu\n", io.Information );
1917
1918 CloseHandle( h );
1919 HeapFree( GetProcessHeap(), 0, info );
1920 HeapFree( GetProcessHeap(), 0, expected );
1921 HeapFree( GetProcessHeap(), 0, volume_prefix );
1922
1923 if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1924 {
1925 skip("Not running on WoW64, skipping test.\n");
1926 HeapFree( GetProcessHeap(), 0, file_name );
1927 return;
1928 }
1929
1930 h = CreateFileW( file_name, GENERIC_READ,
1931 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1932 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1933 ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1934 HeapFree( GetProcessHeap(), 0, file_name );
1935
1936 file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1937 volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1938 expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1939
1940 len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1941 ok(len == file_name_size - 1,
1942 "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1943 len, file_name_size - 1);
1944
1945 len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1946 ok(len, "GetVolumePathNameW failed.\n");
1947
1948 len = lstrlenW( volume_prefix );
1949 if (len && volume_prefix[len - 1] == '\\') --len;
1950 memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1951 expected[file_name_size - len - 1] = '\0';
1952
1953 info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1954 info = HeapAlloc( GetProcessHeap(), 0, info_size );
1955
1956 memset( info, 0xcc, info_size );
1957 hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1958 ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1959 info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1960 ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
1961 wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1962
1963 CloseHandle( h );
1964 HeapFree( GetProcessHeap(), 0, info );
1965 HeapFree( GetProcessHeap(), 0, expected );
1966 HeapFree( GetProcessHeap(), 0, volume_prefix );
1967 HeapFree( GetProcessHeap(), 0, file_name );
1968 }
1969
1970 static void test_query_volume_information_file(void)
1971 {
1972 NTSTATUS status;
1973 HANDLE dir;
1974 WCHAR path[MAX_PATH];
1975 OBJECT_ATTRIBUTES attr;
1976 IO_STATUS_BLOCK io;
1977 UNICODE_STRING nameW;
1978 FILE_FS_VOLUME_INFORMATION *ffvi;
1979 BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1980
1981 GetWindowsDirectoryW( path, MAX_PATH );
1982 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1983 attr.Length = sizeof(attr);
1984 attr.RootDirectory = 0;
1985 attr.ObjectName = &nameW;
1986 attr.Attributes = OBJ_CASE_INSENSITIVE;
1987 attr.SecurityDescriptor = NULL;
1988 attr.SecurityQualityOfService = NULL;
1989
1990 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1991 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1992 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1993 pRtlFreeUnicodeString( &nameW );
1994
1995 ZeroMemory( buf, sizeof(buf) );
1996 U(io).Status = 0xdadadada;
1997 io.Information = 0xcacacaca;
1998
1999 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
2000
2001 ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
2002
2003 todo_wine
2004 {
2005 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
2006 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
2007
2008 ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
2009 "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
2010 io.Information);
2011
2012 ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
2013 ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
2014 ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
2015 }
2016 ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
2017
2018 trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
2019
2020 CloseHandle( dir );
2021 }
2022
2023 static void test_query_attribute_information_file(void)
2024 {
2025 NTSTATUS status;
2026 HANDLE dir;
2027 WCHAR path[MAX_PATH];
2028 OBJECT_ATTRIBUTES attr;
2029 IO_STATUS_BLOCK io;
2030 UNICODE_STRING nameW;
2031 FILE_FS_ATTRIBUTE_INFORMATION *ffai;
2032 BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
2033
2034 GetWindowsDirectoryW( path, MAX_PATH );
2035 pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
2036 attr.Length = sizeof(attr);
2037 attr.RootDirectory = 0;
2038 attr.ObjectName = &nameW;
2039 attr.Attributes = OBJ_CASE_INSENSITIVE;
2040 attr.SecurityDescriptor = NULL;
2041 attr.SecurityQualityOfService = NULL;
2042
2043 status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
2044 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
2045 ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
2046 pRtlFreeUnicodeString( &nameW );
2047
2048 ZeroMemory( buf, sizeof(buf) );
2049 U(io).Status = 0xdadadada;
2050 io.Information = 0xcacacaca;
2051
2052 status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
2053
2054 ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
2055
2056 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
2057 ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
2058 ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
2059 ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
2060 ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
2061
2062 trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
2063 ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
2064 wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
2065
2066 CloseHandle( dir );
2067 }
2068
2069 static void test_NtCreateFile(void)
2070 {
2071 static const struct test_data
2072 {
2073 DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
2074 } td[] =
2075 {
2076 /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
2077 /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
2078 /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
2079 /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
2080 /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
2081 /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
2082 /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
2083 /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
2084 /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
2085 /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
2086 /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
2087 /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
2088 /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
2089 /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
2090 /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
2091 /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
2092 /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
2093 /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
2094 /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
2095 };
2096 static const WCHAR fooW[] = {'f','o','o',0};
2097 NTSTATUS status;
2098 HANDLE handle;
2099 WCHAR path[MAX_PATH];
2100 OBJECT_ATTRIBUTES attr;
2101 IO_STATUS_BLOCK io;
2102 UNICODE_STRING nameW;
2103 DWORD ret, i;
2104
2105 GetTempPathW(MAX_PATH, path);
2106 GetTempFileNameW(path, fooW, 0, path);
2107 DeleteFileW(path);
2108 pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
2109
2110 attr.Length = sizeof(attr);
2111 attr.RootDirectory = NULL;
2112 attr.ObjectName = &nameW;
2113 attr.Attributes = OBJ_CASE_INSENSITIVE;
2114 attr.SecurityDescriptor = NULL;
2115 attr.SecurityQualityOfService = NULL;
2116
2117 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2118 {
2119 status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
2120 td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
2121 td[i].disposition, 0, NULL, 0);
2122
2123 ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
2124
2125 if (!status)
2126 {
2127 ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
2128
2129 ret = GetFileAttributesW(path);
2130 ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
2131 /* FIXME: leave only 'else' case below once Wine is fixed */
2132 if (ret != td[i].attrib_out)
2133 {
2134 todo_wine
2135 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
2136 SetFileAttributesW(path, td[i].attrib_out);
2137 }
2138 else
2139 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
2140
2141 CloseHandle(handle);
2142 }
2143
2144 if (td[i].needs_cleanup)
2145 {
2146 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
2147 DeleteFileW(path);
2148 }
2149 }
2150
2151 pRtlFreeUnicodeString( &nameW );
2152 SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
2153 DeleteFileW( path );
2154 }
2155
2156 static void test_read_write(void)
2157 {
2158 static const char contents[14] = "1234567890abcd";
2159 char buf[256];
2160 HANDLE hfile;
2161 OVERLAPPED ovl;
2162 IO_STATUS_BLOCK iob;
2163 DWORD ret, bytes, status, off;
2164 LARGE_INTEGER offset;
2165 LONG i;
2166
2167 U(iob).Status = -1;
2168 iob.Information = -1;
2169 offset.QuadPart = 0;
2170 status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2171 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
2172 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2173 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2174
2175 U(iob).Status = -1;
2176 iob.Information = -1;
2177 offset.QuadPart = 0;
2178 status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2179 ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
2180 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2181 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2182
2183 hfile = create_temp_file(0);
2184 if (!hfile) return;
2185
2186 U(iob).Status = -1;
2187 iob.Information = -1;
2188 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
2189 ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
2190 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2191 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2192
2193 U(iob).Status = -1;
2194 iob.Information = -1;
2195 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
2196 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
2197 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2198 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2199
2200 U(iob).Status = -1;
2201 iob.Information = -1;
2202 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
2203 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2204 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2205 ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
2206
2207 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2208
2209 U(iob).Status = -1;
2210 iob.Information = -1;
2211 offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
2212 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
2213 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2214 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2215 ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
2216
2217 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2218 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2219
2220 bytes = 0xdeadbeef;
2221 SetLastError(0xdeadbeef);
2222 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
2223 ok(!ret, "ReadFile should fail\n");
2224 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2225 ok(bytes == 0, "bytes %u\n", bytes);
2226
2227 bytes = 0xdeadbeef;
2228 SetLastError(0xdeadbeef);
2229 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
2230 ok(ret, "ReadFile error %d\n", GetLastError());
2231 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2232 ok(bytes == 0, "bytes %u\n", bytes);
2233
2234 bytes = 0xdeadbeef;
2235 SetLastError(0xdeadbeef);
2236 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2237 ok(ret, "ReadFile error %d\n", GetLastError());
2238 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2239 ok(bytes == 0, "bytes %u\n", bytes);
2240
2241 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2242
2243 bytes = 0;
2244 SetLastError(0xdeadbeef);
2245 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2246 ok(ret, "ReadFile error %d\n", GetLastError());
2247 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2248 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2249
2250 for (i = -20; i < -1; i++)
2251 {
2252 if (i == -2) continue;
2253
2254 U(iob).Status = -1;
2255 iob.Information = -1;
2256 offset.QuadPart = (LONGLONG)i;
2257 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2258 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2259 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2260 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2261 }
2262
2263 SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
2264
2265 U(iob).Status = -1;
2266 iob.Information = -1;
2267 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2268 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
2269 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2270 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2271 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
2272
2273 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2274 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2275
2276 U(iob).Status = -1;
2277 iob.Information = -1;
2278 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2279 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2280 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2281 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2282
2283 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2284
2285 bytes = 0;
2286 SetLastError(0xdeadbeef);
2287 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2288 ok(ret, "ReadFile error %d\n", GetLastError());
2289 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2290 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2291 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
2292
2293 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2294 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2295
2296 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2297
2298 bytes = 0;
2299 SetLastError(0xdeadbeef);
2300 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
2301 ok(ret, "WriteFile error %d\n", GetLastError());
2302 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2303
2304 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2305 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2306
2307 /* test reading beyond EOF */
2308 bytes = -1;
2309 SetLastError(0xdeadbeef);
2310 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2311 ok(ret, "ReadFile error %d\n", GetLastError());
2312 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2313 ok(bytes == 0, "bytes %u\n", bytes);
2314
2315 bytes = -1;
2316 SetLastError(0xdeadbeef);
2317 ret = ReadFile(hfile, buf, 0, &bytes, NULL);
2318 ok(ret, "ReadFile error %d\n", GetLastError());
2319 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2320 ok(bytes == 0, "bytes %u\n", bytes);
2321
2322 bytes = -1;
2323 SetLastError(0xdeadbeef);
2324 ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
2325 ok(ret, "ReadFile error %d\n", GetLastError());
2326 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2327 ok(bytes == 0, "bytes %u\n", bytes);
2328
2329 S(U(ovl)).Offset = sizeof(contents);
2330 S(U(ovl)).OffsetHigh = 0;
2331 ovl.Internal = -1;
2332 ovl.InternalHigh = -1;
2333 ovl.hEvent = 0;
2334 bytes = -1;
2335 SetLastError(0xdeadbeef);
2336 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2337 ok(!ret, "ReadFile should fail\n");
2338 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2339 ok(bytes == 0, "bytes %u\n", bytes);
2340 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
2341 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2342
2343 S(U(ovl)).Offset = sizeof(contents);
2344 S(U(ovl)).OffsetHigh = 0;
2345 ovl.Internal = -1;
2346 ovl.InternalHigh = -1;
2347 ovl.hEvent = 0;
2348 bytes = -1;
2349 SetLastError(0xdeadbeef);
2350 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
2351 ok(ret, "ReadFile error %d\n", GetLastError());
2352 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2353 ok(bytes == 0, "bytes %u\n", bytes);
2354 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2355 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2356
2357 U(iob).Status = -1;
2358 iob.Information = -1;
2359 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2360 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2361 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2362 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2363
2364 U(iob).Status = -1;
2365 iob.Information = -1;
2366 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
2367 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2368 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2369 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2370
2371 U(iob).Status = -1;
2372 iob.Information = -1;
2373 offset.QuadPart = sizeof(contents);
2374 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2375 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2376 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2377 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2378
2379 U(iob).Status = -1;
2380 iob.Information = -1;
2381 offset.QuadPart = sizeof(contents);
2382 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2383 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2384 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2385 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2386
2387 U(iob).Status = -1;
2388 iob.Information = -1;
2389 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2390 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2391 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2392 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2393 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2394
2395 U(iob).Status = -1;
2396 iob.Information = -1;
2397 offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
2398 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2399 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2400 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2401 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2402
2403 for (i = -20; i < 0; i++)
2404 {
2405 if (i == -2) continue;
2406
2407 U(iob).Status = -1;
2408 iob.Information = -1;
2409 offset.QuadPart = (LONGLONG)i;
2410 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2411 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2412 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2413 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2414 }
2415
2416 SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
2417
2418 bytes = 0;
2419 SetLastError(0xdeadbeef);
2420 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2421 ok(ret, "ReadFile error %d\n", GetLastError());
2422 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2423 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2424
2425 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2426 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2427
2428 U(iob).Status = -1;
2429 iob.Information = -1;
2430 offset.QuadPart = 0;
2431 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2432 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2433 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2434 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2435 ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
2436
2437 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2438 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2439
2440 U(iob).Status = -1;
2441 iob.Information = -1;
2442 offset.QuadPart = sizeof(contents) - 4;
2443 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
2444 ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
2445 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2446 ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
2447
2448 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2449 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2450
2451 U(iob).Status = -1;
2452 iob.Information = -1;
2453 offset.QuadPart = 0;
2454 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2455 ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
2456 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2457 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2458 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2459 ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
2460
2461 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2462 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2463
2464 S(U(ovl)).Offset = sizeof(contents) - 4;
2465 S(U(ovl)).OffsetHigh = 0;
2466 ovl.hEvent = 0;
2467 bytes = 0;
2468 SetLastError(0xdeadbeef);
2469 ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
2470 ok(ret, "WriteFile error %d\n", GetLastError());
2471 ok(bytes == 4, "bytes %u\n", bytes);
2472
2473 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2474 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2475
2476 S(U(ovl)).Offset = 0;
2477 S(U(ovl)).OffsetHigh = 0;
2478 ovl.Internal = -1;
2479 ovl.InternalHigh = -1;
2480 ovl.hEvent = 0;
2481 bytes = 0;
2482 SetLastError(0xdeadbeef);
2483 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2484 ok(ret, "ReadFile error %d\n", GetLastError());
2485 ok(bytes == sizeof(contents), "bytes %u\n", bytes);
2486 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2487 ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
2488 ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
2489 ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
2490
2491 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2492 ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
2493
2494 CloseHandle(hfile);
2495
2496 hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
2497 if (!hfile) return;
2498
2499 bytes = 0xdeadbeef;
2500 SetLastError(0xdeadbeef);
2501 ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
2502 ok(!ret, "ReadFile should fail\n");
2503 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2504 ok(bytes == 0, "bytes %u\n", bytes);
2505
2506 S(U(ovl)).Offset = 0;
2507 S(U(ovl)).OffsetHigh = 0;
2508 ovl.Internal = -1;
2509 ovl.InternalHigh = -1;
2510 ovl.hEvent = 0;
2511 bytes = 0xdeadbeef;
2512 SetLastError(0xdeadbeef);
2513 /* ReadFile return value depends on Windows version and testing it is not practical */
2514 ReadFile(hfile, buf, 0, &bytes, &ovl);
2515 ok(bytes == 0, "bytes %u\n", bytes);
2516 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2517 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2518
2519 bytes = 0xdeadbeef;
2520 SetLastError(0xdeadbeef);
2521 ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
2522 ok(!ret, "WriteFile should fail\n");
2523 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2524 ok(bytes == 0, "bytes %u\n", bytes);
2525
2526 U(iob).Status = -1;
2527 iob.Information = -1;
2528 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
2529 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2530 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2531 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2532
2533 for (i = -20; i < -1; i++)
2534 {
2535 U(iob).Status = -1;
2536 iob.Information = -1;
2537 offset.QuadPart = (LONGLONG)i;
2538 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2539 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2540 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2541 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2542 }
2543
2544 U(iob).Status = -1;
2545 iob.Information = -1;
2546 offset.QuadPart = 0;
2547 status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
2548 ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
2549 if (status == STATUS_PENDING)
2550 {
2551 ret = WaitForSingleObject(hfile, 3000);
2552 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2553 }
2554 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2555 ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
2556
2557 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2558 ok(off == 0, "expected 0, got %u\n", off);
2559
2560 bytes = 0xdeadbeef;
2561 SetLastError(0xdeadbeef);
2562 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
2563 ok(!ret, "ReadFile should fail\n");
2564 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2565 ok(bytes == 0, "bytes %u\n", bytes);
2566
2567 U(iob).Status = -1;
2568 iob.Information = -1;
2569 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
2570 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2571 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2572 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2573
2574 for (i = -20; i < 0; i++)
2575 {
2576 U(iob).Status = -1;
2577 iob.Information = -1;
2578 offset.QuadPart = (LONGLONG)i;
2579 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2580 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2581 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2582 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2583 }
2584
2585 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2586 ok(off == 0, "expected 0, got %u\n", off);
2587
2588 /* test reading beyond EOF */
2589 offset.QuadPart = sizeof(contents);
2590 S(U(ovl)).Offset = offset.u.LowPart;
2591 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2592 ovl.Internal = -1;
2593 ovl.InternalHigh = -1;
2594 ovl.hEvent = 0;
2595 bytes = 0xdeadbeef;
2596 SetLastError(0xdeadbeef);
2597 ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
2598 ok(!ret, "ReadFile should fail\n");
2599 ret = GetLastError();
2600 ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
2601 ok(bytes == 0, "bytes %u\n", bytes);
2602
2603 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2604 ok(off == 0, "expected 0, got %u\n", off);
2605
2606 if (ret == ERROR_IO_PENDING)
2607 {
2608 bytes = 0xdeadbeef;
2609 SetLastError(0xdeadbeef);
2610 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2611 ok(!ret, "GetOverlappedResult should report FALSE\n");
2612 ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
2613 ok(bytes == 0, "expected 0, read %u\n", bytes);
2614 ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
2615 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2616 }
2617
2618 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2619 ok(off == 0, "expected 0, got %u\n", off);
2620
2621 offset.QuadPart = sizeof(contents);
2622 S(U(ovl)).Offset = offset.u.LowPart;
2623 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2624 ovl.Internal = -1;
2625 ovl.InternalHigh = -1;
2626 ovl.hEvent = 0;
2627 bytes = 0xdeadbeef;
2628 SetLastError(0xdeadbeef);
2629 ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
2630 /* ReadFile return value depends on Windows version and testing it is not practical */
2631 if (!ret)
2632 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2633 ret = GetLastError();
2634 ok(bytes == 0, "bytes %u\n", bytes);
2635
2636 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2637 ok(off == 0, "expected 0, got %u\n", off);
2638
2639 if (ret == ERROR_IO_PENDING)
2640 {
2641 bytes = 0xdeadbeef;
2642 SetLastError(0xdeadbeef);
2643 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2644 ok(ret, "GetOverlappedResult should report TRUE\n");
2645 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2646 ok(bytes == 0, "expected 0, read %u\n", bytes);
2647 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2648 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2649 }
2650
2651 offset.QuadPart = sizeof(contents);
2652 S(U(ovl)).Offset = offset.u.LowPart;
2653 S(U(ovl)).OffsetHigh = offset.u.HighPart;
2654 ovl.Internal = -1;
2655 ovl.InternalHigh = -1;
2656 ovl.hEvent = 0;
2657 bytes = 0xdeadbeef;
2658 SetLastError(0xdeadbeef);
2659 ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
2660 /* ReadFile return value depends on Windows version and testing it is not practical */
2661 if (!ret)
2662 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2663 ret = GetLastError();
2664 ok(bytes == 0, "bytes %u\n", bytes);
2665
2666 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2667 ok(off == 0, "expected 0, got %u\n", off);
2668
2669 if (ret == ERROR_IO_PENDING)
2670 {
2671 bytes = 0xdeadbeef;
2672 SetLastError(0xdeadbeef);
2673 ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
2674 ok(ret, "GetOverlappedResult should report TRUE\n");
2675 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
2676 ok(bytes == 0, "expected 0, read %u\n", bytes);
2677 ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
2678 ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
2679 }
2680
2681 U(iob).Status = -1;
2682 iob.Information = -1;
2683 offset.QuadPart = sizeof(contents);
2684 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
2685 if (status == STATUS_PENDING)
2686 {
2687 ret = WaitForSingleObject(hfile, 3000);
2688 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2689 ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
2690 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2691 }
2692 else
2693 {
2694 ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
2695 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2696 ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
2697 }
2698
2699 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2700 ok(off == 0, "expected 0, got %u\n", off);
2701
2702 U(iob).Status = -1;
2703 iob.Information = -1;
2704 offset.QuadPart = sizeof(contents);
2705 status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2706 if (status == STATUS_PENDING)
2707 {
2708 ret = WaitForSingleObject(hfile, 3000);
2709 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2710 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2711 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2712 }
2713 else
2714 {
2715 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
2716 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2717 ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
2718 }
2719
2720 off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
2721 ok(off == 0, "expected 0, got %u\n", off);
2722
2723 S(U(ovl)).Offset = 0;
2724 S(U(ovl)).OffsetHigh = 0;
2725 ovl.Internal = -1;