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