ntdll: Implement NtCancelIoFileEx and fix NtCancelIoFile.
[wine.git] / dlls / ntdll / tests / file.c
blobba3c688d00fb0140c7458f6b788b82a61dd9a02c
1 /* Unit test suite for Ntdll file functions
3 * Copyright 2007 Jeff Latimer
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2008 Jeff Zaroyko
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.
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.
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
21 * NOTES
22 * We use function pointers here as there is no import library for NTDLL on
23 * windows.
26 #include <stdio.h>
27 #include <stdarg.h>
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
33 #define WIN32_NO_STATUS
35 #include "wine/test.h"
36 #include "winternl.h"
38 #ifndef IO_COMPLETION_ALL_ACCESS
39 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
40 #endif
42 static NTSTATUS (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
43 static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
44 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
45 static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ULONG, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
46 ULONG, ULONG, ULONG, PLARGE_INTEGER );
47 static NTSTATUS (WINAPI *pNtDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes);
48 static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
49 PIO_APC_ROUTINE apc, void* apc_user,
50 PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
51 PLARGE_INTEGER offset, PULONG key);
52 static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
53 PIO_APC_ROUTINE apc, void* apc_user,
54 PIO_STATUS_BLOCK io_status,
55 const void* buffer, ULONG length,
56 PLARGE_INTEGER offset, PULONG key);
57 static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
58 static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
60 static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
61 static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
62 static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
63 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
64 static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
65 static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
67 static inline BOOL is_signaled( HANDLE obj )
69 return WaitForSingleObject( obj, 0 ) == 0;
72 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
73 #define TEST_BUF_LEN 3
75 static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
77 *read = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
78 1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
79 ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
81 *write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
82 ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
84 return TRUE;
87 static HANDLE create_temp_file( ULONG flags )
89 char buffer[MAX_PATH];
90 HANDLE handle;
92 GetTempFileNameA( ".", "foo", 0, buffer );
93 handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
94 flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
95 ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
96 return (handle == INVALID_HANDLE_VALUE) ? 0 : handle;
99 #define CVALUE_FIRST 0xfffabbcc
100 #define CKEY_FIRST 0x1030341
101 #define CKEY_SECOND 0x132E46
103 ULONG_PTR completionKey;
104 IO_STATUS_BLOCK ioSb;
105 ULONG_PTR completionValue;
107 static long get_pending_msgs(HANDLE h)
109 NTSTATUS res;
110 ULONG a, req;
112 res = pNtQueryIoCompletion( h, IoCompletionBasicInformation, &a, sizeof(a), &req );
113 ok( res == STATUS_SUCCESS, "NtQueryIoCompletion failed: %x\n", res );
114 if (res != STATUS_SUCCESS) return -1;
115 ok( req == sizeof(a), "Unexpected response size: %x\n", req );
116 return a;
119 static BOOL get_msg(HANDLE h)
121 LARGE_INTEGER timeout = {{-10000000*3}};
122 DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout);
123 ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res );
124 if (res != STATUS_SUCCESS)
126 completionKey = completionValue = 0;
127 memset(&ioSb, 0, sizeof(ioSb));
128 return FALSE;
130 return TRUE;
134 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
136 int *count = arg;
138 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
139 iosb, U(*iosb).Status, iosb->Information );
140 (*count)++;
141 ok( !reserved, "reserved is not 0: %x\n", reserved );
144 static void delete_file_test(void)
146 NTSTATUS ret;
147 OBJECT_ATTRIBUTES attr;
148 UNICODE_STRING nameW;
149 WCHAR pathW[MAX_PATH];
150 WCHAR pathsubW[MAX_PATH];
151 static const WCHAR testdirW[] = {'n','t','d','e','l','e','t','e','f','i','l','e',0};
152 static const WCHAR subdirW[] = {'\\','s','u','b',0};
154 ret = GetTempPathW(MAX_PATH, pathW);
155 if (!ret)
157 ok(0, "couldn't get temp dir\n");
158 return;
160 if (ret + sizeof(testdirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
162 ok(0, "MAX_PATH exceeded in constructing paths\n");
163 return;
166 lstrcatW(pathW, testdirW);
167 lstrcpyW(pathsubW, pathW);
168 lstrcatW(pathsubW, subdirW);
170 ret = CreateDirectoryW(pathW, NULL);
171 ok(ret == TRUE, "couldn't create directory ntdeletefile\n");
172 if (!pRtlDosPathNameToNtPathName_U(pathW, &nameW, NULL, NULL))
174 ok(0,"RtlDosPathNametoNtPathName_U failed\n");
175 return;
178 attr.Length = sizeof(attr);
179 attr.RootDirectory = 0;
180 attr.Attributes = OBJ_CASE_INSENSITIVE;
181 attr.ObjectName = &nameW;
182 attr.SecurityDescriptor = NULL;
183 attr.SecurityQualityOfService = NULL;
185 /* test NtDeleteFile on an empty directory */
186 ret = pNtDeleteFile(&attr);
187 ok(ret == STATUS_SUCCESS, "NtDeleteFile should succeed in removing an empty directory\n");
188 ret = RemoveDirectoryW(pathW);
189 ok(ret == FALSE, "expected to fail removing directory, NtDeleteFile should have removed it\n");
191 /* test NtDeleteFile on a non-empty directory */
192 ret = CreateDirectoryW(pathW, NULL);
193 ok(ret == TRUE, "couldn't create directory ntdeletefile ?!\n");
194 ret = CreateDirectoryW(pathsubW, NULL);
195 ok(ret == TRUE, "couldn't create directory subdir\n");
196 ret = pNtDeleteFile(&attr);
197 ok(ret == STATUS_SUCCESS, "expected NtDeleteFile to ret STATUS_SUCCESS\n");
198 ret = RemoveDirectoryW(pathsubW);
199 ok(ret == TRUE, "expected to remove directory ntdeletefile\\sub\n");
200 ret = RemoveDirectoryW(pathW);
201 ok(ret == TRUE, "expected to remove directory ntdeletefile, NtDeleteFile failed.\n");
203 pRtlFreeUnicodeString( &nameW );
206 static void read_file_test(void)
208 const char text[] = "foobar";
209 HANDLE handle, read, write;
210 NTSTATUS status;
211 IO_STATUS_BLOCK iosb;
212 DWORD written;
213 int apc_count = 0;
214 char buffer[128];
215 LARGE_INTEGER offset;
216 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
218 buffer[0] = 1;
220 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
222 /* try read with no data */
223 U(iosb).Status = 0xdeadbabe;
224 iosb.Information = 0xdeadbeef;
225 ok( is_signaled( read ), "read handle is not signaled\n" );
226 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
227 ok( status == STATUS_PENDING, "wrong status %x\n", status );
228 ok( !is_signaled( read ), "read handle is signaled\n" );
229 ok( !is_signaled( event ), "event is signaled\n" );
230 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
231 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
232 ok( !apc_count, "apc was called\n" );
233 WriteFile( write, buffer, 1, &written, NULL );
234 /* iosb updated here by async i/o */
235 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
236 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
237 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
238 ok( !is_signaled( read ), "read handle is signaled\n" );
239 ok( is_signaled( event ), "event is not signaled\n" );
240 ok( !apc_count, "apc was called\n" );
241 apc_count = 0;
242 SleepEx( 1, FALSE ); /* non-alertable sleep */
243 ok( !apc_count, "apc was called\n" );
244 SleepEx( 1, TRUE ); /* alertable sleep */
245 ok( apc_count == 1, "apc not called\n" );
247 /* with no event, the pipe handle itself gets signaled */
248 apc_count = 0;
249 U(iosb).Status = 0xdeadbabe;
250 iosb.Information = 0xdeadbeef;
251 ok( !is_signaled( read ), "read handle is not signaled\n" );
252 status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
253 ok( status == STATUS_PENDING, "wrong status %x\n", status );
254 ok( !is_signaled( read ), "read handle is signaled\n" );
255 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
256 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
257 ok( !apc_count, "apc was called\n" );
258 WriteFile( write, buffer, 1, &written, NULL );
259 /* iosb updated here by async i/o */
260 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
261 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
262 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
263 ok( is_signaled( read ), "read handle is signaled\n" );
264 ok( !apc_count, "apc was called\n" );
265 apc_count = 0;
266 SleepEx( 1, FALSE ); /* non-alertable sleep */
267 ok( !apc_count, "apc was called\n" );
268 SleepEx( 1, TRUE ); /* alertable sleep */
269 ok( apc_count == 1, "apc not called\n" );
271 /* now read with data ready */
272 apc_count = 0;
273 U(iosb).Status = 0xdeadbabe;
274 iosb.Information = 0xdeadbeef;
275 ResetEvent( event );
276 WriteFile( write, buffer, 1, &written, NULL );
277 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
278 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
279 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
280 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
281 ok( is_signaled( event ), "event is not signaled\n" );
282 ok( !apc_count, "apc was called\n" );
283 SleepEx( 1, FALSE ); /* non-alertable sleep */
284 ok( !apc_count, "apc was called\n" );
285 SleepEx( 1, TRUE ); /* alertable sleep */
286 ok( apc_count == 1, "apc not called\n" );
288 /* try read with no data */
289 apc_count = 0;
290 U(iosb).Status = 0xdeadbabe;
291 iosb.Information = 0xdeadbeef;
292 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
293 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
294 ok( status == STATUS_PENDING, "wrong status %x\n", status );
295 ok( !is_signaled( event ), "event is signaled\n" );
296 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
297 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
298 ok( !apc_count, "apc was called\n" );
299 WriteFile( write, buffer, 1, &written, NULL );
300 /* partial read is good enough */
301 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
302 ok( is_signaled( event ), "event is signaled\n" );
303 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
304 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
305 ok( !apc_count, "apc was called\n" );
306 SleepEx( 1, TRUE ); /* alertable sleep */
307 ok( apc_count == 1, "apc was not called\n" );
309 /* read from disconnected pipe */
310 apc_count = 0;
311 U(iosb).Status = 0xdeadbabe;
312 iosb.Information = 0xdeadbeef;
313 CloseHandle( write );
314 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
315 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
316 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
317 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
318 ok( !is_signaled( event ), "event is signaled\n" );
319 ok( !apc_count, "apc was called\n" );
320 SleepEx( 1, TRUE ); /* alertable sleep */
321 ok( !apc_count, "apc was called\n" );
322 CloseHandle( read );
324 /* read from closed handle */
325 apc_count = 0;
326 U(iosb).Status = 0xdeadbabe;
327 iosb.Information = 0xdeadbeef;
328 SetEvent( event );
329 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
330 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
331 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
332 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
333 ok( is_signaled( event ), "event is signaled\n" ); /* not reset on invalid handle */
334 ok( !apc_count, "apc was called\n" );
335 SleepEx( 1, TRUE ); /* alertable sleep */
336 ok( !apc_count, "apc was called\n" );
338 /* disconnect while async read is in progress */
339 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
340 apc_count = 0;
341 U(iosb).Status = 0xdeadbabe;
342 iosb.Information = 0xdeadbeef;
343 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
344 ok( status == STATUS_PENDING, "wrong status %x\n", status );
345 ok( !is_signaled( event ), "event is signaled\n" );
346 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
347 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
348 ok( !apc_count, "apc was called\n" );
349 CloseHandle( write );
350 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
351 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
352 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
353 ok( is_signaled( event ), "event is signaled\n" );
354 ok( !apc_count, "apc was called\n" );
355 SleepEx( 1, TRUE ); /* alertable sleep */
356 ok( apc_count == 1, "apc was not called\n" );
357 CloseHandle( read );
359 if (pNtCancelIoFileEx)
361 IO_STATUS_BLOCK iosb2;
362 /* test param order for NtCancelIoFileEx */
363 if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
364 apc_count = 0;
365 U(iosb).Status = 0xdeadbabe;
366 iosb.Information = 0xdeadbeef;
367 status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
368 ok( status == STATUS_PENDING, "wrong status %x\n", status );
369 ok( !is_signaled( event ), "event is signaled\n" );
370 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
371 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
372 ok( !apc_count, "apc was called\n" );
373 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
374 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
375 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
376 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
377 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
378 ok( is_signaled( event ), "event is signaled\n" );
379 todo_wine ok( !apc_count, "apc was called\n" );
380 SleepEx( 1, TRUE ); /* alertable sleep */
381 ok( apc_count == 1, "apc was not called\n" );
382 CloseHandle( read );
383 CloseHandle( write );
386 /* now try a real file */
387 if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
388 apc_count = 0;
389 U(iosb).Status = 0xdeadbabe;
390 iosb.Information = 0xdeadbeef;
391 offset.QuadPart = 0;
392 ResetEvent( event );
393 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
394 ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
395 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
396 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
397 ok( is_signaled( event ), "event is signaled\n" );
398 ok( !apc_count, "apc was called\n" );
399 SleepEx( 1, TRUE ); /* alertable sleep */
400 ok( apc_count == 1, "apc was not called\n" );
402 apc_count = 0;
403 U(iosb).Status = 0xdeadbabe;
404 iosb.Information = 0xdeadbeef;
405 offset.QuadPart = 0;
406 ResetEvent( event );
407 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
408 ok( status == STATUS_SUCCESS ||
409 status == STATUS_PENDING, /* vista */
410 "wrong status %x\n", status );
411 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
412 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
413 ok( is_signaled( event ), "event is signaled\n" );
414 ok( !apc_count, "apc was called\n" );
415 SleepEx( 1, TRUE ); /* alertable sleep */
416 ok( apc_count == 1, "apc was not called\n" );
418 /* read beyond eof */
419 apc_count = 0;
420 U(iosb).Status = 0xdeadbabe;
421 iosb.Information = 0xdeadbeef;
422 offset.QuadPart = strlen(text) + 2;
423 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
424 if (status == STATUS_PENDING) /* vista */
426 ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
427 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
428 ok( is_signaled( event ), "event is signaled\n" );
429 ok( !apc_count, "apc was called\n" );
430 SleepEx( 1, TRUE ); /* alertable sleep */
431 ok( apc_count == 1, "apc was not called\n" );
433 else
435 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
436 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
437 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
438 ok( !is_signaled( event ), "event is signaled\n" );
439 ok( !apc_count, "apc was called\n" );
440 SleepEx( 1, TRUE ); /* alertable sleep */
441 ok( !apc_count, "apc was called\n" );
443 CloseHandle( handle );
445 /* now a non-overlapped file */
446 if (!(handle = create_temp_file(0))) return;
447 apc_count = 0;
448 U(iosb).Status = 0xdeadbabe;
449 iosb.Information = 0xdeadbeef;
450 offset.QuadPart = 0;
451 status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
452 ok( status == STATUS_END_OF_FILE ||
453 status == STATUS_SUCCESS ||
454 status == STATUS_PENDING, /* vista */
455 "wrong status %x\n", status );
456 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
457 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
458 ok( is_signaled( event ), "event is signaled\n" );
459 ok( !apc_count, "apc was called\n" );
460 SleepEx( 1, TRUE ); /* alertable sleep */
461 ok( apc_count == 1, "apc was not called\n" );
463 apc_count = 0;
464 U(iosb).Status = 0xdeadbabe;
465 iosb.Information = 0xdeadbeef;
466 offset.QuadPart = 0;
467 ResetEvent( event );
468 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, strlen(text) + 10, &offset, NULL );
469 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
470 ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
471 ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
472 ok( is_signaled( event ), "event is signaled\n" );
473 ok( !apc_count, "apc was called\n" );
474 SleepEx( 1, TRUE ); /* alertable sleep */
475 todo_wine ok( !apc_count, "apc was called\n" );
477 /* read beyond eof */
478 apc_count = 0;
479 U(iosb).Status = 0xdeadbabe;
480 iosb.Information = 0xdeadbeef;
481 offset.QuadPart = strlen(text) + 2;
482 ResetEvent( event );
483 status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
484 ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
485 todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
486 todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
487 todo_wine ok( is_signaled( event ), "event is not signaled\n" );
488 ok( !apc_count, "apc was called\n" );
489 SleepEx( 1, TRUE ); /* alertable sleep */
490 ok( !apc_count, "apc was called\n" );
492 CloseHandle( handle );
494 CloseHandle( event );
497 static void nt_mailslot_test(void)
499 HANDLE hslot;
500 ACCESS_MASK DesiredAccess;
501 OBJECT_ATTRIBUTES attr;
503 ULONG CreateOptions;
504 ULONG MailslotQuota;
505 ULONG MaxMessageSize;
506 LARGE_INTEGER TimeOut;
507 IO_STATUS_BLOCK IoStatusBlock;
508 NTSTATUS rc;
509 UNICODE_STRING str;
510 WCHAR buffer1[] = { '\\','?','?','\\','M','A','I','L','S','L','O','T','\\',
511 'R',':','\\','F','R','E','D','\0' };
513 TimeOut.QuadPart = -1;
515 pRtlInitUnicodeString(&str, buffer1);
516 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
517 CreateOptions = MailslotQuota = MaxMessageSize = 0;
518 DesiredAccess = GENERIC_READ;
521 * Check for NULL pointer handling
523 rc = pNtCreateMailslotFile(NULL, DesiredAccess,
524 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
525 &TimeOut);
526 ok( rc == STATUS_ACCESS_VIOLATION ||
527 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
528 "rc = %x not STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER\n", rc);
531 * Test to see if the Timeout can be NULL
533 hslot = (HANDLE)0xdeadbeef;
534 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
535 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
536 NULL);
537 ok( rc == STATUS_SUCCESS ||
538 rc == STATUS_INVALID_PARAMETER, /* win2k3 */
539 "rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
540 ok( hslot != 0, "Handle is invalid\n");
542 if ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
545 * Test that the length field is checked properly
547 attr.Length = 0;
548 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
549 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
550 &TimeOut);
551 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
553 if (rc == STATUS_SUCCESS) pNtClose(hslot);
555 attr.Length = sizeof(OBJECT_ATTRIBUTES)+1;
556 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
557 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
558 &TimeOut);
559 todo_wine ok( rc == STATUS_INVALID_PARAMETER, "rc = %x not c000000d STATUS_INVALID_PARAMETER\n", rc);
561 if (rc == STATUS_SUCCESS) pNtClose(hslot);
564 * Test handling of a NULL unicode string in ObjectName
566 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
567 attr.ObjectName = NULL;
568 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
569 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
570 &TimeOut);
571 ok( rc == STATUS_OBJECT_PATH_SYNTAX_BAD ||
572 rc == STATUS_INVALID_PARAMETER,
573 "rc = %x not STATUS_OBJECT_PATH_SYNTAX_BAD or STATUS_INVALID_PARAMETER\n", rc);
575 if (rc == STATUS_SUCCESS) pNtClose(hslot);
578 * Test a valid call
580 InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
581 rc = pNtCreateMailslotFile(&hslot, DesiredAccess,
582 &attr, &IoStatusBlock, CreateOptions, MailslotQuota, MaxMessageSize,
583 &TimeOut);
584 ok( rc == STATUS_SUCCESS, "Create MailslotFile failed rc = %x\n", rc);
585 ok( hslot != 0, "Handle is invalid\n");
587 rc = pNtClose(hslot);
588 ok( rc == STATUS_SUCCESS, "NtClose failed\n");
591 static void test_iocp_setcompletion(HANDLE h)
593 NTSTATUS res;
594 long count;
596 res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
597 ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
599 count = get_pending_msgs(h);
600 ok( count == 1, "Unexpected msg count: %ld\n", count );
602 if (get_msg(h))
604 ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
605 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
606 ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
607 ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
610 count = get_pending_msgs(h);
611 ok( !count, "Unexpected msg count: %ld\n", count );
614 static void test_iocp_fileio(HANDLE h)
616 static const char pipe_name[] = "\\\\.\\pipe\\iocompletiontestnamedpipe";
618 IO_STATUS_BLOCK iosb;
619 FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND};
620 HANDLE hPipeSrv, hPipeClt;
621 NTSTATUS res;
623 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
624 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
625 if (hPipeSrv != INVALID_HANDLE_VALUE )
627 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
628 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
629 if (hPipeClt != INVALID_HANDLE_VALUE)
631 res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
632 ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
633 CloseHandle(hPipeClt);
635 CloseHandle( hPipeSrv );
638 hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
639 ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
640 if (hPipeSrv == INVALID_HANDLE_VALUE )
641 return;
643 hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
644 ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
645 if (hPipeClt != INVALID_HANDLE_VALUE)
647 OVERLAPPED o = {0,};
648 BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
649 DWORD read;
650 long count;
652 NTSTATUS res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
653 ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
654 ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
656 memset( send_buf, 0, TEST_BUF_LEN );
657 memset( recv_buf, 0xde, TEST_BUF_LEN );
658 count = get_pending_msgs(h);
659 ok( !count, "Unexpected msg count: %ld\n", count );
660 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
661 count = get_pending_msgs(h);
662 ok( !count, "Unexpected msg count: %ld\n", count );
663 WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
665 if (get_msg(h))
667 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
668 ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
669 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
670 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
671 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] );
673 count = get_pending_msgs(h);
674 ok( !count, "Unexpected msg count: %ld\n", count );
676 memset( send_buf, 0, TEST_BUF_LEN );
677 memset( recv_buf, 0xde, TEST_BUF_LEN );
678 WriteFile( hPipeClt, send_buf, 2, &read, NULL );
679 count = get_pending_msgs(h);
680 ok( !count, "Unexpected msg count: %ld\n", count );
681 ReadFile( hPipeSrv, recv_buf, 2, &read, &o);
682 count = get_pending_msgs(h);
683 ok( count == 1, "Unexpected msg count: %ld\n", count );
684 if (get_msg(h))
686 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
687 ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information );
688 ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
689 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
690 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] );
693 ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o);
694 CloseHandle( hPipeSrv );
695 count = get_pending_msgs(h);
696 ok( count == 1, "Unexpected msg count: %ld\n", count );
697 if (get_msg(h))
699 ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
700 ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
701 /* wine sends wrong status here */
702 todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
703 ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
707 CloseHandle( hPipeClt );
710 static void test_iocompletion(void)
712 HANDLE h = INVALID_HANDLE_VALUE;
713 NTSTATUS res;
715 res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0);
717 ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res );
718 ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" );
720 if ( h && h != INVALID_HANDLE_VALUE)
722 test_iocp_setcompletion(h);
723 test_iocp_fileio(h);
724 pNtClose(h);
728 START_TEST(file)
730 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
731 if (!hntdll)
733 skip("not running on NT, skipping test\n");
734 return;
737 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
738 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
739 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
740 pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
741 pNtDeleteFile = (void *)GetProcAddress(hntdll, "NtDeleteFile");
742 pNtReadFile = (void *)GetProcAddress(hntdll, "NtReadFile");
743 pNtWriteFile = (void *)GetProcAddress(hntdll, "NtWriteFile");
744 pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
745 pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
746 pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
747 pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
748 pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
749 pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion");
750 pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion");
751 pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
753 delete_file_test();
754 read_file_test();
755 nt_mailslot_test();
756 test_iocompletion();