mshtml: COM cleanup for the IHTMLDOMNode iface.
[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     BOOL ret;
460
461     buffer[0] = 1;
462
463     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
464
465     /* try read with no data */
466     U(iosb).Status = 0xdeadbabe;
467     iosb.Information = 0xdeadbeef;
468     ok( is_signaled( read ), "read handle is not signaled\n" );
469     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
470     ok( status == STATUS_PENDING, "wrong status %x\n", status );
471     ok( !is_signaled( read ), "read handle is signaled\n" );
472     ok( !is_signaled( event ), "event 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( is_signaled( event ), "event is not signaled\n" );
483     ok( !apc_count, "apc was called\n" );
484     apc_count = 0;
485     SleepEx( 1, FALSE ); /* non-alertable sleep */
486     ok( !apc_count, "apc was called\n" );
487     SleepEx( 1, TRUE ); /* alertable sleep */
488     ok( apc_count == 1, "apc not called\n" );
489
490     /* with no event, the pipe handle itself gets signaled */
491     apc_count = 0;
492     U(iosb).Status = 0xdeadbabe;
493     iosb.Information = 0xdeadbeef;
494     ok( !is_signaled( read ), "read handle is not signaled\n" );
495     status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
496     ok( status == STATUS_PENDING, "wrong status %x\n", status );
497     ok( !is_signaled( read ), "read handle is signaled\n" );
498     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
499     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
500     ok( !apc_count, "apc was called\n" );
501     WriteFile( write, buffer, 1, &written, NULL );
502     /* iosb updated here by async i/o */
503     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
504     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
505     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
506     ok( is_signaled( read ), "read handle is signaled\n" );
507     ok( !apc_count, "apc was called\n" );
508     apc_count = 0;
509     SleepEx( 1, FALSE ); /* non-alertable sleep */
510     ok( !apc_count, "apc was called\n" );
511     SleepEx( 1, TRUE ); /* alertable sleep */
512     ok( apc_count == 1, "apc not called\n" );
513
514     /* now read with data ready */
515     apc_count = 0;
516     U(iosb).Status = 0xdeadbabe;
517     iosb.Information = 0xdeadbeef;
518     ResetEvent( event );
519     WriteFile( write, buffer, 1, &written, NULL );
520     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
521     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
522     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
523     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
524     ok( is_signaled( event ), "event is not signaled\n" );
525     ok( !apc_count, "apc was called\n" );
526     SleepEx( 1, FALSE ); /* non-alertable sleep */
527     ok( !apc_count, "apc was called\n" );
528     SleepEx( 1, TRUE ); /* alertable sleep */
529     ok( apc_count == 1, "apc not called\n" );
530
531     /* try read with no data */
532     apc_count = 0;
533     U(iosb).Status = 0xdeadbabe;
534     iosb.Information = 0xdeadbeef;
535     ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
536     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
537     ok( status == STATUS_PENDING, "wrong status %x\n", status );
538     ok( !is_signaled( event ), "event is signaled\n" );
539     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
540     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
541     ok( !apc_count, "apc was called\n" );
542     WriteFile( write, buffer, 1, &written, NULL );
543     /* partial read is good enough */
544     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
545     ok( is_signaled( event ), "event is signaled\n" );
546     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
547     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
548     ok( !apc_count, "apc was called\n" );
549     SleepEx( 1, TRUE ); /* alertable sleep */
550     ok( apc_count == 1, "apc was not called\n" );
551
552     /* read from disconnected pipe */
553     apc_count = 0;
554     U(iosb).Status = 0xdeadbabe;
555     iosb.Information = 0xdeadbeef;
556     CloseHandle( write );
557     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
558     ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
559     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
560     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
561     ok( !is_signaled( event ), "event is signaled\n" );
562     ok( !apc_count, "apc was called\n" );
563     SleepEx( 1, TRUE ); /* alertable sleep */
564     ok( !apc_count, "apc was called\n" );
565     CloseHandle( read );
566
567     /* read from closed handle */
568     apc_count = 0;
569     U(iosb).Status = 0xdeadbabe;
570     iosb.Information = 0xdeadbeef;
571     SetEvent( event );
572     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
573     ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
574     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
575     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
576     ok( is_signaled( event ), "event is signaled\n" );  /* not reset on invalid handle */
577     ok( !apc_count, "apc was called\n" );
578     SleepEx( 1, TRUE ); /* alertable sleep */
579     ok( !apc_count, "apc was called\n" );
580
581     /* disconnect while async read is in progress */
582     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
583     apc_count = 0;
584     U(iosb).Status = 0xdeadbabe;
585     iosb.Information = 0xdeadbeef;
586     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
587     ok( status == STATUS_PENDING, "wrong status %x\n", status );
588     ok( !is_signaled( event ), "event is signaled\n" );
589     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
590     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
591     ok( !apc_count, "apc was called\n" );
592     CloseHandle( write );
593     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
594     ok( U(iosb).Status == STATUS_PIPE_BROKEN, "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     ok( !apc_count, "apc was called\n" );
598     SleepEx( 1, TRUE ); /* alertable sleep */
599     ok( apc_count == 1, "apc was not called\n" );
600     CloseHandle( read );
601
602     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
603     ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
604     ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
605
606     apc_count = 0;
607     U(iosb).Status = 0xdeadbabe;
608     iosb.Information = 0xdeadbeef;
609     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
610     ok( status == STATUS_PENDING, "wrong status %x\n", status );
611     ok( !is_signaled( event ), "event is signaled\n" );
612     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
613     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
614     ok( !apc_count, "apc was called\n" );
615     /* Cancel by other handle */
616     status = pNtCancelIoFile( read, &iosb2 );
617     ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
618     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
619     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
620     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
621     ok( is_signaled( event ), "event is signaled\n" );
622     todo_wine ok( !apc_count, "apc was called\n" );
623     SleepEx( 1, TRUE ); /* alertable sleep */
624     ok( apc_count == 1, "apc was not called\n" );
625
626     apc_count = 0;
627     U(iosb).Status = 0xdeadbabe;
628     iosb.Information = 0xdeadbeef;
629     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
630     ok( status == STATUS_PENDING, "wrong status %x\n", status );
631     ok( !is_signaled( event ), "event is signaled\n" );
632     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
633     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
634     ok( !apc_count, "apc was called\n" );
635     /* Close queued handle */
636     CloseHandle( read );
637     SleepEx( 1, TRUE ); /* alertable sleep */
638     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
639     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
640     status = pNtCancelIoFile( read, &iosb2 );
641     ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
642     status = pNtCancelIoFile( handle, &iosb2 );
643     ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
644     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
645     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
646     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
647     ok( is_signaled( event ), "event is signaled\n" );
648     todo_wine ok( !apc_count, "apc was called\n" );
649     SleepEx( 1, TRUE ); /* alertable sleep */
650     ok( apc_count == 1, "apc was not called\n" );
651     CloseHandle( handle );
652     CloseHandle( write );
653
654     if (pNtCancelIoFileEx)
655     {
656         /* Basic Cancel Ex */
657         if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
658
659         apc_count = 0;
660         U(iosb).Status = 0xdeadbabe;
661         iosb.Information = 0xdeadbeef;
662         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
663         ok( status == STATUS_PENDING, "wrong status %x\n", status );
664         ok( !is_signaled( event ), "event is signaled\n" );
665         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
666         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
667         ok( !apc_count, "apc was called\n" );
668         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
669         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
670         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
671         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
672         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
673         ok( is_signaled( event ), "event is signaled\n" );
674         todo_wine ok( !apc_count, "apc was called\n" );
675         SleepEx( 1, TRUE ); /* alertable sleep */
676         ok( apc_count == 1, "apc was not called\n" );
677
678         /* Duplicate iosb */
679         apc_count = 0;
680         U(iosb).Status = 0xdeadbabe;
681         iosb.Information = 0xdeadbeef;
682         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
683         ok( status == STATUS_PENDING, "wrong status %x\n", status );
684         ok( !is_signaled( event ), "event is signaled\n" );
685         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
686         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
687         ok( !apc_count, "apc was called\n" );
688         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
689         ok( status == STATUS_PENDING, "wrong status %x\n", status );
690         ok( !is_signaled( event ), "event is signaled\n" );
691         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
692         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
693         ok( !apc_count, "apc was called\n" );
694         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
695         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
696         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
697         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
698         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
699         ok( is_signaled( event ), "event is signaled\n" );
700         todo_wine ok( !apc_count, "apc was called\n" );
701         SleepEx( 1, TRUE ); /* alertable sleep */
702         ok( apc_count == 2, "apc was not called\n" );
703
704         CloseHandle( read );
705         CloseHandle( write );
706     }
707
708     /* now try a real file */
709     if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
710     apc_count = 0;
711     U(iosb).Status = 0xdeadbabe;
712     iosb.Information = 0xdeadbeef;
713     offset.QuadPart = 0;
714     ResetEvent( event );
715     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
716     ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
717     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
718     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
719     ok( is_signaled( event ), "event is signaled\n" );
720     ok( !apc_count, "apc was called\n" );
721     SleepEx( 1, TRUE ); /* alertable sleep */
722     ok( apc_count == 1, "apc was not called\n" );
723
724     apc_count = 0;
725     U(iosb).Status = 0xdeadbabe;
726     iosb.Information = 0xdeadbeef;
727     offset.QuadPart = 0;
728     ResetEvent( event );
729     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
730     ok( status == STATUS_SUCCESS ||
731         status == STATUS_PENDING, /* vista */
732         "wrong status %x\n", status );
733     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
734     ok( iosb.Information == strlen(text), "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 == 1, "apc was not called\n" );
739
740     /* read beyond eof */
741     apc_count = 0;
742     U(iosb).Status = 0xdeadbabe;
743     iosb.Information = 0xdeadbeef;
744     offset.QuadPart = strlen(text) + 2;
745     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
746     if (status == STATUS_PENDING)  /* vista */
747     {
748         ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
749         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
750         ok( is_signaled( event ), "event is signaled\n" );
751         ok( !apc_count, "apc was called\n" );
752         SleepEx( 1, TRUE ); /* alertable sleep */
753         ok( apc_count == 1, "apc was not called\n" );
754     }
755     else
756     {
757         ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
758         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
759         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
760         ok( !is_signaled( event ), "event is signaled\n" );
761         ok( !apc_count, "apc was called\n" );
762         SleepEx( 1, TRUE ); /* alertable sleep */
763         ok( !apc_count, "apc was called\n" );
764     }
765     CloseHandle( handle );
766
767     /* now a non-overlapped file */
768     if (!(handle = create_temp_file(0))) return;
769     apc_count = 0;
770     U(iosb).Status = 0xdeadbabe;
771     iosb.Information = 0xdeadbeef;
772     offset.QuadPart = 0;
773     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
774     ok( status == STATUS_END_OF_FILE ||
775         status == STATUS_SUCCESS ||
776         status == STATUS_PENDING,  /* vista */
777         "wrong status %x\n", status );
778     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
779     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
780     ok( is_signaled( event ), "event is signaled\n" );
781     ok( !apc_count, "apc was called\n" );
782     SleepEx( 1, TRUE ); /* alertable sleep */
783     ok( apc_count == 1, "apc was not called\n" );
784
785     apc_count = 0;
786     U(iosb).Status = 0xdeadbabe;
787     iosb.Information = 0xdeadbeef;
788     offset.QuadPart = 0;
789     ResetEvent( event );
790     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
791     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
792     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
793     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
794     ok( is_signaled( event ), "event is signaled\n" );
795     ok( !apc_count, "apc was called\n" );
796     SleepEx( 1, TRUE ); /* alertable sleep */
797     todo_wine ok( !apc_count, "apc was called\n" );
798
799     /* read beyond eof */
800     apc_count = 0;
801     U(iosb).Status = 0xdeadbabe;
802     iosb.Information = 0xdeadbeef;
803     offset.QuadPart = strlen(text) + 2;
804     ResetEvent( event );
805     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
806     ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
807     todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
808     todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
809     todo_wine ok( is_signaled( event ), "event is not signaled\n" );
810     ok( !apc_count, "apc was called\n" );
811     SleepEx( 1, TRUE ); /* alertable sleep */
812     ok( !apc_count, "apc was called\n" );
813
814     CloseHandle( handle );
815
816     CloseHandle( event );
817 }
818
819 static void nt_mailslot_test(void)
820 {
821     HANDLE hslot;
822     ACCESS_MASK DesiredAccess;
823     OBJECT_ATTRIBUTES attr;
824
825     ULONG CreateOptions;
826     ULONG MailslotQuota;
827     ULONG MaxMessageSize;
828     LARGE_INTEGER TimeOut;
829     IO_STATUS_BLOCK IoStatusBlock;
830     NTSTATUS rc;
831     UNICODE_STRING str;
832     WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
833                         'R',':','\\','F','R','E','D','\0' };
834
835     TimeOut.QuadPart = -1;
836
837     pRtlInitUnicodeString(&str, buffer1);
838     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
839     CreateOptions = MailslotQuota = MaxMessageSize = 0;
840     DesiredAccess = GENERIC_READ;
841
842     /*
843      * Check for NULL pointer handling
844      */
845     rc = pNtCreateMailslotFile(NULL, DesiredAccess,
846          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
847          &TimeOut);
848     ok( rc == STATUS_ACCESS_VIOLATION ||
849         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
850         "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
851
852     /*
853      * Test to see if the Timeout can be NULL
854      */
855     hslot = (HANDLE)0xdeadbeef;
856     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
857          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
858          NULL);
859     ok( rc == STATUS_SUCCESS ||
860         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
861         "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
862     ok( hslot != 0, "Handle is invalid\n");
863
864     if  ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
865
866     /*
867      * Test that the length field is checked properly
868      */
869     attr.Length = 0;
870     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
871          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
872          &TimeOut);
873     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
874
875     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
876
877     attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
878     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
879          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
880          &TimeOut);
881     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
882
883     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
884
885     /*
886      * Test handling of a NULL unicode string in ObjectName
887      */
888     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
889     attr.ObjectName = NULL;
890     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
891          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
892          &TimeOut);
893     ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
894         rc == STATUS_INVALID_PARAMETER,
895         "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
896
897     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
898
899     /*
900      * Test a valid call
901      */
902     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
903     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
904          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
905          &TimeOut);
906     ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
907     ok( hslot != 0, "Handle is invalid\n");
908
909     rc = pNtClose(hslot);
910     ok( rc == STATUS_SUCCESS, "NtClose failed\n");
911 }
912
913 static void test_iocp_setcompletion(HANDLE h)
914 {
915     NTSTATUS res;
916     ULONG count;
917
918     res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
919     ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
920
921     count = get_pending_msgs(h);
922     ok( count == 1, "Unexpected msg count: %d\n", count );
923
924     if (get_msg(h))
925     {
926         ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
927         ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
928         ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
929         ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
930     }
931
932     count = get_pending_msgs(h);
933     ok( !count, "Unexpected msg count: %d\n", count );
934 }
935
936 static void test_iocp_fileio(HANDLE h)
937 {
938     static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
939
940     IO_STATUS_BLOCK iosb;
941     FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
942     HANDLE hPipeSrv, hPipeClt;
943     NTSTATUS res;
944
945     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
946     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
947     if (hPipeSrv != INVALID_HANDLE_VALUE )
948     {
949         hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
950         ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
951         if (hPipeClt != INVALID_HANDLE_VALUE)
952         {
953             U(iosb).Status = 0xdeadbeef;
954             res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
955             ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
956             ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
957                 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
958             CloseHandle(hPipeClt);
959         }
960         CloseHandle( hPipeSrv );
961     }
962
963     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
964     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
965     if (hPipeSrv == INVALID_HANDLE_VALUE )
966         return;
967
968     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
969     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
970     if (hPipeClt != INVALID_HANDLE_VALUE)
971     {
972         OVERLAPPED o = {0,};
973         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
974         DWORD read;
975         long count;
976
977         U(iosb).Status = 0xdeadbeef;
978         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
979         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
980         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
981
982         memset( send_buf, 0, TEST_BUF_LEN );
983         memset( recv_buf, 0xde, TEST_BUF_LEN );
984         count = get_pending_msgs(h);
985         ok( !count, "Unexpected msg count: %ld\n", count );
986         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
987         count = get_pending_msgs(h);
988         ok( !count, "Unexpected msg count: %ld\n", count );
989         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
990
991         if (get_msg(h))
992         {
993             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
994             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
995             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
996             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
997             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] );
998         }
999         count = get_pending_msgs(h);
1000         ok( !count, "Unexpected msg count: %ld\n", count );
1001
1002         memset( send_buf, 0, TEST_BUF_LEN );
1003         memset( recv_buf, 0xde, TEST_BUF_LEN );
1004         WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1005         count = get_pending_msgs(h);
1006         ok( !count, "Unexpected msg count: %ld\n", count );
1007         ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1008         count = get_pending_msgs(h);
1009         ok( count == 1, "Unexpected msg count: %ld\n", count );
1010         if (get_msg(h))
1011         {
1012             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1013             ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1014             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1015             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1016             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] );
1017         }
1018
1019         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1020         CloseHandle( hPipeSrv );
1021         count = get_pending_msgs(h);
1022         ok( count == 1, "Unexpected msg count: %ld\n", count );
1023         if (get_msg(h))
1024         {
1025             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1026             ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1027             /* wine sends wrong status here */
1028             todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1029             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1030         }
1031     }
1032
1033     CloseHandle( hPipeClt );
1034 }
1035
1036 static void test_file_basic_information(void)
1037 {
1038     IO_STATUS_BLOCK io;
1039     FILE_BASIC_INFORMATION fbi;
1040     HANDLE h;
1041     int res;
1042     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1043
1044     if (!(h = create_temp_file(0))) return;
1045
1046     /* Check default first */
1047     memset(&fbi, 0, sizeof(fbi));
1048     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1049     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1050     ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1051          "attribute %x not expected\n", fbi.FileAttributes );
1052
1053     /* Then SYSTEM */
1054     /* Clear fbi to avoid setting times */
1055     memset(&fbi, 0, sizeof(fbi));
1056     fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1057     U(io).Status = 0xdeadbeef;
1058     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1059     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1060     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1061
1062     memset(&fbi, 0, sizeof(fbi));
1063     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1064     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1065     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1066
1067     /* Then HIDDEN */
1068     memset(&fbi, 0, sizeof(fbi));
1069     fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1070     U(io).Status = 0xdeadbeef;
1071     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1072     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1073     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1074
1075     memset(&fbi, 0, sizeof(fbi));
1076     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1077     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1078     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1079
1080     /* Check NORMAL last of all (to make sure we can clear attributes) */
1081     memset(&fbi, 0, sizeof(fbi));
1082     fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1083     U(io).Status = 0xdeadbeef;
1084     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1085     ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1086     ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1087
1088     memset(&fbi, 0, sizeof(fbi));
1089     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1090     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1091     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1092
1093     CloseHandle( h );
1094 }
1095
1096 static void test_file_all_information(void)
1097 {
1098     IO_STATUS_BLOCK io;
1099     /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1100      * buffer at the end.  Vista objects with STATUS_BUFFER_OVERFLOW if you
1101      * don't leave enough room there.
1102      */
1103     struct {
1104       FILE_ALL_INFORMATION fai;
1105       WCHAR buf[256];
1106     } fai_buf;
1107     HANDLE h;
1108     int res;
1109     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1110
1111     if (!(h = create_temp_file(0))) return;
1112
1113     /* Check default first */
1114     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1115     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1116     ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1117          "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1118
1119     /* Then SYSTEM */
1120     /* Clear fbi to avoid setting times */
1121     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1122     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1123     U(io).Status = 0xdeadbeef;
1124     res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1125     ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1126     todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1127     U(io).Status = 0xdeadbeef;
1128     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1129     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1130     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1131
1132     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1133     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1134     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1135     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 );
1136
1137     /* Then HIDDEN */
1138     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1139     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1140     U(io).Status = 0xdeadbeef;
1141     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1142     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1143     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1144
1145     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1146     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1147     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1148     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 );
1149
1150     /* Check NORMAL last of all (to make sure we can clear attributes) */
1151     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1152     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1153     U(io).Status = 0xdeadbeef;
1154     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1155     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1156     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1157
1158     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1159     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1160     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1161     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 );
1162
1163     CloseHandle( h );
1164 }
1165
1166 static void test_file_both_information(void)
1167 {
1168     IO_STATUS_BLOCK io;
1169     FILE_BOTH_DIR_INFORMATION fbi;
1170     HANDLE h;
1171     int res;
1172
1173     if (!(h = create_temp_file(0))) return;
1174
1175     memset(&fbi, 0, sizeof(fbi));
1176     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
1177     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
1178
1179     CloseHandle( h );
1180 }
1181
1182 static void test_iocompletion(void)
1183 {
1184     HANDLE h = INVALID_HANDLE_VALUE;
1185     NTSTATUS res;
1186
1187     res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
1188
1189     ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
1190     ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
1191
1192     if ( h && h != INVALID_HANDLE_VALUE)
1193     {
1194         test_iocp_setcompletion(h);
1195         test_iocp_fileio(h);
1196         pNtClose(h);
1197     }
1198 }
1199
1200 static void test_file_name_information(void)
1201 {
1202     WCHAR *file_name, *volume_prefix, *expected;
1203     FILE_NAME_INFORMATION *info;
1204     ULONG old_redir = 1, tmp;
1205     UINT file_name_size;
1206     IO_STATUS_BLOCK io;
1207     UINT info_size;
1208     HRESULT hr;
1209     HANDLE h;
1210     UINT len;
1211
1212     /* GetVolumePathName is not present before w2k */
1213     if (!pGetVolumePathNameW) {
1214         win_skip("GetVolumePathNameW not found\n");
1215         return;
1216     }
1217
1218     file_name_size = GetSystemDirectoryW( NULL, 0 );
1219     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1220     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1221     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1222
1223     len = GetSystemDirectoryW( file_name, file_name_size );
1224     ok(len == file_name_size - 1,
1225             "GetSystemDirectoryW returned %u, expected %u.\n",
1226             len, file_name_size - 1);
1227
1228     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1229     ok(len, "GetVolumePathNameW failed.\n");
1230
1231     len = lstrlenW( volume_prefix );
1232     if (len && volume_prefix[len - 1] == '\\') --len;
1233     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1234     expected[file_name_size - len - 1] = '\0';
1235
1236     /* A bit more than we actually need, but it keeps the calculation simple. */
1237     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1238     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1239
1240     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1241     h = CreateFileW( file_name, GENERIC_READ,
1242             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1243             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1244     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1245     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1246
1247     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
1248     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
1249
1250     memset( info, 0xcc, info_size );
1251     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
1252     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1253             hr, STATUS_BUFFER_OVERFLOW);
1254     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1255             U(io).Status, STATUS_BUFFER_OVERFLOW);
1256     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1257     ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1258     ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1259             "info->FileName[1] is %p, expected %p.\n",
1260             CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1261     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1262
1263     memset( info, 0xcc, info_size );
1264     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1265     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1266     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1267     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1268     ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1269        info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1270     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1271     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1272             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1273     ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1274             "io.Information is %lu, expected %u.\n",
1275             io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1276
1277     CloseHandle( h );
1278     HeapFree( GetProcessHeap(), 0, info );
1279     HeapFree( GetProcessHeap(), 0, expected );
1280     HeapFree( GetProcessHeap(), 0, volume_prefix );
1281
1282     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1283     {
1284         skip("Not running on WoW64, skipping test.\n");
1285         HeapFree( GetProcessHeap(), 0, file_name );
1286         return;
1287     }
1288
1289     h = CreateFileW( file_name, GENERIC_READ,
1290             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1291             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1292     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1293     HeapFree( GetProcessHeap(), 0, file_name );
1294
1295     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1296     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1297     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1298
1299     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1300     ok(len == file_name_size - 1,
1301             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1302             len, file_name_size - 1);
1303
1304     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1305     ok(len, "GetVolumePathNameW failed.\n");
1306
1307     len = lstrlenW( volume_prefix );
1308     if (len && volume_prefix[len - 1] == '\\') --len;
1309     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1310     expected[file_name_size - len - 1] = '\0';
1311
1312     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1313     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1314
1315     memset( info, 0xcc, info_size );
1316     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1317     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1318     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1319     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1320             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1321
1322     CloseHandle( h );
1323     HeapFree( GetProcessHeap(), 0, info );
1324     HeapFree( GetProcessHeap(), 0, expected );
1325     HeapFree( GetProcessHeap(), 0, volume_prefix );
1326     HeapFree( GetProcessHeap(), 0, file_name );
1327 }
1328
1329 static void test_file_all_name_information(void)
1330 {
1331     WCHAR *file_name, *volume_prefix, *expected;
1332     FILE_ALL_INFORMATION *info;
1333     ULONG old_redir = 1, tmp;
1334     UINT file_name_size;
1335     IO_STATUS_BLOCK io;
1336     UINT info_size;
1337     HRESULT hr;
1338     HANDLE h;
1339     UINT len;
1340
1341     /* GetVolumePathName is not present before w2k */
1342     if (!pGetVolumePathNameW) {
1343         win_skip("GetVolumePathNameW not found\n");
1344         return;
1345     }
1346
1347     file_name_size = GetSystemDirectoryW( NULL, 0 );
1348     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1349     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1350     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1351
1352     len = GetSystemDirectoryW( file_name, file_name_size );
1353     ok(len == file_name_size - 1,
1354             "GetSystemDirectoryW returned %u, expected %u.\n",
1355             len, file_name_size - 1);
1356
1357     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1358     ok(len, "GetVolumePathNameW failed.\n");
1359
1360     len = lstrlenW( volume_prefix );
1361     if (len && volume_prefix[len - 1] == '\\') --len;
1362     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1363     expected[file_name_size - len - 1] = '\0';
1364
1365     /* A bit more than we actually need, but it keeps the calculation simple. */
1366     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1367     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1368
1369     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1370     h = CreateFileW( file_name, GENERIC_READ,
1371             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1372             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1373     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1374     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1375
1376     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
1377     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
1378             hr, STATUS_INFO_LENGTH_MISMATCH);
1379
1380     memset( info, 0xcc, info_size );
1381     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
1382     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1383             hr, STATUS_BUFFER_OVERFLOW);
1384     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1385             U(io).Status, STATUS_BUFFER_OVERFLOW);
1386     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1387        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1388     ok(info->NameInformation.FileName[2] == 0xcccc,
1389             "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
1390     ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1391             "info->NameInformation.FileName[1] is %p, expected %p.\n",
1392             CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1393     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1394
1395     memset( info, 0xcc, info_size );
1396     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1397     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1398     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1399     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1400        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1401     ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
1402        "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1403        info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
1404     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1405     ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
1406             "info->NameInformation.FileName is %s, expected %s.\n",
1407             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1408     ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
1409             + info->NameInformation.FileNameLength,
1410             "io.Information is %lu\n", io.Information );
1411
1412     CloseHandle( h );
1413     HeapFree( GetProcessHeap(), 0, info );
1414     HeapFree( GetProcessHeap(), 0, expected );
1415     HeapFree( GetProcessHeap(), 0, volume_prefix );
1416
1417     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1418     {
1419         skip("Not running on WoW64, skipping test.\n");
1420         HeapFree( GetProcessHeap(), 0, file_name );
1421         return;
1422     }
1423
1424     h = CreateFileW( file_name, GENERIC_READ,
1425             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1426             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1427     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1428     HeapFree( GetProcessHeap(), 0, file_name );
1429
1430     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1431     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1432     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1433
1434     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1435     ok(len == file_name_size - 1,
1436             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1437             len, file_name_size - 1);
1438
1439     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1440     ok(len, "GetVolumePathNameW failed.\n");
1441
1442     len = lstrlenW( volume_prefix );
1443     if (len && volume_prefix[len - 1] == '\\') --len;
1444     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1445     expected[file_name_size - len - 1] = '\0';
1446
1447     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1448     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1449
1450     memset( info, 0xcc, info_size );
1451     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1452     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1453     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1454     ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
1455             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1456
1457     CloseHandle( h );
1458     HeapFree( GetProcessHeap(), 0, info );
1459     HeapFree( GetProcessHeap(), 0, expected );
1460     HeapFree( GetProcessHeap(), 0, volume_prefix );
1461     HeapFree( GetProcessHeap(), 0, file_name );
1462 }
1463
1464 static void test_query_volume_information_file(void)
1465 {
1466     NTSTATUS status;
1467     HANDLE dir;
1468     WCHAR path[MAX_PATH];
1469     OBJECT_ATTRIBUTES attr;
1470     IO_STATUS_BLOCK io;
1471     UNICODE_STRING nameW;
1472     FILE_FS_VOLUME_INFORMATION *ffvi;
1473     BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1474
1475     GetWindowsDirectoryW( path, MAX_PATH );
1476     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1477     attr.Length = sizeof(attr);
1478     attr.RootDirectory = 0;
1479     attr.ObjectName = &nameW;
1480     attr.Attributes = OBJ_CASE_INSENSITIVE;
1481     attr.SecurityDescriptor = NULL;
1482     attr.SecurityQualityOfService = NULL;
1483
1484     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1485                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1486     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1487     pRtlFreeUnicodeString( &nameW );
1488
1489     ZeroMemory( buf, sizeof(buf) );
1490     U(io).Status = 0xdadadada;
1491     io.Information = 0xcacacaca;
1492
1493     status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
1494
1495     ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
1496
1497 todo_wine
1498 {
1499     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
1500     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
1501
1502     ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1503     "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1504      io.Information);
1505
1506     ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
1507     ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
1508     ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
1509 }
1510     ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "expected %d, got %d\n",
1511     lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), ffvi->VolumeLabelLength);
1512
1513     trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
1514
1515     CloseHandle( dir );
1516 }
1517
1518 START_TEST(file)
1519 {
1520     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1521     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1522     if (!hntdll)
1523     {
1524         skip("not running on NT, skipping test\n");
1525         return;
1526     }
1527
1528     pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
1529     pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
1530
1531     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
1532     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
1533     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
1534     pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
1535     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
1536     pNtCreateFile           = (void *)GetProcAddress(hntdll, "NtCreateFile");
1537     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
1538     pNtDeleteFile           = (void *)GetProcAddress(hntdll, "NtDeleteFile");
1539     pNtReadFile             = (void *)GetProcAddress(hntdll, "NtReadFile");
1540     pNtWriteFile            = (void *)GetProcAddress(hntdll, "NtWriteFile");
1541     pNtCancelIoFile         = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
1542     pNtCancelIoFileEx       = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
1543     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
1544     pNtCreateIoCompletion   = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
1545     pNtOpenIoCompletion     = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
1546     pNtQueryIoCompletion    = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
1547     pNtRemoveIoCompletion   = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
1548     pNtSetIoCompletion      = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
1549     pNtSetInformationFile   = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
1550     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
1551     pNtQueryDirectoryFile   = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
1552     pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
1553
1554     create_file_test();
1555     open_file_test();
1556     delete_file_test();
1557     read_file_test();
1558     nt_mailslot_test();
1559     test_iocompletion();
1560     test_file_basic_information();
1561     test_file_all_information();
1562     test_file_both_information();
1563     test_file_name_information();
1564     test_file_all_name_information();
1565     test_query_volume_information_file();
1566 }