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"
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 typedef struct _FILE_PIPE_WAIT_FOR_BUFFER
{
55 LARGE_INTEGER Timeout
;
57 BOOLEAN TimeoutSpecified
;
59 } FILE_PIPE_WAIT_FOR_BUFFER
, *PFILE_PIPE_WAIT_FOR_BUFFER
;
61 #ifndef FILE_SYNCHRONOUS_IO_ALERT
62 #define FILE_SYNCHRONOUS_IO_ALERT 0x10
65 #ifndef FILE_SYNCHRONOUS_IO_NONALERT
66 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20
69 #ifndef FSCTL_PIPE_LISTEN
70 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
73 #ifndef FSCTL_PIPE_WAIT
74 #define FSCTL_PIPE_WAIT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
79 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
, BOOL
*);
81 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
);
82 static NTSTATUS (WINAPI
*pNtCreateDirectoryObject
)(HANDLE
*, ACCESS_MASK
, OBJECT_ATTRIBUTES
*);
83 static NTSTATUS (WINAPI
*pNtCreateNamedPipeFile
) (PHANDLE handle
, ULONG access
,
84 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK iosb
,
85 ULONG sharing
, ULONG dispo
, ULONG options
,
86 ULONG pipe_type
, ULONG read_mode
,
87 ULONG completion_mode
, ULONG max_inst
,
88 ULONG inbound_quota
, ULONG outbound_quota
,
89 PLARGE_INTEGER timeout
);
90 static NTSTATUS (WINAPI
*pNtQueryInformationFile
) (IN HANDLE FileHandle
, OUT PIO_STATUS_BLOCK IoStatusBlock
, OUT PVOID FileInformation
, IN ULONG Length
, IN FILE_INFORMATION_CLASS FileInformationClass
);
91 static NTSTATUS (WINAPI
*pNtQueryObject
)(HANDLE
, OBJECT_INFORMATION_CLASS
, void *, ULONG
, ULONG
*);
92 static NTSTATUS (WINAPI
*pNtQueryVolumeInformationFile
)(HANDLE handle
, PIO_STATUS_BLOCK io
, void *buffer
, ULONG length
, FS_INFORMATION_CLASS info_class
);
93 static NTSTATUS (WINAPI
*pNtSetInformationFile
) (HANDLE handle
, PIO_STATUS_BLOCK io
, PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class);
94 static NTSTATUS (WINAPI
*pNtCancelIoFile
) (HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
95 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
) (HANDLE hFile
, IO_STATUS_BLOCK
*iosb
, IO_STATUS_BLOCK
*io_status
);
96 static NTSTATUS (WINAPI
*pNtCancelSynchronousIoFile
) (HANDLE hFile
, IO_STATUS_BLOCK
*iosb
, IO_STATUS_BLOCK
*io_status
);
97 static NTSTATUS (WINAPI
*pNtRemoveIoCompletion
)(HANDLE
, PULONG_PTR
, PULONG_PTR
, PIO_STATUS_BLOCK
, PLARGE_INTEGER
);
98 static void (WINAPI
*pRtlInitUnicodeString
) (PUNICODE_STRING target
, PCWSTR source
);
100 static HANDLE (WINAPI
*pOpenThread
)(DWORD dwDesiredAccess
, BOOL bInheritHandle
, DWORD dwThreadId
);
101 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
104 static BOOL
init_func_ptrs(void)
106 HMODULE module
= GetModuleHandleA("ntdll.dll");
108 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
109 trace("GetProcAddress(%s) failed\n", #name); \
113 loadfunc(NtFsControlFile
)
114 loadfunc(NtCreateDirectoryObject
)
115 loadfunc(NtCreateNamedPipeFile
)
116 loadfunc(NtQueryInformationFile
)
117 loadfunc(NtQueryObject
)
118 loadfunc(NtQueryVolumeInformationFile
)
119 loadfunc(NtSetInformationFile
)
120 loadfunc(NtCancelIoFile
)
121 loadfunc(NtCancelSynchronousIoFile
)
122 loadfunc(RtlInitUnicodeString
)
123 loadfunc(NtRemoveIoCompletion
)
126 pNtCancelIoFileEx
= (void *)GetProcAddress(module
, "NtCancelIoFileEx");
127 module
= GetModuleHandleA("kernel32.dll");
128 pOpenThread
= (void *)GetProcAddress(module
, "OpenThread");
129 pQueueUserAPC
= (void *)GetProcAddress(module
, "QueueUserAPC");
130 pIsWow64Process
= (void *)GetProcAddress(module
, "IsWow64Process");
134 static HANDLE
create_process(const char *arg
)
136 STARTUPINFOA si
= { 0 };
137 PROCESS_INFORMATION pi
;
138 char cmdline
[MAX_PATH
];
143 winetest_get_mainargs(&argv
);
144 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
145 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
146 ok(ret
, "got %lu.\n", GetLastError());
147 ret
= CloseHandle(pi
.hThread
);
148 ok(ret
, "got %lu.\n", GetLastError());
152 static inline BOOL
is_signaled( HANDLE obj
)
154 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
157 #define test_file_access(a,b) _test_file_access(__LINE__,a,b)
158 static void _test_file_access(unsigned line
, HANDLE handle
, DWORD expected_access
)
160 FILE_ACCESS_INFORMATION info
;
164 memset(&info
, 0x11, sizeof(info
));
165 status
= NtQueryInformationFile(handle
, &io
, &info
, sizeof(info
), FileAccessInformation
);
166 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
167 ok_(__FILE__
,line
)(info
.AccessFlags
== expected_access
, "got access %08lx expected %08lx\n",
168 info
.AccessFlags
, expected_access
);
171 static const WCHAR testpipe
[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
172 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
173 static const WCHAR testpipe_nt
[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
174 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
176 static NTSTATUS
create_pipe(PHANDLE handle
, ULONG access
, ULONG sharing
, ULONG options
)
178 IO_STATUS_BLOCK iosb
;
179 OBJECT_ATTRIBUTES attr
;
181 LARGE_INTEGER timeout
;
184 pRtlInitUnicodeString(&name
, testpipe_nt
);
186 attr
.Length
= sizeof(attr
);
187 attr
.RootDirectory
= 0;
188 attr
.ObjectName
= &name
;
189 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
190 attr
.SecurityDescriptor
= NULL
;
191 attr
.SecurityQualityOfService
= NULL
;
193 timeout
.QuadPart
= -100000000;
195 res
= pNtCreateNamedPipeFile(handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| access
, &attr
, &iosb
, sharing
,
196 FILE_CREATE
, options
, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
200 static BOOL ioapc_called
;
201 static void CALLBACK
ioapc(void *arg
, PIO_STATUS_BLOCK io
, ULONG reserved
)
206 static NTSTATUS
listen_pipe(HANDLE hPipe
, HANDLE hEvent
, PIO_STATUS_BLOCK iosb
, BOOL use_apc
)
210 ioapc_called
= FALSE
;
212 return pNtFsControlFile(hPipe
, hEvent
, use_apc
? &ioapc
: NULL
, use_apc
? &dummy
: NULL
, iosb
, FSCTL_PIPE_LISTEN
, 0, 0, 0, 0);
215 static NTSTATUS
wait_pipe(HANDLE handle
, PUNICODE_STRING name
, const LARGE_INTEGER
* timeout
)
219 OBJECT_ATTRIBUTES attr
;
220 IO_STATUS_BLOCK iosb
;
221 FILE_PIPE_WAIT_FOR_BUFFER
*pipe_wait
;
222 ULONG pipe_wait_size
;
224 pipe_wait_size
= offsetof(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) + name
->Length
;
225 pipe_wait
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pipe_wait_size
);
226 if (!pipe_wait
) return STATUS_NO_MEMORY
;
228 pipe_wait
->TimeoutSpecified
= !!timeout
;
229 pipe_wait
->NameLength
= name
->Length
;
230 if (timeout
) pipe_wait
->Timeout
= *timeout
;
231 memcpy(pipe_wait
->Name
, name
->Buffer
, name
->Length
);
233 InitializeObjectAttributes(&attr
, NULL
, 0, 0, NULL
);
234 status
= NtCreateEvent(&event
, GENERIC_ALL
, &attr
, NotificationEvent
, FALSE
);
235 if (status
!= STATUS_SUCCESS
)
237 ok(0, "NtCreateEvent failure: %#lx\n", status
);
238 HeapFree(GetProcessHeap(), 0, pipe_wait
);
242 memset(&iosb
, 0, sizeof(iosb
));
243 iosb
.Status
= STATUS_PENDING
;
244 status
= pNtFsControlFile(handle
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_WAIT
,
245 pipe_wait
, pipe_wait_size
, NULL
, 0);
246 if (status
== STATUS_PENDING
)
248 WaitForSingleObject(event
, INFINITE
);
249 status
= iosb
.Status
;
253 HeapFree(GetProcessHeap(), 0, pipe_wait
);
257 static void test_create_invalid(void)
259 IO_STATUS_BLOCK iosb
;
260 OBJECT_ATTRIBUTES attr
;
262 LARGE_INTEGER timeout
;
264 HANDLE handle
, handle2
;
265 FILE_PIPE_LOCAL_INFORMATION info
;
267 pRtlInitUnicodeString(&name
, testpipe_nt
);
269 attr
.Length
= sizeof(attr
);
270 attr
.RootDirectory
= 0;
271 attr
.ObjectName
= &name
;
272 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
273 attr
.SecurityDescriptor
= NULL
;
274 attr
.SecurityQualityOfService
= NULL
;
276 timeout
.QuadPart
= -100000000;
278 /* create a pipe with FILE_OVERWRITE */
279 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 4 /*FILE_OVERWRITE*/,
280 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
281 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %lx\n", res
);
285 /* create a pipe with FILE_OVERWRITE_IF */
286 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 5 /*FILE_OVERWRITE_IF*/,
287 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
288 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %lx\n", res
);
292 /* create a pipe with sharing = 0 */
293 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, 0, 2 /*FILE_CREATE*/,
294 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
295 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %lx\n", res
);
299 /* create a pipe without r/w access */
300 res
= pNtCreateNamedPipeFile(&handle
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
301 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
302 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
304 res
= pNtQueryInformationFile(handle
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
305 ok(res
== STATUS_ACCESS_DENIED
, "NtQueryInformationFile returned %lx\n", res
);
307 /* test FILE_CREATE creation disposition */
308 res
= pNtCreateNamedPipeFile(&handle2
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
309 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
310 ok(res
== STATUS_ACCESS_DENIED
, "NtCreateNamedPipeFile returned %lx\n", res
);
312 CloseHandle(handle2
);
317 static void test_create(void)
322 FILE_PIPE_LOCAL_INFORMATION info
;
323 IO_STATUS_BLOCK iosb
;
324 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
326 static const DWORD access
[] = { 0, GENERIC_READ
, GENERIC_WRITE
, GENERIC_READ
| GENERIC_WRITE
};
327 static const DWORD sharing
[] = { FILE_SHARE_READ
, FILE_SHARE_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
};
328 static const DWORD pipe_config
[]= { 1, 0, 2 };
330 for (j
= 0; j
< ARRAY_SIZE(sharing
); j
++) {
331 for (k
= 0; k
< ARRAY_SIZE(access
); k
++) {
333 BOOL should_succeed
= TRUE
;
335 res
= create_pipe(&hserver
, 0, sharing
[j
], 0);
337 ok(0, "NtCreateNamedPipeFile returned %lx, sharing: %lx\n", res
, sharing
[j
]);
341 res
= listen_pipe(hserver
, hEvent
, &iosb
, FALSE
);
342 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %lx\n", res
);
344 res
= pNtQueryInformationFile(hserver
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
345 ok(!res
, "NtQueryInformationFile for server returned %lx, sharing: %lx\n", res
, sharing
[j
]);
346 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %ld, expected %ld\n",
347 info
.NamedPipeConfiguration
, pipe_config
[j
]);
349 hclient
= CreateFileW(testpipe
, access
[k
], 0, 0, OPEN_EXISTING
, 0, 0);
350 if (hclient
!= INVALID_HANDLE_VALUE
) {
351 res
= pNtQueryInformationFile(hclient
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
352 ok(!res
, "NtQueryInformationFile for client returned %lx, access: %lx, sharing: %lx\n",
353 res
, access
[k
], sharing
[j
]);
354 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %ld, expected %ld\n",
355 info
.NamedPipeConfiguration
, pipe_config
[j
]);
357 res
= listen_pipe(hclient
, hEvent
, &iosb
, FALSE
);
358 ok(res
== STATUS_ILLEGAL_FUNCTION
, "expected STATUS_ILLEGAL_FUNCTION, got %lx\n", res
);
359 CloseHandle(hclient
);
362 if (access
[k
] & GENERIC_WRITE
)
363 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_WRITE
);
364 if (access
[k
] & GENERIC_READ
)
365 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_READ
);
368 ok(hclient
!= INVALID_HANDLE_VALUE
, "CreateFile failed for sharing %lx, access: %lx, GetLastError: %ld\n",
369 sharing
[j
], access
[k
], GetLastError());
371 ok(hclient
== INVALID_HANDLE_VALUE
, "CreateFile succeeded for sharing %lx, access: %lx\n", sharing
[j
], access
[k
]);
373 CloseHandle(hserver
);
379 static void test_overlapped(void)
381 IO_STATUS_BLOCK iosb
;
387 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
388 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %lx\n", GetLastError());
390 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
391 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
393 memset(&iosb
, 0x55, sizeof(iosb
));
394 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
395 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %lx\n", res
);
396 ok(iosb
.Status
== 0x55555555, "iosb.Status got changed to %lx\n", iosb
.Status
);
398 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
399 ok(hClient
!= INVALID_HANDLE_VALUE
, "can't open pipe, GetLastError: %lx\n", GetLastError());
401 ok(iosb
.Status
== 0, "Wrong iostatus %lx\n", iosb
.Status
);
402 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
404 ok(!ioapc_called
, "IOAPC ran too early\n");
406 SleepEx(0, TRUE
); /* alertable wait state */
408 ok(ioapc_called
, "IOAPC didn't run\n");
411 CloseHandle(hClient
);
413 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
414 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
416 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
417 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
418 "can't open pipe, GetLastError: %lx\n", GetLastError());
420 if (hClient
!= INVALID_HANDLE_VALUE
)
423 memset(&iosb
, 0x55, sizeof(iosb
));
424 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
425 ok(res
== STATUS_PIPE_CONNECTED
, "NtFsControlFile returned %lx\n", res
);
426 ok(iosb
.Status
== 0x55555555, "iosb.Status got changed to %lx\n", iosb
.Status
);
427 ok(!is_signaled(hEvent
), "hEvent not signaled\n");
429 CloseHandle(hClient
);
436 static BOOL userapc_called
;
437 static void CALLBACK
userapc(ULONG_PTR dwParam
)
439 userapc_called
= TRUE
;
442 static BOOL open_succeeded
;
443 static DWORD WINAPI
thread(PVOID main_thread
)
451 userapc_called
= FALSE
;
452 ret
= pQueueUserAPC(&userapc
, main_thread
, 0);
453 ok(ret
, "can't queue user apc, GetLastError: %lx\n", GetLastError());
454 CloseHandle(main_thread
);
459 h
= CreateFileW(testpipe
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
461 if (h
!= INVALID_HANDLE_VALUE
) {
462 open_succeeded
= TRUE
;
466 open_succeeded
= FALSE
;
471 static void test_alertable(void)
473 IO_STATUS_BLOCK iosb
;
480 memset(&iosb
, 0x55, sizeof(iosb
));
482 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
483 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %lx\n", GetLastError());
485 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
486 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
488 /* queue an user apc before calling listen */
489 userapc_called
= FALSE
;
490 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
491 ok(ret
, "can't queue user apc, GetLastError: %lx\n", GetLastError());
493 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
494 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %lx\n", res
);
496 ok(userapc_called
, "user apc didn't run\n");
497 ok(iosb
.Status
== 0x55555555, "iosb.Status got changed to %lx\n", iosb
.Status
);
498 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
499 ok(!ioapc_called
, "IOAPC ran\n");
501 /* queue an user apc from a different thread */
502 hThread
= CreateThread(NULL
, 0, &thread
, pOpenThread(MAXIMUM_ALLOWED
, FALSE
, GetCurrentThreadId()), 0, 0);
503 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %lx\n", GetLastError());
505 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
506 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
507 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
508 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %lx\n", res
);
510 ok(userapc_called
, "user apc didn't run\n");
511 ok(iosb
.Status
== 0x55555555, "iosb.Status got changed to %lx\n", iosb
.Status
);
512 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
513 ok(!ioapc_called
, "IOAPC ran\n");
515 WaitForSingleObject(hThread
, INFINITE
);
517 SleepEx(0, TRUE
); /* get rid of the userapc, if NtFsControlFile failed */
519 ok(open_succeeded
, "couldn't open client side pipe\n");
521 CloseHandle(hThread
);
522 DisconnectNamedPipe(hPipe
);
524 /* finally try without an apc */
525 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
526 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %lx\n", GetLastError());
528 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
529 ok(!res
, "NtFsControlFile returned %lx\n", res
);
531 ok(open_succeeded
, "couldn't open client side pipe\n");
532 ok(!iosb
.Status
, "Wrong iostatus %lx\n", iosb
.Status
);
533 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
535 WaitForSingleObject(hThread
, INFINITE
);
536 CloseHandle(hThread
);
541 static void test_nonalertable(void)
543 IO_STATUS_BLOCK iosb
;
550 memset(&iosb
, 0x55, sizeof(iosb
));
552 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
553 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %lx\n", GetLastError());
555 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
556 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
558 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
559 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %lx\n", GetLastError());
561 userapc_called
= FALSE
;
562 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
563 ok(ret
, "can't queue user apc, GetLastError: %lx\n", GetLastError());
565 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
566 ok(!res
, "NtFsControlFile returned %lx\n", res
);
568 ok(open_succeeded
, "couldn't open client side pipe\n");
569 ok(!iosb
.Status
, "Wrong iostatus %lx\n", iosb
.Status
);
570 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
572 ok(!ioapc_called
, "IOAPC ran too early\n");
573 ok(!userapc_called
, "user apc ran too early\n");
575 SleepEx(0, TRUE
); /* alertable wait state */
577 ok(ioapc_called
, "IOAPC didn't run\n");
578 ok(userapc_called
, "user apc didn't run\n");
580 WaitForSingleObject(hThread
, INFINITE
);
581 CloseHandle(hThread
);
586 static void test_cancelio(void)
588 IO_STATUS_BLOCK iosb
;
589 IO_STATUS_BLOCK cancel_sb
;
594 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
595 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %lx\n", GetLastError());
597 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
598 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
600 memset(&iosb
, 0x55, sizeof(iosb
));
602 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
603 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %lx\n", res
);
605 res
= pNtCancelIoFile(hPipe
, &cancel_sb
);
606 ok(!res
, "NtCancelIoFile returned %lx\n", res
);
608 ok(iosb
.Status
== STATUS_CANCELLED
, "Wrong iostatus %lx\n", iosb
.Status
);
609 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
611 ok(!ioapc_called
, "IOAPC ran too early\n");
613 SleepEx(0, TRUE
); /* alertable wait state */
615 ok(ioapc_called
, "IOAPC didn't run\n");
619 if (pNtCancelIoFileEx
)
621 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
622 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
624 memset(&iosb
, 0x55, sizeof(iosb
));
625 res
= listen_pipe(hPipe
, hEvent
, &iosb
, FALSE
);
626 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %lx\n", res
);
628 res
= pNtCancelIoFileEx(hPipe
, &iosb
, &cancel_sb
);
629 ok(!res
, "NtCancelIoFileEx returned %lx\n", res
);
631 ok(iosb
.Status
== STATUS_CANCELLED
, "Wrong iostatus %lx\n", iosb
.Status
);
632 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
637 win_skip("NtCancelIoFileEx not available\n");
642 struct synchronousio_thread_args
645 IO_STATUS_BLOCK iosb
;
648 static DWORD WINAPI
synchronousio_thread(void *arg
)
650 struct synchronousio_thread_args
*ctx
= arg
;
653 res
= listen_pipe(ctx
->pipe
, NULL
, &ctx
->iosb
, FALSE
);
654 ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %lx\n", res
);
658 static void test_cancelsynchronousio(void)
665 IO_STATUS_BLOCK iosb
;
666 struct synchronousio_thread_args ctx
;
669 res
= pNtCancelSynchronousIoFile((HANDLE
)0xdeadbeef, NULL
, &iosb
);
670 ok(res
== STATUS_INVALID_HANDLE
, "NtCancelSynchronousIoFile returned %lx\n", res
);
671 res
= pNtCancelSynchronousIoFile(GetCurrentThread(), NULL
, NULL
);
672 ok(res
== STATUS_ACCESS_VIOLATION
, "NtCancelSynchronousIoFile returned %lx\n", res
);
673 res
= pNtCancelSynchronousIoFile(GetCurrentThread(), NULL
, (IO_STATUS_BLOCK
*)0xdeadbeef);
674 ok(res
== STATUS_ACCESS_VIOLATION
, "NtCancelSynchronousIoFile returned %lx\n", res
);
675 memset(&iosb
, 0x55, sizeof(iosb
));
676 res
= pNtCancelSynchronousIoFile(GetCurrentThread(), (IO_STATUS_BLOCK
*)0xdeadbeef, &iosb
);
677 ok(res
== STATUS_NOT_FOUND
|| broken(is_wow64
&& res
== STATUS_ACCESS_VIOLATION
),
678 "NtCancelSynchronousIoFile returned %lx\n", res
);
679 if (res
!= STATUS_ACCESS_VIOLATION
)
681 ok(iosb
.Status
== STATUS_NOT_FOUND
, "iosb.Status got changed to %lx\n", iosb
.Status
);
682 ok(iosb
.Information
== 0, "iosb.Information got changed to %Iu\n", iosb
.Information
);
685 /* synchronous i/o */
686 res
= create_pipe(&ctx
.pipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
687 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
690 ctx
.iosb
.Status
= 0xdeadbabe;
691 ctx
.iosb
.Information
= 0xdeadbeef;
692 thread
= CreateThread(NULL
, 0, synchronousio_thread
, &ctx
, 0, 0);
693 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
694 while ((ret
= WaitForSingleObject(ctx
.pipe
, 0)) == WAIT_OBJECT_0
) Sleep(1);
695 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lu (error %lu)\n", ret
, GetLastError());
696 memset(&iosb
, 0x55, sizeof(iosb
));
697 res
= pNtCancelSynchronousIoFile(thread
, NULL
, &iosb
);
698 ok(res
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
699 ok(iosb
.Status
== STATUS_SUCCESS
, "iosb.Status got changed to %lx\n", iosb
.Status
);
700 ok(iosb
.Information
== 0, "iosb.Information got changed to %Iu\n", iosb
.Information
);
701 ret
= WaitForSingleObject(thread
, 1000);
702 ok(ret
== WAIT_OBJECT_0
, "wait returned %lx\n", ret
);
704 CloseHandle(ctx
.pipe
);
705 ok(ctx
.iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", ctx
.iosb
.Status
);
706 ok(ctx
.iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", ctx
.iosb
.Information
);
709 res
= create_pipe(&ctx
.pipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
710 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
712 ctx
.iosb
.Status
= 0xdeadbabe;
713 ctx
.iosb
.Information
= 0xdeadbeef;
714 thread
= CreateThread(NULL
, 0, synchronousio_thread
, &ctx
, 0, 0);
715 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
716 while ((ret
= WaitForSingleObject(ctx
.pipe
, 0)) == WAIT_OBJECT_0
) Sleep(1);
717 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lu (error %lu)\n", ret
, GetLastError());
718 memset(&iosb
, 0x55, sizeof(iosb
));
719 res
= pNtCancelSynchronousIoFile(thread
, &iosb
, &iosb
);
720 ok(res
== STATUS_NOT_FOUND
, "NtCancelSynchronousIoFile returned %lx\n", res
);
721 res
= pNtCancelSynchronousIoFile(NULL
, &ctx
.iosb
, &iosb
);
722 ok(res
== STATUS_INVALID_HANDLE
, "NtCancelSynchronousIoFile returned %lx\n", res
);
723 res
= pNtCancelSynchronousIoFile(thread
, &ctx
.iosb
, &iosb
);
724 ok(res
== STATUS_SUCCESS
|| broken(is_wow64
&& res
== STATUS_NOT_FOUND
),
725 "Failed to cancel I/O\n");
726 ok(iosb
.Status
== STATUS_SUCCESS
|| broken(is_wow64
&& iosb
.Status
== STATUS_NOT_FOUND
),
727 "iosb.Status got changed to %lx\n", iosb
.Status
);
728 ok(iosb
.Information
== 0, "iosb.Information got changed to %Iu\n", iosb
.Information
);
729 if (res
== STATUS_NOT_FOUND
)
731 res
= pNtCancelSynchronousIoFile(thread
, NULL
, &iosb
);
732 ok(res
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
733 ok(iosb
.Status
== STATUS_SUCCESS
, "iosb.Status got changed to %lx\n", iosb
.Status
);
735 ret
= WaitForSingleObject(thread
, 1000);
736 ok(ret
== WAIT_OBJECT_0
, "wait returned %lx\n", ret
);
738 CloseHandle(ctx
.pipe
);
739 ok(ctx
.iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", ctx
.iosb
.Status
);
740 ok(ctx
.iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", ctx
.iosb
.Information
);
742 /* asynchronous i/o */
743 ctx
.iosb
.Status
= 0xdeadbabe;
744 ctx
.iosb
.Information
= 0xdeadbeef;
745 res
= create_pipe(&ctx
.pipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
746 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
747 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
748 ok(event
!= INVALID_HANDLE_VALUE
, "Can't create event, GetLastError: %lx\n", GetLastError());
749 res
= listen_pipe(ctx
.pipe
, event
, &ctx
.iosb
, FALSE
);
750 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %lx\n", res
);
751 memset(&iosb
, 0x55, sizeof(iosb
));
752 res
= pNtCancelSynchronousIoFile(GetCurrentThread(), NULL
, &iosb
);
753 ok(res
== STATUS_NOT_FOUND
, "NtCancelSynchronousIoFile returned %lx\n", res
);
754 ok(iosb
.Status
== STATUS_NOT_FOUND
, "iosb.Status got changed to %lx\n", iosb
.Status
);
755 ok(iosb
.Information
== 0, "iosb.Information got changed to %Iu\n", iosb
.Information
);
756 memset(&iosb
, 0x55, sizeof(iosb
));
757 res
= pNtCancelSynchronousIoFile(GetCurrentThread(), &ctx
.iosb
, &iosb
);
758 ok(res
== STATUS_NOT_FOUND
, "NtCancelSynchronousIoFile returned %lx\n", res
);
759 ok(iosb
.Status
== STATUS_NOT_FOUND
, "iosb.Status got changed to %lx\n", iosb
.Status
);
760 ok(iosb
.Information
== 0, "iosb.Information got changed to %Iu\n", iosb
.Information
);
761 ret
= WaitForSingleObject(event
, 0);
762 ok(ret
== WAIT_TIMEOUT
, "wait returned %lx\n", ret
);
763 client
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
764 FILE_FLAG_OVERLAPPED
, 0);
765 ok(client
!= INVALID_HANDLE_VALUE
, "can't open pipe: %lu\n", GetLastError());
766 ret
= WaitForSingleObject(event
, 0);
767 ok(ret
== WAIT_OBJECT_0
, "wait returned %lx\n", ret
);
768 CloseHandle(ctx
.pipe
);
773 static void _check_pipe_handle_state(int line
, HANDLE handle
, ULONG read
, ULONG completion
)
775 IO_STATUS_BLOCK iosb
;
776 FILE_PIPE_INFORMATION fpi
;
778 if (handle
!= INVALID_HANDLE_VALUE
)
780 memset(&fpi
, 0x55, sizeof(fpi
));
781 res
= pNtQueryInformationFile(handle
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
782 ok_(__FILE__
, line
)(!res
, "NtQueryInformationFile returned %lx\n", res
);
783 ok_(__FILE__
, line
)(fpi
.ReadMode
== read
, "Unexpected ReadMode, expected %lx, got %lx\n",
785 ok_(__FILE__
, line
)(fpi
.CompletionMode
== completion
, "Unexpected CompletionMode, expected %lx, got %lx\n",
786 completion
, fpi
.CompletionMode
);
789 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
791 static void test_filepipeinfo(void)
793 FILE_PIPE_LOCAL_INFORMATION local_info
;
794 IO_STATUS_BLOCK iosb
;
795 OBJECT_ATTRIBUTES attr
;
797 LARGE_INTEGER timeout
;
798 HANDLE hServer
, hClient
;
799 FILE_PIPE_INFORMATION fpi
;
802 pRtlInitUnicodeString(&name
, testpipe_nt
);
804 attr
.Length
= sizeof(attr
);
805 attr
.RootDirectory
= 0;
806 attr
.ObjectName
= &name
;
807 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
808 attr
.SecurityDescriptor
= NULL
;
809 attr
.SecurityQualityOfService
= NULL
;
811 timeout
.QuadPart
= -100000000;
813 /* test with INVALID_HANDLE_VALUE */
814 res
= pNtQueryInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
815 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtQueryInformationFile returned %lx\n", res
);
818 fpi
.CompletionMode
= 0;
819 res
= pNtSetInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
820 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtSetInformationFile returned %lx\n", res
);
822 /* server end with read-only attributes */
823 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
824 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
825 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout
);
826 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
828 check_pipe_handle_state(hServer
, 0, 1);
830 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
831 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
832 "can't open pipe, GetLastError: %lx\n", GetLastError());
834 check_pipe_handle_state(hServer
, 0, 1);
835 check_pipe_handle_state(hClient
, 0, 0);
838 fpi
.CompletionMode
= 0;
839 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
840 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %lx\n", res
);
842 check_pipe_handle_state(hServer
, 0, 1);
843 check_pipe_handle_state(hClient
, 0, 0);
845 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
846 fpi
.CompletionMode
= 1;
847 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
848 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %lx\n", res
);
850 check_pipe_handle_state(hServer
, 0, 1);
851 check_pipe_handle_state(hClient
, 0, 0);
853 if (hClient
!= INVALID_HANDLE_VALUE
)
855 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
856 fpi
.CompletionMode
= 1;
857 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
858 ok(res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile returned %lx\n", res
);
861 check_pipe_handle_state(hServer
, 0, 1);
862 check_pipe_handle_state(hClient
, 0, 0);
864 if (hClient
!= INVALID_HANDLE_VALUE
)
867 fpi
.CompletionMode
= 1;
868 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
869 ok(!res
, "NtSetInformationFile returned %lx\n", res
);
872 check_pipe_handle_state(hServer
, 0, 1);
873 check_pipe_handle_state(hClient
, 0, 1);
875 if (hClient
!= INVALID_HANDLE_VALUE
)
878 fpi
.CompletionMode
= 2; /* not in range 0-1 */
879 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
880 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %lx\n", res
);
882 fpi
.ReadMode
= 2; /* not in range 0-1 */
883 fpi
.CompletionMode
= 0;
884 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
885 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %lx\n", res
);
888 CloseHandle(hClient
);
890 check_pipe_handle_state(hServer
, 0, 1);
893 fpi
.CompletionMode
= 0;
894 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
895 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %lx\n", res
);
897 CloseHandle(hServer
);
899 /* message mode server with read/write attributes */
900 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
901 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
902 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
903 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
905 check_pipe_handle_state(hServer
, 1, 0);
907 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
908 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
909 "can't open pipe, GetLastError: %lx\n", GetLastError());
911 check_pipe_handle_state(hServer
, 1, 0);
912 check_pipe_handle_state(hClient
, 0, 0);
914 if (hClient
!= INVALID_HANDLE_VALUE
)
917 fpi
.CompletionMode
= 1;
918 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
919 ok(!res
, "NtSetInformationFile returned %lx\n", res
);
922 check_pipe_handle_state(hServer
, 1, 0);
923 check_pipe_handle_state(hClient
, 1, 1);
926 fpi
.CompletionMode
= 1;
927 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
928 ok(!res
, "NtSetInformationFile returned %lx\n", res
);
930 check_pipe_handle_state(hServer
, 0, 1);
931 check_pipe_handle_state(hClient
, 1, 1);
933 if (hClient
!= INVALID_HANDLE_VALUE
)
936 fpi
.CompletionMode
= 2; /* not in range 0-1 */
937 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
938 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %lx\n", res
);
940 fpi
.ReadMode
= 2; /* not in range 0-1 */
941 fpi
.CompletionMode
= 0;
942 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
943 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %lx\n", res
);
946 CloseHandle(hClient
);
948 check_pipe_handle_state(hServer
, 0, 1);
951 fpi
.CompletionMode
= 0;
952 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
953 ok(!res
, "NtSetInformationFile returned %lx\n", res
);
955 check_pipe_handle_state(hServer
, 1, 0);
957 CloseHandle(hServer
);
959 res
= pNtCreateNamedPipeFile(&hServer
,
960 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
961 &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_CREATE
,
962 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
963 ok(!res
, "NtCreateNamedPipeFile returned %lx\n", res
);
965 res
= NtCreateFile(&hClient
, SYNCHRONIZE
, &attr
, &iosb
, NULL
, 0,
966 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0 );
967 ok(!res
, "NtCreateFile returned %lx\n", res
);
969 test_file_access(hClient
, SYNCHRONIZE
);
971 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
972 FilePipeLocalInformation
);
973 ok(res
== STATUS_ACCESS_DENIED
,
974 "NtQueryInformationFile(FilePipeLocalInformation) returned: %lx\n", res
);
976 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
977 FilePipeInformation
);
978 ok(res
== STATUS_ACCESS_DENIED
,
979 "NtQueryInformationFile(FilePipeInformation) returned: %lx\n", res
);
981 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
982 FileNameInformation
);
983 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile(FileNameInformation) returned: %lx\n", res
);
985 CloseHandle(hClient
);
986 CloseHandle(hServer
);
989 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
993 ok( !reserved
, "reserved is not 0: %lx\n", reserved
);
996 static void test_peek(HANDLE pipe
)
998 FILE_PIPE_PEEK_BUFFER buf
;
999 IO_STATUS_BLOCK iosb
;
1000 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1003 memset(&iosb
, 0x55, sizeof(iosb
));
1004 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
1005 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %lx\n", status
);
1006 ok(!iosb
.Status
, "iosb.Status = %lx\n", iosb
.Status
);
1007 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %lu\n", buf
.ReadDataAvailable
);
1010 memset(&iosb
, 0x55, sizeof(iosb
));
1011 status
= NtFsControlFile(pipe
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
1012 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %lx\n", status
);
1013 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %lu\n", buf
.ReadDataAvailable
);
1014 ok(!iosb
.Status
, "iosb.Status = %lx\n", iosb
.Status
);
1015 ok(is_signaled(event
), "event is not signaled\n");
1020 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
1022 static BOOL
create_pipe_pair( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG type
, ULONG size
)
1024 HANDLE client
, server
;
1026 server
= CreateNamedPipeA(PIPENAME
, flags
, PIPE_WAIT
| type
,
1027 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
1028 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
1030 client
= CreateFileA(PIPENAME
, (flags
& PIPE_ACCESS_INBOUND
? GENERIC_WRITE
: 0)
1031 | (flags
& PIPE_ACCESS_OUTBOUND
? GENERIC_READ
: 0)
1032 | FILE_WRITE_ATTRIBUTES
, 0,
1033 NULL
, OPEN_EXISTING
, flags
& FILE_FLAG_OVERLAPPED
, 0);
1034 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%ld)\n", GetLastError());
1036 if ((type
& PIPE_READMODE_MESSAGE
) && (flags
& PIPE_ACCESS_OUTBOUND
))
1038 DWORD read_mode
= PIPE_READMODE_MESSAGE
;
1039 ok(SetNamedPipeHandleState(client
, &read_mode
, NULL
, NULL
), "Change mode\n");
1042 if (flags
& PIPE_ACCESS_INBOUND
)
1055 static void read_pipe_test(ULONG pipe_flags
, ULONG pipe_type
)
1057 IO_STATUS_BLOCK iosb
, iosb2
;
1058 HANDLE handle
, read
, write
;
1059 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1066 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1068 /* try read with no data */
1069 iosb
.Status
= 0xdeadbabe;
1070 iosb
.Information
= 0xdeadbeef;
1071 ok( is_signaled( read
), "read handle is not signaled\n" );
1072 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1073 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1074 ok( !is_signaled( read
), "read handle is signaled\n" );
1075 ok( !is_signaled( event
), "event is signaled\n" );
1076 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1077 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1078 ok( !apc_count
, "apc was called\n" );
1079 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
1080 ok(ret
&& written
== 1, "WriteFile error %ld\n", GetLastError());
1081 /* iosb updated here by async i/o */
1082 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1083 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1084 ok( !is_signaled( read
), "read handle is signaled\n" );
1085 ok( is_signaled( event
), "event is not signaled\n" );
1086 ok( !apc_count
, "apc was called\n" );
1088 SleepEx( 1, FALSE
); /* non-alertable sleep */
1089 ok( !apc_count
, "apc was called\n" );
1090 SleepEx( 1, TRUE
); /* alertable sleep */
1091 ok( apc_count
== 1, "apc not called\n" );
1093 /* with no event, the pipe handle itself gets signaled */
1095 iosb
.Status
= 0xdeadbabe;
1096 iosb
.Information
= 0xdeadbeef;
1097 ok( !is_signaled( read
), "read handle is signaled\n" );
1098 status
= NtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1099 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1100 ok( !is_signaled( read
), "read handle is signaled\n" );
1101 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1102 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1103 ok( !apc_count
, "apc was called\n" );
1104 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
1105 ok(ret
&& written
== 1, "WriteFile error %ld\n", GetLastError());
1106 /* iosb updated here by async i/o */
1107 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1108 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1109 ok( is_signaled( read
), "read handle is not signaled\n" );
1110 ok( !apc_count
, "apc was called\n" );
1112 SleepEx( 1, FALSE
); /* non-alertable sleep */
1113 ok( !apc_count
, "apc was called\n" );
1114 SleepEx( 1, TRUE
); /* alertable sleep */
1115 ok( apc_count
== 1, "apc not called\n" );
1117 /* now read with data ready */
1119 iosb
.Status
= 0xdeadbabe;
1120 iosb
.Information
= 0xdeadbeef;
1121 ResetEvent( event
);
1122 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
1123 ok(ret
&& written
== 1, "WriteFile error %ld\n", GetLastError());
1127 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1128 ok( status
== STATUS_SUCCESS
, "wrong status %lx\n", status
);
1129 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1130 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1131 ok( is_signaled( event
), "event is not signaled\n" );
1132 ok( !apc_count
, "apc was called\n" );
1133 SleepEx( 1, FALSE
); /* non-alertable sleep */
1134 ok( !apc_count
, "apc was called\n" );
1135 SleepEx( 1, TRUE
); /* alertable sleep */
1136 ok( apc_count
== 1, "apc not called\n" );
1138 /* now partial read with data ready */
1140 iosb
.Status
= 0xdeadbabe;
1141 iosb
.Information
= 0xdeadbeef;
1142 ResetEvent( event
);
1143 ret
= WriteFile( write
, buffer
, 2, &written
, NULL
);
1144 ok(ret
&& written
== 2, "WriteFile error %ld\n", GetLastError());
1146 memset( &iosb
, 0xcc, sizeof(iosb
) );
1147 status
= NtFsControlFile( read
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, buffer
,
1148 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[1]) );
1149 if (pipe_type
& PIPE_TYPE_MESSAGE
)
1151 ok( status
== STATUS_BUFFER_OVERFLOW
|| status
== STATUS_PENDING
,
1152 "FSCTL_PIPE_PEEK returned %lx\n", status
);
1153 ok( iosb
.Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %lx\n", iosb
.Status
);
1157 ok( !status
|| status
== STATUS_PENDING
, "FSCTL_PIPE_PEEK returned %lx\n", status
);
1158 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1160 ok( iosb
.Information
== FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[1]),
1161 "wrong info %Iu\n", iosb
.Information
);
1163 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1164 if (pipe_type
& PIPE_READMODE_MESSAGE
)
1166 ok( status
== STATUS_BUFFER_OVERFLOW
, "wrong status %lx\n", status
);
1167 ok( iosb
.Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %lx\n", iosb
.Status
);
1171 ok( status
== STATUS_SUCCESS
, "wrong status %lx\n", status
);
1172 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1174 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1175 ok( is_signaled( event
), "event is not signaled\n" );
1176 ok( !apc_count
, "apc was called\n" );
1177 SleepEx( 1, FALSE
); /* non-alertable sleep */
1178 ok( !apc_count
, "apc was called\n" );
1179 SleepEx( 1, TRUE
); /* alertable sleep */
1180 ok( apc_count
== 1, "apc not called\n" );
1182 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1183 ok( status
== STATUS_SUCCESS
, "wrong status %lx\n", status
);
1184 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1185 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1186 ok( is_signaled( event
), "event is not signaled\n" );
1187 ok( !apc_count
, "apc was called\n" );
1188 SleepEx( 1, FALSE
); /* non-alertable sleep */
1189 ok( !apc_count
, "apc was called\n" );
1190 SleepEx( 1, TRUE
); /* alertable sleep */
1191 ok( apc_count
== 1, "apc not called\n" );
1193 /* try read with no data */
1195 iosb
.Status
= 0xdeadbabe;
1196 iosb
.Information
= 0xdeadbeef;
1197 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
1198 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1199 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1200 ok( !is_signaled( event
), "event is signaled\n" );
1201 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1202 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1203 ok( !apc_count
, "apc was called\n" );
1204 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
1205 ok(ret
&& written
== 1, "WriteFile error %ld\n", GetLastError());
1206 /* partial read is good enough */
1207 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1208 ok( is_signaled( event
), "event is not signaled\n" );
1209 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1210 ok( iosb
.Information
== 1, "wrong info %Iu\n", iosb
.Information
);
1211 ok( !apc_count
, "apc was called\n" );
1212 SleepEx( 1, TRUE
); /* alertable sleep */
1213 ok( apc_count
== 1, "apc was not called\n" );
1215 /* read from disconnected pipe */
1217 iosb
.Status
= 0xdeadbabe;
1218 iosb
.Information
= 0xdeadbeef;
1219 CloseHandle( write
);
1220 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1221 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %lx\n", status
);
1222 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1223 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1224 ok( !is_signaled( event
), "event is signaled\n" );
1225 ok( !apc_count
, "apc was called\n" );
1226 SleepEx( 1, TRUE
); /* alertable sleep */
1227 ok( !apc_count
, "apc was called\n" );
1228 CloseHandle( read
);
1230 /* read from disconnected pipe, with invalid event handle */
1232 iosb
.Status
= 0xdeadbabe;
1233 iosb
.Information
= 0xdeadbeef;
1234 status
= NtReadFile( read
, (HANDLE
)0xdeadbeef, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1235 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %lx\n", status
);
1236 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1237 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1238 ok( !apc_count
, "apc was called\n" );
1239 SleepEx( 1, TRUE
); /* alertable sleep */
1240 ok( !apc_count
, "apc was called\n" );
1241 CloseHandle( read
);
1243 /* read from closed handle */
1245 iosb
.Status
= 0xdeadbabe;
1246 iosb
.Information
= 0xdeadbeef;
1248 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1249 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %lx\n", status
);
1250 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1251 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1252 ok( is_signaled( event
), "event is not signaled\n" ); /* not reset on invalid handle */
1253 ok( !apc_count
, "apc was called\n" );
1254 SleepEx( 1, TRUE
); /* alertable sleep */
1255 ok( !apc_count
, "apc was called\n" );
1257 /* disconnect while async read is in progress */
1258 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1260 iosb
.Status
= 0xdeadbabe;
1261 iosb
.Information
= 0xdeadbeef;
1262 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1263 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1264 ok( !is_signaled( event
), "event is signaled\n" );
1265 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1266 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1267 ok( !apc_count
, "apc was called\n" );
1268 CloseHandle( write
);
1269 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1270 ok( iosb
.Status
== STATUS_PIPE_BROKEN
, "wrong status %lx\n", iosb
.Status
);
1271 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
1272 ok( is_signaled( event
), "event is not signaled\n" );
1273 ok( !apc_count
, "apc was called\n" );
1274 SleepEx( 1, TRUE
); /* alertable sleep */
1275 ok( apc_count
== 1, "apc was not called\n" );
1276 CloseHandle( read
);
1278 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1279 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
1280 ok(ret
, "Failed to duplicate handle: %ld\n", GetLastError());
1283 iosb
.Status
= 0xdeadbabe;
1284 iosb
.Information
= 0xdeadbeef;
1285 status
= NtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1286 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1287 ok( !is_signaled( event
), "event is signaled\n" );
1288 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1289 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1290 ok( !apc_count
, "apc was called\n" );
1291 /* Cancel by other handle */
1292 status
= pNtCancelIoFile( read
, &iosb2
);
1293 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %lx\n", status
);
1294 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1295 ok( iosb
.Status
== STATUS_CANCELLED
, "wrong status %lx\n", iosb
.Status
);
1296 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
1297 ok( is_signaled( event
), "event is not signaled\n" );
1298 ok( !apc_count
, "apc was called\n" );
1299 SleepEx( 1, TRUE
); /* alertable sleep */
1300 ok( apc_count
== 1, "apc was not called\n" );
1303 iosb
.Status
= 0xdeadbabe;
1304 iosb
.Information
= 0xdeadbeef;
1305 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1306 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1307 ok( !is_signaled( event
), "event is signaled\n" );
1308 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1309 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1310 ok( !apc_count
, "apc was called\n" );
1311 /* Close queued handle */
1312 CloseHandle( read
);
1313 SleepEx( 1, TRUE
); /* alertable sleep */
1314 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1315 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1316 status
= pNtCancelIoFile( read
, &iosb2
);
1317 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
1318 status
= pNtCancelIoFile( handle
, &iosb2
);
1319 ok(status
== STATUS_SUCCESS
, "failed to cancel: %lx\n", status
);
1320 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1321 ok( iosb
.Status
== STATUS_CANCELLED
, "wrong status %lx\n", iosb
.Status
);
1322 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
1323 ok( is_signaled( event
), "event is not signaled\n" );
1324 ok( !apc_count
, "apc was called\n" );
1325 SleepEx( 1, TRUE
); /* alertable sleep */
1326 ok( apc_count
== 1, "apc was not called\n" );
1327 CloseHandle( handle
);
1328 CloseHandle( write
);
1330 if (pNtCancelIoFileEx
)
1332 /* Basic Cancel Ex */
1333 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1336 iosb
.Status
= 0xdeadbabe;
1337 iosb
.Information
= 0xdeadbeef;
1338 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1339 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1340 ok( !is_signaled( event
), "event is signaled\n" );
1341 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1342 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1343 ok( !apc_count
, "apc was called\n" );
1344 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1345 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1346 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1347 ok( iosb
.Status
== STATUS_CANCELLED
, "wrong status %lx\n", iosb
.Status
);
1348 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
1349 ok( is_signaled( event
), "event is not signaled\n" );
1350 ok( !apc_count
, "apc was called\n" );
1351 SleepEx( 1, TRUE
); /* alertable sleep */
1352 ok( apc_count
== 1, "apc was not called\n" );
1354 /* Duplicate iosb */
1356 iosb
.Status
= 0xdeadbabe;
1357 iosb
.Information
= 0xdeadbeef;
1358 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1359 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1360 ok( !is_signaled( event
), "event is signaled\n" );
1361 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1362 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1363 ok( !apc_count
, "apc was called\n" );
1364 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1365 ok( status
== STATUS_PENDING
, "wrong status %lx\n", status
);
1366 ok( !is_signaled( event
), "event is signaled\n" );
1367 ok( iosb
.Status
== 0xdeadbabe, "wrong status %lx\n", iosb
.Status
);
1368 ok( iosb
.Information
== 0xdeadbeef, "wrong info %Iu\n", iosb
.Information
);
1369 ok( !apc_count
, "apc was called\n" );
1370 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1371 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1372 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1373 ok( iosb
.Status
== STATUS_CANCELLED
, "wrong status %lx\n", iosb
.Status
);
1374 ok( iosb
.Information
== 0, "wrong info %Iu\n", iosb
.Information
);
1375 ok( is_signaled( event
), "event is not signaled\n" );
1376 ok( !apc_count
, "apc was called\n" );
1377 SleepEx( 1, TRUE
); /* alertable sleep */
1378 ok( apc_count
== 2, "apc was not called\n" );
1380 CloseHandle( read
);
1381 CloseHandle( write
);
1384 win_skip("NtCancelIoFileEx not available\n");
1389 static void test_transceive(void)
1391 IO_STATUS_BLOCK iosb
;
1392 HANDLE caller
, callee
;
1393 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1399 if (!create_pipe_pair( &caller
, &callee
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1400 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 )) return;
1402 status
= NtFsControlFile( caller
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_TRANSCEIVE
,
1403 (BYTE
*)"test", 4, buffer
, sizeof(buffer
) );
1404 ok( status
== STATUS_PENDING
, "NtFsControlFile(FSCTL_PIPE_TRANSCEIVE) returned %lx\n", status
);
1405 ok( !is_signaled( event
), "event is signaled\n" );
1407 ret
= WriteFile( callee
, buffer
, 2, &written
, NULL
);
1408 ok(ret
&& written
== 2, "WriteFile error %ld\n", GetLastError());
1410 ok( iosb
.Status
== 0, "wrong status %lx\n", iosb
.Status
);
1411 ok( iosb
.Information
== 2, "wrong info %Iu\n", iosb
.Information
);
1412 ok( is_signaled( event
), "event is not signaled\n" );
1414 CloseHandle( caller
);
1415 CloseHandle( callee
);
1418 #define test_no_queued_completion(a) _test_no_queued_completion(__LINE__,a)
1419 static void _test_no_queued_completion(unsigned line
, HANDLE port
)
1426 pov
= (void *)0xdeadbeef;
1427 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 10);
1428 ok_(__FILE__
,line
)(!ret
&& GetLastError() == WAIT_TIMEOUT
,
1429 "GetQueuedCompletionStatus returned %x(%lu)\n", ret
, GetLastError());
1432 #define test_queued_completion(a,b,c,d) _test_queued_completion(__LINE__,a,b,c,d)
1433 static void _test_queued_completion(unsigned line
, HANDLE port
, IO_STATUS_BLOCK
*io
,
1434 NTSTATUS expected_status
, ULONG expected_information
)
1436 LARGE_INTEGER timeout
= {{0}};
1437 ULONG_PTR value
= 0xdeadbeef;
1438 IO_STATUS_BLOCK iosb
;
1442 status
= pNtRemoveIoCompletion(port
, &key
, &value
, &iosb
, &timeout
);
1443 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
, "NtRemoveIoCompletion returned %lx\n", status
);
1444 ok_(__FILE__
,line
)(value
== (ULONG_PTR
)io
, "value = %Ix\n", value
);
1445 ok_(__FILE__
,line
)(io
->Status
== expected_status
, "Status = %lx\n", io
->Status
);
1446 ok_(__FILE__
,line
)(io
->Information
== expected_information
,
1447 "Information = %Iu\n", io
->Information
);
1450 static void test_completion(void)
1452 static const char buf
[] = "testdata";
1453 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
1454 FILE_PIPE_PEEK_BUFFER peek_buf
;
1456 HANDLE port
, pipe
, client
, event
;
1463 create_pipe_pair( &pipe
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1464 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 );
1466 status
= pNtQueryInformationFile(pipe
, &io
, &info
, sizeof(info
),
1467 FileIoCompletionNotificationInformation
);
1468 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_INVALID_INFO_CLASS
),
1469 "status = %lx\n", status
);
1472 win_skip("FileIoCompletionNotificationInformation not supported\n");
1474 CloseHandle(client
);
1478 memset(&ov
, 0, sizeof(ov
));
1479 ov
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1480 ok(ov
.hEvent
!= INVALID_HANDLE_VALUE
, "CreateEvent failed, error %lu\n", GetLastError());
1482 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
1483 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %lu\n", GetLastError());
1485 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1486 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1487 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
1488 test_queued_completion(port
, (IO_STATUS_BLOCK
*)&ov
, STATUS_SUCCESS
, num_bytes
);
1490 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1491 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1492 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
, "FSCTL_PIPE_PEEK returned %lx\n", status
);
1493 test_queued_completion(port
, &io
, STATUS_SUCCESS
, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
));
1495 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
1496 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1497 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
1499 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1500 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1501 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
1502 test_no_queued_completion(port
);
1504 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1505 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1506 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %lu\n", num_bytes
);
1508 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, 1, NULL
, NULL
);
1509 ok(status
== STATUS_BUFFER_OVERFLOW
|| status
== STATUS_PENDING
, "status = %lx\n", status
);
1510 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "Status = %lx\n", io
.Status
);
1511 ok(io
.Information
== 1, "Information = %Iu\n", io
.Information
);
1512 if(status
== STATUS_PENDING
) /* win8+ */
1513 test_queued_completion(port
, &io
, STATUS_BUFFER_OVERFLOW
, 1);
1515 test_no_queued_completion(port
);
1517 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1518 ok(status
== STATUS_SUCCESS
, "status = %lx\n", status
);
1519 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1520 ok(io
.Information
== sizeof(buf
)-1, "Information = %Iu\n", io
.Information
);
1521 test_no_queued_completion(port
);
1523 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1524 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1525 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
, "FSCTL_PIPE_PEEK returned %lx\n", status
);
1526 if(status
== STATUS_PENDING
) /* win8+ */
1527 test_queued_completion(port
, &io
, STATUS_SUCCESS
, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
));
1529 test_no_queued_completion(port
);
1531 memset(&io
, 0xcc, sizeof(io
));
1532 status
= NtReadFile(client
, ov
.hEvent
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1533 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1534 ok(!is_signaled(ov
.hEvent
), "event is signtaled\n");
1535 test_no_queued_completion(port
);
1537 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1538 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1539 test_queued_completion(port
, &io
, STATUS_SUCCESS
, sizeof(buf
));
1541 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1542 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1543 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1544 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1545 ok(status
== STATUS_PENDING
|| status
== STATUS_BUFFER_OVERFLOW
,
1546 "FSCTL_PIPE_PEEK returned %lx\n", status
);
1547 if(status
== STATUS_PENDING
) /* win8+ */
1548 test_queued_completion(port
, &io
, STATUS_BUFFER_OVERFLOW
, sizeof(peek_buf
));
1550 test_no_queued_completion(port
);
1552 CloseHandle(ov
.hEvent
);
1553 CloseHandle(client
);
1557 event
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1558 create_pipe_pair( &pipe
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1559 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 );
1561 ok(is_signaled(client
), "client is not signaled\n");
1563 /* no event, APC nor completion: only signals on handle */
1564 memset(&io
, 0xcc, sizeof(io
));
1565 status
= NtReadFile(client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1566 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1567 ok(!is_signaled(client
), "client is signaled\n");
1569 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1570 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1571 ok(is_signaled(client
), "client is signaled\n");
1572 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1573 ok(io
.Information
== sizeof(buf
), "Information = %Iu\n", io
.Information
);
1575 /* event with no APC nor completion: signals only event */
1576 memset(&io
, 0xcc, sizeof(io
));
1577 status
= NtReadFile(client
, event
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1578 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1579 ok(!is_signaled(client
), "client is signaled\n");
1580 ok(!is_signaled(event
), "event is signaled\n");
1582 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1583 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1584 ok(!is_signaled(client
), "client is signaled\n");
1585 ok(is_signaled(event
), "event is not signaled\n");
1586 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1587 ok(io
.Information
== sizeof(buf
), "Information = %Iu\n", io
.Information
);
1589 /* APC with no event: handle is signaled */
1590 ioapc_called
= FALSE
;
1591 memset(&io
, 0xcc, sizeof(io
));
1592 status
= NtReadFile(client
, NULL
, ioapc
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1593 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1594 ok(!is_signaled(client
), "client is signaled\n");
1596 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1597 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1598 ok(is_signaled(client
), "client is signaled\n");
1599 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1600 ok(io
.Information
== sizeof(buf
), "Information = %Iu\n", io
.Information
);
1602 ok(!ioapc_called
, "ioapc called\n");
1604 ok(ioapc_called
, "ioapc not called\n");
1606 /* completion with no completion port: handle signaled */
1607 memset(&io
, 0xcc, sizeof(io
));
1608 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1609 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1610 ok(!is_signaled(client
), "client is signaled\n");
1612 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1613 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1614 ok(is_signaled(client
), "client is not signaled\n");
1616 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
1617 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %lu\n", GetLastError());
1619 /* skipping completion on success: handle is signaled */
1620 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
1621 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1622 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
1623 ok(is_signaled(client
), "client is not signaled\n");
1625 memset(&io
, 0xcc, sizeof(io
));
1626 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1627 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1628 ok(!is_signaled(client
), "client is signaled\n");
1630 ret
= WriteFile(client
, buf
, 1, &num_bytes
, NULL
);
1631 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1632 ok(is_signaled(client
), "client is not signaled\n");
1634 /* skipping set event on handle: handle is never signaled */
1635 info
.Flags
= FILE_SKIP_SET_EVENT_ON_HANDLE
;
1636 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1637 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08lx\n", status
);
1638 ok(!is_signaled(client
), "client is not signaled\n");
1640 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1641 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1642 ok(!is_signaled(client
), "client is signaled\n");
1643 test_queued_completion(port
, &io
, STATUS_SUCCESS
, sizeof(buf
));
1645 memset(&io
, 0xcc, sizeof(io
));
1646 status
= NtReadFile(client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1647 ok(status
== STATUS_PENDING
, "status = %lx\n", status
);
1648 ok(!is_signaled(client
), "client is signaled\n");
1650 ret
= WriteFile(client
, buf
, 1, &num_bytes
, NULL
);
1651 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1652 ok(!is_signaled(client
), "client is signaled\n");
1654 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1655 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1656 ok(!is_signaled(client
), "client is signaled\n");
1659 CloseHandle(client
);
1663 struct blocking_thread_args
1668 BLOCKING_THREAD_WRITE
,
1669 BLOCKING_THREAD_READ
,
1670 BLOCKING_THREAD_QUIT
1677 static DWORD WINAPI
blocking_thread(void *arg
)
1679 struct blocking_thread_args
*ctx
= arg
;
1680 static const char buf
[] = "testdata";
1682 DWORD res
, num_bytes
;
1687 res
= WaitForSingleObject(ctx
->wait
, 10000);
1688 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1689 if (res
!= WAIT_OBJECT_0
) break;
1691 case BLOCKING_THREAD_WRITE
:
1694 ok(!is_signaled(ctx
->event
), "event is signaled\n");
1695 ok(!ioapc_called
, "ioapc called\n");
1696 ok(!is_signaled(ctx
->client
), "client is signaled\n");
1697 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1698 ret
= WriteFile(ctx
->pipe
, buf
, 1, &num_bytes
, NULL
);
1699 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1700 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1702 case BLOCKING_THREAD_READ
:
1705 ok(!is_signaled(ctx
->event
), "event is signaled\n");
1706 ok(!ioapc_called
, "ioapc called\n");
1707 ok(!is_signaled(ctx
->client
), "client is signaled\n");
1708 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1709 ret
= ReadFile(ctx
->pipe
, read_buf
, 1, &num_bytes
, NULL
);
1710 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1711 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1713 case BLOCKING_THREAD_QUIT
:
1716 ok(0, "unvalid command\n");
1718 SetEvent(ctx
->done
);
1724 static void test_blocking(ULONG options
)
1726 struct blocking_thread_args ctx
;
1727 OBJECT_ATTRIBUTES attr
;
1728 UNICODE_STRING name
;
1733 DWORD res
, num_bytes
;
1736 ctx
.wait
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1737 ctx
.done
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1738 thread
= CreateThread(NULL
, 0, blocking_thread
, &ctx
, 0, 0);
1739 ok(thread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %lx\n", GetLastError());
1741 status
= create_pipe(&ctx
.pipe
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1743 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile returned %lx\n", status
);
1745 pRtlInitUnicodeString(&name
, testpipe_nt
);
1746 attr
.Length
= sizeof(attr
);
1747 attr
.RootDirectory
= 0;
1748 attr
.ObjectName
= &name
;
1749 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1750 attr
.SecurityDescriptor
= NULL
;
1751 attr
.SecurityQualityOfService
= NULL
;
1752 status
= NtCreateFile(&ctx
.client
, SYNCHRONIZE
| GENERIC_READ
| GENERIC_WRITE
, &attr
, &io
,
1753 NULL
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN
,
1755 ok(status
== STATUS_SUCCESS
, "NtCreateFile returned %lx\n", status
);
1757 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1758 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1760 /* blocking read with no event nor APC */
1761 ioapc_called
= FALSE
;
1762 memset(&io
, 0xff, sizeof(io
));
1763 ctx
.cmd
= BLOCKING_THREAD_WRITE
;
1766 status
= NtReadFile(ctx
.client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1767 ok(status
== STATUS_SUCCESS
, "status = %lx\n", status
);
1768 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1769 ok(io
.Information
== 1, "Information = %Iu\n", io
.Information
);
1770 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1772 res
= WaitForSingleObject(ctx
.done
, 10000);
1773 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1775 /* blocking read with event and APC */
1776 ioapc_called
= FALSE
;
1777 memset(&io
, 0xff, sizeof(io
));
1778 ctx
.cmd
= BLOCKING_THREAD_WRITE
;
1779 ctx
.event
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1781 status
= NtReadFile(ctx
.client
, ctx
.event
, ioapc
, &io
, &io
, read_buf
,
1782 sizeof(read_buf
), NULL
, NULL
);
1783 ok(status
== STATUS_SUCCESS
, "status = %lx\n", status
);
1784 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1785 ok(io
.Information
== 1, "Information = %Iu\n", io
.Information
);
1786 ok(is_signaled(ctx
.event
), "event is not signaled\n");
1788 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1790 if (!(options
& FILE_SYNCHRONOUS_IO_ALERT
))
1791 ok(!ioapc_called
, "ioapc called\n");
1792 SleepEx(0, TRUE
); /* alertable wait state */
1793 ok(ioapc_called
, "ioapc not called\n");
1795 res
= WaitForSingleObject(ctx
.done
, 10000);
1796 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1797 ioapc_called
= FALSE
;
1798 CloseHandle(ctx
.event
);
1801 /* blocking flush */
1802 ret
= WriteFile(ctx
.client
, read_buf
, 1, &num_bytes
, NULL
);
1803 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1805 ioapc_called
= FALSE
;
1806 memset(&io
, 0xff, sizeof(io
));
1807 ctx
.cmd
= BLOCKING_THREAD_READ
;
1809 status
= NtFlushBuffersFile(ctx
.client
, &io
);
1810 ok(status
== STATUS_SUCCESS
, "status = %lx\n", status
);
1811 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1812 ok(io
.Information
== 0, "Information = %Iu\n", io
.Information
);
1813 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1815 res
= WaitForSingleObject(ctx
.done
, 10000);
1816 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1818 CloseHandle(ctx
.pipe
);
1819 CloseHandle(ctx
.client
);
1821 /* flush is blocking even in overlapped mode */
1822 create_pipe_pair(&ctx
.pipe
, &ctx
.client
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
1823 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096);
1825 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1827 ret
= WriteFile(ctx
.client
, read_buf
, 1, &num_bytes
, NULL
);
1828 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
1830 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1832 ioapc_called
= FALSE
;
1833 memset(&io
, 0xff, sizeof(io
));
1834 ctx
.cmd
= BLOCKING_THREAD_READ
;
1836 status
= NtFlushBuffersFile(ctx
.client
, &io
);
1837 ok(status
== STATUS_SUCCESS
, "status = %lx\n", status
);
1838 ok(io
.Status
== STATUS_SUCCESS
, "Status = %lx\n", io
.Status
);
1839 ok(io
.Information
== 0, "Information = %Iu\n", io
.Information
);
1840 /* client signaling is inconsistent in this case */
1842 res
= WaitForSingleObject(ctx
.done
, 10000);
1843 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1845 CloseHandle(ctx
.pipe
);
1846 CloseHandle(ctx
.client
);
1848 ctx
.cmd
= BLOCKING_THREAD_QUIT
;
1850 res
= WaitForSingleObject(thread
, 10000);
1851 ok(res
== WAIT_OBJECT_0
, "wait returned %lx\n", res
);
1853 CloseHandle(ctx
.wait
);
1854 CloseHandle(ctx
.done
);
1855 CloseHandle(thread
);
1858 static void test_volume_info(void)
1860 FILE_FS_DEVICE_INFORMATION
*device_info
;
1861 IO_STATUS_BLOCK iosb
;
1866 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1867 PIPE_TYPE_MESSAGE
, 4096 )) return;
1869 memset( buffer
, 0xaa, sizeof(buffer
) );
1870 memset( &iosb
, 0xaa, sizeof(iosb
) );
1871 status
= pNtQueryVolumeInformationFile( read
, &iosb
, buffer
, sizeof(buffer
), FileFsDeviceInformation
);
1872 ok( status
== STATUS_SUCCESS
, "NtQueryVolumeInformationFile failed: %lx\n", status
);
1873 ok( iosb
.Status
== STATUS_SUCCESS
, "got status %#lx\n", iosb
.Status
);
1874 ok( iosb
.Information
== sizeof(*device_info
), "Information = %Iu\n", iosb
.Information
);
1875 device_info
= (FILE_FS_DEVICE_INFORMATION
*)buffer
;
1876 ok( device_info
->DeviceType
== FILE_DEVICE_NAMED_PIPE
, "DeviceType = %lu\n", device_info
->DeviceType
);
1877 ok( !(device_info
->Characteristics
& ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
),
1878 "Characteristics = %lx\n", device_info
->Characteristics
);
1880 memset( buffer
, 0xaa, sizeof(buffer
) );
1881 memset( &iosb
, 0xaa, sizeof(iosb
) );
1882 status
= pNtQueryVolumeInformationFile( write
, &iosb
, buffer
, sizeof(buffer
), FileFsDeviceInformation
);
1883 ok( status
== STATUS_SUCCESS
, "NtQueryVolumeInformationFile failed: %lx\n", status
);
1884 ok( iosb
.Status
== STATUS_SUCCESS
, "got status %#lx\n", iosb
.Status
);
1885 ok( iosb
.Information
== sizeof(*device_info
), "Information = %Iu\n", iosb
.Information
);
1886 device_info
= (FILE_FS_DEVICE_INFORMATION
*)buffer
;
1887 ok( device_info
->DeviceType
== FILE_DEVICE_NAMED_PIPE
, "DeviceType = %lu\n", device_info
->DeviceType
);
1888 ok( !(device_info
->Characteristics
& ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
),
1889 "Characteristics = %lx\n", device_info
->Characteristics
);
1891 CloseHandle( read
);
1892 CloseHandle( write
);
1895 #define test_file_name_fail(a,b,c) _test_file_name_fail(__LINE__,a,b,c)
1896 static void _test_file_name_fail(unsigned line
, HANDLE pipe
, NTSTATUS expected_status
, BOOL todo
)
1899 IO_STATUS_BLOCK iosb
;
1902 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, 0, FileNameInformation
);
1903 ok_(__FILE__
,line
)( status
== STATUS_INFO_LENGTH_MISMATCH
,
1904 "expected STATUS_INFO_LENGTH_MISMATCH, got %#lx\n", status
);
1906 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, sizeof(buffer
), FileNameInformation
);
1908 ok_(__FILE__
,line
)( status
== expected_status
, "expected %#lx, got %#lx\n", expected_status
, status
);
1911 #define test_file_name(a) _test_file_name(__LINE__,a)
1912 static void _test_file_name(unsigned line
, HANDLE pipe
)
1915 FILE_NAME_INFORMATION
*name_info
= (FILE_NAME_INFORMATION
*)buffer
;
1916 IO_STATUS_BLOCK iosb
;
1919 static const WCHAR nameW
[] =
1920 {'\\','n','t','d','l','l','_','t','e','s','t','s','_','p','i','p','e','.','c'};
1922 memset( buffer
, 0xaa, sizeof(buffer
) );
1923 memset( &iosb
, 0xaa, sizeof(iosb
) );
1924 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, sizeof(buffer
), FileNameInformation
);
1925 ok_(__FILE__
,line
)( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed: %lx\n", status
);
1926 ok_(__FILE__
,line
)( iosb
.Status
== STATUS_SUCCESS
, "Status = %lx\n", iosb
.Status
);
1927 ok_(__FILE__
,line
)( iosb
.Information
== sizeof(name_info
->FileNameLength
) + sizeof(nameW
),
1928 "Information = %Iu\n", iosb
.Information
);
1929 ok( name_info
->FileNameLength
== sizeof(nameW
), "FileNameLength = %lu\n", name_info
->FileNameLength
);
1930 ok( !memcmp(name_info
->FileName
, nameW
, sizeof(nameW
)), "FileName = %s\n", wine_dbgstr_w(name_info
->FileName
) );
1932 /* too small buffer */
1933 memset( buffer
, 0xaa, sizeof(buffer
) );
1934 memset( &iosb
, 0xaa, sizeof(iosb
) );
1935 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, 20, FileNameInformation
);
1936 ok( status
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile failed: %lx\n", status
);
1937 ok( iosb
.Status
== STATUS_BUFFER_OVERFLOW
, "Status = %lx\n", iosb
.Status
);
1938 ok( iosb
.Information
== 20, "Information = %Iu\n", iosb
.Information
);
1939 ok( name_info
->FileNameLength
== sizeof(nameW
), "FileNameLength = %lu\n", name_info
->FileNameLength
);
1940 ok( !memcmp(name_info
->FileName
, nameW
, 16), "FileName = %s\n", wine_dbgstr_w(name_info
->FileName
) );
1942 /* too small buffer */
1943 memset( buffer
, 0xaa, sizeof(buffer
) );
1944 memset( &iosb
, 0xaa, sizeof(iosb
) );
1945 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, 4, FileNameInformation
);
1946 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile failed: %lx\n", status
);
1949 static HANDLE
create_pipe_server(void)
1954 status
= create_pipe(&handle
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0);
1955 ok(status
== STATUS_SUCCESS
, "create_pipe failed: %lx\n", status
);
1959 static HANDLE
connect_pipe(HANDLE server
)
1963 client
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
1964 FILE_FLAG_OVERLAPPED
, 0);
1965 ok(client
!= INVALID_HANDLE_VALUE
, "can't open pipe: %lu\n", GetLastError());
1970 static HANDLE
connect_and_write_pipe(HANDLE server
)
1977 client
= connect_pipe(server
);
1979 res
= WriteFile(client
, buf
, sizeof(buf
), &written
, NULL
);
1980 ok(res
, "WriteFile failed: %lu\n", GetLastError());
1981 res
= WriteFile(server
, buf
, sizeof(buf
), &written
, NULL
);
1982 ok(res
, "WriteFile failed: %lu\n", GetLastError());
1987 static void test_pipe_state(HANDLE pipe
, BOOL is_server
, DWORD state
)
1989 FILE_PIPE_PEEK_BUFFER peek_buf
;
1991 static char buf
[] = "test";
1992 NTSTATUS status
, expected_status
;
1994 memset(&peek_buf
, 0xcc, sizeof(peek_buf
));
1995 memset(&io
, 0xcc, sizeof(io
));
1996 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1997 if (!status
|| status
== STATUS_PENDING
)
2001 case FILE_PIPE_DISCONNECTED_STATE
:
2002 expected_status
= is_server
? STATUS_INVALID_PIPE_STATE
: STATUS_PIPE_DISCONNECTED
;
2004 case FILE_PIPE_LISTENING_STATE
:
2005 expected_status
= STATUS_INVALID_PIPE_STATE
;
2007 case FILE_PIPE_CONNECTED_STATE
:
2008 expected_status
= STATUS_SUCCESS
;
2011 expected_status
= STATUS_PIPE_BROKEN
;
2014 ok(status
== expected_status
, "status = %lx, expected %lx in %s state %lu\n",
2015 status
, expected_status
, is_server
? "server" : "client", state
);
2017 ok(peek_buf
.NamedPipeState
== state
, "NamedPipeState = %lu, expected %lu\n",
2018 peek_buf
.NamedPipeState
, state
);
2020 if (state
!= FILE_PIPE_CONNECTED_STATE
)
2022 if (state
== FILE_PIPE_CLOSING_STATE
)
2023 expected_status
= STATUS_INVALID_PIPE_STATE
;
2024 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_TRANSCEIVE
,
2026 if (!status
|| status
== STATUS_PENDING
)
2028 ok(status
== expected_status
,
2029 "NtFsControlFile(FSCTL_PIPE_TRANSCEIVE) failed in %s state %lu: %lx\n",
2030 is_server
? "server" : "client", state
, status
);
2033 memset(&io
, 0xcc, sizeof(io
));
2034 status
= NtFlushBuffersFile(pipe
, &io
);
2035 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2037 ok(status
== STATUS_PIPE_DISCONNECTED
, "status = %lx in %s state %lu\n",
2038 status
, is_server
? "server" : "client", state
);
2042 ok(status
== STATUS_SUCCESS
, "status = %lx in %s state %lu\n",
2043 status
, is_server
? "server" : "client", state
);
2044 ok(io
.Status
== status
, "io.Status = %lx\n", io
.Status
);
2045 ok(!io
.Information
, "io.Information = %Ix\n", io
.Information
);
2048 if (state
!= FILE_PIPE_CONNECTED_STATE
)
2052 case FILE_PIPE_DISCONNECTED_STATE
:
2053 expected_status
= STATUS_PIPE_DISCONNECTED
;
2055 case FILE_PIPE_LISTENING_STATE
:
2056 expected_status
= STATUS_PIPE_LISTENING
;
2059 expected_status
= STATUS_PIPE_BROKEN
;
2062 status
= NtReadFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
2063 ok(status
== expected_status
, "NtReadFile failed in %s state %lu: %lx\n",
2064 is_server
? "server" : "client", state
, status
);
2067 if (is_server
&& (state
== FILE_PIPE_CLOSING_STATE
|| state
== FILE_PIPE_CONNECTED_STATE
))
2069 memset(&io
, 0xcc, sizeof(io
));
2070 status
= listen_pipe(pipe
, NULL
, &io
, FALSE
);
2071 ok(status
== (state
== FILE_PIPE_CLOSING_STATE
? STATUS_PIPE_CLOSING
: STATUS_PIPE_CONNECTED
),
2072 "status = %lx in %lu state\n", status
, state
);
2076 static void test_pipe_with_data_state(HANDLE pipe
, BOOL is_server
, DWORD state
)
2078 FILE_PIPE_LOCAL_INFORMATION local_info
;
2079 FILE_PIPE_INFORMATION pipe_info
;
2080 FILE_PIPE_PEEK_BUFFER peek_buf
;
2082 char buf
[256] = "test";
2083 NTSTATUS status
, expected_status
;
2084 FILE_STANDARD_INFORMATION std_info
;
2086 memset(&io
, 0xcc, sizeof(io
));
2087 status
= pNtQueryInformationFile(pipe
, &io
, &local_info
, sizeof(local_info
), FilePipeLocalInformation
);
2088 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2089 ok(status
== STATUS_PIPE_DISCONNECTED
,
2090 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2091 is_server
? "server" : "client", state
, status
);
2093 ok(status
== STATUS_SUCCESS
,
2094 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2095 is_server
? "server" : "client", state
, status
);
2098 ok(local_info
.NamedPipeState
== state
, "%s NamedPipeState = %lu, expected %lu\n",
2099 is_server
? "server" : "client", local_info
.NamedPipeState
, state
);
2100 if (state
!= FILE_PIPE_DISCONNECTED_STATE
&& state
!= FILE_PIPE_LISTENING_STATE
)
2101 ok(local_info
.ReadDataAvailable
!= 0, "ReadDataAvailable, expected non-zero, in %s state %lu\n",
2102 is_server
? "server" : "client", state
);
2104 ok(local_info
.ReadDataAvailable
== 0, "ReadDataAvailable, expected zero, in %s state %lu\n",
2105 is_server
? "server" : "client", state
);
2108 status
= pNtQueryInformationFile(pipe
, &io
, &std_info
, sizeof(std_info
), FileStandardInformation
);
2109 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2110 ok(status
== STATUS_PIPE_DISCONNECTED
,
2111 "NtQueryInformationFile(FileStandardInformation) failed in %s state %lu: %lx\n",
2112 is_server
? "server" : "client", state
, status
);
2114 ok(status
== STATUS_SUCCESS
,
2115 "NtQueryInformationFile(FileStandardInformation) failed in %s state %lu: %lx\n",
2116 is_server
? "server" : "client", state
, status
);
2119 ok(std_info
.AllocationSize
.QuadPart
== local_info
.InboundQuota
+ local_info
.OutboundQuota
,
2120 "got %I64u, expected %lu.\n",
2121 std_info
.AllocationSize
.QuadPart
, local_info
.InboundQuota
+ local_info
.OutboundQuota
);
2122 ok(std_info
.EndOfFile
.QuadPart
== local_info
.ReadDataAvailable
, "got %I64u.\n", std_info
.EndOfFile
.QuadPart
);
2123 ok(std_info
.NumberOfLinks
== 1, "got %lu.\n", std_info
.NumberOfLinks
);
2124 todo_wine
ok(std_info
.DeletePending
, "got %d.\n", std_info
.DeletePending
);
2125 ok(!std_info
.Directory
, "got %d.\n", std_info
.Directory
);
2128 status
= pNtQueryInformationFile(pipe
, &io
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
2129 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2130 ok(status
== STATUS_PIPE_DISCONNECTED
,
2131 "NtQueryInformationFile(FilePipeInformation) failed in %s state %lu: %lx\n",
2132 is_server
? "server" : "client", state
, status
);
2134 ok(status
== STATUS_SUCCESS
,
2135 "NtQueryInformationFile(FilePipeInformation) failed in %s state %lu: %lx\n",
2136 is_server
? "server" : "client", state
, status
);
2138 status
= NtQueryInformationFile(pipe
, &io
, buf
, sizeof(buf
), FileNameInformation
);
2139 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2140 ok(status
== STATUS_PIPE_DISCONNECTED
,
2141 "NtQueryInformationFile(FileNameInformation) failed: %lx\n", status
);
2143 todo_wine_if(!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
2144 ok(status
== STATUS_SUCCESS
,
2145 "NtQueryInformationFile(FileNameInformation) failed: %lx\n", status
);
2147 memset(&peek_buf
, 0xcc, sizeof(peek_buf
));
2148 memset(&io
, 0xcc, sizeof(io
));
2149 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, &peek_buf
, sizeof(peek_buf
));
2150 if (!status
|| status
== STATUS_PENDING
)
2154 case FILE_PIPE_DISCONNECTED_STATE
:
2155 expected_status
= is_server
? STATUS_INVALID_PIPE_STATE
: STATUS_PIPE_DISCONNECTED
;
2157 case FILE_PIPE_LISTENING_STATE
:
2158 expected_status
= STATUS_INVALID_PIPE_STATE
;
2161 expected_status
= STATUS_BUFFER_OVERFLOW
;
2164 ok(status
== expected_status
, "status = %lx, expected %lx in %s state %lu\n",
2165 status
, expected_status
, is_server
? "server" : "client", state
);
2166 if (status
== STATUS_BUFFER_OVERFLOW
)
2167 ok(peek_buf
.NamedPipeState
== state
, "NamedPipeState = %lu, expected %lu\n",
2168 peek_buf
.NamedPipeState
, state
);
2172 case FILE_PIPE_DISCONNECTED_STATE
:
2173 expected_status
= STATUS_PIPE_DISCONNECTED
;
2175 case FILE_PIPE_LISTENING_STATE
:
2176 expected_status
= STATUS_PIPE_LISTENING
;
2178 case FILE_PIPE_CONNECTED_STATE
:
2179 expected_status
= STATUS_SUCCESS
;
2182 expected_status
= STATUS_PIPE_CLOSING
;
2185 status
= NtWriteFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
2186 ok(status
== expected_status
, "NtWriteFile failed in %s state %lu: %lx\n",
2187 is_server
? "server" : "client", state
, status
);
2189 if (state
== FILE_PIPE_CLOSING_STATE
)
2190 expected_status
= STATUS_SUCCESS
;
2191 status
= NtReadFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
2192 ok(status
== expected_status
, "NtReadFile failed in %s state %lu: %lx\n",
2193 is_server
? "server" : "client", state
, status
);
2196 static void pipe_for_each_state(HANDLE (*create_server
)(void),
2197 HANDLE (*connect_client
)(HANDLE
),
2198 void (*test
)(HANDLE pipe
, BOOL is_server
, DWORD pipe_state
))
2200 HANDLE client
, server
;
2201 IO_STATUS_BLOCK iosb
;
2206 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
2208 server
= create_server();
2209 test(server
, TRUE
, FILE_PIPE_LISTENING_STATE
);
2211 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
2212 ok(status
== STATUS_PENDING
, "listen_pipe returned %lx\n", status
);
2213 test(server
, TRUE
, FILE_PIPE_LISTENING_STATE
);
2215 client
= connect_client(server
);
2216 test(server
, TRUE
, FILE_PIPE_CONNECTED_STATE
);
2217 test(client
, FALSE
, FILE_PIPE_CONNECTED_STATE
);
2219 /* server closed, but not disconnected */
2220 CloseHandle(server
);
2221 test(client
, FALSE
, FILE_PIPE_CLOSING_STATE
);
2222 CloseHandle(client
);
2224 server
= create_server();
2225 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
2226 ok(status
== STATUS_PENDING
, "listen_pipe returned %lx\n", status
);
2228 client
= connect_client(server
);
2229 ret
= DisconnectNamedPipe(server
);
2230 ok(ret
, "DisconnectNamedPipe failed: %lu\n", GetLastError());
2231 test(server
, TRUE
, FILE_PIPE_DISCONNECTED_STATE
);
2232 test(client
, FALSE
, FILE_PIPE_DISCONNECTED_STATE
);
2233 CloseHandle(server
);
2234 test(client
, FALSE
, FILE_PIPE_DISCONNECTED_STATE
);
2235 CloseHandle(client
);
2237 server
= create_server();
2238 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
2239 ok(status
== STATUS_PENDING
, "listen_pipe returned %lx\n", status
);
2241 client
= connect_client(server
);
2242 CloseHandle(client
);
2243 test(server
, TRUE
, FILE_PIPE_CLOSING_STATE
);
2244 ret
= DisconnectNamedPipe(server
);
2245 ok(ret
, "DisconnectNamedPipe failed: %lu\n", GetLastError());
2246 test(server
, TRUE
, FILE_PIPE_DISCONNECTED_STATE
);
2248 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
2249 ok(status
== STATUS_PENDING
, "listen_pipe returned %lx\n", status
);
2250 client
= connect_client(server
);
2251 test(server
, TRUE
, FILE_PIPE_CONNECTED_STATE
);
2252 test(client
, FALSE
, FILE_PIPE_CONNECTED_STATE
);
2253 CloseHandle(client
);
2254 CloseHandle(server
);
2259 static HANDLE
create_local_info_test_pipe(void)
2261 IO_STATUS_BLOCK iosb
;
2262 OBJECT_ATTRIBUTES attr
;
2263 UNICODE_STRING name
;
2264 LARGE_INTEGER timeout
;
2268 pRtlInitUnicodeString(&name
, testpipe_nt
);
2270 attr
.Length
= sizeof(attr
);
2271 attr
.RootDirectory
= 0;
2272 attr
.ObjectName
= &name
;
2273 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2274 attr
.SecurityDescriptor
= NULL
;
2275 attr
.SecurityQualityOfService
= NULL
;
2277 timeout
.QuadPart
= -100000000;
2279 status
= pNtCreateNamedPipeFile(&pipe
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| GENERIC_WRITE
,
2280 &attr
, &iosb
, FILE_SHARE_READ
, FILE_CREATE
, 0, 1, 0, 0, 1,
2281 100, 200, &timeout
);
2282 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile failed: %lx\n", status
);
2287 static HANDLE
connect_pipe_reader(HANDLE server
)
2291 client
= CreateFileW(testpipe
, GENERIC_READ
| FILE_WRITE_ATTRIBUTES
, 0, 0, OPEN_EXISTING
,
2292 FILE_FLAG_OVERLAPPED
, 0);
2293 ok(client
!= INVALID_HANDLE_VALUE
, "can't open pipe: %lu\n", GetLastError());
2298 static void test_pipe_local_info(HANDLE pipe
, BOOL is_server
, DWORD state
)
2300 FILE_PIPE_LOCAL_INFORMATION local_info
;
2301 FILE_PIPE_INFORMATION pipe_info
;
2302 OBJECT_ATTRIBUTES attr
;
2303 UNICODE_STRING name
;
2304 LARGE_INTEGER timeout
;
2306 IO_STATUS_BLOCK iosb
;
2309 memset(&iosb
, 0xcc, sizeof(iosb
));
2310 memset(&local_info
, 0xcc, sizeof(local_info
));
2311 status
= pNtQueryInformationFile(pipe
, &iosb
, &local_info
, sizeof(local_info
), FilePipeLocalInformation
);
2312 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2313 ok(status
== STATUS_PIPE_DISCONNECTED
,
2314 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2315 is_server
? "server" : "client", state
, status
);
2317 ok(status
== STATUS_SUCCESS
,
2318 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2319 is_server
? "server" : "client", state
, status
);
2322 ok(local_info
.NamedPipeType
== 1, "NamedPipeType = %lu\n", local_info
.NamedPipeType
);
2323 ok(local_info
.NamedPipeConfiguration
== 1, "NamedPipeConfiguration = %lu\n",
2324 local_info
.NamedPipeConfiguration
);
2325 ok(local_info
.MaximumInstances
== 1, "MaximumInstances = %lu\n", local_info
.MaximumInstances
);
2326 if (!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
2327 ok(local_info
.CurrentInstances
== 0 || broken(local_info
.CurrentInstances
== 1 /* winxp */),
2328 "CurrentInstances = %lu\n", local_info
.CurrentInstances
);
2330 ok(local_info
.CurrentInstances
== 1,
2331 "CurrentInstances = %lu\n", local_info
.CurrentInstances
);
2332 ok(local_info
.InboundQuota
== 100, "InboundQuota = %lu\n", local_info
.InboundQuota
);
2333 ok(local_info
.ReadDataAvailable
== 0, "ReadDataAvailable = %lu\n",
2334 local_info
.ReadDataAvailable
);
2335 ok(local_info
.OutboundQuota
== 200, "OutboundQuota = %lu\n", local_info
.OutboundQuota
);
2337 ok(local_info
.WriteQuotaAvailable
== (is_server
? 200 : 100), "WriteQuotaAvailable = %lu\n",
2338 local_info
.WriteQuotaAvailable
);
2339 ok(local_info
.NamedPipeState
== state
, "%s NamedPipeState = %lu, expected %lu\n",
2340 is_server
? "server" : "client", local_info
.NamedPipeState
, state
);
2341 ok(local_info
.NamedPipeEnd
== is_server
, "NamedPipeEnd = %lu\n", local_info
.NamedPipeEnd
);
2343 /* try to create another, incompatible, instance of pipe */
2344 pRtlInitUnicodeString(&name
, testpipe_nt
);
2346 attr
.Length
= sizeof(attr
);
2347 attr
.RootDirectory
= 0;
2348 attr
.ObjectName
= &name
;
2349 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2350 attr
.SecurityDescriptor
= NULL
;
2351 attr
.SecurityQualityOfService
= NULL
;
2353 timeout
.QuadPart
= -100000000;
2355 status
= pNtCreateNamedPipeFile(&new_pipe
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| GENERIC_READ
,
2356 &attr
, &iosb
, FILE_SHARE_WRITE
, FILE_CREATE
, 0, 0, 0, 0, 1,
2357 100, 200, &timeout
);
2358 if (!local_info
.CurrentInstances
)
2359 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile failed: %lx\n", status
);
2361 ok(status
== STATUS_INSTANCE_NOT_AVAILABLE
, "NtCreateNamedPipeFile failed: %lx\n", status
);
2362 if (!status
) CloseHandle(new_pipe
);
2364 memset(&iosb
, 0xcc, sizeof(iosb
));
2365 status
= pNtQueryInformationFile(pipe
, &iosb
, &local_info
, sizeof(local_info
),
2366 FilePipeLocalInformation
);
2367 ok(status
== STATUS_SUCCESS
,
2368 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2369 is_server
? "server" : "client", state
, status
);
2371 if (!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
2372 ok(local_info
.CurrentInstances
== 0 || broken(local_info
.CurrentInstances
== 1 /* winxp */),
2373 "CurrentInstances = %lu\n", local_info
.CurrentInstances
);
2375 ok(local_info
.CurrentInstances
== 1,
2376 "CurrentInstances = %lu\n", local_info
.CurrentInstances
);
2379 memset(&iosb
, 0xcc, sizeof(iosb
));
2380 status
= pNtQueryInformationFile(pipe
, &iosb
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
2381 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2382 ok(status
== STATUS_PIPE_DISCONNECTED
,
2383 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2384 is_server
? "server" : "client", state
, status
);
2386 ok(status
== STATUS_SUCCESS
,
2387 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2388 is_server
? "server" : "client", state
, status
);
2392 ok(pipe_info
.ReadMode
== 0, "ReadMode = %lu\n", pipe_info
.ReadMode
);
2393 ok(pipe_info
.CompletionMode
== 0, "CompletionMode = %lu\n", pipe_info
.CompletionMode
);
2396 pipe_info
.ReadMode
= 0;
2397 pipe_info
.CompletionMode
= 0;
2398 memset(&iosb
, 0xcc, sizeof(iosb
));
2399 status
= pNtSetInformationFile(pipe
, &iosb
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
2400 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2401 ok(status
== STATUS_PIPE_DISCONNECTED
,
2402 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2403 is_server
? "server" : "client", state
, status
);
2405 ok(status
== STATUS_SUCCESS
,
2406 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %lu: %lx\n",
2407 is_server
? "server" : "client", state
, status
);
2410 static void test_file_info(void)
2412 HANDLE server
, client
, device
;
2414 if (!create_pipe_pair( &server
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
2415 PIPE_TYPE_MESSAGE
, 4096 )) return;
2417 test_file_name( client
);
2418 test_file_name( server
);
2420 DisconnectNamedPipe( server
);
2421 test_file_name_fail( client
, STATUS_PIPE_DISCONNECTED
, FALSE
);
2423 CloseHandle( server
);
2424 CloseHandle( client
);
2426 device
= CreateFileA("\\\\.\\pipe", 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2427 ok(device
!= INVALID_HANDLE_VALUE
, "got error %lu\n", GetLastError());
2429 test_file_name_fail( device
, STATUS_INVALID_PARAMETER
, TRUE
);
2431 CloseHandle( device
);
2434 static PSECURITY_DESCRIPTOR
get_security_descriptor(HANDLE handle
, BOOL todo
)
2436 SECURITY_DESCRIPTOR
*sec_desc
;
2440 status
= NtQuerySecurityObject(handle
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2442 todo_wine_if(todo
&& status
== STATUS_PIPE_DISCONNECTED
)
2443 ok(status
== STATUS_BUFFER_TOO_SMALL
,
2444 "Failed to query object security descriptor length: %08lx\n", status
);
2445 if(status
!= STATUS_BUFFER_TOO_SMALL
) return NULL
;
2446 ok(length
!= 0, "length = 0\n");
2448 sec_desc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, length
);
2449 status
= NtQuerySecurityObject(handle
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2450 sec_desc
, length
, &length
);
2451 ok(status
== STATUS_SUCCESS
, "Failed to query object security descriptor: %08lx\n", status
);
2456 static TOKEN_OWNER
*get_current_owner(void)
2463 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS
, &token
);
2464 ok(ret
, "Failed to get process token: %lu\n", GetLastError());
2466 ret
= GetTokenInformation(token
, TokenOwner
, NULL
, 0, &length
);
2467 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2468 "GetTokenInformation failed: %lu\n", GetLastError());
2469 ok(length
!= 0, "Failed to get token owner information length: %lu\n", GetLastError());
2471 owner
= HeapAlloc(GetProcessHeap(), 0, length
);
2472 ret
= GetTokenInformation(token
, TokenOwner
, owner
, length
, &length
);
2473 ok(ret
, "Failed to get token owner information: %lu)\n", GetLastError());
2479 static TOKEN_PRIMARY_GROUP
*get_current_group(void)
2481 TOKEN_PRIMARY_GROUP
*group
;
2486 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS
, &token
);
2487 ok(ret
, "Failed to get process token: %lu\n", GetLastError());
2489 ret
= GetTokenInformation(token
, TokenPrimaryGroup
, NULL
, 0, &length
);
2490 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2491 "GetTokenInformation failed: %lu\n", GetLastError());
2492 ok(length
!= 0, "Failed to get primary group token information length: %lu\n", GetLastError());
2494 group
= HeapAlloc(GetProcessHeap(), 0, length
);
2495 ret
= GetTokenInformation(token
, TokenPrimaryGroup
, group
, length
, &length
);
2496 ok(ret
, "Failed to get primary group token information: %lu\n", GetLastError());
2502 static SID
*well_known_sid(WELL_KNOWN_SID_TYPE sid_type
)
2504 DWORD size
= SECURITY_MAX_SID_SIZE
;
2508 sid
= HeapAlloc(GetProcessHeap(), 0, size
);
2509 ret
= CreateWellKnownSid(sid_type
, NULL
, sid
, &size
);
2510 ok(ret
, "CreateWellKnownSid failed: %lu\n", GetLastError());
2514 #define test_group(a,b,c) _test_group(__LINE__,a,b,c)
2515 static void _test_group(unsigned line
, HANDLE handle
, SID
*expected_sid
, BOOL todo
)
2517 SECURITY_DESCRIPTOR
*sec_desc
;
2522 sec_desc
= get_security_descriptor(handle
, todo
);
2523 if (!sec_desc
) return;
2525 status
= RtlGetGroupSecurityDescriptor(sec_desc
, &group_sid
, &defaulted
);
2526 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
,
2527 "Failed to query group from security descriptor: %08lx\n", status
);
2529 ok_(__FILE__
,line
)(EqualSid(group_sid
, expected_sid
), "SIDs are not equal\n");
2531 HeapFree(GetProcessHeap(), 0, sec_desc
);
2534 static void test_security_info(void)
2536 char sec_desc
[SECURITY_DESCRIPTOR_MIN_LENGTH
];
2537 TOKEN_PRIMARY_GROUP
*process_group
;
2538 SECURITY_ATTRIBUTES sec_attr
;
2539 TOKEN_OWNER
*process_owner
;
2540 HANDLE server
, client
, server2
;
2541 SID
*world_sid
, *local_sid
;
2546 trace("security tests...\n");
2548 process_owner
= get_current_owner();
2549 process_group
= get_current_group();
2550 world_sid
= well_known_sid(WinWorldSid
);
2551 local_sid
= well_known_sid(WinLocalSid
);
2553 ret
= InitializeSecurityDescriptor(sec_desc
, SECURITY_DESCRIPTOR_REVISION
);
2554 ok(ret
, "InitializeSecurityDescriptor failed\n");
2556 ret
= SetSecurityDescriptorOwner(sec_desc
, process_owner
->Owner
, FALSE
);
2557 ok(ret
, "SetSecurityDescriptorOwner failed\n");
2559 ret
= SetSecurityDescriptorGroup(sec_desc
, process_group
->PrimaryGroup
, FALSE
);
2560 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2562 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2563 0x20000, 0x20000, 0, NULL
);
2564 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError());
2566 client
= CreateFileA(PIPENAME
, GENERIC_ALL
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2567 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
2569 test_group(server
, process_group
->PrimaryGroup
, TRUE
);
2570 test_group(client
, process_group
->PrimaryGroup
, TRUE
);
2572 /* set server group, client changes as well */
2573 ret
= SetSecurityDescriptorGroup(sec_desc
, world_sid
, FALSE
);
2574 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2575 status
= NtSetSecurityObject(server
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2576 ok(status
== STATUS_SUCCESS
, "NtSetSecurityObject failed: %08lx\n", status
);
2578 test_group(server
, world_sid
, FALSE
);
2579 test_group(client
, world_sid
, FALSE
);
2581 /* new instance of pipe server has the same security descriptor */
2582 server2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
, 10,
2583 0x20000, 0x20000, 0, NULL
);
2584 ok(server2
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError());
2585 test_group(server2
, world_sid
, FALSE
);
2587 /* set client group, server changes as well */
2588 ret
= SetSecurityDescriptorGroup(sec_desc
, local_sid
, FALSE
);
2589 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2590 status
= NtSetSecurityObject(server
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2591 ok(status
== STATUS_SUCCESS
, "NtSetSecurityObject failed: %08lx\n", status
);
2593 test_group(server
, local_sid
, FALSE
);
2594 test_group(client
, local_sid
, FALSE
);
2595 test_group(server2
, local_sid
, FALSE
);
2597 CloseHandle(server
);
2598 /* SD is preserved after closing server object */
2599 test_group(client
, local_sid
, FALSE
);
2600 CloseHandle(client
);
2603 client
= CreateFileA(PIPENAME
, GENERIC_ALL
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2604 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
2606 test_group(client
, local_sid
, FALSE
);
2608 ret
= DisconnectNamedPipe(server
);
2609 ok(ret
, "DisconnectNamedPipe failed: %lu\n", GetLastError());
2611 /* disconnected server may be queried for security info, but client does not */
2612 test_group(server
, local_sid
, FALSE
);
2613 status
= NtQuerySecurityObject(client
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2615 ok(status
== STATUS_PIPE_DISCONNECTED
, "NtQuerySecurityObject returned %08lx\n", status
);
2616 status
= NtSetSecurityObject(client
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2617 ok(status
== STATUS_PIPE_DISCONNECTED
, "NtQuerySecurityObject returned %08lx\n", status
);
2619 /* attempting to create another pipe instance with specified sd fails */
2620 sec_attr
.nLength
= sizeof(sec_attr
);
2621 sec_attr
.lpSecurityDescriptor
= sec_desc
;
2622 sec_attr
.bInheritHandle
= FALSE
;
2623 ret
= SetSecurityDescriptorGroup(sec_desc
, local_sid
, FALSE
);
2624 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2625 server2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2626 0x20000, 0x20000, 0, &sec_attr
);
2628 ok(server2
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_ACCESS_DENIED
,
2629 "CreateNamedPipe failed: %lu\n", GetLastError());
2630 if (server2
!= INVALID_HANDLE_VALUE
) CloseHandle(server2
);
2632 CloseHandle(server
);
2633 CloseHandle(client
);
2635 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2636 0x20000, 0x20000, 0, &sec_attr
);
2637 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %lu\n", GetLastError());
2638 test_group(server
, local_sid
, FALSE
);
2639 CloseHandle(server
);
2641 HeapFree(GetProcessHeap(), 0, process_owner
);
2642 HeapFree(GetProcessHeap(), 0, process_group
);
2643 HeapFree(GetProcessHeap(), 0, world_sid
);
2644 HeapFree(GetProcessHeap(), 0, local_sid
);
2647 static void subtest_empty_name_pipe_operations(HANDLE handle
)
2649 static const struct fsctl_test
{
2653 NTSTATUS status_broken
;
2655 #define FSCTL_TEST(code, ...) { #code, code, __VA_ARGS__ }
2656 FSCTL_TEST(FSCTL_PIPE_ASSIGN_EVENT
, STATUS_NOT_SUPPORTED
),
2657 FSCTL_TEST(FSCTL_PIPE_DISCONNECT
, STATUS_PIPE_DISCONNECTED
),
2658 FSCTL_TEST(FSCTL_PIPE_LISTEN
, STATUS_ILLEGAL_FUNCTION
),
2659 FSCTL_TEST(FSCTL_PIPE_QUERY_EVENT
, STATUS_NOT_SUPPORTED
),
2660 FSCTL_TEST(FSCTL_PIPE_TRANSCEIVE
, STATUS_PIPE_DISCONNECTED
),
2661 FSCTL_TEST(FSCTL_PIPE_IMPERSONATE
, STATUS_ILLEGAL_FUNCTION
),
2662 FSCTL_TEST(FSCTL_PIPE_SET_CLIENT_PROCESS
, STATUS_NOT_SUPPORTED
),
2663 FSCTL_TEST(FSCTL_PIPE_QUERY_CLIENT_PROCESS
, STATUS_INVALID_PARAMETER
, /* win10 1507 */ STATUS_PIPE_DISCONNECTED
),
2666 FILE_PIPE_PEEK_BUFFER peek_buf
;
2667 OBJECT_ATTRIBUTES attr
;
2676 InitializeObjectAttributes(&attr
, NULL
, 0, 0, NULL
);
2677 status
= NtCreateEvent(&event
, GENERIC_ALL
, &attr
, NotificationEvent
, FALSE
);
2678 ok(status
== STATUS_SUCCESS
, "NtCreateEvent returned %#lx\n", status
);
2680 status
= NtReadFile(handle
, event
, NULL
, NULL
, &io
, buffer
, sizeof(buffer
), NULL
, NULL
);
2682 ok(status
== STATUS_INVALID_PARAMETER
, "NtReadFile on \\Device\\NamedPipe: got %#lx\n", status
);
2684 status
= NtWriteFile(handle
, event
, NULL
, NULL
, &io
, buffer
, sizeof(buffer
), NULL
, NULL
);
2686 ok(status
== STATUS_INVALID_PARAMETER
, "NtWriteFile on \\Device\\NamedPipe: got %#lx\n", status
);
2688 status
= NtFsControlFile(handle
, event
, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, &peek_buf
, sizeof(peek_buf
));
2689 if (status
== STATUS_PENDING
)
2691 WaitForSingleObject(event
, INFINITE
);
2695 ok(status
== STATUS_INVALID_PARAMETER
, "FSCTL_PIPE_PEEK on \\Device\\NamedPipe: got %lx\n", status
);
2697 status
= NtFsControlFile(handle
, event
, NULL
, NULL
, &io
, FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE
, (void *)"ClientProcessId", sizeof("ClientProcessId"), &peer_pid
, sizeof(peer_pid
));
2698 if (status
== STATUS_PENDING
)
2700 WaitForSingleObject(event
, INFINITE
);
2704 ok(status
== STATUS_INVALID_PARAMETER
, "FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE ClientProcessId on \\Device\\NamedPipe: got %lx\n", status
);
2706 status
= NtFsControlFile(handle
, event
, NULL
, NULL
, &io
, FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE
, (void *)"ServerProcessId", sizeof("ServerProcessId"), &peer_pid
, sizeof(peer_pid
));
2707 if (status
== STATUS_PENDING
)
2709 WaitForSingleObject(event
, INFINITE
);
2713 ok(status
== STATUS_INVALID_PARAMETER
, "FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE ServerProcessId on \\Device\\NamedPipe: got %lx\n", status
);
2715 for (i
= 0; i
< ARRAY_SIZE(fsctl_tests
); i
++)
2717 const struct fsctl_test
*ft
= &fsctl_tests
[i
];
2719 status
= NtFsControlFile(handle
, event
, NULL
, NULL
, &io
, ft
->code
, 0, 0, 0, 0);
2720 if (status
== STATUS_PENDING
)
2722 WaitForSingleObject(event
, INFINITE
);
2725 todo_wine_if(ft
->status
!= STATUS_NOT_SUPPORTED
)
2726 ok(status
== ft
->status
|| (ft
->status_broken
&& broken(status
== ft
->status_broken
)),
2727 "NtFsControlFile(%s) on \\Device\\NamedPipe: expected %#lx, got %#lx\n",
2728 ft
->name
, ft
->status
, status
);
2734 static void test_empty_name(void)
2736 static const LARGE_INTEGER zero_timeout
= {{ 0 }};
2737 HANDLE hdirectory
, hpipe
, hpipe2
, hwrite
, hwrite2
, handle
;
2738 OBJECT_TYPE_INFORMATION
*type_info
;
2739 OBJECT_NAME_INFORMATION
*name_info
;
2740 OBJECT_ATTRIBUTES attr
;
2741 LARGE_INTEGER timeout
;
2742 UNICODE_STRING name
;
2749 type_info
= (OBJECT_TYPE_INFORMATION
*)buffer
;
2750 name_info
= (OBJECT_NAME_INFORMATION
*)buffer
;
2752 hpipe
= hwrite
= NULL
;
2754 attr
.Length
= sizeof(attr
);
2755 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2756 attr
.SecurityDescriptor
= NULL
;
2757 attr
.SecurityQualityOfService
= NULL
;
2759 pRtlInitUnicodeString(&name
, L
"\\Device\\NamedPipe");
2760 attr
.RootDirectory
= 0;
2761 attr
.ObjectName
= &name
;
2763 status
= NtCreateFile(&hdirectory
, GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2764 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0 );
2765 ok(!status
, "Got unexpected status %#lx.\n", status
);
2767 pRtlInitUnicodeString(&name
, L
"nonexistent_pipe");
2768 status
= wait_pipe(hdirectory
, &name
, &zero_timeout
);
2769 todo_wine
ok(status
== STATUS_ILLEGAL_FUNCTION
, "unexpected status for FSCTL_PIPE_WAIT on \\Device\\NamedPipe: %#lx\n", status
);
2771 subtest_empty_name_pipe_operations(hdirectory
);
2775 name
.MaximumLength
= 0;
2776 attr
.RootDirectory
= hdirectory
;
2778 timeout
.QuadPart
= -(LONG64
)10000000;
2779 status
= pNtCreateNamedPipeFile(&hpipe
, GENERIC_READ
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
,
2780 &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_CREATE
, FILE_SYNCHRONOUS_IO_NONALERT
,
2781 0, 0, 0, 3, 4096, 4096, &timeout
);
2782 todo_wine
ok(status
== STATUS_OBJECT_NAME_INVALID
, "Got unexpected status %#lx.\n", status
);
2786 pRtlInitUnicodeString(&name
, L
"test3\\pipe");
2787 attr
.RootDirectory
= hdirectory
;
2788 attr
.ObjectName
= &name
;
2789 timeout
.QuadPart
= -(LONG64
)10000000;
2790 status
= pNtCreateNamedPipeFile(&hpipe
, GENERIC_READ
|GENERIC_WRITE
, &attr
, &io
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2791 FILE_CREATE
, FILE_PIPE_FULL_DUPLEX
, 0, 0, 0, 1, 256, 256, &timeout
);
2792 ok(status
== STATUS_OBJECT_NAME_INVALID
, "unexpected status from NtCreateNamedPipeFile: %#lx\n", status
);
2796 CloseHandle(hdirectory
);
2798 pRtlInitUnicodeString(&name
, L
"\\Device\\NamedPipe\\");
2799 attr
.RootDirectory
= 0;
2800 attr
.ObjectName
= &name
;
2802 status
= pNtCreateDirectoryObject(&hdirectory
, GENERIC_READ
| SYNCHRONIZE
, &attr
);
2803 todo_wine
ok(status
== STATUS_OBJECT_TYPE_MISMATCH
, "Got unexpected status %#lx.\n", status
);
2805 status
= NtCreateFile(&hdirectory
, GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2806 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0 );
2807 ok(!status
, "Got unexpected status %#lx.\n", status
);
2809 pRtlInitUnicodeString(&name
, L
"nonexistent_pipe");
2810 status
= wait_pipe(hdirectory
, &name
, &zero_timeout
);
2811 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "unexpected status for FSCTL_PIPE_WAIT on \\Device\\NamedPipe\\: %#lx\n", status
);
2813 subtest_empty_name_pipe_operations(hdirectory
);
2817 name
.MaximumLength
= 0;
2818 attr
.RootDirectory
= hdirectory
;
2821 status
= pNtCreateNamedPipeFile(&hpipe
, GENERIC_READ
| SYNCHRONIZE
, &attr
,
2822 &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_CREATE
, FILE_SYNCHRONOUS_IO_NONALERT
,
2823 0, 0, 0, 3, 4096, 4096, &timeout
);
2824 ok(!status
, "Got unexpected status %#lx.\n", status
);
2825 type_info
->TypeName
.Buffer
= NULL
;
2826 status
= pNtQueryObject(hpipe
, ObjectTypeInformation
, type_info
, sizeof(buffer
), NULL
);
2827 ok(!status
, "Got unexpected status %#lx.\n", status
);
2828 ok(type_info
->TypeName
.Buffer
&& !wcscmp(type_info
->TypeName
.Buffer
, L
"File"),
2829 "Got unexpected type %s.\n", debugstr_w(type_info
->TypeName
.Buffer
));
2830 status
= pNtQueryObject(hpipe
, ObjectNameInformation
, name_info
, sizeof(buffer
), NULL
);
2831 ok(status
== STATUS_OBJECT_PATH_INVALID
, "Got unexpected status %#lx.\n", status
);
2833 status
= pNtCreateNamedPipeFile(&handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
,
2834 &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN
, FILE_SYNCHRONOUS_IO_NONALERT
,
2835 0, 0, 0, 1, 4096, 4096, &timeout
);
2836 todo_wine
ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "Got unexpected status %#lx.\n", status
);
2838 status
= pNtCreateNamedPipeFile(&hpipe2
, GENERIC_READ
| SYNCHRONIZE
, &attr
,
2839 &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_CREATE
, FILE_SYNCHRONOUS_IO_NONALERT
,
2840 0, 0, 0, 3, 4096, 4096, &timeout
);
2841 ok(!status
, "Got unexpected status %#lx.\n", status
);
2843 attr
.RootDirectory
= hpipe
;
2844 pRtlInitUnicodeString(&name
, L
"a");
2845 status
= NtCreateFile(&hwrite
, GENERIC_WRITE
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2846 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
2847 ok(status
== STATUS_OBJECT_NAME_INVALID
, "Got unexpected status %#lx.\n", status
);
2851 name
.MaximumLength
= 0;
2852 attr
.RootDirectory
= hpipe
;
2853 status
= NtCreateFile(&hwrite
, GENERIC_WRITE
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2854 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
2855 ok(!status
, "Got unexpected status %#lx.\n", status
);
2857 type_info
->TypeName
.Buffer
= NULL
;
2858 status
= pNtQueryObject(hwrite
, ObjectTypeInformation
, type_info
, sizeof(buffer
), NULL
);
2859 ok(!status
, "Got unexpected status %#lx.\n", status
);
2860 ok(type_info
->TypeName
.Buffer
&& !wcscmp(type_info
->TypeName
.Buffer
, L
"File"),
2861 "Got unexpected type %s.\n", debugstr_w(type_info
->TypeName
.Buffer
));
2862 status
= pNtQueryObject(hwrite
, ObjectNameInformation
, name_info
, sizeof(buffer
), NULL
);
2863 ok(status
== STATUS_OBJECT_PATH_INVALID
, "Got unexpected status %#lx.\n", status
);
2865 attr
.RootDirectory
= hpipe
;
2866 status
= NtCreateFile(&handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2867 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
,
2868 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
2869 ok(status
== STATUS_PIPE_NOT_AVAILABLE
, "Got unexpected status %#lx.\n", status
);
2871 attr
.RootDirectory
= hpipe
;
2872 status
= NtCreateFile(&handle
, GENERIC_WRITE
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2873 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
2874 ok(status
== STATUS_PIPE_NOT_AVAILABLE
, "Got unexpected status %#lx.\n", status
);
2876 attr
.RootDirectory
= hpipe2
;
2877 status
= NtCreateFile(&hwrite2
, GENERIC_WRITE
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &io
, NULL
, 0,
2878 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
2879 ok(!status
, "Got unexpected status %#lx.\n", status
);
2882 ret
= WriteFile(hwrite
, &data
, sizeof(data
), &length
, NULL
);
2883 ok(ret
, "Got unexpected ret %#x, GetLastError() %lu.\n", ret
, GetLastError());
2884 ok(length
== sizeof(data
), "Got unexpected length %#lx.\n", length
);
2887 ret
= WriteFile(hwrite2
, &data
, sizeof(data
), &length
, NULL
);
2888 ok(ret
, "Got unexpected ret %#x, GetLastError() %lu.\n", ret
, GetLastError());
2889 ok(length
== sizeof(data
), "Got unexpected length %#lx.\n", length
);
2892 ret
= ReadFile(hpipe
, &data
, sizeof(data
), &length
, NULL
);
2893 ok(ret
, "Got unexpected ret %#x, GetLastError() %lu.\n", ret
, GetLastError());
2894 ok(length
== sizeof(data
), "Got unexpected length %#lx.\n", length
);
2895 ok(data
== 0xdeadbeef, "Got unexpected data %#lx.\n", data
);
2898 ret
= ReadFile(hpipe2
, &data
, sizeof(data
), &length
, NULL
);
2899 ok(ret
, "Got unexpected ret %#x, GetLastError() %lu.\n", ret
, GetLastError());
2900 ok(length
== sizeof(data
), "Got unexpected length %#lx.\n", length
);
2901 ok(data
== 0xfeedcafe, "Got unexpected data %#lx.\n", data
);
2903 CloseHandle(hwrite
);
2905 CloseHandle(hpipe2
);
2906 CloseHandle(hwrite2
);
2908 pRtlInitUnicodeString(&name
, L
"test3\\pipe");
2909 attr
.RootDirectory
= hdirectory
;
2910 attr
.ObjectName
= &name
;
2911 timeout
.QuadPart
= -(LONG64
)10000000;
2912 status
= pNtCreateNamedPipeFile(&hpipe
, GENERIC_READ
|GENERIC_WRITE
, &attr
, &io
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2913 FILE_CREATE
, FILE_PIPE_FULL_DUPLEX
, 0, 0, 0, 1, 256, 256, &timeout
);
2914 todo_wine
ok(!status
, "unexpected failure from NtCreateNamedPipeFile: %#lx\n", status
);
2916 handle
= CreateFileA("\\\\.\\pipe\\test3\\pipe", GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
,
2917 OPEN_EXISTING
, 0, 0 );
2918 todo_wine
ok(handle
!= INVALID_HANDLE_VALUE
, "Failed to open NamedPipe (%lu)\n", GetLastError());
2920 CloseHandle(handle
);
2922 CloseHandle(hdirectory
);
2925 struct pipe_name_test
{
2929 const WCHAR
*no_open_name
;
2932 static void subtest_pipe_name(const struct pipe_name_test
*pnt
)
2934 OBJECT_ATTRIBUTES attr
;
2935 LARGE_INTEGER timeout
;
2936 IO_STATUS_BLOCK iosb
;
2937 HANDLE pipe
, client
;
2938 UNICODE_STRING name
;
2941 pRtlInitUnicodeString(&name
, pnt
->name
);
2942 InitializeObjectAttributes(&attr
, &name
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2943 timeout
.QuadPart
= -100000000;
2945 status
= pNtCreateNamedPipeFile(&pipe
,
2946 GENERIC_READ
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
2947 &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2948 FILE_CREATE
, FILE_SYNCHRONOUS_IO_NONALERT
,
2949 0, 0, 0, 3, 4096, 4096, &timeout
);
2950 todo_wine_if(pnt
->todo
)
2951 ok(status
== pnt
->status
, "Expected status %#lx, got %#lx\n", pnt
->status
, status
);
2953 if (!NT_SUCCESS(status
))
2955 ok(pipe
== NULL
, "expected NULL handle, got %p\n", pipe
);
2959 ok(pipe
!= NULL
, "expected non-NULL handle\n");
2962 status
= NtCreateFile(&client
, SYNCHRONIZE
, &attr
, &iosb
, NULL
, 0,
2963 FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0);
2964 ok(status
== STATUS_SUCCESS
, "Expected success, got %#lx\n", status
);
2965 ok(client
!= NULL
, "expected non-NULL handle\n");
2968 if (pnt
->no_open_name
)
2970 OBJECT_ATTRIBUTES no_open_attr
;
2971 UNICODE_STRING no_open_name
;
2973 pRtlInitUnicodeString(&no_open_name
, pnt
->no_open_name
);
2974 InitializeObjectAttributes(&no_open_attr
, &no_open_name
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2976 status
= NtCreateFile(&client
, SYNCHRONIZE
, &no_open_attr
, &iosb
, NULL
, 0,
2977 FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0);
2978 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
,
2979 "Expected STATUS_OBJECT_NAME_NOT_FOUND opening %s, got %#lx\n",
2980 debugstr_wn(no_open_name
.Buffer
, no_open_name
.Length
/ sizeof(WCHAR
)), status
);
2981 ok(client
== NULL
, "expected NULL handle, got %p\n", client
);
2987 static void test_pipe_names(void)
2989 static const struct pipe_name_test tests
[] = {
2990 { L
"\\Device\\NamedPipe" , STATUS_OBJECT_NAME_INVALID
, TRUE
},
2991 { L
"\\Device\\NamedPipe\\" , STATUS_OBJECT_NAME_INVALID
, TRUE
},
2992 { L
"\\Device\\NamedPipe\\\\" , STATUS_SUCCESS
},
2993 { L
"\\Device\\NamedPipe\\wine-test\\" , STATUS_SUCCESS
, 0, L
"\\Device\\NamedPipe\\wine-test" },
2994 { L
"\\Device\\NamedPipe\\wine/test" , STATUS_SUCCESS
, 0, L
"\\Device\\NamedPipe\\wine\\test" },
2995 { L
"\\Device\\NamedPipe\\wine:test" , STATUS_SUCCESS
},
2996 { L
"\\Device\\NamedPipe\\wine\\.\\test" , STATUS_SUCCESS
, 0, L
"\\Device\\NamedPipe\\wine\\test" },
2997 { L
"\\Device\\NamedPipe\\wine\\..\\test" , STATUS_SUCCESS
, 0, L
"\\Device\\NamedPipe\\test" },
2998 { L
"\\Device\\NamedPipe\\..\\wine-test" , STATUS_SUCCESS
},
2999 { L
"\\Device\\NamedPipe\\!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", STATUS_SUCCESS
},
3003 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
3005 const struct pipe_name_test
*pnt
= &tests
[i
];
3007 winetest_push_context("test %Iu: %s", i
, debugstr_w(pnt
->name
));
3008 subtest_pipe_name(pnt
);
3009 winetest_pop_context();
3013 static void test_async_cancel_on_handle_close(void)
3018 PIO_APC_ROUTINE apc
;
3028 {FALSE
, NULL
, TRUE
},
3029 {TRUE
, ioapc
, TRUE
},
3030 {FALSE
, ioapc
, TRUE
},
3033 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
3035 HANDLE port
, write
, read
, event
, handle2
, process_handle
;
3038 unsigned int i
, other_process
;
3042 create_pipe_pair(&read
, &write
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
3043 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096);
3045 status
= pNtQueryInformationFile(read
, &io
, &info
, sizeof(info
),
3046 FileIoCompletionNotificationInformation
);
3047 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_INVALID_INFO_CLASS
),
3048 "status = %lx\n", status
);
3053 win_skip("FileIoCompletionNotificationInformation is not supported.\n");
3057 process_handle
= create_process("sleep");
3058 event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
3060 for (other_process
= 0; other_process
< 2; ++other_process
)
3062 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
3064 winetest_push_context("other_process %u, i %u", other_process
, i
);
3065 create_pipe_pair(&read
, &write
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
3066 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096);
3067 port
= CreateIoCompletionPort(read
, NULL
, 0, 0);
3068 ok(!!port
, "got %p.\n", port
);
3070 memset(&io
, 0xcc, sizeof(io
));
3072 status
= NtReadFile(read
, tests
[i
].event
? event
: NULL
, tests
[i
].apc
, tests
[i
].apc_context
? &io
: NULL
, &io
,
3073 read_buf
, 16, NULL
, NULL
);
3076 ok(status
== STATUS_INVALID_PARAMETER
, "got %#lx.\n", status
);
3080 winetest_pop_context();
3083 ok(status
== STATUS_PENDING
, "got %#lx.\n", status
);
3084 ok(io
.Status
== 0xcccccccc, "got %#lx.\n", io
.Status
);
3086 bret
= DuplicateHandle(GetCurrentProcess(), read
, other_process
? process_handle
: GetCurrentProcess(),
3087 &handle2
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
3088 ok(bret
, "failed, error %lu.\n", GetLastError());
3091 /* Canceled asyncs with completion port and no event do not update IOSB before removing completion. */
3092 todo_wine_if(other_process
&& tests
[i
].apc_context
&& !tests
[i
].event
)
3093 ok(io
.Status
== 0xcccccccc, "got %#lx.\n", io
.Status
);
3095 if (other_process
&& tests
[i
].apc_context
&& !tests
[i
].event
)
3096 test_queued_completion(port
, &io
, STATUS_CANCELLED
, 0);
3098 test_no_queued_completion(port
);
3100 ret
= WaitForSingleObject(event
, 0);
3101 ok(ret
== WAIT_TIMEOUT
, "got %#lx.\n", ret
);
3105 bret
= DuplicateHandle(process_handle
, handle2
, GetCurrentProcess(), &read
, 0, FALSE
,
3106 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
);
3107 ok(bret
, "failed, error %lu.\n", GetLastError());
3116 winetest_pop_context();
3121 TerminateProcess(process_handle
, 0);
3122 WaitForSingleObject(process_handle
, INFINITE
);
3123 CloseHandle(process_handle
);
3131 if (!init_func_ptrs())
3134 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
3136 argc
= winetest_get_mainargs(&argv
);
3139 if (!strcmp(argv
[2], "sleep"))
3147 trace("starting invalid create tests\n");
3148 test_create_invalid();
3150 trace("starting create tests\n");
3153 trace("starting overlapped tests\n");
3156 trace("starting completion tests\n");
3159 trace("starting blocking tests\n");
3160 test_blocking(FILE_SYNCHRONOUS_IO_NONALERT
);
3161 test_blocking(FILE_SYNCHRONOUS_IO_ALERT
);
3163 trace("starting FILE_PIPE_INFORMATION tests\n");
3164 test_filepipeinfo();
3166 if (!pOpenThread
|| !pQueueUserAPC
)
3169 trace("starting alertable tests\n");
3172 trace("starting nonalertable tests\n");
3173 test_nonalertable();
3175 trace("starting cancelio tests\n");
3178 trace("starting cancelsynchronousio tests\n");
3179 test_cancelsynchronousio();
3181 trace("starting byte read in byte mode client -> server\n");
3182 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_BYTE
);
3183 trace("starting byte read in message mode client -> server\n");
3184 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
);
3185 trace("starting message read in message mode client -> server\n");
3186 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
3187 trace("starting byte read in byte mode server -> client\n");
3188 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
);
3189 trace("starting byte read in message mode server -> client\n");
3190 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
);
3191 trace("starting message read in message mode server -> client\n");
3192 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
3197 test_security_info();
3200 test_async_cancel_on_handle_close();
3202 pipe_for_each_state(create_pipe_server
, connect_pipe
, test_pipe_state
);
3203 pipe_for_each_state(create_pipe_server
, connect_and_write_pipe
, test_pipe_with_data_state
);
3204 pipe_for_each_state(create_local_info_test_pipe
, connect_pipe_reader
, test_pipe_local_info
);