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
20 #include "ntdll_test.h"
22 #ifndef __WINE_WINTERNL_H
27 } FILE_PIPE_INFORMATION
;
31 ULONG NamedPipeConfiguration
;
32 ULONG MaximumInstances
;
33 ULONG CurrentInstances
;
35 ULONG ReadDataAvailable
;
37 ULONG WriteQuotaAvailable
;
40 } FILE_PIPE_LOCAL_INFORMATION
;
42 #ifndef FILE_SYNCHRONOUS_IO_ALERT
43 #define FILE_SYNCHRONOUS_IO_ALERT 0x10
46 #ifndef FILE_SYNCHRONOUS_IO_NONALERT
47 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20
50 #ifndef FSCTL_PIPE_LISTEN
51 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
55 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
);
56 static NTSTATUS (WINAPI
*pNtCreateNamedPipeFile
) (PHANDLE handle
, ULONG access
,
57 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK iosb
,
58 ULONG sharing
, ULONG dispo
, ULONG options
,
59 ULONG pipe_type
, ULONG read_mode
,
60 ULONG completion_mode
, ULONG max_inst
,
61 ULONG inbound_quota
, ULONG outbound_quota
,
62 PLARGE_INTEGER timeout
);
63 static NTSTATUS (WINAPI
*pNtQueryInformationFile
) (IN HANDLE FileHandle
, OUT PIO_STATUS_BLOCK IoStatusBlock
, OUT PVOID FileInformation
, IN ULONG Length
, IN FILE_INFORMATION_CLASS FileInformationClass
);
64 static NTSTATUS (WINAPI
*pNtSetInformationFile
) (HANDLE handle
, PIO_STATUS_BLOCK io
, PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class);
65 static NTSTATUS (WINAPI
*pNtCancelIoFile
) (HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
66 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
) (HANDLE hFile
, IO_STATUS_BLOCK
*iosb
, IO_STATUS_BLOCK
*io_status
);
67 static void (WINAPI
*pRtlInitUnicodeString
) (PUNICODE_STRING target
, PCWSTR source
);
69 static HANDLE (WINAPI
*pOpenThread
)(DWORD dwDesiredAccess
, BOOL bInheritHandle
, DWORD dwThreadId
);
70 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
73 static BOOL
init_func_ptrs(void)
75 HMODULE module
= GetModuleHandleA("ntdll.dll");
77 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
78 trace("GetProcAddress(%s) failed\n", #name); \
82 loadfunc(NtFsControlFile
)
83 loadfunc(NtCreateNamedPipeFile
)
84 loadfunc(NtQueryInformationFile
)
85 loadfunc(NtSetInformationFile
)
86 loadfunc(NtCancelIoFile
)
87 loadfunc(NtCancelIoFileEx
)
88 loadfunc(RtlInitUnicodeString
)
91 module
= GetModuleHandleA("kernel32.dll");
92 pOpenThread
= (void *)GetProcAddress(module
, "OpenThread");
93 pQueueUserAPC
= (void *)GetProcAddress(module
, "QueueUserAPC");
97 static inline BOOL
is_signaled( HANDLE obj
)
99 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
102 static const WCHAR testpipe
[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
103 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
104 static const WCHAR testpipe_nt
[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
105 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
107 static NTSTATUS
create_pipe(PHANDLE handle
, ULONG sharing
, ULONG options
)
109 IO_STATUS_BLOCK iosb
;
110 OBJECT_ATTRIBUTES attr
;
112 LARGE_INTEGER timeout
;
115 pRtlInitUnicodeString(&name
, testpipe_nt
);
117 attr
.Length
= sizeof(attr
);
118 attr
.RootDirectory
= 0;
119 attr
.ObjectName
= &name
;
120 attr
.Attributes
= 0x40; /*case insensitive */
121 attr
.SecurityDescriptor
= NULL
;
122 attr
.SecurityQualityOfService
= NULL
;
124 timeout
.QuadPart
= -100000000;
126 res
= pNtCreateNamedPipeFile(handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, sharing
, 2 /*FILE_CREATE*/,
127 options
, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
131 static BOOL ioapc_called
;
132 static void CALLBACK
ioapc(void *arg
, PIO_STATUS_BLOCK io
, ULONG reserved
)
137 static NTSTATUS
listen_pipe(HANDLE hPipe
, HANDLE hEvent
, PIO_STATUS_BLOCK iosb
, BOOL use_apc
)
141 ioapc_called
= FALSE
;
143 return pNtFsControlFile(hPipe
, hEvent
, use_apc
? &ioapc
: NULL
, use_apc
? &dummy
: NULL
, iosb
, FSCTL_PIPE_LISTEN
, 0, 0, 0, 0);
146 static void test_create_invalid(void)
148 IO_STATUS_BLOCK iosb
;
149 OBJECT_ATTRIBUTES attr
;
151 LARGE_INTEGER timeout
;
153 HANDLE handle
, handle2
;
154 FILE_PIPE_LOCAL_INFORMATION info
;
156 pRtlInitUnicodeString(&name
, testpipe_nt
);
158 attr
.Length
= sizeof(attr
);
159 attr
.RootDirectory
= 0;
160 attr
.ObjectName
= &name
;
161 attr
.Attributes
= 0x40; /*case insensitive */
162 attr
.SecurityDescriptor
= NULL
;
163 attr
.SecurityQualityOfService
= NULL
;
165 timeout
.QuadPart
= -100000000;
167 /* create a pipe with FILE_OVERWRITE */
168 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 4 /*FILE_OVERWRITE*/,
169 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
170 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
174 /* create a pipe with FILE_OVERWRITE_IF */
175 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 5 /*FILE_OVERWRITE_IF*/,
176 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
177 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
181 /* create a pipe with sharing = 0 */
182 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, 0, 2 /*FILE_CREATE*/,
183 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
184 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
188 /* create a pipe without r/w access */
189 res
= pNtCreateNamedPipeFile(&handle
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
190 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
191 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
193 res
= pNtQueryInformationFile(handle
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
194 ok(res
== STATUS_ACCESS_DENIED
, "NtQueryInformationFile returned %x\n", res
);
196 /* test FILE_CREATE creation disposition */
197 res
= pNtCreateNamedPipeFile(&handle2
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
198 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
199 todo_wine
ok(res
== STATUS_ACCESS_DENIED
, "NtCreateNamedPipeFile returned %x\n", res
);
201 CloseHandle(handle2
);
206 static void test_create(void)
211 FILE_PIPE_LOCAL_INFORMATION info
;
212 IO_STATUS_BLOCK iosb
;
213 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
215 static const DWORD access
[] = { 0, GENERIC_READ
, GENERIC_WRITE
, GENERIC_READ
| GENERIC_WRITE
};
216 static const DWORD sharing
[] = { FILE_SHARE_READ
, FILE_SHARE_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
};
217 static const DWORD pipe_config
[]= { 1, 0, 2 };
219 for (j
= 0; j
< sizeof(sharing
) / sizeof(DWORD
); j
++) {
220 for (k
= 0; k
< sizeof(access
) / sizeof(DWORD
); k
++) {
222 BOOL should_succeed
= TRUE
;
224 res
= create_pipe(&hserver
, sharing
[j
], 0);
226 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res
, sharing
[j
]);
230 res
= listen_pipe(hserver
, hEvent
, &iosb
, FALSE
);
231 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
233 res
= pNtQueryInformationFile(hserver
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
234 ok(!res
, "NtQueryInformationFile for server returned %x, sharing: %x\n", res
, sharing
[j
]);
235 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
236 info
.NamedPipeConfiguration
, pipe_config
[j
]);
238 hclient
= CreateFileW(testpipe
, access
[k
], 0, 0, OPEN_EXISTING
, 0, 0);
239 if (hclient
!= INVALID_HANDLE_VALUE
) {
240 res
= pNtQueryInformationFile(hclient
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
241 ok(!res
, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n",
242 res
, access
[k
], sharing
[j
]);
243 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
244 info
.NamedPipeConfiguration
, pipe_config
[j
]);
245 CloseHandle(hclient
);
248 if (access
[k
] & GENERIC_WRITE
)
249 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_WRITE
);
250 if (access
[k
] & GENERIC_READ
)
251 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_READ
);
254 ok(hclient
!= INVALID_HANDLE_VALUE
, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n",
255 sharing
[j
], access
[k
], GetLastError());
257 ok(hclient
== INVALID_HANDLE_VALUE
, "CreateFile succeeded for sharing %x, access: %x\n", sharing
[j
], access
[k
]);
259 CloseHandle(hserver
);
265 static void test_overlapped(void)
267 IO_STATUS_BLOCK iosb
;
273 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
274 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
276 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
277 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
279 memset(&iosb
, 0x55, sizeof(iosb
));
280 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
281 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
282 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
284 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
285 ok(hClient
!= INVALID_HANDLE_VALUE
, "can't open pipe, GetLastError: %x\n", GetLastError());
287 ok(U(iosb
).Status
== 0, "Wrong iostatus %x\n", U(iosb
).Status
);
288 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
290 ok(!ioapc_called
, "IOAPC ran too early\n");
292 SleepEx(0, TRUE
); /* alertable wait state */
294 ok(ioapc_called
, "IOAPC didn't run\n");
297 CloseHandle(hClient
);
299 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
300 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
302 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
303 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
304 "can't open pipe, GetLastError: %x\n", GetLastError());
306 if (hClient
!= INVALID_HANDLE_VALUE
)
309 memset(&iosb
, 0x55, sizeof(iosb
));
310 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
311 ok(res
== STATUS_PIPE_CONNECTED
, "NtFsControlFile returned %x\n", res
);
312 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
313 ok(!is_signaled(hEvent
), "hEvent not signaled\n");
315 CloseHandle(hClient
);
322 static void test_completion(void)
324 static const char buf
[] = "testdata";
325 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
326 HANDLE port
, pipe
, client
;
327 IO_STATUS_BLOCK iosb
;
336 memset(&ov
, 0, sizeof(ov
));
337 ov
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
338 ok(ov
.hEvent
!= INVALID_HANDLE_VALUE
, "CreateEvent failed, error %u\n", GetLastError());
340 status
= create_pipe(&pipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
341 ok(!status
, "NtCreateNamedPipeFile returned %x\n", status
);
342 status
= listen_pipe(pipe
, ov
.hEvent
, &iosb
, FALSE
);
343 ok(status
== STATUS_PENDING
, "NtFsControlFile returned %x\n", status
);
345 client
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
346 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
347 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed, error %u\n", GetLastError());
348 dwret
= WaitForSingleObject(ov
.hEvent
, 0);
349 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", dwret
);
351 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
352 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %u\n", GetLastError());
354 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
355 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
356 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
360 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
361 ok(ret
, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
362 ok(key
== 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key
);
363 ok(pov
== &ov
, "expected %p, got %p\n", &ov
, pov
);
365 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
366 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
367 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
370 status
= pNtQueryInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
371 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
372 ok((info
.Flags
& FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
) != 0, "got %08x\n", info
.Flags
);
374 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
375 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
376 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
378 pov
= (void *)0xdeadbeef;
379 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 1000);
380 ok(!ret
, "GetQueuedCompletionStatus succeeded\n");
381 ok(pov
== NULL
, "expected NULL, got %p\n", pov
);
383 CloseHandle(ov
.hEvent
);
389 static BOOL userapc_called
;
390 static void CALLBACK
userapc(ULONG_PTR dwParam
)
392 userapc_called
= TRUE
;
395 static BOOL open_succeeded
;
396 static DWORD WINAPI
thread(PVOID main_thread
)
404 userapc_called
= FALSE
;
405 ret
= pQueueUserAPC(&userapc
, main_thread
, 0);
406 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
407 CloseHandle(main_thread
);
412 h
= CreateFileW(testpipe
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
414 if (h
!= INVALID_HANDLE_VALUE
) {
415 open_succeeded
= TRUE
;
419 open_succeeded
= FALSE
;
424 static void test_alertable(void)
426 IO_STATUS_BLOCK iosb
;
433 memset(&iosb
, 0x55, sizeof(iosb
));
435 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
436 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
438 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
439 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
441 /* queue an user apc before calling listen */
442 userapc_called
= FALSE
;
443 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
444 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
446 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
447 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
449 todo_wine
ok(userapc_called
, "user apc didn't run\n");
450 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
451 todo_wine
ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
452 ok(!ioapc_called
, "IOAPC ran\n");
454 /* queue an user apc from a different thread */
455 hThread
= CreateThread(NULL
, 0, &thread
, pOpenThread(MAXIMUM_ALLOWED
, FALSE
, GetCurrentThreadId()), 0, 0);
456 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
458 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
459 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
460 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
461 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
463 ok(userapc_called
, "user apc didn't run\n");
464 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
465 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
466 ok(!ioapc_called
, "IOAPC ran\n");
468 WaitForSingleObject(hThread
, INFINITE
);
470 SleepEx(0, TRUE
); /* get rid of the userapc, if NtFsControlFile failed */
472 ok(open_succeeded
, "couldn't open client side pipe\n");
474 CloseHandle(hThread
);
475 DisconnectNamedPipe(hPipe
);
477 /* finally try without an apc */
478 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
479 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
481 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
482 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
484 ok(open_succeeded
, "couldn't open client side pipe\n");
485 ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
486 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
488 WaitForSingleObject(hThread
, INFINITE
);
489 CloseHandle(hThread
);
494 static void test_nonalertable(void)
496 IO_STATUS_BLOCK iosb
;
503 memset(&iosb
, 0x55, sizeof(iosb
));
505 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
506 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
508 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
509 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
511 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
512 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
514 userapc_called
= FALSE
;
515 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
516 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
518 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
519 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
521 ok(open_succeeded
, "couldn't open client side pipe\n");
522 todo_wine
ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
523 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
525 ok(!ioapc_called
, "IOAPC ran too early\n");
526 ok(!userapc_called
, "user apc ran too early\n");
528 SleepEx(0, TRUE
); /* alertable wait state */
530 ok(ioapc_called
, "IOAPC didn't run\n");
531 ok(userapc_called
, "user apc didn't run\n");
533 WaitForSingleObject(hThread
, INFINITE
);
534 CloseHandle(hThread
);
539 static void test_cancelio(void)
541 IO_STATUS_BLOCK iosb
;
542 IO_STATUS_BLOCK cancel_sb
;
547 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
548 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
550 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
551 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
553 memset(&iosb
, 0x55, sizeof(iosb
));
555 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
556 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
558 res
= pNtCancelIoFile(hPipe
, &cancel_sb
);
559 ok(!res
, "NtCancelIoFile returned %x\n", res
);
561 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
562 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
564 ok(!ioapc_called
, "IOAPC ran too early\n");
566 SleepEx(0, TRUE
); /* alertable wait state */
568 ok(ioapc_called
, "IOAPC didn't run\n");
572 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
573 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
575 memset(&iosb
, 0x55, sizeof(iosb
));
576 res
= listen_pipe(hPipe
, hEvent
, &iosb
, FALSE
);
577 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
579 res
= pNtCancelIoFileEx(hPipe
, &iosb
, &cancel_sb
);
580 ok(!res
, "NtCancelIoFileEx returned %x\n", res
);
582 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
583 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
589 static void _check_pipe_handle_state(int line
, HANDLE handle
, ULONG read
, ULONG completion
)
591 IO_STATUS_BLOCK iosb
;
592 FILE_PIPE_INFORMATION fpi
;
594 if (handle
!= INVALID_HANDLE_VALUE
)
596 memset(&fpi
, 0x55, sizeof(fpi
));
597 res
= pNtQueryInformationFile(handle
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
598 ok_(__FILE__
, line
)(!res
, "NtQueryInformationFile returned %x\n", res
);
599 ok_(__FILE__
, line
)(fpi
.ReadMode
== read
, "Unexpected ReadMode, expected %x, got %x\n",
601 ok_(__FILE__
, line
)(fpi
.CompletionMode
== completion
, "Unexpected CompletionMode, expected %x, got %x\n",
602 completion
, fpi
.CompletionMode
);
605 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
607 static void test_filepipeinfo(void)
609 IO_STATUS_BLOCK iosb
;
610 OBJECT_ATTRIBUTES attr
;
612 LARGE_INTEGER timeout
;
613 HANDLE hServer
, hClient
;
614 FILE_PIPE_INFORMATION fpi
;
617 pRtlInitUnicodeString(&name
, testpipe_nt
);
619 attr
.Length
= sizeof(attr
);
620 attr
.RootDirectory
= 0;
621 attr
.ObjectName
= &name
;
622 attr
.Attributes
= 0x40; /* case insensitive */
623 attr
.SecurityDescriptor
= NULL
;
624 attr
.SecurityQualityOfService
= NULL
;
626 timeout
.QuadPart
= -100000000;
628 /* test with INVALID_HANDLE_VALUE */
629 res
= pNtQueryInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
630 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtQueryInformationFile returned %x\n", res
);
633 fpi
.CompletionMode
= 0;
634 res
= pNtSetInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
635 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtSetInformationFile returned %x\n", res
);
637 /* server end with read-only attributes */
638 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
639 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
640 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout
);
641 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
643 check_pipe_handle_state(hServer
, 0, 1);
645 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
646 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
647 "can't open pipe, GetLastError: %x\n", GetLastError());
649 check_pipe_handle_state(hServer
, 0, 1);
650 check_pipe_handle_state(hClient
, 0, 0);
653 fpi
.CompletionMode
= 0;
654 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
655 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
657 check_pipe_handle_state(hServer
, 0, 1);
658 check_pipe_handle_state(hClient
, 0, 0);
660 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
661 fpi
.CompletionMode
= 1;
662 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
663 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
665 check_pipe_handle_state(hServer
, 0, 1);
666 check_pipe_handle_state(hClient
, 0, 0);
668 if (hClient
!= INVALID_HANDLE_VALUE
)
670 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
671 fpi
.CompletionMode
= 1;
672 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
673 ok(res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile returned %x\n", res
);
676 check_pipe_handle_state(hServer
, 0, 1);
677 check_pipe_handle_state(hClient
, 0, 0);
679 if (hClient
!= INVALID_HANDLE_VALUE
)
682 fpi
.CompletionMode
= 1;
683 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
684 ok(!res
, "NtSetInformationFile returned %x\n", res
);
687 check_pipe_handle_state(hServer
, 0, 1);
688 check_pipe_handle_state(hClient
, 0, 1);
690 if (hClient
!= INVALID_HANDLE_VALUE
)
693 fpi
.CompletionMode
= 2; /* not in range 0-1 */
694 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
695 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
697 fpi
.ReadMode
= 2; /* not in range 0-1 */
698 fpi
.CompletionMode
= 0;
699 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
700 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
703 CloseHandle(hClient
);
705 check_pipe_handle_state(hServer
, 0, 1);
708 fpi
.CompletionMode
= 0;
709 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
710 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
712 CloseHandle(hServer
);
714 /* message mode server with read/write attributes */
715 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
716 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
717 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
718 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
720 check_pipe_handle_state(hServer
, 1, 0);
722 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
723 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
724 "can't open pipe, GetLastError: %x\n", GetLastError());
726 check_pipe_handle_state(hServer
, 1, 0);
727 check_pipe_handle_state(hClient
, 0, 0);
729 if (hClient
!= INVALID_HANDLE_VALUE
)
732 fpi
.CompletionMode
= 1;
733 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
734 ok(!res
, "NtSetInformationFile returned %x\n", res
);
737 check_pipe_handle_state(hServer
, 1, 0);
738 check_pipe_handle_state(hClient
, 1, 1);
741 fpi
.CompletionMode
= 1;
742 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
743 ok(!res
, "NtSetInformationFile returned %x\n", res
);
745 check_pipe_handle_state(hServer
, 0, 1);
746 check_pipe_handle_state(hClient
, 1, 1);
748 if (hClient
!= INVALID_HANDLE_VALUE
)
751 fpi
.CompletionMode
= 2; /* not in range 0-1 */
752 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
753 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
755 fpi
.ReadMode
= 2; /* not in range 0-1 */
756 fpi
.CompletionMode
= 0;
757 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
758 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
761 CloseHandle(hClient
);
763 check_pipe_handle_state(hServer
, 0, 1);
766 fpi
.CompletionMode
= 0;
767 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
768 ok(!res
, "NtSetInformationFile returned %x\n", res
);
770 check_pipe_handle_state(hServer
, 1, 0);
772 CloseHandle(hServer
);
775 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
779 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
782 static void test_peek(HANDLE pipe
, BOOL is_msgmode
)
784 FILE_PIPE_PEEK_BUFFER buf
;
785 IO_STATUS_BLOCK iosb
;
786 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
789 memset(&iosb
, 0x55, sizeof(iosb
));
790 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
791 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
792 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
793 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
796 memset(&iosb
, 0x55, sizeof(iosb
));
797 status
= NtFsControlFile(pipe
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
798 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
799 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
800 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
801 todo_wine_if(!is_msgmode
)
802 ok(is_signaled(event
), "event is not signaled\n");
807 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
809 static BOOL
create_pipe_pair( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG type
, ULONG size
)
811 const BOOL server_reader
= flags
& PIPE_ACCESS_INBOUND
;
812 HANDLE client
, server
;
814 server
= CreateNamedPipeA(PIPENAME
, flags
, PIPE_WAIT
| type
,
815 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
816 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
818 client
= CreateFileA(PIPENAME
, server_reader
? GENERIC_WRITE
: GENERIC_READ
| FILE_WRITE_ATTRIBUTES
, 0,
819 NULL
, OPEN_EXISTING
, flags
& FILE_FLAG_OVERLAPPED
, 0);
820 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
829 if(type
& PIPE_READMODE_MESSAGE
)
831 DWORD read_mode
= PIPE_READMODE_MESSAGE
;
832 ok(SetNamedPipeHandleState(client
, &read_mode
, NULL
, NULL
), "Change mode\n");
841 static void read_pipe_test(ULONG pipe_flags
, ULONG pipe_type
)
843 IO_STATUS_BLOCK iosb
, iosb2
;
844 HANDLE handle
, read
, write
;
845 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
852 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
854 /* try read with no data */
855 U(iosb
).Status
= 0xdeadbabe;
856 iosb
.Information
= 0xdeadbeef;
857 ok( is_signaled( read
), "read handle is not signaled\n" );
858 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
859 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
860 ok( !is_signaled( read
), "read handle is signaled\n" );
861 ok( !is_signaled( event
), "event is signaled\n" );
862 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
863 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
864 ok( !apc_count
, "apc was called\n" );
865 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
866 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
867 /* iosb updated here by async i/o */
868 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
869 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
870 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
871 ok( !is_signaled( read
), "read handle is signaled\n" );
872 ok( is_signaled( event
), "event is not signaled\n" );
873 ok( !apc_count
, "apc was called\n" );
875 SleepEx( 1, FALSE
); /* non-alertable sleep */
876 ok( !apc_count
, "apc was called\n" );
877 SleepEx( 1, TRUE
); /* alertable sleep */
878 ok( apc_count
== 1, "apc not called\n" );
880 /* with no event, the pipe handle itself gets signaled */
882 U(iosb
).Status
= 0xdeadbabe;
883 iosb
.Information
= 0xdeadbeef;
884 ok( !is_signaled( read
), "read handle is signaled\n" );
885 status
= NtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
886 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
887 ok( !is_signaled( read
), "read handle is signaled\n" );
888 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
889 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
890 ok( !apc_count
, "apc was called\n" );
891 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
892 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
893 /* iosb updated here by async i/o */
894 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
895 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
896 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
897 ok( is_signaled( read
), "read handle is not signaled\n" );
898 ok( !apc_count
, "apc was called\n" );
900 SleepEx( 1, FALSE
); /* non-alertable sleep */
901 ok( !apc_count
, "apc was called\n" );
902 SleepEx( 1, TRUE
); /* alertable sleep */
903 ok( apc_count
== 1, "apc not called\n" );
905 /* now read with data ready */
907 U(iosb
).Status
= 0xdeadbabe;
908 iosb
.Information
= 0xdeadbeef;
910 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
911 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
913 test_peek(read
, pipe_type
& PIPE_TYPE_MESSAGE
);
915 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
916 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
917 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
918 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
919 ok( is_signaled( event
), "event is not signaled\n" );
920 ok( !apc_count
, "apc was called\n" );
921 SleepEx( 1, FALSE
); /* non-alertable sleep */
922 ok( !apc_count
, "apc was called\n" );
923 SleepEx( 1, TRUE
); /* alertable sleep */
924 ok( apc_count
== 1, "apc not called\n" );
926 /* now partial read with data ready */
928 U(iosb
).Status
= 0xdeadbabe;
929 iosb
.Information
= 0xdeadbeef;
931 ret
= WriteFile( write
, buffer
, 2, &written
, NULL
);
932 ok(ret
&& written
== 2, "WriteFile error %d\n", GetLastError());
933 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
934 if (pipe_type
& PIPE_READMODE_MESSAGE
)
936 ok( status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", status
);
937 ok( U(iosb
).Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", U(iosb
).Status
);
941 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
942 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
944 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
945 ok( is_signaled( event
), "event is not signaled\n" );
946 ok( !apc_count
, "apc was called\n" );
947 SleepEx( 1, FALSE
); /* non-alertable sleep */
948 ok( !apc_count
, "apc was called\n" );
949 SleepEx( 1, TRUE
); /* alertable sleep */
950 ok( apc_count
== 1, "apc not called\n" );
952 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
953 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
954 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
955 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
956 ok( is_signaled( event
), "event is not signaled\n" );
957 ok( !apc_count
, "apc was called\n" );
958 SleepEx( 1, FALSE
); /* non-alertable sleep */
959 ok( !apc_count
, "apc was called\n" );
960 SleepEx( 1, TRUE
); /* alertable sleep */
961 ok( apc_count
== 1, "apc not called\n" );
963 /* try read with no data */
965 U(iosb
).Status
= 0xdeadbabe;
966 iosb
.Information
= 0xdeadbeef;
967 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
968 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
969 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
970 ok( !is_signaled( event
), "event is signaled\n" );
971 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
972 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
973 ok( !apc_count
, "apc was called\n" );
974 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
975 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
976 /* partial read is good enough */
977 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
978 ok( is_signaled( event
), "event is not signaled\n" );
979 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
980 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
981 ok( !apc_count
, "apc was called\n" );
982 SleepEx( 1, TRUE
); /* alertable sleep */
983 ok( apc_count
== 1, "apc was not called\n" );
985 /* read from disconnected pipe */
987 U(iosb
).Status
= 0xdeadbabe;
988 iosb
.Information
= 0xdeadbeef;
989 CloseHandle( write
);
990 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
991 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", status
);
992 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
993 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
994 ok( !is_signaled( event
), "event is signaled\n" );
995 ok( !apc_count
, "apc was called\n" );
996 SleepEx( 1, TRUE
); /* alertable sleep */
997 ok( !apc_count
, "apc was called\n" );
1000 /* read from disconnected pipe, with invalid event handle */
1002 U(iosb
).Status
= 0xdeadbabe;
1003 iosb
.Information
= 0xdeadbeef;
1004 status
= NtReadFile( read
, (HANDLE
)0xdeadbeef, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1005 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1006 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1007 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1008 ok( !apc_count
, "apc was called\n" );
1009 SleepEx( 1, TRUE
); /* alertable sleep */
1010 ok( !apc_count
, "apc was called\n" );
1011 CloseHandle( read
);
1013 /* read from closed handle */
1015 U(iosb
).Status
= 0xdeadbabe;
1016 iosb
.Information
= 0xdeadbeef;
1018 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1019 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1020 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1021 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1022 ok( is_signaled( event
), "event is not signaled\n" ); /* not reset on invalid handle */
1023 ok( !apc_count
, "apc was called\n" );
1024 SleepEx( 1, TRUE
); /* alertable sleep */
1025 ok( !apc_count
, "apc was called\n" );
1027 /* disconnect while async read is in progress */
1028 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1030 U(iosb
).Status
= 0xdeadbabe;
1031 iosb
.Information
= 0xdeadbeef;
1032 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1033 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1034 ok( !is_signaled( event
), "event is signaled\n" );
1035 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1036 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1037 ok( !apc_count
, "apc was called\n" );
1038 CloseHandle( write
);
1039 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1040 todo_wine_if(!(pipe_type
& PIPE_TYPE_MESSAGE
) && (pipe_flags
& PIPE_ACCESS_OUTBOUND
))
1041 ok( U(iosb
).Status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", U(iosb
).Status
);
1042 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1043 ok( is_signaled( event
), "event is not signaled\n" );
1044 ok( !apc_count
, "apc was called\n" );
1045 SleepEx( 1, TRUE
); /* alertable sleep */
1046 ok( apc_count
== 1, "apc was not called\n" );
1047 CloseHandle( read
);
1049 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1050 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
1051 ok(ret
, "Failed to duplicate handle: %d\n", GetLastError());
1054 U(iosb
).Status
= 0xdeadbabe;
1055 iosb
.Information
= 0xdeadbeef;
1056 status
= NtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1057 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1058 ok( !is_signaled( event
), "event is signaled\n" );
1059 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1060 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1061 ok( !apc_count
, "apc was called\n" );
1062 /* Cancel by other handle */
1063 status
= pNtCancelIoFile( read
, &iosb2
);
1064 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %x\n", status
);
1065 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1066 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1067 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1068 ok( is_signaled( event
), "event is not signaled\n" );
1069 ok( !apc_count
, "apc was called\n" );
1070 SleepEx( 1, TRUE
); /* alertable sleep */
1071 ok( apc_count
== 1, "apc was not called\n" );
1074 U(iosb
).Status
= 0xdeadbabe;
1075 iosb
.Information
= 0xdeadbeef;
1076 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1077 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1078 ok( !is_signaled( event
), "event is signaled\n" );
1079 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1080 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1081 ok( !apc_count
, "apc was called\n" );
1082 /* Close queued handle */
1083 CloseHandle( read
);
1084 SleepEx( 1, TRUE
); /* alertable sleep */
1085 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1086 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1087 status
= pNtCancelIoFile( read
, &iosb2
);
1088 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
1089 status
= pNtCancelIoFile( handle
, &iosb2
);
1090 ok(status
== STATUS_SUCCESS
, "failed to cancel: %x\n", status
);
1091 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1092 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1093 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1094 ok( is_signaled( event
), "event is not signaled\n" );
1095 ok( !apc_count
, "apc was called\n" );
1096 SleepEx( 1, TRUE
); /* alertable sleep */
1097 ok( apc_count
== 1, "apc was not called\n" );
1098 CloseHandle( handle
);
1099 CloseHandle( write
);
1101 if (pNtCancelIoFileEx
)
1103 /* Basic Cancel Ex */
1104 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1107 U(iosb
).Status
= 0xdeadbabe;
1108 iosb
.Information
= 0xdeadbeef;
1109 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1110 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1111 ok( !is_signaled( event
), "event is signaled\n" );
1112 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1113 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1114 ok( !apc_count
, "apc was called\n" );
1115 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1116 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1117 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1118 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1119 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1120 ok( is_signaled( event
), "event is not signaled\n" );
1121 ok( !apc_count
, "apc was called\n" );
1122 SleepEx( 1, TRUE
); /* alertable sleep */
1123 ok( apc_count
== 1, "apc was not called\n" );
1125 /* Duplicate iosb */
1127 U(iosb
).Status
= 0xdeadbabe;
1128 iosb
.Information
= 0xdeadbeef;
1129 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1130 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1131 ok( !is_signaled( event
), "event is signaled\n" );
1132 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1133 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1134 ok( !apc_count
, "apc was called\n" );
1135 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1136 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1137 ok( !is_signaled( event
), "event is signaled\n" );
1138 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1139 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1140 ok( !apc_count
, "apc was called\n" );
1141 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1142 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1143 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1144 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1145 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1146 ok( is_signaled( event
), "event is not signaled\n" );
1147 ok( !apc_count
, "apc was called\n" );
1148 SleepEx( 1, TRUE
); /* alertable sleep */
1149 ok( apc_count
== 2, "apc was not called\n" );
1151 CloseHandle( read
);
1152 CloseHandle( write
);
1160 if (!init_func_ptrs())
1163 trace("starting invalid create tests\n");
1164 test_create_invalid();
1166 trace("starting create tests\n");
1169 trace("starting overlapped tests\n");
1172 trace("starting completion tests\n");
1175 trace("starting FILE_PIPE_INFORMATION tests\n");
1176 test_filepipeinfo();
1178 if (!pOpenThread
|| !pQueueUserAPC
)
1181 trace("starting alertable tests\n");
1184 trace("starting nonalertable tests\n");
1185 test_nonalertable();
1187 trace("starting cancelio tests\n");
1190 trace("starting byte read in byte mode client -> server\n");
1191 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_BYTE
);
1192 trace("starting byte read in message mode client -> server\n");
1193 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
);
1194 trace("starting message read in message mode client -> server\n");
1195 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
1196 trace("starting byte read in byte mode server -> client\n");
1197 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
);
1198 trace("starting byte read in message mode server -> client\n");
1199 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
);
1200 trace("starting message read in message mode server -> client\n");
1201 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);