48cfad03b5f9acc59867b5b19597226d600ff1ed
[reactos.git] / modules / rostests / winetests / ntdll / pipe.c
1 /* Unit test suite for Ntdll NamedPipe API functions
2 *
3 * Copyright 2011 Bernhard Loos
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include "ntdll_test.h"
21
22 #ifndef __WINE_WINTERNL_H
23
24 typedef struct {
25 ULONG ReadMode;
26 ULONG CompletionMode;
27 } FILE_PIPE_INFORMATION;
28
29 typedef struct {
30 ULONG NamedPipeType;
31 ULONG NamedPipeConfiguration;
32 ULONG MaximumInstances;
33 ULONG CurrentInstances;
34 ULONG InboundQuota;
35 ULONG ReadDataAvailable;
36 ULONG OutboundQuota;
37 ULONG WriteQuotaAvailable;
38 ULONG NamedPipeState;
39 ULONG NamedPipeEnd;
40 } FILE_PIPE_LOCAL_INFORMATION;
41
42 #ifndef FILE_SYNCHRONOUS_IO_ALERT
43 #define FILE_SYNCHRONOUS_IO_ALERT 0x10
44 #endif
45
46 #ifndef FILE_SYNCHRONOUS_IO_NONALERT
47 #define FILE_SYNCHRONOUS_IO_NONALERT 0x20
48 #endif
49
50 #ifndef FSCTL_PIPE_LISTEN
51 #define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
52 #endif
53 #endif
54
55 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);
56 static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access,
57 POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb,
58 ULONG sharing, ULONG dispo, ULONG options,
59 ULONG pipe_type, ULONG read_mode,
60 ULONG completion_mode, ULONG max_inst,
61 ULONG inbound_quota, ULONG outbound_quota,
62 PLARGE_INTEGER timeout);
63 static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
64 static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class);
65 static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
66 static NTSTATUS (WINAPI *pNtCancelIoFileEx) (HANDLE hFile, IO_STATUS_BLOCK *iosb, IO_STATUS_BLOCK *io_status);
67 static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
68
69 static HANDLE (WINAPI *pOpenThread)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
70 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
71
72
73 static BOOL init_func_ptrs(void)
74 {
75 HMODULE module = GetModuleHandleA("ntdll.dll");
76
77 #define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
78 trace("GetProcAddress(%s) failed\n", #name); \
79 return FALSE; \
80 }
81
82 loadfunc(NtFsControlFile)
83 loadfunc(NtCreateNamedPipeFile)
84 loadfunc(NtQueryInformationFile)
85 loadfunc(NtSetInformationFile)
86 loadfunc(NtCancelIoFile)
87 loadfunc(NtCancelIoFileEx)
88 loadfunc(RtlInitUnicodeString)
89
90 /* not fatal */
91 module = GetModuleHandleA("kernel32.dll");
92 pOpenThread = (void *)GetProcAddress(module, "OpenThread");
93 pQueueUserAPC = (void *)GetProcAddress(module, "QueueUserAPC");
94 return TRUE;
95 }
96
97 static inline BOOL is_signaled( HANDLE obj )
98 {
99 return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
100 }
101
102 static const WCHAR testpipe[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
103 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
104 static const WCHAR testpipe_nt[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
105 't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
106
107 static NTSTATUS create_pipe(PHANDLE handle, ULONG sharing, ULONG options)
108 {
109 IO_STATUS_BLOCK iosb;
110 OBJECT_ATTRIBUTES attr;
111 UNICODE_STRING name;
112 LARGE_INTEGER timeout;
113 NTSTATUS res;
114
115 pRtlInitUnicodeString(&name, testpipe_nt);
116
117 attr.Length = sizeof(attr);
118 attr.RootDirectory = 0;
119 attr.ObjectName = &name;
120 attr.Attributes = 0x40; /*case insensitive */
121 attr.SecurityDescriptor = NULL;
122 attr.SecurityQualityOfService = NULL;
123
124 timeout.QuadPart = -100000000;
125
126 res = pNtCreateNamedPipeFile(handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, sharing, 2 /*FILE_CREATE*/,
127 options, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
128 return res;
129 }
130
131 static BOOL ioapc_called;
132 static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved)
133 {
134 ioapc_called = TRUE;
135 }
136
137 static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb, BOOL use_apc)
138 {
139 int dummy;
140
141 ioapc_called = FALSE;
142
143 return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0);
144 }
145
146 static void test_create_invalid(void)
147 {
148 IO_STATUS_BLOCK iosb;
149 OBJECT_ATTRIBUTES attr;
150 UNICODE_STRING name;
151 LARGE_INTEGER timeout;
152 NTSTATUS res;
153 HANDLE handle, handle2;
154 FILE_PIPE_LOCAL_INFORMATION info;
155
156 pRtlInitUnicodeString(&name, testpipe_nt);
157
158 attr.Length = sizeof(attr);
159 attr.RootDirectory = 0;
160 attr.ObjectName = &name;
161 attr.Attributes = 0x40; /*case insensitive */
162 attr.SecurityDescriptor = NULL;
163 attr.SecurityQualityOfService = NULL;
164
165 timeout.QuadPart = -100000000;
166
167 /* create a pipe with FILE_OVERWRITE */
168 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ, 4 /*FILE_OVERWRITE*/,
169 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
170 todo_wine ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res);
171 if (!res)
172 CloseHandle(handle);
173
174 /* create a pipe with FILE_OVERWRITE_IF */
175 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ, 5 /*FILE_OVERWRITE_IF*/,
176 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
177 todo_wine ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res);
178 if (!res)
179 CloseHandle(handle);
180
181 /* create a pipe with sharing = 0 */
182 res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, 0, 2 /*FILE_CREATE*/,
183 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
184 ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res);
185 if (!res)
186 CloseHandle(handle);
187
188 /* create a pipe without r/w access */
189 res = pNtCreateNamedPipeFile(&handle, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/,
190 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
191 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
192
193 res = pNtQueryInformationFile(handle, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24);
194 ok(res == STATUS_ACCESS_DENIED, "NtQueryInformationFile returned %x\n", res);
195
196 /* test FILE_CREATE creation disposition */
197 res = pNtCreateNamedPipeFile(&handle2, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/,
198 0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
199 todo_wine ok(res == STATUS_ACCESS_DENIED, "NtCreateNamedPipeFile returned %x\n", res);
200 if (!res)
201 CloseHandle(handle2);
202
203 CloseHandle(handle);
204 }
205
206 static void test_create(void)
207 {
208 HANDLE hserver;
209 NTSTATUS res;
210 int j, k;
211 FILE_PIPE_LOCAL_INFORMATION info;
212 IO_STATUS_BLOCK iosb;
213 HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
214
215 static const DWORD access[] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE};
216 static const DWORD sharing[] = { FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE };
217 static const DWORD pipe_config[]= { 1, 0, 2 };
218
219 for (j = 0; j < sizeof(sharing) / sizeof(DWORD); j++) {
220 for (k = 0; k < sizeof(access) / sizeof(DWORD); k++) {
221 HANDLE hclient;
222 BOOL should_succeed = TRUE;
223
224 res = create_pipe(&hserver, sharing[j], 0);
225 if (res) {
226 ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res, sharing[j]);
227 continue;
228 }
229
230 res = listen_pipe(hserver, hEvent, &iosb, FALSE);
231 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
232
233 res = pNtQueryInformationFile(hserver, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24);
234 ok(!res, "NtQueryInformationFile for server returned %x, sharing: %x\n", res, sharing[j]);
235 ok(info.NamedPipeConfiguration == pipe_config[j], "wrong duplex status for pipe: %d, expected %d\n",
236 info.NamedPipeConfiguration, pipe_config[j]);
237
238 hclient = CreateFileW(testpipe, access[k], 0, 0, OPEN_EXISTING, 0, 0);
239 if (hclient != INVALID_HANDLE_VALUE) {
240 res = pNtQueryInformationFile(hclient, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24);
241 ok(!res, "NtQueryInformationFile for client returned %x, access: %x, sharing: %x\n",
242 res, access[k], sharing[j]);
243 ok(info.NamedPipeConfiguration == pipe_config[j], "wrong duplex status for pipe: %d, expected %d\n",
244 info.NamedPipeConfiguration, pipe_config[j]);
245 CloseHandle(hclient);
246 }
247
248 if (access[k] & GENERIC_WRITE)
249 should_succeed &= !!(sharing[j] & FILE_SHARE_WRITE);
250 if (access[k] & GENERIC_READ)
251 should_succeed &= !!(sharing[j] & FILE_SHARE_READ);
252
253 if (should_succeed)
254 ok(hclient != INVALID_HANDLE_VALUE, "CreateFile failed for sharing %x, access: %x, GetLastError: %d\n",
255 sharing[j], access[k], GetLastError());
256 else
257 ok(hclient == INVALID_HANDLE_VALUE, "CreateFile succeeded for sharing %x, access: %x\n", sharing[j], access[k]);
258
259 CloseHandle(hserver);
260 }
261 }
262 CloseHandle(hEvent);
263 }
264
265 static void test_overlapped(void)
266 {
267 IO_STATUS_BLOCK iosb;
268 HANDLE hEvent;
269 HANDLE hPipe;
270 HANDLE hClient;
271 NTSTATUS res;
272
273 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
274 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
275
276 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
277 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
278
279 memset(&iosb, 0x55, sizeof(iosb));
280 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
281 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
282 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
283
284 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
285 ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError());
286
287 ok(U(iosb).Status == 0, "Wrong iostatus %x\n", U(iosb).Status);
288 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
289
290 ok(!ioapc_called, "IOAPC ran too early\n");
291
292 SleepEx(0, TRUE); /* alertable wait state */
293
294 ok(ioapc_called, "IOAPC didn't run\n");
295
296 CloseHandle(hPipe);
297 CloseHandle(hClient);
298
299 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
300 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
301
302 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
303 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */,
304 "can't open pipe, GetLastError: %x\n", GetLastError());
305
306 if (hClient != INVALID_HANDLE_VALUE)
307 {
308 SetEvent(hEvent);
309 memset(&iosb, 0x55, sizeof(iosb));
310 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
311 ok(res == STATUS_PIPE_CONNECTED, "NtFsControlFile returned %x\n", res);
312 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
313 ok(!is_signaled(hEvent), "hEvent not signaled\n");
314
315 CloseHandle(hClient);
316 }
317
318 CloseHandle(hPipe);
319 CloseHandle(hEvent);
320 }
321
322 static void test_completion(void)
323 {
324 static const char buf[] = "testdata";
325 FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
326 HANDLE port, pipe, client;
327 IO_STATUS_BLOCK iosb;
328 OVERLAPPED ov, *pov;
329 IO_STATUS_BLOCK io;
330 NTSTATUS status;
331 DWORD num_bytes;
332 ULONG_PTR key;
333 DWORD dwret;
334 BOOL ret;
335
336 memset(&ov, 0, sizeof(ov));
337 ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
338 ok(ov.hEvent != INVALID_HANDLE_VALUE, "CreateEvent failed, error %u\n", GetLastError());
339
340 status = create_pipe(&pipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
341 ok(!status, "NtCreateNamedPipeFile returned %x\n", status);
342 status = listen_pipe(pipe, ov.hEvent, &iosb, FALSE);
343 ok(status == STATUS_PENDING, "NtFsControlFile returned %x\n", status);
344
345 client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0,
346 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
347 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed, error %u\n", GetLastError());
348 dwret = WaitForSingleObject(ov.hEvent, 0);
349 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
350
351 port = CreateIoCompletionPort(client, NULL, 0xdeadbeef, 0);
352 ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
353
354 ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
355 ok(ret, "WriteFile failed, error %u\n", GetLastError());
356 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
357
358 key = 0;
359 pov = NULL;
360 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
361 ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
362 ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
363 ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
364
365 info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
366 status = pNtSetInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
367 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
368
369 info.Flags = 0;
370 status = pNtQueryInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
371 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
372 ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
373
374 ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
375 ok(ret, "WriteFile failed, error %u\n", GetLastError());
376 ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
377
378 pov = (void *)0xdeadbeef;
379 ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
380 ok(!ret, "GetQueuedCompletionStatus succeeded\n");
381 ok(pov == NULL, "expected NULL, got %p\n", pov);
382
383 CloseHandle(ov.hEvent);
384 CloseHandle(client);
385 CloseHandle(pipe);
386 CloseHandle(port);
387 }
388
389 static BOOL userapc_called;
390 static void CALLBACK userapc(ULONG_PTR dwParam)
391 {
392 userapc_called = TRUE;
393 }
394
395 static BOOL open_succeeded;
396 static DWORD WINAPI thread(PVOID main_thread)
397 {
398 HANDLE h;
399
400 Sleep(400);
401
402 if (main_thread) {
403 DWORD ret;
404 userapc_called = FALSE;
405 ret = pQueueUserAPC(&userapc, main_thread, 0);
406 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError());
407 CloseHandle(main_thread);
408 }
409
410 Sleep(400);
411
412 h = CreateFileW(testpipe, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
413
414 if (h != INVALID_HANDLE_VALUE) {
415 open_succeeded = TRUE;
416 Sleep(100);
417 CloseHandle(h);
418 } else
419 open_succeeded = FALSE;
420
421 return 0;
422 }
423
424 static void test_alertable(void)
425 {
426 IO_STATUS_BLOCK iosb;
427 HANDLE hEvent;
428 HANDLE hPipe;
429 NTSTATUS res;
430 HANDLE hThread;
431 DWORD ret;
432
433 memset(&iosb, 0x55, sizeof(iosb));
434
435 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
436 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
437
438 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT);
439 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
440
441 /* queue an user apc before calling listen */
442 userapc_called = FALSE;
443 ret = pQueueUserAPC(&userapc, GetCurrentThread(), 0);
444 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError());
445
446 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
447 todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res);
448
449 todo_wine ok(userapc_called, "user apc didn't run\n");
450 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
451 todo_wine ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n");
452 ok(!ioapc_called, "IOAPC ran\n");
453
454 /* queue an user apc from a different thread */
455 hThread = CreateThread(NULL, 0, &thread, pOpenThread(MAXIMUM_ALLOWED, FALSE, GetCurrentThreadId()), 0, 0);
456 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
457
458 /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
459 instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
460 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
461 todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res);
462
463 ok(userapc_called, "user apc didn't run\n");
464 ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
465 ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n");
466 ok(!ioapc_called, "IOAPC ran\n");
467
468 WaitForSingleObject(hThread, INFINITE);
469
470 SleepEx(0, TRUE); /* get rid of the userapc, if NtFsControlFile failed */
471
472 ok(open_succeeded, "couldn't open client side pipe\n");
473
474 CloseHandle(hThread);
475 DisconnectNamedPipe(hPipe);
476
477 /* finally try without an apc */
478 hThread = CreateThread(NULL, 0, &thread, 0, 0, 0);
479 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
480
481 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
482 todo_wine ok(!res, "NtFsControlFile returned %x\n", res);
483
484 ok(open_succeeded, "couldn't open client side pipe\n");
485 ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status);
486 todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
487
488 WaitForSingleObject(hThread, INFINITE);
489 CloseHandle(hThread);
490 CloseHandle(hEvent);
491 CloseHandle(hPipe);
492 }
493
494 static void test_nonalertable(void)
495 {
496 IO_STATUS_BLOCK iosb;
497 HANDLE hEvent;
498 HANDLE hPipe;
499 NTSTATUS res;
500 HANDLE hThread;
501 DWORD ret;
502
503 memset(&iosb, 0x55, sizeof(iosb));
504
505 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
506 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
507
508 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
509 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
510
511 hThread = CreateThread(NULL, 0, &thread, 0, 0, 0);
512 ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
513
514 userapc_called = FALSE;
515 ret = pQueueUserAPC(&userapc, GetCurrentThread(), 0);
516 ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError());
517
518 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
519 todo_wine ok(!res, "NtFsControlFile returned %x\n", res);
520
521 ok(open_succeeded, "couldn't open client side pipe\n");
522 todo_wine ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status);
523 todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
524
525 ok(!ioapc_called, "IOAPC ran too early\n");
526 ok(!userapc_called, "user apc ran too early\n");
527
528 SleepEx(0, TRUE); /* alertable wait state */
529
530 ok(ioapc_called, "IOAPC didn't run\n");
531 ok(userapc_called, "user apc didn't run\n");
532
533 WaitForSingleObject(hThread, INFINITE);
534 CloseHandle(hThread);
535 CloseHandle(hEvent);
536 CloseHandle(hPipe);
537 }
538
539 static void test_cancelio(void)
540 {
541 IO_STATUS_BLOCK iosb;
542 IO_STATUS_BLOCK cancel_sb;
543 HANDLE hEvent;
544 HANDLE hPipe;
545 NTSTATUS res;
546
547 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
548 ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
549
550 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
551 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
552
553 memset(&iosb, 0x55, sizeof(iosb));
554
555 res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
556 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
557
558 res = pNtCancelIoFile(hPipe, &cancel_sb);
559 ok(!res, "NtCancelIoFile returned %x\n", res);
560
561 ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status);
562 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
563
564 ok(!ioapc_called, "IOAPC ran too early\n");
565
566 SleepEx(0, TRUE); /* alertable wait state */
567
568 ok(ioapc_called, "IOAPC didn't run\n");
569
570 CloseHandle(hPipe);
571
572 res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
573 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
574
575 memset(&iosb, 0x55, sizeof(iosb));
576 res = listen_pipe(hPipe, hEvent, &iosb, FALSE);
577 ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
578
579 res = pNtCancelIoFileEx(hPipe, &iosb, &cancel_sb);
580 ok(!res, "NtCancelIoFileEx returned %x\n", res);
581
582 ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status);
583 ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
584
585 CloseHandle(hEvent);
586 CloseHandle(hPipe);
587 }
588
589 static void _check_pipe_handle_state(int line, HANDLE handle, ULONG read, ULONG completion)
590 {
591 IO_STATUS_BLOCK iosb;
592 FILE_PIPE_INFORMATION fpi;
593 NTSTATUS res;
594 if (handle != INVALID_HANDLE_VALUE)
595 {
596 memset(&fpi, 0x55, sizeof(fpi));
597 res = pNtQueryInformationFile(handle, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
598 ok_(__FILE__, line)(!res, "NtQueryInformationFile returned %x\n", res);
599 ok_(__FILE__, line)(fpi.ReadMode == read, "Unexpected ReadMode, expected %x, got %x\n",
600 read, fpi.ReadMode);
601 ok_(__FILE__, line)(fpi.CompletionMode == completion, "Unexpected CompletionMode, expected %x, got %x\n",
602 completion, fpi.CompletionMode);
603 }
604 }
605 #define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle, r, c)
606
607 static void test_filepipeinfo(void)
608 {
609 IO_STATUS_BLOCK iosb;
610 OBJECT_ATTRIBUTES attr;
611 UNICODE_STRING name;
612 LARGE_INTEGER timeout;
613 HANDLE hServer, hClient;
614 FILE_PIPE_INFORMATION fpi;
615 NTSTATUS res;
616
617 pRtlInitUnicodeString(&name, testpipe_nt);
618
619 attr.Length = sizeof(attr);
620 attr.RootDirectory = 0;
621 attr.ObjectName = &name;
622 attr.Attributes = 0x40; /* case insensitive */
623 attr.SecurityDescriptor = NULL;
624 attr.SecurityQualityOfService = NULL;
625
626 timeout.QuadPart = -100000000;
627
628 /* test with INVALID_HANDLE_VALUE */
629 res = pNtQueryInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
630 ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtQueryInformationFile returned %x\n", res);
631
632 fpi.ReadMode = 0;
633 fpi.CompletionMode = 0;
634 res = pNtSetInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
635 ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtSetInformationFile returned %x\n", res);
636
637 /* server end with read-only attributes */
638 res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb,
639 FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */,
640 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout);
641 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
642
643 check_pipe_handle_state(hServer, 0, 1);
644
645 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
646 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */,
647 "can't open pipe, GetLastError: %x\n", GetLastError());
648
649 check_pipe_handle_state(hServer, 0, 1);
650 check_pipe_handle_state(hClient, 0, 0);
651
652 fpi.ReadMode = 0;
653 fpi.CompletionMode = 0;
654 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
655 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
656
657 check_pipe_handle_state(hServer, 0, 1);
658 check_pipe_handle_state(hClient, 0, 0);
659
660 fpi.ReadMode = 1; /* invalid on a byte stream pipe */
661 fpi.CompletionMode = 1;
662 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
663 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
664
665 check_pipe_handle_state(hServer, 0, 1);
666 check_pipe_handle_state(hClient, 0, 0);
667
668 if (hClient != INVALID_HANDLE_VALUE)
669 {
670 fpi.ReadMode = 1; /* invalid on a byte stream pipe */
671 fpi.CompletionMode = 1;
672 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
673 ok(res == STATUS_INVALID_PARAMETER, "NtSetInformationFile returned %x\n", res);
674 }
675
676 check_pipe_handle_state(hServer, 0, 1);
677 check_pipe_handle_state(hClient, 0, 0);
678
679 if (hClient != INVALID_HANDLE_VALUE)
680 {
681 fpi.ReadMode = 0;
682 fpi.CompletionMode = 1;
683 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
684 ok(!res, "NtSetInformationFile returned %x\n", res);
685 }
686
687 check_pipe_handle_state(hServer, 0, 1);
688 check_pipe_handle_state(hClient, 0, 1);
689
690 if (hClient != INVALID_HANDLE_VALUE)
691 {
692 fpi.ReadMode = 0;
693 fpi.CompletionMode = 2; /* not in range 0-1 */
694 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
695 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
696
697 fpi.ReadMode = 2; /* not in range 0-1 */
698 fpi.CompletionMode = 0;
699 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
700 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
701 }
702
703 CloseHandle(hClient);
704
705 check_pipe_handle_state(hServer, 0, 1);
706
707 fpi.ReadMode = 0;
708 fpi.CompletionMode = 0;
709 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
710 ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
711
712 CloseHandle(hServer);
713
714 /* message mode server with read/write attributes */
715 res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb,
716 FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */,
717 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout);
718 ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
719
720 check_pipe_handle_state(hServer, 1, 0);
721
722 hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
723 ok(hClient != INVALID_HANDLE_VALUE || broken(GetLastError() == ERROR_PIPE_BUSY) /* > Win 8 */,
724 "can't open pipe, GetLastError: %x\n", GetLastError());
725
726 check_pipe_handle_state(hServer, 1, 0);
727 check_pipe_handle_state(hClient, 0, 0);
728
729 if (hClient != INVALID_HANDLE_VALUE)
730 {
731 fpi.ReadMode = 1;
732 fpi.CompletionMode = 1;
733 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
734 ok(!res, "NtSetInformationFile returned %x\n", res);
735 }
736
737 check_pipe_handle_state(hServer, 1, 0);
738 check_pipe_handle_state(hClient, 1, 1);
739
740 fpi.ReadMode = 0;
741 fpi.CompletionMode = 1;
742 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
743 ok(!res, "NtSetInformationFile returned %x\n", res);
744
745 check_pipe_handle_state(hServer, 0, 1);
746 check_pipe_handle_state(hClient, 1, 1);
747
748 if (hClient != INVALID_HANDLE_VALUE)
749 {
750 fpi.ReadMode = 0;
751 fpi.CompletionMode = 2; /* not in range 0-1 */
752 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
753 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
754
755 fpi.ReadMode = 2; /* not in range 0-1 */
756 fpi.CompletionMode = 0;
757 res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
758 ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
759 }
760
761 CloseHandle(hClient);
762
763 check_pipe_handle_state(hServer, 0, 1);
764
765 fpi.ReadMode = 1;
766 fpi.CompletionMode = 0;
767 res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
768 ok(!res, "NtSetInformationFile returned %x\n", res);
769
770 check_pipe_handle_state(hServer, 1, 0);
771
772 CloseHandle(hServer);
773 }
774
775 static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
776 {
777 int *count = arg;
778 (*count)++;
779 ok( !reserved, "reserved is not 0: %x\n", reserved );
780 }
781
782 static void test_peek(HANDLE pipe, BOOL is_msgmode)
783 {
784 FILE_PIPE_PEEK_BUFFER buf;
785 IO_STATUS_BLOCK iosb;
786 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
787 NTSTATUS status;
788
789 memset(&iosb, 0x55, sizeof(iosb));
790 status = NtFsControlFile(pipe, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf));
791 ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status);
792 ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status);
793 ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable);
794
795 ResetEvent(event);
796 memset(&iosb, 0x55, sizeof(iosb));
797 status = NtFsControlFile(pipe, event, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf));
798 ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status);
799 ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable);
800 ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status);
801 todo_wine_if(!is_msgmode)
802 ok(is_signaled(event), "event is not signaled\n");
803
804 CloseHandle(event);
805 }
806
807 #define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
808
809 static BOOL create_pipe_pair( HANDLE *read, HANDLE *write, ULONG flags, ULONG type, ULONG size )
810 {
811 const BOOL server_reader = flags & PIPE_ACCESS_INBOUND;
812 HANDLE client, server;
813
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");
817
818 client = CreateFileA(PIPENAME, server_reader ? GENERIC_WRITE : GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0,
819 NULL, OPEN_EXISTING, flags & FILE_FLAG_OVERLAPPED, 0);
820 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
821
822 if(server_reader)
823 {
824 *read = server;
825 *write = client;
826 }
827 else
828 {
829 if(type & PIPE_READMODE_MESSAGE)
830 {
831 DWORD read_mode = PIPE_READMODE_MESSAGE;
832 ok(SetNamedPipeHandleState(client, &read_mode, NULL, NULL), "Change mode\n");
833 }
834
835 *read = client;
836 *write = server;
837 }
838 return TRUE;
839 }
840
841 static void read_pipe_test(ULONG pipe_flags, ULONG pipe_type)
842 {
843 IO_STATUS_BLOCK iosb, iosb2;
844 HANDLE handle, read, write;
845 HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
846 int apc_count = 0;
847 char buffer[128];
848 DWORD written;
849 BOOL ret;
850 NTSTATUS status;
851
852 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
853
854 /* try read with no data */
855 U(iosb).Status = 0xdeadbabe;
856 iosb.Information = 0xdeadbeef;
857 ok( is_signaled( read ), "read handle is not signaled\n" );
858 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
859 ok( status == STATUS_PENDING, "wrong status %x\n", status );
860 ok( !is_signaled( read ), "read handle is signaled\n" );
861 ok( !is_signaled( event ), "event is signaled\n" );
862 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
863 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
864 ok( !apc_count, "apc was called\n" );
865 ret = WriteFile( write, buffer, 1, &written, NULL );
866 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
867 /* iosb updated here by async i/o */
868 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
869 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
870 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
871 ok( !is_signaled( read ), "read handle is signaled\n" );
872 ok( is_signaled( event ), "event is not signaled\n" );
873 ok( !apc_count, "apc was called\n" );
874 apc_count = 0;
875 SleepEx( 1, FALSE ); /* non-alertable sleep */
876 ok( !apc_count, "apc was called\n" );
877 SleepEx( 1, TRUE ); /* alertable sleep */
878 ok( apc_count == 1, "apc not called\n" );
879
880 /* with no event, the pipe handle itself gets signaled */
881 apc_count = 0;
882 U(iosb).Status = 0xdeadbabe;
883 iosb.Information = 0xdeadbeef;
884 ok( !is_signaled( read ), "read handle is signaled\n" );
885 status = NtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
886 ok( status == STATUS_PENDING, "wrong status %x\n", status );
887 ok( !is_signaled( read ), "read handle is signaled\n" );
888 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
889 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
890 ok( !apc_count, "apc was called\n" );
891 ret = WriteFile( write, buffer, 1, &written, NULL );
892 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
893 /* iosb updated here by async i/o */
894 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
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" );
904
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());
912
913 test_peek(read, pipe_type & PIPE_TYPE_MESSAGE);
914
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" );
925
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());
933 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
934 if (pipe_type & PIPE_READMODE_MESSAGE)
935 {
936 ok( status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", status );
937 ok( U(iosb).Status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", U(iosb).Status );
938 }
939 else
940 {
941 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
942 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
943 }
944 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
945 ok( is_signaled( event ), "event is not signaled\n" );
946 ok( !apc_count, "apc was called\n" );
947 SleepEx( 1, FALSE ); /* non-alertable sleep */
948 ok( !apc_count, "apc was called\n" );
949 SleepEx( 1, TRUE ); /* alertable sleep */
950 ok( apc_count == 1, "apc not called\n" );
951 apc_count = 0;
952 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
953 ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
954 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
955 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
956 ok( is_signaled( event ), "event is not signaled\n" );
957 ok( !apc_count, "apc was called\n" );
958 SleepEx( 1, FALSE ); /* non-alertable sleep */
959 ok( !apc_count, "apc was called\n" );
960 SleepEx( 1, TRUE ); /* alertable sleep */
961 ok( apc_count == 1, "apc not called\n" );
962
963 /* try read with no data */
964 apc_count = 0;
965 U(iosb).Status = 0xdeadbabe;
966 iosb.Information = 0xdeadbeef;
967 ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
968 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
969 ok( status == STATUS_PENDING, "wrong status %x\n", status );
970 ok( !is_signaled( event ), "event is signaled\n" );
971 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
972 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
973 ok( !apc_count, "apc was called\n" );
974 ret = WriteFile( write, buffer, 1, &written, NULL );
975 ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
976 /* partial read is good enough */
977 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
978 ok( is_signaled( event ), "event is not signaled\n" );
979 ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
980 ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
981 ok( !apc_count, "apc was called\n" );
982 SleepEx( 1, TRUE ); /* alertable sleep */
983 ok( apc_count == 1, "apc was not called\n" );
984
985 /* read from disconnected pipe */
986 apc_count = 0;
987 U(iosb).Status = 0xdeadbabe;
988 iosb.Information = 0xdeadbeef;
989 CloseHandle( write );
990 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
991 ok( status == STATUS_PIPE_BROKEN, "wrong status %x\n", status );
992 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
993 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
994 ok( !is_signaled( event ), "event is signaled\n" );
995 ok( !apc_count, "apc was called\n" );
996 SleepEx( 1, TRUE ); /* alertable sleep */
997 ok( !apc_count, "apc was called\n" );
998 CloseHandle( read );
999
1000 /* read from disconnected pipe, with invalid event handle */
1001 apc_count = 0;
1002 U(iosb).Status = 0xdeadbabe;
1003 iosb.Information = 0xdeadbeef;
1004 status = NtReadFile( read, (HANDLE)0xdeadbeef, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
1005 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
1006 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1007 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1008 ok( !apc_count, "apc was called\n" );
1009 SleepEx( 1, TRUE ); /* alertable sleep */
1010 ok( !apc_count, "apc was called\n" );
1011 CloseHandle( read );
1012
1013 /* read from closed handle */
1014 apc_count = 0;
1015 U(iosb).Status = 0xdeadbabe;
1016 iosb.Information = 0xdeadbeef;
1017 SetEvent( event );
1018 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
1019 ok( status == STATUS_INVALID_HANDLE, "wrong status %x\n", status );
1020 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1021 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1022 ok( is_signaled( event ), "event is not signaled\n" ); /* not reset on invalid handle */
1023 ok( !apc_count, "apc was called\n" );
1024 SleepEx( 1, TRUE ); /* alertable sleep */
1025 ok( !apc_count, "apc was called\n" );
1026
1027 /* disconnect while async read is in progress */
1028 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
1029 apc_count = 0;
1030 U(iosb).Status = 0xdeadbabe;
1031 iosb.Information = 0xdeadbeef;
1032 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1033 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1034 ok( !is_signaled( event ), "event is signaled\n" );
1035 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1036 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1037 ok( !apc_count, "apc was called\n" );
1038 CloseHandle( write );
1039 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1040 todo_wine_if(!(pipe_type & PIPE_TYPE_MESSAGE) && (pipe_flags & PIPE_ACCESS_OUTBOUND))
1041 ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
1042 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
1043 ok( is_signaled( event ), "event is not signaled\n" );
1044 ok( !apc_count, "apc was called\n" );
1045 SleepEx( 1, TRUE ); /* alertable sleep */
1046 ok( apc_count == 1, "apc was not called\n" );
1047 CloseHandle( read );
1048
1049 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
1050 ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
1051 ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
1052
1053 apc_count = 0;
1054 U(iosb).Status = 0xdeadbabe;
1055 iosb.Information = 0xdeadbeef;
1056 status = NtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1057 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1058 ok( !is_signaled( event ), "event is signaled\n" );
1059 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1060 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1061 ok( !apc_count, "apc was called\n" );
1062 /* Cancel by other handle */
1063 status = pNtCancelIoFile( read, &iosb2 );
1064 ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
1065 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1066 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
1067 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
1068 ok( is_signaled( event ), "event is not signaled\n" );
1069 ok( !apc_count, "apc was called\n" );
1070 SleepEx( 1, TRUE ); /* alertable sleep */
1071 ok( apc_count == 1, "apc was not called\n" );
1072
1073 apc_count = 0;
1074 U(iosb).Status = 0xdeadbabe;
1075 iosb.Information = 0xdeadbeef;
1076 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1077 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1078 ok( !is_signaled( event ), "event is signaled\n" );
1079 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1080 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1081 ok( !apc_count, "apc was called\n" );
1082 /* Close queued handle */
1083 CloseHandle( read );
1084 SleepEx( 1, TRUE ); /* alertable sleep */
1085 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1086 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1087 status = pNtCancelIoFile( read, &iosb2 );
1088 ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
1089 status = pNtCancelIoFile( handle, &iosb2 );
1090 ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
1091 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1092 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
1093 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
1094 ok( is_signaled( event ), "event is not signaled\n" );
1095 ok( !apc_count, "apc was called\n" );
1096 SleepEx( 1, TRUE ); /* alertable sleep */
1097 ok( apc_count == 1, "apc was not called\n" );
1098 CloseHandle( handle );
1099 CloseHandle( write );
1100
1101 if (pNtCancelIoFileEx)
1102 {
1103 /* Basic Cancel Ex */
1104 if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
1105
1106 apc_count = 0;
1107 U(iosb).Status = 0xdeadbabe;
1108 iosb.Information = 0xdeadbeef;
1109 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1110 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1111 ok( !is_signaled( event ), "event is signaled\n" );
1112 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1113 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1114 ok( !apc_count, "apc was called\n" );
1115 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
1116 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
1117 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1118 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
1119 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
1120 ok( is_signaled( event ), "event is not signaled\n" );
1121 ok( !apc_count, "apc was called\n" );
1122 SleepEx( 1, TRUE ); /* alertable sleep */
1123 ok( apc_count == 1, "apc was not called\n" );
1124
1125 /* Duplicate iosb */
1126 apc_count = 0;
1127 U(iosb).Status = 0xdeadbabe;
1128 iosb.Information = 0xdeadbeef;
1129 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1130 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1131 ok( !is_signaled( event ), "event is signaled\n" );
1132 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1133 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1134 ok( !apc_count, "apc was called\n" );
1135 status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
1136 ok( status == STATUS_PENDING, "wrong status %x\n", status );
1137 ok( !is_signaled( event ), "event is signaled\n" );
1138 ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
1139 ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
1140 ok( !apc_count, "apc was called\n" );
1141 status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
1142 ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
1143 Sleep(1); /* FIXME: needed for wine to run the i/o apc */
1144 ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
1145 ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
1146 ok( is_signaled( event ), "event is not signaled\n" );
1147 ok( !apc_count, "apc was called\n" );
1148 SleepEx( 1, TRUE ); /* alertable sleep */
1149 ok( apc_count == 2, "apc was not called\n" );
1150
1151 CloseHandle( read );
1152 CloseHandle( write );
1153 }
1154
1155 CloseHandle(event);
1156 }
1157
1158 START_TEST(pipe)
1159 {
1160 if (!init_func_ptrs())
1161 return;
1162
1163 trace("starting invalid create tests\n");
1164 test_create_invalid();
1165
1166 trace("starting create tests\n");
1167 test_create();
1168
1169 trace("starting overlapped tests\n");
1170 test_overlapped();
1171
1172 trace("starting completion tests\n");
1173 test_completion();
1174
1175 trace("starting FILE_PIPE_INFORMATION tests\n");
1176 test_filepipeinfo();
1177
1178 if (!pOpenThread || !pQueueUserAPC)
1179 return;
1180
1181 trace("starting alertable tests\n");
1182 test_alertable();
1183
1184 trace("starting nonalertable tests\n");
1185 test_nonalertable();
1186
1187 trace("starting cancelio tests\n");
1188 test_cancelio();
1189
1190 trace("starting byte read in byte mode client -> server\n");
1191 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE);
1192 trace("starting byte read in message mode client -> server\n");
1193 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE);
1194 trace("starting message read in message mode client -> server\n");
1195 read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1196 trace("starting byte read in byte mode server -> client\n");
1197 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE);
1198 trace("starting byte read in message mode server -> client\n");
1199 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE);
1200 trace("starting message read in message mode server -> client\n");
1201 read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1202 }