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