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