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