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
*pNtSetInformationFile
) (HANDLE handle
, PIO_STATUS_BLOCK io
, PVOID ptr
, ULONG len
, FILE_INFORMATION_CLASS
class);
77 static NTSTATUS (WINAPI
*pNtCancelIoFile
) (HANDLE hFile
, PIO_STATUS_BLOCK io_status
);
78 static void (WINAPI
*pRtlInitUnicodeString
) (PUNICODE_STRING target
, PCWSTR source
);
80 static HANDLE (WINAPI
*pOpenThread
)(DWORD dwDesiredAccess
, BOOL bInheritHandle
, DWORD dwThreadId
);
81 static DWORD (WINAPI
*pQueueUserAPC
)(PAPCFUNC pfnAPC
, HANDLE hThread
, ULONG_PTR dwData
);
84 static BOOL
init_func_ptrs(void)
86 HMODULE module
= GetModuleHandleA("ntdll.dll");
88 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
89 trace("GetProcAddress(%s) failed\n", #name); \
93 loadfunc(NtFsControlFile
)
94 loadfunc(NtCreateNamedPipeFile
)
95 loadfunc(NtQueryInformationFile
)
96 loadfunc(NtSetInformationFile
)
97 loadfunc(NtCancelIoFile
)
98 loadfunc(RtlInitUnicodeString
)
101 module
= GetModuleHandleA("kernel32.dll");
102 pOpenThread
= (void *)GetProcAddress(module
, "OpenThread");
103 pQueueUserAPC
= (void *)GetProcAddress(module
, "QueueUserAPC");
107 static const WCHAR testpipe
[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
108 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
109 static const WCHAR testpipe_nt
[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
110 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
112 static NTSTATUS
create_pipe(PHANDLE handle
, ULONG sharing
, ULONG options
)
114 IO_STATUS_BLOCK iosb
;
115 OBJECT_ATTRIBUTES attr
;
117 LARGE_INTEGER timeout
;
120 pRtlInitUnicodeString(&name
, testpipe_nt
);
122 attr
.Length
= sizeof(attr
);
123 attr
.RootDirectory
= 0;
124 attr
.ObjectName
= &name
;
125 attr
.Attributes
= 0x40; /*case insensitive */
126 attr
.SecurityDescriptor
= NULL
;
127 attr
.SecurityQualityOfService
= NULL
;
129 timeout
.QuadPart
= -100000000;
131 res
= pNtCreateNamedPipeFile(handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, sharing
, 2 /*FILE_CREATE*/,
132 options
, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
136 static void test_create_invalid(void)
138 IO_STATUS_BLOCK iosb
;
139 OBJECT_ATTRIBUTES attr
;
141 LARGE_INTEGER timeout
;
143 HANDLE handle
, handle2
;
144 FILE_PIPE_LOCAL_INFORMATION info
;
146 pRtlInitUnicodeString(&name
, testpipe_nt
);
148 attr
.Length
= sizeof(attr
);
149 attr
.RootDirectory
= 0;
150 attr
.ObjectName
= &name
;
151 attr
.Attributes
= 0x40; /*case insensitive */
152 attr
.SecurityDescriptor
= NULL
;
153 attr
.SecurityQualityOfService
= NULL
;
155 timeout
.QuadPart
= -100000000;
157 /* create a pipe with FILE_OVERWRITE */
158 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 4 /*FILE_OVERWRITE*/,
159 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
160 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
164 /* create a pipe with FILE_OVERWRITE_IF */
165 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
, 5 /*FILE_OVERWRITE_IF*/,
166 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
167 todo_wine
ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
171 /* create a pipe with sharing = 0 */
172 res
= pNtCreateNamedPipeFile(&handle
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
, 0, 2 /*FILE_CREATE*/,
173 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
174 ok(res
== STATUS_INVALID_PARAMETER
, "NtCreateNamedPipeFile returned %x\n", res
);
178 /* create a pipe without r/w access */
179 res
= pNtCreateNamedPipeFile(&handle
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
180 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
181 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
183 res
= pNtQueryInformationFile(handle
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
184 ok(res
== STATUS_ACCESS_DENIED
, "NtQueryInformationFile returned %x\n", res
);
186 /* test FILE_CREATE creation disposition */
187 res
= pNtCreateNamedPipeFile(&handle2
, SYNCHRONIZE
, &attr
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /*FILE_CREATE*/,
188 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout
);
189 todo_wine
ok(res
== STATUS_ACCESS_DENIED
, "NtCreateNamedPipeFile returned %x\n", res
);
191 CloseHandle(handle2
);
196 static void test_create(void)
201 FILE_PIPE_LOCAL_INFORMATION info
;
202 IO_STATUS_BLOCK iosb
;
204 static const DWORD access
[] = { 0, GENERIC_READ
, GENERIC_WRITE
, GENERIC_READ
| GENERIC_WRITE
};
205 static const DWORD sharing
[] = { FILE_SHARE_READ
, FILE_SHARE_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
};
206 static const DWORD pipe_config
[]= { 1, 0, 2 };
208 for (j
= 0; j
< sizeof(sharing
) / sizeof(DWORD
); j
++) {
209 for (k
= 0; k
< sizeof(access
) / sizeof(DWORD
); k
++) {
211 BOOL should_succeed
= TRUE
;
213 res
= create_pipe(&hserver
, sharing
[j
], FILE_SYNCHRONOUS_IO_NONALERT
);
215 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res
, sharing
[j
]);
219 res
= pNtQueryInformationFile(hserver
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
220 ok(!res
, "NtQueryInformationFile for server returned %x, sharing: %x\n", res
, sharing
[j
]);
221 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
222 info
.NamedPipeConfiguration
, pipe_config
[j
]);
224 hclient
= CreateFileW(testpipe
, access
[k
], 0, 0, OPEN_EXISTING
, 0, 0);
225 if (hclient
!= INVALID_HANDLE_VALUE
) {
226 res
= pNtQueryInformationFile(hclient
, &iosb
, &info
, sizeof(info
), (FILE_INFORMATION_CLASS
)24);
227 ok(!res
, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n",
228 res
, access
[k
], sharing
[j
]);
229 ok(info
.NamedPipeConfiguration
== pipe_config
[j
], "wrong duplex status for pipe: %d, expected %d\n",
230 info
.NamedPipeConfiguration
, pipe_config
[j
]);
231 CloseHandle(hclient
);
234 if (access
[k
] & GENERIC_WRITE
)
235 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_WRITE
);
236 if (access
[k
] & GENERIC_READ
)
237 should_succeed
&= !!(sharing
[j
] & FILE_SHARE_READ
);
240 ok(hclient
!= INVALID_HANDLE_VALUE
, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n",
241 sharing
[j
], access
[k
], GetLastError());
243 ok(hclient
== INVALID_HANDLE_VALUE
, "CreateFile succeeded for sharing %x, access: %x\n", sharing
[j
], access
[k
]);
245 CloseHandle(hserver
);
250 static BOOL ioapc_called
;
251 static void CALLBACK
ioapc(void *arg
, PIO_STATUS_BLOCK io
, ULONG reserved
)
256 static NTSTATUS
listen_pipe(HANDLE hPipe
, HANDLE hEvent
, PIO_STATUS_BLOCK iosb
, BOOL use_apc
)
260 ioapc_called
= FALSE
;
262 return pNtFsControlFile(hPipe
, hEvent
, use_apc
? &ioapc
: NULL
, use_apc
? &dummy
: NULL
, iosb
, FSCTL_PIPE_LISTEN
, 0, 0, 0, 0);
265 static void test_overlapped(void)
267 IO_STATUS_BLOCK iosb
;
273 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
274 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
276 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
277 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
279 memset(&iosb
, 0x55, sizeof(iosb
));
280 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
281 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
282 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
284 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
285 ok(hClient
!= INVALID_HANDLE_VALUE
, "can't open pipe, GetLastError: %x\n", GetLastError());
287 ok(U(iosb
).Status
== 0, "Wrong iostatus %x\n", U(iosb
).Status
);
288 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
290 ok(!ioapc_called
, "IOAPC ran too early\n");
292 SleepEx(0, TRUE
); /* alertable wait state */
294 ok(ioapc_called
, "IOAPC didn't run\n");
297 CloseHandle(hClient
);
299 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
300 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
302 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
303 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
304 "can't open pipe, GetLastError: %x\n", GetLastError());
306 if (hClient
!= INVALID_HANDLE_VALUE
)
308 memset(&iosb
, 0x55, sizeof(iosb
));
309 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
310 ok(res
== STATUS_PIPE_CONNECTED
, "NtFsControlFile returned %x\n", res
);
311 todo_wine
ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
313 CloseHandle(hClient
);
320 static BOOL userapc_called
;
321 static void CALLBACK
userapc(ULONG_PTR dwParam
)
323 userapc_called
= TRUE
;
326 static BOOL open_succeeded
;
327 static DWORD WINAPI
thread(PVOID main_thread
)
335 userapc_called
= FALSE
;
336 ret
= pQueueUserAPC(&userapc
, main_thread
, 0);
337 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
338 CloseHandle(main_thread
);
343 h
= CreateFileW(testpipe
, GENERIC_WRITE
| GENERIC_READ
, 0, 0, OPEN_EXISTING
, 0, 0);
345 if (h
!= INVALID_HANDLE_VALUE
) {
346 open_succeeded
= TRUE
;
350 open_succeeded
= FALSE
;
355 static void test_alertable(void)
357 IO_STATUS_BLOCK iosb
;
364 memset(&iosb
, 0x55, sizeof(iosb
));
366 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
367 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
369 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
370 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
372 /* queue an user apc before calling listen */
373 userapc_called
= FALSE
;
374 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
375 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
377 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
378 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
380 todo_wine
ok(userapc_called
, "user apc didn't run\n");
381 ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
382 todo_wine
ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
383 ok(!ioapc_called
, "IOAPC ran\n");
385 /* queue an user apc from a different thread */
386 hThread
= CreateThread(NULL
, 0, &thread
, pOpenThread(MAXIMUM_ALLOWED
, FALSE
, GetCurrentThreadId()), 0, 0);
387 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
389 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
390 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
391 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
392 todo_wine
ok(res
== STATUS_CANCELLED
, "NtFsControlFile returned %x\n", res
);
394 ok(userapc_called
, "user apc didn't run\n");
395 todo_wine
ok(U(iosb
).Status
== 0x55555555, "iosb.Status got changed to %x\n", U(iosb
).Status
);
396 ok(WaitForSingleObjectEx(hEvent
, 0, TRUE
) == WAIT_TIMEOUT
, "hEvent signaled\n");
397 ok(!ioapc_called
, "IOAPC ran\n");
399 WaitForSingleObject(hThread
, INFINITE
);
401 SleepEx(0, TRUE
); /* get rid of the userapc, if NtFsControlFile failed */
403 ok(open_succeeded
, "couldn't open client side pipe\n");
405 CloseHandle(hThread
);
406 DisconnectNamedPipe(hPipe
);
408 /* finally try without an apc */
409 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
410 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
412 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
413 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
415 ok(open_succeeded
, "couldn't open client side pipe\n");
416 ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
417 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
419 WaitForSingleObject(hThread
, INFINITE
);
420 CloseHandle(hThread
);
425 static void test_nonalertable(void)
427 IO_STATUS_BLOCK iosb
;
434 memset(&iosb
, 0x55, sizeof(iosb
));
436 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
437 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
439 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_NONALERT
);
440 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
442 hThread
= CreateThread(NULL
, 0, &thread
, 0, 0, 0);
443 ok(hThread
!= INVALID_HANDLE_VALUE
, "can't create thread, GetLastError: %x\n", GetLastError());
445 userapc_called
= FALSE
;
446 ret
= pQueueUserAPC(&userapc
, GetCurrentThread(), 0);
447 ok(ret
, "can't queue user apc, GetLastError: %x\n", GetLastError());
449 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
450 todo_wine
ok(!res
, "NtFsControlFile returned %x\n", res
);
452 ok(open_succeeded
, "couldn't open client side pipe\n");
453 todo_wine
ok(!U(iosb
).Status
, "Wrong iostatus %x\n", U(iosb
).Status
);
454 todo_wine
ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
456 ok(!ioapc_called
, "IOAPC ran too early\n");
457 ok(!userapc_called
, "user apc ran too early\n");
459 SleepEx(0, TRUE
); /* alertable wait state */
461 ok(ioapc_called
, "IOAPC didn't run\n");
462 ok(userapc_called
, "user apc didn't run\n");
464 WaitForSingleObject(hThread
, INFINITE
);
465 CloseHandle(hThread
);
470 static void test_cancelio(void)
472 IO_STATUS_BLOCK iosb
;
473 IO_STATUS_BLOCK cancel_sb
;
478 hEvent
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
479 ok(hEvent
!= INVALID_HANDLE_VALUE
, "can't create event, GetLastError: %x\n", GetLastError());
481 res
= create_pipe(&hPipe
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0 /* OVERLAPPED */);
482 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
484 memset(&iosb
, 0x55, sizeof(iosb
));
486 res
= listen_pipe(hPipe
, hEvent
, &iosb
, TRUE
);
487 ok(res
== STATUS_PENDING
, "NtFsControlFile returned %x\n", res
);
489 res
= pNtCancelIoFile(hPipe
, &cancel_sb
);
490 ok(!res
, "NtCancelIoFile returned %x\n", res
);
492 ok(U(iosb
).Status
== STATUS_CANCELLED
, "Wrong iostatus %x\n", U(iosb
).Status
);
493 ok(WaitForSingleObject(hEvent
, 0) == 0, "hEvent not signaled\n");
495 ok(!ioapc_called
, "IOAPC ran too early\n");
497 SleepEx(0, TRUE
); /* alertable wait state */
499 ok(ioapc_called
, "IOAPC didn't run\n");
505 static void _check_pipe_handle_state(int line
, HANDLE handle
, ULONG read
, ULONG completion
)
507 IO_STATUS_BLOCK iosb
;
508 FILE_PIPE_INFORMATION fpi
;
510 if (handle
!= INVALID_HANDLE_VALUE
)
512 memset(&fpi
, 0x55, sizeof(fpi
));
513 res
= pNtQueryInformationFile(handle
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
514 ok_(__FILE__
, line
)(!res
, "NtQueryInformationFile returned %x\n", res
);
515 ok_(__FILE__
, line
)(fpi
.ReadMode
== read
, "Unexpected ReadMode, expected %x, got %x\n",
517 ok_(__FILE__
, line
)(fpi
.CompletionMode
== completion
, "Unexpected CompletionMode, expected %x, got %x\n",
518 completion
, fpi
.CompletionMode
);
521 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
523 static void test_filepipeinfo(void)
525 IO_STATUS_BLOCK iosb
;
526 OBJECT_ATTRIBUTES attr
;
528 LARGE_INTEGER timeout
;
529 HANDLE hServer
, hClient
;
530 FILE_PIPE_INFORMATION fpi
;
533 pRtlInitUnicodeString(&name
, testpipe_nt
);
535 attr
.Length
= sizeof(attr
);
536 attr
.RootDirectory
= 0;
537 attr
.ObjectName
= &name
;
538 attr
.Attributes
= 0x40; /* case insensitive */
539 attr
.SecurityDescriptor
= NULL
;
540 attr
.SecurityQualityOfService
= NULL
;
542 timeout
.QuadPart
= -100000000;
544 /* test with INVALID_HANDLE_VALUE */
545 res
= pNtQueryInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
546 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtQueryInformationFile returned %x\n", res
);
549 fpi
.CompletionMode
= 0;
550 res
= pNtSetInformationFile(INVALID_HANDLE_VALUE
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
551 ok(res
== STATUS_OBJECT_TYPE_MISMATCH
, "NtSetInformationFile returned %x\n", res
);
553 /* server end with read-only attributes */
554 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
555 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
556 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout
);
557 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
559 check_pipe_handle_state(hServer
, 0, 1);
561 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
562 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
563 "can't open pipe, GetLastError: %x\n", GetLastError());
565 check_pipe_handle_state(hServer
, 0, 1);
566 check_pipe_handle_state(hClient
, 0, 0);
569 fpi
.CompletionMode
= 0;
570 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
571 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
573 check_pipe_handle_state(hServer
, 0, 1);
574 check_pipe_handle_state(hClient
, 0, 0);
576 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
577 fpi
.CompletionMode
= 1;
578 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
579 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
581 check_pipe_handle_state(hServer
, 0, 1);
582 check_pipe_handle_state(hClient
, 0, 0);
584 if (hClient
!= INVALID_HANDLE_VALUE
)
586 fpi
.ReadMode
= 1; /* invalid on a byte stream pipe */
587 fpi
.CompletionMode
= 1;
588 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
589 ok(res
== STATUS_INVALID_PARAMETER
, "NtSetInformationFile returned %x\n", res
);
592 check_pipe_handle_state(hServer
, 0, 1);
593 check_pipe_handle_state(hClient
, 0, 0);
595 if (hClient
!= INVALID_HANDLE_VALUE
)
598 fpi
.CompletionMode
= 1;
599 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
600 ok(!res
, "NtSetInformationFile returned %x\n", res
);
603 check_pipe_handle_state(hServer
, 0, 1);
604 check_pipe_handle_state(hClient
, 0, 1);
606 if (hClient
!= INVALID_HANDLE_VALUE
)
609 fpi
.CompletionMode
= 2; /* not in range 0-1 */
610 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
611 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
613 fpi
.ReadMode
= 2; /* not in range 0-1 */
614 fpi
.CompletionMode
= 0;
615 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
616 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
619 CloseHandle(hClient
);
621 check_pipe_handle_state(hServer
, 0, 1);
624 fpi
.CompletionMode
= 0;
625 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
626 ok(res
== STATUS_ACCESS_DENIED
, "NtSetInformationFile returned %x\n", res
);
628 CloseHandle(hServer
);
630 /* message mode server with read/write attributes */
631 res
= pNtCreateNamedPipeFile(&hServer
, FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
, &attr
, &iosb
,
632 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 2 /* FILE_CREATE */,
633 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout
);
634 ok(!res
, "NtCreateNamedPipeFile returned %x\n", res
);
636 check_pipe_handle_state(hServer
, 1, 0);
638 hClient
= CreateFileW(testpipe
, GENERIC_READ
| GENERIC_WRITE
, 0, 0, OPEN_EXISTING
, 0, 0);
639 ok(hClient
!= INVALID_HANDLE_VALUE
|| broken(GetLastError() == ERROR_PIPE_BUSY
) /* > Win 8 */,
640 "can't open pipe, GetLastError: %x\n", GetLastError());
642 check_pipe_handle_state(hServer
, 1, 0);
643 check_pipe_handle_state(hClient
, 0, 0);
645 if (hClient
!= INVALID_HANDLE_VALUE
)
648 fpi
.CompletionMode
= 1;
649 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
650 ok(!res
, "NtSetInformationFile returned %x\n", res
);
653 check_pipe_handle_state(hServer
, 1, 0);
654 check_pipe_handle_state(hClient
, 1, 1);
657 fpi
.CompletionMode
= 1;
658 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
659 ok(!res
, "NtSetInformationFile returned %x\n", res
);
661 check_pipe_handle_state(hServer
, 0, 1);
662 check_pipe_handle_state(hClient
, 1, 1);
664 if (hClient
!= INVALID_HANDLE_VALUE
)
667 fpi
.CompletionMode
= 2; /* not in range 0-1 */
668 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
669 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
671 fpi
.ReadMode
= 2; /* not in range 0-1 */
672 fpi
.CompletionMode
= 0;
673 res
= pNtSetInformationFile(hClient
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
674 ok(res
== STATUS_INVALID_PARAMETER
|| broken(!res
) /* < Vista */, "NtSetInformationFile returned %x\n", res
);
677 CloseHandle(hClient
);
679 check_pipe_handle_state(hServer
, 0, 1);
682 fpi
.CompletionMode
= 0;
683 res
= pNtSetInformationFile(hServer
, &iosb
, &fpi
, sizeof(fpi
), (FILE_INFORMATION_CLASS
)23);
684 ok(!res
, "NtSetInformationFile returned %x\n", res
);
686 check_pipe_handle_state(hServer
, 1, 0);
688 CloseHandle(hServer
);
693 if (!init_func_ptrs())
696 trace("starting invalid create tests\n");
697 test_create_invalid();
699 trace("starting create tests\n");
702 trace("starting overlapped tests\n");
705 trace("starting FILE_PIPE_INFORMATION tests\n");
708 if (!pOpenThread
|| !pQueueUserAPC
)
711 trace("starting alertable tests\n");
714 trace("starting nonalertable tests\n");
717 trace("starting cancelio tests\n");