~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ntdll/tests/file.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 
 45 static NTSTATUS (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
 46 static VOID     (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
 47 static BOOL     (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
 48 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
 49                                        ULONG, ULONG, ULONG, PLARGE_INTEGER );
 50 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
 51 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
 52                                       PIO_APC_ROUTINE apc, void* apc_user,
 53                                       PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
 54                                       PLARGE_INTEGER offset, PULONG key);
 55 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
 56                                        PIO_APC_ROUTINE apc, void* apc_user,
 57                                        PIO_STATUS_BLOCK io_status,
 58                                        const void* buffer, ULONG length,
 59                                        PLARGE_INTEGER offset, PULONG key);
 60 static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
 61 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
 62 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
 63 
 64 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
 65 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
 66 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
 67 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
 68 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
 69 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
 70 static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
 71 
 72 static inline BOOL is_signaled( HANDLE obj )
 73 {
 74     return WaitForSingleObject( obj, 0 ) == 0;
 75 }
 76 
 77 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
 78 #define TEST_BUF_LEN 3
 79 
 80 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
 81 {
 82     *read = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
 83                             1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
 84     ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
 85 
 86     *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
 87     ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
 88 
 89     return TRUE;
 90 }
 91 
 92 static HANDLE create_temp_file( ULONG flags )
 93 {
 94     char buffer[MAX_PATH];
 95     HANDLE handle;
 96 
 97     GetTempFileNameA( ".", "foo", 0, buffer );
 98     handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
 99                          flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
100     ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
101     return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
102 }
103 
104 #define CVALUE_FIRST 0xfffabbcc
105 #define CKEY_FIRST 0x1030341
106 #define CKEY_SECOND 0x132E46
107 
108 ULONG_PTR completionKey;
109 IO_STATUS_BLOCK ioSb;
110 ULONG_PTR completionValue;
111 
112 static long get_pending_msgs(HANDLE h)
113 {
114     NTSTATUS res;
115     ULONG a, req;
116 
117     res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
118     ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
119     if (res != STATUS_SUCCESS) return -1;
120     ok( req == sizeof(a), "Unexpected response size: %x\n", req );
121     return a;
122 }
123 
124 static BOOL get_msg(HANDLE h)
125 {
126     LARGE_INTEGER timeout = {{-10000000*3}};
127     DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
128     ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
129     if (res != STATUS_SUCCESS)
130     {
131         completionKey = completionValue = 0;
132         memset(&ioSb, 0, sizeof(ioSb));
133         return FALSE;
134     }
135     return TRUE;
136 }
137 
138 
139 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
140 {
141     int *count = arg;
142 
143     trace( "apc called block %p iosb.status %x iosb.info %lu\n",
144            iosb, U(*iosb).Status, iosb->Information );
145     (*count)++;
146     ok( !reserved, "reserved is not 0: %x\n", reserved );
147 }
148 
149 static void delete_file_test(void)
150 {
151     NTSTATUS ret;
152     OBJECT_ATTRIBUTES attr;
153     UNICODE_STRING nameW;
154     WCHAR pathW[MAX_PATH];
155     WCHAR pathsubW[MAX_PATH];
156     static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
157     static const WCHAR subdirW[]  = {'\\','s','u','b',0};
158 
159     ret = GetTempPathW(MAX_PATH, pathW);
160     if (!ret)
161     {
162         ok(0, "couldn't get temp dir\n");
163         return;
164     }
165     if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
166     {
167         ok(0, "MAX_PATH exceeded in constructing paths\n");
168         return;
169     }
170 
171     lstrcatW(pathW, testdirW);
172     lstrcpyW(pathsubW, pathW);
173     lstrcatW(pathsubW, subdirW);
174 
175     ret = CreateDirectoryW(pathW, NULL);
176     ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
177     if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
178     {
179         ok(0,"RtlDosPathNametoNtPathName_U failed\n");
180         return;
181     }
182 
183     attr.Length = sizeof(attr);
184     attr.RootDirectory = 0;
185     attr.Attributes = OBJ_CASE_INSENSITIVE;
186     attr.ObjectName = &nameW;
187     attr.SecurityDescriptor = NULL;
188     attr.SecurityQualityOfService = NULL;
189 
190     /* test NtDeleteFile on an empty directory */
191     ret = pNtDeleteFile(&attr);
192     ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
193     ret = RemoveDirectoryW(pathW);
194     ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
195 
196     /* test NtDeleteFile on a non-empty directory */
197     ret = CreateDirectoryW(pathW, NULL);
198     ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
199     ret = CreateDirectoryW(pathsubW, NULL);
200     ok(ret == TRUE, "couldn't create directory subdir\n");
201     ret = pNtDeleteFile(&attr);
202     ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
203     ret = RemoveDirectoryW(pathsubW);
204     ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
205     ret = RemoveDirectoryW(pathW);
206     ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
207 
208     pRtlFreeUnicodeString( &nameW );
209 }
210 
211 static void read_file_test(void)
212 {
213     const char text[] = "foobar";
214     HANDLE handle, read, write;
215     NTSTATUS status;
216     IO_STATUS_BLOCK iosb, iosb2;
217     DWORD written;
218     int apc_count = 0;
219     char buffer[128];
220     LARGE_INTEGER offset;
221     HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
222 
223     buffer[0] = 1;
224 
225     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
226 
227     /* try read with no data */
228     U(iosb).Status = 0xdeadbabe;
229     iosb.Information = 0xdeadbeef;
230     ok( is_signaled( read ), "read handle is not signaled\n" );
231     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
232     ok( status == STATUS_PENDING, "wrong status %x\n", status );
233     ok( !is_signaled( read ), "read handle is signaled\n" );
234     ok( !is_signaled( event ), "event is signaled\n" );
235     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
236     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
237     ok( !apc_count, "apc was called\n" );
238     WriteFile( write, buffer, 1, &written, NULL );
239     /* iosb updated here by async i/o */
240     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
241     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
242     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
243     ok( !is_signaled( read ), "read handle is signaled\n" );
244     ok( is_signaled( event ), "event is not signaled\n" );
245     ok( !apc_count, "apc was called\n" );
246     apc_count = 0;
247     SleepEx( 1, FALSE ); /* non-alertable sleep */
248     ok( !apc_count, "apc was called\n" );
249     SleepEx( 1, TRUE ); /* alertable sleep */
250     ok( apc_count == 1, "apc not called\n" );
251 
252     /* with no event, the pipe handle itself gets signaled */
253     apc_count = 0;
254     U(iosb).Status = 0xdeadbabe;
255     iosb.Information = 0xdeadbeef;
256     ok( !is_signaled( read ), "read handle is not signaled\n" );
257     status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
258     ok( status == STATUS_PENDING, "wrong status %x\n", status );
259     ok( !is_signaled( read ), "read handle is signaled\n" );
260     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
261     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
262     ok( !apc_count, "apc was called\n" );
263     WriteFile( write, buffer, 1, &written, NULL );
264     /* iosb updated here by async i/o */
265     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
266     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
267     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
268     ok( is_signaled( read ), "read handle is signaled\n" );
269     ok( !apc_count, "apc was called\n" );
270     apc_count = 0;
271     SleepEx( 1, FALSE ); /* non-alertable sleep */
272     ok( !apc_count, "apc was called\n" );
273     SleepEx( 1, TRUE ); /* alertable sleep */
274     ok( apc_count == 1, "apc not called\n" );
275 
276     /* now read with data ready */
277     apc_count = 0;
278     U(iosb).Status = 0xdeadbabe;
279     iosb.Information = 0xdeadbeef;
280     ResetEvent( event );
281     WriteFile( write, buffer, 1, &written, NULL );
282     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
283     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
284     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
285     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
286     ok( is_signaled( event ), "event is not signaled\n" );
287     ok( !apc_count, "apc was called\n" );
288     SleepEx( 1, FALSE ); /* non-alertable sleep */
289     ok( !apc_count, "apc was called\n" );
290     SleepEx( 1, TRUE ); /* alertable sleep */
291     ok( apc_count == 1, "apc not called\n" );
292 
293     /* try read with no data */
294     apc_count = 0;
295     U(iosb).Status = 0xdeadbabe;
296     iosb.Information = 0xdeadbeef;
297     ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
298     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
299     ok( status == STATUS_PENDING, "wrong status %x\n", status );
300     ok( !is_signaled( event ), "event is signaled\n" );
301     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
302     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
303     ok( !apc_count, "apc was called\n" );
304     WriteFile( write, buffer, 1, &written, NULL );
305     /* partial read is good enough */
306     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
307     ok( is_signaled( event ), "event is signaled\n" );
308     ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
309     ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
310     ok( !apc_count, "apc was called\n" );
311     SleepEx( 1, TRUE ); /* alertable sleep */
312     ok( apc_count == 1, "apc was not called\n" );
313 
314     /* read from disconnected pipe */
315     apc_count = 0;
316     U(iosb).Status = 0xdeadbabe;
317     iosb.Information = 0xdeadbeef;
318     CloseHandle( write );
319     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
320     ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
321     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
322     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
323     ok( !is_signaled( event ), "event is signaled\n" );
324     ok( !apc_count, "apc was called\n" );
325     SleepEx( 1, TRUE ); /* alertable sleep */
326     ok( !apc_count, "apc was called\n" );
327     CloseHandle( read );
328 
329     /* read from closed handle */
330     apc_count = 0;
331     U(iosb).Status = 0xdeadbabe;
332     iosb.Information = 0xdeadbeef;
333     SetEvent( event );
334     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
335     ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
336     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
337     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
338     ok( is_signaled( event ), "event is signaled\n" );  /* not reset on invalid handle */
339     ok( !apc_count, "apc was called\n" );
340     SleepEx( 1, TRUE ); /* alertable sleep */
341     ok( !apc_count, "apc was called\n" );
342 
343     /* disconnect while async read is in progress */
344     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
345     apc_count = 0;
346     U(iosb).Status = 0xdeadbabe;
347     iosb.Information = 0xdeadbeef;
348     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
349     ok( status == STATUS_PENDING, "wrong status %x\n", status );
350     ok( !is_signaled( event ), "event is signaled\n" );
351     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
352     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
353     ok( !apc_count, "apc was called\n" );
354     CloseHandle( write );
355     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
356     ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
357     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
358     ok( is_signaled( event ), "event is signaled\n" );
359     ok( !apc_count, "apc was called\n" );
360     SleepEx( 1, TRUE ); /* alertable sleep */
361     ok( apc_count == 1, "apc was not called\n" );
362     CloseHandle( read );
363 
364     if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
365     ok(DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS),
366         "Failed to duplicate handle: %d\n", GetLastError());
367 
368     apc_count = 0;
369     U(iosb).Status = 0xdeadbabe;
370     iosb.Information = 0xdeadbeef;
371     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
372     ok( status == STATUS_PENDING, "wrong status %x\n", status );
373     ok( !is_signaled( event ), "event is signaled\n" );
374     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
375     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
376     ok( !apc_count, "apc was called\n" );
377     /* Cancel by other handle */
378     status = pNtCancelIoFile( read, &iosb2 );
379     ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
380     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
381     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
382     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
383     ok( is_signaled( event ), "event is signaled\n" );
384     todo_wine ok( !apc_count, "apc was called\n" );
385     SleepEx( 1, TRUE ); /* alertable sleep */
386     ok( apc_count == 1, "apc was not called\n" );
387 
388     apc_count = 0;
389     U(iosb).Status = 0xdeadbabe;
390     iosb.Information = 0xdeadbeef;
391     status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
392     ok( status == STATUS_PENDING, "wrong status %x\n", status );
393     ok( !is_signaled( event ), "event is signaled\n" );
394     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
395     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
396     ok( !apc_count, "apc was called\n" );
397     /* Close queued handle */
398     CloseHandle( read );
399     SleepEx( 1, TRUE ); /* alertable sleep */
400     ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
401     ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
402     status = pNtCancelIoFile( read, &iosb2 );
403     ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
404     status = pNtCancelIoFile( handle, &iosb2 );
405     ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
406     Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
407     ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
408     ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
409     ok( is_signaled( event ), "event is signaled\n" );
410     todo_wine ok( !apc_count, "apc was called\n" );
411     SleepEx( 1, TRUE ); /* alertable sleep */
412     ok( apc_count == 1, "apc was not called\n" );
413     CloseHandle( handle );
414     CloseHandle( write );
415 
416     if (pNtCancelIoFileEx)
417     {
418         /* Basic Cancel Ex */
419         if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
420 
421         apc_count = 0;
422         U(iosb).Status = 0xdeadbabe;
423         iosb.Information = 0xdeadbeef;
424         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
425         ok( status == STATUS_PENDING, "wrong status %x\n", status );
426         ok( !is_signaled( event ), "event is signaled\n" );
427         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
428         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
429         ok( !apc_count, "apc was called\n" );
430         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
431         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
432         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
433         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
434         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
435         ok( is_signaled( event ), "event is signaled\n" );
436         todo_wine ok( !apc_count, "apc was called\n" );
437         SleepEx( 1, TRUE ); /* alertable sleep */
438         ok( apc_count == 1, "apc was not called\n" );
439 
440         /* Duplicate iosb */
441         apc_count = 0;
442         U(iosb).Status = 0xdeadbabe;
443         iosb.Information = 0xdeadbeef;
444         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
445         ok( status == STATUS_PENDING, "wrong status %x\n", status );
446         ok( !is_signaled( event ), "event is signaled\n" );
447         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
448         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
449         ok( !apc_count, "apc was called\n" );
450         status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
451         ok( status == STATUS_PENDING, "wrong status %x\n", status );
452         ok( !is_signaled( event ), "event is signaled\n" );
453         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
454         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
455         ok( !apc_count, "apc was called\n" );
456         status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
457         ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
458         Sleep(1);  /* FIXME: needed for wine to run the i/o apc  */
459         ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
460         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
461         ok( is_signaled( event ), "event is signaled\n" );
462         todo_wine ok( !apc_count, "apc was called\n" );
463         SleepEx( 1, TRUE ); /* alertable sleep */
464         ok( apc_count == 2, "apc was not called\n" );
465 
466         CloseHandle( read );
467         CloseHandle( write );
468     }
469 
470     /* now try a real file */
471     if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
472     apc_count = 0;
473     U(iosb).Status = 0xdeadbabe;
474     iosb.Information = 0xdeadbeef;
475     offset.QuadPart = 0;
476     ResetEvent( event );
477     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
478     ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
479     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
480     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
481     ok( is_signaled( event ), "event is signaled\n" );
482     ok( !apc_count, "apc was called\n" );
483     SleepEx( 1, TRUE ); /* alertable sleep */
484     ok( apc_count == 1, "apc was not called\n" );
485 
486     apc_count = 0;
487     U(iosb).Status = 0xdeadbabe;
488     iosb.Information = 0xdeadbeef;
489     offset.QuadPart = 0;
490     ResetEvent( event );
491     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
492     ok( status == STATUS_SUCCESS ||
493         status == STATUS_PENDING, /* vista */
494         "wrong status %x\n", status );
495     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
496     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
497     ok( is_signaled( event ), "event is signaled\n" );
498     ok( !apc_count, "apc was called\n" );
499     SleepEx( 1, TRUE ); /* alertable sleep */
500     ok( apc_count == 1, "apc was not called\n" );
501 
502     /* read beyond eof */
503     apc_count = 0;
504     U(iosb).Status = 0xdeadbabe;
505     iosb.Information = 0xdeadbeef;
506     offset.QuadPart = strlen(text) + 2;
507     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
508     if (status == STATUS_PENDING)  /* vista */
509     {
510         ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
511         ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
512         ok( is_signaled( event ), "event is signaled\n" );
513         ok( !apc_count, "apc was called\n" );
514         SleepEx( 1, TRUE ); /* alertable sleep */
515         ok( apc_count == 1, "apc was not called\n" );
516     }
517     else
518     {
519         ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
520         ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
521         ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
522         ok( !is_signaled( event ), "event is signaled\n" );
523         ok( !apc_count, "apc was called\n" );
524         SleepEx( 1, TRUE ); /* alertable sleep */
525         ok( !apc_count, "apc was called\n" );
526     }
527     CloseHandle( handle );
528 
529     /* now a non-overlapped file */
530     if (!(handle = create_temp_file(0))) return;
531     apc_count = 0;
532     U(iosb).Status = 0xdeadbabe;
533     iosb.Information = 0xdeadbeef;
534     offset.QuadPart = 0;
535     status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
536     ok( status == STATUS_END_OF_FILE ||
537         status == STATUS_SUCCESS ||
538         status == STATUS_PENDING,  /* vista */
539         "wrong status %x\n", status );
540     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
541     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
542     ok( is_signaled( event ), "event is signaled\n" );
543     ok( !apc_count, "apc was called\n" );
544     SleepEx( 1, TRUE ); /* alertable sleep */
545     ok( apc_count == 1, "apc was not called\n" );
546 
547     apc_count = 0;
548     U(iosb).Status = 0xdeadbabe;
549     iosb.Information = 0xdeadbeef;
550     offset.QuadPart = 0;
551     ResetEvent( event );
552     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
553     ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
554     ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
555     ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
556     ok( is_signaled( event ), "event is signaled\n" );
557     ok( !apc_count, "apc was called\n" );
558     SleepEx( 1, TRUE ); /* alertable sleep */
559     todo_wine ok( !apc_count, "apc was called\n" );
560 
561     /* read beyond eof */
562     apc_count = 0;
563     U(iosb).Status = 0xdeadbabe;
564     iosb.Information = 0xdeadbeef;
565     offset.QuadPart = strlen(text) + 2;
566     ResetEvent( event );
567     status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
568     ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
569     todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
570     todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
571     todo_wine ok( is_signaled( event ), "event is not signaled\n" );
572     ok( !apc_count, "apc was called\n" );
573     SleepEx( 1, TRUE ); /* alertable sleep */
574     ok( !apc_count, "apc was called\n" );
575 
576     CloseHandle( handle );
577 
578     CloseHandle( event );
579 }
580 
581 static void nt_mailslot_test(void)
582 {
583     HANDLE hslot;
584     ACCESS_MASK DesiredAccess;
585     OBJECT_ATTRIBUTES attr;
586 
587     ULONG CreateOptions;
588     ULONG MailslotQuota;
589     ULONG MaxMessageSize;
590     LARGE_INTEGER TimeOut;
591     IO_STATUS_BLOCK IoStatusBlock;
592     NTSTATUS rc;
593     UNICODE_STRING str;
594     WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
595                         'R',':','\\','F','R','E','D','\0' };
596 
597     TimeOut.QuadPart = -1;
598 
599     pRtlInitUnicodeString(&str, buffer1);
600     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
601     CreateOptions = MailslotQuota = MaxMessageSize = 0;
602     DesiredAccess = GENERIC_READ;
603 
604     /*
605      * Check for NULL pointer handling
606      */
607     rc = pNtCreateMailslotFile(NULL, DesiredAccess,
608          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
609          &TimeOut);
610     ok( rc == STATUS_ACCESS_VIOLATION ||
611         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
612         "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
613 
614     /*
615      * Test to see if the Timeout can be NULL
616      */
617     hslot = (HANDLE)0xdeadbeef;
618     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
619          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
620          NULL);
621     ok( rc == STATUS_SUCCESS ||
622         rc == STATUS_INVALID_PARAMETER, /* win2k3 */
623         "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
624     ok( hslot != 0, "Handle is invalid\n");
625 
626     if  ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
627 
628     /*
629      * Test that the length field is checked properly
630      */
631     attr.Length = 0;
632     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
633          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
634          &TimeOut);
635     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
636 
637     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
638 
639     attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
640     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
641          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
642          &TimeOut);
643     todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
644 
645     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
646 
647     /*
648      * Test handling of a NULL unicode string in ObjectName
649      */
650     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
651     attr.ObjectName = NULL;
652     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
653          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
654          &TimeOut);
655     ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
656         rc == STATUS_INVALID_PARAMETER,
657         "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
658 
659     if  (rc == STATUS_SUCCESS) pNtClose(hslot);
660 
661     /*
662      * Test a valid call
663      */
664     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
665     rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
666          &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
667          &TimeOut);
668     ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
669     ok( hslot != 0, "Handle is invalid\n");
670 
671     rc = pNtClose(hslot);
672     ok( rc == STATUS_SUCCESS, "NtClose failed\n");
673 }
674 
675 static void test_iocp_setcompletion(HANDLE h)
676 {
677     NTSTATUS res;
678     long count;
679 
680     res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
681     ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
682 
683     count = get_pending_msgs(h);
684     ok( count == 1, "Unexpected msg count: %ld\n", count );
685 
686     if (get_msg(h))
687     {
688         ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
689         ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
690         ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
691         ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
692     }
693 
694     count = get_pending_msgs(h);
695     ok( !count, "Unexpected msg count: %ld\n", count );
696 }
697 
698 static void test_iocp_fileio(HANDLE h)
699 {
700     static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
701 
702     IO_STATUS_BLOCK iosb;
703     FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
704     HANDLE hPipeSrv, hPipeClt;
705     NTSTATUS res;
706 
707     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
708     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
709     if (hPipeSrv != INVALID_HANDLE_VALUE )
710     {
711         hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
712         ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
713         if (hPipeClt != INVALID_HANDLE_VALUE)
714         {
715             res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
716             ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
717             CloseHandle(hPipeClt);
718         }
719         CloseHandle( hPipeSrv );
720     }
721 
722     hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
723     ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
724     if (hPipeSrv == INVALID_HANDLE_VALUE )
725         return;
726 
727     hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
728     ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
729     if (hPipeClt != INVALID_HANDLE_VALUE)
730     {
731         OVERLAPPED o = {0,};
732         BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
733         DWORD read;
734         long count;
735 
736         NTSTATUS res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
737         ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
738         ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
739 
740         memset( send_buf, 0, TEST_BUF_LEN );
741         memset( recv_buf, 0xde, TEST_BUF_LEN );
742         count = get_pending_msgs(h);
743         ok( !count, "Unexpected msg count: %ld\n", count );
744         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
745         count = get_pending_msgs(h);
746         ok( !count, "Unexpected msg count: %ld\n", count );
747         WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
748 
749         if (get_msg(h))
750         {
751             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
752             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
753             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
754             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
755             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] );
756         }
757         count = get_pending_msgs(h);
758         ok( !count, "Unexpected msg count: %ld\n", count );
759 
760         memset( send_buf, 0, TEST_BUF_LEN );
761         memset( recv_buf, 0xde, TEST_BUF_LEN );
762         WriteFile( hPipeClt, send_buf, 2, &read, NULL );
763         count = get_pending_msgs(h);
764         ok( !count, "Unexpected msg count: %ld\n", count );
765         ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
766         count = get_pending_msgs(h);
767         ok( count == 1, "Unexpected msg count: %ld\n", count );
768         if (get_msg(h))
769         {
770             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
771             ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
772             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
773             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
774             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] );
775         }
776 
777         ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
778         CloseHandle( hPipeSrv );
779         count = get_pending_msgs(h);
780         ok( count == 1, "Unexpected msg count: %ld\n", count );
781         if (get_msg(h))
782         {
783             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
784             ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
785             /* wine sends wrong status here */
786             todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
787             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
788         }
789     }
790 
791     CloseHandle( hPipeClt );
792 }
793 
794 static void test_file_basic_information(void)
795 {
796     IO_STATUS_BLOCK io;
797     FILE_BASIC_INFORMATION fbi;
798     HANDLE h;
799     int res;
800     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
801 
802     if (!(h = create_temp_file(0))) return;
803 
804     /* Check default first */
805     memset(&fbi, 0, sizeof(fbi));
806     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
807     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
808     ok ( (fbi.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
809          "attribute %x not expected\n", fbi.FileAttributes );
810 
811     /* Then SYSTEM */
812     /* Clear fbi to avoid setting times */
813     memset(&fbi, 0, sizeof(fbi));
814     fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
815     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
816     ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
817 
818     memset(&fbi, 0, sizeof(fbi));
819     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
820     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
821     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
822 
823     /* Then HIDDEN */
824     memset(&fbi, 0, sizeof(fbi));
825     fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
826     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
827     ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
828 
829     memset(&fbi, 0, sizeof(fbi));
830     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
831     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
832     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
833 
834     /* Check NORMAL last of all (to make sure we can clear attributes) */
835     memset(&fbi, 0, sizeof(fbi));
836     fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
837     res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
838     ok ( res == STATUS_SUCCESS, "can't set normal attribute\n");
839 
840     memset(&fbi, 0, sizeof(fbi));
841     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
842     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
843     todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_NORMAL, "attribute %x not 0\n", fbi.FileAttributes );
844 
845     CloseHandle( h );
846 }
847 
848 static void test_file_all_information(void)
849 {
850     IO_STATUS_BLOCK io;
851     /* FileAllInformation, like FileNameInformation, has a variable-length pathname
852      * buffer at the end.  Vista objects with STATUS_BUFFER_OVERFLOW if you
853      * don't leave enough room there.
854      */
855     struct {
856       FILE_ALL_INFORMATION fai;
857       WCHAR buf[256];
858     } fai_buf;
859     HANDLE h;
860     int res;
861     int attrib_mask = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL;
862 
863     if (!(h = create_temp_file(0))) return;
864 
865     /* Check default first */
866     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
867     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
868     ok ( (fai_buf.fai.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE,
869          "attribute %x not expected\n", fai_buf.fai.BasicInformation.FileAttributes );
870 
871     /* Then SYSTEM */
872     /* Clear fbi to avoid setting times */
873     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
874     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
875     res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
876     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to set FileAllInformation, res %x\n", res);
877     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
878     ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
879 
880     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
881     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
882     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
883     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 );
884 
885     /* Then HIDDEN */
886     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
887     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
888     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
889     ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
890 
891     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
892     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
893     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
894     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 );
895 
896     /* Check NORMAL last of all (to make sure we can clear attributes) */
897     memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
898     fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
899     res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
900     ok ( res == STATUS_SUCCESS, "can't set normal attribute\n");
901 
902     memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
903     res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
904     ok ( res == STATUS_SUCCESS, "can't get attributes\n");
905     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 );
906 
907     CloseHandle( h );
908 }
909 
910 static void test_file_both_information(void)
911 {
912     IO_STATUS_BLOCK io;
913     FILE_BOTH_DIR_INFORMATION fbi;
914     HANDLE h;
915     int res;
916 
917     if (!(h = create_temp_file(0))) return;
918 
919     memset(&fbi, 0, sizeof(fbi));
920     res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBothDirectoryInformation);
921     ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to query FileBothDirectoryInformation, res %x\n", res);
922 
923     CloseHandle( h );
924 }
925 
926 static void test_iocompletion(void)
927 {
928     HANDLE h = INVALID_HANDLE_VALUE;
929     NTSTATUS res;
930 
931     res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
932 
933     ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
934     ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
935 
936     if ( h && h != INVALID_HANDLE_VALUE)
937     {
938         test_iocp_setcompletion(h);
939         test_iocp_fileio(h);
940         pNtClose(h);
941     }
942 }
943 
944 static void test_file_name_information(void)
945 {
946     WCHAR *file_name, *volume_prefix, *expected;
947     FILE_NAME_INFORMATION *info;
948     UINT file_name_size;
949     IO_STATUS_BLOCK io;
950     UINT info_size;
951     HRESULT hr;
952     HANDLE h;
953     UINT len;
954 
955     /* GetVolumePathName is not present before w2k */
956     if (!pGetVolumePathNameW) {
957         win_skip("GetVolumePathNameW not found\n");
958         return;
959     }
960 
961     file_name_size = GetSystemDirectoryW( NULL, 0 );
962     file_name = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*file_name) );
963     volume_prefix = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
964     expected = HeapAlloc( GetProcessHeap(), 0, file_name_size * sizeof(*volume_prefix) );
965 
966     len = GetSystemDirectoryW( file_name, file_name_size );
967     ok(len == file_name_size - 1,
968             "GetSystemDirectoryW returned %u, expected %u.\n",
969             len, file_name_size - 1);
970 
971     len = pGetVolumePathNameW( file_name, volume_prefix, file_name_size );
972     ok(len, "GetVolumePathNameW failed.\n");
973 
974     len = lstrlenW( volume_prefix );
975     if (len && volume_prefix[len - 1] == '\\') --len;
976     memcpy( expected, file_name + len, (file_name_size - len - 1) * sizeof(WCHAR) );
977     expected[file_name_size - len - 1] = '\0';
978 
979     /* A bit more than we actually need, but it keeps the calculation simple. */
980     info_size = sizeof(*info) + (file_name_size * sizeof(WCHAR));
981     info = HeapAlloc( GetProcessHeap(), 0, info_size );
982 
983     h = CreateFileW( file_name, GENERIC_READ,
984             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
985             NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
986     ok(h != INVALID_HANDLE_VALUE, "Failed to open file.\n");
987 
988     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info) - 1, FileNameInformation );
989     ok(hr == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationFile returned %#x.\n", hr);
990 
991     memset( info, 0xcc, info_size );
992     hr = pNtQueryInformationFile( h, &io, info, sizeof(*info), FileNameInformation );
993     ok(hr == STATUS_BUFFER_OVERFLOW, "NtQueryInformationFile returned %#x, expected %#x.\n",
994             hr, STATUS_BUFFER_OVERFLOW);
995     ok(U(io).Status == STATUS_BUFFER_OVERFLOW, "io.Status is %#x, expected %#x.\n",
996             U(io).Status, STATUS_BUFFER_OVERFLOW);
997     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u, expected %u.\n",
998             info->FileNameLength, lstrlenW( expected ) * sizeof(WCHAR));
999     ok(info->FileName[2] == 0xcccc, "info->FileName[2] is %#x, expected 0xcccc.\n", info->FileName[2]);
1000     ok(CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]) == CharLowerW((LPWSTR)(UINT_PTR)expected[1]),
1001             "info->FileName[1] is %p, expected %p.\n",
1002             CharLowerW((LPWSTR)(UINT_PTR)info->FileName[1]), CharLowerW((LPWSTR)(UINT_PTR)expected[1]));
1003     ok(io.Information == sizeof(*info), "io.Information is %lu, expected %u.\n", io.Information, sizeof(*info));
1004 
1005     memset( info, 0xcc, info_size );
1006     hr = pNtQueryInformationFile( h, &io, info, info_size, FileNameInformation );
1007     ok(hr == STATUS_SUCCESS, "NtQueryInformationFile returned %#x, expected %#x.\n", hr, STATUS_SUCCESS);
1008     ok(U(io).Status == STATUS_SUCCESS, "io.Status is %#x, expected %#x.\n", U(io).Status, STATUS_SUCCESS);
1009     ok(info->FileNameLength == lstrlenW( expected ) * sizeof(WCHAR), "info->FileNameLength is %u, expected %u.\n",
1010             info->FileNameLength, lstrlenW( expected ) * sizeof(WCHAR));
1011     ok(info->FileName[info->FileNameLength / sizeof(WCHAR)] == 0xcccc, "info->FileName[%u] is %#x, expected 0xcccc.\n",
1012             info->FileNameLength / sizeof(WCHAR), info->FileName[info->FileNameLength / sizeof(WCHAR)]);
1013     info->FileName[info->FileNameLength / sizeof(WCHAR)] = '\0';
1014     ok(!lstrcmpiW( info->FileName, expected ), "info->FileName is %s, expected %s.\n",
1015             wine_dbgstr_w( info->FileName ), wine_dbgstr_w( expected ));
1016     ok(io.Information == FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength,
1017             "io.Information is %lu, expected %u.\n",
1018             io.Information, FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + info->FileNameLength);
1019 
1020     CloseHandle( h );
1021     HeapFree( GetProcessHeap(), 0, info );
1022     HeapFree( GetProcessHeap(), 0, expected );
1023     HeapFree( GetProcessHeap(), 0, volume_prefix );
1024     HeapFree( GetProcessHeap(), 0, file_name );
1025 }
1026 
1027 START_TEST(file)
1028 {
1029     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
1030     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1031     if (!hntdll)
1032     {
1033         skip("not running on NT, skipping test\n");
1034         return;
1035     }
1036 
1037     pGetVolumePathNameW = (void *)GetProcAddress(hkernel32, "GetVolumePathNameW");
1038 
1039     pRtlFreeUnicodeString   = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
1040     pRtlInitUnicodeString   = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
1041     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
1042     pNtCreateMailslotFile   = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
1043     pNtDeleteFile           = (void *)GetProcAddress(hntdll, "NtDeleteFile");
1044     pNtReadFile             = (void *)GetProcAddress(hntdll, "NtReadFile");
1045     pNtWriteFile            = (void *)GetProcAddress(hntdll, "NtWriteFile");
1046     pNtCancelIoFile         = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
1047     pNtCancelIoFileEx       = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
1048     pNtClose                = (void *)GetProcAddress(hntdll, "NtClose");
1049     pNtCreateIoCompletion   = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
1050     pNtOpenIoCompletion     = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
1051     pNtQueryIoCompletion    = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
1052     pNtRemoveIoCompletion   = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
1053     pNtSetIoCompletion      = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
1054     pNtSetInformationFile   = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
1055     pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
1056 
1057     delete_file_test();
1058     read_file_test();
1059     nt_mailslot_test();
1060     test_iocompletion();
1061     test_file_basic_information();
1062     test_file_all_information();
1063     test_file_both_information();
1064     test_file_name_information();
1065 }
1066 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.