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