1 /* Unit test suite for Ntdll NamedPipe API functions
3 * Copyright 2011 Bernhard Loos
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WIN32_NO_STATUS
30 #include "wine/test.h"
31 #include "wine/winternl.h"
34 #ifndef __WINE_WINTERNL_H
39 } FILE_PIPE_INFORMATION
;
43 ULONG NamedPipeConfiguration
;
44 ULONG MaximumInstances
;
45 ULONG CurrentInstances
;
47 ULONG ReadDataAvailable
;
49 ULONG WriteQuotaAvailable
;
52 } FILE_PIPE_LOCAL_INFORMATION
;
54 #ifndef FILE_SYNCHRONOUS_IO_ALERT
55 #define FILE_SYNCHRONOUS_IO_ALERT 0x10
58 #ifndef FILE_SYNCHRONOUS_IO_NONALERT
59 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20
62 #ifndef FSCTL_PIPE_LISTEN
63 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
67 static NTSTATUS (WINAPI
*pNtFsControlFile
) (HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, PVOID apc_context
, PIO_STATUS_BLOCK io
, ULONG code
, PVOID in_buffer
, ULONG in_size
, PVOID out_buffer
, ULONG out_size
);
68 static NTSTATUS (WINAPI
*pNtCreateNamedPipeFile
) (PHANDLE handle
, ULONG access
,
69 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK iosb
,
70 ULONG sharing
, ULONG dispo
, ULONG options
,
71 ULONG pipe_type
, ULONG read_mode
,
72 ULONG completion_mode
, ULONG max_inst
,
73 ULONG inbound_quota
, ULONG outbound_quota
,
74 PLARGE_INTEGER timeout
);
75 static NTSTATUS (WINAPI
*pNtQueryInformationFile
) (IN HANDLE FileHandle
, OUT PIO_STATUS_BLOCK IoStatusBlock
, OUT PVOID FileInformation
, IN ULONG Length
, IN FILE_INFORMATION_CLASS FileInformationClass
);
76 static NTSTATUS (WINAPI
*pNtSetInformationFile
) (HANDLE handle
, PIO_STATUS_BLOCK io
, PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class);
77 static NTSTATUS (WINAPI
*pNtCancelIoFile
) (HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
78 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
) (HANDLE hFile
, IO_STATUS_BLOCK
*iosb
, IO_STATUS_BLOCK
*io_status
);
79 static void (WINAPI
*pRtlInitUnicodeString
) (PUNICODE_STRING target
, PCWSTR source
);
81 static HANDLE (WINAPI
*pOpenThread
)(DWORD dwDesiredAccess
, BOOL bInheritHandle
, DWORD dwThreadId
);
82 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
85 static BOOL
init_func_ptrs(void)
87 HMODULE module
= GetModuleHandleA("ntdll.dll");
89 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
90 trace("GetProcAddress(%s) failed\n", #name); \
94 loadfunc(NtFsControlFile
)
95 loadfunc(NtCreateNamedPipeFile
)
96 loadfunc(NtQueryInformationFile
)
97 loadfunc(NtSetInformationFile
)
98 loadfunc(NtCancelIoFile
)
99 loadfunc(NtCancelIoFileEx
)
100 loadfunc(RtlInitUnicodeString
)
103 module
= GetModuleHandleA("kernel32.dll");
104 pOpenThread
= (void *)GetProcAddress(module
, "OpenThread");
105 pQueueUserAPC
= (void *)GetProcAddress(module
, "QueueUserAPC");
109 static inline BOOL
is_signaled( HANDLE obj
)
111 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
114 static const WCHAR testpipe
[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
115 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
116 static const WCHAR testpipe_nt
[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
117 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
119 static NTSTATUS
create_pipe(PHANDLE handle
, ULONG sharing
, ULONG options
)
121 IO_STATUS_BLOCK iosb
;
122 OBJECT_ATTRIBUTES attr
;
124 LARGE_INTEGER timeout
;
127 pRtlInitUnicodeString(&name
, testpipe_nt
);
129 attr
.Length
= sizeof(attr
);
130 attr
.RootDirectory
= 0;
131 attr
.ObjectName
= &name
;
132 attr
.Attributes
= 0x40; /*case insensitive */
133 attr
.SecurityDescriptor
= NULL
;
134 attr
.SecurityQualityOfService
= NULL
;
136 timeout
.QuadPart
= -100000000;
138 res
= pNtCreateNamedPipeFile(handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, sharing
, 2 /*FILE_CREATE*/,
139 options
, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
143 static BOOL ioapc_called
;
144 static void CALLBACK
ioapc(void *arg
, PIO_STATUS_BLOCK io
, ULONG reserved
)
149 static NTSTATUS
listen_pipe(HANDLE hPipe
, HANDLE hEvent
, PIO_STATUS_BLOCK iosb
, BOOL use_apc
)
153 ioapc_called
= FALSE
;
155 return pNtFsControlFile(hPipe
, hEvent
, use_apc
? &ioapc
: NULL
, use_apc
? &dummy
: NULL
, iosb
, FSCTL_PIPE_LISTEN
, 0, 0, 0, 0);
158 static void test_create_invalid(void)
160 IO_STATUS_BLOCK iosb
;
161 OBJECT_ATTRIBUTES attr
;
163 LARGE_INTEGER timeout
;
165 HANDLE handle
, handle2
;
166 FILE_PIPE_LOCAL_INFORMATION info
;
168 pRtlInitUnicodeString(&name
, testpipe_nt
);
170 attr
.Length
= sizeof(attr
);
171 attr
.RootDirectory
= 0;
172 attr
.ObjectName
= &name
;
173 attr
.Attributes
= 0x40; /*case insensitive */
174 attr
.SecurityDescriptor
= NULL
;
175 attr
.SecurityQualityOfService
= NULL
;
177 timeout
.QuadPart
= -100000000;
179 /* create a pipe with FILE_OVERWRITE */
180 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 4 /*FILE_OVERWRITE*/,
181 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
182 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
186 /* create a pipe with FILE_OVERWRITE_IF */
187 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 5 /*FILE_OVERWRITE_IF*/,
188 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
189 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
193 /* create a pipe with sharing = 0 */
194 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, 0, 2 /*FILE_CREATE*/,
195 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
196 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
200 /* create a pipe without r/w access */
201 res
= pNtCreateNamedPipeFile(&handle
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
202 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
203 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
205 res
= pNtQueryInformationFile(handle
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
206 ok(res
== STATUS_ACCESS_DENIED
, "NtQueryInformationFile returned %x\n", res
);
208 /* test FILE_CREATE creation disposition */
209 res
= pNtCreateNamedPipeFile(&handle2
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
210 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
211 todo_wine
ok(res
== STATUS_ACCESS_DENIED
, "NtCreateNamedPipeFile returned %x\n", res
);
213 CloseHandle(handle2
);
218 static void test_create(void)
223 FILE_PIPE_LOCAL_INFORMATION info
;
224 IO_STATUS_BLOCK iosb
;
225 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
227 static const DWORD access
[] = { 0, GENERIC_READ
, GENERIC_WRITE
, GENERIC_READ
| GENERIC_WRITE
};
228 static const DWORD sharing
[] = { FILE_SHARE_READ
, FILE_SHARE_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
};
229 static const DWORD pipe_config
[]= { 1, 0, 2 };
231 for (j
= 0; j
< sizeof(sharing
) / sizeof(DWORD
); j
++) {
232 for (k
= 0; k
< sizeof(access
) / sizeof(DWORD
); k
++) {
234 BOOL should_succeed
= TRUE
;
236 res
= create_pipe(&hserver
, sharing
[j
], 0);
238 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res
, sharing
[j
]);
242 res
= listen_pipe(hserver
, hEvent
, &iosb
, FALSE
);
243 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
245 res
= pNtQueryInformationFile(hserver
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
246 ok(!res
, "NtQueryInformationFile for server returned %x, sharing: %x\n", res
, sharing
[j
]);
247 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
248 info
.NamedPipeConfiguration
, pipe_config
[j
]);
250 hclient
= CreateFileW(testpipe
, access
[k
], 0, 0, OPEN_EXISTING
, 0, 0);
251 if (hclient
!= INVALID_HANDLE_VALUE
) {
252 res
= pNtQueryInformationFile(hclient
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
253 ok(!res
, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n",
254 res
, access
[k
], sharing
[j
]);
255 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
256 info
.NamedPipeConfiguration
, pipe_config
[j
]);
257 CloseHandle(hclient
);
260 if (access
[k
] & GENERIC_WRITE
)
261 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_WRITE
);
262 if (access
[k
] & GENERIC_READ
)
263 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_READ
);
266 ok(hclient
!= INVALID_HANDLE_VALUE
, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n",
267 sharing
[j
], access
[k
], GetLastError());
269 ok(hclient
== INVALID_HANDLE_VALUE
, "CreateFile succeeded for sharing %x, access: %x\n", sharing
[j
], access
[k
]);
271 CloseHandle(hserver
);
277 static void test_overlapped(void)
279 IO_STATUS_BLOCK iosb
;
285 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
286 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
288 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
289 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
291 memset(&iosb
, 0x55, sizeof(iosb
));
292 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
293 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
294 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
296 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
297 ok(hClient
!= INVALID_HANDLE_VALUE
, "can't open pipe, GetLastError: %x\n", GetLastError());
299 ok(U(iosb
).Status
== 0, "Wrong iostatus %x\n", U(iosb
).Status
);
300 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
302 ok(!ioapc_called
, "IOAPC ran too early\n");
304 SleepEx(0, TRUE
); /* alertable wait state */
306 ok(ioapc_called
, "IOAPC didn't run\n");
309 CloseHandle(hClient
);
311 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
312 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
314 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
315 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
316 "can't open pipe, GetLastError: %x\n", GetLastError());
318 if (hClient
!= INVALID_HANDLE_VALUE
)
321 memset(&iosb
, 0x55, sizeof(iosb
));
322 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
323 ok(res
== STATUS_PIPE_CONNECTED
, "NtFsControlFile returned %x\n", res
);
324 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
325 ok(!is_signaled(hEvent
), "hEvent not signaled\n");
327 CloseHandle(hClient
);
334 static void test_completion(void)
336 static const char buf
[] = "testdata";
337 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
338 HANDLE port
, pipe
, client
;
339 IO_STATUS_BLOCK iosb
;
348 memset(&ov
, 0, sizeof(ov
));
349 ov
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
350 ok(ov
.hEvent
!= INVALID_HANDLE_VALUE
, "CreateEvent failed, error %u\n", GetLastError());
352 status
= create_pipe(&pipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
353 ok(!status
, "NtCreateNamedPipeFile returned %x\n", status
);
354 status
= listen_pipe(pipe
, ov
.hEvent
, &iosb
, FALSE
);
355 ok(status
== STATUS_PENDING
, "NtFsControlFile returned %x\n", status
);
357 client
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
358 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
359 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed, error %u\n", GetLastError());
360 dwret
= WaitForSingleObject(ov
.hEvent
, 0);
361 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", dwret
);
363 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
364 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %u\n", GetLastError());
366 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
367 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
368 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
372 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
373 ok(ret
, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
374 ok(key
== 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key
);
375 ok(pov
== &ov
, "expected %p, got %p\n", &ov
, pov
);
377 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
378 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
379 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
382 status
= pNtQueryInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
383 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
384 ok((info
.Flags
& FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
) != 0, "got %08x\n", info
.Flags
);
386 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
387 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
388 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
390 pov
= (void *)0xdeadbeef;
391 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
392 ok(!ret
, "GetQueuedCompletionStatus succeeded\n");
393 ok(pov
== NULL
, "expected NULL, got %p\n", pov
);
395 CloseHandle(ov
.hEvent
);
401 static BOOL userapc_called
;
402 static void CALLBACK
userapc(ULONG_PTR dwParam
)
404 userapc_called
= TRUE
;
407 static BOOL open_succeeded
;
408 static DWORD WINAPI
thread(PVOID main_thread
)
416 userapc_called
= FALSE
;
417 ret
= pQueueUserAPC(&userapc
, main_thread
, 0);
418 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
419 CloseHandle(main_thread
);
424 h
= CreateFileW(testpipe
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
426 if (h
!= INVALID_HANDLE_VALUE
) {
427 open_succeeded
= TRUE
;
431 open_succeeded
= FALSE
;
436 static void test_alertable(void)
438 IO_STATUS_BLOCK iosb
;
445 memset(&iosb
, 0x55, sizeof(iosb
));
447 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
448 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
450 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
451 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
453 /* queue an user apc before calling listen */
454 userapc_called
= FALSE
;
455 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
456 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
458 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
459 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
461 todo_wine
ok(userapc_called
, "user apc didn't run\n");
462 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
463 todo_wine
ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
464 ok(!ioapc_called
, "IOAPC ran\n");
466 /* queue an user apc from a different thread */
467 hThread
= CreateThread(NULL
, 0, &thread
, pOpenThread(MAXIMUM_ALLOWED
, FALSE
, GetCurrentThreadId()), 0, 0);
468 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
470 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
471 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
472 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
473 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
475 ok(userapc_called
, "user apc didn't run\n");
476 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
477 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
478 ok(!ioapc_called
, "IOAPC ran\n");
480 WaitForSingleObject(hThread
, INFINITE
);
482 SleepEx(0, TRUE
); /* get rid of the userapc, if NtFsControlFile failed */
484 ok(open_succeeded
, "couldn't open client side pipe\n");
486 CloseHandle(hThread
);
487 DisconnectNamedPipe(hPipe
);
489 /* finally try without an apc */
490 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
491 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
493 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
494 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
496 ok(open_succeeded
, "couldn't open client side pipe\n");
497 ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
498 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
500 WaitForSingleObject(hThread
, INFINITE
);
501 CloseHandle(hThread
);
506 static void test_nonalertable(void)
508 IO_STATUS_BLOCK iosb
;
515 memset(&iosb
, 0x55, sizeof(iosb
));
517 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
518 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
520 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
521 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
523 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
524 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
526 userapc_called
= FALSE
;
527 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
528 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
530 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
531 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
533 ok(open_succeeded
, "couldn't open client side pipe\n");
534 todo_wine
ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
535 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
537 ok(!ioapc_called
, "IOAPC ran too early\n");
538 ok(!userapc_called
, "user apc ran too early\n");
540 SleepEx(0, TRUE
); /* alertable wait state */
542 ok(ioapc_called
, "IOAPC didn't run\n");
543 ok(userapc_called
, "user apc didn't run\n");
545 WaitForSingleObject(hThread
, INFINITE
);
546 CloseHandle(hThread
);
551 static void test_cancelio(void)
553 IO_STATUS_BLOCK iosb
;
554 IO_STATUS_BLOCK cancel_sb
;
559 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
560 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
562 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
563 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
565 memset(&iosb
, 0x55, sizeof(iosb
));
567 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
568 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
570 res
= pNtCancelIoFile(hPipe
, &cancel_sb
);
571 ok(!res
, "NtCancelIoFile returned %x\n", res
);
573 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
574 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
576 ok(!ioapc_called
, "IOAPC ran too early\n");
578 SleepEx(0, TRUE
); /* alertable wait state */
580 ok(ioapc_called
, "IOAPC didn't run\n");
584 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
585 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
587 memset(&iosb
, 0x55, sizeof(iosb
));
588 res
= listen_pipe(hPipe
, hEvent
, &iosb
, FALSE
);
589 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
591 res
= pNtCancelIoFileEx(hPipe
, &iosb
, &cancel_sb
);
592 ok(!res
, "NtCancelIoFileEx returned %x\n", res
);
594 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
595 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
601 static void _check_pipe_handle_state(int line
, HANDLE handle
, ULONG read
, ULONG completion
)
603 IO_STATUS_BLOCK iosb
;
604 FILE_PIPE_INFORMATION fpi
;
606 if (handle
!= INVALID_HANDLE_VALUE
)
608 memset(&fpi
, 0x55, sizeof(fpi
));
609 res
= pNtQueryInformationFile(handle
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
610 ok_(__FILE__
, line
)(!res
, "NtQueryInformationFile returned %x\n", res
);
611 ok_(__FILE__
, line
)(fpi
.ReadMode
== read
, "Unexpected ReadMode, expected %x, got %x\n",
613 ok_(__FILE__
, line
)(fpi
.CompletionMode
== completion
, "Unexpected CompletionMode, expected %x, got %x\n",
614 completion
, fpi
.CompletionMode
);
617 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
619 static void test_filepipeinfo(void)
621 IO_STATUS_BLOCK iosb
;
622 OBJECT_ATTRIBUTES attr
;
624 LARGE_INTEGER timeout
;
625 HANDLE hServer
, hClient
;
626 FILE_PIPE_INFORMATION fpi
;
629 pRtlInitUnicodeString(&name
, testpipe_nt
);
631 attr
.Length
= sizeof(attr
);
632 attr
.RootDirectory
= 0;
633 attr
.ObjectName
= &name
;
634 attr
.Attributes
= 0x40; /* case insensitive */
635 attr
.SecurityDescriptor
= NULL
;
636 attr
.SecurityQualityOfService
= NULL
;
638 timeout
.QuadPart
= -100000000;
640 /* test with INVALID_HANDLE_VALUE */
641 res
= pNtQueryInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
642 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtQueryInformationFile returned %x\n", res
);
645 fpi
.CompletionMode
= 0;
646 res
= pNtSetInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
647 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtSetInformationFile returned %x\n", res
);
649 /* server end with read-only attributes */
650 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
651 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
652 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout
);
653 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
655 check_pipe_handle_state(hServer
, 0, 1);
657 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
658 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
659 "can't open pipe, GetLastError: %x\n", GetLastError());
661 check_pipe_handle_state(hServer
, 0, 1);
662 check_pipe_handle_state(hClient
, 0, 0);
665 fpi
.CompletionMode
= 0;
666 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
667 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
669 check_pipe_handle_state(hServer
, 0, 1);
670 check_pipe_handle_state(hClient
, 0, 0);
672 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
673 fpi
.CompletionMode
= 1;
674 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
675 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
677 check_pipe_handle_state(hServer
, 0, 1);
678 check_pipe_handle_state(hClient
, 0, 0);
680 if (hClient
!= INVALID_HANDLE_VALUE
)
682 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
683 fpi
.CompletionMode
= 1;
684 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
685 ok(res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile returned %x\n", res
);
688 check_pipe_handle_state(hServer
, 0, 1);
689 check_pipe_handle_state(hClient
, 0, 0);
691 if (hClient
!= INVALID_HANDLE_VALUE
)
694 fpi
.CompletionMode
= 1;
695 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
696 ok(!res
, "NtSetInformationFile returned %x\n", res
);
699 check_pipe_handle_state(hServer
, 0, 1);
700 check_pipe_handle_state(hClient
, 0, 1);
702 if (hClient
!= INVALID_HANDLE_VALUE
)
705 fpi
.CompletionMode
= 2; /* not in range 0-1 */
706 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
707 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
709 fpi
.ReadMode
= 2; /* not in range 0-1 */
710 fpi
.CompletionMode
= 0;
711 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
712 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
715 CloseHandle(hClient
);
717 check_pipe_handle_state(hServer
, 0, 1);
720 fpi
.CompletionMode
= 0;
721 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
722 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
724 CloseHandle(hServer
);
726 /* message mode server with read/write attributes */
727 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
728 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
729 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
730 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
732 check_pipe_handle_state(hServer
, 1, 0);
734 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
735 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
736 "can't open pipe, GetLastError: %x\n", GetLastError());
738 check_pipe_handle_state(hServer
, 1, 0);
739 check_pipe_handle_state(hClient
, 0, 0);
741 if (hClient
!= INVALID_HANDLE_VALUE
)
744 fpi
.CompletionMode
= 1;
745 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
746 ok(!res
, "NtSetInformationFile returned %x\n", res
);
749 check_pipe_handle_state(hServer
, 1, 0);
750 check_pipe_handle_state(hClient
, 1, 1);
753 fpi
.CompletionMode
= 1;
754 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
755 ok(!res
, "NtSetInformationFile returned %x\n", res
);
757 check_pipe_handle_state(hServer
, 0, 1);
758 check_pipe_handle_state(hClient
, 1, 1);
760 if (hClient
!= INVALID_HANDLE_VALUE
)
763 fpi
.CompletionMode
= 2; /* not in range 0-1 */
764 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
765 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
767 fpi
.ReadMode
= 2; /* not in range 0-1 */
768 fpi
.CompletionMode
= 0;
769 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
770 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
773 CloseHandle(hClient
);
775 check_pipe_handle_state(hServer
, 0, 1);
778 fpi
.CompletionMode
= 0;
779 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
780 ok(!res
, "NtSetInformationFile returned %x\n", res
);
782 check_pipe_handle_state(hServer
, 1, 0);
784 CloseHandle(hServer
);
787 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
791 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
794 static void test_peek(HANDLE pipe
, BOOL is_msgmode
)
796 FILE_PIPE_PEEK_BUFFER buf
;
797 IO_STATUS_BLOCK iosb
;
798 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
801 memset(&iosb
, 0x55, sizeof(iosb
));
802 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
803 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
804 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
805 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
808 memset(&iosb
, 0x55, sizeof(iosb
));
809 status
= NtFsControlFile(pipe
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
810 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
811 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
812 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
813 todo_wine_if(!is_msgmode
)
814 ok(is_signaled(event
), "event is not signaled\n");
819 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
821 static BOOL
create_pipe_pair( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG type
, ULONG size
)
823 const BOOL server_reader
= flags
& PIPE_ACCESS_INBOUND
;
824 HANDLE client
, server
;
826 server
= CreateNamedPipeA(PIPENAME
, flags
, PIPE_WAIT
| type
,
827 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
828 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
830 client
= CreateFileA(PIPENAME
, server_reader
? GENERIC_WRITE
: GENERIC_READ
| FILE_WRITE_ATTRIBUTES
, 0,
831 NULL
, OPEN_EXISTING
, flags
& FILE_FLAG_OVERLAPPED
, 0);
832 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
841 if(type
& PIPE_READMODE_MESSAGE
)
843 DWORD read_mode
= PIPE_READMODE_MESSAGE
;
844 ok(SetNamedPipeHandleState(client
, &read_mode
, NULL
, NULL
), "Change mode\n");
853 static void read_pipe_test(ULONG pipe_flags
, ULONG pipe_type
)
855 IO_STATUS_BLOCK iosb
, iosb2
;
856 HANDLE handle
, read
, write
;
857 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
864 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
866 /* try read with no data */
867 U(iosb
).Status
= 0xdeadbabe;
868 iosb
.Information
= 0xdeadbeef;
869 ok( is_signaled( read
), "read handle is not signaled\n" );
870 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
871 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
872 ok( !is_signaled( read
), "read handle is signaled\n" );
873 ok( !is_signaled( event
), "event is signaled\n" );
874 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
875 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
876 ok( !apc_count
, "apc was called\n" );
877 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
878 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
879 /* iosb updated here by async i/o */
880 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
881 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
882 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
883 ok( !is_signaled( read
), "read handle is signaled\n" );
884 ok( is_signaled( event
), "event is not signaled\n" );
885 ok( !apc_count
, "apc was called\n" );
887 SleepEx( 1, FALSE
); /* non-alertable sleep */
888 ok( !apc_count
, "apc was called\n" );
889 SleepEx( 1, TRUE
); /* alertable sleep */
890 ok( apc_count
== 1, "apc not called\n" );
892 /* with no event, the pipe handle itself gets signaled */
894 U(iosb
).Status
= 0xdeadbabe;
895 iosb
.Information
= 0xdeadbeef;
896 ok( !is_signaled( read
), "read handle is signaled\n" );
897 status
= NtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
898 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
899 ok( !is_signaled( read
), "read handle is signaled\n" );
900 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
901 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
902 ok( !apc_count
, "apc was called\n" );
903 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
904 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
905 /* iosb updated here by async i/o */
906 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
907 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
908 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
909 ok( is_signaled( read
), "read handle is not signaled\n" );
910 ok( !apc_count
, "apc was called\n" );
912 SleepEx( 1, FALSE
); /* non-alertable sleep */
913 ok( !apc_count
, "apc was called\n" );
914 SleepEx( 1, TRUE
); /* alertable sleep */
915 ok( apc_count
== 1, "apc not called\n" );
917 /* now read with data ready */
919 U(iosb
).Status
= 0xdeadbabe;
920 iosb
.Information
= 0xdeadbeef;
922 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
923 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
925 test_peek(read
, pipe_type
& PIPE_TYPE_MESSAGE
);
927 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
928 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
929 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
930 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
931 ok( is_signaled( event
), "event is not signaled\n" );
932 ok( !apc_count
, "apc was called\n" );
933 SleepEx( 1, FALSE
); /* non-alertable sleep */
934 ok( !apc_count
, "apc was called\n" );
935 SleepEx( 1, TRUE
); /* alertable sleep */
936 ok( apc_count
== 1, "apc not called\n" );
938 /* now partial read with data ready */
940 U(iosb
).Status
= 0xdeadbabe;
941 iosb
.Information
= 0xdeadbeef;
943 ret
= WriteFile( write
, buffer
, 2, &written
, NULL
);
944 ok(ret
&& written
== 2, "WriteFile error %d\n", GetLastError());
945 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
946 if (pipe_type
& PIPE_READMODE_MESSAGE
)
948 ok( status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", status
);
949 ok( U(iosb
).Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", U(iosb
).Status
);
953 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
954 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
956 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
957 ok( is_signaled( event
), "event is not signaled\n" );
958 ok( !apc_count
, "apc was called\n" );
959 SleepEx( 1, FALSE
); /* non-alertable sleep */
960 ok( !apc_count
, "apc was called\n" );
961 SleepEx( 1, TRUE
); /* alertable sleep */
962 ok( apc_count
== 1, "apc not called\n" );
964 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
965 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
966 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
967 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
968 ok( is_signaled( event
), "event is not signaled\n" );
969 ok( !apc_count
, "apc was called\n" );
970 SleepEx( 1, FALSE
); /* non-alertable sleep */
971 ok( !apc_count
, "apc was called\n" );
972 SleepEx( 1, TRUE
); /* alertable sleep */
973 ok( apc_count
== 1, "apc not called\n" );
975 /* try read with no data */
977 U(iosb
).Status
= 0xdeadbabe;
978 iosb
.Information
= 0xdeadbeef;
979 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
980 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
981 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
982 ok( !is_signaled( event
), "event is signaled\n" );
983 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
984 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
985 ok( !apc_count
, "apc was called\n" );
986 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
987 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
988 /* partial read is good enough */
989 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
990 ok( is_signaled( event
), "event is not signaled\n" );
991 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
992 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
993 ok( !apc_count
, "apc was called\n" );
994 SleepEx( 1, TRUE
); /* alertable sleep */
995 ok( apc_count
== 1, "apc was not called\n" );
997 /* read from disconnected pipe */
999 U(iosb
).Status
= 0xdeadbabe;
1000 iosb
.Information
= 0xdeadbeef;
1001 CloseHandle( write
);
1002 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1003 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", status
);
1004 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1005 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1006 ok( !is_signaled( event
), "event is signaled\n" );
1007 ok( !apc_count
, "apc was called\n" );
1008 SleepEx( 1, TRUE
); /* alertable sleep */
1009 ok( !apc_count
, "apc was called\n" );
1010 CloseHandle( read
);
1012 /* read from disconnected pipe, with invalid event handle */
1014 U(iosb
).Status
= 0xdeadbabe;
1015 iosb
.Information
= 0xdeadbeef;
1016 status
= NtReadFile( read
, (HANDLE
)0xdeadbeef, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1017 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1018 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1019 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1020 ok( !apc_count
, "apc was called\n" );
1021 SleepEx( 1, TRUE
); /* alertable sleep */
1022 ok( !apc_count
, "apc was called\n" );
1023 CloseHandle( read
);
1025 /* read from closed handle */
1027 U(iosb
).Status
= 0xdeadbabe;
1028 iosb
.Information
= 0xdeadbeef;
1030 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1031 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1032 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1033 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1034 ok( is_signaled( event
), "event is not signaled\n" ); /* not reset on invalid handle */
1035 ok( !apc_count
, "apc was called\n" );
1036 SleepEx( 1, TRUE
); /* alertable sleep */
1037 ok( !apc_count
, "apc was called\n" );
1039 /* disconnect while async read is in progress */
1040 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1042 U(iosb
).Status
= 0xdeadbabe;
1043 iosb
.Information
= 0xdeadbeef;
1044 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1045 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1046 ok( !is_signaled( event
), "event is signaled\n" );
1047 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1048 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1049 ok( !apc_count
, "apc was called\n" );
1050 CloseHandle( write
);
1051 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1052 todo_wine_if(!(pipe_type
& PIPE_TYPE_MESSAGE
) && (pipe_flags
& PIPE_ACCESS_OUTBOUND
))
1053 ok( U(iosb
).Status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", U(iosb
).Status
);
1054 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1055 ok( is_signaled( event
), "event is not signaled\n" );
1056 ok( !apc_count
, "apc was called\n" );
1057 SleepEx( 1, TRUE
); /* alertable sleep */
1058 ok( apc_count
== 1, "apc was not called\n" );
1059 CloseHandle( read
);
1061 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1062 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
1063 ok(ret
, "Failed to duplicate handle: %d\n", GetLastError());
1066 U(iosb
).Status
= 0xdeadbabe;
1067 iosb
.Information
= 0xdeadbeef;
1068 status
= NtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1069 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1070 ok( !is_signaled( event
), "event is signaled\n" );
1071 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1072 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1073 ok( !apc_count
, "apc was called\n" );
1074 /* Cancel by other handle */
1075 status
= pNtCancelIoFile( read
, &iosb2
);
1076 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %x\n", status
);
1077 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1078 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1079 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1080 ok( is_signaled( event
), "event is not signaled\n" );
1081 ok( !apc_count
, "apc was called\n" );
1082 SleepEx( 1, TRUE
); /* alertable sleep */
1083 ok( apc_count
== 1, "apc was not called\n" );
1086 U(iosb
).Status
= 0xdeadbabe;
1087 iosb
.Information
= 0xdeadbeef;
1088 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1089 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1090 ok( !is_signaled( event
), "event is signaled\n" );
1091 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1092 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1093 ok( !apc_count
, "apc was called\n" );
1094 /* Close queued handle */
1095 CloseHandle( read
);
1096 SleepEx( 1, TRUE
); /* alertable sleep */
1097 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1098 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1099 status
= pNtCancelIoFile( read
, &iosb2
);
1100 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
1101 status
= pNtCancelIoFile( handle
, &iosb2
);
1102 ok(status
== STATUS_SUCCESS
, "failed to cancel: %x\n", status
);
1103 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1104 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1105 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1106 ok( is_signaled( event
), "event is not signaled\n" );
1107 ok( !apc_count
, "apc was called\n" );
1108 SleepEx( 1, TRUE
); /* alertable sleep */
1109 ok( apc_count
== 1, "apc was not called\n" );
1110 CloseHandle( handle
);
1111 CloseHandle( write
);
1113 if (pNtCancelIoFileEx
)
1115 /* Basic Cancel Ex */
1116 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1119 U(iosb
).Status
= 0xdeadbabe;
1120 iosb
.Information
= 0xdeadbeef;
1121 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1122 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1123 ok( !is_signaled( event
), "event is signaled\n" );
1124 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1125 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1126 ok( !apc_count
, "apc was called\n" );
1127 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1128 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1129 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1130 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1131 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1132 ok( is_signaled( event
), "event is not signaled\n" );
1133 ok( !apc_count
, "apc was called\n" );
1134 SleepEx( 1, TRUE
); /* alertable sleep */
1135 ok( apc_count
== 1, "apc was not called\n" );
1137 /* Duplicate iosb */
1139 U(iosb
).Status
= 0xdeadbabe;
1140 iosb
.Information
= 0xdeadbeef;
1141 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1142 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1143 ok( !is_signaled( event
), "event is signaled\n" );
1144 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1145 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1146 ok( !apc_count
, "apc was called\n" );
1147 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1148 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1149 ok( !is_signaled( event
), "event is signaled\n" );
1150 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1151 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1152 ok( !apc_count
, "apc was called\n" );
1153 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1154 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1155 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1156 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1157 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1158 ok( is_signaled( event
), "event is not signaled\n" );
1159 ok( !apc_count
, "apc was called\n" );
1160 SleepEx( 1, TRUE
); /* alertable sleep */
1161 ok( apc_count
== 2, "apc was not called\n" );
1163 CloseHandle( read
);
1164 CloseHandle( write
);
1172 if (!init_func_ptrs())
1175 trace("starting invalid create tests\n");
1176 test_create_invalid();
1178 trace("starting create tests\n");
1181 trace("starting overlapped tests\n");
1184 trace("starting completion tests\n");
1187 trace("starting FILE_PIPE_INFORMATION tests\n");
1188 test_filepipeinfo();
1190 if (!pOpenThread
|| !pQueueUserAPC
)
1193 trace("starting alertable tests\n");
1196 trace("starting nonalertable tests\n");
1197 test_nonalertable();
1199 trace("starting cancelio tests\n");
1202 trace("starting byte read in byte mode client -> server\n");
1203 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_BYTE
);
1204 trace("starting byte read in message mode client -> server\n");
1205 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
);
1206 trace("starting message read in message mode client -> server\n");
1207 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
1208 trace("starting byte read in byte mode server -> client\n");
1209 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
);
1210 trace("starting byte read in message mode server -> client\n");
1211 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
);
1212 trace("starting message read in message mode server -> client\n");
1213 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);