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 #ifndef FILE_SYNCHRONOUS_IO_ALERT
55 #define FILE_SYNCHRONOUS_IO_ALERT 0x10
58 #ifndef FILE_SYNCHRONOUS_IO_NONALERT
59 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20
62 #ifndef FSCTL_PIPE_LISTEN
63 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
67 static NTSTATUS (WINAPI
*pNtFsControlFile
) (HANDLE handle
, HANDLE event
, PIO_APC_ROUTINE apc
, PVOID apc_context
, PIO_STATUS_BLOCK io
, ULONG code
, PVOID in_buffer
, ULONG in_size
, PVOID out_buffer
, ULONG out_size
);
68 static NTSTATUS (WINAPI
*pNtCreateNamedPipeFile
) (PHANDLE handle
, ULONG access
,
69 POBJECT_ATTRIBUTES attr
, PIO_STATUS_BLOCK iosb
,
70 ULONG sharing
, ULONG dispo
, ULONG options
,
71 ULONG pipe_type
, ULONG read_mode
,
72 ULONG completion_mode
, ULONG max_inst
,
73 ULONG inbound_quota
, ULONG outbound_quota
,
74 PLARGE_INTEGER timeout
);
75 static NTSTATUS (WINAPI
*pNtQueryInformationFile
) (IN HANDLE FileHandle
, OUT PIO_STATUS_BLOCK IoStatusBlock
, OUT PVOID FileInformation
, IN ULONG Length
, IN FILE_INFORMATION_CLASS FileInformationClass
);
76 static NTSTATUS (WINAPI
*pNtQueryVolumeInformationFile
)(HANDLE handle
, PIO_STATUS_BLOCK io
, void *buffer
, ULONG length
, FS_INFORMATION_CLASS info_class
);
77 static NTSTATUS (WINAPI
*pNtSetInformationFile
) (HANDLE handle
, PIO_STATUS_BLOCK io
, PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class);
78 static NTSTATUS (WINAPI
*pNtCancelIoFile
) (HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
79 static NTSTATUS (WINAPI
*pNtCancelIoFileEx
) (HANDLE hFile
, IO_STATUS_BLOCK
*iosb
, IO_STATUS_BLOCK
*io_status
);
80 static NTSTATUS (WINAPI
*pNtRemoveIoCompletion
)(HANDLE
, PULONG_PTR
, PULONG_PTR
, PIO_STATUS_BLOCK
, PLARGE_INTEGER
);
81 static void (WINAPI
*pRtlInitUnicodeString
) (PUNICODE_STRING target
, PCWSTR source
);
83 static HANDLE (WINAPI
*pOpenThread
)(DWORD dwDesiredAccess
, BOOL bInheritHandle
, DWORD dwThreadId
);
84 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
87 static BOOL
init_func_ptrs(void)
89 HMODULE module
= GetModuleHandleA("ntdll.dll");
91 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
92 trace("GetProcAddress(%s) failed\n", #name); \
96 loadfunc(NtFsControlFile
)
97 loadfunc(NtCreateNamedPipeFile
)
98 loadfunc(NtQueryInformationFile
)
99 loadfunc(NtQueryVolumeInformationFile
)
100 loadfunc(NtSetInformationFile
)
101 loadfunc(NtCancelIoFile
)
102 loadfunc(RtlInitUnicodeString
)
103 loadfunc(NtRemoveIoCompletion
)
106 pNtCancelIoFileEx
= (void *)GetProcAddress(module
, "NtCancelIoFileEx");
107 module
= GetModuleHandleA("kernel32.dll");
108 pOpenThread
= (void *)GetProcAddress(module
, "OpenThread");
109 pQueueUserAPC
= (void *)GetProcAddress(module
, "QueueUserAPC");
113 static inline BOOL
is_signaled( HANDLE obj
)
115 return WaitForSingleObject( obj
, 0 ) == WAIT_OBJECT_0
;
118 #define test_file_access(a,b) _test_file_access(__LINE__,a,b)
119 static void _test_file_access(unsigned line
, HANDLE handle
, DWORD expected_access
)
121 FILE_ACCESS_INFORMATION info
;
125 memset(&info
, 0x11, sizeof(info
));
126 status
= NtQueryInformationFile(handle
, &io
, &info
, sizeof(info
), FileAccessInformation
);
127 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
128 ok_(__FILE__
,line
)(info
.AccessFlags
== expected_access
, "got access %08x expected %08x\n",
129 info
.AccessFlags
, expected_access
);
132 static const WCHAR testpipe
[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
133 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
134 static const WCHAR testpipe_nt
[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
135 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
137 static NTSTATUS
create_pipe(PHANDLE handle
, ULONG access
, ULONG sharing
, ULONG options
)
139 IO_STATUS_BLOCK iosb
;
140 OBJECT_ATTRIBUTES attr
;
142 LARGE_INTEGER timeout
;
145 pRtlInitUnicodeString(&name
, testpipe_nt
);
147 attr
.Length
= sizeof(attr
);
148 attr
.RootDirectory
= 0;
149 attr
.ObjectName
= &name
;
150 attr
.Attributes
= 0x40; /*case insensitive */
151 attr
.SecurityDescriptor
= NULL
;
152 attr
.SecurityQualityOfService
= NULL
;
154 timeout
.QuadPart
= -100000000;
156 res
= pNtCreateNamedPipeFile(handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| access
, &attr
, &iosb
, sharing
,
157 FILE_CREATE
, options
, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
161 static BOOL ioapc_called
;
162 static void CALLBACK
ioapc(void *arg
, PIO_STATUS_BLOCK io
, ULONG reserved
)
167 static NTSTATUS
listen_pipe(HANDLE hPipe
, HANDLE hEvent
, PIO_STATUS_BLOCK iosb
, BOOL use_apc
)
171 ioapc_called
= FALSE
;
173 return pNtFsControlFile(hPipe
, hEvent
, use_apc
? &ioapc
: NULL
, use_apc
? &dummy
: NULL
, iosb
, FSCTL_PIPE_LISTEN
, 0, 0, 0, 0);
176 static void test_create_invalid(void)
178 IO_STATUS_BLOCK iosb
;
179 OBJECT_ATTRIBUTES attr
;
181 LARGE_INTEGER timeout
;
183 HANDLE handle
, handle2
;
184 FILE_PIPE_LOCAL_INFORMATION info
;
186 pRtlInitUnicodeString(&name
, testpipe_nt
);
188 attr
.Length
= sizeof(attr
);
189 attr
.RootDirectory
= 0;
190 attr
.ObjectName
= &name
;
191 attr
.Attributes
= 0x40; /*case insensitive */
192 attr
.SecurityDescriptor
= NULL
;
193 attr
.SecurityQualityOfService
= NULL
;
195 timeout
.QuadPart
= -100000000;
197 /* create a pipe with FILE_OVERWRITE */
198 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 4 /*FILE_OVERWRITE*/,
199 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
200 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
204 /* create a pipe with FILE_OVERWRITE_IF */
205 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 5 /*FILE_OVERWRITE_IF*/,
206 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
207 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
211 /* create a pipe with sharing = 0 */
212 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, 0, 2 /*FILE_CREATE*/,
213 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
214 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
218 /* create a pipe without r/w access */
219 res
= pNtCreateNamedPipeFile(&handle
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
220 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
221 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
223 res
= pNtQueryInformationFile(handle
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
224 ok(res
== STATUS_ACCESS_DENIED
, "NtQueryInformationFile returned %x\n", res
);
226 /* test FILE_CREATE creation disposition */
227 res
= pNtCreateNamedPipeFile(&handle2
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
228 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
229 todo_wine
ok(res
== STATUS_ACCESS_DENIED
, "NtCreateNamedPipeFile returned %x\n", res
);
231 CloseHandle(handle2
);
236 static void test_create(void)
241 FILE_PIPE_LOCAL_INFORMATION info
;
242 IO_STATUS_BLOCK iosb
;
243 HANDLE hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
245 static const DWORD access
[] = { 0, GENERIC_READ
, GENERIC_WRITE
, GENERIC_READ
| GENERIC_WRITE
};
246 static const DWORD sharing
[] = { FILE_SHARE_READ
, FILE_SHARE_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
};
247 static const DWORD pipe_config
[]= { 1, 0, 2 };
249 for (j
= 0; j
< ARRAY_SIZE(sharing
); j
++) {
250 for (k
= 0; k
< ARRAY_SIZE(access
); k
++) {
252 BOOL should_succeed
= TRUE
;
254 res
= create_pipe(&hserver
, 0, sharing
[j
], 0);
256 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res
, sharing
[j
]);
260 res
= listen_pipe(hserver
, hEvent
, &iosb
, FALSE
);
261 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
263 res
= pNtQueryInformationFile(hserver
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
264 ok(!res
, "NtQueryInformationFile for server returned %x, sharing: %x\n", res
, sharing
[j
]);
265 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
266 info
.NamedPipeConfiguration
, pipe_config
[j
]);
268 hclient
= CreateFileW(testpipe
, access
[k
], 0, 0, OPEN_EXISTING
, 0, 0);
269 if (hclient
!= INVALID_HANDLE_VALUE
) {
270 res
= pNtQueryInformationFile(hclient
, &iosb
, &info
, sizeof(info
), FilePipeLocalInformation
);
271 ok(!res
, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n",
272 res
, access
[k
], sharing
[j
]);
273 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
274 info
.NamedPipeConfiguration
, pipe_config
[j
]);
276 res
= listen_pipe(hclient
, hEvent
, &iosb
, FALSE
);
277 ok(res
== STATUS_ILLEGAL_FUNCTION
, "expected STATUS_ILLEGAL_FUNCTION, got %x\n", res
);
278 CloseHandle(hclient
);
281 if (access
[k
] & GENERIC_WRITE
)
282 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_WRITE
);
283 if (access
[k
] & GENERIC_READ
)
284 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_READ
);
287 ok(hclient
!= INVALID_HANDLE_VALUE
, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n",
288 sharing
[j
], access
[k
], GetLastError());
290 ok(hclient
== INVALID_HANDLE_VALUE
, "CreateFile succeeded for sharing %x, access: %x\n", sharing
[j
], access
[k
]);
292 CloseHandle(hserver
);
298 static void test_overlapped(void)
300 IO_STATUS_BLOCK iosb
;
306 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
307 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
309 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
310 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
312 memset(&iosb
, 0x55, sizeof(iosb
));
313 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
314 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
315 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
317 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
318 ok(hClient
!= INVALID_HANDLE_VALUE
, "can't open pipe, GetLastError: %x\n", GetLastError());
320 ok(U(iosb
).Status
== 0, "Wrong iostatus %x\n", U(iosb
).Status
);
321 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
323 ok(!ioapc_called
, "IOAPC ran too early\n");
325 SleepEx(0, TRUE
); /* alertable wait state */
327 ok(ioapc_called
, "IOAPC didn't run\n");
330 CloseHandle(hClient
);
332 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
333 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
335 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
336 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
337 "can't open pipe, GetLastError: %x\n", GetLastError());
339 if (hClient
!= INVALID_HANDLE_VALUE
)
342 memset(&iosb
, 0x55, sizeof(iosb
));
343 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
344 ok(res
== STATUS_PIPE_CONNECTED
, "NtFsControlFile returned %x\n", res
);
345 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
346 ok(!is_signaled(hEvent
), "hEvent not signaled\n");
348 CloseHandle(hClient
);
355 static BOOL userapc_called
;
356 static void CALLBACK
userapc(ULONG_PTR dwParam
)
358 userapc_called
= TRUE
;
361 static BOOL open_succeeded
;
362 static DWORD WINAPI
thread(PVOID main_thread
)
370 userapc_called
= FALSE
;
371 ret
= pQueueUserAPC(&userapc
, main_thread
, 0);
372 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
373 CloseHandle(main_thread
);
378 h
= CreateFileW(testpipe
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
380 if (h
!= INVALID_HANDLE_VALUE
) {
381 open_succeeded
= TRUE
;
385 open_succeeded
= FALSE
;
390 static void test_alertable(void)
392 IO_STATUS_BLOCK iosb
;
399 memset(&iosb
, 0x55, sizeof(iosb
));
401 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
402 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
404 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
405 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
407 /* queue an user apc before calling listen */
408 userapc_called
= FALSE
;
409 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
410 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
412 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
413 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
415 ok(userapc_called
, "user apc didn't run\n");
416 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
417 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
418 ok(!ioapc_called
, "IOAPC ran\n");
420 /* queue an user apc from a different thread */
421 hThread
= CreateThread(NULL
, 0, &thread
, pOpenThread(MAXIMUM_ALLOWED
, FALSE
, GetCurrentThreadId()), 0, 0);
422 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
424 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
425 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
426 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
427 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
429 ok(userapc_called
, "user apc didn't run\n");
430 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
431 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
432 ok(!ioapc_called
, "IOAPC ran\n");
434 WaitForSingleObject(hThread
, INFINITE
);
436 SleepEx(0, TRUE
); /* get rid of the userapc, if NtFsControlFile failed */
438 ok(open_succeeded
, "couldn't open client side pipe\n");
440 CloseHandle(hThread
);
441 DisconnectNamedPipe(hPipe
);
443 /* finally try without an apc */
444 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
445 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
447 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
448 ok(!res
, "NtFsControlFile returned %x\n", res
);
450 ok(open_succeeded
, "couldn't open client side pipe\n");
451 ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
452 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
454 WaitForSingleObject(hThread
, INFINITE
);
455 CloseHandle(hThread
);
460 static void test_nonalertable(void)
462 IO_STATUS_BLOCK iosb
;
469 memset(&iosb
, 0x55, sizeof(iosb
));
471 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
472 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
474 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
475 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
477 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
478 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
480 userapc_called
= FALSE
;
481 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
482 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
484 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
485 ok(!res
, "NtFsControlFile returned %x\n", res
);
487 ok(open_succeeded
, "couldn't open client side pipe\n");
488 ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
489 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
491 ok(!ioapc_called
, "IOAPC ran too early\n");
492 ok(!userapc_called
, "user apc ran too early\n");
494 SleepEx(0, TRUE
); /* alertable wait state */
496 ok(ioapc_called
, "IOAPC didn't run\n");
497 ok(userapc_called
, "user apc didn't run\n");
499 WaitForSingleObject(hThread
, INFINITE
);
500 CloseHandle(hThread
);
505 static void test_cancelio(void)
507 IO_STATUS_BLOCK iosb
;
508 IO_STATUS_BLOCK cancel_sb
;
513 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
514 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
516 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
517 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
519 memset(&iosb
, 0x55, sizeof(iosb
));
521 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
522 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
524 res
= pNtCancelIoFile(hPipe
, &cancel_sb
);
525 ok(!res
, "NtCancelIoFile returned %x\n", res
);
527 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
528 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
530 ok(!ioapc_called
, "IOAPC ran too early\n");
532 SleepEx(0, TRUE
); /* alertable wait state */
534 ok(ioapc_called
, "IOAPC didn't run\n");
538 if (pNtCancelIoFileEx
)
540 res
= create_pipe(&hPipe
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
541 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
543 memset(&iosb
, 0x55, sizeof(iosb
));
544 res
= listen_pipe(hPipe
, hEvent
, &iosb
, FALSE
);
545 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
547 res
= pNtCancelIoFileEx(hPipe
, &iosb
, &cancel_sb
);
548 ok(!res
, "NtCancelIoFileEx returned %x\n", res
);
550 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
551 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
556 win_skip("NtCancelIoFileEx not available\n");
561 static void _check_pipe_handle_state(int line
, HANDLE handle
, ULONG read
, ULONG completion
)
563 IO_STATUS_BLOCK iosb
;
564 FILE_PIPE_INFORMATION fpi
;
566 if (handle
!= INVALID_HANDLE_VALUE
)
568 memset(&fpi
, 0x55, sizeof(fpi
));
569 res
= pNtQueryInformationFile(handle
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
570 ok_(__FILE__
, line
)(!res
, "NtQueryInformationFile returned %x\n", res
);
571 ok_(__FILE__
, line
)(fpi
.ReadMode
== read
, "Unexpected ReadMode, expected %x, got %x\n",
573 ok_(__FILE__
, line
)(fpi
.CompletionMode
== completion
, "Unexpected CompletionMode, expected %x, got %x\n",
574 completion
, fpi
.CompletionMode
);
577 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
579 static void test_filepipeinfo(void)
581 FILE_PIPE_LOCAL_INFORMATION local_info
;
582 IO_STATUS_BLOCK iosb
;
583 OBJECT_ATTRIBUTES attr
;
585 LARGE_INTEGER timeout
;
586 HANDLE hServer
, hClient
;
587 FILE_PIPE_INFORMATION fpi
;
590 pRtlInitUnicodeString(&name
, testpipe_nt
);
592 attr
.Length
= sizeof(attr
);
593 attr
.RootDirectory
= 0;
594 attr
.ObjectName
= &name
;
595 attr
.Attributes
= 0x40; /* case insensitive */
596 attr
.SecurityDescriptor
= NULL
;
597 attr
.SecurityQualityOfService
= NULL
;
599 timeout
.QuadPart
= -100000000;
601 /* test with INVALID_HANDLE_VALUE */
602 res
= pNtQueryInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
603 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtQueryInformationFile returned %x\n", res
);
606 fpi
.CompletionMode
= 0;
607 res
= pNtSetInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
608 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtSetInformationFile returned %x\n", res
);
610 /* server end with read-only attributes */
611 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
612 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
613 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout
);
614 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
616 check_pipe_handle_state(hServer
, 0, 1);
618 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
619 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
620 "can't open pipe, GetLastError: %x\n", GetLastError());
622 check_pipe_handle_state(hServer
, 0, 1);
623 check_pipe_handle_state(hClient
, 0, 0);
626 fpi
.CompletionMode
= 0;
627 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
628 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
630 check_pipe_handle_state(hServer
, 0, 1);
631 check_pipe_handle_state(hClient
, 0, 0);
633 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
634 fpi
.CompletionMode
= 1;
635 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
636 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
638 check_pipe_handle_state(hServer
, 0, 1);
639 check_pipe_handle_state(hClient
, 0, 0);
641 if (hClient
!= INVALID_HANDLE_VALUE
)
643 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
644 fpi
.CompletionMode
= 1;
645 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
646 ok(res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile returned %x\n", res
);
649 check_pipe_handle_state(hServer
, 0, 1);
650 check_pipe_handle_state(hClient
, 0, 0);
652 if (hClient
!= INVALID_HANDLE_VALUE
)
655 fpi
.CompletionMode
= 1;
656 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
657 ok(!res
, "NtSetInformationFile returned %x\n", res
);
660 check_pipe_handle_state(hServer
, 0, 1);
661 check_pipe_handle_state(hClient
, 0, 1);
663 if (hClient
!= INVALID_HANDLE_VALUE
)
666 fpi
.CompletionMode
= 2; /* not in range 0-1 */
667 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
668 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
670 fpi
.ReadMode
= 2; /* not in range 0-1 */
671 fpi
.CompletionMode
= 0;
672 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
673 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
676 CloseHandle(hClient
);
678 check_pipe_handle_state(hServer
, 0, 1);
681 fpi
.CompletionMode
= 0;
682 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
683 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
685 CloseHandle(hServer
);
687 /* message mode server with read/write attributes */
688 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
689 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
690 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
691 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
693 check_pipe_handle_state(hServer
, 1, 0);
695 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
696 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
697 "can't open pipe, GetLastError: %x\n", GetLastError());
699 check_pipe_handle_state(hServer
, 1, 0);
700 check_pipe_handle_state(hClient
, 0, 0);
702 if (hClient
!= INVALID_HANDLE_VALUE
)
705 fpi
.CompletionMode
= 1;
706 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
707 ok(!res
, "NtSetInformationFile returned %x\n", res
);
710 check_pipe_handle_state(hServer
, 1, 0);
711 check_pipe_handle_state(hClient
, 1, 1);
714 fpi
.CompletionMode
= 1;
715 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
716 ok(!res
, "NtSetInformationFile returned %x\n", res
);
718 check_pipe_handle_state(hServer
, 0, 1);
719 check_pipe_handle_state(hClient
, 1, 1);
721 if (hClient
!= INVALID_HANDLE_VALUE
)
724 fpi
.CompletionMode
= 2; /* not in range 0-1 */
725 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
726 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
728 fpi
.ReadMode
= 2; /* not in range 0-1 */
729 fpi
.CompletionMode
= 0;
730 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
731 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
734 CloseHandle(hClient
);
736 check_pipe_handle_state(hServer
, 0, 1);
739 fpi
.CompletionMode
= 0;
740 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), FilePipeInformation
);
741 ok(!res
, "NtSetInformationFile returned %x\n", res
);
743 check_pipe_handle_state(hServer
, 1, 0);
745 CloseHandle(hServer
);
747 res
= pNtCreateNamedPipeFile(&hServer
,
748 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
749 &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_CREATE
,
750 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
751 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
753 res
= NtCreateFile(&hClient
, SYNCHRONIZE
, &attr
, &iosb
, NULL
, 0,
754 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0, NULL
, 0 );
755 ok(!res
, "NtCreateFile returned %x\n", res
);
757 test_file_access(hClient
, SYNCHRONIZE
);
759 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
760 FilePipeLocalInformation
);
761 ok(res
== STATUS_ACCESS_DENIED
,
762 "NtQueryInformationFile(FilePipeLocalInformation) returned: %x\n", res
);
764 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
765 FilePipeInformation
);
766 ok(res
== STATUS_ACCESS_DENIED
,
767 "NtQueryInformationFile(FilePipeInformation) returned: %x\n", res
);
769 res
= pNtQueryInformationFile(hClient
, &iosb
, &local_info
, sizeof(local_info
),
770 FileNameInformation
);
771 ok(res
== STATUS_SUCCESS
, "NtQueryInformationFile(FileNameInformation) returned: %x\n", res
);
773 CloseHandle(hClient
);
774 CloseHandle(hServer
);
777 static void WINAPI
apc( void *arg
, IO_STATUS_BLOCK
*iosb
, ULONG reserved
)
781 ok( !reserved
, "reserved is not 0: %x\n", reserved
);
784 static void test_peek(HANDLE pipe
)
786 FILE_PIPE_PEEK_BUFFER buf
;
787 IO_STATUS_BLOCK iosb
;
788 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
791 memset(&iosb
, 0x55, sizeof(iosb
));
792 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
793 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
794 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
795 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
798 memset(&iosb
, 0x55, sizeof(iosb
));
799 status
= NtFsControlFile(pipe
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, &buf
, sizeof(buf
));
800 ok(!status
|| status
== STATUS_PENDING
, "NtFsControlFile failed: %x\n", status
);
801 ok(buf
.ReadDataAvailable
== 1, "ReadDataAvailable = %u\n", buf
.ReadDataAvailable
);
802 ok(!iosb
.Status
, "iosb.Status = %x\n", iosb
.Status
);
803 ok(is_signaled(event
), "event is not signaled\n");
808 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
810 static BOOL
create_pipe_pair( HANDLE
*read
, HANDLE
*write
, ULONG flags
, ULONG type
, ULONG size
)
812 HANDLE client
, server
;
814 server
= CreateNamedPipeA(PIPENAME
, flags
, PIPE_WAIT
| type
,
815 1, size
, size
, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
816 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed\n");
818 client
= CreateFileA(PIPENAME
, (flags
& PIPE_ACCESS_INBOUND
? GENERIC_WRITE
: 0)
819 | (flags
& PIPE_ACCESS_OUTBOUND
? GENERIC_READ
: 0)
820 | FILE_WRITE_ATTRIBUTES
, 0,
821 NULL
, OPEN_EXISTING
, flags
& FILE_FLAG_OVERLAPPED
, 0);
822 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed (%d)\n", GetLastError());
824 if ((type
& PIPE_READMODE_MESSAGE
) && (flags
& PIPE_ACCESS_OUTBOUND
))
826 DWORD read_mode
= PIPE_READMODE_MESSAGE
;
827 ok(SetNamedPipeHandleState(client
, &read_mode
, NULL
, NULL
), "Change mode\n");
830 if (flags
& PIPE_ACCESS_INBOUND
)
843 static void read_pipe_test(ULONG pipe_flags
, ULONG pipe_type
)
845 IO_STATUS_BLOCK iosb
, iosb2
;
846 HANDLE handle
, read
, write
;
847 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
854 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
856 /* try read with no data */
857 U(iosb
).Status
= 0xdeadbabe;
858 iosb
.Information
= 0xdeadbeef;
859 ok( is_signaled( read
), "read handle is not signaled\n" );
860 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
861 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
862 ok( !is_signaled( read
), "read handle is signaled\n" );
863 ok( !is_signaled( event
), "event is signaled\n" );
864 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
865 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
866 ok( !apc_count
, "apc was called\n" );
867 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
868 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
869 /* iosb updated here by async i/o */
870 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
871 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
872 ok( !is_signaled( read
), "read handle is signaled\n" );
873 ok( is_signaled( event
), "event is not signaled\n" );
874 ok( !apc_count
, "apc was called\n" );
876 SleepEx( 1, FALSE
); /* non-alertable sleep */
877 ok( !apc_count
, "apc was called\n" );
878 SleepEx( 1, TRUE
); /* alertable sleep */
879 ok( apc_count
== 1, "apc not called\n" );
881 /* with no event, the pipe handle itself gets signaled */
883 U(iosb
).Status
= 0xdeadbabe;
884 iosb
.Information
= 0xdeadbeef;
885 ok( !is_signaled( read
), "read handle is signaled\n" );
886 status
= NtReadFile( read
, 0, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
887 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
888 ok( !is_signaled( read
), "read handle is signaled\n" );
889 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
890 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
891 ok( !apc_count
, "apc was called\n" );
892 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
893 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
894 /* iosb updated here by async i/o */
895 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
896 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
897 ok( is_signaled( read
), "read handle is not signaled\n" );
898 ok( !apc_count
, "apc was called\n" );
900 SleepEx( 1, FALSE
); /* non-alertable sleep */
901 ok( !apc_count
, "apc was called\n" );
902 SleepEx( 1, TRUE
); /* alertable sleep */
903 ok( apc_count
== 1, "apc not called\n" );
905 /* now read with data ready */
907 U(iosb
).Status
= 0xdeadbabe;
908 iosb
.Information
= 0xdeadbeef;
910 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
911 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
915 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
916 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
917 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
918 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
919 ok( is_signaled( event
), "event is not signaled\n" );
920 ok( !apc_count
, "apc was called\n" );
921 SleepEx( 1, FALSE
); /* non-alertable sleep */
922 ok( !apc_count
, "apc was called\n" );
923 SleepEx( 1, TRUE
); /* alertable sleep */
924 ok( apc_count
== 1, "apc not called\n" );
926 /* now partial read with data ready */
928 U(iosb
).Status
= 0xdeadbabe;
929 iosb
.Information
= 0xdeadbeef;
931 ret
= WriteFile( write
, buffer
, 2, &written
, NULL
);
932 ok(ret
&& written
== 2, "WriteFile error %d\n", GetLastError());
934 memset( &iosb
, 0xcc, sizeof(iosb
) );
935 status
= NtFsControlFile( read
, NULL
, NULL
, NULL
, &iosb
, FSCTL_PIPE_PEEK
, NULL
, 0, buffer
,
936 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[1]) );
937 if (pipe_type
& PIPE_TYPE_MESSAGE
)
939 ok( status
== STATUS_BUFFER_OVERFLOW
|| status
== STATUS_PENDING
,
940 "FSCTL_PIPE_PEEK returned %x\n", status
);
941 ok( U(iosb
).Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", U(iosb
).Status
);
945 ok( !status
|| status
== STATUS_PENDING
, "FSCTL_PIPE_PEEK returned %x\n", status
);
946 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
948 ok( iosb
.Information
== FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[1]),
949 "wrong info %lu\n", iosb
.Information
);
951 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
952 if (pipe_type
& PIPE_READMODE_MESSAGE
)
954 ok( status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", status
);
955 ok( U(iosb
).Status
== STATUS_BUFFER_OVERFLOW
, "wrong status %x\n", U(iosb
).Status
);
959 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
960 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
962 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
963 ok( is_signaled( event
), "event is not signaled\n" );
964 ok( !apc_count
, "apc was called\n" );
965 SleepEx( 1, FALSE
); /* non-alertable sleep */
966 ok( !apc_count
, "apc was called\n" );
967 SleepEx( 1, TRUE
); /* alertable sleep */
968 ok( apc_count
== 1, "apc not called\n" );
970 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
971 ok( status
== STATUS_SUCCESS
, "wrong status %x\n", status
);
972 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
973 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
974 ok( is_signaled( event
), "event is not signaled\n" );
975 ok( !apc_count
, "apc was called\n" );
976 SleepEx( 1, FALSE
); /* non-alertable sleep */
977 ok( !apc_count
, "apc was called\n" );
978 SleepEx( 1, TRUE
); /* alertable sleep */
979 ok( apc_count
== 1, "apc not called\n" );
981 /* try read with no data */
983 U(iosb
).Status
= 0xdeadbabe;
984 iosb
.Information
= 0xdeadbeef;
985 ok( is_signaled( event
), "event is not signaled\n" ); /* check that read resets the event */
986 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
987 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
988 ok( !is_signaled( event
), "event is signaled\n" );
989 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
990 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
991 ok( !apc_count
, "apc was called\n" );
992 ret
= WriteFile( write
, buffer
, 1, &written
, NULL
);
993 ok(ret
&& written
== 1, "WriteFile error %d\n", GetLastError());
994 /* partial read is good enough */
995 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
996 ok( is_signaled( event
), "event is not signaled\n" );
997 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
998 ok( iosb
.Information
== 1, "wrong info %lu\n", iosb
.Information
);
999 ok( !apc_count
, "apc was called\n" );
1000 SleepEx( 1, TRUE
); /* alertable sleep */
1001 ok( apc_count
== 1, "apc was not called\n" );
1003 /* read from disconnected pipe */
1005 U(iosb
).Status
= 0xdeadbabe;
1006 iosb
.Information
= 0xdeadbeef;
1007 CloseHandle( write
);
1008 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1009 ok( status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", status
);
1010 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1011 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1012 ok( !is_signaled( event
), "event is signaled\n" );
1013 ok( !apc_count
, "apc was called\n" );
1014 SleepEx( 1, TRUE
); /* alertable sleep */
1015 ok( !apc_count
, "apc was called\n" );
1016 CloseHandle( read
);
1018 /* read from disconnected pipe, with invalid event handle */
1020 U(iosb
).Status
= 0xdeadbabe;
1021 iosb
.Information
= 0xdeadbeef;
1022 status
= NtReadFile( read
, (HANDLE
)0xdeadbeef, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1023 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1024 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1025 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1026 ok( !apc_count
, "apc was called\n" );
1027 SleepEx( 1, TRUE
); /* alertable sleep */
1028 ok( !apc_count
, "apc was called\n" );
1029 CloseHandle( read
);
1031 /* read from closed handle */
1033 U(iosb
).Status
= 0xdeadbabe;
1034 iosb
.Information
= 0xdeadbeef;
1036 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 1, NULL
, NULL
);
1037 ok( status
== STATUS_INVALID_HANDLE
, "wrong status %x\n", status
);
1038 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1039 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1040 ok( is_signaled( event
), "event is not signaled\n" ); /* not reset on invalid handle */
1041 ok( !apc_count
, "apc was called\n" );
1042 SleepEx( 1, TRUE
); /* alertable sleep */
1043 ok( !apc_count
, "apc was called\n" );
1045 /* disconnect while async read is in progress */
1046 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1048 U(iosb
).Status
= 0xdeadbabe;
1049 iosb
.Information
= 0xdeadbeef;
1050 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1051 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1052 ok( !is_signaled( event
), "event is signaled\n" );
1053 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1054 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1055 ok( !apc_count
, "apc was called\n" );
1056 CloseHandle( write
);
1057 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1058 ok( U(iosb
).Status
== STATUS_PIPE_BROKEN
, "wrong status %x\n", U(iosb
).Status
);
1059 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1060 ok( is_signaled( event
), "event is not signaled\n" );
1061 ok( !apc_count
, "apc was called\n" );
1062 SleepEx( 1, TRUE
); /* alertable sleep */
1063 ok( apc_count
== 1, "apc was not called\n" );
1064 CloseHandle( read
);
1066 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1067 ret
= DuplicateHandle(GetCurrentProcess(), read
, GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
1068 ok(ret
, "Failed to duplicate handle: %d\n", GetLastError());
1071 U(iosb
).Status
= 0xdeadbabe;
1072 iosb
.Information
= 0xdeadbeef;
1073 status
= NtReadFile( handle
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1074 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1075 ok( !is_signaled( event
), "event is signaled\n" );
1076 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1077 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1078 ok( !apc_count
, "apc was called\n" );
1079 /* Cancel by other handle */
1080 status
= pNtCancelIoFile( read
, &iosb2
);
1081 ok(status
== STATUS_SUCCESS
, "failed to cancel by different handle: %x\n", status
);
1082 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1083 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1084 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1085 ok( is_signaled( event
), "event is not signaled\n" );
1086 ok( !apc_count
, "apc was called\n" );
1087 SleepEx( 1, TRUE
); /* alertable sleep */
1088 ok( apc_count
== 1, "apc was not called\n" );
1091 U(iosb
).Status
= 0xdeadbabe;
1092 iosb
.Information
= 0xdeadbeef;
1093 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1094 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1095 ok( !is_signaled( event
), "event is signaled\n" );
1096 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1097 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1098 ok( !apc_count
, "apc was called\n" );
1099 /* Close queued handle */
1100 CloseHandle( read
);
1101 SleepEx( 1, TRUE
); /* alertable sleep */
1102 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1103 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1104 status
= pNtCancelIoFile( read
, &iosb2
);
1105 ok(status
== STATUS_INVALID_HANDLE
, "cancelled by closed handle?\n");
1106 status
= pNtCancelIoFile( handle
, &iosb2
);
1107 ok(status
== STATUS_SUCCESS
, "failed to cancel: %x\n", status
);
1108 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1109 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1110 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1111 ok( is_signaled( event
), "event is not signaled\n" );
1112 ok( !apc_count
, "apc was called\n" );
1113 SleepEx( 1, TRUE
); /* alertable sleep */
1114 ok( apc_count
== 1, "apc was not called\n" );
1115 CloseHandle( handle
);
1116 CloseHandle( write
);
1118 if (pNtCancelIoFileEx
)
1120 /* Basic Cancel Ex */
1121 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| pipe_flags
, pipe_type
, 4096 )) return;
1124 U(iosb
).Status
= 0xdeadbabe;
1125 iosb
.Information
= 0xdeadbeef;
1126 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1127 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1128 ok( !is_signaled( event
), "event is signaled\n" );
1129 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1130 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1131 ok( !apc_count
, "apc was called\n" );
1132 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1133 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1134 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1135 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1136 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1137 ok( is_signaled( event
), "event is not signaled\n" );
1138 ok( !apc_count
, "apc was called\n" );
1139 SleepEx( 1, TRUE
); /* alertable sleep */
1140 ok( apc_count
== 1, "apc was not called\n" );
1142 /* Duplicate iosb */
1144 U(iosb
).Status
= 0xdeadbabe;
1145 iosb
.Information
= 0xdeadbeef;
1146 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1147 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1148 ok( !is_signaled( event
), "event is signaled\n" );
1149 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1150 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1151 ok( !apc_count
, "apc was called\n" );
1152 status
= NtReadFile( read
, event
, apc
, &apc_count
, &iosb
, buffer
, 2, NULL
, NULL
);
1153 ok( status
== STATUS_PENDING
, "wrong status %x\n", status
);
1154 ok( !is_signaled( event
), "event is signaled\n" );
1155 ok( U(iosb
).Status
== 0xdeadbabe, "wrong status %x\n", U(iosb
).Status
);
1156 ok( iosb
.Information
== 0xdeadbeef, "wrong info %lu\n", iosb
.Information
);
1157 ok( !apc_count
, "apc was called\n" );
1158 status
= pNtCancelIoFileEx( read
, &iosb
, &iosb2
);
1159 ok(status
== STATUS_SUCCESS
, "Failed to cancel I/O\n");
1160 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1161 ok( U(iosb
).Status
== STATUS_CANCELLED
, "wrong status %x\n", U(iosb
).Status
);
1162 ok( iosb
.Information
== 0, "wrong info %lu\n", iosb
.Information
);
1163 ok( is_signaled( event
), "event is not signaled\n" );
1164 ok( !apc_count
, "apc was called\n" );
1165 SleepEx( 1, TRUE
); /* alertable sleep */
1166 ok( apc_count
== 2, "apc was not called\n" );
1168 CloseHandle( read
);
1169 CloseHandle( write
);
1172 win_skip("NtCancelIoFileEx not available\n");
1177 static void test_transceive(void)
1179 IO_STATUS_BLOCK iosb
;
1180 HANDLE caller
, callee
;
1181 HANDLE event
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1187 if (!create_pipe_pair( &caller
, &callee
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1188 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 )) return;
1190 status
= NtFsControlFile( caller
, event
, NULL
, NULL
, &iosb
, FSCTL_PIPE_TRANSCEIVE
,
1191 (BYTE
*)"test", 4, buffer
, sizeof(buffer
) );
1192 ok( status
== STATUS_PENDING
, "NtFsControlFile(FSCTL_PIPE_TRANSCEIVE) returned %x\n", status
);
1193 ok( !is_signaled( event
), "event is signaled\n" );
1195 ret
= WriteFile( callee
, buffer
, 2, &written
, NULL
);
1196 ok(ret
&& written
== 2, "WriteFile error %d\n", GetLastError());
1198 ok( U(iosb
).Status
== 0, "wrong status %x\n", U(iosb
).Status
);
1199 ok( iosb
.Information
== 2, "wrong info %lu\n", iosb
.Information
);
1200 ok( is_signaled( event
), "event is not signaled\n" );
1202 CloseHandle( caller
);
1203 CloseHandle( callee
);
1206 #define test_no_queued_completion(a) _test_no_queued_completion(__LINE__,a)
1207 static void _test_no_queued_completion(unsigned line
, HANDLE port
)
1214 pov
= (void *)0xdeadbeef;
1215 ret
= GetQueuedCompletionStatus(port
, &num_bytes
, &key
, &pov
, 10);
1216 ok_(__FILE__
,line
)(!ret
&& GetLastError() == WAIT_TIMEOUT
,
1217 "GetQueuedCompletionStatus returned %x(%u)\n", ret
, GetLastError());
1220 #define test_queued_completion(a,b,c,d) _test_queued_completion(__LINE__,a,b,c,d)
1221 static void _test_queued_completion(unsigned line
, HANDLE port
, IO_STATUS_BLOCK
*io
,
1222 NTSTATUS expected_status
, ULONG expected_information
)
1224 LARGE_INTEGER timeout
= {{0}};
1225 ULONG_PTR value
= 0xdeadbeef;
1226 IO_STATUS_BLOCK iosb
;
1230 status
= pNtRemoveIoCompletion(port
, &key
, &value
, &iosb
, &timeout
);
1231 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
, "NtRemoveIoCompletion returned %x\n", status
);
1232 ok_(__FILE__
,line
)(value
== (ULONG_PTR
)io
, "value = %lx\n", value
);
1233 ok_(__FILE__
,line
)(io
->Status
== expected_status
, "Status = %x\n", io
->Status
);
1234 ok_(__FILE__
,line
)(io
->Information
== expected_information
,
1235 "Information = %lu\n", io
->Information
);
1238 static void test_completion(void)
1240 static const char buf
[] = "testdata";
1241 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info
;
1242 FILE_PIPE_PEEK_BUFFER peek_buf
;
1244 HANDLE port
, pipe
, client
, event
;
1251 create_pipe_pair( &pipe
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1252 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 );
1254 status
= pNtQueryInformationFile(pipe
, &io
, &info
, sizeof(info
),
1255 FileIoCompletionNotificationInformation
);
1256 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_INVALID_INFO_CLASS
),
1257 "status = %x\n", status
);
1260 win_skip("FileIoCompletionNotificationInformation not supported\n");
1262 CloseHandle(client
);
1266 memset(&ov
, 0, sizeof(ov
));
1267 ov
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1268 ok(ov
.hEvent
!= INVALID_HANDLE_VALUE
, "CreateEvent failed, error %u\n", GetLastError());
1270 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
1271 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %u\n", GetLastError());
1273 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1274 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1275 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
1276 test_queued_completion(port
, (IO_STATUS_BLOCK
*)&ov
, STATUS_SUCCESS
, num_bytes
);
1278 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1279 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1280 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
, "FSCTL_PIPE_PEEK returned %x\n", status
);
1281 test_queued_completion(port
, &io
, STATUS_SUCCESS
, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
));
1283 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
1284 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1285 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1287 ret
= WriteFile(client
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1288 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1289 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
1290 test_no_queued_completion(port
);
1292 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, &ov
);
1293 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1294 ok(num_bytes
== sizeof(buf
), "expected sizeof(buf), got %u\n", num_bytes
);
1296 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, 1, NULL
, NULL
);
1297 ok(status
== STATUS_BUFFER_OVERFLOW
|| status
== STATUS_PENDING
, "status = %x\n", status
);
1298 ok(io
.Status
== STATUS_BUFFER_OVERFLOW
, "Status = %x\n", io
.Status
);
1299 ok(io
.Information
== 1, "Information = %lu\n", io
.Information
);
1300 if(status
== STATUS_PENDING
) /* win8+ */
1301 test_queued_completion(port
, &io
, STATUS_BUFFER_OVERFLOW
, 1);
1303 test_no_queued_completion(port
);
1305 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1306 ok(status
== STATUS_SUCCESS
, "status = %x\n", status
);
1307 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1308 ok(io
.Information
== sizeof(buf
)-1, "Information = %lu\n", io
.Information
);
1309 test_no_queued_completion(port
);
1311 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1312 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1313 ok(status
== STATUS_PENDING
|| status
== STATUS_SUCCESS
, "FSCTL_PIPE_PEEK returned %x\n", status
);
1314 if(status
== STATUS_PENDING
) /* win8+ */
1315 test_queued_completion(port
, &io
, STATUS_SUCCESS
, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
));
1317 test_no_queued_completion(port
);
1319 memset(&io
, 0xcc, sizeof(io
));
1320 status
= NtReadFile(client
, ov
.hEvent
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1321 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1322 ok(!is_signaled(ov
.hEvent
), "event is signtaled\n");
1323 test_no_queued_completion(port
);
1325 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1326 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1327 test_queued_completion(port
, &io
, STATUS_SUCCESS
, sizeof(buf
));
1329 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1330 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1331 status
= NtFsControlFile(client
, NULL
, NULL
, &io
, &io
, FSCTL_PIPE_PEEK
,
1332 NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1333 ok(status
== STATUS_PENDING
|| status
== STATUS_BUFFER_OVERFLOW
,
1334 "FSCTL_PIPE_PEEK returned %x\n", status
);
1335 if(status
== STATUS_PENDING
) /* win8+ */
1336 test_queued_completion(port
, &io
, STATUS_BUFFER_OVERFLOW
, sizeof(peek_buf
));
1338 test_no_queued_completion(port
);
1340 CloseHandle(ov
.hEvent
);
1341 CloseHandle(client
);
1345 event
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1346 create_pipe_pair( &pipe
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_DUPLEX
,
1347 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096 );
1349 ok(is_signaled(client
), "client is not signaled\n");
1351 /* no event, APC nor completion: only signals on handle */
1352 memset(&io
, 0xcc, sizeof(io
));
1353 status
= NtReadFile(client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1354 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1355 ok(!is_signaled(client
), "client is signaled\n");
1357 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1358 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1359 ok(is_signaled(client
), "client is signaled\n");
1360 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1361 ok(io
.Information
== sizeof(buf
), "Information = %lu\n", io
.Information
);
1363 /* event with no APC nor completion: signals only event */
1364 memset(&io
, 0xcc, sizeof(io
));
1365 status
= NtReadFile(client
, event
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1366 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1367 ok(!is_signaled(client
), "client is signaled\n");
1368 ok(!is_signaled(event
), "event is signaled\n");
1370 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1371 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1372 ok(!is_signaled(client
), "client is signaled\n");
1373 ok(is_signaled(event
), "event is not signaled\n");
1374 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1375 ok(io
.Information
== sizeof(buf
), "Information = %lu\n", io
.Information
);
1377 /* APC with no event: handle is signaled */
1378 ioapc_called
= FALSE
;
1379 memset(&io
, 0xcc, sizeof(io
));
1380 status
= NtReadFile(client
, NULL
, ioapc
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1381 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1382 ok(!is_signaled(client
), "client is signaled\n");
1384 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1385 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1386 ok(is_signaled(client
), "client is signaled\n");
1387 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1388 ok(io
.Information
== sizeof(buf
), "Information = %lu\n", io
.Information
);
1390 ok(!ioapc_called
, "ioapc called\n");
1392 ok(ioapc_called
, "ioapc not called\n");
1394 /* completion with no completion port: handle signaled */
1395 memset(&io
, 0xcc, sizeof(io
));
1396 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1397 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1398 ok(!is_signaled(client
), "client is signaled\n");
1400 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1401 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1402 ok(is_signaled(client
), "client is not signaled\n");
1404 port
= CreateIoCompletionPort(client
, NULL
, 0xdeadbeef, 0);
1405 ok(port
!= NULL
, "CreateIoCompletionPort failed, error %u\n", GetLastError());
1407 /* skipping completion on succcess: handle is signaled */
1408 info
.Flags
= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
;
1409 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1410 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1411 ok(is_signaled(client
), "client is not signaled\n");
1413 memset(&io
, 0xcc, sizeof(io
));
1414 status
= NtReadFile(client
, NULL
, NULL
, &io
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1415 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1416 ok(!is_signaled(client
), "client is signaled\n");
1418 ret
= WriteFile(client
, buf
, 1, &num_bytes
, NULL
);
1419 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1420 ok(is_signaled(client
), "client is not signaled\n");
1422 /* skipping set event on handle: handle is never signaled */
1423 info
.Flags
= FILE_SKIP_SET_EVENT_ON_HANDLE
;
1424 status
= pNtSetInformationFile(client
, &io
, &info
, sizeof(info
), FileIoCompletionNotificationInformation
);
1425 ok(status
== STATUS_SUCCESS
, "expected STATUS_SUCCESS, got %08x\n", status
);
1426 ok(!is_signaled(client
), "client is not signaled\n");
1428 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1429 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1430 ok(!is_signaled(client
), "client is signaled\n");
1431 test_queued_completion(port
, &io
, STATUS_SUCCESS
, sizeof(buf
));
1433 memset(&io
, 0xcc, sizeof(io
));
1434 status
= NtReadFile(client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1435 ok(status
== STATUS_PENDING
, "status = %x\n", status
);
1436 ok(!is_signaled(client
), "client is signaled\n");
1438 ret
= WriteFile(client
, buf
, 1, &num_bytes
, NULL
);
1439 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1440 ok(!is_signaled(client
), "client is signaled\n");
1442 ret
= WriteFile(pipe
, buf
, sizeof(buf
), &num_bytes
, NULL
);
1443 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1444 ok(!is_signaled(client
), "client is signaled\n");
1447 CloseHandle(client
);
1451 struct blocking_thread_args
1456 BLOCKING_THREAD_WRITE
,
1457 BLOCKING_THREAD_READ
,
1458 BLOCKING_THREAD_QUIT
1465 static DWORD WINAPI
blocking_thread(void *arg
)
1467 struct blocking_thread_args
*ctx
= arg
;
1468 static const char buf
[] = "testdata";
1470 DWORD res
, num_bytes
;
1475 res
= WaitForSingleObject(ctx
->wait
, 10000);
1476 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1477 if (res
!= WAIT_OBJECT_0
) break;
1479 case BLOCKING_THREAD_WRITE
:
1482 ok(!is_signaled(ctx
->event
), "event is signaled\n");
1483 ok(!ioapc_called
, "ioapc called\n");
1484 ok(!is_signaled(ctx
->client
), "client is signaled\n");
1485 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1486 ret
= WriteFile(ctx
->pipe
, buf
, 1, &num_bytes
, NULL
);
1487 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1489 case BLOCKING_THREAD_READ
:
1492 ok(!is_signaled(ctx
->event
), "event is signaled\n");
1493 ok(!ioapc_called
, "ioapc called\n");
1494 ok(!is_signaled(ctx
->client
), "client is signaled\n");
1495 ok(is_signaled(ctx
->pipe
), "pipe is not signaled\n");
1496 ret
= ReadFile(ctx
->pipe
, read_buf
, 1, &num_bytes
, NULL
);
1497 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1499 case BLOCKING_THREAD_QUIT
:
1502 ok(0, "unvalid command\n");
1504 SetEvent(ctx
->done
);
1510 static void test_blocking(ULONG options
)
1512 struct blocking_thread_args ctx
;
1513 OBJECT_ATTRIBUTES attr
;
1514 UNICODE_STRING name
;
1519 DWORD res
, num_bytes
;
1522 ctx
.wait
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1523 ctx
.done
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1524 thread
= CreateThread(NULL
, 0, blocking_thread
, &ctx
, 0, 0);
1525 ok(thread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
1527 status
= create_pipe(&ctx
.pipe
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1529 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile returned %x\n", status
);
1531 pRtlInitUnicodeString(&name
, testpipe_nt
);
1532 attr
.Length
= sizeof(attr
);
1533 attr
.RootDirectory
= 0;
1534 attr
.ObjectName
= &name
;
1535 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1536 attr
.SecurityDescriptor
= NULL
;
1537 attr
.SecurityQualityOfService
= NULL
;
1538 status
= NtCreateFile(&ctx
.client
, SYNCHRONIZE
| GENERIC_READ
| GENERIC_WRITE
, &attr
, &io
,
1539 NULL
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN
,
1541 ok(status
== STATUS_SUCCESS
, "NtCreateFile returned %x\n", status
);
1543 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1544 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1546 /* blocking read with no event nor APC */
1547 ioapc_called
= FALSE
;
1548 memset(&io
, 0xff, sizeof(io
));
1549 ctx
.cmd
= BLOCKING_THREAD_WRITE
;
1552 status
= NtReadFile(ctx
.client
, NULL
, NULL
, NULL
, &io
, read_buf
, sizeof(read_buf
), NULL
, NULL
);
1553 ok(status
== STATUS_SUCCESS
, "status = %x\n", status
);
1554 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1555 ok(io
.Information
== 1, "Information = %lu\n", io
.Information
);
1556 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1557 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1559 res
= WaitForSingleObject(ctx
.done
, 10000);
1560 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1562 /* blocking read with event and APC */
1563 ioapc_called
= FALSE
;
1564 memset(&io
, 0xff, sizeof(io
));
1565 ctx
.cmd
= BLOCKING_THREAD_WRITE
;
1566 ctx
.event
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1568 status
= NtReadFile(ctx
.client
, ctx
.event
, ioapc
, &io
, &io
, read_buf
,
1569 sizeof(read_buf
), NULL
, NULL
);
1570 ok(status
== STATUS_SUCCESS
, "status = %x\n", status
);
1571 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1572 ok(io
.Information
== 1, "Information = %lu\n", io
.Information
);
1573 ok(is_signaled(ctx
.event
), "event is not signaled\n");
1575 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1576 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1578 if (!(options
& FILE_SYNCHRONOUS_IO_ALERT
))
1579 ok(!ioapc_called
, "ioapc called\n");
1580 SleepEx(0, TRUE
); /* alertable wait state */
1581 ok(ioapc_called
, "ioapc not called\n");
1583 res
= WaitForSingleObject(ctx
.done
, 10000);
1584 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1585 ioapc_called
= FALSE
;
1586 CloseHandle(ctx
.event
);
1589 /* blocking flush */
1590 ret
= WriteFile(ctx
.client
, read_buf
, 1, &num_bytes
, NULL
);
1591 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1593 ioapc_called
= FALSE
;
1594 memset(&io
, 0xff, sizeof(io
));
1595 ctx
.cmd
= BLOCKING_THREAD_READ
;
1597 status
= NtFlushBuffersFile(ctx
.client
, &io
);
1598 ok(status
== STATUS_SUCCESS
, "status = %x\n", status
);
1599 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1600 ok(io
.Information
== 0, "Information = %lu\n", io
.Information
);
1601 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1603 res
= WaitForSingleObject(ctx
.done
, 10000);
1604 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1606 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1607 CloseHandle(ctx
.pipe
);
1608 CloseHandle(ctx
.client
);
1610 /* flush is blocking even in overlapped mode */
1611 create_pipe_pair(&ctx
.pipe
, &ctx
.client
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
1612 PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
, 4096);
1614 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1615 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1617 ret
= WriteFile(ctx
.client
, read_buf
, 1, &num_bytes
, NULL
);
1618 ok(ret
, "WriteFile failed, error %u\n", GetLastError());
1620 ok(is_signaled(ctx
.client
), "client is not signaled\n");
1621 ok(is_signaled(ctx
.pipe
), "pipe is not signaled\n");
1623 ioapc_called
= FALSE
;
1624 memset(&io
, 0xff, sizeof(io
));
1625 ctx
.cmd
= BLOCKING_THREAD_READ
;
1627 status
= NtFlushBuffersFile(ctx
.client
, &io
);
1628 ok(status
== STATUS_SUCCESS
, "status = %x\n", status
);
1629 ok(io
.Status
== STATUS_SUCCESS
, "Status = %x\n", io
.Status
);
1630 ok(io
.Information
== 0, "Information = %lu\n", io
.Information
);
1631 /* client signaling is inconsistent in this case */
1633 res
= WaitForSingleObject(ctx
.done
, 10000);
1634 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1636 CloseHandle(ctx
.pipe
);
1637 CloseHandle(ctx
.client
);
1639 ctx
.cmd
= BLOCKING_THREAD_QUIT
;
1641 res
= WaitForSingleObject(thread
, 10000);
1642 ok(res
== WAIT_OBJECT_0
, "wait returned %x\n", res
);
1644 CloseHandle(ctx
.wait
);
1645 CloseHandle(ctx
.done
);
1646 CloseHandle(thread
);
1649 static void test_volume_info(void)
1651 FILE_FS_DEVICE_INFORMATION
*device_info
;
1652 IO_STATUS_BLOCK iosb
;
1657 if (!create_pipe_pair( &read
, &write
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
1658 PIPE_TYPE_MESSAGE
, 4096 )) return;
1660 memset( buffer
, 0xaa, sizeof(buffer
) );
1661 status
= pNtQueryVolumeInformationFile( read
, &iosb
, buffer
, sizeof(buffer
), FileFsDeviceInformation
);
1662 ok( status
== STATUS_SUCCESS
, "NtQueryVolumeInformationFile failed: %x\n", status
);
1663 ok( iosb
.Information
== sizeof(*device_info
), "Information = %lu\n", iosb
.Information
);
1664 device_info
= (FILE_FS_DEVICE_INFORMATION
*)buffer
;
1665 ok( device_info
->DeviceType
== FILE_DEVICE_NAMED_PIPE
, "DeviceType = %u\n", device_info
->DeviceType
);
1666 ok( !(device_info
->Characteristics
& ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
),
1667 "Characteristics = %x\n", device_info
->Characteristics
);
1669 memset( buffer
, 0xaa, sizeof(buffer
) );
1670 status
= pNtQueryVolumeInformationFile( write
, &iosb
, buffer
, sizeof(buffer
), FileFsDeviceInformation
);
1671 ok( status
== STATUS_SUCCESS
, "NtQueryVolumeInformationFile failed: %x\n", status
);
1672 ok( iosb
.Information
== sizeof(*device_info
), "Information = %lu\n", iosb
.Information
);
1673 device_info
= (FILE_FS_DEVICE_INFORMATION
*)buffer
;
1674 ok( device_info
->DeviceType
== FILE_DEVICE_NAMED_PIPE
, "DeviceType = %u\n", device_info
->DeviceType
);
1675 ok( !(device_info
->Characteristics
& ~FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
),
1676 "Characteristics = %x\n", device_info
->Characteristics
);
1678 CloseHandle( read
);
1679 CloseHandle( write
);
1682 #define test_file_name_fail(a,b) _test_file_name_fail(__LINE__,a,b)
1683 static void _test_file_name_fail(unsigned line
, HANDLE pipe
, NTSTATUS expected_status
)
1686 IO_STATUS_BLOCK iosb
;
1689 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, sizeof(buffer
), FileNameInformation
);
1690 ok_(__FILE__
,line
)( status
== expected_status
, "NtQueryInformationFile failed: %x, expected %x\n",
1691 status
, expected_status
);
1694 #define test_file_name(a) _test_file_name(__LINE__,a)
1695 static void _test_file_name(unsigned line
, HANDLE pipe
)
1698 FILE_NAME_INFORMATION
*name_info
= (FILE_NAME_INFORMATION
*)buffer
;
1699 IO_STATUS_BLOCK iosb
;
1702 static const WCHAR nameW
[] =
1703 {'\\','n','t','d','l','l','_','t','e','s','t','s','_','p','i','p','e','.','c'};
1705 memset( buffer
, 0xaa, sizeof(buffer
) );
1706 memset( &iosb
, 0xaa, sizeof(iosb
) );
1707 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, sizeof(buffer
), FileNameInformation
);
1708 ok_(__FILE__
,line
)( status
== STATUS_SUCCESS
, "NtQueryInformationFile failed: %x\n", status
);
1709 ok_(__FILE__
,line
)( iosb
.Status
== STATUS_SUCCESS
, "Status = %x\n", iosb
.Status
);
1710 ok_(__FILE__
,line
)( iosb
.Information
== sizeof(name_info
->FileNameLength
) + sizeof(nameW
),
1711 "Information = %lu\n", iosb
.Information
);
1712 ok( name_info
->FileNameLength
== sizeof(nameW
), "FileNameLength = %u\n", name_info
->FileNameLength
);
1713 ok( !memcmp(name_info
->FileName
, nameW
, sizeof(nameW
)), "FileName = %s\n", wine_dbgstr_w(name_info
->FileName
) );
1715 /* too small buffer */
1716 memset( buffer
, 0xaa, sizeof(buffer
) );
1717 memset( &iosb
, 0xaa, sizeof(iosb
) );
1718 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, 20, FileNameInformation
);
1719 ok( status
== STATUS_BUFFER_OVERFLOW
, "NtQueryInformationFile failed: %x\n", status
);
1720 ok( iosb
.Status
== STATUS_BUFFER_OVERFLOW
, "Status = %x\n", iosb
.Status
);
1721 ok( iosb
.Information
== 20, "Information = %lu\n", iosb
.Information
);
1722 ok( name_info
->FileNameLength
== sizeof(nameW
), "FileNameLength = %u\n", name_info
->FileNameLength
);
1723 ok( !memcmp(name_info
->FileName
, nameW
, 16), "FileName = %s\n", wine_dbgstr_w(name_info
->FileName
) );
1725 /* too small buffer */
1726 memset( buffer
, 0xaa, sizeof(buffer
) );
1727 memset( &iosb
, 0xaa, sizeof(iosb
) );
1728 status
= NtQueryInformationFile( pipe
, &iosb
, buffer
, 4, FileNameInformation
);
1729 ok( status
== STATUS_INFO_LENGTH_MISMATCH
, "NtQueryInformationFile failed: %x\n", status
);
1732 static HANDLE
create_pipe_server(void)
1737 status
= create_pipe(&handle
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0);
1738 ok(status
== STATUS_SUCCESS
, "create_pipe failed: %x\n", status
);
1742 static HANDLE
connect_pipe(HANDLE server
)
1746 client
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
,
1747 FILE_FLAG_OVERLAPPED
, 0);
1748 ok(client
!= INVALID_HANDLE_VALUE
, "can't open pipe: %u\n", GetLastError());
1753 static HANDLE
connect_and_write_pipe(HANDLE server
)
1760 client
= connect_pipe(server
);
1762 res
= WriteFile(client
, buf
, sizeof(buf
), &written
, NULL
);
1763 ok(res
, "WriteFile failed: %u\n", GetLastError());
1764 res
= WriteFile(server
, buf
, sizeof(buf
), &written
, NULL
);
1765 ok(res
, "WriteFile failed: %u\n", GetLastError());
1770 static void test_pipe_state(HANDLE pipe
, BOOL is_server
, DWORD state
)
1772 FILE_PIPE_PEEK_BUFFER peek_buf
;
1774 static char buf
[] = "test";
1775 NTSTATUS status
, expected_status
;
1777 memset(&peek_buf
, 0xcc, sizeof(peek_buf
));
1778 memset(&io
, 0xcc, sizeof(io
));
1779 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1780 if (!status
|| status
== STATUS_PENDING
)
1784 case FILE_PIPE_DISCONNECTED_STATE
:
1785 expected_status
= is_server
? STATUS_INVALID_PIPE_STATE
: STATUS_PIPE_DISCONNECTED
;
1787 case FILE_PIPE_LISTENING_STATE
:
1788 expected_status
= STATUS_INVALID_PIPE_STATE
;
1790 case FILE_PIPE_CONNECTED_STATE
:
1791 expected_status
= STATUS_SUCCESS
;
1794 expected_status
= STATUS_PIPE_BROKEN
;
1797 ok(status
== expected_status
, "status = %x, expected %x in %s state %u\n",
1798 status
, expected_status
, is_server
? "server" : "client", state
);
1800 ok(peek_buf
.NamedPipeState
== state
, "NamedPipeState = %u, expected %u\n",
1801 peek_buf
.NamedPipeState
, state
);
1803 if (state
!= FILE_PIPE_CONNECTED_STATE
)
1805 if (state
== FILE_PIPE_CLOSING_STATE
)
1806 expected_status
= STATUS_INVALID_PIPE_STATE
;
1807 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_TRANSCEIVE
,
1809 if (!status
|| status
== STATUS_PENDING
)
1811 ok(status
== expected_status
,
1812 "NtFsControlFile(FSCTL_PIPE_TRANSCEIVE) failed in %s state %u: %x\n",
1813 is_server
? "server" : "client", state
, status
);
1816 memset(&io
, 0xcc, sizeof(io
));
1817 status
= NtFlushBuffersFile(pipe
, &io
);
1818 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
1820 ok(status
== STATUS_PIPE_DISCONNECTED
, "status = %x in %s state %u\n",
1821 status
, is_server
? "server" : "client", state
);
1825 ok(status
== STATUS_SUCCESS
, "status = %x in %s state %u\n",
1826 status
, is_server
? "server" : "client", state
);
1827 ok(io
.Status
== status
, "io.Status = %x\n", io
.Status
);
1828 ok(!io
.Information
, "io.Information = %lx\n", io
.Information
);
1831 if (state
!= FILE_PIPE_CONNECTED_STATE
)
1835 case FILE_PIPE_DISCONNECTED_STATE
:
1836 expected_status
= STATUS_PIPE_DISCONNECTED
;
1838 case FILE_PIPE_LISTENING_STATE
:
1839 expected_status
= STATUS_PIPE_LISTENING
;
1842 expected_status
= STATUS_PIPE_BROKEN
;
1845 status
= NtReadFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
1846 ok(status
== expected_status
, "NtReadFile failed in %s state %u: %x\n",
1847 is_server
? "server" : "client", state
, status
);
1850 if (is_server
&& (state
== FILE_PIPE_CLOSING_STATE
|| state
== FILE_PIPE_CONNECTED_STATE
))
1852 memset(&io
, 0xcc, sizeof(io
));
1853 status
= listen_pipe(pipe
, NULL
, &io
, FALSE
);
1854 ok(status
== (state
== FILE_PIPE_CLOSING_STATE
? STATUS_PIPE_CLOSING
: STATUS_PIPE_CONNECTED
),
1855 "status = %x in %u state\n", status
, state
);
1859 static void test_pipe_with_data_state(HANDLE pipe
, BOOL is_server
, DWORD state
)
1861 FILE_PIPE_LOCAL_INFORMATION local_info
;
1862 FILE_PIPE_INFORMATION pipe_info
;
1863 FILE_PIPE_PEEK_BUFFER peek_buf
;
1865 char buf
[256] = "test";
1866 NTSTATUS status
, expected_status
;
1868 memset(&io
, 0xcc, sizeof(io
));
1869 status
= pNtQueryInformationFile(pipe
, &io
, &local_info
, sizeof(local_info
), FilePipeLocalInformation
);
1870 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
1871 ok(status
== STATUS_PIPE_DISCONNECTED
,
1872 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
1873 is_server
? "server" : "client", state
, status
);
1875 ok(status
== STATUS_SUCCESS
,
1876 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
1877 is_server
? "server" : "client", state
, status
);
1879 ok(local_info
.NamedPipeState
== state
, "%s NamedPipeState = %u, expected %u\n",
1880 is_server
? "server" : "client", local_info
.NamedPipeState
, state
);
1882 status
= pNtQueryInformationFile(pipe
, &io
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
1883 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
1884 ok(status
== STATUS_PIPE_DISCONNECTED
,
1885 "NtQueryInformationFile(FilePipeInformation) failed in %s state %u: %x\n",
1886 is_server
? "server" : "client", state
, status
);
1888 ok(status
== STATUS_SUCCESS
,
1889 "NtQueryInformationFile(FilePipeInformation) failed in %s state %u: %x\n",
1890 is_server
? "server" : "client", state
, status
);
1892 status
= NtQueryInformationFile(pipe
, &io
, buf
, sizeof(buf
), FileNameInformation
);
1893 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
1894 ok(status
== STATUS_PIPE_DISCONNECTED
,
1895 "NtQueryInformationFile(FileNameInformation) failed: %x\n", status
);
1897 todo_wine_if(!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
1898 ok(status
== STATUS_SUCCESS
,
1899 "NtQueryInformationFile(FileNameInformation) failed: %x\n", status
);
1901 memset(&peek_buf
, 0xcc, sizeof(peek_buf
));
1902 memset(&io
, 0xcc, sizeof(io
));
1903 status
= NtFsControlFile(pipe
, NULL
, NULL
, NULL
, &io
, FSCTL_PIPE_PEEK
, NULL
, 0, &peek_buf
, sizeof(peek_buf
));
1904 if (!status
|| status
== STATUS_PENDING
)
1908 case FILE_PIPE_DISCONNECTED_STATE
:
1909 expected_status
= is_server
? STATUS_INVALID_PIPE_STATE
: STATUS_PIPE_DISCONNECTED
;
1911 case FILE_PIPE_LISTENING_STATE
:
1912 expected_status
= STATUS_INVALID_PIPE_STATE
;
1915 expected_status
= STATUS_BUFFER_OVERFLOW
;
1918 ok(status
== expected_status
, "status = %x, expected %x in %s state %u\n",
1919 status
, expected_status
, is_server
? "server" : "client", state
);
1920 if (status
== STATUS_BUFFER_OVERFLOW
)
1921 ok(peek_buf
.NamedPipeState
== state
, "NamedPipeState = %u, expected %u\n",
1922 peek_buf
.NamedPipeState
, state
);
1926 case FILE_PIPE_DISCONNECTED_STATE
:
1927 expected_status
= STATUS_PIPE_DISCONNECTED
;
1929 case FILE_PIPE_LISTENING_STATE
:
1930 expected_status
= STATUS_PIPE_LISTENING
;
1932 case FILE_PIPE_CONNECTED_STATE
:
1933 expected_status
= STATUS_SUCCESS
;
1936 expected_status
= STATUS_PIPE_CLOSING
;
1939 status
= NtWriteFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
1940 ok(status
== expected_status
, "NtWriteFile failed in %s state %u: %x\n",
1941 is_server
? "server" : "client", state
, status
);
1943 if (state
== FILE_PIPE_CLOSING_STATE
)
1944 expected_status
= STATUS_SUCCESS
;
1945 status
= NtReadFile(pipe
, NULL
, NULL
, NULL
, &io
, buf
, 1, NULL
, NULL
);
1946 ok(status
== expected_status
, "NtReadFile failed in %s state %u: %x\n",
1947 is_server
? "server" : "client", state
, status
);
1950 static void pipe_for_each_state(HANDLE (*create_server
)(void),
1951 HANDLE (*connect_client
)(HANDLE
),
1952 void (*test
)(HANDLE pipe
, BOOL is_server
, DWORD pipe_state
))
1954 HANDLE client
, server
;
1955 IO_STATUS_BLOCK iosb
;
1960 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1962 server
= create_server();
1963 test(server
, TRUE
, FILE_PIPE_LISTENING_STATE
);
1965 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
1966 ok(status
== STATUS_PENDING
, "listen_pipe returned %x\n", status
);
1967 test(server
, TRUE
, FILE_PIPE_LISTENING_STATE
);
1969 client
= connect_client(server
);
1970 test(server
, TRUE
, FILE_PIPE_CONNECTED_STATE
);
1971 test(client
, FALSE
, FILE_PIPE_CONNECTED_STATE
);
1973 /* server closed, but not disconnected */
1974 CloseHandle(server
);
1975 test(client
, FALSE
, FILE_PIPE_CLOSING_STATE
);
1976 CloseHandle(client
);
1978 server
= create_server();
1979 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
1980 ok(status
== STATUS_PENDING
, "listen_pipe returned %x\n", status
);
1982 client
= connect_client(server
);
1983 ret
= DisconnectNamedPipe(server
);
1984 ok(ret
, "DisconnectNamedPipe failed: %u\n", GetLastError());
1985 test(server
, TRUE
, FILE_PIPE_DISCONNECTED_STATE
);
1986 test(client
, FALSE
, FILE_PIPE_DISCONNECTED_STATE
);
1987 CloseHandle(server
);
1988 test(client
, FALSE
, FILE_PIPE_DISCONNECTED_STATE
);
1989 CloseHandle(client
);
1991 server
= create_server();
1992 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
1993 ok(status
== STATUS_PENDING
, "listen_pipe returned %x\n", status
);
1995 client
= connect_client(server
);
1996 CloseHandle(client
);
1997 test(server
, TRUE
, FILE_PIPE_CLOSING_STATE
);
1998 ret
= DisconnectNamedPipe(server
);
1999 ok(ret
, "DisconnectNamedPipe failed: %u\n", GetLastError());
2000 test(server
, TRUE
, FILE_PIPE_DISCONNECTED_STATE
);
2002 status
= listen_pipe(server
, event
, &iosb
, FALSE
);
2003 ok(status
== STATUS_PENDING
, "listen_pipe returned %x\n", status
);
2004 client
= connect_client(server
);
2005 test(server
, TRUE
, FILE_PIPE_CONNECTED_STATE
);
2006 test(client
, FALSE
, FILE_PIPE_CONNECTED_STATE
);
2007 CloseHandle(client
);
2008 CloseHandle(server
);
2013 static HANDLE
create_local_info_test_pipe(void)
2015 IO_STATUS_BLOCK iosb
;
2016 OBJECT_ATTRIBUTES attr
;
2017 UNICODE_STRING name
;
2018 LARGE_INTEGER timeout
;
2022 pRtlInitUnicodeString(&name
, testpipe_nt
);
2024 attr
.Length
= sizeof(attr
);
2025 attr
.RootDirectory
= 0;
2026 attr
.ObjectName
= &name
;
2027 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2028 attr
.SecurityDescriptor
= NULL
;
2029 attr
.SecurityQualityOfService
= NULL
;
2031 timeout
.QuadPart
= -100000000;
2033 status
= pNtCreateNamedPipeFile(&pipe
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| GENERIC_WRITE
,
2034 &attr
, &iosb
, FILE_SHARE_READ
, FILE_CREATE
, 0, 1, 0, 0, 1,
2035 100, 200, &timeout
);
2036 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile failed: %x\n", status
);
2041 static HANDLE
connect_pipe_reader(HANDLE server
)
2045 client
= CreateFileW(testpipe
, GENERIC_READ
| FILE_WRITE_ATTRIBUTES
, 0, 0, OPEN_EXISTING
,
2046 FILE_FLAG_OVERLAPPED
, 0);
2047 ok(client
!= INVALID_HANDLE_VALUE
, "can't open pipe: %u\n", GetLastError());
2052 static void test_pipe_local_info(HANDLE pipe
, BOOL is_server
, DWORD state
)
2054 FILE_PIPE_LOCAL_INFORMATION local_info
;
2055 FILE_PIPE_INFORMATION pipe_info
;
2056 OBJECT_ATTRIBUTES attr
;
2057 UNICODE_STRING name
;
2058 LARGE_INTEGER timeout
;
2060 IO_STATUS_BLOCK iosb
;
2063 memset(&iosb
, 0xcc, sizeof(iosb
));
2064 memset(&local_info
, 0xcc, sizeof(local_info
));
2065 status
= pNtQueryInformationFile(pipe
, &iosb
, &local_info
, sizeof(local_info
), FilePipeLocalInformation
);
2066 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2067 ok(status
== STATUS_PIPE_DISCONNECTED
,
2068 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2069 is_server
? "server" : "client", state
, status
);
2071 ok(status
== STATUS_SUCCESS
,
2072 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2073 is_server
? "server" : "client", state
, status
);
2076 ok(local_info
.NamedPipeType
== 1, "NamedPipeType = %u\n", local_info
.NamedPipeType
);
2077 ok(local_info
.NamedPipeConfiguration
== 1, "NamedPipeConfiguration = %u\n",
2078 local_info
.NamedPipeConfiguration
);
2079 ok(local_info
.MaximumInstances
== 1, "MaximumInstances = %u\n", local_info
.MaximumInstances
);
2080 if (!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
2081 ok(local_info
.CurrentInstances
== 0 || broken(local_info
.CurrentInstances
== 1 /* winxp */),
2082 "CurrentInstances = %u\n", local_info
.CurrentInstances
);
2084 ok(local_info
.CurrentInstances
== 1,
2085 "CurrentInstances = %u\n", local_info
.CurrentInstances
);
2086 ok(local_info
.InboundQuota
== 100, "InboundQuota = %u\n", local_info
.InboundQuota
);
2087 ok(local_info
.ReadDataAvailable
== 0, "ReadDataAvailable = %u\n",
2088 local_info
.ReadDataAvailable
);
2089 ok(local_info
.OutboundQuota
== 200, "OutboundQuota = %u\n", local_info
.OutboundQuota
);
2091 ok(local_info
.WriteQuotaAvailable
== (is_server
? 200 : 100), "WriteQuotaAvailable = %u\n",
2092 local_info
.WriteQuotaAvailable
);
2093 ok(local_info
.NamedPipeState
== state
, "%s NamedPipeState = %u, expected %u\n",
2094 is_server
? "server" : "client", local_info
.NamedPipeState
, state
);
2095 ok(local_info
.NamedPipeEnd
== is_server
, "NamedPipeEnd = %u\n", local_info
.NamedPipeEnd
);
2097 /* try to create another, incompatible, instance of pipe */
2098 pRtlInitUnicodeString(&name
, testpipe_nt
);
2100 attr
.Length
= sizeof(attr
);
2101 attr
.RootDirectory
= 0;
2102 attr
.ObjectName
= &name
;
2103 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2104 attr
.SecurityDescriptor
= NULL
;
2105 attr
.SecurityQualityOfService
= NULL
;
2107 timeout
.QuadPart
= -100000000;
2109 status
= pNtCreateNamedPipeFile(&new_pipe
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
| GENERIC_READ
,
2110 &attr
, &iosb
, FILE_SHARE_WRITE
, FILE_CREATE
, 0, 0, 0, 0, 1,
2111 100, 200, &timeout
);
2112 if (!local_info
.CurrentInstances
)
2113 ok(status
== STATUS_SUCCESS
, "NtCreateNamedPipeFile failed: %x\n", status
);
2115 ok(status
== STATUS_INSTANCE_NOT_AVAILABLE
, "NtCreateNamedPipeFile failed: %x\n", status
);
2116 if (!status
) CloseHandle(new_pipe
);
2118 memset(&iosb
, 0xcc, sizeof(iosb
));
2119 status
= pNtQueryInformationFile(pipe
, &iosb
, &local_info
, sizeof(local_info
),
2120 FilePipeLocalInformation
);
2121 ok(status
== STATUS_SUCCESS
,
2122 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2123 is_server
? "server" : "client", state
, status
);
2125 if (!is_server
&& state
== FILE_PIPE_CLOSING_STATE
)
2126 ok(local_info
.CurrentInstances
== 0 || broken(local_info
.CurrentInstances
== 1 /* winxp */),
2127 "CurrentInstances = %u\n", local_info
.CurrentInstances
);
2129 ok(local_info
.CurrentInstances
== 1,
2130 "CurrentInstances = %u\n", local_info
.CurrentInstances
);
2133 memset(&iosb
, 0xcc, sizeof(iosb
));
2134 status
= pNtQueryInformationFile(pipe
, &iosb
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
2135 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2136 ok(status
== STATUS_PIPE_DISCONNECTED
,
2137 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2138 is_server
? "server" : "client", state
, status
);
2140 ok(status
== STATUS_SUCCESS
,
2141 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2142 is_server
? "server" : "client", state
, status
);
2146 ok(pipe_info
.ReadMode
== 0, "ReadMode = %u\n", pipe_info
.ReadMode
);
2147 ok(pipe_info
.CompletionMode
== 0, "CompletionMode = %u\n", pipe_info
.CompletionMode
);
2150 pipe_info
.ReadMode
= 0;
2151 pipe_info
.CompletionMode
= 0;
2152 memset(&iosb
, 0xcc, sizeof(iosb
));
2153 status
= pNtSetInformationFile(pipe
, &iosb
, &pipe_info
, sizeof(pipe_info
), FilePipeInformation
);
2154 if (!is_server
&& state
== FILE_PIPE_DISCONNECTED_STATE
)
2155 ok(status
== STATUS_PIPE_DISCONNECTED
,
2156 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2157 is_server
? "server" : "client", state
, status
);
2159 ok(status
== STATUS_SUCCESS
,
2160 "NtQueryInformationFile(FilePipeLocalInformation) failed in %s state %u: %x\n",
2161 is_server
? "server" : "client", state
, status
);
2164 static void test_file_info(void)
2166 HANDLE server
, client
;
2168 if (!create_pipe_pair( &server
, &client
, FILE_FLAG_OVERLAPPED
| PIPE_ACCESS_INBOUND
,
2169 PIPE_TYPE_MESSAGE
, 4096 )) return;
2171 test_file_name( client
);
2172 test_file_name( server
);
2174 DisconnectNamedPipe( server
);
2175 test_file_name_fail( client
, STATUS_PIPE_DISCONNECTED
);
2177 CloseHandle( server
);
2178 CloseHandle( client
);
2181 static PSECURITY_DESCRIPTOR
get_security_descriptor(HANDLE handle
, BOOL todo
)
2183 SECURITY_DESCRIPTOR
*sec_desc
;
2187 status
= NtQuerySecurityObject(handle
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2189 todo_wine_if(todo
&& status
== STATUS_PIPE_DISCONNECTED
)
2190 ok(status
== STATUS_BUFFER_TOO_SMALL
,
2191 "Failed to query object security descriptor length: %08x\n", status
);
2192 if(status
!= STATUS_BUFFER_TOO_SMALL
) return NULL
;
2193 ok(length
!= 0, "length = 0\n");
2195 sec_desc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, length
);
2196 status
= NtQuerySecurityObject(handle
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2197 sec_desc
, length
, &length
);
2198 ok(status
== STATUS_SUCCESS
, "Failed to query object security descriptor: %08x\n", status
);
2203 static TOKEN_OWNER
*get_current_owner(void)
2210 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS
, &token
);
2211 ok(ret
, "Failed to get process token: %u\n", GetLastError());
2213 ret
= GetTokenInformation(token
, TokenOwner
, NULL
, 0, &length
);
2214 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2215 "GetTokenInformation failed: %u\n", GetLastError());
2216 ok(length
!= 0, "Failed to get token owner information length: %u\n", GetLastError());
2218 owner
= HeapAlloc(GetProcessHeap(), 0, length
);
2219 ret
= GetTokenInformation(token
, TokenOwner
, owner
, length
, &length
);
2220 ok(ret
, "Failed to get token owner information: %u)\n", GetLastError());
2226 static TOKEN_PRIMARY_GROUP
*get_current_group(void)
2228 TOKEN_PRIMARY_GROUP
*group
;
2233 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS
, &token
);
2234 ok(ret
, "Failed to get process token: %u\n", GetLastError());
2236 ret
= GetTokenInformation(token
, TokenPrimaryGroup
, NULL
, 0, &length
);
2237 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2238 "GetTokenInformation failed: %u\n", GetLastError());
2239 ok(length
!= 0, "Failed to get primary group token information length: %u\n", GetLastError());
2241 group
= HeapAlloc(GetProcessHeap(), 0, length
);
2242 ret
= GetTokenInformation(token
, TokenPrimaryGroup
, group
, length
, &length
);
2243 ok(ret
, "Failed to get primary group token information: %u\n", GetLastError());
2249 static SID
*well_known_sid(WELL_KNOWN_SID_TYPE sid_type
)
2251 DWORD size
= SECURITY_MAX_SID_SIZE
;
2255 sid
= HeapAlloc(GetProcessHeap(), 0, size
);
2256 ret
= CreateWellKnownSid(sid_type
, NULL
, sid
, &size
);
2257 ok(ret
, "CreateWellKnownSid failed: %u\n", GetLastError());
2261 #define test_group(a,b,c) _test_group(__LINE__,a,b,c)
2262 static void _test_group(unsigned line
, HANDLE handle
, SID
*expected_sid
, BOOL todo
)
2264 SECURITY_DESCRIPTOR
*sec_desc
;
2269 sec_desc
= get_security_descriptor(handle
, todo
);
2270 if (!sec_desc
) return;
2272 status
= RtlGetGroupSecurityDescriptor(sec_desc
, &group_sid
, &defaulted
);
2273 ok_(__FILE__
,line
)(status
== STATUS_SUCCESS
,
2274 "Failed to query group from security descriptor: %08x\n", status
);
2276 ok_(__FILE__
,line
)(EqualSid(group_sid
, expected_sid
), "SIDs are not equal\n");
2278 HeapFree(GetProcessHeap(), 0, sec_desc
);
2281 static void test_security_info(void)
2283 char sec_desc
[SECURITY_DESCRIPTOR_MIN_LENGTH
];
2284 TOKEN_PRIMARY_GROUP
*process_group
;
2285 SECURITY_ATTRIBUTES sec_attr
;
2286 TOKEN_OWNER
*process_owner
;
2287 HANDLE server
, client
, server2
;
2288 SID
*world_sid
, *local_sid
;
2293 trace("security tests...\n");
2295 process_owner
= get_current_owner();
2296 process_group
= get_current_group();
2297 world_sid
= well_known_sid(WinWorldSid
);
2298 local_sid
= well_known_sid(WinLocalSid
);
2300 ret
= InitializeSecurityDescriptor(sec_desc
, SECURITY_DESCRIPTOR_REVISION
);
2301 ok(ret
, "InitializeSecurityDescriptor failed\n");
2303 ret
= SetSecurityDescriptorOwner(sec_desc
, process_owner
->Owner
, FALSE
);
2304 ok(ret
, "SetSecurityDescriptorOwner failed\n");
2306 ret
= SetSecurityDescriptorGroup(sec_desc
, process_group
->PrimaryGroup
, FALSE
);
2307 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2309 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2310 0x20000, 0x20000, 0, NULL
);
2311 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %u\n", GetLastError());
2313 client
= CreateFileA(PIPENAME
, GENERIC_ALL
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2314 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
2316 test_group(server
, process_group
->PrimaryGroup
, TRUE
);
2317 test_group(client
, process_group
->PrimaryGroup
, TRUE
);
2319 /* set server group, client changes as well */
2320 ret
= SetSecurityDescriptorGroup(sec_desc
, world_sid
, FALSE
);
2321 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2322 status
= NtSetSecurityObject(server
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2323 ok(status
== STATUS_SUCCESS
, "NtSetSecurityObject failed: %08x\n", status
);
2325 test_group(server
, world_sid
, FALSE
);
2326 test_group(client
, world_sid
, FALSE
);
2328 /* new instance of pipe server has the same security descriptor */
2329 server2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
, PIPE_TYPE_BYTE
, 10,
2330 0x20000, 0x20000, 0, NULL
);
2331 ok(server2
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %u\n", GetLastError());
2332 test_group(server2
, world_sid
, FALSE
);
2334 /* set client group, server changes as well */
2335 ret
= SetSecurityDescriptorGroup(sec_desc
, local_sid
, FALSE
);
2336 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2337 status
= NtSetSecurityObject(server
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2338 ok(status
== STATUS_SUCCESS
, "NtSetSecurityObject failed: %08x\n", status
);
2340 test_group(server
, local_sid
, FALSE
);
2341 test_group(client
, local_sid
, FALSE
);
2342 test_group(server2
, local_sid
, FALSE
);
2344 CloseHandle(server
);
2345 /* SD is preserved after closing server object */
2346 test_group(client
, local_sid
, FALSE
);
2347 CloseHandle(client
);
2350 client
= CreateFileA(PIPENAME
, GENERIC_ALL
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2351 ok(client
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
2353 test_group(client
, local_sid
, FALSE
);
2355 ret
= DisconnectNamedPipe(server
);
2356 ok(ret
, "DisconnectNamedPipe failed: %u\n", GetLastError());
2358 /* disconnected server may be queried for security info, but client does not */
2359 test_group(server
, local_sid
, FALSE
);
2360 status
= NtQuerySecurityObject(client
, GROUP_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
2362 ok(status
== STATUS_PIPE_DISCONNECTED
, "NtQuerySecurityObject returned %08x\n", status
);
2363 status
= NtSetSecurityObject(client
, GROUP_SECURITY_INFORMATION
, sec_desc
);
2364 ok(status
== STATUS_PIPE_DISCONNECTED
, "NtQuerySecurityObject returned %08x\n", status
);
2366 /* attempting to create another pipe instance with specified sd fails */
2367 sec_attr
.nLength
= sizeof(sec_attr
);
2368 sec_attr
.lpSecurityDescriptor
= sec_desc
;
2369 sec_attr
.bInheritHandle
= FALSE
;
2370 ret
= SetSecurityDescriptorGroup(sec_desc
, local_sid
, FALSE
);
2371 ok(ret
, "SetSecurityDescriptorGroup failed\n");
2372 server2
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2373 0x20000, 0x20000, 0, &sec_attr
);
2375 ok(server2
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_ACCESS_DENIED
,
2376 "CreateNamedPipe failed: %u\n", GetLastError());
2377 if (server2
!= INVALID_HANDLE_VALUE
) CloseHandle(server2
);
2379 CloseHandle(server
);
2380 CloseHandle(client
);
2382 server
= CreateNamedPipeA(PIPENAME
, PIPE_ACCESS_DUPLEX
| WRITE_OWNER
, PIPE_TYPE_BYTE
, 10,
2383 0x20000, 0x20000, 0, &sec_attr
);
2384 ok(server
!= INVALID_HANDLE_VALUE
, "CreateNamedPipe failed: %u\n", GetLastError());
2385 test_group(server
, local_sid
, FALSE
);
2386 CloseHandle(server
);
2388 HeapFree(GetProcessHeap(), 0, process_owner
);
2389 HeapFree(GetProcessHeap(), 0, process_group
);
2390 HeapFree(GetProcessHeap(), 0, world_sid
);
2391 HeapFree(GetProcessHeap(), 0, local_sid
);
2396 if (!init_func_ptrs())
2399 trace("starting invalid create tests\n");
2400 test_create_invalid();
2402 trace("starting create tests\n");
2405 trace("starting overlapped tests\n");
2408 trace("starting completion tests\n");
2411 trace("starting blocking tests\n");
2412 test_blocking(FILE_SYNCHRONOUS_IO_NONALERT
);
2413 test_blocking(FILE_SYNCHRONOUS_IO_ALERT
);
2415 trace("starting FILE_PIPE_INFORMATION tests\n");
2416 test_filepipeinfo();
2418 if (!pOpenThread
|| !pQueueUserAPC
)
2421 trace("starting alertable tests\n");
2424 trace("starting nonalertable tests\n");
2425 test_nonalertable();
2427 trace("starting cancelio tests\n");
2430 trace("starting byte read in byte mode client -> server\n");
2431 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_BYTE
);
2432 trace("starting byte read in message mode client -> server\n");
2433 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
);
2434 trace("starting message read in message mode client -> server\n");
2435 read_pipe_test(PIPE_ACCESS_INBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
2436 trace("starting byte read in byte mode server -> client\n");
2437 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
);
2438 trace("starting byte read in message mode server -> client\n");
2439 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
);
2440 trace("starting message read in message mode server -> client\n");
2441 read_pipe_test(PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_MESSAGE
| PIPE_READMODE_MESSAGE
);
2446 test_security_info();
2448 pipe_for_each_state(create_pipe_server
, connect_pipe
, test_pipe_state
);
2449 pipe_for_each_state(create_pipe_server
, connect_and_write_pipe
, test_pipe_with_data_state
);
2450 pipe_for_each_state(create_local_info_test_pipe
, connect_pipe_reader
, test_pipe_local_info
);