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