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
22 * We use function pointers here as there is no import library for NTDLL on
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"
38 #ifndef IO_COMPLETION_ALL_ACCESS
39 #define IO_COMPLETION_ALL_ACCESS 0x001F0003
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());
87 static HANDLE
create_temp_file( ULONG flags
)
89 char buffer
[MAX_PATH
];
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
)
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
);
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
));
134 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
138 trace( "apc called block %p iosb.status %x iosb.info %lu\n",
139 iosb
, U(*iosb
).Status
, iosb
->Information
);
141 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
144 static void delete_file_test(void)
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
);
157 ok(0, "couldn't get temp dir\n");
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");
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");
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
;
211 IO_STATUS_BLOCK iosb
;
215 LARGE_INTEGER offset
;
216 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
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" );
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 */
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" );
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 */
273 U(iosb
).Status
= 0xdeadbabe;
274 iosb
.Information
= 0xdeadbeef;
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 */
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 */
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" );
324 /* read from closed handle */
326 U(iosb
).Status
= 0xdeadbabe;
327 iosb
.Information
= 0xdeadbeef;
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;
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" );
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;
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" );
383 CloseHandle( write
);
386 /* now try a real file */
387 if (!(handle
= create_temp_file( FILE_FLAG_OVERLAPPED
))) return;
389 U(iosb
).Status
= 0xdeadbabe;
390 iosb
.Information
= 0xdeadbeef;
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" );
403 U(iosb
).Status
= 0xdeadbabe;
404 iosb
.Information
= 0xdeadbeef;
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 */
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" );
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;
448 U(iosb
).Status
= 0xdeadbabe;
449 iosb
.Information
= 0xdeadbeef;
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" );
464 U(iosb
).Status
= 0xdeadbabe;
465 iosb
.Information
= 0xdeadbeef;
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 */
479 U(iosb
).Status
= 0xdeadbabe;
480 iosb
.Information
= 0xdeadbeef;
481 offset
.QuadPart
= strlen(text
) + 2;
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)
500 ACCESS_MASK DesiredAccess
;
501 OBJECT_ATTRIBUTES attr
;
505 ULONG MaxMessageSize
;
506 LARGE_INTEGER TimeOut
;
507 IO_STATUS_BLOCK IoStatusBlock
;
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
,
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
,
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
548 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
549 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
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
,
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
,
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
);
580 InitializeObjectAttributes(&attr
, &str
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
581 rc
= pNtCreateMailslotFile(&hslot
, DesiredAccess
,
582 &attr
, &IoStatusBlock
, CreateOptions
, MailslotQuota
, MaxMessageSize
,
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
)
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
);
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
;
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
)
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
)
648 BYTE send_buf
[TEST_BUF_LEN
], recv_buf
[TEST_BUF_LEN
];
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
);
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
);
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
);
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
;
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
);
730 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
733 skip("not running on NT, skipping test\n");
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");