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