crypt32: Add additional path for Solaris 11 Express.
[wine] / dlls / ntdll / tests / file.c
1 /* Unit test suite for Ntdll file functions
2  *
3  * Copyright 2007 Jeff Latimer
4  * Copyright 2007 Andrey Turkin
5  * Copyright 2008 Jeff Zaroyko
6  * Copyright 2011 Dmitry Timoshkov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  *
22  * NOTES
23  * We use function pointers here as there is no import library for NTDLL on
24  * windows.
25  */
26
27 #include <stdio.h>
28 #include <stdarg.h>
29
30 #include "ntstatus.h"
31 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
32  * definition errors when we get to winnt.h
33  */
34 #define WIN32_NO_STATUS
35
36 #include "wine/test.h"
37 #include "winternl.h"
38 #include "winuser.h"
39 #include "winioctl.h"
40
41 #ifndef IO_COMPLETION_ALL_ACCESS
42 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
43 #endif
44
45 static BOOL     (WINAPI * pGetVolumePathNameW)(LPCWSTR, LPWSTR, DWORD);
46 static UINT     (WINAPI *pGetSystemWow64DirectoryW)( LPWSTR, UINT );
47
48 static VOID     (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
49 static VOID     (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
50 static BOOL     (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
51 static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG, ULONG * );
52
53 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
54                                        ULONG, ULONG, ULONG, PLARGE_INTEGER );
55 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
56 static NTSTATUS (WINAPI *pNtOpenFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,ULONG,ULONG);
57 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
58 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
59                                       PIO_APC_ROUTINE apc, void* apc_user,
60                                       PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
61                                       PLARGE_INTEGER offset, PULONG key);
62 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
63                                        PIO_APC_ROUTINE apc, void* apc_user,
64                                        PIO_STATUS_BLOCK io_status,
65                                        const void* buffer, ULONG length,
66                                        PLARGE_INTEGER offset, PULONG key);
67 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
68 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
69 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
70
71 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
72 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
73 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
74 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
75 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
76 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
77 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
78 static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
79                                                 PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
80 static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
81
82 static inline BOOL is_signaled( HANDLE obj )
83 {
84     return WaitForSingleObject( obj, 0 ) == 0;
85 }
86
87 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
88 #define TEST_BUF_LEN 3
89
90 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
91 {
92     *read = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
93                             1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
94     ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
95
96     *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
97     ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
98
99     return TRUE;
100 }
101
102 static HANDLE create_temp_file( ULONG flags )
103 {
104     char buffer[MAX_PATH];
105     HANDLE handle;
106
107     GetTempFileNameA( ".", "foo", 0, buffer );
108     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
109                          flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
110     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
111     return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
112 }
113
114 #define CVALUE_FIRST 0xfffabbcc
115 #define CKEY_FIRST 0x1030341
116 #define CKEY_SECOND 0x132E46
117
118 static ULONG_PTR completionKey;
119 static IO_STATUS_BLOCK ioSb;
120 static ULONG_PTR completionValue;
121
122 static ULONG get_pending_msgs(HANDLE h)
123 {
124     NTSTATUS res;
125     ULONG a, req;
126
127     res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
128     ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
129     if (res != STATUS_SUCCESS) return -1;
130     ok( req == sizeof(a), "Unexpected response size: %x\n", req );
131     return a;
132 }
133
134 static BOOL get_msg(HANDLE h)
135 {
136     LARGE_INTEGER timeout = {{-10000000*3}};
137     DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
138     ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
139     if (res != STATUS_SUCCESS)
140     {
141         completionKey = completionValue = 0;
142         memset(&ioSb, 0, sizeof(ioSb));
143         return FALSE;
144     }
145     return TRUE;
146 }
147
148
149 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
150 {
151     int *count = arg;
152
153     trace( "apc called block %p iosb.status %x iosb.info %lu\n",
154            iosb, U(*iosb).Status, iosb->Information );
155     (*count)++;
156     ok( !reserved, "reserved is not 0: %x\n", reserved );
157 }
158
159 static void create_file_test(void)
160 {
161     static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
162                                         '\\','f','a','i','l','i','n','g',0};
163     NTSTATUS status;
164     HANDLE dir;
165     WCHAR path[MAX_PATH];
166     OBJECT_ATTRIBUTES attr;
167     IO_STATUS_BLOCK io;
168     UNICODE_STRING nameW;
169
170     GetCurrentDirectoryW( MAX_PATH, path );
171     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
172     attr.Length = sizeof(attr);
173     attr.RootDirectory = 0;
174     attr.ObjectName = &nameW;
175     attr.Attributes = OBJ_CASE_INSENSITIVE;
176     attr.SecurityDescriptor = NULL;
177     attr.SecurityQualityOfService = NULL;
178
179     /* try various open modes and options on directories */
180     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
181                             FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 );
182     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
183     CloseHandle( dir );
184
185     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
186                             FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0 );
187     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
188         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
189
190     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
191                             FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 );
192     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
193     CloseHandle( dir );
194
195     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
196                             FILE_SUPERSEDE, FILE_DIRECTORY_FILE, NULL, 0 );
197     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
198
199     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
200                             FILE_OVERWRITE, FILE_DIRECTORY_FILE, NULL, 0 );
201     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
202
203     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
204                             FILE_OVERWRITE_IF, FILE_DIRECTORY_FILE, NULL, 0 );
205     ok( status == STATUS_INVALID_PARAMETER, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
206
207     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
208                             FILE_OPEN, 0, NULL, 0 );
209     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
210     CloseHandle( dir );
211
212     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
213                             FILE_CREATE, 0, NULL, 0 );
214     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
215         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
216
217     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
218                             FILE_OPEN_IF, 0, NULL, 0 );
219     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
220     CloseHandle( dir );
221
222     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
223                             FILE_SUPERSEDE, 0, NULL, 0 );
224     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
225         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
226
227     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
228                             FILE_OVERWRITE, 0, NULL, 0 );
229     ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_ACCESS_DENIED,
230         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
231
232     status = pNtCreateFile( &dir, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
233                             FILE_OVERWRITE_IF, 0, 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     pRtlFreeUnicodeString( &nameW );
238
239     pRtlInitUnicodeString( &nameW, systemrootW );
240     attr.Length = sizeof(attr);
241     attr.RootDirectory = NULL;
242     attr.ObjectName = &nameW;
243     attr.Attributes = OBJ_CASE_INSENSITIVE;
244     attr.SecurityDescriptor = NULL;
245     attr.SecurityQualityOfService = NULL;
246     dir = NULL;
247     status = pNtCreateFile( &dir, FILE_APPEND_DATA, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0,
248                             FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
249     todo_wine
250     ok( status == STATUS_INVALID_PARAMETER,
251         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
252 }
253
254 static void open_file_test(void)
255 {
256     NTSTATUS status;
257     HANDLE dir, root, handle;
258     WCHAR path[MAX_PATH];
259     BYTE data[1024];
260     OBJECT_ATTRIBUTES attr;
261     IO_STATUS_BLOCK io;
262     UNICODE_STRING nameW;
263     UINT i, len;
264     BOOL restart = TRUE;
265
266     len = GetWindowsDirectoryW( path, MAX_PATH );
267     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
268     attr.Length = sizeof(attr);
269     attr.RootDirectory = 0;
270     attr.ObjectName = &nameW;
271     attr.Attributes = OBJ_CASE_INSENSITIVE;
272     attr.SecurityDescriptor = NULL;
273     attr.SecurityQualityOfService = NULL;
274     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
275                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
276     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
277     pRtlFreeUnicodeString( &nameW );
278
279     path[3] = 0;  /* root of the drive */
280     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
281     status = pNtOpenFile( &root, GENERIC_READ, &attr, &io,
282                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
283     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
284     pRtlFreeUnicodeString( &nameW );
285
286     /* test opening system dir with RootDirectory set to windows dir */
287     GetSystemDirectoryW( path, MAX_PATH );
288     while (path[len] == '\\') len++;
289     nameW.Buffer = path + len;
290     nameW.Length = lstrlenW(path + len) * sizeof(WCHAR);
291     attr.RootDirectory = dir;
292     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
293                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
294     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
295     CloseHandle( handle );
296
297     /* try uppercase name */
298     for (i = len; path[i]; i++) if (path[i] >= 'a' && path[i] <= 'z') path[i] -= 'a' - 'A';
299     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
300                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
301     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
302     CloseHandle( handle );
303
304     /* try with leading backslash */
305     nameW.Buffer--;
306     nameW.Length += sizeof(WCHAR);
307     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
308                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
309     ok( status == STATUS_INVALID_PARAMETER ||
310         status == STATUS_OBJECT_NAME_INVALID ||
311         status == STATUS_OBJECT_PATH_SYNTAX_BAD,
312         "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
313     if (!status) CloseHandle( handle );
314
315     /* try with empty name */
316     nameW.Length = 0;
317     status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
318                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE );
319     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
320     CloseHandle( handle );
321
322     /* try open by file id */
323
324     while (!pNtQueryDirectoryFile( dir, NULL, NULL, NULL, &io, data, sizeof(data),
325                                    FileIdBothDirectoryInformation, TRUE, NULL, restart ))
326     {
327         FILE_ID_BOTH_DIRECTORY_INFORMATION *info = (FILE_ID_BOTH_DIRECTORY_INFORMATION *)data;
328
329         restart = FALSE;
330
331         if (!info->FileId.QuadPart) continue;
332
333         nameW.Buffer = (WCHAR *)&info->FileId;
334         nameW.Length = sizeof(info->FileId);
335         info->FileName[info->FileNameLength/sizeof(WCHAR)] = 0;
336         attr.RootDirectory = dir;
337         /* We skip 'open' files by not specifying FILE_SHARE_WRITE */
338         status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
339                               FILE_SHARE_READ,
340                               FILE_OPEN_BY_FILE_ID |
341                               ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
342         ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION,
343             "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
344         if (status == STATUS_NOT_IMPLEMENTED)
345         {
346             win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" );
347             break;
348         }
349         if (status == STATUS_SHARING_VIOLATION)
350             trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) );
351         if (!status)
352         {
353             BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
354
355             if (!pNtQueryInformationFile( handle, &io, buf, sizeof(buf), FileAllInformation ))
356             {
357                 FILE_ALL_INFORMATION *fai = (FILE_ALL_INFORMATION *)buf;
358
359                 /* check that it's the same file/directory */
360
361                 /* don't check the size for directories */
362                 if (!(info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
363                     ok( info->EndOfFile.QuadPart == fai->StandardInformation.EndOfFile.QuadPart,
364                         "mismatched file size for %s\n", wine_dbgstr_w(info->FileName));
365
366                 ok( info->CreationTime.QuadPart == fai->BasicInformation.CreationTime.QuadPart,
367                     "mismatched creation time for %s\n", wine_dbgstr_w(info->FileName));
368             }
369             CloseHandle( handle );
370
371             /* try same thing from drive root */
372             attr.RootDirectory = root;
373             status = pNtOpenFile( &handle, GENERIC_READ, &attr, &io,
374                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
375                                   FILE_OPEN_BY_FILE_ID |
376                                   ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) );
377             ok( status == STATUS_SUCCESS || status == STATUS_NOT_IMPLEMENTED,
378                 "open %s failed %x\n", wine_dbgstr_w(info->FileName), status );
379             if (!status) CloseHandle( handle );
380         }
381     }
382
383     CloseHandle( dir );
384     CloseHandle( root );
385 }
386
387 static void delete_file_test(void)
388 {
389     NTSTATUS ret;
390     OBJECT_ATTRIBUTES attr;
391     UNICODE_STRING nameW;
392     WCHAR pathW[MAX_PATH];
393     WCHAR pathsubW[MAX_PATH];
394     static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
395     static const WCHAR subdirW[]  = {'\\','s','u','b',0};
396
397     ret = GetTempPathW(MAX_PATH, pathW);
398     if (!ret)
399     {
400         ok(0, "couldn't get temp dir\n");
401         return;
402     }
403     if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
404     {
405         ok(0, "MAX_PATH exceeded in constructing paths\n");
406         return;
407     }
408
409     lstrcatW(pathW, testdirW);
410     lstrcpyW(pathsubW, pathW);
411     lstrcatW(pathsubW, subdirW);
412
413     ret = CreateDirectoryW(pathW, NULL);
414     ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
415     if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
416     {
417         ok(0,"RtlDosPathNametoNtPathName_U failed\n");
418         return;
419     }
420
421     attr.Length = sizeof(attr);
422     attr.RootDirectory = 0;
423     attr.Attributes = OBJ_CASE_INSENSITIVE;
424     attr.ObjectName = &nameW;
425     attr.SecurityDescriptor = NULL;
426     attr.SecurityQualityOfService = NULL;
427
428     /* test NtDeleteFile on an empty directory */
429     ret = pNtDeleteFile(&attr);
430     ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
431     ret = RemoveDirectoryW(pathW);
432     ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
433
434     /* test NtDeleteFile on a non-empty directory */
435     ret = CreateDirectoryW(pathW, NULL);
436     ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
437     ret = CreateDirectoryW(pathsubW, NULL);
438     ok(ret == TRUE, "couldn't create directory subdir\n");
439     ret = pNtDeleteFile(&attr);
440     ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
441     ret = RemoveDirectoryW(pathsubW);
442     ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
443     ret = RemoveDirectoryW(pathW);
444     ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
445
446     pRtlFreeUnicodeString( &nameW );
447 }
448
449 static void read_file_test(void)
450 {
451     const char text[] = "foobar";
452     HANDLE handle, read, write;
453     NTSTATUS status;
454     IO_STATUS_BLOCK iosb, iosb2;
455     DWORD written;
456     int apc_count = 0;
457     char buffer[128];
458     LARGE_INTEGER offset;
459     HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
460     BOOL ret;
461
462     buffer[0] = 1;
463
464     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
465
466     /* try read with no data */
467     U(iosb).Status = 0xdeadbabe;
468     iosb.Information = 0xdeadbeef;
469     ok( is_signaled( read ), "read handle is not signaled\n" );
470     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
471     ok( status == STATUS_PENDING, "wrong status %x\n", status );
472     ok( !is_signaled( read ), "read handle is signaled\n" );
473     ok( !is_signaled( event ), "event is signaled\n" );
474     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
475     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
476     ok( !apc_count, "apc was called\n" );
477     WriteFile( write, buffer, 1, &written, NULL );
478     /* iosb updated here by async i/o */
479     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
480     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
481     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
482     ok( !is_signaled( read ), "read handle is signaled\n" );
483     ok( is_signaled( event ), "event is not signaled\n" );
484     ok( !apc_count, "apc was called\n" );
485     apc_count = 0;
486     SleepEx( 1, FALSE ); /* non-alertable sleep */
487     ok( !apc_count, "apc was called\n" );
488     SleepEx( 1, TRUE ); /* alertable sleep */
489     ok( apc_count == 1, "apc not called\n" );
490
491     /* with no event, the pipe handle itself gets signaled */
492     apc_count = 0;
493     U(iosb).Status = 0xdeadbabe;
494     iosb.Information = 0xdeadbeef;
495     ok( !is_signaled( read ), "read handle is not signaled\n" );
496     status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
497     ok( status == STATUS_PENDING, "wrong status %x\n", status );
498     ok( !is_signaled( read ), "read handle is signaled\n" );
499     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
500     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
501     ok( !apc_count, "apc was called\n" );
502     WriteFile( write, buffer, 1, &written, NULL );
503     /* iosb updated here by async i/o */
504     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
505     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
506     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
507     ok( is_signaled( read ), "read handle is signaled\n" );
508     ok( !apc_count, "apc was called\n" );
509     apc_count = 0;
510     SleepEx( 1, FALSE ); /* non-alertable sleep */
511     ok( !apc_count, "apc was called\n" );
512     SleepEx( 1, TRUE ); /* alertable sleep */
513     ok( apc_count == 1, "apc not called\n" );
514
515     /* now read with data ready */
516     apc_count = 0;
517     U(iosb).Status = 0xdeadbabe;
518     iosb.Information = 0xdeadbeef;
519     ResetEvent( event );
520     WriteFile( write, buffer, 1, &written, NULL );
521     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
522     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
523     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
524     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
525     ok( is_signaled( event ), "event is not signaled\n" );
526     ok( !apc_count, "apc was called\n" );
527     SleepEx( 1, FALSE ); /* non-alertable sleep */
528     ok( !apc_count, "apc was called\n" );
529     SleepEx( 1, TRUE ); /* alertable sleep */
530     ok( apc_count == 1, "apc not called\n" );
531
532     /* try read with no data */
533     apc_count = 0;
534     U(iosb).Status = 0xdeadbabe;
535     iosb.Information = 0xdeadbeef;
536     ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
537     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
538     ok( status == STATUS_PENDING, "wrong status %x\n", status );
539     ok( !is_signaled( event ), "event is signaled\n" );
540     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
541     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
542     ok( !apc_count, "apc was called\n" );
543     WriteFile( write, buffer, 1, &written, NULL );
544     /* partial read is good enough */
545     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
546     ok( is_signaled( event ), "event is signaled\n" );
547     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
548     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
549     ok( !apc_count, "apc was called\n" );
550     SleepEx( 1, TRUE ); /* alertable sleep */
551     ok( apc_count == 1, "apc was not called\n" );
552
553     /* read from disconnected pipe */
554     apc_count = 0;
555     U(iosb).Status = 0xdeadbabe;
556     iosb.Information = 0xdeadbeef;
557     CloseHandle( write );
558     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
559     ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
560     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
561     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
562     ok( !is_signaled( event ), "event is signaled\n" );
563     ok( !apc_count, "apc was called\n" );
564     SleepEx( 1, TRUE ); /* alertable sleep */
565     ok( !apc_count, "apc was called\n" );
566     CloseHandle( read );
567
568     /* read from closed handle */
569     apc_count = 0;
570     U(iosb).Status = 0xdeadbabe;
571     iosb.Information = 0xdeadbeef;
572     SetEvent( event );
573     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
574     ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
575     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
576     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
577     ok( is_signaled( event ), "event is signaled\n" );  /* not reset on invalid handle */
578     ok( !apc_count, "apc was called\n" );
579     SleepEx( 1, TRUE ); /* alertable sleep */
580     ok( !apc_count, "apc was called\n" );
581
582     /* disconnect while async read is in progress */
583     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
584     apc_count = 0;
585     U(iosb).Status = 0xdeadbabe;
586     iosb.Information = 0xdeadbeef;
587     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
588     ok( status == STATUS_PENDING, "wrong status %x\n", status );
589     ok( !is_signaled( event ), "event is signaled\n" );
590     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
591     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
592     ok( !apc_count, "apc was called\n" );
593     CloseHandle( write );
594     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
595     ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
596     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
597     ok( is_signaled( event ), "event is signaled\n" );
598     ok( !apc_count, "apc was called\n" );
599     SleepEx( 1, TRUE ); /* alertable sleep */
600     ok( apc_count == 1, "apc was not called\n" );
601     CloseHandle( read );
602
603     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
604     ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
605     ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
606
607     apc_count = 0;
608     U(iosb).Status = 0xdeadbabe;
609     iosb.Information = 0xdeadbeef;
610     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
611     ok( status == STATUS_PENDING, "wrong status %x\n", status );
612     ok( !is_signaled( event ), "event is signaled\n" );
613     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
614     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
615     ok( !apc_count, "apc was called\n" );
616     /* Cancel by other handle */
617     status = pNtCancelIoFile( read, &iosb2 );
618     ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
619     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
620     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
621     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
622     ok( is_signaled( event ), "event is signaled\n" );
623     todo_wine ok( !apc_count, "apc was called\n" );
624     SleepEx( 1, TRUE ); /* alertable sleep */
625     ok( apc_count == 1, "apc was not called\n" );
626
627     apc_count = 0;
628     U(iosb).Status = 0xdeadbabe;
629     iosb.Information = 0xdeadbeef;
630     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
631     ok( status == STATUS_PENDING, "wrong status %x\n", status );
632     ok( !is_signaled( event ), "event is signaled\n" );
633     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
634     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
635     ok( !apc_count, "apc was called\n" );
636     /* Close queued handle */
637     CloseHandle( read );
638     SleepEx( 1, TRUE ); /* alertable sleep */
639     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
640     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
641     status = pNtCancelIoFile( read, &iosb2 );
642     ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
643     status = pNtCancelIoFile( handle, &iosb2 );
644     ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
645     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
646     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
647     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
648     ok( is_signaled( event ), "event is signaled\n" );
649     todo_wine ok( !apc_count, "apc was called\n" );
650     SleepEx( 1, TRUE ); /* alertable sleep */
651     ok( apc_count == 1, "apc was not called\n" );
652     CloseHandle( handle );
653     CloseHandle( write );
654
655     if (pNtCancelIoFileEx)
656     {
657         /* Basic Cancel Ex */
658         if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
659
660         apc_count = 0;
661         U(iosb).Status = 0xdeadbabe;
662         iosb.Information = 0xdeadbeef;
663         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
664         ok( status == STATUS_PENDING, "wrong status %x\n", status );
665         ok( !is_signaled( event ), "event is signaled\n" );
666         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
667         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
668         ok( !apc_count, "apc was called\n" );
669         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
670         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
671         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
672         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
673         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
674         ok( is_signaled( event ), "event is signaled\n" );
675         todo_wine ok( !apc_count, "apc was called\n" );
676         SleepEx( 1, TRUE ); /* alertable sleep */
677         ok( apc_count == 1, "apc was not called\n" );
678
679         /* Duplicate iosb */
680         apc_count = 0;
681         U(iosb).Status = 0xdeadbabe;
682         iosb.Information = 0xdeadbeef;
683         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
684         ok( status == STATUS_PENDING, "wrong status %x\n", status );
685         ok( !is_signaled( event ), "event is signaled\n" );
686         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
687         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
688         ok( !apc_count, "apc was called\n" );
689         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
690         ok( status == STATUS_PENDING, "wrong status %x\n", status );
691         ok( !is_signaled( event ), "event is signaled\n" );
692         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
693         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
694         ok( !apc_count, "apc was called\n" );
695         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
696         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
697         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
698         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
699         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
700         ok( is_signaled( event ), "event is signaled\n" );
701         todo_wine ok( !apc_count, "apc was called\n" );
702         SleepEx( 1, TRUE ); /* alertable sleep */
703         ok( apc_count == 2, "apc was not called\n" );
704
705         CloseHandle( read );
706         CloseHandle( write );
707     }
708
709     /* now try a real file */
710     if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
711     apc_count = 0;
712     U(iosb).Status = 0xdeadbabe;
713     iosb.Information = 0xdeadbeef;
714     offset.QuadPart = 0;
715     ResetEvent( event );
716     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
717     ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
718     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
719     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
720     ok( is_signaled( event ), "event is signaled\n" );
721     ok( !apc_count, "apc was called\n" );
722     SleepEx( 1, TRUE ); /* alertable sleep */
723     ok( apc_count == 1, "apc was not called\n" );
724
725     apc_count = 0;
726     U(iosb).Status = 0xdeadbabe;
727     iosb.Information = 0xdeadbeef;
728     offset.QuadPart = 0;
729     ResetEvent( event );
730     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
731     ok( status == STATUS_SUCCESS ||
732         status == STATUS_PENDING, /* vista */
733         "wrong status %x\n", status );
734     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
735     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
736     ok( is_signaled( event ), "event is signaled\n" );
737     ok( !apc_count, "apc was called\n" );
738     SleepEx( 1, TRUE ); /* alertable sleep */
739     ok( apc_count == 1, "apc was not called\n" );
740
741     /* read beyond eof */
742     apc_count = 0;
743     U(iosb).Status = 0xdeadbabe;
744     iosb.Information = 0xdeadbeef;
745     offset.QuadPart = strlen(text) + 2;
746     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
747     if (status == STATUS_PENDING)  /* vista */
748     {
749         ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
750         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
751         ok( is_signaled( event ), "event is signaled\n" );
752         ok( !apc_count, "apc was called\n" );
753         SleepEx( 1, TRUE ); /* alertable sleep */
754         ok( apc_count == 1, "apc was not called\n" );
755     }
756     else
757     {
758         ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
759         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
760         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
761         ok( !is_signaled( event ), "event is signaled\n" );
762         ok( !apc_count, "apc was called\n" );
763         SleepEx( 1, TRUE ); /* alertable sleep */
764         ok( !apc_count, "apc was called\n" );
765     }
766     CloseHandle( handle );
767
768     /* now a non-overlapped file */
769     if (!(handle = create_temp_file(0))) return;
770     apc_count = 0;
771     U(iosb).Status = 0xdeadbabe;
772     iosb.Information = 0xdeadbeef;
773     offset.QuadPart = 0;
774     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
775     ok( status == STATUS_END_OF_FILE ||
776         status == STATUS_SUCCESS ||
777         status == STATUS_PENDING,  /* vista */
778         "wrong status %x\n", status );
779     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
780     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
781     ok( is_signaled( event ), "event is signaled\n" );
782     ok( !apc_count, "apc was called\n" );
783     SleepEx( 1, TRUE ); /* alertable sleep */
784     ok( apc_count == 1, "apc was not called\n" );
785
786     apc_count = 0;
787     U(iosb).Status = 0xdeadbabe;
788     iosb.Information = 0xdeadbeef;
789     offset.QuadPart = 0;
790     ResetEvent( event );
791     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
792     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
793     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
794     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
795     ok( is_signaled( event ), "event is signaled\n" );
796     ok( !apc_count, "apc was called\n" );
797     SleepEx( 1, TRUE ); /* alertable sleep */
798     todo_wine ok( !apc_count, "apc was called\n" );
799
800     /* read beyond eof */
801     apc_count = 0;
802     U(iosb).Status = 0xdeadbabe;
803     iosb.Information = 0xdeadbeef;
804     offset.QuadPart = strlen(text) + 2;
805     ResetEvent( event );
806     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
807     ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
808     todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
809     todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
810     todo_wine ok( is_signaled( event ), "event is not signaled\n" );
811     ok( !apc_count, "apc was called\n" );
812     SleepEx( 1, TRUE ); /* alertable sleep */
813     ok( !apc_count, "apc was called\n" );
814
815     CloseHandle( handle );
816
817     CloseHandle( event );
818 }
819
820 static void append_file_test(void)
821 {
822     const char text[] = "foobar";
823     HANDLE handle;
824     NTSTATUS status;
825     IO_STATUS_BLOCK iosb;
826     DWORD written;
827     char buffer[128];
828
829     GetTempFileNameA( ".", "foo", 0, buffer );
830     /* It is possible to open a file with only FILE_APPEND_DATA access flags.
831        It matches the O_WRONLY|O_APPEND open() posix behavior */
832     handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, CREATE_ALWAYS,
833                          FILE_FLAG_DELETE_ON_CLOSE, 0);
834     ok( handle != INVALID_HANDLE_VALUE, "Failed to create a temp file in FILE_APPEND_DATA mode.\n" );
835     if(handle == INVALID_HANDLE_VALUE)
836     {
837         skip("Couldn't create a temporary file, skipping FILE_APPEND_DATA test\n");
838         return;
839     }
840
841     U(iosb).Status = STATUS_PENDING;
842     iosb.Information = 0;
843
844     status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb,
845                           text, sizeof(text), NULL, NULL);
846
847     if (status == STATUS_PENDING)
848     {
849         WaitForSingleObject( handle, INFINITE );
850         status = U(iosb).Status;
851     }
852     written = iosb.Information;
853
854     todo_wine
855     ok(status == STATUS_SUCCESS && written == sizeof(text), "FILE_APPEND_DATA NtWriteFile failed\n");
856
857     CloseHandle(handle);
858 }
859
860 static void nt_mailslot_test(void)
861 {
862     HANDLE hslot;
863     ACCESS_MASK DesiredAccess;
864     OBJECT_ATTRIBUTES attr;
865
866     ULONG CreateOptions;
867     ULONG MailslotQuota;
868     ULONG MaxMessageSize;
869     LARGE_INTEGER TimeOut;
870     IO_STATUS_BLOCK IoStatusBlock;
871     NTSTATUS rc;
872     UNICODE_STRING str;
873     WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
874                         'R',':','\\','F','R','E','D','\0' };
875
876     TimeOut.QuadPart = -1;
877
878     pRtlInitUnicodeString(&str, buffer1);
879     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
880     CreateOptions = MailslotQuota = MaxMessageSize = 0;
881     DesiredAccess = GENERIC_READ;
882
883     /*
884      * Check for NULL pointer handling
885      */
886     rc = pNtCreateMailslotFile(NULL, DesiredAccess,
887          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
888          &TimeOut);
889     ok( rc == STATUS_ACCESS_VIOLATION ||
890         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
891         "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
892
893     /*
894      * Test to see if the Timeout can be NULL
895      */
896     hslot = (HANDLE)0xdeadbeef;
897     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
898          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
899          NULL);
900     ok( rc == STATUS_SUCCESS ||
901         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
902         "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
903     ok( hslot != 0, "Handle is invalid\n");
904
905     if  ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
906
907     /*
908      * Test that the length field is checked properly
909      */
910     attr.Length = 0;
911     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
912          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
913          &TimeOut);
914     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
915
916     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
917
918     attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
919     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
920          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
921          &TimeOut);
922     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
923
924     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
925
926     /*
927      * Test handling of a NULL unicode string in ObjectName
928      */
929     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
930     attr.ObjectName = NULL;
931     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
932          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
933          &TimeOut);
934     ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
935         rc == STATUS_INVALID_PARAMETER,
936         "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
937
938     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
939
940     /*
941      * Test a valid call
942      */
943     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
944     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
945          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
946          &TimeOut);
947     ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
948     ok( hslot != 0, "Handle is invalid\n");
949
950     rc = pNtClose(hslot);
951     ok( rc == STATUS_SUCCESS, "NtClose failed\n");
952 }
953
954 static void test_iocp_setcompletion(HANDLE h)
955 {
956     NTSTATUS res;
957     ULONG count;
958
959     res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
960     ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
961
962     count = get_pending_msgs(h);
963     ok( count == 1, "Unexpected msg count: %d\n", count );
964
965     if (get_msg(h))
966     {
967         ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
968         ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
969         ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
970         ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
971     }
972
973     count = get_pending_msgs(h);
974     ok( !count, "Unexpected msg count: %d\n", count );
975 }
976
977 static void test_iocp_fileio(HANDLE h)
978 {
979     static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
980
981     IO_STATUS_BLOCK iosb;
982     FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
983     HANDLE hPipeSrv, hPipeClt;
984     NTSTATUS res;
985
986     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
987     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
988     if (hPipeSrv != INVALID_HANDLE_VALUE )
989     {
990         hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
991         ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
992         if (hPipeClt != INVALID_HANDLE_VALUE)
993         {
994             U(iosb).Status = 0xdeadbeef;
995             res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
996             ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
997             ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
998                 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
999             CloseHandle(hPipeClt);
1000         }
1001         CloseHandle( hPipeSrv );
1002     }
1003
1004     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1005     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1006     if (hPipeSrv == INVALID_HANDLE_VALUE )
1007         return;
1008
1009     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1010     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1011     if (hPipeClt != INVALID_HANDLE_VALUE)
1012     {
1013         OVERLAPPED o = {0,};
1014         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1015         DWORD read;
1016         long count;
1017
1018         U(iosb).Status = 0xdeadbeef;
1019         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1020         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1021         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1022
1023         memset( send_buf, 0, TEST_BUF_LEN );
1024         memset( recv_buf, 0xde, TEST_BUF_LEN );
1025         count = get_pending_msgs(h);
1026         ok( !count, "Unexpected msg count: %ld\n", count );
1027         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1028         count = get_pending_msgs(h);
1029         ok( !count, "Unexpected msg count: %ld\n", count );
1030         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1031
1032         if (get_msg(h))
1033         {
1034             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1035             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1036             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1037             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1038             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] );
1039         }
1040         count = get_pending_msgs(h);
1041         ok( !count, "Unexpected msg count: %ld\n", count );
1042
1043         memset( send_buf, 0, TEST_BUF_LEN );
1044         memset( recv_buf, 0xde, TEST_BUF_LEN );
1045         WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1046         count = get_pending_msgs(h);
1047         ok( !count, "Unexpected msg count: %ld\n", count );
1048         ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1049         count = get_pending_msgs(h);
1050         ok( count == 1, "Unexpected msg count: %ld\n", count );
1051         if (get_msg(h))
1052         {
1053             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1054             ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1055             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1056             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1057             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] );
1058         }
1059
1060         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1061         CloseHandle( hPipeSrv );
1062         count = get_pending_msgs(h);
1063         ok( count == 1, "Unexpected msg count: %ld\n", count );
1064         if (get_msg(h))
1065         {
1066             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1067             ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1068             /* wine sends wrong status here */
1069             todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1070             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1071         }
1072     }
1073
1074     CloseHandle( hPipeClt );
1075 }
1076
1077 static void test_file_basic_information(void)
1078 {
1079     IO_STATUS_BLOCK io;
1080     FILE_BASIC_INFORMATION fbi;
1081     HANDLE h;
1082     int res;
1083     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1084
1085     if (!(h = create_temp_file(0))) return;
1086
1087     /* Check default first */
1088     memset(&fbi, 0, sizeof(fbi));
1089     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1090     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1091     ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1092          "attribute %x not expected\n", fbi.FileAttributes );
1093
1094     /* Then SYSTEM */
1095     /* Clear fbi to avoid setting times */
1096     memset(&fbi, 0, sizeof(fbi));
1097     fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1098     U(io).Status = 0xdeadbeef;
1099     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1100     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1101     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1102
1103     memset(&fbi, 0, sizeof(fbi));
1104     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1105     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1106     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1107
1108     /* Then HIDDEN */
1109     memset(&fbi, 0, sizeof(fbi));
1110     fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1111     U(io).Status = 0xdeadbeef;
1112     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1113     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1114     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1115
1116     memset(&fbi, 0, sizeof(fbi));
1117     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1118     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1119     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1120
1121     /* Check NORMAL last of all (to make sure we can clear attributes) */
1122     memset(&fbi, 0, sizeof(fbi));
1123     fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1124     U(io).Status = 0xdeadbeef;
1125     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1126     ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1127     ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1128
1129     memset(&fbi, 0, sizeof(fbi));
1130     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1131     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1132     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1133
1134     CloseHandle( h );
1135 }
1136
1137 static void test_file_all_information(void)
1138 {
1139     IO_STATUS_BLOCK io;
1140     /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1141      * buffer at the end.  Vista objects with STATUS_BUFFER_OVERFLOW if you
1142      * don't leave enough room there.
1143      */
1144     struct {
1145       FILE_ALL_INFORMATION fai;
1146       WCHAR buf[256];
1147     } fai_buf;
1148     HANDLE h;
1149     int res;
1150     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1151
1152     if (!(h = create_temp_file(0))) return;
1153
1154     /* Check default first */
1155     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1156     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1157     ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1158          "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1159
1160     /* Then SYSTEM */
1161     /* Clear fbi to avoid setting times */
1162     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1163     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1164     U(io).Status = 0xdeadbeef;
1165     res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1166     ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1167     todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1168     U(io).Status = 0xdeadbeef;
1169     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1170     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1171     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1172
1173     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1174     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1175     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1176     todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes );
1177
1178     /* Then HIDDEN */
1179     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1180     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1181     U(io).Status = 0xdeadbeef;
1182     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1183     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1184     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1185
1186     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1187     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1188     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1189     todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes );
1190
1191     /* Check NORMAL last of all (to make sure we can clear attributes) */
1192     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1193     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1194     U(io).Status = 0xdeadbeef;
1195     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1196     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1197     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1198
1199     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1200     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1201     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1202     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 );
1203
1204     CloseHandle( h );
1205 }
1206
1207 static void test_file_both_information(void)
1208 {
1209     IO_STATUS_BLOCK io;
1210     FILE_BOTH_DIR_INFORMATION fbi;
1211     HANDLE h;
1212     int res;
1213
1214     if (!(h = create_temp_file(0))) return;
1215
1216     memset(&fbi, 0, sizeof(fbi));
1217     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
1218     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
1219
1220     CloseHandle( h );
1221 }
1222
1223 static void test_iocompletion(void)
1224 {
1225     HANDLE h = INVALID_HANDLE_VALUE;
1226     NTSTATUS res;
1227
1228     res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
1229
1230     ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
1231     ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
1232
1233     if ( h && h != INVALID_HANDLE_VALUE)
1234     {
1235         test_iocp_setcompletion(h);
1236         test_iocp_fileio(h);
1237         pNtClose(h);
1238     }
1239 }
1240
1241 static void test_file_name_information(void)
1242 {
1243     WCHAR *file_name, *volume_prefix, *expected;
1244     FILE_NAME_INFORMATION *info;
1245     ULONG old_redir = 1, tmp;
1246     UINT file_name_size;
1247     IO_STATUS_BLOCK io;
1248     UINT info_size;
1249     HRESULT hr;
1250     HANDLE h;
1251     UINT len;
1252
1253     /* GetVolumePathName is not present before w2k */
1254     if (!pGetVolumePathNameW) {
1255         win_skip("GetVolumePathNameW not found\n");
1256         return;
1257     }
1258
1259     file_name_size = GetSystemDirectoryW( NULL, 0 );
1260     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1261     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1262     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1263
1264     len = GetSystemDirectoryW( file_name, file_name_size );
1265     ok(len == file_name_size - 1,
1266             "GetSystemDirectoryW returned %u, expected %u.\n",
1267             len, file_name_size - 1);
1268
1269     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1270     ok(len, "GetVolumePathNameW failed.\n");
1271
1272     len = lstrlenW( volume_prefix );
1273     if (len && volume_prefix[len - 1] == '\\') --len;
1274     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1275     expected[file_name_size - len - 1] = '\0';
1276
1277     /* A bit more than we actually need, but it keeps the calculation simple. */
1278     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1279     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1280
1281     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1282     h = CreateFileW( file_name, GENERIC_READ,
1283             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1284             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1285     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1286     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1287
1288     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
1289     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
1290
1291     memset( info, 0xcc, info_size );
1292     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
1293     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1294             hr, STATUS_BUFFER_OVERFLOW);
1295     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1296             U(io).Status, STATUS_BUFFER_OVERFLOW);
1297     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1298     ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1299     ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1300             "info->FileName[1] is %p, expected %p.\n",
1301             CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1302     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1303
1304     memset( info, 0xcc, info_size );
1305     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1306     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1307     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1308     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1309     ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1310        info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1311     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1312     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1313             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1314     ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1315             "io.Information is %lu, expected %u.\n",
1316             io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1317
1318     CloseHandle( h );
1319     HeapFree( GetProcessHeap(), 0, info );
1320     HeapFree( GetProcessHeap(), 0, expected );
1321     HeapFree( GetProcessHeap(), 0, volume_prefix );
1322
1323     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1324     {
1325         skip("Not running on WoW64, skipping test.\n");
1326         HeapFree( GetProcessHeap(), 0, file_name );
1327         return;
1328     }
1329
1330     h = CreateFileW( file_name, GENERIC_READ,
1331             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1332             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1333     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1334     HeapFree( GetProcessHeap(), 0, file_name );
1335
1336     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1337     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1338     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1339
1340     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1341     ok(len == file_name_size - 1,
1342             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1343             len, file_name_size - 1);
1344
1345     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1346     ok(len, "GetVolumePathNameW failed.\n");
1347
1348     len = lstrlenW( volume_prefix );
1349     if (len && volume_prefix[len - 1] == '\\') --len;
1350     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1351     expected[file_name_size - len - 1] = '\0';
1352
1353     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1354     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1355
1356     memset( info, 0xcc, info_size );
1357     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1358     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1359     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1360     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1361             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1362
1363     CloseHandle( h );
1364     HeapFree( GetProcessHeap(), 0, info );
1365     HeapFree( GetProcessHeap(), 0, expected );
1366     HeapFree( GetProcessHeap(), 0, volume_prefix );
1367     HeapFree( GetProcessHeap(), 0, file_name );
1368 }
1369
1370 static void test_file_all_name_information(void)
1371 {
1372     WCHAR *file_name, *volume_prefix, *expected;
1373     FILE_ALL_INFORMATION *info;
1374     ULONG old_redir = 1, tmp;
1375     UINT file_name_size;
1376     IO_STATUS_BLOCK io;
1377     UINT info_size;
1378     HRESULT hr;
1379     HANDLE h;
1380     UINT len;
1381
1382     /* GetVolumePathName is not present before w2k */
1383     if (!pGetVolumePathNameW) {
1384         win_skip("GetVolumePathNameW not found\n");
1385         return;
1386     }
1387
1388     file_name_size = GetSystemDirectoryW( NULL, 0 );
1389     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1390     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1391     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1392
1393     len = GetSystemDirectoryW( file_name, file_name_size );
1394     ok(len == file_name_size - 1,
1395             "GetSystemDirectoryW returned %u, expected %u.\n",
1396             len, file_name_size - 1);
1397
1398     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1399     ok(len, "GetVolumePathNameW failed.\n");
1400
1401     len = lstrlenW( volume_prefix );
1402     if (len && volume_prefix[len - 1] == '\\') --len;
1403     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1404     expected[file_name_size - len - 1] = '\0';
1405
1406     /* A bit more than we actually need, but it keeps the calculation simple. */
1407     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1408     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1409
1410     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1411     h = CreateFileW( file_name, GENERIC_READ,
1412             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1413             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1414     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1415     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1416
1417     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
1418     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
1419             hr, STATUS_INFO_LENGTH_MISMATCH);
1420
1421     memset( info, 0xcc, info_size );
1422     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
1423     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1424             hr, STATUS_BUFFER_OVERFLOW);
1425     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1426             U(io).Status, STATUS_BUFFER_OVERFLOW);
1427     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1428        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1429     ok(info->NameInformation.FileName[2] == 0xcccc,
1430             "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
1431     ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1432             "info->NameInformation.FileName[1] is %p, expected %p.\n",
1433             CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1434     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1435
1436     memset( info, 0xcc, info_size );
1437     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1438     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1439     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1440     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1441        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1442     ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
1443        "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1444        info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
1445     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1446     ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
1447             "info->NameInformation.FileName is %s, expected %s.\n",
1448             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1449     ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
1450             + info->NameInformation.FileNameLength,
1451             "io.Information is %lu\n", io.Information );
1452
1453     CloseHandle( h );
1454     HeapFree( GetProcessHeap(), 0, info );
1455     HeapFree( GetProcessHeap(), 0, expected );
1456     HeapFree( GetProcessHeap(), 0, volume_prefix );
1457
1458     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1459     {
1460         skip("Not running on WoW64, skipping test.\n");
1461         HeapFree( GetProcessHeap(), 0, file_name );
1462         return;
1463     }
1464
1465     h = CreateFileW( file_name, GENERIC_READ,
1466             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1467             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1468     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1469     HeapFree( GetProcessHeap(), 0, file_name );
1470
1471     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1472     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1473     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1474
1475     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1476     ok(len == file_name_size - 1,
1477             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1478             len, file_name_size - 1);
1479
1480     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1481     ok(len, "GetVolumePathNameW failed.\n");
1482
1483     len = lstrlenW( volume_prefix );
1484     if (len && volume_prefix[len - 1] == '\\') --len;
1485     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1486     expected[file_name_size - len - 1] = '\0';
1487
1488     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1489     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1490
1491     memset( info, 0xcc, info_size );
1492     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1493     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1494     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1495     ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
1496             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1497
1498     CloseHandle( h );
1499     HeapFree( GetProcessHeap(), 0, info );
1500     HeapFree( GetProcessHeap(), 0, expected );
1501     HeapFree( GetProcessHeap(), 0, volume_prefix );
1502     HeapFree( GetProcessHeap(), 0, file_name );
1503 }
1504
1505 static void test_query_volume_information_file(void)
1506 {
1507     NTSTATUS status;
1508     HANDLE dir;
1509     WCHAR path[MAX_PATH];
1510     OBJECT_ATTRIBUTES attr;
1511     IO_STATUS_BLOCK io;
1512     UNICODE_STRING nameW;
1513     FILE_FS_VOLUME_INFORMATION *ffvi;
1514     BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1515
1516     GetWindowsDirectoryW( path, MAX_PATH );
1517     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1518     attr.Length = sizeof(attr);
1519     attr.RootDirectory = 0;
1520     attr.ObjectName = &nameW;
1521     attr.Attributes = OBJ_CASE_INSENSITIVE;
1522     attr.SecurityDescriptor = NULL;
1523     attr.SecurityQualityOfService = NULL;
1524
1525     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1526                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1527     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1528     pRtlFreeUnicodeString( &nameW );
1529
1530     ZeroMemory( buf, sizeof(buf) );
1531     U(io).Status = 0xdadadada;
1532     io.Information = 0xcacacaca;
1533
1534     status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
1535
1536     ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
1537
1538 todo_wine
1539 {
1540     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
1541     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
1542
1543     ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1544     "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1545      io.Information);
1546
1547     ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
1548     ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
1549     ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
1550 }
1551     ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
1552
1553     trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
1554
1555     CloseHandle( dir );
1556 }
1557
1558 static void test_NtCreateFile(void)
1559 {
1560     static const struct test_data
1561     {
1562         DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
1563     } td[] =
1564     {
1565     /* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1566     /* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
1567     /* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1568     /* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
1569     /* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
1570     /* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1571     /* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
1572     /* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1573     /* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1574     /* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
1575     /*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
1576     /*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1577     /*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1578     /*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
1579     /*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1580     /*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
1581     /*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
1582     /*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
1583     /*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
1584     };
1585     static const WCHAR fooW[] = {'f','o','o',0};
1586     static const WCHAR dotW[] = {'.',0};
1587     NTSTATUS status;
1588     HANDLE handle;
1589     WCHAR path[MAX_PATH];
1590     OBJECT_ATTRIBUTES attr;
1591     IO_STATUS_BLOCK io;
1592     UNICODE_STRING nameW;
1593     DWORD ret, i;
1594
1595     GetTempFileNameW(dotW, fooW, 0, path);
1596     DeleteFileW(path);
1597     pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
1598
1599     attr.Length = sizeof(attr);
1600     attr.RootDirectory = NULL;
1601     attr.ObjectName = &nameW;
1602     attr.Attributes = OBJ_CASE_INSENSITIVE;
1603     attr.SecurityDescriptor = NULL;
1604     attr.SecurityQualityOfService = NULL;
1605
1606     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1607     {
1608         status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
1609                                td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
1610                                td[i].disposition, 0, NULL, 0);
1611
1612         ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
1613
1614         if (!status)
1615         {
1616             ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
1617
1618             ret = GetFileAttributesW(path);
1619             ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
1620             /* FIXME: leave only 'else' case below once Wine is fixed */
1621             if (ret != td[i].attrib_out)
1622             {
1623             todo_wine
1624                 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
1625                 SetFileAttributesW(path, td[i].attrib_out);
1626             }
1627             else
1628                 ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
1629
1630             CloseHandle(handle);
1631         }
1632
1633         if (td[i].needs_cleanup)
1634         {
1635             SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
1636             DeleteFileW(path);
1637         }
1638     }
1639
1640     SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
1641     DeleteFileW( path );
1642 }
1643
1644 START_TEST(file)
1645 {
1646     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1647     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1648     if (!hntdll)
1649     {
1650         skip("not running on NT, skipping test\n");
1651         return;
1652     }
1653
1654     pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
1655     pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
1656
1657     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
1658     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
1659     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
1660     pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
1661     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
1662     pNtCreateFile           = (void *)GetProcAddress(hntdll, "NtCreateFile");
1663     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
1664     pNtDeleteFile           = (void *)GetProcAddress(hntdll, "NtDeleteFile");
1665     pNtReadFile             = (void *)GetProcAddress(hntdll, "NtReadFile");
1666     pNtWriteFile            = (void *)GetProcAddress(hntdll, "NtWriteFile");
1667     pNtCancelIoFile         = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
1668     pNtCancelIoFileEx       = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
1669     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
1670     pNtCreateIoCompletion   = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
1671     pNtOpenIoCompletion     = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
1672     pNtQueryIoCompletion    = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
1673     pNtRemoveIoCompletion   = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
1674     pNtSetIoCompletion      = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
1675     pNtSetInformationFile   = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
1676     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
1677     pNtQueryDirectoryFile   = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
1678     pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
1679
1680     test_NtCreateFile();
1681     create_file_test();
1682     open_file_test();
1683     delete_file_test();
1684     read_file_test();
1685     append_file_test();
1686     nt_mailslot_test();
1687     test_iocompletion();
1688     test_file_basic_information();
1689     test_file_all_information();
1690     test_file_both_information();
1691     test_file_name_information();
1692     test_file_all_name_information();
1693     test_query_volume_information_file();
1694 }