mshtml: Added IHTMLWindow2::focus implementation.
[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 append_file_test(void)
820 {
821     const char text[] = "foobar";
822     HANDLE handle;
823     NTSTATUS status;
824     IO_STATUS_BLOCK iosb;
825     DWORD written;
826     char buffer[128];
827
828     GetTempFileNameA( ".", "foo", 0, buffer );
829     /* It is possible to open a file with only FILE_APPEND_DATA access flags.
830        It matches the O_WRONLY|O_APPEND open() posix behavior */
831     handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, CREATE_ALWAYS,
832                          FILE_FLAG_DELETE_ON_CLOSE, 0);
833     ok( handle != INVALID_HANDLE_VALUE, "Failed to create a temp file in FILE_APPEND_DATA mode.\n" );
834     if(handle == INVALID_HANDLE_VALUE)
835     {
836         skip("Couldn't create a temporary file, skipping FILE_APPEND_DATA test\n");
837         return;
838     }
839
840     U(iosb).Status = STATUS_PENDING;
841     iosb.Information = 0;
842
843     status = NtWriteFile(handle, NULL, NULL, NULL, &iosb,
844                          text, sizeof(text), NULL, NULL);
845
846     if (status == STATUS_PENDING)
847     {
848         WaitForSingleObject( handle, INFINITE );
849         status = U(iosb).Status;
850     }
851     written = iosb.Information;
852
853     todo_wine
854     ok(status == STATUS_SUCCESS && written == sizeof(text), "FILE_APPEND_DATA NtWriteFile failed\n");
855
856     CloseHandle(handle);
857 }
858
859 static void nt_mailslot_test(void)
860 {
861     HANDLE hslot;
862     ACCESS_MASK DesiredAccess;
863     OBJECT_ATTRIBUTES attr;
864
865     ULONG CreateOptions;
866     ULONG MailslotQuota;
867     ULONG MaxMessageSize;
868     LARGE_INTEGER TimeOut;
869     IO_STATUS_BLOCK IoStatusBlock;
870     NTSTATUS rc;
871     UNICODE_STRING str;
872     WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
873                         'R',':','\\','F','R','E','D','\0' };
874
875     TimeOut.QuadPart = -1;
876
877     pRtlInitUnicodeString(&str, buffer1);
878     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
879     CreateOptions = MailslotQuota = MaxMessageSize = 0;
880     DesiredAccess = GENERIC_READ;
881
882     /*
883      * Check for NULL pointer handling
884      */
885     rc = pNtCreateMailslotFile(NULL, DesiredAccess,
886          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
887          &TimeOut);
888     ok( rc == STATUS_ACCESS_VIOLATION ||
889         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
890         "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
891
892     /*
893      * Test to see if the Timeout can be NULL
894      */
895     hslot = (HANDLE)0xdeadbeef;
896     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
897          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
898          NULL);
899     ok( rc == STATUS_SUCCESS ||
900         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
901         "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
902     ok( hslot != 0, "Handle is invalid\n");
903
904     if  ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
905
906     /*
907      * Test that the length field is checked properly
908      */
909     attr.Length = 0;
910     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
911          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
912          &TimeOut);
913     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
914
915     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
916
917     attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
918     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
919          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
920          &TimeOut);
921     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
922
923     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
924
925     /*
926      * Test handling of a NULL unicode string in ObjectName
927      */
928     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
929     attr.ObjectName = NULL;
930     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
931          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
932          &TimeOut);
933     ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
934         rc == STATUS_INVALID_PARAMETER,
935         "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
936
937     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
938
939     /*
940      * Test a valid call
941      */
942     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
943     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
944          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
945          &TimeOut);
946     ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
947     ok( hslot != 0, "Handle is invalid\n");
948
949     rc = pNtClose(hslot);
950     ok( rc == STATUS_SUCCESS, "NtClose failed\n");
951 }
952
953 static void test_iocp_setcompletion(HANDLE h)
954 {
955     NTSTATUS res;
956     ULONG count;
957
958     res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
959     ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
960
961     count = get_pending_msgs(h);
962     ok( count == 1, "Unexpected msg count: %d\n", count );
963
964     if (get_msg(h))
965     {
966         ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
967         ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
968         ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
969         ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
970     }
971
972     count = get_pending_msgs(h);
973     ok( !count, "Unexpected msg count: %d\n", count );
974 }
975
976 static void test_iocp_fileio(HANDLE h)
977 {
978     static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
979
980     IO_STATUS_BLOCK iosb;
981     FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
982     HANDLE hPipeSrv, hPipeClt;
983     NTSTATUS res;
984
985     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
986     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
987     if (hPipeSrv != INVALID_HANDLE_VALUE )
988     {
989         hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
990         ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
991         if (hPipeClt != INVALID_HANDLE_VALUE)
992         {
993             U(iosb).Status = 0xdeadbeef;
994             res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
995             ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
996             ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
997                 "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
998             CloseHandle(hPipeClt);
999         }
1000         CloseHandle( hPipeSrv );
1001     }
1002
1003     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
1004     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
1005     if (hPipeSrv == INVALID_HANDLE_VALUE )
1006         return;
1007
1008     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
1009     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
1010     if (hPipeClt != INVALID_HANDLE_VALUE)
1011     {
1012         OVERLAPPED o = {0,};
1013         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
1014         DWORD read;
1015         long count;
1016
1017         U(iosb).Status = 0xdeadbeef;
1018         res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
1019         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
1020         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
1021
1022         memset( send_buf, 0, TEST_BUF_LEN );
1023         memset( recv_buf, 0xde, TEST_BUF_LEN );
1024         count = get_pending_msgs(h);
1025         ok( !count, "Unexpected msg count: %ld\n", count );
1026         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1027         count = get_pending_msgs(h);
1028         ok( !count, "Unexpected msg count: %ld\n", count );
1029         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
1030
1031         if (get_msg(h))
1032         {
1033             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1034             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1035             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1036             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1037             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] );
1038         }
1039         count = get_pending_msgs(h);
1040         ok( !count, "Unexpected msg count: %ld\n", count );
1041
1042         memset( send_buf, 0, TEST_BUF_LEN );
1043         memset( recv_buf, 0xde, TEST_BUF_LEN );
1044         WriteFile( hPipeClt, send_buf, 2, &read, NULL );
1045         count = get_pending_msgs(h);
1046         ok( !count, "Unexpected msg count: %ld\n", count );
1047         ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
1048         count = get_pending_msgs(h);
1049         ok( count == 1, "Unexpected msg count: %ld\n", count );
1050         if (get_msg(h))
1051         {
1052             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1053             ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1054             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1055             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1056             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] );
1057         }
1058
1059         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
1060         CloseHandle( hPipeSrv );
1061         count = get_pending_msgs(h);
1062         ok( count == 1, "Unexpected msg count: %ld\n", count );
1063         if (get_msg(h))
1064         {
1065             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
1066             ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
1067             /* wine sends wrong status here */
1068             todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
1069             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
1070         }
1071     }
1072
1073     CloseHandle( hPipeClt );
1074 }
1075
1076 static void test_file_basic_information(void)
1077 {
1078     IO_STATUS_BLOCK io;
1079     FILE_BASIC_INFORMATION fbi;
1080     HANDLE h;
1081     int res;
1082     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1083
1084     if (!(h = create_temp_file(0))) return;
1085
1086     /* Check default first */
1087     memset(&fbi, 0, sizeof(fbi));
1088     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1089     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1090     ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1091          "attribute %x not expected\n", fbi.FileAttributes );
1092
1093     /* Then SYSTEM */
1094     /* Clear fbi to avoid setting times */
1095     memset(&fbi, 0, sizeof(fbi));
1096     fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1097     U(io).Status = 0xdeadbeef;
1098     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1099     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1100     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1101
1102     memset(&fbi, 0, sizeof(fbi));
1103     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1104     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1105     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
1106
1107     /* Then HIDDEN */
1108     memset(&fbi, 0, sizeof(fbi));
1109     fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1110     U(io).Status = 0xdeadbeef;
1111     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1112     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
1113     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
1114
1115     memset(&fbi, 0, sizeof(fbi));
1116     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1117     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1118     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
1119
1120     /* Check NORMAL last of all (to make sure we can clear attributes) */
1121     memset(&fbi, 0, sizeof(fbi));
1122     fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1123     U(io).Status = 0xdeadbeef;
1124     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1125     ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
1126     ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
1127
1128     memset(&fbi, 0, sizeof(fbi));
1129     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
1130     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1131     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
1132
1133     CloseHandle( h );
1134 }
1135
1136 static void test_file_all_information(void)
1137 {
1138     IO_STATUS_BLOCK io;
1139     /* FileAllInformation, like FileNameInformation, has a variable-length pathname
1140      * buffer at the end.  Vista objects with STATUS_BUFFER_OVERFLOW if you
1141      * don't leave enough room there.
1142      */
1143     struct {
1144       FILE_ALL_INFORMATION fai;
1145       WCHAR buf[256];
1146     } fai_buf;
1147     HANDLE h;
1148     int res;
1149     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
1150
1151     if (!(h = create_temp_file(0))) return;
1152
1153     /* Check default first */
1154     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1155     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1156     ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
1157          "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
1158
1159     /* Then SYSTEM */
1160     /* Clear fbi to avoid setting times */
1161     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1162     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
1163     U(io).Status = 0xdeadbeef;
1164     res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1165     ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
1166     todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
1167     U(io).Status = 0xdeadbeef;
1168     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1169     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1170     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1171
1172     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1173     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1174     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
1175     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 );
1176
1177     /* Then HIDDEN */
1178     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1179     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
1180     U(io).Status = 0xdeadbeef;
1181     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1182     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1183     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1184
1185     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1186     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1187     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1188     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 );
1189
1190     /* Check NORMAL last of all (to make sure we can clear attributes) */
1191     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
1192     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1193     U(io).Status = 0xdeadbeef;
1194     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
1195     ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
1196     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
1197
1198     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
1199     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
1200     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
1201     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 );
1202
1203     CloseHandle( h );
1204 }
1205
1206 static void test_file_both_information(void)
1207 {
1208     IO_STATUS_BLOCK io;
1209     FILE_BOTH_DIR_INFORMATION fbi;
1210     HANDLE h;
1211     int res;
1212
1213     if (!(h = create_temp_file(0))) return;
1214
1215     memset(&fbi, 0, sizeof(fbi));
1216     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
1217     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
1218
1219     CloseHandle( h );
1220 }
1221
1222 static void test_iocompletion(void)
1223 {
1224     HANDLE h = INVALID_HANDLE_VALUE;
1225     NTSTATUS res;
1226
1227     res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
1228
1229     ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
1230     ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
1231
1232     if ( h && h != INVALID_HANDLE_VALUE)
1233     {
1234         test_iocp_setcompletion(h);
1235         test_iocp_fileio(h);
1236         pNtClose(h);
1237     }
1238 }
1239
1240 static void test_file_name_information(void)
1241 {
1242     WCHAR *file_name, *volume_prefix, *expected;
1243     FILE_NAME_INFORMATION *info;
1244     ULONG old_redir = 1, tmp;
1245     UINT file_name_size;
1246     IO_STATUS_BLOCK io;
1247     UINT info_size;
1248     HRESULT hr;
1249     HANDLE h;
1250     UINT len;
1251
1252     /* GetVolumePathName is not present before w2k */
1253     if (!pGetVolumePathNameW) {
1254         win_skip("GetVolumePathNameW not found\n");
1255         return;
1256     }
1257
1258     file_name_size = GetSystemDirectoryW( NULL, 0 );
1259     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1260     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1261     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1262
1263     len = GetSystemDirectoryW( file_name, file_name_size );
1264     ok(len == file_name_size - 1,
1265             "GetSystemDirectoryW returned %u, expected %u.\n",
1266             len, file_name_size - 1);
1267
1268     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1269     ok(len, "GetVolumePathNameW failed.\n");
1270
1271     len = lstrlenW( volume_prefix );
1272     if (len && volume_prefix[len - 1] == '\\') --len;
1273     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1274     expected[file_name_size - len - 1] = '\0';
1275
1276     /* A bit more than we actually need, but it keeps the calculation simple. */
1277     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1278     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1279
1280     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1281     h = CreateFileW( file_name, GENERIC_READ,
1282             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1283             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1284     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1285     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1286
1287     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
1288     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
1289
1290     memset( info, 0xcc, info_size );
1291     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
1292     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1293             hr, STATUS_BUFFER_OVERFLOW);
1294     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1295             U(io).Status, STATUS_BUFFER_OVERFLOW);
1296     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1297     ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1298     ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1299             "info->FileName[1] is %p, expected %p.\n",
1300             CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1301     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1302
1303     memset( info, 0xcc, info_size );
1304     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1305     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1306     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1307     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u\n", info->FileNameLength);
1308     ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[len] is %#x, expected 0xcccc.\n",
1309        info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1310     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1311     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1312             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1313     ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1314             "io.Information is %lu, expected %u.\n",
1315             io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1316
1317     CloseHandle( h );
1318     HeapFree( GetProcessHeap(), 0, info );
1319     HeapFree( GetProcessHeap(), 0, expected );
1320     HeapFree( GetProcessHeap(), 0, volume_prefix );
1321
1322     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1323     {
1324         skip("Not running on WoW64, skipping test.\n");
1325         HeapFree( GetProcessHeap(), 0, file_name );
1326         return;
1327     }
1328
1329     h = CreateFileW( file_name, GENERIC_READ,
1330             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1331             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1332     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1333     HeapFree( GetProcessHeap(), 0, file_name );
1334
1335     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1336     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1337     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1338
1339     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1340     ok(len == file_name_size - 1,
1341             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1342             len, file_name_size - 1);
1343
1344     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1345     ok(len, "GetVolumePathNameW failed.\n");
1346
1347     len = lstrlenW( volume_prefix );
1348     if (len && volume_prefix[len - 1] == '\\') --len;
1349     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1350     expected[file_name_size - len - 1] = '\0';
1351
1352     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1353     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1354
1355     memset( info, 0xcc, info_size );
1356     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1357     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1358     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1359     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1360             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1361
1362     CloseHandle( h );
1363     HeapFree( GetProcessHeap(), 0, info );
1364     HeapFree( GetProcessHeap(), 0, expected );
1365     HeapFree( GetProcessHeap(), 0, volume_prefix );
1366     HeapFree( GetProcessHeap(), 0, file_name );
1367 }
1368
1369 static void test_file_all_name_information(void)
1370 {
1371     WCHAR *file_name, *volume_prefix, *expected;
1372     FILE_ALL_INFORMATION *info;
1373     ULONG old_redir = 1, tmp;
1374     UINT file_name_size;
1375     IO_STATUS_BLOCK io;
1376     UINT info_size;
1377     HRESULT hr;
1378     HANDLE h;
1379     UINT len;
1380
1381     /* GetVolumePathName is not present before w2k */
1382     if (!pGetVolumePathNameW) {
1383         win_skip("GetVolumePathNameW not found\n");
1384         return;
1385     }
1386
1387     file_name_size = GetSystemDirectoryW( NULL, 0 );
1388     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1389     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1390     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1391
1392     len = GetSystemDirectoryW( file_name, file_name_size );
1393     ok(len == file_name_size - 1,
1394             "GetSystemDirectoryW returned %u, expected %u.\n",
1395             len, file_name_size - 1);
1396
1397     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1398     ok(len, "GetVolumePathNameW failed.\n");
1399
1400     len = lstrlenW( volume_prefix );
1401     if (len && volume_prefix[len - 1] == '\\') --len;
1402     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1403     expected[file_name_size - len - 1] = '\0';
1404
1405     /* A bit more than we actually need, but it keeps the calculation simple. */
1406     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1407     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1408
1409     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( TRUE, &old_redir );
1410     h = CreateFileW( file_name, GENERIC_READ,
1411             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1412             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1413     if (pRtlWow64EnableFsRedirectionEx) pRtlWow64EnableFsRedirectionEx( old_redir, &tmp );
1414     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1415
1416     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileAllInformation );
1417     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x, expected %#x.\n",
1418             hr, STATUS_INFO_LENGTH_MISMATCH);
1419
1420     memset( info, 0xcc, info_size );
1421     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileAllInformation );
1422     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
1423             hr, STATUS_BUFFER_OVERFLOW);
1424     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
1425             U(io).Status, STATUS_BUFFER_OVERFLOW);
1426     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1427        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1428     ok(info->NameInformation.FileName[2] == 0xcccc,
1429             "info->NameInformation.FileName[2] is %#x, expected 0xcccc.\n", info->NameInformation.FileName[2]);
1430     ok(CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1431             "info->NameInformation.FileName[1] is %p, expected %p.\n",
1432             CharLowerW((LPWSTR)(UINT_PTR)info->NameInformation.FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1433     ok(io.Information == sizeof(*info), "io.Information is %lu\n", io.Information);
1434
1435     memset( info, 0xcc, info_size );
1436     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1437     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1438     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1439     ok(info->NameInformation.FileNameLength == lstrlenW( expected ) * sizeof(WCHAR),
1440        "info->NameInformation.FileNameLength is %u\n", info->NameInformation.FileNameLength );
1441     ok(info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] == 0xcccc,
1442        "info->NameInformation.FileName[len] is %#x, expected 0xcccc.\n",
1443        info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)]);
1444     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1445     ok(!lstrcmpiW( info->NameInformation.FileName, expected ),
1446             "info->NameInformation.FileName is %s, expected %s.\n",
1447             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1448     ok(io.Information == FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)
1449             + info->NameInformation.FileNameLength,
1450             "io.Information is %lu\n", io.Information );
1451
1452     CloseHandle( h );
1453     HeapFree( GetProcessHeap(), 0, info );
1454     HeapFree( GetProcessHeap(), 0, expected );
1455     HeapFree( GetProcessHeap(), 0, volume_prefix );
1456
1457     if (old_redir || !pGetSystemWow64DirectoryW || !(file_name_size = pGetSystemWow64DirectoryW( NULL, 0 )))
1458     {
1459         skip("Not running on WoW64, skipping test.\n");
1460         HeapFree( GetProcessHeap(), 0, file_name );
1461         return;
1462     }
1463
1464     h = CreateFileW( file_name, GENERIC_READ,
1465             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1466             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
1467     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
1468     HeapFree( GetProcessHeap(), 0, file_name );
1469
1470     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
1471     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
1472     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*expected) );
1473
1474     len = pGetSystemWow64DirectoryW( file_name, file_name_size );
1475     ok(len == file_name_size - 1,
1476             "GetSystemWow64DirectoryW returned %u, expected %u.\n",
1477             len, file_name_size - 1);
1478
1479     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
1480     ok(len, "GetVolumePathNameW failed.\n");
1481
1482     len = lstrlenW( volume_prefix );
1483     if (len && volume_prefix[len - 1] == '\\') --len;
1484     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
1485     expected[file_name_size - len - 1] = '\0';
1486
1487     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
1488     info = HeapAlloc( GetProcessHeap(), 0, info_size );
1489
1490     memset( info, 0xcc, info_size );
1491     hr = pNtQueryInformationFile( h, &io, info, info_size, FileAllInformation );
1492     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1493     info->NameInformation.FileName[info->NameInformation.FileNameLength / sizeof(WCHAR)] = '\0';
1494     ok(!lstrcmpiW( info->NameInformation.FileName, expected ), "info->NameInformation.FileName is %s, expected %s.\n",
1495             wine_dbgstr_w( info->NameInformation.FileName ), wine_dbgstr_w( expected ));
1496
1497     CloseHandle( h );
1498     HeapFree( GetProcessHeap(), 0, info );
1499     HeapFree( GetProcessHeap(), 0, expected );
1500     HeapFree( GetProcessHeap(), 0, volume_prefix );
1501     HeapFree( GetProcessHeap(), 0, file_name );
1502 }
1503
1504 static void test_query_volume_information_file(void)
1505 {
1506     NTSTATUS status;
1507     HANDLE dir;
1508     WCHAR path[MAX_PATH];
1509     OBJECT_ATTRIBUTES attr;
1510     IO_STATUS_BLOCK io;
1511     UNICODE_STRING nameW;
1512     FILE_FS_VOLUME_INFORMATION *ffvi;
1513     BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
1514
1515     GetWindowsDirectoryW( path, MAX_PATH );
1516     pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
1517     attr.Length = sizeof(attr);
1518     attr.RootDirectory = 0;
1519     attr.ObjectName = &nameW;
1520     attr.Attributes = OBJ_CASE_INSENSITIVE;
1521     attr.SecurityDescriptor = NULL;
1522     attr.SecurityQualityOfService = NULL;
1523
1524     status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
1525                           FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
1526     ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
1527     pRtlFreeUnicodeString( &nameW );
1528
1529     ZeroMemory( buf, sizeof(buf) );
1530     U(io).Status = 0xdadadada;
1531     io.Information = 0xcacacaca;
1532
1533     status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
1534
1535     ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
1536
1537 todo_wine
1538 {
1539     ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
1540     ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
1541
1542     ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1543     "expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
1544      io.Information);
1545
1546     ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
1547     ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
1548     ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
1549 }
1550     ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
1551
1552     trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
1553
1554     CloseHandle( dir );
1555 }
1556
1557 START_TEST(file)
1558 {
1559     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1560     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1561     if (!hntdll)
1562     {
1563         skip("not running on NT, skipping test\n");
1564         return;
1565     }
1566
1567     pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
1568     pGetSystemWow64DirectoryW = (void *)GetProcAddress(hkernel32, "GetSystemWow64DirectoryW");
1569
1570     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
1571     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
1572     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
1573     pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll, "RtlWow64EnableFsRedirectionEx");
1574     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
1575     pNtCreateFile           = (void *)GetProcAddress(hntdll, "NtCreateFile");
1576     pNtOpenFile             = (void *)GetProcAddress(hntdll, "NtOpenFile");
1577     pNtDeleteFile           = (void *)GetProcAddress(hntdll, "NtDeleteFile");
1578     pNtReadFile             = (void *)GetProcAddress(hntdll, "NtReadFile");
1579     pNtWriteFile            = (void *)GetProcAddress(hntdll, "NtWriteFile");
1580     pNtCancelIoFile         = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
1581     pNtCancelIoFileEx       = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
1582     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
1583     pNtCreateIoCompletion   = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
1584     pNtOpenIoCompletion     = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
1585     pNtQueryIoCompletion    = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
1586     pNtRemoveIoCompletion   = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
1587     pNtSetIoCompletion      = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
1588     pNtSetInformationFile   = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
1589     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
1590     pNtQueryDirectoryFile   = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
1591     pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
1592
1593     create_file_test();
1594     open_file_test();
1595     delete_file_test();
1596     read_file_test();
1597     append_file_test();
1598     nt_mailslot_test();
1599     test_iocompletion();
1600     test_file_basic_information();
1601     test_file_all_information();
1602     test_file_both_information();
1603     test_file_name_information();
1604     test_file_all_name_information();
1605     test_query_volume_information_file();
1606 }