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 "winternl.h"
38 #include "winuser.h"
39 #include "winioctl.h"
40 #ifndef __REACTOS__
41 #include "ntifs.h"
42 #else
43 /* FIXME: Inspect */
44 typedef struct _REPARSE_DATA_BUFFER {
45   ULONG ReparseTag;
46   USHORT ReparseDataLength;
47   USHORT Reserved;
48   _ANONYMOUS_UNION union {
49     struct {
50       USHORT SubstituteNameOffset;
51       USHORT SubstituteNameLength;
52       USHORT PrintNameOffset;
53       USHORT PrintNameLength;
54       ULONG Flags;
55       WCHAR PathBuffer[1];
56     } SymbolicLinkReparseBuffer;
57     struct {
58       USHORT SubstituteNameOffset;
59       USHORT SubstituteNameLength;
60       USHORT PrintNameOffset;
61       USHORT PrintNameLength;
62       WCHAR PathBuffer[1];
63     } MountPointReparseBuffer;
64     struct {
65       UCHAR DataBuffer[1];
66     } GenericReparseBuffer;
67   } DUMMYUNIONNAME;
68 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
69 #endif
70 
71 #ifndef IO_COMPLETION_ALL_ACCESS
72 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
73 #endif
74 
75 static BOOL     (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
76 static UINT     (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
77 
78 static VOID     (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
79 static VOID     (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
80 static BOOL     (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
81 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
82 
83 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
84                                        ULONG, ULONG, ULONG, PLARGE_INTEGER );
85 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
86 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
87 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
88 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
89                                       PIO_APC_ROUTINE apc, void* apc_user,
90                                       PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
91                                       PLARGE_INTEGER offset, PULONG key);
92 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
93                                        PIO_APC_ROUTINE apc, void* apc_user,
94                                        PIO_STATUS_BLOCK io_status,
95                                        const void* buffer, ULONG length,
96                                        PLARGE_INTEGER offset, PULONG key);
97 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
98 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
99 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
100 static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
101 
102 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
103 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
104 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
105 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
106 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
107 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
108 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
109 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
110                                                 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
111 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
112 static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
113 static NTSTATUS (WINAPI *pNtFlushBuffersFile)(HANDLE, IO_STATUS_BLOCK*);
114 static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
115 
116 static inline BOOL is_signaled( HANDLE obj )
117 {
118     return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
119 }
120 
121 #define TEST_BUF_LEN 3
122 
123 static HANDLE create_temp_file( ULONG flags )
124 {
125     char path[MAX_PATH], buffer[MAX_PATH];
126     HANDLE handle;
127 
128     GetTempPathA( MAX_PATH, path );
129     GetTempFileNameA( path, "foo", 0, buffer );
130     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
131                          flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
132     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
133     return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
134 }
135 
136 #define CVALUE_FIRST 0xfffabbcc
137 #define CKEY_FIRST 0x1030341
138 #define CKEY_SECOND 0x132E46
139 
140 static ULONG_PTR completionKey;
141 static IO_STATUS_BLOCK ioSb;
142 static ULONG_PTR completionValue;
143 
144 static ULONG get_pending_msgs(HANDLE h)
145 {
146     NTSTATUS res;
147     ULONG a, req;
148 
149     res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
150     ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
151     if (res != STATUS_SUCCESS) return -1;
152     ok( req == sizeof(a), "Unexpected response size: %x\n", req );
153     return a;
154 }
155 
156 static BOOL get_msg(HANDLE h)
157 {
158     LARGE_INTEGER timeout = {{-10000000*3}};
159     DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
160     ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
161     if (res != STATUS_SUCCESS)
162     {
163         completionKey = completionValue = 0;
164         memset(&ioSb, 0, sizeof(ioSb));
165         return FALSE;
166     }
167     return TRUE;
168 }
169 
170 
171 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
172 {
173     int *count = arg;
174 
175     trace( "apc called block %p iosb.status %x iosb.info %lu\n",
176            iosb, U(*iosb).Status, iosb->Information );
177     (*count)++;
178     ok( !reserved, "reserved is not 0: %x\n", reserved );
179 }
180 
181 static void create_file_test(void)
182 {
183     static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
184     static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
185                                         '\\','f','a','i','l','i','n','g',0};
186     static const WCHAR systemrootExplorerW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
187                                                '\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
188     static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
189     static const WCHAR pipeInvalidNameW[]  = {'a','|','b',0};
190     static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
191     static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
192     static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
193     static const char testdata[] = "Hello World";
194     static const WCHAR sepW[] = {'\\',0};
195     FILE_NETWORK_OPEN_INFORMATION info;
196     NTSTATUS status;
197     HANDLE dir, file;
198     WCHAR path[MAX_PATH], temp[MAX_PATH];
199     OBJECT_ATTRIBUTES attr;
200     IO_STATUS_BLOCK io;
201     UNICODE_STRING nameW;
202     LARGE_INTEGER offset;
203     char buf[32];
204     DWORD ret;
205 
206     GetCurrentDirectoryW( MAX_PATH, path );
207     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
208     attr.Length = sizeof(attr);
209     attr.RootDirectory = 0;
210     attr.ObjectName = &nameW;
211     attr.Attributes = OBJ_CASE_INSENSITIVE;
212     attr.SecurityDescriptor = NULL;
213     attr.SecurityQualityOfService = NULL;
214 
215     /* try various open modes and options on directories */
216     status = pNtCreateFile( &dir, GENERIC_READ|GENERIC_WRITE, &attr, &io, NULL, 0,
217                             FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
218     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
219 
220     U(io).Status = 0xdeadbeef;
221     offset.QuadPart = 0;
222     status = pNtReadFile( dir, NULL, NULL, NULL, &io, buf, sizeof(buf), &offset, NULL );
223     ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtReadFile error %08x\n", status );
224     if (status == STATUS_PENDING)
225     {
226         ret = WaitForSingleObject( dir, 1000 );
227         ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
228         ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
229             "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
230     }
231 
232     U(io).Status = 0xdeadbeef;
233     offset.QuadPart = 0;
234     status = pNtWriteFile( dir, NULL, NULL, NULL, &io, testdata, sizeof(testdata), &offset, NULL);
235     todo_wine
236     ok( status == STATUS_INVALID_DEVICE_REQUEST || status == STATUS_PENDING, "NtWriteFile error %08x\n", status );
237     if (status == STATUS_PENDING)
238     {
239         ret = WaitForSingleObject( dir, 1000 );
240         ok( ret == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", ret );
241         ok( U(io).Status == STATUS_INVALID_DEVICE_REQUEST,
242             "expected STATUS_INVALID_DEVICE_REQUEST, got %08x\n", U(io).Status );
243     }
244 
245     CloseHandle( dir );
246 
247     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
248                             FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
249     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
250         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
251 
252     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
253                             FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
254     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
255     CloseHandle( dir );
256 
257     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
258                             FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
259     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
260 
261     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
262                             FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
263     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
264 
265     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
266                             FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
267     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
268 
269     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
270                             FILE_OPEN, 0, NULL, 0 );
271     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
272     CloseHandle( dir );
273 
274     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
275                             FILE_CREATE, 0, NULL, 0 );
276     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
277         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
278 
279     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
280                             FILE_OPEN_IF, 0, NULL, 0 );
281     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
282     CloseHandle( dir );
283 
284     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
285                             FILE_SUPERSEDE, 0, NULL, 0 );
286     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
287         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
288 
289     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
290                             FILE_OVERWRITE, 0, NULL, 0 );
291     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
292         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
293 
294     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
295                             FILE_OVERWRITE_IF, 0, NULL, 0 );
296     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
297         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
298 
299     pRtlFreeUnicodeString( &nameW );
300 
301     pRtlInitUnicodeString( &nameW, systemrootW );
302     attr.Length = sizeof(attr);
303     attr.RootDirectory = NULL;
304     attr.ObjectName = &nameW;
305     attr.Attributes = OBJ_CASE_INSENSITIVE;
306     attr.SecurityDescriptor = NULL;
307     attr.SecurityQualityOfService = NULL;
308     dir = NULL;
309     status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
310                             FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
311     todo_wine
312     ok( status == STATUS_INVALID_PARAMETER,
313         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
314 
315     /* Invalid chars in file/dirnames */
316     pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
317     attr.ObjectName = &nameW;
318     status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
319                            FILE_SHARE_READ, FILE_CREATE,
320                            FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
321     ok(status == STATUS_OBJECT_NAME_INVALID,
322        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
323 
324     status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
325                            0, FILE_CREATE,
326                            FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
327     ok(status == STATUS_OBJECT_NAME_INVALID,
328        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
329     pRtlFreeUnicodeString(&nameW);
330 
331     pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
332     attr.ObjectName = &nameW;
333     status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
334                            FILE_SHARE_READ, FILE_CREATE,
335                            FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
336     ok(status == STATUS_OBJECT_NAME_INVALID,
337        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
338 
339     status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
340                            0, FILE_CREATE,
341                            FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
342     ok(status == STATUS_OBJECT_NAME_INVALID,
343        "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
344     pRtlFreeUnicodeString(&nameW);
345 
346     pRtlInitUnicodeString( &nameW, pathInvalidNtW );
347     status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
348                             FILE_SHARE_READ, FILE_CREATE,
349                             FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
350     ok( status == STATUS_OBJECT_NAME_INVALID,
351         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
352 
353     status = pNtQueryFullAttributesFile( &attr, &info );
354     todo_wine ok( status == STATUS_OBJECT_NAME_INVALID,
355                   "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
356 
357     pRtlInitUnicodeString( &nameW, pathInvalidNt2W );
358     status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
359                             FILE_SHARE_READ, FILE_CREATE,
360                             FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
361     ok( status == STATUS_OBJECT_NAME_INVALID,
362         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
363 
364     status = pNtQueryFullAttributesFile( &attr, &info );
365     ok( status == STATUS_OBJECT_NAME_INVALID,
366         "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
367 
368     pRtlInitUnicodeString( &nameW, pathInvalidDosW );
369     status = pNtCreateFile( &dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
370                             FILE_SHARE_READ, FILE_CREATE,
371                             FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
372     ok( status == STATUS_OBJECT_NAME_INVALID,
373         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
374 
375     status = pNtQueryFullAttributesFile( &attr, &info );
376     ok( status == STATUS_OBJECT_NAME_INVALID,
377         "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
378 
379     GetWindowsDirectoryW( path, MAX_PATH );
380     path[2] = 0;
381     ok( QueryDosDeviceW( path, temp, MAX_PATH ),
382         "QueryDosDeviceW failed with error %u\n", GetLastError() );
383     lstrcatW( temp, sepW );
384     lstrcatW( temp, path+3 );
385     lstrcatW( temp, sepW );
386     lstrcatW( temp, notepadW );
387 
388     pRtlInitUnicodeString( &nameW, temp );
389     status = pNtQueryFullAttributesFile( &attr, &info );
390     ok( status == STATUS_SUCCESS,
391         "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
392 
393     pRtlInitUnicodeString( &nameW, systemrootExplorerW );
394     status = pNtQueryFullAttributesFile( &attr, &info );
395     ok( status == STATUS_SUCCESS,
396         "query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
397 }
398 
399 static void open_file_test(void)
400 {
401     static const char testdata[] = "Hello World";
402     static WCHAR fooW[] = {'f','o','o',0};
403     NTSTATUS status;
404     HANDLE dir, root, handle, file;
405     WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
406     BYTE data[1024];
407     OBJECT_ATTRIBUTES attr;
408     IO_STATUS_BLOCK io;
409     UNICODE_STRING nameW;
410     UINT i, len;
411     BOOL ret, restart = TRUE;
412     DWORD numbytes;
413 
414     len = GetWindowsDirectoryW( path, MAX_PATH );
415     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
416     attr.Length = sizeof(attr);
417     attr.RootDirectory = 0;
418     attr.ObjectName = &nameW;
419     attr.Attributes = OBJ_CASE_INSENSITIVE;
420     attr.SecurityDescriptor = NULL;
421     attr.SecurityQualityOfService = NULL;
422     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
423                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
424     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
425     pRtlFreeUnicodeString( &nameW );
426 
427     path[3] = 0;  /* root of the drive */
428     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
429     status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
430                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
431     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
432     pRtlFreeUnicodeString( &nameW );
433 
434     /* test opening system dir with RootDirectory set to windows dir */
435     GetSystemDirectoryW( path, MAX_PATH );
436     while (path[len] == '\\') len++;
437     nameW.Buffer = path + len;
438     nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
439     attr.RootDirectory = dir;
440     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
441                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
442     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
443     CloseHandle( handle );
444 
445     /* try uppercase name */
446     for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
447     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
448                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
449     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
450     CloseHandle( handle );
451 
452     /* try with leading backslash */
453     nameW.Buffer--;
454     nameW.Length += sizeof(WCHAR);
455     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
456                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
457     ok( status == STATUS_INVALID_PARAMETER ||
458         status == STATUS_OBJECT_NAME_INVALID ||
459         status == STATUS_OBJECT_PATH_SYNTAX_BAD,
460         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
461     if (!status) CloseHandle( handle );
462 
463     /* try with empty name */
464     nameW.Length = 0;
465     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
466                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
467     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
468     CloseHandle( handle );
469 
470     /* try open by file id */
471 
472     while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
473                                    FileIdBothDirectoryInformation, TRUE, NULL, restart ))
474     {
475         FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
476 
477         restart = FALSE;
478 
479         if (!info->FileId.QuadPart) continue;
480 
481         nameW.Buffer = (WCHAR *)&info->FileId;
482         nameW.Length = sizeof(info->FileId);
483         info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
484         attr.RootDirectory = dir;
485         /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
486         status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
487                               FILE_SHARE_READ,
488                               FILE_OPEN_BY_FILE_ID |
489                               ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
490         ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
491             "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
492         if (status == STATUS_NOT_IMPLEMENTED)
493         {
494             win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
495             break;
496         }
497         if (status == STATUS_SHARING_VIOLATION)
498             trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
499         if (!status)
500         {
501             BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
502 
503             if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
504             {
505                 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
506 
507                 /* check that it's the same file/directory */
508 
509                 /* don't check the size for directories */
510                 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
511                     ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
512                         "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
513 
514                 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
515                     "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
516             }
517             CloseHandle( handle );
518 
519             /* try same thing from drive root */
520             attr.RootDirectory = root;
521             status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
522                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
523                                   FILE_OPEN_BY_FILE_ID |
524                                   ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
525             ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
526                 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
527             if (!status) CloseHandle( handle );
528         }
529     }
530 
531     CloseHandle( dir );
532     CloseHandle( root );
533 
534     GetTempPathW( MAX_PATH, path );
535     GetTempFileNameW( path, fooW, 0, tmpfile );
536     pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
537 
538     file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
539     ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
540     numbytes = 0xdeadbeef;
541     ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
542     ok( ret, "WriteFile failed with error %u\n", GetLastError() );
543     ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
544     CloseHandle( file );
545 
546     attr.Length = sizeof(attr);
547     attr.RootDirectory = 0;
548     attr.ObjectName = &nameW;
549     attr.Attributes = OBJ_CASE_INSENSITIVE;
550     attr.SecurityDescriptor = NULL;
551     attr.SecurityQualityOfService = NULL;
552     status = pNtOpenFile( &file, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
553                          FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
554     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
555     pRtlFreeUnicodeString( &nameW );
556 
557     numbytes = 0xdeadbeef;
558     memset( data, 0, sizeof(data) );
559     ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
560     ok( ret, "ReadFile failed with error %u\n", GetLastError() );
561     ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
562     ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
563 
564     nameW.Length = sizeof(fooW) - sizeof(WCHAR);
565     nameW.Buffer = fooW;
566     attr.RootDirectory = file;
567     attr.ObjectName = &nameW;
568     status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
569                          FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
570     ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
571         "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
572 
573     nameW.Length = 0;
574     nameW.Buffer = NULL;
575     attr.RootDirectory = file;
576     attr.ObjectName = &nameW;
577     status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
578                           FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
579     ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
580 
581     numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
582     ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
583     numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
584     ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
585 
586     numbytes = 0xdeadbeef;
587     memset( data, 0, sizeof(data) );
588     ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
589     ok( ret, "ReadFile failed with error %u\n", GetLastError() );
590     ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
591     ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
592 
593     numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
594     ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
595     numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
596     ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
597 
598     CloseHandle( file );
599     CloseHandle( root );
600     DeleteFileW( tmpfile );
601 }
602 
603 static void delete_file_test(void)
604 {
605     NTSTATUS ret;
606     OBJECT_ATTRIBUTES attr;
607     UNICODE_STRING nameW;
608     WCHAR pathW[MAX_PATH];
609     WCHAR pathsubW[MAX_PATH];
610     static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
611     static const WCHAR subdirW[]  = {'\\','s','u','b',0};
612 
613     ret = GetTempPathW(MAX_PATH, pathW);
614     if (!ret)
615     {
616 	ok(0, "couldn't get temp dir\n");
617 	return;
618     }
619     if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
620     {
621 	ok(0, "MAX_PATH exceeded in constructing paths\n");
622 	return;
623     }
624 
625     lstrcatW(pathW, testdirW);
626     lstrcpyW(pathsubW, pathW);
627     lstrcatW(pathsubW, subdirW);
628 
629     ret = CreateDirectoryW(pathW, NULL);
630     ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
631     if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
632     {
633 	ok(0,"RtlDosPathNametoNtPathName_U failed\n");
634 	return;
635     }
636 
637     attr.Length = sizeof(attr);
638     attr.RootDirectory = 0;
639     attr.Attributes = OBJ_CASE_INSENSITIVE;
640     attr.ObjectName = &nameW;
641     attr.SecurityDescriptor = NULL;
642     attr.SecurityQualityOfService = NULL;
643 
644     /* test NtDeleteFile on an empty directory */
645     ret = pNtDeleteFile(&attr);
646     ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
647     ret = RemoveDirectoryW(pathW);
648     ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
649 
650     /* test NtDeleteFile on a non-empty directory */
651     ret = CreateDirectoryW(pathW, NULL);
652     ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
653     ret = CreateDirectoryW(pathsubW, NULL);
654     ok(ret == TRUE, "couldn't create directory subdir\n");
655     ret = pNtDeleteFile(&attr);
656     ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
657     ret = RemoveDirectoryW(pathsubW);
658     ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
659     ret = RemoveDirectoryW(pathW);
660     ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
661 
662     pRtlFreeUnicodeString( &nameW );
663 }
664 
665 static void read_file_test(void)
666 {
667     const char text[] = "foobar";
668     HANDLE handle;
669     IO_STATUS_BLOCK iosb;
670     NTSTATUS status;
671     int apc_count = 0;
672     char buffer[128];
673     LARGE_INTEGER offset;
674     HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
675 
676     if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
677     apc_count = 0;
678     U(iosb).Status = 0xdeadbabe;
679     iosb.Information = 0xdeadbeef;
680     offset.QuadPart = 0;
681     ResetEvent( event );
682     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
683     ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
684     if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
685     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
686     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
687     ok( is_signaled( event ), "event is not signaled\n" );
688     ok( !apc_count, "apc was called\n" );
689     SleepEx( 1, TRUE ); /* alertable sleep */
690     ok( apc_count == 1, "apc was not called\n" );
691 
692     apc_count = 0;
693     U(iosb).Status = 0xdeadbabe;
694     iosb.Information = 0xdeadbeef;
695     offset.QuadPart = 0;
696     ResetEvent( event );
697     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
698     ok( status == STATUS_SUCCESS ||
699         status == STATUS_PENDING, /* vista */
700         "wrong status %x\n", status );
701     if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
702     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
703     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
704     ok( is_signaled( event ), "event is not signaled\n" );
705     ok( !apc_count, "apc was called\n" );
706     SleepEx( 1, TRUE ); /* alertable sleep */
707     ok( apc_count == 1, "apc was not called\n" );
708 
709     /* read beyond eof */
710     apc_count = 0;
711     U(iosb).Status = 0xdeadbabe;
712     iosb.Information = 0xdeadbeef;
713     offset.QuadPart = strlen(text) + 2;
714     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
715     ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
716     if (status == STATUS_PENDING)  /* vista */
717     {
718         WaitForSingleObject( event, 1000 );
719         ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
720         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
721         ok( is_signaled( event ), "event is not signaled\n" );
722         ok( !apc_count, "apc was called\n" );
723         SleepEx( 1, TRUE ); /* alertable sleep */
724         ok( apc_count == 1, "apc was not called\n" );
725     }
726     CloseHandle( handle );
727 
728     /* now a non-overlapped file */
729     if (!(handle = create_temp_file(0))) return;
730     apc_count = 0;
731     U(iosb).Status = 0xdeadbabe;
732     iosb.Information = 0xdeadbeef;
733     offset.QuadPart = 0;
734     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
735     ok( status == STATUS_END_OF_FILE ||
736         status == STATUS_SUCCESS ||
737         status == STATUS_PENDING,  /* vista */
738         "wrong status %x\n", status );
739     if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
740     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
741     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
742     ok( is_signaled( event ), "event is not signaled\n" );
743     ok( !apc_count, "apc was called\n" );
744     SleepEx( 1, TRUE ); /* alertable sleep */
745     ok( apc_count == 1, "apc was not called\n" );
746 
747     apc_count = 0;
748     U(iosb).Status = 0xdeadbabe;
749     iosb.Information = 0xdeadbeef;
750     offset.QuadPart = 0;
751     ResetEvent( event );
752     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
753     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
754     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
755     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
756     ok( is_signaled( event ), "event is not signaled\n" );
757     ok( !apc_count, "apc was called\n" );
758     SleepEx( 1, TRUE ); /* alertable sleep */
759     todo_wine ok( !apc_count, "apc was called\n" );
760 
761     /* read beyond eof */
762     apc_count = 0;
763     U(iosb).Status = 0xdeadbabe;
764     iosb.Information = 0xdeadbeef;
765     offset.QuadPart = strlen(text) + 2;
766     ResetEvent( event );
767     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
768     ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
769     ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
770     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
771     ok( is_signaled( event ), "event is not signaled\n" );
772     ok( !apc_count, "apc was called\n" );
773     SleepEx( 1, TRUE ); /* alertable sleep */
774     ok( !apc_count, "apc was called\n" );
775 
776     CloseHandle( handle );
777 
778     CloseHandle( event );
779 }
780 
781 static void append_file_test(void)
782 {
783     static const char text[6] = "foobar";
784     HANDLE handle;
785     NTSTATUS status;
786     IO_STATUS_BLOCK iosb;
787     LARGE_INTEGER offset;
788     char path[MAX_PATH], buffer[MAX_PATH], buf[16];
789     DWORD ret;
790 
791     GetTempPathA( MAX_PATH, path );
792     GetTempFileNameA( path, "foo", 0, buffer );
793 
794     handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
795     ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
796 
797     U(iosb).Status = -1;
798     iosb.Information = -1;
799     status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
800     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
801     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
802     ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
803 
804     CloseHandle(handle);
805 
806     /* It is possible to open a file with only FILE_APPEND_DATA access flags.
807        It matches the O_WRONLY|O_APPEND open() posix behavior */
808     handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
809     ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
810 
811     U(iosb).Status = -1;
812     iosb.Information = -1;
813     offset.QuadPart = 1;
814     status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
815     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
816     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
817     ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
818 
819     ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
820     ok(ret == 4, "expected 4, got %u\n", ret);
821 
822     U(iosb).Status = -1;
823     iosb.Information = -1;
824     offset.QuadPart = 3;
825     status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
826     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
827     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
828     ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
829 
830     ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
831     ok(ret == 6, "expected 6, got %u\n", ret);
832 
833     CloseHandle(handle);
834 
835     handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
836     ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
837 
838     memset(buf, 0, sizeof(buf));
839     U(iosb).Status = -1;
840     iosb.Information = -1;
841     offset.QuadPart = 0;
842     status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
843     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
844     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
845     ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
846     buf[6] = 0;
847     ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
848 
849     U(iosb).Status = -1;
850     iosb.Information = -1;
851     offset.QuadPart = 0;
852     status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
853     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
854     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
855     ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
856 
857     memset(buf, 0, sizeof(buf));
858     U(iosb).Status = -1;
859     iosb.Information = -1;
860     offset.QuadPart = 0;
861     status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
862     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
863     ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
864     ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
865     buf[6] = 0;
866     ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
867 
868     CloseHandle(handle);
869     DeleteFileA(buffer);
870 }
871 
872 static void nt_mailslot_test(void)
873 {
874     HANDLE hslot;
875     ACCESS_MASK DesiredAccess;
876     OBJECT_ATTRIBUTES attr;
877 
878     ULONG CreateOptions;
879     ULONG MailslotQuota;
880     ULONG MaxMessageSize;
881     LARGE_INTEGER TimeOut;
882     IO_STATUS_BLOCK IoStatusBlock;
883     NTSTATUS rc;
884     UNICODE_STRING str;
885     WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
886                         'R',':','\\','F','R','E','D','\0' };
887 
888     TimeOut.QuadPart = -1;
889 
890     pRtlInitUnicodeString(&str, buffer1);
891     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
892     CreateOptions = MailslotQuota = MaxMessageSize = 0;
893     DesiredAccess = GENERIC_READ;
894 
895     /*
896      * Check for NULL pointer handling
897      */
898     rc = pNtCreateMailslotFile(NULL, DesiredAccess,
899          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
900          &TimeOut);
901     ok( rc == STATUS_ACCESS_VIOLATION ||
902         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
903         "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
904 
905     /*
906      * Test to see if the Timeout can be NULL
907      */
908     hslot = (HANDLE)0xdeadbeef;
909     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
910          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
911          NULL);
912     ok( rc == STATUS_SUCCESS ||
913         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
914         "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
915     ok( hslot != 0, "Handle is invalid\n");
916 
917     if  ( rc == STATUS_SUCCESS ) pNtClose(hslot);
918 
919     /*
920      * Test a valid call
921      */
922     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
923     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
924          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
925          &TimeOut);
926     ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
927     ok( hslot != 0, "Handle is invalid\n");
928 
929     rc = pNtClose(hslot);
930     ok( rc == STATUS_SUCCESS, "NtClose failed\n");
931 }
932 
933 static void test_iocp_setcompletion(HANDLE h)
934 {
935     NTSTATUS res;
936     ULONG count;
937     SIZE_T size = 3;
938 
939     if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
940 
941     res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
942     ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
943 
944     count = get_pending_msgs(h);
945     ok( count == 1, "Unexpected msg count: %d\n", count );
946 
947     if (get_msg(h))
948     {
949         ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
950         ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
951         ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
952         ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
953     }
954 
955     count = get_pending_msgs(h);
956     ok( !count, "Unexpected msg count: %d\n", count );
957 }
958 
959 static void test_iocp_fileio(HANDLE h)
960 {
961     static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
962 
963     IO_STATUS_BLOCK iosb;
964     FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
965     HANDLE hPipeSrv, hPipeClt;
966     NTSTATUS res;
967 
968     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
969     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
970     if (hPipeSrv != INVALID_HANDLE_VALUE )
971     {
972         hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
973         ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
974         if (hPipeClt != INVALID_HANDLE_VALUE)
975         {
976             U(iosb).Status = 0xdeadbeef;
977             res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
978             ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
979             ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
980                 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
981             CloseHandle(hPipeClt);
982         }
983         CloseHandle( hPipeSrv );
984     }
985 
986     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
987     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
988     if (hPipeSrv == INVALID_HANDLE_VALUE )
989         return;
990 
991     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
992     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
993     if (hPipeClt != INVALID_HANDLE_VALUE)
994     {
995         OVERLAPPED o = {0,};
996         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
997         DWORD read;
998         long count;
999 
1000         U(iosb).Status = 0xdeadbeef;
1001         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1002         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1003         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1004 
1005         memset( send_buf, 0, TEST_BUF_LEN );
1006         memset( recv_buf, 0xde, TEST_BUF_LEN );
1007         count = get_pending_msgs(h);
1008         ok( !count, "Unexpected msg count: %ld\n", count );
1009         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1010         count = get_pending_msgs(h);
1011         ok( !count, "Unexpected msg count: %ld\n", count );
1012         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1013 
1014         if (get_msg(h))
1015         {
1016             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1017             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1018             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1019             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1020             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] );
1021         }
1022         count = get_pending_msgs(h);
1023         ok( !count, "Unexpected msg count: %ld\n", count );
1024 
1025         memset( send_buf, 0, TEST_BUF_LEN );
1026         memset( recv_buf, 0xde, TEST_BUF_LEN );
1027         WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1028         count = get_pending_msgs(h);
1029         ok( !count, "Unexpected msg count: %ld\n", count );
1030         ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1031         count = get_pending_msgs(h);
1032         ok( count == 1, "Unexpected msg count: %ld\n", count );
1033         if (get_msg(h))
1034         {
1035             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1036             ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1037             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1038             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1039             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] );
1040         }
1041 
1042         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1043         CloseHandle( hPipeSrv );
1044         count = get_pending_msgs(h);
1045         ok( count == 1, "Unexpected msg count: %ld\n", count );
1046         if (get_msg(h))
1047         {
1048             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1049             ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1050             /* wine sends wrong status here */
1051             ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1052             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1053         }
1054     }
1055 
1056     CloseHandle( hPipeClt );
1057 
1058     /* test associating a completion port with a handle after an async is queued */
1059     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1060     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1061     if (hPipeSrv == INVALID_HANDLE_VALUE )
1062         return;
1063     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1064     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1065     if (hPipeClt != INVALID_HANDLE_VALUE)
1066     {
1067         OVERLAPPED o = {0,};
1068         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1069         int apc_count = 0;
1070         DWORD read;
1071         long count;
1072 
1073         memset( send_buf, 0, TEST_BUF_LEN );
1074         memset( recv_buf, 0xde, TEST_BUF_LEN );
1075         count = get_pending_msgs(h);
1076         ok( !count, "Unexpected msg count: %ld\n", count );
1077         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1078 
1079         U(iosb).Status = 0xdeadbeef;
1080         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1081         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1082         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1083         count = get_pending_msgs(h);
1084         ok( !count, "Unexpected msg count: %ld\n", count );
1085 
1086         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1087 
1088         if (get_msg(h))
1089         {
1090             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1091             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1092             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1093             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1094             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] );
1095         }
1096         count = get_pending_msgs(h);
1097         ok( !count, "Unexpected msg count: %ld\n", count );
1098 
1099         /* using APCs on handle with associated completion port is not allowed */
1100         res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1101         ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1102     }
1103 
1104     CloseHandle( hPipeSrv );
1105     CloseHandle( hPipeClt );
1106 
1107     /* test associating a completion port with a handle after an async using APC is queued */
1108     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1109     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1110     if (hPipeSrv == INVALID_HANDLE_VALUE )
1111         return;
1112     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1113     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1114     if (hPipeClt != INVALID_HANDLE_VALUE)
1115     {
1116         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1117         int apc_count = 0;
1118         DWORD read;
1119         long count;
1120 
1121         memset( send_buf, 0, TEST_BUF_LEN );
1122         memset( recv_buf, 0xde, TEST_BUF_LEN );
1123         count = get_pending_msgs(h);
1124         ok( !count, "Unexpected msg count: %ld\n", count );
1125 
1126         res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1127         ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
1128 
1129         U(iosb).Status = 0xdeadbeef;
1130         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1131         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1132         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1133         count = get_pending_msgs(h);
1134         ok( !count, "Unexpected msg count: %ld\n", count );
1135 
1136         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1137 
1138         ok(!apc_count, "apc_count = %u\n", apc_count);
1139         count = get_pending_msgs(h);
1140         ok( !count, "Unexpected msg count: %ld\n", count );
1141 
1142         SleepEx(1, TRUE); /* alertable sleep */
1143         ok(apc_count == 1, "apc was not called\n");
1144         count = get_pending_msgs(h);
1145         ok( !count, "Unexpected msg count: %ld\n", count );
1146 
1147         /* using APCs on handle with associated completion port is not allowed */
1148         res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
1149         ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
1150     }
1151 
1152     CloseHandle( hPipeSrv );
1153     CloseHandle( hPipeClt );
1154 }
1155 
1156 static void test_file_full_size_information(void)
1157 {
1158     IO_STATUS_BLOCK io;
1159     FILE_FS_FULL_SIZE_INFORMATION ffsi;
1160     FILE_FS_SIZE_INFORMATION fsi;
1161     HANDLE h;
1162     NTSTATUS res;
1163 
1164     if(!(h = create_temp_file(0))) return ;
1165 
1166     memset(&ffsi,0,sizeof(ffsi));
1167     memset(&fsi,0,sizeof(fsi));
1168 
1169     /* Assume No Quota Settings configured on Wine Testbot */
1170     res = pNtQueryVolumeInformationFile(h, &io, &ffsi, sizeof ffsi, FileFsFullSizeInformation);
1171     ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1172     res = pNtQueryVolumeInformationFile(h, &io, &fsi, sizeof fsi, FileFsSizeInformation);
1173     ok(res == STATUS_SUCCESS, "cannot get attributes, res %x\n", res);
1174 
1175     /* Test for FileFsSizeInformation */
1176     ok(fsi.TotalAllocationUnits.QuadPart > 0,
1177         "[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
1178         wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
1179     ok(fsi.AvailableAllocationUnits.QuadPart > 0,
1180         "[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
1181         wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
1182 
1183     /* Assume file system is NTFS */
1184     ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
1185     ok(fsi.SectorsPerAllocationUnit == 8, "[fsi] SectorsPerAllocationUnit expected 8, got %d\n",fsi.SectorsPerAllocationUnit);
1186 
1187     ok(ffsi.TotalAllocationUnits.QuadPart > 0,
1188         "[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
1189         wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1190     ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
1191         "[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1192         wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1193     ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
1194         "[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
1195         wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
1196     ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
1197         "[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
1198         wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
1199         wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
1200     ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
1201         "[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
1202         wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
1203         wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
1204 
1205     /* Assume file system is NTFS */
1206     ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
1207     ok(ffsi.SectorsPerAllocationUnit == 8, "[ffsi] SectorsPerAllocationUnit expected 8, got %d\n",ffsi.SectorsPerAllocationUnit);
1208 
1209     CloseHandle( h );
1210 }
1211 
1212 static void test_file_basic_information(void)
1213 {
1214     IO_STATUS_BLOCK io;
1215     FILE_BASIC_INFORMATION fbi;
1216     HANDLE h;
1217     int res;
1218     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1219 
1220     if (!(h = create_temp_file(0))) return;
1221 
1222     /* Check default first */
1223     memset(&fbi, 0, sizeof(fbi));
1224     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1225     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1226     ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1227          "attribute %x not expected\n", fbi.FileAttributes );
1228 
1229     /* Then SYSTEM */
1230     /* Clear fbi to avoid setting times */
1231     memset(&fbi, 0, sizeof(fbi));
1232     fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1233     U(io).Status = 0xdeadbeef;
1234     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1235     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1236     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1237 
1238     memset(&fbi, 0, sizeof(fbi));
1239     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1240     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1241     ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes );
1242 
1243     /* Then HIDDEN */
1244     memset(&fbi, 0, sizeof(fbi));
1245     fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1246     U(io).Status = 0xdeadbeef;
1247     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1248     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1249     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1250 
1251     memset(&fbi, 0, sizeof(fbi));
1252     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1253     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1254     ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes );
1255 
1256     /* Check NORMAL last of all (to make sure we can clear attributes) */
1257     memset(&fbi, 0, sizeof(fbi));
1258     fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1259     U(io).Status = 0xdeadbeef;
1260     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1261     ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1262     ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1263 
1264     memset(&fbi, 0, sizeof(fbi));
1265     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1266     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1267     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1268 
1269     CloseHandle( h );
1270 }
1271 
1272 static void test_file_all_information(void)
1273 {
1274     IO_STATUS_BLOCK io;
1275     /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1276      * buffer at the end.  Vista objects with STATUS_BUFFER_OVERFLOW if you
1277      * don't leave enough room there.
1278      */
1279     struct {
1280       FILE_ALL_INFORMATION fai;
1281       WCHAR buf[256];
1282     } fai_buf;
1283     HANDLE h;
1284     int res;
1285     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1286 
1287     if (!(h = create_temp_file(0))) return;
1288 
1289     /* Check default first */
1290     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1291     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1292     ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1293          "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1294 
1295     /* Then SYSTEM */
1296     /* Clear fbi to avoid setting times */
1297     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1298     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1299     U(io).Status = 0xdeadbeef;
1300     res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1301     ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1302     todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1303     U(io).Status = 0xdeadbeef;
1304     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1305     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1306     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1307 
1308     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1309     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1310     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1311     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 );
1312 
1313     /* Then HIDDEN */
1314     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1315     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1316     U(io).Status = 0xdeadbeef;
1317     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1318     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1319     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1320 
1321     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1322     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1323     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1324     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 );
1325 
1326     /* Check NORMAL last of all (to make sure we can clear attributes) */
1327     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1328     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1329     U(io).Status = 0xdeadbeef;
1330     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1331     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1332     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1333 
1334     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1335     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1336     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1337     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 );
1338 
1339     CloseHandle( h );
1340 }
1341 
1342 static void delete_object( WCHAR *path )
1343 {
1344     BOOL ret = DeleteFileW( path );
1345     ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
1346         "DeleteFileW failed with %u\n", GetLastError() );
1347     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1348     {
1349         ret = RemoveDirectoryW( path );
1350         ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
1351     }
1352 }
1353 
1354 static void test_file_rename_information(void)
1355 {
1356     static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1357     static const WCHAR fooW[] = {'f','o','o',0};
1358     WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1359     FILE_RENAME_INFORMATION *fri;
1360     FILE_NAME_INFORMATION *fni;
1361     BOOL success, fileDeleted;
1362     UNICODE_STRING name_str;
1363     HANDLE handle, handle2;
1364     IO_STATUS_BLOCK io;
1365     NTSTATUS res;
1366 
1367     GetTempPathW( MAX_PATH, tmp_path );
1368 
1369     /* oldpath is a file, newpath doesn't exist */
1370     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1371     ok( res != 0, "failed to create temp file\n" );
1372     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1373     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1374 
1375     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1376     ok( res != 0, "failed to create temp file\n" );
1377     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1378     DeleteFileW( newpath );
1379     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1380     fri->Replace = FALSE;
1381     fri->RootDir = NULL;
1382     fri->FileNameLength = name_str.Length;
1383     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1384     pRtlFreeUnicodeString( &name_str );
1385 
1386     U(io).Status = 0xdeadbeef;
1387     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1388     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1389     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1390     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1391     ok( fileDeleted, "file should not exist\n" );
1392     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1393     ok( !fileDeleted, "file should exist\n" );
1394 
1395     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1396     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1397     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1398     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1399     ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1400         wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1401     HeapFree( GetProcessHeap(), 0, fni );
1402 
1403     CloseHandle( handle );
1404     HeapFree( GetProcessHeap(), 0, fri );
1405     delete_object( oldpath );
1406     delete_object( newpath );
1407 
1408     /* oldpath is a file, newpath is a file, Replace = FALSE */
1409     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1410     ok( res != 0, "failed to create temp file\n" );
1411     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1412     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1413 
1414     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1415     ok( res != 0, "failed to create temp file\n" );
1416     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1417     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1418     fri->Replace = FALSE;
1419     fri->RootDir = NULL;
1420     fri->FileNameLength = name_str.Length;
1421     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1422     pRtlFreeUnicodeString( &name_str );
1423 
1424     U(io).Status = 0xdeadbeef;
1425     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1426     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1427     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1428     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1429     ok( !fileDeleted, "file should exist\n" );
1430     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1431     ok( !fileDeleted, "file should exist\n" );
1432 
1433     CloseHandle( handle );
1434     HeapFree( GetProcessHeap(), 0, fri );
1435     delete_object( oldpath );
1436     delete_object( newpath );
1437 
1438     /* oldpath is a file, newpath is a file, Replace = TRUE */
1439     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1440     ok( res != 0, "failed to create temp file\n" );
1441     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1442     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1443 
1444     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1445     ok( res != 0, "failed to create temp file\n" );
1446     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1447     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1448     fri->Replace = TRUE;
1449     fri->RootDir = NULL;
1450     fri->FileNameLength = name_str.Length;
1451     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1452     pRtlFreeUnicodeString( &name_str );
1453 
1454     U(io).Status = 0xdeadbeef;
1455     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1456     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1457     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1458     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1459     ok( fileDeleted, "file should not exist\n" );
1460     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1461     ok( !fileDeleted, "file should exist\n" );
1462 
1463     CloseHandle( handle );
1464     HeapFree( GetProcessHeap(), 0, fri );
1465     delete_object( oldpath );
1466     delete_object( newpath );
1467 
1468     /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
1469     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1470     ok( res != 0, "failed to create temp file\n" );
1471     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1472     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1473 
1474     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1475     ok( res != 0, "failed to create temp file\n" );
1476     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1477     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1478 
1479     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1480     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1481     fri->Replace = FALSE;
1482     fri->RootDir = NULL;
1483     fri->FileNameLength = name_str.Length;
1484     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1485     pRtlFreeUnicodeString( &name_str );
1486 
1487     U(io).Status = 0xdeadbeef;
1488     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1489     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1490     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1491     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1492     ok( !fileDeleted, "file should exist\n" );
1493     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1494     ok( !fileDeleted, "file should exist\n" );
1495 
1496     CloseHandle( handle );
1497     CloseHandle( handle2 );
1498     HeapFree( GetProcessHeap(), 0, fri );
1499     delete_object( oldpath );
1500     delete_object( newpath );
1501 
1502     /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
1503     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1504     ok( res != 0, "failed to create temp file\n" );
1505     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1506     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1507 
1508     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1509     ok( res != 0, "failed to create temp file\n" );
1510     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1511     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1512 
1513     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1514     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1515     fri->Replace = TRUE;
1516     fri->RootDir = NULL;
1517     fri->FileNameLength = name_str.Length;
1518     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1519     pRtlFreeUnicodeString( &name_str );
1520 
1521     U(io).Status = 0xdeadbeef;
1522     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1523     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1524     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1525     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1526     ok( !fileDeleted, "file should exist\n" );
1527     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1528     ok( !fileDeleted, "file should exist\n" );
1529 
1530     CloseHandle( handle );
1531     CloseHandle( handle2 );
1532     HeapFree( GetProcessHeap(), 0, fri );
1533     delete_object( oldpath );
1534     delete_object( newpath );
1535 
1536     /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
1537     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1538     ok( res != 0, "failed to create temp file\n" );
1539     DeleteFileW( oldpath );
1540     success = CreateDirectoryW( oldpath, NULL );
1541     ok( success != 0, "failed to create temp directory\n" );
1542     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1543     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1544 
1545     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1546     ok( res != 0, "failed to create temp file\n" );
1547     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1548     DeleteFileW( newpath );
1549     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1550     fri->Replace = FALSE;
1551     fri->RootDir = NULL;
1552     fri->FileNameLength = name_str.Length;
1553     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1554     pRtlFreeUnicodeString( &name_str );
1555 
1556     U(io).Status = 0xdeadbeef;
1557     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1558     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1559     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1560     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1561     ok( fileDeleted, "file should not exist\n" );
1562     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1563     ok( !fileDeleted, "file should exist\n" );
1564 
1565     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1566     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1567     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1568     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1569     ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1570         wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1571     HeapFree( GetProcessHeap(), 0, fni );
1572 
1573     CloseHandle( handle );
1574     HeapFree( GetProcessHeap(), 0, fri );
1575     delete_object( oldpath );
1576     delete_object( newpath );
1577 
1578     /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
1579     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1580     ok( res != 0, "failed to create temp file\n" );
1581     DeleteFileW( oldpath );
1582     success = CreateDirectoryW( oldpath, NULL );
1583     ok( success != 0, "failed to create temp directory\n" );
1584     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1585     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1586 
1587     lstrcpyW( newpath, oldpath );
1588     lstrcatW( newpath, foo_txtW );
1589     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
1590     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1591 
1592     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1593     ok( res != 0, "failed to create temp file\n" );
1594     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1595     DeleteFileW( newpath );
1596     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1597     fri->Replace = FALSE;
1598     fri->RootDir = NULL;
1599     fri->FileNameLength = name_str.Length;
1600     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1601     pRtlFreeUnicodeString( &name_str );
1602 
1603     U(io).Status = 0xdeadbeef;
1604     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1605     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1606     todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1607     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1608     todo_wine ok( !fileDeleted, "file should exist\n" );
1609     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1610     todo_wine ok( fileDeleted, "file should not exist\n" );
1611 
1612     CloseHandle( handle );
1613     CloseHandle( handle2 );
1614     HeapFree( GetProcessHeap(), 0, fri );
1615     delete_object( oldpath );
1616     if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
1617     {
1618         lstrcpyW( oldpath, newpath );
1619         lstrcatW( oldpath, foo_txtW );
1620         delete_object( oldpath );
1621     }
1622     delete_object( newpath );
1623 
1624     /* oldpath is a directory, newpath is a file, Replace = FALSE */
1625     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1626     ok( res != 0, "failed to create temp file\n" );
1627     DeleteFileW( oldpath );
1628     success = CreateDirectoryW( oldpath, NULL );
1629     ok( success != 0, "failed to create temp directory\n" );
1630     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1631     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1632 
1633     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1634     ok( res != 0, "failed to create temp file\n" );
1635     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1636     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1637     fri->Replace = FALSE;
1638     fri->RootDir = NULL;
1639     fri->FileNameLength = name_str.Length;
1640     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1641     pRtlFreeUnicodeString( &name_str );
1642 
1643     U(io).Status = 0xdeadbeef;
1644     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1645     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1646     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1647     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1648     ok( !fileDeleted, "file should exist\n" );
1649     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1650     ok( !fileDeleted, "file should exist\n" );
1651 
1652     CloseHandle( handle );
1653     HeapFree( GetProcessHeap(), 0, fri );
1654     delete_object( oldpath );
1655     delete_object( newpath );
1656 
1657     /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
1658     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1659     ok( res != 0, "failed to create temp file\n" );
1660     DeleteFileW( oldpath );
1661     success = CreateDirectoryW( oldpath, NULL );
1662     ok( success != 0, "failed to create temp directory\n" );
1663     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1664     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1665 
1666     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1667     ok( res != 0, "failed to create temp file\n" );
1668     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1669     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1670 
1671     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1672     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1673     fri->Replace = FALSE;
1674     fri->RootDir = NULL;
1675     fri->FileNameLength = name_str.Length;
1676     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1677     pRtlFreeUnicodeString( &name_str );
1678 
1679     U(io).Status = 0xdeadbeef;
1680     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1681     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1682     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1683     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1684     ok( !fileDeleted, "file should exist\n" );
1685     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1686     ok( !fileDeleted, "file should exist\n" );
1687 
1688     CloseHandle( handle );
1689     CloseHandle( handle2 );
1690     HeapFree( GetProcessHeap(), 0, fri );
1691     delete_object( oldpath );
1692     delete_object( newpath );
1693 
1694     /* oldpath is a directory, newpath is a file, Replace = TRUE */
1695     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1696     ok( res != 0, "failed to create temp file\n" );
1697     DeleteFileW( oldpath );
1698     success = CreateDirectoryW( oldpath, NULL );
1699     ok( success != 0, "failed to create temp directory\n" );
1700     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1701     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1702 
1703     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1704     ok( res != 0, "failed to create temp file\n" );
1705     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1706     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1707     fri->Replace = TRUE;
1708     fri->RootDir = NULL;
1709     fri->FileNameLength = name_str.Length;
1710     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1711     pRtlFreeUnicodeString( &name_str );
1712 
1713     U(io).Status = 0xdeadbeef;
1714     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1715     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1716     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1717     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1718     ok( fileDeleted, "file should not exist\n" );
1719     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1720     ok( !fileDeleted, "file should exist\n" );
1721 
1722     CloseHandle( handle );
1723     HeapFree( GetProcessHeap(), 0, fri );
1724     delete_object( oldpath );
1725     delete_object( newpath );
1726 
1727     /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
1728     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1729     ok( res != 0, "failed to create temp file\n" );
1730     DeleteFileW( oldpath );
1731     success = CreateDirectoryW( oldpath, NULL );
1732     ok( success != 0, "failed to create temp directory\n" );
1733     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1734     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1735 
1736     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1737     ok( res != 0, "failed to create temp file\n" );
1738     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1739     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1740 
1741     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1742     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1743     fri->Replace = TRUE;
1744     fri->RootDir = NULL;
1745     fri->FileNameLength = name_str.Length;
1746     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1747     pRtlFreeUnicodeString( &name_str );
1748 
1749     U(io).Status = 0xdeadbeef;
1750     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1751     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1752     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1753     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1754     ok( !fileDeleted, "file should exist\n" );
1755     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1756     ok( !fileDeleted, "file should exist\n" );
1757 
1758     CloseHandle( handle );
1759     CloseHandle( handle2 );
1760     HeapFree( GetProcessHeap(), 0, fri );
1761     delete_object( oldpath );
1762     delete_object( newpath );
1763 
1764     /* oldpath is a directory, newpath is a directory, Replace = FALSE */
1765     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1766     ok( res != 0, "failed to create temp file\n" );
1767     DeleteFileW( oldpath );
1768     success = CreateDirectoryW( oldpath, NULL );
1769     ok( success != 0, "failed to create temp directory\n" );
1770     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1771     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1772 
1773     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1774     ok( res != 0, "failed to create temp file\n" );
1775     DeleteFileW( newpath );
1776     success = CreateDirectoryW( newpath, NULL );
1777     ok( success != 0, "failed to create temp directory\n" );
1778     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1779     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1780     fri->Replace = FALSE;
1781     fri->RootDir = NULL;
1782     fri->FileNameLength = name_str.Length;
1783     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1784     pRtlFreeUnicodeString( &name_str );
1785 
1786     U(io).Status = 0xdeadbeef;
1787     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1788     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1789     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1790     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1791     ok( !fileDeleted, "file should exist\n" );
1792     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1793     ok( !fileDeleted, "file should exist\n" );
1794 
1795     CloseHandle( handle );
1796     HeapFree( GetProcessHeap(), 0, fri );
1797     delete_object( oldpath );
1798     delete_object( newpath );
1799 
1800     /* oldpath is a directory, newpath is a directory, Replace = TRUE */
1801     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1802     ok( res != 0, "failed to create temp file\n" );
1803     DeleteFileW( oldpath );
1804     success = CreateDirectoryW( oldpath, NULL );
1805     ok( success != 0, "failed to create temp directory\n" );
1806     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1807     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1808 
1809     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1810     ok( res != 0, "failed to create temp file\n" );
1811     DeleteFileW( newpath );
1812     success = CreateDirectoryW( newpath, NULL );
1813     ok( success != 0, "failed to create temp directory\n" );
1814     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1815     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1816     fri->Replace = TRUE;
1817     fri->RootDir = NULL;
1818     fri->FileNameLength = name_str.Length;
1819     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1820     pRtlFreeUnicodeString( &name_str );
1821 
1822     U(io).Status = 0xdeadbeef;
1823     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1824     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1825     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1826     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1827     ok( !fileDeleted, "file should exist\n" );
1828     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1829     ok( !fileDeleted, "file should exist\n" );
1830 
1831     CloseHandle( handle );
1832     HeapFree( GetProcessHeap(), 0, fri );
1833     delete_object( oldpath );
1834     delete_object( newpath );
1835 
1836     /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
1837     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1838     ok( res != 0, "failed to create temp file\n" );
1839     DeleteFileW( oldpath );
1840     success = CreateDirectoryW( oldpath, NULL );
1841     ok( success != 0, "failed to create temp directory\n" );
1842     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1843     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1844 
1845     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1846     ok( res != 0, "failed to create temp file\n" );
1847     DeleteFileW( newpath );
1848     success = CreateDirectoryW( newpath, NULL );
1849     ok( success != 0, "failed to create temp directory\n" );
1850     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1851     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1852 
1853     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1854     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1855     fri->Replace = TRUE;
1856     fri->RootDir = NULL;
1857     fri->FileNameLength = name_str.Length;
1858     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1859     pRtlFreeUnicodeString( &name_str );
1860 
1861     U(io).Status = 0xdeadbeef;
1862     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1863     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1864     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1865     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1866     ok( !fileDeleted, "file should exist\n" );
1867     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1868     ok( !fileDeleted, "file should exist\n" );
1869 
1870     CloseHandle( handle );
1871     CloseHandle( handle2 );
1872     HeapFree( GetProcessHeap(), 0, fri );
1873     delete_object( oldpath );
1874     delete_object( newpath );
1875 
1876     /* oldpath is a file, newpath is a directory, Replace = FALSE */
1877     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1878     ok( res != 0, "failed to create temp file\n" );
1879     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1880     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1881 
1882     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1883     ok( res != 0, "failed to create temp file\n" );
1884     DeleteFileW( newpath );
1885     success = CreateDirectoryW( newpath, NULL );
1886     ok( success != 0, "failed to create temp directory\n" );
1887     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1888     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1889     fri->Replace = FALSE;
1890     fri->RootDir = NULL;
1891     fri->FileNameLength = name_str.Length;
1892     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1893     pRtlFreeUnicodeString( &name_str );
1894 
1895     U(io).Status = 0xdeadbeef;
1896     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1897     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1898     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
1899     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1900     ok( !fileDeleted, "file should exist\n" );
1901     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1902     ok( !fileDeleted, "file should exist\n" );
1903 
1904     CloseHandle( handle );
1905     HeapFree( GetProcessHeap(), 0, fri );
1906     delete_object( oldpath );
1907     delete_object( newpath );
1908 
1909     /* oldpath is a file, newpath is a directory, Replace = TRUE */
1910     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1911     ok( res != 0, "failed to create temp file\n" );
1912     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1913     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1914 
1915     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1916     ok( res != 0, "failed to create temp file\n" );
1917     DeleteFileW( newpath );
1918     success = CreateDirectoryW( newpath, NULL );
1919     ok( success != 0, "failed to create temp directory\n" );
1920     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
1921     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
1922     fri->Replace = TRUE;
1923     fri->RootDir = NULL;
1924     fri->FileNameLength = name_str.Length;
1925     memcpy( fri->FileName, name_str.Buffer, name_str.Length );
1926     pRtlFreeUnicodeString( &name_str );
1927 
1928     U(io).Status = 0xdeadbeef;
1929     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1930     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
1931     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
1932     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1933     ok( !fileDeleted, "file should exist\n" );
1934     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1935     ok( !fileDeleted, "file should exist\n" );
1936 
1937     CloseHandle( handle );
1938     HeapFree( GetProcessHeap(), 0, fri );
1939     delete_object( oldpath );
1940     delete_object( newpath );
1941 
1942     /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
1943     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
1944     ok( res != 0, "failed to create temp file\n" );
1945     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
1946     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1947 
1948     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
1949     ok( res != 0, "failed to create temp file\n" );
1950     DeleteFileW( newpath );
1951     for (filename = newpath, p = newpath; *p; p++)
1952         if (*p == '\\') filename = p + 1;
1953     handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1954     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
1955 
1956     fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
1957     fri->Replace = FALSE;
1958     fri->RootDir = handle2;
1959     fri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
1960     memcpy( fri->FileName, filename, fri->FileNameLength );
1961 
1962     U(io).Status = 0xdeadbeef;
1963     res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
1964     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
1965     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1966     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1967     ok( fileDeleted, "file should not exist\n" );
1968     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
1969     ok( !fileDeleted, "file should exist\n" );
1970 
1971     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
1972     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
1973     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
1974     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
1975     ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
1976         wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
1977     HeapFree( GetProcessHeap(), 0, fni );
1978 
1979     CloseHandle( handle );
1980     CloseHandle( handle2 );
1981     HeapFree( GetProcessHeap(), 0, fri );
1982     delete_object( oldpath );
1983     delete_object( newpath );
1984 }
1985 
1986 static void test_file_link_information(void)
1987 {
1988     static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
1989     static const WCHAR fooW[] = {'f','o','o',0};
1990     WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
1991     FILE_LINK_INFORMATION *fli;
1992     FILE_NAME_INFORMATION *fni;
1993     BOOL success, fileDeleted;
1994     UNICODE_STRING name_str;
1995     HANDLE handle, handle2;
1996     IO_STATUS_BLOCK io;
1997     NTSTATUS res;
1998 
1999     GetTempPathW( MAX_PATH, tmp_path );
2000 
2001     /* oldpath is a file, newpath doesn't exist */
2002     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2003     ok( res != 0, "failed to create temp file\n" );
2004     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2005     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2006 
2007     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2008     ok( res != 0, "failed to create temp file\n" );
2009     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2010     DeleteFileW( newpath );
2011     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2012     fli->ReplaceIfExists = FALSE;
2013     fli->RootDirectory = NULL;
2014     fli->FileNameLength = name_str.Length;
2015     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2016     pRtlFreeUnicodeString( &name_str );
2017 
2018     U(io).Status = 0xdeadbeef;
2019     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2020     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2021     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2022     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2023     ok( !fileDeleted, "file should exist\n" );
2024     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2025     ok( !fileDeleted, "file should exist\n" );
2026 
2027     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2028     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2029     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2030     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2031     ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2032         wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2033     HeapFree( GetProcessHeap(), 0, fni );
2034 
2035     CloseHandle( handle );
2036     HeapFree( GetProcessHeap(), 0, fli );
2037     delete_object( oldpath );
2038     delete_object( newpath );
2039 
2040     /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
2041     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2042     ok( res != 0, "failed to create temp file\n" );
2043     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2044     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2045 
2046     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2047     ok( res != 0, "failed to create temp file\n" );
2048     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2049     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2050     fli->ReplaceIfExists = FALSE;
2051     fli->RootDirectory = NULL;
2052     fli->FileNameLength = name_str.Length;
2053     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2054     pRtlFreeUnicodeString( &name_str );
2055 
2056     U(io).Status = 0xdeadbeef;
2057     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2058     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2059     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2060     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2061     ok( !fileDeleted, "file should exist\n" );
2062     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2063     ok( !fileDeleted, "file should exist\n" );
2064 
2065     CloseHandle( handle );
2066     HeapFree( GetProcessHeap(), 0, fli );
2067     delete_object( oldpath );
2068     delete_object( newpath );
2069 
2070     /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
2071     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2072     ok( res != 0, "failed to create temp file\n" );
2073     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2074     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2075 
2076     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2077     ok( res != 0, "failed to create temp file\n" );
2078     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2079     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2080     fli->ReplaceIfExists = TRUE;
2081     fli->RootDirectory = NULL;
2082     fli->FileNameLength = name_str.Length;
2083     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2084     pRtlFreeUnicodeString( &name_str );
2085 
2086     U(io).Status = 0xdeadbeef;
2087     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2088     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2089     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2090     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2091     ok( !fileDeleted, "file should exist\n" );
2092     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2093     ok( !fileDeleted, "file should exist\n" );
2094 
2095     CloseHandle( handle );
2096     HeapFree( GetProcessHeap(), 0, fli );
2097     delete_object( oldpath );
2098     delete_object( newpath );
2099 
2100     /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2101     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2102     ok( res != 0, "failed to create temp file\n" );
2103     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2104     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2105 
2106     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2107     ok( res != 0, "failed to create temp file\n" );
2108     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2109     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2110 
2111     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2112     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2113     fli->ReplaceIfExists = FALSE;
2114     fli->RootDirectory = NULL;
2115     fli->FileNameLength = name_str.Length;
2116     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2117     pRtlFreeUnicodeString( &name_str );
2118 
2119     U(io).Status = 0xdeadbeef;
2120     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2121     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2122     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2123     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2124     ok( !fileDeleted, "file should exist\n" );
2125     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2126     ok( !fileDeleted, "file should exist\n" );
2127 
2128     CloseHandle( handle );
2129     CloseHandle( handle2 );
2130     HeapFree( GetProcessHeap(), 0, fli );
2131     delete_object( oldpath );
2132     delete_object( newpath );
2133 
2134     /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2135     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2136     ok( res != 0, "failed to create temp file\n" );
2137     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2138     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2139 
2140     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2141     ok( res != 0, "failed to create temp file\n" );
2142     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2143     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2144 
2145     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2146     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2147     fli->ReplaceIfExists = TRUE;
2148     fli->RootDirectory = NULL;
2149     fli->FileNameLength = name_str.Length;
2150     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2151     pRtlFreeUnicodeString( &name_str );
2152 
2153     U(io).Status = 0xdeadbeef;
2154     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2155     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2156     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2157     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2158     ok( !fileDeleted, "file should exist\n" );
2159     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2160     ok( !fileDeleted, "file should exist\n" );
2161 
2162     CloseHandle( handle );
2163     CloseHandle( handle2 );
2164     HeapFree( GetProcessHeap(), 0, fli );
2165     delete_object( oldpath );
2166     delete_object( newpath );
2167 
2168     /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
2169     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2170     ok( res != 0, "failed to create temp file\n" );
2171     DeleteFileW( oldpath );
2172     success = CreateDirectoryW( oldpath, NULL );
2173     ok( success != 0, "failed to create temp directory\n" );
2174     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2175     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2176 
2177     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2178     ok( res != 0, "failed to create temp file\n" );
2179     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2180     DeleteFileW( newpath );
2181     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2182     fli->ReplaceIfExists = FALSE;
2183     fli->RootDirectory = NULL;
2184     fli->FileNameLength = name_str.Length;
2185     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2186     pRtlFreeUnicodeString( &name_str );
2187 
2188     U(io).Status = 0xdeadbeef;
2189     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2190     todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2191     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2192     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2193     ok( !fileDeleted, "file should exist\n" );
2194     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2195     ok( fileDeleted, "file should not exist\n" );
2196 
2197     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2198     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2199     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2200     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2201     ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2202         wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2203     HeapFree( GetProcessHeap(), 0, fni );
2204 
2205     CloseHandle( handle );
2206     HeapFree( GetProcessHeap(), 0, fli );
2207     delete_object( oldpath );
2208     delete_object( newpath );
2209 
2210     /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
2211     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2212     ok( res != 0, "failed to create temp file\n" );
2213     DeleteFileW( oldpath );
2214     success = CreateDirectoryW( oldpath, NULL );
2215     ok( success != 0, "failed to create temp directory\n" );
2216     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2217     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2218 
2219     lstrcpyW( newpath, oldpath );
2220     lstrcatW( newpath, foo_txtW );
2221     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
2222     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2223 
2224     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2225     ok( res != 0, "failed to create temp file\n" );
2226     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2227     DeleteFileW( newpath );
2228     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2229     fli->ReplaceIfExists = FALSE;
2230     fli->RootDirectory = NULL;
2231     fli->FileNameLength = name_str.Length;
2232     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2233     pRtlFreeUnicodeString( &name_str );
2234 
2235     U(io).Status = 0xdeadbeef;
2236     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2237     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2238     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2239     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2240     ok( !fileDeleted, "file should exist\n" );
2241     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2242     ok( fileDeleted, "file should not exist\n" );
2243 
2244     CloseHandle( handle );
2245     CloseHandle( handle2 );
2246     HeapFree( GetProcessHeap(), 0, fli );
2247     delete_object( oldpath );
2248     delete_object( newpath );
2249 
2250     /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
2251     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2252     ok( res != 0, "failed to create temp file\n" );
2253     DeleteFileW( oldpath );
2254     success = CreateDirectoryW( oldpath, NULL );
2255     ok( success != 0, "failed to create temp directory\n" );
2256     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2257     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2258 
2259     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2260     ok( res != 0, "failed to create temp file\n" );
2261     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2262     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2263     fli->ReplaceIfExists = FALSE;
2264     fli->RootDirectory = NULL;
2265     fli->FileNameLength = name_str.Length;
2266     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2267     pRtlFreeUnicodeString( &name_str );
2268 
2269     U(io).Status = 0xdeadbeef;
2270     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2271     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2272     ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2273         "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2274     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2275     ok( !fileDeleted, "file should exist\n" );
2276     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2277     ok( !fileDeleted, "file should exist\n" );
2278 
2279     CloseHandle( handle );
2280     HeapFree( GetProcessHeap(), 0, fli );
2281     delete_object( oldpath );
2282     delete_object( newpath );
2283 
2284     /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
2285     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2286     ok( res != 0, "failed to create temp file\n" );
2287     DeleteFileW( oldpath );
2288     success = CreateDirectoryW( oldpath, NULL );
2289     ok( success != 0, "failed to create temp directory\n" );
2290     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2291     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2292 
2293     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2294     ok( res != 0, "failed to create temp file\n" );
2295     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2296     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2297 
2298     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2299     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2300     fli->ReplaceIfExists = FALSE;
2301     fli->RootDirectory = NULL;
2302     fli->FileNameLength = name_str.Length;
2303     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2304     pRtlFreeUnicodeString( &name_str );
2305 
2306     U(io).Status = 0xdeadbeef;
2307     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2308     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2309     ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2310         "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2311     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2312     ok( !fileDeleted, "file should exist\n" );
2313     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2314     ok( !fileDeleted, "file should exist\n" );
2315 
2316     CloseHandle( handle );
2317     CloseHandle( handle2 );
2318     HeapFree( GetProcessHeap(), 0, fli );
2319     delete_object( oldpath );
2320     delete_object( newpath );
2321 
2322     /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
2323     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2324     ok( res != 0, "failed to create temp file\n" );
2325     DeleteFileW( oldpath );
2326     success = CreateDirectoryW( oldpath, NULL );
2327     ok( success != 0, "failed to create temp directory\n" );
2328     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2329     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2330 
2331     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2332     ok( res != 0, "failed to create temp file\n" );
2333     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2334     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2335     fli->ReplaceIfExists = TRUE;
2336     fli->RootDirectory = NULL;
2337     fli->FileNameLength = name_str.Length;
2338     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2339     pRtlFreeUnicodeString( &name_str );
2340 
2341     U(io).Status = 0xdeadbeef;
2342     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2343     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2344     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2345     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2346     ok( !fileDeleted, "file should exist\n" );
2347     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2348     ok( !fileDeleted, "file should exist\n" );
2349 
2350     CloseHandle( handle );
2351     HeapFree( GetProcessHeap(), 0, fli );
2352     delete_object( oldpath );
2353     delete_object( newpath );
2354 
2355     /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
2356     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2357     ok( res != 0, "failed to create temp file\n" );
2358     DeleteFileW( oldpath );
2359     success = CreateDirectoryW( oldpath, NULL );
2360     ok( success != 0, "failed to create temp directory\n" );
2361     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2362     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2363 
2364     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2365     ok( res != 0, "failed to create temp file\n" );
2366     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2367     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2368 
2369     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2370     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2371     fli->ReplaceIfExists = TRUE;
2372     fli->RootDirectory = NULL;
2373     fli->FileNameLength = name_str.Length;
2374     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2375     pRtlFreeUnicodeString( &name_str );
2376 
2377     U(io).Status = 0xdeadbeef;
2378     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2379     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2380     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2381     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2382     ok( !fileDeleted, "file should exist\n" );
2383     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2384     ok( !fileDeleted, "file should exist\n" );
2385 
2386     CloseHandle( handle );
2387     CloseHandle( handle2 );
2388     HeapFree( GetProcessHeap(), 0, fli );
2389     delete_object( oldpath );
2390     delete_object( newpath );
2391 
2392     /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
2393     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2394     ok( res != 0, "failed to create temp file\n" );
2395     DeleteFileW( oldpath );
2396     success = CreateDirectoryW( oldpath, NULL );
2397     ok( success != 0, "failed to create temp directory\n" );
2398     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2399     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2400 
2401     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2402     ok( res != 0, "failed to create temp file\n" );
2403     DeleteFileW( newpath );
2404     success = CreateDirectoryW( newpath, NULL );
2405     ok( success != 0, "failed to create temp directory\n" );
2406     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2407     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2408     fli->ReplaceIfExists = FALSE;
2409     fli->RootDirectory = NULL;
2410     fli->FileNameLength = name_str.Length;
2411     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2412     pRtlFreeUnicodeString( &name_str );
2413 
2414     U(io).Status = 0xdeadbeef;
2415     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2416     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2417     ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
2418         "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2419     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2420     ok( !fileDeleted, "file should exist\n" );
2421     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2422     ok( !fileDeleted, "file should exist\n" );
2423 
2424     CloseHandle( handle );
2425     HeapFree( GetProcessHeap(), 0, fli );
2426     delete_object( oldpath );
2427     delete_object( newpath );
2428 
2429     /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
2430     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2431     ok( res != 0, "failed to create temp file\n" );
2432     DeleteFileW( oldpath );
2433     success = CreateDirectoryW( oldpath, NULL );
2434     ok( success != 0, "failed to create temp directory\n" );
2435     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2436     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2437 
2438     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2439     ok( res != 0, "failed to create temp file\n" );
2440     DeleteFileW( newpath );
2441     success = CreateDirectoryW( newpath, NULL );
2442     ok( success != 0, "failed to create temp directory\n" );
2443     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2444     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2445     fli->ReplaceIfExists = TRUE;
2446     fli->RootDirectory = NULL;
2447     fli->FileNameLength = name_str.Length;
2448     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2449     pRtlFreeUnicodeString( &name_str );
2450 
2451     U(io).Status = 0xdeadbeef;
2452     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2453     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2454     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2455     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2456     ok( !fileDeleted, "file should exist\n" );
2457     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2458     ok( !fileDeleted, "file should exist\n" );
2459 
2460     CloseHandle( handle );
2461     HeapFree( GetProcessHeap(), 0, fli );
2462     delete_object( oldpath );
2463     delete_object( newpath );
2464 
2465     /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
2466     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2467     ok( res != 0, "failed to create temp file\n" );
2468     DeleteFileW( oldpath );
2469     success = CreateDirectoryW( oldpath, NULL );
2470     ok( success != 0, "failed to create temp directory\n" );
2471     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2472     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2473 
2474     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2475     ok( res != 0, "failed to create temp file\n" );
2476     DeleteFileW( newpath );
2477     success = CreateDirectoryW( newpath, NULL );
2478     ok( success != 0, "failed to create temp directory\n" );
2479     handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2480     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2481 
2482     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2483     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2484     fli->ReplaceIfExists = TRUE;
2485     fli->RootDirectory = NULL;
2486     fli->FileNameLength = name_str.Length;
2487     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2488     pRtlFreeUnicodeString( &name_str );
2489 
2490     U(io).Status = 0xdeadbeef;
2491     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2492     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2493     ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
2494     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2495     ok( !fileDeleted, "file should exist\n" );
2496     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2497     ok( !fileDeleted, "file should exist\n" );
2498 
2499     CloseHandle( handle );
2500     CloseHandle( handle2 );
2501     HeapFree( GetProcessHeap(), 0, fli );
2502     delete_object( oldpath );
2503     delete_object( newpath );
2504 
2505     /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
2506     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2507     ok( res != 0, "failed to create temp file\n" );
2508     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2509     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2510 
2511     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2512     ok( res != 0, "failed to create temp file\n" );
2513     DeleteFileW( newpath );
2514     success = CreateDirectoryW( newpath, NULL );
2515     ok( success != 0, "failed to create temp directory\n" );
2516     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2517     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2518     fli->ReplaceIfExists = FALSE;
2519     fli->RootDirectory = NULL;
2520     fli->FileNameLength = name_str.Length;
2521     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2522     pRtlFreeUnicodeString( &name_str );
2523 
2524     U(io).Status = 0xdeadbeef;
2525     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2526     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2527     ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
2528     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2529     ok( !fileDeleted, "file should exist\n" );
2530     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2531     ok( !fileDeleted, "file should exist\n" );
2532 
2533     CloseHandle( handle );
2534     HeapFree( GetProcessHeap(), 0, fli );
2535     delete_object( oldpath );
2536     delete_object( newpath );
2537 
2538     /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
2539     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2540     ok( res != 0, "failed to create temp file\n" );
2541     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2542     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2543 
2544     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2545     ok( res != 0, "failed to create temp file\n" );
2546     DeleteFileW( newpath );
2547     success = CreateDirectoryW( newpath, NULL );
2548     ok( success != 0, "failed to create temp directory\n" );
2549     pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
2550     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
2551     fli->ReplaceIfExists = TRUE;
2552     fli->RootDirectory = NULL;
2553     fli->FileNameLength = name_str.Length;
2554     memcpy( fli->FileName, name_str.Buffer, name_str.Length );
2555     pRtlFreeUnicodeString( &name_str );
2556 
2557     U(io).Status = 0xdeadbeef;
2558     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2559     todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
2560     ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
2561     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2562     ok( !fileDeleted, "file should exist\n" );
2563     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2564     ok( !fileDeleted, "file should exist\n" );
2565 
2566     CloseHandle( handle );
2567     HeapFree( GetProcessHeap(), 0, fli );
2568     delete_object( oldpath );
2569     delete_object( newpath );
2570 
2571     /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
2572     res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
2573     ok( res != 0, "failed to create temp file\n" );
2574     handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2575     ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2576 
2577     res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
2578     ok( res != 0, "failed to create temp file\n" );
2579     DeleteFileW( newpath );
2580     for (filename = newpath, p = newpath; *p; p++)
2581         if (*p == '\\') filename = p + 1;
2582     handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2583     ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
2584 
2585     fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
2586     fli->ReplaceIfExists = FALSE;
2587     fli->RootDirectory = handle2;
2588     fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
2589     memcpy( fli->FileName, filename, fli->FileNameLength );
2590 
2591     U(io).Status = 0xdeadbeef;
2592     res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
2593     ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
2594     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2595     fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2596     ok( !fileDeleted, "file should exist\n" );
2597     fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2598     ok( !fileDeleted, "file should exist\n" );
2599 
2600     fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
2601     res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
2602     ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
2603     fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
2604     ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
2605         wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
2606     HeapFree( GetProcessHeap(), 0, fni );
2607 
2608     CloseHandle( handle );
2609     CloseHandle( handle2 );
2610     HeapFree( GetProcessHeap(), 0, fli );
2611     delete_object( oldpath );
2612     delete_object( newpath );
2613 }
2614 
2615 static void test_file_both_information(void)
2616 {
2617     IO_STATUS_BLOCK io;
2618     FILE_BOTH_DIR_INFORMATION fbi;
2619     HANDLE h;
2620     int res;
2621 
2622     if (!(h = create_temp_file(0))) return;
2623 
2624     memset(&fbi, 0, sizeof(fbi));
2625     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
2626     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
2627 
2628     CloseHandle( h );
2629 }
2630 
2631 static void test_file_disposition_information(void)
2632 {
2633     char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
2634     DWORD dirpos;
2635     HANDLE handle, handle2, mapping;
2636     NTSTATUS res;
2637     IO_STATUS_BLOCK io;
2638     FILE_DISPOSITION_INFORMATION fdi;
2639     BOOL fileDeleted;
2640     DWORD fdi2;
2641     void *ptr;
2642 
2643     GetTempPathA( MAX_PATH, tmp_path );
2644 
2645     /* tests for info struct size */
2646     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2647     handle = CreateFileA( buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2648     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2649     res = pNtSetInformationFile( handle, &io, &fdi, 0, FileDispositionInformation );
2650     todo_wine
2651     ok( res == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %x\n", res );
2652     fdi2 = 0x100;
2653     res = pNtSetInformationFile( handle, &io, &fdi2, sizeof(fdi2), FileDispositionInformation );
2654     ok( res == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x\n", res );
2655     CloseHandle( handle );
2656     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2657     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2658     DeleteFileA( buffer );
2659 
2660     /* cannot set disposition on file not opened with delete access */
2661     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2662     handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2663     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2664     res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2665     ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
2666     fdi.DoDeleteFile = TRUE;
2667     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2668     ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
2669     CloseHandle( handle );
2670     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2671     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2672     DeleteFileA( buffer );
2673 
2674     /* can set disposition on file opened with proper access */
2675     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2676     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2677     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2678     fdi.DoDeleteFile = TRUE;
2679     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2680     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2681     CloseHandle( handle );
2682     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2683     ok( fileDeleted, "File should have been deleted\n" );
2684     DeleteFileA( buffer );
2685 
2686     /* cannot set disposition on readonly file */
2687     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2688     DeleteFileA( buffer );
2689     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2690     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2691     fdi.DoDeleteFile = TRUE;
2692     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2693     ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2694     CloseHandle( handle );
2695     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2696     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2697     SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2698     DeleteFileA( buffer );
2699 
2700     /* cannot set disposition on readonly file */
2701     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2702     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
2703     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2704     fdi.DoDeleteFile = TRUE;
2705     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2706     todo_wine
2707     ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2708     CloseHandle( handle );
2709     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2710     todo_wine
2711     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2712     SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
2713     DeleteFileA( buffer );
2714 
2715     /* can set disposition on file and then reset it */
2716     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2717     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2718     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2719     fdi.DoDeleteFile = TRUE;
2720     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2721     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2722     fdi.DoDeleteFile = FALSE;
2723     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2724     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2725     CloseHandle( handle );
2726     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2727     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2728     DeleteFileA( buffer );
2729 
2730     /* Delete-on-close flag doesn't change file disposition until a handle is closed */
2731     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2732     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2733     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2734     fdi.DoDeleteFile = FALSE;
2735     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2736     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2737     CloseHandle( handle );
2738     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2739     ok( fileDeleted, "File should have been deleted\n" );
2740     DeleteFileA( buffer );
2741 
2742     /* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
2743     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2744     handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
2745     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2746     ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
2747     CloseHandle( handle );
2748     fdi.DoDeleteFile = FALSE;
2749     res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
2750     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2751     CloseHandle( handle2 );
2752     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2753     ok( fileDeleted, "File should have been deleted\n" );
2754     DeleteFileA( buffer );
2755 
2756     /* can set disposition on a directory opened with proper access */
2757     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2758     DeleteFileA( buffer );
2759     ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2760     handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2761     ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2762     fdi.DoDeleteFile = TRUE;
2763     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2764     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2765     CloseHandle( handle );
2766     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2767     ok( fileDeleted, "Directory should have been deleted\n" );
2768     RemoveDirectoryA( buffer );
2769 
2770     /* RemoveDirectory sets directory disposition and it can be undone */
2771     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2772     DeleteFileA( buffer );
2773     ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2774     handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2775     ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2776     RemoveDirectoryA( buffer );
2777     fdi.DoDeleteFile = FALSE;
2778     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2779     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2780     CloseHandle( handle );
2781     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2782     ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2783     RemoveDirectoryA( buffer );
2784 
2785     /* cannot set disposition on a non-empty directory */
2786     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2787     DeleteFileA( buffer );
2788     ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
2789     handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
2790     ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
2791     dirpos = lstrlenA( buffer );
2792     lstrcpyA( buffer + dirpos, "\\tst" );
2793     handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2794     CloseHandle( handle2 );
2795     fdi.DoDeleteFile = TRUE;
2796     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2797     todo_wine
2798     ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
2799     DeleteFileA( buffer );
2800     buffer[dirpos] = '\0';
2801     CloseHandle( handle );
2802     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2803     todo_wine
2804     ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
2805     RemoveDirectoryA( buffer );
2806 
2807     /* cannot set disposition on file with file mapping opened */
2808     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2809     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2810     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2811     mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2812     ok( mapping != NULL, "failed to create file mapping\n");
2813     fdi.DoDeleteFile = TRUE;
2814     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2815     ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2816     CloseHandle( handle );
2817     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2818     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2819     CloseHandle( mapping );
2820     DeleteFileA( buffer );
2821 
2822     /* can set disposition on file with file mapping closed */
2823     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2824     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2825     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2826     mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2827     ok( mapping != NULL, "failed to create file mapping\n");
2828     CloseHandle( mapping );
2829     fdi.DoDeleteFile = TRUE;
2830     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2831     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2832     CloseHandle( handle );
2833     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2834     ok( fileDeleted, "File should have been deleted\n" );
2835     DeleteFileA( buffer );
2836 
2837     /* cannot set disposition on file which is mapped to memory */
2838     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2839     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2840     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2841     mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2842     ok( mapping != NULL, "failed to create file mapping\n");
2843     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
2844     ok( ptr != NULL, "MapViewOfFile failed\n");
2845     CloseHandle( mapping );
2846     fdi.DoDeleteFile = TRUE;
2847     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2848     ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
2849     CloseHandle( handle );
2850     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2851     ok( !fileDeleted, "File shouldn't have been deleted\n" );
2852     UnmapViewOfFile( ptr );
2853     DeleteFileA( buffer );
2854 
2855     /* can set disposition on file which is mapped to memory and unmapped again */
2856     GetTempFileNameA( tmp_path, "dis", 0, buffer );
2857     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
2858     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
2859     mapping = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 64 * 1024, "DelFileTest" );
2860     ok( mapping != NULL, "failed to create file mapping\n");
2861     ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
2862     ok( ptr != NULL, "MapViewOfFile failed\n");
2863     CloseHandle( mapping );
2864     UnmapViewOfFile( ptr );
2865     fdi.DoDeleteFile = TRUE;
2866     res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
2867     ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
2868     CloseHandle( handle );
2869     fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
2870     ok( fileDeleted, "File should have been deleted\n" );
2871     DeleteFileA( buffer );
2872 }
2873 
2874 static void test_iocompletion(void)
2875 {
2876     HANDLE h = INVALID_HANDLE_VALUE;
2877     NTSTATUS res;
2878 
2879     res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
2880 
2881     ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
2882     ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
2883 
2884     if ( h && h != INVALID_HANDLE_VALUE)
2885     {
2886         test_iocp_setcompletion(h);
2887         test_iocp_fileio(h);
2888         pNtClose(h);
2889     }
2890 }
2891 
2892 static void test_file_name_information(void)
2893 {
2894     WCHAR *file_name, *volume_prefix, *expected;
2895     FILE_NAME_INFORMATION *info;
2896     ULONG old_redir = 1, tmp;
2897     UINT file_name_size;
2898     IO_STATUS_BLOCK io;
2899     UINT info_size;
2900     HRESULT hr;
2901     HANDLE h;
2902     UINT len;
2903 
2904     /* GetVolumePathName is not present before w2k */
2905     if (!pGetVolumePathNameW) {
2906         win_skip("GetVolumePathNameW not found\n");
2907         return;
2908     }
2909 
2910     file_name_size = GetSystemDirectoryW( NULL, 0 );
2911     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
2912     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
2913     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
2914 
2915     len = GetSystemDirectoryW( file_name, file_name_size );
2916     ok(len == file_name_size - 1,
2917             "GetSystemDirectoryW returned %u, expected %u.\n",
2918             len, file_name_size - 1);
2919 
2920     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
2921     ok(len, "GetVolumePathNameW failed.\n");
2922 
2923     len = lstrlenW( volume_prefix );
2924     if (len && volume_prefix[len - 1] == '\\') --len;
2925     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
2926     expected[file_name_size - len - 1] = '\0';
2927 
2928     /* A bit more than we actually need, but it keeps the calculation simple. */
2929     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
2930     info = HeapAlloc( GetProcessHeap(), 0, info_size );
2931 
2932     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
2933     h = CreateFileW( file_name, GENERIC_READ,
2934             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2935             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2936     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
2937     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
2938 
2939     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
2940     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
2941 
2942     memset( info, 0xcc, info_size );
2943     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
2944     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
2945             hr, STATUS_BUFFER_OVERFLOW);
2946     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
2947             U(io).Status, STATUS_BUFFER_OVERFLOW);
2948     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
2949     ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
2950     ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
2951             "info->FileName[1] is %p, expected %p.\n",
2952             CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
2953     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
2954 
2955     memset( info, 0xcc, info_size );
2956     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
2957     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
2958     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
2959     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
2960     ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
2961        info->FileName[info->FileNameLength / sizeof(WCHAR)]);
2962     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
2963     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
2964             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
2965     ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
2966             "io.Information is %lu, expected %u.\n",
2967             io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
2968 
2969     CloseHandle( h );
2970     HeapFree( GetProcessHeap(), 0, info );
2971     HeapFree( GetProcessHeap(), 0, expected );
2972     HeapFree( GetProcessHeap(), 0, volume_prefix );
2973 
2974     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
2975     {
2976         skip("Not running on WoW64, skipping test.\n");
2977         HeapFree( GetProcessHeap(), 0, file_name );
2978         return;
2979     }
2980 
2981     h = CreateFileW( file_name, GENERIC_READ,
2982             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2983             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
2984     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
2985     HeapFree( GetProcessHeap(), 0, file_name );
2986 
2987     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
2988     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
2989     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
2990 
2991     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
2992     ok(len == file_name_size - 1,
2993             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
2994             len, file_name_size - 1);
2995 
2996     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
2997     ok(len, "GetVolumePathNameW failed.\n");
2998 
2999     len = lstrlenW( volume_prefix );
3000     if (len && volume_prefix[len - 1] == '\\') --len;
3001     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3002     expected[file_name_size - len - 1] = '\0';
3003 
3004     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3005     info = HeapAlloc( GetProcessHeap(), 0, info_size );
3006 
3007     memset( info, 0xcc, info_size );
3008     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
3009     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3010     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
3011     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
3012             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
3013 
3014     CloseHandle( h );
3015     HeapFree( GetProcessHeap(), 0, info );
3016     HeapFree( GetProcessHeap(), 0, expected );
3017     HeapFree( GetProcessHeap(), 0, volume_prefix );
3018     HeapFree( GetProcessHeap(), 0, file_name );
3019 }
3020 
3021 static void test_file_all_name_information(void)
3022 {
3023     WCHAR *file_name, *volume_prefix, *expected;
3024     FILE_ALL_INFORMATION *info;
3025     ULONG old_redir = 1, tmp;
3026     UINT file_name_size;
3027     IO_STATUS_BLOCK io;
3028     UINT info_size;
3029     HRESULT hr;
3030     HANDLE h;
3031     UINT len;
3032 
3033     /* GetVolumePathName is not present before w2k */
3034     if (!pGetVolumePathNameW) {
3035         win_skip("GetVolumePathNameW not found\n");
3036         return;
3037     }
3038 
3039     file_name_size = GetSystemDirectoryW( NULL, 0 );
3040     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3041     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3042     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3043 
3044     len = GetSystemDirectoryW( file_name, file_name_size );
3045     ok(len == file_name_size - 1,
3046             "GetSystemDirectoryW returned %u, expected %u.\n",
3047             len, file_name_size - 1);
3048 
3049     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3050     ok(len, "GetVolumePathNameW failed.\n");
3051 
3052     len = lstrlenW( volume_prefix );
3053     if (len && volume_prefix[len - 1] == '\\') --len;
3054     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3055     expected[file_name_size - len - 1] = '\0';
3056 
3057     /* A bit more than we actually need, but it keeps the calculation simple. */
3058     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3059     info = HeapAlloc( GetProcessHeap(), 0, info_size );
3060 
3061     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
3062     h = CreateFileW( file_name, GENERIC_READ,
3063             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3064             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3065     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
3066     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3067 
3068     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
3069     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
3070             hr, STATUS_INFO_LENGTH_MISMATCH);
3071 
3072     memset( info, 0xcc, info_size );
3073     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
3074     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
3075             hr, STATUS_BUFFER_OVERFLOW);
3076     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
3077             U(io).Status, STATUS_BUFFER_OVERFLOW);
3078     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3079        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3080     ok(info->NameInformation.FileName[2] == 0xcccc,
3081             "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
3082     ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
3083             "info->NameInformation.FileName[1] is %p, expected %p.\n",
3084             CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
3085     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
3086 
3087     memset( info, 0xcc, info_size );
3088     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3089     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3090     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
3091     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
3092        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
3093     ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
3094        "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
3095        info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
3096     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3097     ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
3098             "info->NameInformation.FileName is %s, expected %s.\n",
3099             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3100     ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
3101             + info->NameInformation.FileNameLength,
3102             "io.Information is %lu\n", io.Information );
3103 
3104     CloseHandle( h );
3105     HeapFree( GetProcessHeap(), 0, info );
3106     HeapFree( GetProcessHeap(), 0, expected );
3107     HeapFree( GetProcessHeap(), 0, volume_prefix );
3108 
3109     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
3110     {
3111         skip("Not running on WoW64, skipping test.\n");
3112         HeapFree( GetProcessHeap(), 0, file_name );
3113         return;
3114     }
3115 
3116     h = CreateFileW( file_name, GENERIC_READ,
3117             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
3118             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
3119     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
3120     HeapFree( GetProcessHeap(), 0, file_name );
3121 
3122     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
3123     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
3124     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
3125 
3126     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
3127     ok(len == file_name_size - 1,
3128             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
3129             len, file_name_size - 1);
3130 
3131     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
3132     ok(len, "GetVolumePathNameW failed.\n");
3133 
3134     len = lstrlenW( volume_prefix );
3135     if (len && volume_prefix[len - 1] == '\\') --len;
3136     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
3137     expected[file_name_size - len - 1] = '\0';
3138 
3139     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
3140     info = HeapAlloc( GetProcessHeap(), 0, info_size );
3141 
3142     memset( info, 0xcc, info_size );
3143     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
3144     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
3145     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
3146     ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
3147             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
3148 
3149     CloseHandle( h );
3150     HeapFree( GetProcessHeap(), 0, info );
3151     HeapFree( GetProcessHeap(), 0, expected );
3152     HeapFree( GetProcessHeap(), 0, volume_prefix );
3153     HeapFree( GetProcessHeap(), 0, file_name );
3154 }
3155 
3156 static void test_file_completion_information(void)
3157 {
3158     static const char buf[] = "testdata";
3159     FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
3160     OVERLAPPED ov, *pov;
3161     IO_STATUS_BLOCK io;
3162     NTSTATUS status;
3163     DWORD num_bytes;
3164     HANDLE port, h;
3165     ULONG_PTR key;
3166     BOOL ret;
3167     int i;
3168 
3169     if (!(h = create_temp_file(0))) return;
3170 
3171     status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
3172     ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
3173        "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
3174     if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
3175     {
3176         win_skip("FileIoCompletionNotificationInformation class not supported\n");
3177         CloseHandle(h);
3178         return;
3179     }
3180 
3181     info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3182     status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3183     ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08x\n", status);
3184 
3185     CloseHandle(h);
3186     if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3187 
3188     info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
3189     status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3190     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3191 
3192     info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
3193     status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3194     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3195 
3196     CloseHandle(h);
3197     if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
3198 
3199     info.Flags = ~0U;
3200     status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3201     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3202     ok(!(info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS), "got %08x\n", info.Flags);
3203 
3204     memset(&ov, 0, sizeof(ov));
3205     ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
3206     port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
3207     ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
3208 
3209     for (i = 0; i < 10; i++)
3210     {
3211         SetLastError(0xdeadbeef);
3212         ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3213         if (ret || GetLastError() != ERROR_IO_PENDING) break;
3214         ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3215         ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3216         ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3217         ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3218         ret = FALSE;
3219     }
3220     if (ret)
3221     {
3222         ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3223 
3224         key = 0;
3225         pov = NULL;
3226         ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3227         ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3228         ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
3229         ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
3230     }
3231     else
3232         win_skip("WriteFile never returned TRUE\n");
3233 
3234     info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
3235     status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3236     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3237 
3238     info.Flags = 0;
3239     status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3240     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3241     ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
3242 
3243     for (i = 0; i < 10; i++)
3244     {
3245         SetLastError(0xdeadbeef);
3246         ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3247         if (ret || GetLastError() != ERROR_IO_PENDING) break;
3248         ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3249         ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3250         ret = FALSE;
3251     }
3252     if (ret)
3253     {
3254         ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3255 
3256         pov = (void *)0xdeadbeef;
3257         ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
3258         ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3259         ok(pov == NULL, "expected NULL, got %p\n", pov);
3260     }
3261     else
3262         win_skip("WriteFile never returned TRUE\n");
3263 
3264     info.Flags = 0;
3265     status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3266     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3267 
3268     info.Flags = 0;
3269     status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
3270     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
3271     ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
3272 
3273     for (i = 0; i < 10; i++)
3274     {
3275         SetLastError(0xdeadbeef);
3276         ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
3277         if (ret || GetLastError() != ERROR_IO_PENDING) break;
3278         ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
3279         ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
3280         ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3281         ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
3282         ret = FALSE;
3283     }
3284     if (ret)
3285     {
3286         ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
3287 
3288         pov = (void *)0xdeadbeef;
3289         ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
3290         ok(!ret, "GetQueuedCompletionStatus succeeded\n");
3291         ok(pov == NULL, "expected NULL, got %p\n", pov);
3292     }
3293     else
3294         win_skip("WriteFile never returned TRUE\n");
3295 
3296     CloseHandle(ov.hEvent);
3297     CloseHandle(port);
3298     CloseHandle(h);
3299 }
3300 
3301 static void test_file_id_information(void)
3302 {
3303     BY_HANDLE_FILE_INFORMATION info;
3304     FILE_ID_INFORMATION fid;
3305     IO_STATUS_BLOCK io;
3306     NTSTATUS status;
3307     DWORD *dwords;
3308     HANDLE h;
3309     BOOL ret;
3310 
3311     if (!(h = create_temp_file(0))) return;
3312 
3313     memset( &fid, 0x11, sizeof(fid) );
3314     status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
3315     if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
3316     {
3317         win_skip( "FileIdInformation not supported\n" );
3318         CloseHandle( h );
3319         return;
3320     }
3321 
3322     memset( &info, 0x22, sizeof(info) );
3323     ret = GetFileInformationByHandle( h, &info );
3324     ok( ret, "GetFileInformationByHandle failed\n" );
3325 
3326     dwords = (DWORD *)&fid.VolumeSerialNumber;
3327     ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08x, got %08x\n",
3328         info.dwVolumeSerialNumber, dwords[0] );
3329     ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
3330 
3331     dwords = (DWORD *)&fid.FileId;
3332     ok( dwords[0] == info.nFileIndexLow, "expected %08x, got %08x\n", info.nFileIndexLow, dwords[0] );
3333     ok( dwords[1] == info.nFileIndexHigh, "expected %08x, got %08x\n", info.nFileIndexHigh, dwords[1] );
3334     ok( dwords[2] == 0, "expected 0, got %08x\n", dwords[2] );
3335     ok( dwords[3] == 0, "expected 0, got %08x\n", dwords[3] );
3336 
3337     CloseHandle( h );
3338 }
3339 
3340 static void test_file_access_information(void)
3341 {
3342     FILE_ACCESS_INFORMATION info;
3343     IO_STATUS_BLOCK io;
3344     NTSTATUS status;
3345     HANDLE h;
3346 
3347     if (!(h = create_temp_file(0))) return;
3348 
3349     status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
3350     ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
3351 
3352     status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
3353     ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status );
3354 
3355     memset(&info, 0x11, sizeof(info));
3356     status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
3357     ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status );
3358     ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags );
3359 
3360     CloseHandle( h );
3361 }
3362 
3363 static void test_query_volume_information_file(void)
3364 {
3365     NTSTATUS status;
3366     HANDLE dir;
3367     WCHAR path[MAX_PATH];
3368     OBJECT_ATTRIBUTES attr;
3369     IO_STATUS_BLOCK io;
3370     UNICODE_STRING nameW;
3371     FILE_FS_VOLUME_INFORMATION *ffvi;
3372     BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3373 
3374     GetWindowsDirectoryW( path, MAX_PATH );
3375     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3376     attr.Length = sizeof(attr);
3377     attr.RootDirectory = 0;
3378     attr.ObjectName = &nameW;
3379     attr.Attributes = OBJ_CASE_INSENSITIVE;
3380     attr.SecurityDescriptor = NULL;
3381     attr.SecurityQualityOfService = NULL;
3382 
3383     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3384                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3385     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3386     pRtlFreeUnicodeString( &nameW );
3387 
3388     ZeroMemory( buf, sizeof(buf) );
3389     U(io).Status = 0xdadadada;
3390     io.Information = 0xcacacaca;
3391 
3392     status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
3393 
3394     ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
3395 
3396     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3397     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3398 
3399 todo_wine
3400 {
3401     ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3402     "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
3403      io.Information);
3404 
3405     ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
3406     ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
3407     ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
3408 }
3409     ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
3410 
3411     trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
3412 
3413     CloseHandle( dir );
3414 }
3415 
3416 static void test_query_attribute_information_file(void)
3417 {
3418     NTSTATUS status;
3419     HANDLE dir;
3420     WCHAR path[MAX_PATH];
3421     OBJECT_ATTRIBUTES attr;
3422     IO_STATUS_BLOCK io;
3423     UNICODE_STRING nameW;
3424     FILE_FS_ATTRIBUTE_INFORMATION *ffai;
3425     BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
3426 
3427     GetWindowsDirectoryW( path, MAX_PATH );
3428     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
3429     attr.Length = sizeof(attr);
3430     attr.RootDirectory = 0;
3431     attr.ObjectName = &nameW;
3432     attr.Attributes = OBJ_CASE_INSENSITIVE;
3433     attr.SecurityDescriptor = NULL;
3434     attr.SecurityQualityOfService = NULL;
3435 
3436     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
3437                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
3438     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
3439     pRtlFreeUnicodeString( &nameW );
3440 
3441     ZeroMemory( buf, sizeof(buf) );
3442     U(io).Status = 0xdadadada;
3443     io.Information = 0xcacacaca;
3444 
3445     status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
3446 
3447     ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
3448 
3449     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
3450     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
3451     ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
3452     ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
3453     ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
3454 
3455     trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
3456           ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
3457           wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
3458 
3459     CloseHandle( dir );
3460 }
3461 
3462 static void test_NtCreateFile(void)
3463 {
3464     static const struct test_data
3465     {
3466         DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
3467     } td[] =
3468     {
3469     /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3470     /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
3471     /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3472     /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3473     /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3474     /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3475     /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
3476     /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3477     /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3478     /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3479     /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
3480     /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3481     /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3482     /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
3483     /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3484     /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
3485     /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
3486     /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
3487     /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
3488     };
3489     static const WCHAR fooW[] = {'f','o','o',0};
3490     NTSTATUS status;
3491     HANDLE handle;
3492     WCHAR path[MAX_PATH];
3493     OBJECT_ATTRIBUTES attr;
3494     IO_STATUS_BLOCK io;
3495     UNICODE_STRING nameW;
3496     DWORD ret, i;
3497 
3498     GetTempPathW(MAX_PATH, path);
3499     GetTempFileNameW(path, fooW, 0, path);
3500     DeleteFileW(path);
3501     pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3502 
3503     attr.Length = sizeof(attr);
3504     attr.RootDirectory = NULL;
3505     attr.ObjectName = &nameW;
3506     attr.Attributes = OBJ_CASE_INSENSITIVE;
3507     attr.SecurityDescriptor = NULL;
3508     attr.SecurityQualityOfService = NULL;
3509 
3510     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3511     {
3512         status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
3513                                td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
3514                                td[i].disposition, 0, NULL, 0);
3515 
3516         ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
3517 
3518         if (!status)
3519         {
3520             ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
3521 
3522             ret = GetFileAttributesW(path);
3523             ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
3524             /* FIXME: leave only 'else' case below once Wine is fixed */
3525             if (ret != td[i].attrib_out)
3526             {
3527             todo_wine
3528                 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3529                 SetFileAttributesW(path, td[i].attrib_out);
3530             }
3531             else
3532                 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
3533 
3534             CloseHandle(handle);
3535         }
3536 
3537         if (td[i].needs_cleanup)
3538         {
3539             SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3540             DeleteFileW(path);
3541         }
3542     }
3543 
3544     pRtlFreeUnicodeString( &nameW );
3545     SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3546     DeleteFileW( path );
3547 }
3548 
3549 static void test_readonly(void)
3550 {
3551     static const WCHAR fooW[] = {'f','o','o',0};
3552     NTSTATUS status;
3553     HANDLE handle;
3554     WCHAR path[MAX_PATH];
3555     OBJECT_ATTRIBUTES attr;
3556     IO_STATUS_BLOCK io;
3557     UNICODE_STRING nameW;
3558 
3559     GetTempPathW(MAX_PATH, path);
3560     GetTempFileNameW(path, fooW, 0, path);
3561     DeleteFileW(path);
3562     pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
3563 
3564     attr.Length = sizeof(attr);
3565     attr.RootDirectory = NULL;
3566     attr.ObjectName = &nameW;
3567     attr.Attributes = OBJ_CASE_INSENSITIVE;
3568     attr.SecurityDescriptor = NULL;
3569     attr.SecurityQualityOfService = NULL;
3570 
3571     status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL, FILE_ATTRIBUTE_READONLY,
3572                            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_CREATE, 0, NULL, 0);
3573     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3574     CloseHandle(handle);
3575 
3576     status = pNtOpenFile(&handle, GENERIC_WRITE,  &attr, &io,
3577                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3578     ok(status == STATUS_ACCESS_DENIED, "got %#x\n", status);
3579     CloseHandle(handle);
3580 
3581     status = pNtOpenFile(&handle, GENERIC_READ,  &attr, &io,
3582                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3583     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3584     CloseHandle(handle);
3585 
3586     status = pNtOpenFile(&handle, FILE_READ_ATTRIBUTES,  &attr, &io,
3587                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3588     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3589     CloseHandle(handle);
3590 
3591     status = pNtOpenFile(&handle, FILE_WRITE_ATTRIBUTES,  &attr, &io,
3592                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3593     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3594     CloseHandle(handle);
3595 
3596     status = pNtOpenFile(&handle, DELETE,  &attr, &io,
3597                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3598     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3599     CloseHandle(handle);
3600 
3601     status = pNtOpenFile(&handle, READ_CONTROL,  &attr, &io,
3602                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3603     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3604     CloseHandle(handle);
3605 
3606     status = pNtOpenFile(&handle, WRITE_DAC,  &attr, &io,
3607                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3608     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3609     CloseHandle(handle);
3610 
3611     status = pNtOpenFile(&handle, WRITE_OWNER,  &attr, &io,
3612                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3613     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3614     CloseHandle(handle);
3615 
3616     status = pNtOpenFile(&handle, SYNCHRONIZE,  &attr, &io,
3617                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_FOR_BACKUP_INTENT);
3618     ok(status == STATUS_SUCCESS, "got %#x\n", status);
3619     CloseHandle( handle );
3620 
3621     pRtlFreeUnicodeString(&nameW);
3622     SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
3623     DeleteFileW(path);
3624 }
3625 
3626 static void test_read_write(void)
3627 {
3628     static const char contents[14] = "1234567890abcd";
3629     char buf[256];
3630     HANDLE hfile, event;
3631     OVERLAPPED ovl;
3632     IO_STATUS_BLOCK iob;
3633     DWORD ret, bytes, status, off;
3634     LARGE_INTEGER offset;
3635     LONG i;
3636 
3637     event = CreateEventA( NULL, TRUE, FALSE, NULL );
3638 
3639     U(iob).Status = -1;
3640     iob.Information = -1;
3641     offset.QuadPart = 0;
3642     status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3643     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3644     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3645     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3646 
3647     U(iob).Status = -1;
3648     iob.Information = -1;
3649     offset.QuadPart = 0;
3650     status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
3651     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3652     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3653     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3654 
3655     U(iob).Status = -1;
3656     iob.Information = -1;
3657     offset.QuadPart = 0;
3658     status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3659     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3660     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3661     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3662 
3663     U(iob).Status = -1;
3664     iob.Information = -1;
3665     offset.QuadPart = 0;
3666     status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3667     ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
3668     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3669     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3670 
3671     hfile = create_temp_file(0);
3672     if (!hfile) return;
3673 
3674     U(iob).Status = -1;
3675     iob.Information = -1;
3676     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3677     ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3678     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3679     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3680 
3681     U(iob).Status = -1;
3682     iob.Information = -1;
3683     SetEvent(event);
3684     status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3685     ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
3686     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3687     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3688     ok(!is_signaled(event), "event is not signaled\n");
3689 
3690     U(iob).Status = -1;
3691     iob.Information = -1;
3692     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3693     ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3694     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3695     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3696 
3697     U(iob).Status = -1;
3698     iob.Information = -1;
3699     SetEvent(event);
3700     status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
3701     ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3702     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3703     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3704     ok(is_signaled(event), "event is not signaled\n");
3705 
3706     U(iob).Status = -1;
3707     iob.Information = -1;
3708     SetEvent(event);
3709     status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
3710     ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
3711     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3712     ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
3713     ok(is_signaled(event), "event is not signaled\n");
3714 
3715     U(iob).Status = -1;
3716     iob.Information = -1;
3717     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
3718     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3719     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3720     ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
3721 
3722     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3723 
3724     U(iob).Status = -1;
3725     iob.Information = -1;
3726     offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
3727     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
3728     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3729     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3730     ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
3731 
3732     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3733     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3734 
3735     bytes = 0xdeadbeef;
3736     SetLastError(0xdeadbeef);
3737     ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
3738     ok(!ret, "ReadFile should fail\n");
3739     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3740     ok(bytes == 0, "bytes %u\n", bytes);
3741 
3742     bytes = 0xdeadbeef;
3743     SetLastError(0xdeadbeef);
3744     ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3745     ok(ret, "ReadFile error %d\n", GetLastError());
3746     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3747     ok(bytes == 0, "bytes %u\n", bytes);
3748 
3749     bytes = 0xdeadbeef;
3750     SetLastError(0xdeadbeef);
3751     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3752     ok(ret, "ReadFile error %d\n", GetLastError());
3753     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3754     ok(bytes == 0, "bytes %u\n", bytes);
3755 
3756     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3757 
3758     bytes = 0;
3759     SetLastError(0xdeadbeef);
3760     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3761     ok(ret, "ReadFile error %d\n", GetLastError());
3762     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3763     ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3764 
3765     for (i = -20; i < -1; i++)
3766     {
3767         if (i == -2) continue;
3768 
3769         U(iob).Status = -1;
3770         iob.Information = -1;
3771         offset.QuadPart = (LONGLONG)i;
3772         status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
3773         ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3774         ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3775         ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3776     }
3777 
3778     SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
3779 
3780     U(iob).Status = -1;
3781     iob.Information = -1;
3782     offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3783     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3784     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3785     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3786     ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3787 
3788     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3789     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3790 
3791     U(iob).Status = -1;
3792     iob.Information = -1;
3793     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3794     ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3795     ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3796     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3797 
3798     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3799 
3800     bytes = 0;
3801     SetLastError(0xdeadbeef);
3802     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3803     ok(ret, "ReadFile error %d\n", GetLastError());
3804     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3805     ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3806     ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3807 
3808     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3809     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3810 
3811     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3812 
3813     bytes = 0;
3814     SetLastError(0xdeadbeef);
3815     ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
3816     ok(ret, "WriteFile error %d\n", GetLastError());
3817     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3818 
3819     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3820     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3821 
3822     /* test reading beyond EOF */
3823     bytes = -1;
3824     SetLastError(0xdeadbeef);
3825     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3826     ok(ret, "ReadFile error %d\n", GetLastError());
3827     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3828     ok(bytes == 0, "bytes %u\n", bytes);
3829 
3830     bytes = -1;
3831     SetLastError(0xdeadbeef);
3832     ret = ReadFile(hfile, buf, 0, &bytes, NULL);
3833     ok(ret, "ReadFile error %d\n", GetLastError());
3834     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3835     ok(bytes == 0, "bytes %u\n", bytes);
3836 
3837     bytes = -1;
3838     SetLastError(0xdeadbeef);
3839     ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
3840     ok(ret, "ReadFile error %d\n", GetLastError());
3841     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3842     ok(bytes == 0, "bytes %u\n", bytes);
3843 
3844     S(U(ovl)).Offset = sizeof(contents);
3845     S(U(ovl)).OffsetHigh = 0;
3846     ovl.Internal = -1;
3847     ovl.InternalHigh = -1;
3848     ovl.hEvent = 0;
3849     bytes = -1;
3850     SetLastError(0xdeadbeef);
3851     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3852     ok(!ret, "ReadFile should fail\n");
3853     ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
3854     ok(bytes == 0, "bytes %u\n", bytes);
3855     ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
3856     ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3857 
3858     S(U(ovl)).Offset = sizeof(contents);
3859     S(U(ovl)).OffsetHigh = 0;
3860     ovl.Internal = -1;
3861     ovl.InternalHigh = -1;
3862     ovl.hEvent = 0;
3863     bytes = -1;
3864     SetLastError(0xdeadbeef);
3865     ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
3866     ok(ret, "ReadFile error %d\n", GetLastError());
3867     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
3868     ok(bytes == 0, "bytes %u\n", bytes);
3869     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
3870     ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
3871 
3872     U(iob).Status = -1;
3873     iob.Information = -1;
3874     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
3875     ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3876     ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3877     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3878 
3879     U(iob).Status = -1;
3880     iob.Information = -1;
3881     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
3882     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3883     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3884     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3885 
3886     U(iob).Status = -1;
3887     iob.Information = -1;
3888     offset.QuadPart = sizeof(contents);
3889     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3890     ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3891     ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3892     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3893 
3894     U(iob).Status = -1;
3895     iob.Information = -1;
3896     offset.QuadPart = sizeof(contents);
3897     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3898     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3899     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3900     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3901 
3902     U(iob).Status = -1;
3903     iob.Information = -1;
3904     offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3905     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3906     ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
3907     ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
3908     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3909 
3910     U(iob).Status = -1;
3911     iob.Information = -1;
3912     offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
3913     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
3914     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3915     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3916     ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
3917 
3918     for (i = -20; i < 0; i++)
3919     {
3920         if (i == -2) continue;
3921 
3922         U(iob).Status = -1;
3923         iob.Information = -1;
3924         offset.QuadPart = (LONGLONG)i;
3925         status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3926         ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
3927         ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
3928         ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
3929     }
3930 
3931     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
3932 
3933     bytes = 0;
3934     SetLastError(0xdeadbeef);
3935     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
3936     ok(ret, "ReadFile error %d\n", GetLastError());
3937     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
3938     ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3939 
3940     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3941     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3942 
3943     U(iob).Status = -1;
3944     iob.Information = -1;
3945     offset.QuadPart = 0;
3946     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3947     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3948     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3949     ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3950     ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
3951 
3952     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3953     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3954 
3955     U(iob).Status = -1;
3956     iob.Information = -1;
3957     offset.QuadPart = sizeof(contents) - 4;
3958     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
3959     ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
3960     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3961     ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
3962 
3963     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3964     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3965 
3966     U(iob).Status = -1;
3967     iob.Information = -1;
3968     offset.QuadPart = 0;
3969     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
3970     ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
3971     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
3972     ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
3973     ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
3974     ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
3975 
3976     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3977     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3978 
3979     S(U(ovl)).Offset = sizeof(contents) - 4;
3980     S(U(ovl)).OffsetHigh = 0;
3981     ovl.hEvent = 0;
3982     bytes = 0;
3983     SetLastError(0xdeadbeef);
3984     ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
3985     ok(ret, "WriteFile error %d\n", GetLastError());
3986     ok(bytes == 4, "bytes %u\n", bytes);
3987 
3988     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
3989     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
3990 
3991     S(U(ovl)).Offset = 0;
3992     S(U(ovl)).OffsetHigh = 0;
3993     ovl.Internal = -1;
3994     ovl.InternalHigh = -1;
3995     ovl.hEvent = 0;
3996     bytes = 0;
3997     SetLastError(0xdeadbeef);
3998     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
3999     ok(ret, "ReadFile error %d\n", GetLastError());
4000     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4001     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4002     ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4003     ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4004     ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4005 
4006     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4007     ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
4008 
4009     CloseHandle(hfile);
4010 
4011     hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
4012     if (!hfile) return;
4013 
4014     bytes = 0xdeadbeef;
4015     SetLastError(0xdeadbeef);
4016     ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
4017     ok(!ret, "ReadFile should fail\n");
4018     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
4019     ok(bytes == 0, "bytes %u\n", bytes);
4020 
4021     S(U(ovl)).Offset = 0;
4022     S(U(ovl)).OffsetHigh = 0;
4023     ovl.Internal = -1;
4024     ovl.InternalHigh = -1;
4025     ovl.hEvent = 0;
4026     bytes = 0xdeadbeef;
4027     SetLastError(0xdeadbeef);
4028     /* ReadFile return value depends on Windows version and testing it is not practical */
4029     ReadFile(hfile, buf, 0, &bytes, &ovl);
4030     ok(bytes == 0, "bytes %u\n", bytes);
4031     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4032     ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4033 
4034     bytes = 0xdeadbeef;
4035     SetLastError(0xdeadbeef);
4036     ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
4037     ok(!ret, "WriteFile should fail\n");
4038     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4039     ok(bytes == 0, "bytes %u\n", bytes);
4040 
4041     U(iob).Status = -1;
4042     iob.Information = -1;
4043     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
4044     ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4045     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4046     ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4047 
4048     for (i = -20; i < -1; i++)
4049     {
4050         U(iob).Status = -1;
4051         iob.Information = -1;
4052         offset.QuadPart = (LONGLONG)i;
4053         status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4054         ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4055         ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4056         ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4057     }
4058 
4059     U(iob).Status = -1;
4060     iob.Information = -1;
4061     offset.QuadPart = 0;
4062     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
4063     ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4064     if (status == STATUS_PENDING)
4065     {
4066         ret = WaitForSingleObject(hfile, 3000);
4067         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4068     }
4069     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4070     ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4071 
4072     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4073     ok(off == 0, "expected 0, got %u\n", off);
4074 
4075     bytes = 0xdeadbeef;
4076     SetLastError(0xdeadbeef);
4077     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
4078     ok(!ret, "ReadFile should fail\n");
4079     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4080     ok(bytes == 0, "bytes %u\n", bytes);
4081 
4082     U(iob).Status = -1;
4083     iob.Information = -1;
4084     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
4085     ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
4086     ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4087     ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4088 
4089     for (i = -20; i < 0; i++)
4090     {
4091         U(iob).Status = -1;
4092         iob.Information = -1;
4093         offset.QuadPart = (LONGLONG)i;
4094         status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4095         ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
4096         ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4097         ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
4098     }
4099 
4100     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4101     ok(off == 0, "expected 0, got %u\n", off);
4102 
4103     /* test reading beyond EOF */
4104     offset.QuadPart = sizeof(contents);
4105     S(U(ovl)).Offset = offset.u.LowPart;
4106     S(U(ovl)).OffsetHigh = offset.u.HighPart;
4107     ovl.Internal = -1;
4108     ovl.InternalHigh = -1;
4109     ovl.hEvent = 0;
4110     bytes = 0xdeadbeef;
4111     SetLastError(0xdeadbeef);
4112     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4113     ok(!ret, "ReadFile should fail\n");
4114     ret = GetLastError();
4115     ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
4116     ok(bytes == 0, "bytes %u\n", bytes);
4117 
4118     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4119     ok(off == 0, "expected 0, got %u\n", off);
4120 
4121     if (ret == ERROR_IO_PENDING)
4122     {
4123         bytes = 0xdeadbeef;
4124         SetLastError(0xdeadbeef);
4125         ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4126         ok(!ret, "GetOverlappedResult should report FALSE\n");
4127         ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
4128         ok(bytes == 0, "expected 0, read %u\n", bytes);
4129         ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
4130         ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4131     }
4132 
4133     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4134     ok(off == 0, "expected 0, got %u\n", off);
4135 
4136     offset.QuadPart = sizeof(contents);
4137     S(U(ovl)).Offset = offset.u.LowPart;
4138     S(U(ovl)).OffsetHigh = offset.u.HighPart;
4139     ovl.Internal = -1;
4140     ovl.InternalHigh = -1;
4141     ovl.hEvent = 0;
4142     bytes = 0xdeadbeef;
4143     SetLastError(0xdeadbeef);
4144     ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
4145     /* ReadFile return value depends on Windows version and testing it is not practical */
4146     if (!ret)
4147         ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4148     ret = GetLastError();
4149     ok(bytes == 0, "bytes %u\n", bytes);
4150 
4151     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4152     ok(off == 0, "expected 0, got %u\n", off);
4153 
4154     if (ret == ERROR_IO_PENDING)
4155     {
4156         bytes = 0xdeadbeef;
4157         SetLastError(0xdeadbeef);
4158         ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4159         ok(ret, "GetOverlappedResult should report TRUE\n");
4160         ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4161         ok(bytes == 0, "expected 0, read %u\n", bytes);
4162         ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4163         ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4164     }
4165 
4166     offset.QuadPart = sizeof(contents);
4167     S(U(ovl)).Offset = offset.u.LowPart;
4168     S(U(ovl)).OffsetHigh = offset.u.HighPart;
4169     ovl.Internal = -1;
4170     ovl.InternalHigh = -1;
4171     ovl.hEvent = 0;
4172     bytes = 0xdeadbeef;
4173     SetLastError(0xdeadbeef);
4174     ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
4175     /* ReadFile return value depends on Windows version and testing it is not practical */
4176     if (!ret)
4177         ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4178     ret = GetLastError();
4179     ok(bytes == 0, "bytes %u\n", bytes);
4180 
4181     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4182     ok(off == 0, "expected 0, got %u\n", off);
4183 
4184     if (ret == ERROR_IO_PENDING)
4185     {
4186         bytes = 0xdeadbeef;
4187         SetLastError(0xdeadbeef);
4188         ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4189         ok(ret, "GetOverlappedResult should report TRUE\n");
4190         ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
4191         ok(bytes == 0, "expected 0, read %u\n", bytes);
4192         ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4193         ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
4194     }
4195 
4196     U(iob).Status = -1;
4197     iob.Information = -1;
4198     offset.QuadPart = sizeof(contents);
4199     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4200     if (status == STATUS_PENDING)
4201     {
4202         ret = WaitForSingleObject(hfile, 3000);
4203         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4204         ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
4205         ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4206     }
4207     else
4208     {
4209         ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
4210         ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
4211         ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
4212     }
4213 
4214     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4215     ok(off == 0, "expected 0, got %u\n", off);
4216 
4217     U(iob).Status = -1;
4218     iob.Information = -1;
4219     offset.QuadPart = sizeof(contents);
4220     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
4221     if (status == STATUS_PENDING)
4222     {
4223         ret = WaitForSingleObject(hfile, 3000);
4224         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4225         ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4226         ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4227     }
4228     else
4229     {
4230         ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
4231         ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4232         ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
4233     }
4234 
4235     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4236     ok(off == 0, "expected 0, got %u\n", off);
4237 
4238     S(U(ovl)).Offset = 0;
4239     S(U(ovl)).OffsetHigh = 0;
4240     ovl.Internal = -1;
4241     ovl.InternalHigh = -1;
4242     ovl.hEvent = 0;
4243     bytes = 0;
4244     SetLastError(0xdeadbeef);
4245     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4246     /* ReadFile return value depends on Windows version and testing it is not practical */
4247     if (!ret)
4248     {
4249         ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4250         ok(bytes == 0, "bytes %u\n", bytes);
4251     }
4252     else ok(bytes == 14, "bytes %u\n", bytes);
4253     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4254     ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4255 
4256     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4257     ok(off == 0, "expected 0, got %u\n", off);
4258 
4259     bytes = 0xdeadbeef;
4260     ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4261     ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4262     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4263     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4264     ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4265     ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
4266 
4267     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4268     ok(off == 0, "expected 0, got %u\n", off);
4269 
4270     SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
4271     SetEndOfFile(hfile);
4272     SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
4273 
4274     U(iob).Status = -1;
4275     iob.Information = -1;
4276     offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
4277     status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
4278     ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4279     if (status == STATUS_PENDING)
4280     {
4281         ret = WaitForSingleObject(hfile, 3000);
4282         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4283     }
4284     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4285     ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
4286 
4287     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4288     ok(off == 0, "expected 0, got %u\n", off);
4289 
4290     U(iob).Status = -1;
4291     iob.Information = -1;
4292     offset.QuadPart = 0;
4293     status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
4294     ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
4295     if (status == STATUS_PENDING)
4296     {
4297         ret = WaitForSingleObject(hfile, 3000);
4298         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4299     }
4300     ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
4301     ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
4302 
4303     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4304     ok(off == 0, "expected 0, got %u\n", off);
4305 
4306     ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4307     ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
4308 
4309     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4310     ok(off == 0, "expected 0, got %u\n", off);
4311 
4312     S(U(ovl)).Offset = sizeof(contents) - 4;
4313     S(U(ovl)).OffsetHigh = 0;
4314     ovl.Internal = -1;
4315     ovl.InternalHigh = -1;
4316     ovl.hEvent = 0;
4317     bytes = 0;
4318     SetLastError(0xdeadbeef);
4319     ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
4320     /* WriteFile return value depends on Windows version and testing it is not practical */
4321     if (!ret)
4322     {
4323         ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4324         ok(bytes == 0, "bytes %u\n", bytes);
4325         ret = WaitForSingleObject(hfile, 3000);
4326         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4327     }
4328     else ok(bytes == 4, "bytes %u\n", bytes);
4329     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4330     ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4331 
4332     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4333     ok(off == 0, "expected 0, got %u\n", off);
4334 
4335     bytes = 0xdeadbeef;
4336     ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4337     ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4338     ok(bytes == 4, "bytes %u\n", bytes);
4339     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4340     ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
4341 
4342     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4343     ok(off == 0, "expected 0, got %u\n", off);
4344 
4345     S(U(ovl)).Offset = 0;
4346     S(U(ovl)).OffsetHigh = 0;
4347     ovl.Internal = -1;
4348     ovl.InternalHigh = -1;
4349     ovl.hEvent = 0;
4350     bytes = 0;
4351     SetLastError(0xdeadbeef);
4352     ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
4353     /* ReadFile return value depends on Windows version and testing it is not practical */
4354     if (!ret)
4355     {
4356         ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
4357         ok(bytes == 0, "bytes %u\n", bytes);
4358         ret = WaitForSingleObject(hfile, 3000);
4359         ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
4360     }
4361     else ok(bytes == 14, "bytes %u\n", bytes);
4362     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4363     ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4364 
4365     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4366     ok(off == 0, "expected 0, got %u\n", off);
4367 
4368     bytes = 0xdeadbeef;
4369     ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
4370     ok(ret, "GetOverlappedResult error %d\n", GetLastError());
4371     ok(bytes == sizeof(contents), "bytes %u\n", bytes);
4372     ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
4373     ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
4374     ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
4375     ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
4376 
4377     off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
4378     ok(off == 0, "expected 0, got %u\n", off);
4379 
4380     CloseHandle(event);
4381     CloseHandle(hfile);
4382 }
4383 
4384 static void test_ioctl(void)
4385 {
4386     HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
4387     FILE_PIPE_PEEK_BUFFER peek_buf;
4388     IO_STATUS_BLOCK iosb;
4389     HANDLE file;
4390     NTSTATUS status;
4391 
4392     file = create_temp_file(FILE_FLAG_OVERLAPPED);
4393     ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
4394 
4395     SetEvent(event);
4396     status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4397     todo_wine
4398     ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %x\n", status);
4399     ok(!is_signaled(event), "event is signaled\n");
4400 
4401     status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
4402     ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %x\n", status);
4403 
4404     memset(&iosb, 0x55, sizeof(iosb));
4405     status = NtFsControlFile(file, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0,
4406                              &peek_buf, sizeof(peek_buf));
4407     todo_wine
4408     ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile failed: %x\n", status);
4409     ok(iosb.Status == 0x55555555, "iosb.Status = %x\n", iosb.Status);
4410 
4411     CloseHandle(event);
4412     CloseHandle(file);
4413 }
4414 
4415 static void test_flush_buffers_file(void)
4416 {
4417     char path[MAX_PATH], buffer[MAX_PATH];
4418     HANDLE hfile, hfileread;
4419     NTSTATUS status;
4420     IO_STATUS_BLOCK io_status_block;
4421 
4422     GetTempPathA(MAX_PATH, path);
4423     GetTempFileNameA(path, "foo", 0, buffer);
4424     hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
4425             FILE_ATTRIBUTE_NORMAL, 0);
4426     ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
4427 
4428     hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4429             OPEN_EXISTING, 0, NULL);
4430     ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4431 
4432     status = pNtFlushBuffersFile(hfile, NULL);
4433     todo_wine
4434     ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4435 
4436     status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
4437     todo_wine
4438     ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
4439 
4440     status = pNtFlushBuffersFile(hfile, &io_status_block);
4441     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4442 
4443     status = pNtFlushBuffersFile(hfileread, &io_status_block);
4444     ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#x.\n", status);
4445 
4446     status = pNtFlushBuffersFile(NULL, &io_status_block);
4447     ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status);
4448 
4449     CloseHandle(hfileread);
4450     CloseHandle(hfile);
4451     hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
4452             OPEN_EXISTING, 0, NULL);
4453     ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
4454 
4455     status = pNtFlushBuffersFile(hfile, &io_status_block);
4456     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
4457 
4458     CloseHandle(hfile);
4459     DeleteFileA(buffer);
4460 }
4461 
4462 static void test_query_ea(void)
4463 {
4464     #define EA_BUFFER_SIZE 4097
4465     unsigned char data[EA_BUFFER_SIZE + 8];
4466     unsigned char *buffer = (void *)(((DWORD_PTR)data + 7) & ~7);
4467     DWORD buffer_len, i;
4468     IO_STATUS_BLOCK io;
4469     NTSTATUS status;
4470     HANDLE handle;
4471 
4472     if (!(handle = create_temp_file(0))) return;
4473 
4474     /* test with INVALID_HANDLE_VALUE */
4475     U(io).Status = 0xdeadbeef;
4476     io.Information = 0xdeadbeef;
4477     memset(buffer, 0xcc, EA_BUFFER_SIZE);
4478     buffer_len = EA_BUFFER_SIZE - 1;
4479     status = pNtQueryEaFile(INVALID_HANDLE_VALUE, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4480     ok(status == STATUS_OBJECT_TYPE_MISMATCH, "expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", status);
4481     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4482     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4483     ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
4484 
4485     /* test with 0xdeadbeef */
4486     U(io).Status = 0xdeadbeef;
4487     io.Information = 0xdeadbeef;
4488     memset(buffer, 0xcc, EA_BUFFER_SIZE);
4489     buffer_len = EA_BUFFER_SIZE - 1;
4490     status = pNtQueryEaFile((void *)0xdeadbeef, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4491     ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %x\n", status);
4492     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4493     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4494     ok(buffer[0] == 0xcc, "data at position 0 overwritten\n");
4495 
4496     /* test without buffer */
4497     U(io).Status = 0xdeadbeef;
4498     io.Information = 0xdeadbeef;
4499     status = pNtQueryEaFile(handle, &io, NULL, 0, TRUE, NULL, 0, NULL, FALSE);
4500     ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4501     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4502     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4503 
4504     /* test with zero buffer */
4505     U(io).Status = 0xdeadbeef;
4506     io.Information = 0xdeadbeef;
4507     status = pNtQueryEaFile(handle, &io, buffer, 0, TRUE, NULL, 0, NULL, FALSE);
4508     ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4509     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4510     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4511 
4512     /* test with very small buffer */
4513     U(io).Status = 0xdeadbeef;
4514     io.Information = 0xdeadbeef;
4515     memset(buffer, 0xcc, EA_BUFFER_SIZE);
4516     buffer_len = 4;
4517     status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4518     ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4519     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4520     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4521     for (i = 0; i < buffer_len && !buffer[i]; i++);
4522     ok(i == buffer_len,  "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
4523     ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
4524 
4525     /* test with very big buffer */
4526     U(io).Status = 0xdeadbeef;
4527     io.Information = 0xdeadbeef;
4528     memset(buffer, 0xcc, EA_BUFFER_SIZE);
4529     buffer_len = EA_BUFFER_SIZE - 1;
4530     status = pNtQueryEaFile(handle, &io, buffer, buffer_len, TRUE, NULL, 0, NULL, FALSE);
4531     ok(status == STATUS_NO_EAS_ON_FILE, "expected STATUS_NO_EAS_ON_FILE, got %x\n", status);
4532     ok(U(io).Status == 0xdeadbeef, "expected 0xdeadbeef, got %x\n", U(io).Status);
4533     ok(io.Information == 0xdeadbeef, "expected 0xdeadbeef, got %lu\n", io.Information);
4534     for (i = 0; i < buffer_len && !buffer[i]; i++);
4535     ok(i == buffer_len,  "expected %u bytes filled with 0x00, got %u bytes\n", buffer_len, i);
4536     ok(buffer[i] == 0xcc, "data at position %u overwritten\n", buffer[i]);
4537 
4538     CloseHandle(handle);
4539     #undef EA_BUFFER_SIZE
4540 }
4541 
4542 static INT build_reparse_buffer(WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
4543 {
4544     REPARSE_DATA_BUFFER *buffer;
4545     INT buffer_len, string_len;
4546     WCHAR *dest;
4547 
4548     string_len = (lstrlenW(filename)+1)*sizeof(WCHAR);
4549     buffer_len = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[1]) + string_len;
4550     buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
4551     buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
4552     buffer->ReparseDataLength = sizeof(buffer->MountPointReparseBuffer) + string_len;
4553     buffer->MountPointReparseBuffer.SubstituteNameLength = string_len - sizeof(WCHAR);
4554     buffer->MountPointReparseBuffer.PrintNameOffset = string_len;
4555     dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
4556     memcpy(dest, filename, string_len);
4557     *pbuffer = buffer;
4558     return buffer_len;
4559 }
4560 
4561 static void test_junction_points(void)
4562 {
4563     static const WCHAR junctionW[] = {'\\','j','u','n','c','t','i','o','n',0};
4564     WCHAR path[MAX_PATH], junction_path[MAX_PATH], target_path[MAX_PATH];
4565     static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
4566     FILE_BASIC_INFORMATION old_attrib, new_attrib;
4567     static const WCHAR fooW[] = {'f','o','o',0};
4568     static WCHAR volW[] = {'c',':','\\',0};
4569     REPARSE_GUID_DATA_BUFFER guid_buffer;
4570     static const WCHAR dotW[] = {'.',0};
4571     REPARSE_DATA_BUFFER *buffer = NULL;
4572     DWORD dwret, dwLen, dwFlags, err;
4573     INT buffer_len, string_len;
4574     IO_STATUS_BLOCK iosb;
4575     UNICODE_STRING nameW;
4576     HANDLE hJunction;
4577     WCHAR *dest;
4578     BOOL bret;
4579 
4580     /* Create a temporary folder for the junction point tests */
4581     GetTempFileNameW(dotW, fooW, 0, path);
4582     DeleteFileW(path);
4583     if (!CreateDirectoryW(path, NULL))
4584     {
4585         win_skip("Unable to create a temporary junction point directory.\n");
4586         return;
4587     }
4588 
4589     /* Check that the volume this folder is located on supports junction points */
4590     pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
4591     volW[0] = nameW.Buffer[4];
4592     pRtlFreeUnicodeString( &nameW );
4593     GetVolumeInformationW(volW, 0, 0, 0, &dwLen, &dwFlags, 0, 0);
4594     if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
4595     {
4596         skip("File system does not support junction points.\n");
4597         RemoveDirectoryW(path);
4598         return;
4599     }
4600 
4601     /* Create the folder to be replaced by a junction point */
4602     lstrcpyW(junction_path, path);
4603     lstrcatW(junction_path, junctionW);
4604     bret = CreateDirectoryW(junction_path, NULL);
4605     ok(bret, "Failed to create junction point directory.\n");
4606 
4607     /* Create a destination folder for the junction point to target */
4608     lstrcpyW(target_path, path);
4609     lstrcatW(target_path, targetW);
4610     bret = CreateDirectoryW(target_path, NULL);
4611     ok(bret, "Failed to create junction point target directory.\n");
4612     pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
4613 
4614     /* Create the junction point */
4615     hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4616                             FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4617     if (hJunction == INVALID_HANDLE_VALUE)
4618     {
4619         win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError());
4620         goto cleanup;
4621     }
4622     dwret = NtQueryInformationFile(hJunction, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
4623     ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
4624     buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4625     bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4626     ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4627 
4628     /* Check the file attributes of the junction point */
4629     dwret = GetFileAttributesW(junction_path);
4630     ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret);
4631     ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: %d)\n", dwret);
4632 
4633     /* Read back the junction point */
4634     HeapFree(GetProcessHeap(), 0, buffer);
4635     buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
4636     buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
4637     bret = DeviceIoControl(hJunction, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
4638     string_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
4639     dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
4640     ok(bret, "Failed to read junction point!\n");
4641     ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
4642                                                       wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
4643 
4644     /* Delete the junction point */
4645     memset(&old_attrib, 0x00, sizeof(old_attrib));
4646     old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
4647     dwret = NtSetInformationFile(hJunction, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
4648     ok(dwret == STATUS_SUCCESS, "Failed to set junction point folder's attributes (0x%x).\n", dwret);
4649     memset(&guid_buffer, 0x00, sizeof(guid_buffer));
4650     guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
4651     bret = DeviceIoControl(hJunction, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
4652                            REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &dwret, 0);
4653     ok(bret, "Failed to delete junction point! (0x%x)\n", GetLastError());
4654     memset(&new_attrib, 0x00, sizeof(new_attrib));
4655     dwret = NtQueryInformationFile(hJunction, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
4656     ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret);
4657     ok(old_attrib.LastAccessTime.QuadPart == new_attrib.LastAccessTime.QuadPart,
4658        "Junction point folder's access time does not match.\n");
4659     CloseHandle(hJunction);
4660 
4661     /* Check deleting a junction point as if it were a directory */
4662     HeapFree(GetProcessHeap(), 0, buffer);
4663     hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4664                             FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4665     buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4666     bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4667     ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4668     CloseHandle(hJunction);
4669     bret = RemoveDirectoryW(junction_path);
4670     ok(bret, "Failed to delete junction point as directory!\n");
4671     dwret = GetFileAttributesW(junction_path);
4672     ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%x)!\n", dwret);
4673 
4674     /* Check deleting a junction point as if it were a file */
4675     HeapFree(GetProcessHeap(), 0, buffer);
4676     bret = CreateDirectoryW(junction_path, NULL);
4677     ok(bret, "Failed to create junction point target directory.\n");
4678     hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
4679                             FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
4680     buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
4681     bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
4682     ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
4683     CloseHandle(hJunction);
4684     bret = DeleteFileW(junction_path);
4685     ok(!bret, "Succeeded in deleting junction point as file!\n");
4686     err = GetLastError();
4687     ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!\n",
4688                                    ERROR_ACCESS_DENIED, err);
4689     dwret = GetFileAttributesW(junction_path);
4690     ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret);
4691     ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%x)\n", dwret);
4692 
4693     /* Test deleting a junction point's target */
4694     dwret = GetFileAttributesW(junction_path);
4695     ok(dwret == 0x410 || broken(dwret == 0x430) /* win2k */,
4696        "Unexpected junction point attributes (0x%x != 0x410)!\n", dwret);
4697     bret = RemoveDirectoryW(target_path);
4698     ok(bret, "Failed to delete junction point target!\n");
4699     bret = CreateDirectoryW(target_path, NULL);
4700     ok(bret, "Failed to create junction point target directory.\n");
4701 
4702 cleanup:
4703     /* Cleanup */
4704     pRtlFreeUnicodeString( &nameW );
4705     HeapFree(GetProcessHeap(), 0, buffer);
4706     bret = RemoveDirectoryW(junction_path);
4707     ok(bret, "Failed to remove temporary junction point directory!\n");
4708     bret = RemoveDirectoryW(target_path);
4709     ok(bret, "Failed to remove temporary target directory!\n");
4710     RemoveDirectoryW(path);
4711 }
4712 
4713 START_TEST(file)
4714 {
4715     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
4716     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
4717     if (!hntdll)
4718     {
4719         skip("not running on NT, skipping test\n");
4720         return;
4721     }
4722 
4723     pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
4724     pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
4725 
4726     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
4727     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
4728     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
4729     pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
4730     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
4731     pNtCreateFile           = (void *)GetProcAddress(hntdll, "NtCreateFile");
4732     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
4733     pNtDeleteFile           = (void *)GetProcAddress(hntdll, "NtDeleteFile");
4734     pNtReadFile             = (void *)GetProcAddress(hntdll, "NtReadFile");
4735     pNtWriteFile            = (void *)GetProcAddress(hntdll, "NtWriteFile");
4736     pNtCancelIoFile         = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
4737     pNtCancelIoFileEx       = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
4738     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
4739     pNtFsControlFile        = (void *)GetProcAddress(hntdll, "NtFsControlFile");
4740     pNtCreateIoCompletion   = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
4741     pNtOpenIoCompletion     = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
4742     pNtQueryIoCompletion    = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
4743     pNtRemoveIoCompletion   = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
4744     pNtSetIoCompletion      = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
4745     pNtSetInformationFile   = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
4746     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
4747     pNtQueryDirectoryFile   = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
4748     pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
4749     pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
4750     pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
4751     pNtQueryEaFile          = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
4752 
4753     test_read_write();
4754     test_NtCreateFile();
4755     test_readonly();
4756     create_file_test();
4757     open_file_test();
4758     delete_file_test();
4759     read_file_test();
4760     append_file_test();
4761     nt_mailslot_test();
4762     test_iocompletion();
4763     test_file_basic_information();
4764     test_file_all_information();
4765     test_file_both_information();
4766     test_file_name_information();
4767     test_file_full_size_information();
4768     test_file_all_name_information();
4769     test_file_rename_information();
4770     test_file_link_information();
4771     test_file_disposition_information();
4772     test_file_completion_information();
4773     test_file_id_information();
4774     test_file_access_information();
4775     test_query_volume_information_file();
4776     test_query_attribute_information_file();
4777     test_ioctl();
4778     test_flush_buffers_file();
4779     test_query_ea();
4780     test_junction_points();
4781 }
4782