winex11.drv: Map coordinates before calling send_mouse_input.
[wine/zf.git] / dlls / kernel32 / tests / pipe.c
blob0ac356c8483e3d3a30e422a1b898e0d7082f4c64
1 /*
2 * Unit tests for named pipe functions in Wine
4 * Copyright (c) 2002 Dan Kegel
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winioctl.h"
30 #include "wine/test.h"
32 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
34 #define NB_SERVER_LOOPS 8
36 static HANDLE alarm_event;
37 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
38 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
39 static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
40 static BOOL (WINAPI *pGetNamedPipeClientProcessId)(HANDLE,ULONG*);
41 static BOOL (WINAPI *pGetNamedPipeServerProcessId)(HANDLE,ULONG*);
42 static BOOL (WINAPI *pGetNamedPipeClientSessionId)(HANDLE,ULONG*);
43 static BOOL (WINAPI *pGetNamedPipeServerSessionId)(HANDLE,ULONG*);
44 static BOOL (WINAPI *pGetOverlappedResultEx)(HANDLE,OVERLAPPED *,DWORD *,DWORD,BOOL);
46 static BOOL user_apc_ran;
47 static void CALLBACK user_apc(ULONG_PTR param)
49 user_apc_ran = TRUE;
53 enum rpcThreadOp
55 RPC_READFILE
58 struct rpcThreadArgs
60 ULONG_PTR returnValue;
61 DWORD lastError;
62 enum rpcThreadOp op;
63 ULONG_PTR args[5];
66 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
68 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
69 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
70 SetLastError( rpcargs->lastError );
72 switch (rpcargs->op)
74 case RPC_READFILE:
75 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
76 (LPVOID)rpcargs->args[1], /* buffer */
77 (DWORD)rpcargs->args[2], /* bytesToRead */
78 (LPDWORD)rpcargs->args[3], /* bytesRead */
79 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
80 break;
82 default:
83 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
84 rpcargs->returnValue = 0;
85 break;
88 rpcargs->lastError = GetLastError();
89 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
90 return 0;
93 /* Runs ReadFile(...) from a different thread */
94 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
96 struct rpcThreadArgs rpcargs;
97 HANDLE thread;
98 DWORD threadId, ret;
100 rpcargs.returnValue = 0;
101 rpcargs.lastError = GetLastError();
102 rpcargs.op = RPC_READFILE;
103 rpcargs.args[0] = (ULONG_PTR)hFile;
104 rpcargs.args[1] = (ULONG_PTR)buffer;
105 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
106 rpcargs.args[3] = (ULONG_PTR)bytesRead;
107 rpcargs.args[4] = (ULONG_PTR)overlapped;
109 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
110 ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
111 ret = WaitForSingleObject(thread, INFINITE);
112 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
113 CloseHandle(thread);
115 SetLastError(rpcargs.lastError);
116 return (BOOL)rpcargs.returnValue;
119 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
120 static void _test_not_signaled(unsigned line, HANDLE handle)
122 DWORD res = WaitForSingleObject(handle, 0);
123 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
126 #define test_signaled(h) _test_signaled(__LINE__,h)
127 static void _test_signaled(unsigned line, HANDLE handle)
129 DWORD res = WaitForSingleObject(handle, 0);
130 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
133 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
134 static void _test_pipe_info(unsigned line, HANDLE pipe, DWORD ex_flags, DWORD ex_out_buf_size, DWORD ex_in_buf_size, DWORD ex_max_instances)
136 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
137 BOOL res;
139 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
140 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
141 ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
142 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
143 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
144 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
147 #define test_file_access(a,b) _test_file_access(__LINE__,a,b)
148 static void _test_file_access(unsigned line, HANDLE handle, DWORD expected_access)
150 FILE_ACCESS_INFORMATION info;
151 IO_STATUS_BLOCK io;
152 NTSTATUS status;
154 memset(&info, 0x11, sizeof(info));
155 status = NtQueryInformationFile(handle, &io, &info, sizeof(info), FileAccessInformation);
156 ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
157 ok_(__FILE__,line)(info.AccessFlags == expected_access, "got access %08x expected %08x\n",
158 info.AccessFlags, expected_access);
161 static void test_CreateNamedPipe(int pipemode)
163 HANDLE hnp;
164 HANDLE hFile;
165 static const char obuf[] = "Bit Bucket";
166 static const char obuf2[] = "More bits";
167 char ibuf[32], *pbuf;
168 DWORD written;
169 DWORD readden;
170 DWORD avail;
171 DWORD left;
172 DWORD lpmode;
173 BOOL ret;
175 if (pipemode == PIPE_TYPE_BYTE)
176 trace("test_CreateNamedPipe starting in byte mode\n");
177 else
178 trace("test_CreateNamedPipe starting in message mode\n");
180 /* Wait for nonexistent pipe */
181 ret = WaitNamedPipeA(PIPENAME, 2000);
182 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
183 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
185 /* Bad parameter checks */
186 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
187 /* nMaxInstances */ 1,
188 /* nOutBufSize */ 1024,
189 /* nInBufSize */ 1024,
190 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
191 /* lpSecurityAttrib */ NULL);
192 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
193 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
195 if (pipemode == PIPE_TYPE_BYTE)
197 /* Bad parameter checks */
198 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
199 /* nMaxInstances */ 1,
200 /* nOutBufSize */ 1024,
201 /* nInBufSize */ 1024,
202 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
203 /* lpSecurityAttrib */ NULL);
204 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
205 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
208 hnp = CreateNamedPipeA(NULL,
209 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
210 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
211 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
212 "CreateNamedPipe should fail if name is NULL\n");
214 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
215 ok(hFile == INVALID_HANDLE_VALUE
216 && GetLastError() == ERROR_FILE_NOT_FOUND,
217 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
219 /* Functional checks */
221 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
222 /* nMaxInstances */ 1,
223 /* nOutBufSize */ 1024,
224 /* nInBufSize */ 1024,
225 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
226 /* lpSecurityAttrib */ NULL);
227 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
228 test_signaled(hnp);
230 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
231 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES
232 | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA);
234 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
235 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
236 ret, GetLastError());
238 ret = WaitNamedPipeA(PIPENAME, 2000);
239 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
241 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
242 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
244 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
246 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
248 /* Test ConnectNamedPipe() in both directions */
249 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
250 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", GetLastError());
251 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
252 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %u\n", GetLastError());
254 /* don't try to do i/o if one side couldn't be opened, as it hangs */
255 if (hFile != INVALID_HANDLE_VALUE) {
256 HANDLE hFile2;
258 /* Make sure we can read and write a few bytes in both directions */
259 memset(ibuf, 0, sizeof(ibuf));
260 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
261 ok(written == sizeof(obuf), "write file len\n");
262 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
263 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
264 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
266 memset(ibuf, 0, sizeof(ibuf));
267 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
268 ok(written == sizeof(obuf2), "write file len\n");
269 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
270 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
271 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
273 /* Now the same again, but with an additional call to PeekNamedPipe */
274 memset(ibuf, 0, sizeof(ibuf));
275 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
276 ok(written == sizeof(obuf), "write file len 1\n");
277 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
278 ok(avail == sizeof(obuf), "peek 1 got %d bytes\n", avail);
279 if (pipemode == PIPE_TYPE_BYTE)
280 ok(left == 0, "peek 1 got %d bytes left\n", left);
281 else
282 ok(left == sizeof(obuf), "peek 1 got %d bytes left\n", left);
283 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
284 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
285 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
287 memset(ibuf, 0, sizeof(ibuf));
288 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
289 ok(written == sizeof(obuf2), "write file len 2\n");
290 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
291 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
292 if (pipemode == PIPE_TYPE_BYTE)
293 ok(left == 0, "peek 2 got %d bytes left\n", left);
294 else
295 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
296 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
297 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
298 if (pipemode == PIPE_TYPE_BYTE)
299 ok(left == 0, "peek 2 got %d bytes left\n", left);
300 else
301 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
302 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
303 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
304 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
306 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
307 memset(ibuf, 0, sizeof(ibuf));
308 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
309 ok(written == sizeof(obuf2), "write file len\n");
310 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
311 ok(readden == 4, "peek got %d bytes\n", readden);
312 ok(avail == sizeof(obuf2), "peek got %d bytes available\n", avail);
313 if (pipemode == PIPE_TYPE_BYTE)
314 ok(left == -4, "peek got %d bytes left\n", left);
315 else
316 ok(left == sizeof(obuf2)-4, "peek got %d bytes left\n", left);
317 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
318 ok(readden == 4, "read got %d bytes\n", readden);
319 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
320 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
321 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
323 memset(ibuf, 0, sizeof(ibuf));
324 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
325 ok(written == sizeof(obuf), "write file len\n");
326 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
327 ok(readden == 4, "peek got %d bytes\n", readden);
328 ok(avail == sizeof(obuf), "peek got %d bytes available\n", avail);
329 if (pipemode == PIPE_TYPE_BYTE)
331 ok(left == -4, "peek got %d bytes left\n", left);
332 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
334 else
336 ok(left == sizeof(obuf)-4, "peek got %d bytes left\n", left);
337 SetLastError(0xdeadbeef);
338 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
339 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
341 ok(readden == 4, "read got %d bytes\n", readden);
342 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
343 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
344 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
346 /* Similar to above, but use a read buffer size small enough to read in three parts */
347 memset(ibuf, 0, sizeof(ibuf));
348 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
349 ok(written == sizeof(obuf2), "write file len\n");
350 if (pipemode == PIPE_TYPE_BYTE)
352 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
353 ok(readden == 4, "read got %d bytes\n", readden);
354 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
356 else
358 SetLastError(0xdeadbeef);
359 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
360 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
361 ok(readden == 4, "read got %d bytes\n", readden);
362 SetLastError(0xdeadbeef);
363 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
364 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
366 ok(readden == 4, "read got %d bytes\n", readden);
367 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
368 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
369 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
371 /* Test reading of multiple writes */
372 memset(ibuf, 0, sizeof(ibuf));
373 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
374 ok(written == sizeof(obuf), "write file len 3a\n");
375 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
376 ok(written == sizeof(obuf2), "write file len 3b\n");
377 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
378 ok(readden == 4, "peek3 got %d bytes\n", readden);
379 if (pipemode == PIPE_TYPE_BYTE)
380 ok(left == -4, "peek3 got %d bytes left\n", left);
381 else
382 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
383 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
384 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
385 if (pipemode == PIPE_TYPE_BYTE) {
386 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
387 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %d bytes left\n", left);
389 else
391 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
392 ok(left == 0, "peek3 got %d bytes left\n", left);
394 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
395 pbuf = ibuf;
396 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
397 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
398 pbuf += sizeof(obuf);
399 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
401 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
402 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
403 pbuf = ibuf;
404 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
405 pbuf += sizeof(obuf);
406 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
408 /* Multiple writes in the reverse direction */
409 memset(ibuf, 0, sizeof(ibuf));
410 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
411 ok(written == sizeof(obuf), "write file len 4a\n");
412 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
413 ok(written == sizeof(obuf2), "write file len 4b\n");
414 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
415 ok(readden == 4, "peek3 got %d bytes\n", readden);
416 if (pipemode == PIPE_TYPE_BYTE)
417 ok(left == -4, "peek3 got %d bytes left\n", left);
418 else
419 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
420 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
421 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
422 if (pipemode == PIPE_TYPE_BYTE) {
423 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
424 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %d bytes left\n", left);
426 else
428 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
429 ok(left == 0, "peek4 got %d bytes left\n", left);
431 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
432 pbuf = ibuf;
433 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
434 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
435 pbuf += sizeof(obuf);
436 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
438 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
439 if (pipemode == PIPE_TYPE_BYTE) {
440 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
442 else {
443 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
445 pbuf = ibuf;
446 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
447 if (pipemode == PIPE_TYPE_BYTE) {
448 pbuf += sizeof(obuf);
449 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
452 /* Test reading of multiple writes after a mode change
453 (CreateFile always creates a byte mode pipe) */
454 lpmode = PIPE_READMODE_MESSAGE;
455 if (pipemode == PIPE_TYPE_BYTE) {
456 /* trying to change the client end of a byte pipe to message mode should fail */
457 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
459 else {
460 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
462 memset(ibuf, 0, sizeof(ibuf));
463 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
464 ok(written == sizeof(obuf), "write file len 3a\n");
465 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
466 ok(written == sizeof(obuf2), "write file len 3b\n");
467 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
468 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
469 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
470 ok(left == 0, "peek5 got %d bytes left\n", left);
471 pbuf = ibuf;
472 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
473 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
474 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
475 pbuf = ibuf;
476 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
477 if (readden <= sizeof(obuf))
478 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
480 /* Multiple writes in the reverse direction */
481 /* the write of obuf2 from write4 should still be in the buffer */
482 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
483 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
484 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
485 if (avail > 0) {
486 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
487 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
488 pbuf = ibuf;
489 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
491 memset(ibuf, 0, sizeof(ibuf));
492 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
493 ok(written == sizeof(obuf), "write file len 6a\n");
494 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
495 ok(written == sizeof(obuf2), "write file len 6b\n");
496 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
497 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
499 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
500 pbuf = ibuf;
501 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
502 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
503 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
504 pbuf = ibuf;
505 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
506 if (readden <= sizeof(obuf))
507 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
509 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
510 memset(ibuf, 0, sizeof(ibuf));
511 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
512 ok(written == sizeof(obuf2), "write file len 7\n");
513 SetLastError(0xdeadbeef);
514 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
515 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
516 ok(readden == 4, "read got %d bytes 7\n", readden);
517 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
518 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
519 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
521 memset(ibuf, 0, sizeof(ibuf));
522 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
523 ok(written == sizeof(obuf), "write file len 8\n");
524 SetLastError(0xdeadbeef);
525 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
526 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
527 ok(readden == 4, "read got %d bytes 8\n", readden);
528 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
529 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
530 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
532 /* The following test shows that when doing a partial read of a message, the rest
533 * is still in the pipe, and can be received from a second thread. This shows
534 * especially that the content is _not_ stored in thread-local-storage until it is
535 * completely transmitted. The same method works even across multiple processes. */
536 memset(ibuf, 0, sizeof(ibuf));
537 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
538 ok(written == sizeof(obuf), "write file len 9\n");
539 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
540 ok(written == sizeof(obuf2), "write file len 9\n");
541 SetLastError(0xdeadbeef);
542 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
543 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
544 ok(readden == 4, "read got %d bytes 9\n", readden);
545 SetLastError(0xdeadbeef);
546 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
547 ok(!ret, "RpcReadFile 9\n");
548 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
549 ok(readden == 4, "read got %d bytes 9\n", readden);
550 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
551 ok(ret, "RpcReadFile 9\n");
552 ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
553 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
554 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
556 memset(ibuf, 0, sizeof(ibuf));
557 SetLastError(0xdeadbeef);
558 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
559 ok(!ret, "RpcReadFile 9\n");
560 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
561 ok(readden == 4, "read got %d bytes 9\n", readden);
562 SetLastError(0xdeadbeef);
563 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
564 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
565 ok(readden == 4, "read got %d bytes 9\n", readden);
566 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
567 ok(ret, "RpcReadFile 9\n");
568 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
569 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
572 /* Now the reverse direction */
573 memset(ibuf, 0, sizeof(ibuf));
574 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
575 ok(written == sizeof(obuf2), "write file len 10\n");
576 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
577 ok(written == sizeof(obuf), "write file len 10\n");
578 SetLastError(0xdeadbeef);
579 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
580 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
581 ok(readden == 4, "read got %d bytes 10\n", readden);
582 SetLastError(0xdeadbeef);
583 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
584 ok(!ret, "RpcReadFile 10\n");
585 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
586 ok(readden == 4, "read got %d bytes 10\n", readden);
587 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
588 ok(ret, "RpcReadFile 10\n");
589 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
590 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
591 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
593 memset(ibuf, 0, sizeof(ibuf));
594 SetLastError(0xdeadbeef);
595 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
596 ok(!ret, "RpcReadFile 10\n");
597 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
598 ok(readden == 4, "read got %d bytes 10\n", readden);
599 SetLastError(0xdeadbeef);
600 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
601 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
602 ok(readden == 4, "read got %d bytes 10\n", readden);
603 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
604 ok(ret, "RpcReadFile 10\n");
605 ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
606 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
611 /* Picky conformance tests */
613 /* Verify that you can't connect to pipe again
614 * until server calls DisconnectNamedPipe+ConnectNamedPipe
615 * or creates a new pipe
616 * case 1: other client not yet closed
618 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
619 ok(hFile2 == INVALID_HANDLE_VALUE,
620 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
621 ok(GetLastError() == ERROR_PIPE_BUSY,
622 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
624 ok(CloseHandle(hFile), "CloseHandle\n");
626 /* case 2: other client already closed */
627 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
628 ok(hFile == INVALID_HANDLE_VALUE,
629 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
630 ok(GetLastError() == ERROR_PIPE_BUSY,
631 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
633 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
635 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
636 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
637 ok(hFile == INVALID_HANDLE_VALUE,
638 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
639 ok(GetLastError() == ERROR_PIPE_BUSY,
640 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
642 /* to be complete, we'd call ConnectNamedPipe here and loop,
643 * but by default that's blocking, so we'd either have
644 * to turn on the uncommon nonblocking mode, or
645 * use another thread.
649 ok(CloseHandle(hnp), "CloseHandle\n");
651 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, pipemode | PIPE_WAIT,
652 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
653 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
654 test_signaled(hnp);
656 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES
657 | FILE_READ_DATA);
659 CloseHandle(hnp);
661 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_OUTBOUND, pipemode | PIPE_WAIT,
662 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
663 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
664 test_signaled(hnp);
666 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
667 | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA);
669 hFile = CreateFileA(PIPENAME, 0, 0, NULL, OPEN_EXISTING, 0, 0);
670 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
671 test_file_access(hFile, SYNCHRONIZE | FILE_READ_ATTRIBUTES);
672 CloseHandle(hFile);
674 CloseHandle(hnp);
676 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
679 static void test_CreateNamedPipe_instances_must_match(void)
681 HANDLE hnp, hnp2;
683 /* Check no mismatch */
684 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
685 /* nMaxInstances */ 2,
686 /* nOutBufSize */ 1024,
687 /* nInBufSize */ 1024,
688 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
689 /* lpSecurityAttrib */ NULL);
690 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
692 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
693 /* nMaxInstances */ 2,
694 /* nOutBufSize */ 1024,
695 /* nInBufSize */ 1024,
696 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
697 /* lpSecurityAttrib */ NULL);
698 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
700 ok(CloseHandle(hnp), "CloseHandle\n");
701 ok(CloseHandle(hnp2), "CloseHandle\n");
703 /* Check nMaxInstances */
704 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
705 /* nMaxInstances */ 1,
706 /* nOutBufSize */ 1024,
707 /* nInBufSize */ 1024,
708 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
709 /* lpSecurityAttrib */ NULL);
710 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
712 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
713 /* nMaxInstances */ 1,
714 /* nOutBufSize */ 1024,
715 /* nInBufSize */ 1024,
716 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
717 /* lpSecurityAttrib */ NULL);
718 ok(hnp2 == INVALID_HANDLE_VALUE
719 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
721 ok(CloseHandle(hnp), "CloseHandle\n");
723 /* Check PIPE_ACCESS_* */
724 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
725 /* nMaxInstances */ 2,
726 /* nOutBufSize */ 1024,
727 /* nInBufSize */ 1024,
728 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
729 /* lpSecurityAttrib */ NULL);
730 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
732 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
733 /* nMaxInstances */ 2,
734 /* nOutBufSize */ 1024,
735 /* nInBufSize */ 1024,
736 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
737 /* lpSecurityAttrib */ NULL);
738 ok(hnp2 == INVALID_HANDLE_VALUE
739 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
741 ok(CloseHandle(hnp), "CloseHandle\n");
743 /* check everything else */
744 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
745 /* nMaxInstances */ 4,
746 /* nOutBufSize */ 1024,
747 /* nInBufSize */ 1024,
748 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
749 /* lpSecurityAttrib */ NULL);
750 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
752 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
753 /* nMaxInstances */ 3,
754 /* nOutBufSize */ 102,
755 /* nInBufSize */ 24,
756 /* nDefaultWait */ 1234,
757 /* lpSecurityAttrib */ NULL);
758 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
760 ok(CloseHandle(hnp), "CloseHandle\n");
761 ok(CloseHandle(hnp2), "CloseHandle\n");
764 static void test_ReadFile(void)
766 HANDLE server, client;
767 OVERLAPPED overlapped;
768 DWORD size;
769 BOOL res;
771 static char buf[512];
773 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
774 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
775 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
776 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
778 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
779 OPEN_EXISTING, 0, 0);
780 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
782 ok(WriteFile(client, buf, sizeof(buf), &size, NULL), "WriteFile\n");
784 res = ReadFile(server, buf, 1, &size, NULL);
785 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
786 ok(size == 1, "size = %u\n", size);
788 /* pass both overlapped and ret read */
789 memset(&overlapped, 0, sizeof(overlapped));
790 res = ReadFile(server, buf, 1, &size, &overlapped);
791 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%u)\n", res, GetLastError());
792 ok(size == 0, "size = %u\n", size);
793 ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "Internal = %lx\n", overlapped.Internal);
794 ok(overlapped.InternalHigh == 1, "InternalHigh = %lx\n", overlapped.InternalHigh);
796 DisconnectNamedPipe(server);
798 memset(&overlapped, 0, sizeof(overlapped));
799 overlapped.InternalHigh = 0xdeadbeef;
800 res = ReadFile(server, buf, 1, &size, &overlapped);
801 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
802 ok(size == 0, "size = %u\n", size);
803 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
804 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
806 memset(&overlapped, 0, sizeof(overlapped));
807 overlapped.InternalHigh = 0xdeadbeef;
808 res = WriteFile(server, buf, 1, &size, &overlapped);
809 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%u)\n", res, GetLastError());
810 ok(size == 0, "size = %u\n", size);
811 ok(overlapped.Internal == STATUS_PENDING, "Internal = %lx\n", overlapped.Internal);
812 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %lx\n", overlapped.InternalHigh);
814 CloseHandle(server);
815 CloseHandle(client);
818 /** implementation of alarm() */
819 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
821 DWORD_PTR timeout = (DWORD_PTR) arg;
822 if (winetest_debug > 1) trace("alarmThreadMain\n");
823 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
825 ok(FALSE, "alarm\n");
826 ExitProcess(1);
828 return 1;
831 static HANDLE hnp = INVALID_HANDLE_VALUE;
833 /** Trivial byte echo server - disconnects after each session */
834 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
836 int i;
838 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
839 /* Set up a simple echo server */
840 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
841 PIPE_TYPE_BYTE | PIPE_WAIT,
842 /* nMaxInstances */ 1,
843 /* nOutBufSize */ 1024,
844 /* nInBufSize */ 1024,
845 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
846 /* lpSecurityAttrib */ NULL);
848 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
849 for (i = 0; i < NB_SERVER_LOOPS; i++) {
850 char buf[512];
851 DWORD written;
852 DWORD readden;
853 BOOL success;
855 /* Wait for client to connect */
856 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
857 ok(ConnectNamedPipe(hnp, NULL)
858 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
859 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
861 /* Echo bytes once */
862 memset(buf, 0, sizeof(buf));
864 if (winetest_debug > 1) trace("Server reading...\n");
865 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
866 if (winetest_debug > 1) trace("Server done reading.\n");
867 ok(success, "ReadFile\n");
868 ok(readden, "short read\n");
870 if (winetest_debug > 1) trace("Server writing...\n");
871 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
872 if (winetest_debug > 1) trace("Server done writing.\n");
873 ok(written == readden, "write file len\n");
875 /* finish this connection, wait for next one */
876 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
877 if (winetest_debug > 1) trace("Server done flushing.\n");
878 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
879 if (winetest_debug > 1) trace("Server done disconnecting.\n");
881 return 0;
884 /** Trivial byte echo server - closes after each connection */
885 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
887 int i;
888 HANDLE hnpNext = 0;
890 trace("serverThreadMain2\n");
891 /* Set up a simple echo server */
892 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
893 PIPE_TYPE_BYTE | PIPE_WAIT,
894 /* nMaxInstances */ 2,
895 /* nOutBufSize */ 1024,
896 /* nInBufSize */ 1024,
897 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
898 /* lpSecurityAttrib */ NULL);
899 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
901 for (i = 0; i < NB_SERVER_LOOPS; i++) {
902 char buf[512];
903 DWORD written;
904 DWORD readden;
905 DWORD ret;
906 BOOL success;
909 user_apc_ran = FALSE;
910 if (i == 0)
912 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
913 ret = QueueUserAPC(&user_apc, GetCurrentThread(), 0);
914 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
917 /* Wait for client to connect */
918 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
919 ok(ConnectNamedPipe(hnp, NULL)
920 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
921 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
923 /* Echo bytes once */
924 memset(buf, 0, sizeof(buf));
926 if (winetest_debug > 1) trace("Server reading...\n");
927 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
928 if (winetest_debug > 1) trace("Server done reading.\n");
929 ok(success, "ReadFile\n");
931 if (winetest_debug > 1) trace("Server writing...\n");
932 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
933 if (winetest_debug > 1) trace("Server done writing.\n");
934 ok(written == readden, "write file len\n");
936 /* finish this connection, wait for next one */
937 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
938 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
940 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
942 if (i == 0)
943 SleepEx(0, TRUE); /* get rid of apc */
945 /* Set up next echo server */
946 hnpNext =
947 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
948 PIPE_TYPE_BYTE | PIPE_WAIT,
949 /* nMaxInstances */ 2,
950 /* nOutBufSize */ 1024,
951 /* nInBufSize */ 1024,
952 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
953 /* lpSecurityAttrib */ NULL);
955 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
957 ok(CloseHandle(hnp), "CloseHandle\n");
958 hnp = hnpNext;
960 return 0;
963 /** Trivial byte echo server - uses overlapped named pipe calls */
964 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
966 int i;
967 HANDLE hEvent;
969 if (winetest_debug > 1) trace("serverThreadMain3\n");
970 /* Set up a simple echo server */
971 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
972 PIPE_TYPE_BYTE | PIPE_WAIT,
973 /* nMaxInstances */ 1,
974 /* nOutBufSize */ 1024,
975 /* nInBufSize */ 1024,
976 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
977 /* lpSecurityAttrib */ NULL);
978 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
980 hEvent = CreateEventW(NULL, /* security attribute */
981 TRUE, /* manual reset event */
982 FALSE, /* initial state */
983 NULL); /* name */
984 ok(hEvent != NULL, "CreateEvent\n");
986 for (i = 0; i < NB_SERVER_LOOPS; i++) {
987 char buf[512];
988 DWORD written;
989 DWORD readden;
990 DWORD dummy;
991 BOOL success;
992 OVERLAPPED oOverlap;
993 int letWFSOEwait = (i & 2);
994 int letGORwait = (i & 1);
995 DWORD err;
997 memset(&oOverlap, 0, sizeof(oOverlap));
998 oOverlap.hEvent = hEvent;
1000 /* Wait for client to connect */
1001 if (i == 0) {
1002 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
1003 success = ConnectNamedPipe(hnp, NULL);
1004 err = GetLastError();
1005 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1006 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1007 } else {
1008 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1009 success = ConnectNamedPipe(hnp, &oOverlap);
1010 err = GetLastError();
1011 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
1012 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
1013 if (!success && (err == ERROR_IO_PENDING)) {
1014 if (letWFSOEwait)
1016 DWORD ret;
1017 do {
1018 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1019 } while (ret == WAIT_IO_COMPLETION);
1020 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
1022 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
1023 if (!letGORwait && !letWFSOEwait && !success) {
1024 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1025 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
1028 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
1029 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1032 /* Echo bytes once */
1033 memset(buf, 0, sizeof(buf));
1035 if (winetest_debug > 1) trace("Server reading...\n");
1036 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
1037 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1038 err = GetLastError();
1039 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
1040 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
1041 if (!success && (err == ERROR_IO_PENDING)) {
1042 if (letWFSOEwait)
1044 DWORD ret;
1045 do {
1046 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1047 } while (ret == WAIT_IO_COMPLETION);
1048 ok(ret == 0, "wait ReadFile returned %x\n", ret);
1050 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
1051 if (!letGORwait && !letWFSOEwait && !success) {
1052 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1053 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
1056 if (winetest_debug > 1) trace("Server done reading.\n");
1057 ok(success, "overlapped ReadFile\n");
1059 if (winetest_debug > 1) trace("Server writing...\n");
1060 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
1061 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1062 err = GetLastError();
1063 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
1064 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1065 if (!success && (err == ERROR_IO_PENDING)) {
1066 if (letWFSOEwait)
1068 DWORD ret;
1069 do {
1070 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1071 } while (ret == WAIT_IO_COMPLETION);
1072 ok(ret == 0, "wait WriteFile returned %x\n", ret);
1074 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
1075 if (!letGORwait && !letWFSOEwait && !success) {
1076 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1077 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
1080 if (winetest_debug > 1) trace("Server done writing.\n");
1081 ok(success, "overlapped WriteFile\n");
1082 ok(written == readden, "write file len\n");
1084 /* finish this connection, wait for next one */
1085 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1086 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1088 return 0;
1091 /** Trivial byte echo server - uses i/o completion ports */
1092 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
1094 int i;
1095 HANDLE hcompletion;
1096 BOOL ret;
1098 if (winetest_debug > 1) trace("serverThreadMain4\n");
1099 /* Set up a simple echo server */
1100 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1101 PIPE_TYPE_BYTE | PIPE_WAIT,
1102 /* nMaxInstances */ 1,
1103 /* nOutBufSize */ 1024,
1104 /* nInBufSize */ 1024,
1105 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1106 /* lpSecurityAttrib */ NULL);
1107 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1109 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1110 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
1112 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1113 char buf[512];
1114 DWORD written;
1115 DWORD readden;
1116 DWORD dummy;
1117 BOOL success;
1118 OVERLAPPED oConnect;
1119 OVERLAPPED oRead;
1120 OVERLAPPED oWrite;
1121 OVERLAPPED *oResult;
1122 DWORD err;
1123 ULONG_PTR compkey;
1125 memset(&oConnect, 0, sizeof(oConnect));
1126 memset(&oRead, 0, sizeof(oRead));
1127 memset(&oWrite, 0, sizeof(oWrite));
1129 /* Wait for client to connect */
1130 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1131 success = ConnectNamedPipe(hnp, &oConnect);
1132 err = GetLastError();
1133 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1134 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
1135 if (!success && err == ERROR_IO_PENDING) {
1136 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1137 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1138 if (!success)
1140 ok( GetLastError() == WAIT_TIMEOUT,
1141 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1142 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1144 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1145 if (success)
1147 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1148 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1151 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1153 /* Echo bytes once */
1154 memset(buf, 0, sizeof(buf));
1156 if (winetest_debug > 1) trace("Server reading...\n");
1157 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1158 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1159 err = GetLastError();
1160 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
1161 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1162 &oResult, 10000);
1163 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1164 if (success)
1166 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1167 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1169 if (winetest_debug > 1) trace("Server done reading.\n");
1171 if (winetest_debug > 1) trace("Server writing...\n");
1172 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1173 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1174 err = GetLastError();
1175 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
1176 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1177 &oResult, 10000);
1178 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1179 if (success)
1181 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1182 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1183 ok(written == readden, "write file len\n");
1185 if (winetest_debug > 1) trace("Server done writing.\n");
1187 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1189 /* Wait for the pipe to break. */
1190 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1192 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1193 SetLastError(ERROR_SUCCESS);
1194 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1195 err = GetLastError();
1196 ok(!success && err == ERROR_NO_DATA,
1197 "overlapped WriteFile on disconnected pipe returned %u, err=%i\n", success, err);
1199 /* No completion status is queued on immediate error. */
1200 SetLastError(ERROR_SUCCESS);
1201 oResult = (OVERLAPPED *)0xdeadbeef;
1202 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1203 &oResult, 0);
1204 err = GetLastError();
1205 ok(!success && err == WAIT_TIMEOUT && !oResult,
1206 "WriteFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1207 success, err, oResult);
1209 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1210 SetLastError(ERROR_SUCCESS);
1211 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1212 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1213 err = GetLastError();
1214 ok(!success && err == ERROR_BROKEN_PIPE,
1215 "overlapped ReadFile on disconnected pipe returned %u, err=%i\n", success, err);
1217 SetLastError(ERROR_SUCCESS);
1218 oResult = (OVERLAPPED *)0xdeadbeef;
1219 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1220 &oResult, 0);
1221 err = GetLastError();
1222 ok(!success && err == WAIT_TIMEOUT && !oResult,
1223 "ReadFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1224 success, err, oResult);
1226 /* finish this connection, wait for next one */
1227 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1228 success = DisconnectNamedPipe(hnp);
1229 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1232 ret = CloseHandle(hnp);
1233 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1234 ret = CloseHandle(hcompletion);
1235 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
1237 return 0;
1240 static int completion_called;
1241 static DWORD completion_errorcode;
1242 static DWORD completion_num_bytes;
1243 static LPOVERLAPPED completion_lpoverlapped;
1245 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1247 completion_called++;
1248 completion_errorcode = errorcode;
1249 completion_num_bytes = num_bytes;
1250 completion_lpoverlapped = lpoverlapped;
1251 SetEvent(lpoverlapped->hEvent);
1254 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1255 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1257 int i;
1258 HANDLE hEvent;
1260 if (winetest_debug > 1) trace("serverThreadMain5\n");
1261 /* Set up a simple echo server */
1262 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1263 PIPE_TYPE_BYTE | PIPE_WAIT,
1264 /* nMaxInstances */ 1,
1265 /* nOutBufSize */ 1024,
1266 /* nInBufSize */ 1024,
1267 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1268 /* lpSecurityAttrib */ NULL);
1269 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1271 hEvent = CreateEventW(NULL, /* security attribute */
1272 TRUE, /* manual reset event */
1273 FALSE, /* initial state */
1274 NULL); /* name */
1275 ok(hEvent != NULL, "CreateEvent\n");
1277 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1278 char buf[512];
1279 DWORD readden;
1280 BOOL success;
1281 OVERLAPPED oOverlap;
1282 DWORD err;
1284 memset(&oOverlap, 0, sizeof(oOverlap));
1285 oOverlap.hEvent = hEvent;
1287 /* Wait for client to connect */
1288 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1289 success = ConnectNamedPipe(hnp, NULL);
1290 err = GetLastError();
1291 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1292 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1294 /* Echo bytes once */
1295 memset(buf, 0, sizeof(buf));
1297 if (winetest_debug > 1) trace("Server reading...\n");
1298 completion_called = 0;
1299 ResetEvent(hEvent);
1300 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1301 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1302 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
1303 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1304 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1305 if (success) {
1306 DWORD ret;
1307 do {
1308 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1309 } while (ret == WAIT_IO_COMPLETION);
1310 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
1312 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1313 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1314 ok(completion_num_bytes != 0, "read 0 bytes\n");
1315 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1316 readden = completion_num_bytes;
1317 if (winetest_debug > 1) trace("Server done reading.\n");
1319 if (winetest_debug > 1) trace("Server writing...\n");
1320 completion_called = 0;
1321 ResetEvent(hEvent);
1322 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1323 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1324 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
1325 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1326 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1327 if (success) {
1328 DWORD ret;
1329 do {
1330 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1331 } while (ret == WAIT_IO_COMPLETION);
1332 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
1334 if (winetest_debug > 1) trace("Server done writing.\n");
1335 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1336 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1337 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
1338 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1340 /* finish this connection, wait for next one */
1341 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1342 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1344 return 0;
1347 static void exerciseServer(const char *pipename, HANDLE serverThread)
1349 int i;
1351 if (winetest_debug > 1) trace("exerciseServer starting\n");
1352 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1353 HANDLE hFile=INVALID_HANDLE_VALUE;
1354 static const char obuf[] = "Bit Bucket";
1355 char ibuf[32];
1356 DWORD written;
1357 DWORD readden;
1358 int loop;
1360 for (loop = 0; loop < 3; loop++) {
1361 DWORD err;
1362 if (winetest_debug > 1) trace("Client connecting...\n");
1363 /* Connect to the server */
1364 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1365 NULL, OPEN_EXISTING, 0, 0);
1366 if (hFile != INVALID_HANDLE_VALUE)
1367 break;
1368 err = GetLastError();
1369 if (loop == 0)
1370 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1371 else
1372 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1373 if (winetest_debug > 1) trace("connect failed, retrying\n");
1374 Sleep(200);
1376 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1378 /* Make sure it can echo */
1379 memset(ibuf, 0, sizeof(ibuf));
1380 if (winetest_debug > 1) trace("Client writing...\n");
1381 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1382 ok(written == sizeof(obuf), "write file len\n");
1383 if (winetest_debug > 1) trace("Client reading...\n");
1384 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1385 ok(readden == sizeof(obuf), "read file len\n");
1386 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1388 if (winetest_debug > 1) trace("Client closing...\n");
1389 ok(CloseHandle(hFile), "CloseHandle\n");
1392 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1393 CloseHandle(hnp);
1394 if (winetest_debug > 1) trace("exerciseServer returning\n");
1397 static void test_NamedPipe_2(void)
1399 HANDLE serverThread;
1400 DWORD serverThreadId;
1401 HANDLE alarmThread;
1402 DWORD alarmThreadId;
1404 trace("test_NamedPipe_2 starting\n");
1405 /* Set up a twenty second timeout */
1406 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1407 SetLastError(0xdeadbeef);
1408 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1409 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1411 /* The servers we're about to exercise do try to clean up carefully,
1412 * but to reduce the chance of a test failure due to a pipe handle
1413 * leak in the test code, we'll use a different pipe name for each server.
1416 /* Try server #1 */
1417 SetLastError(0xdeadbeef);
1418 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1419 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1420 exerciseServer(PIPENAME "serverThreadMain1", serverThread);
1422 /* Try server #2 */
1423 SetLastError(0xdeadbeef);
1424 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1425 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1426 exerciseServer(PIPENAME "serverThreadMain2", serverThread);
1428 /* Try server #3 */
1429 SetLastError(0xdeadbeef);
1430 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1431 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1432 exerciseServer(PIPENAME "serverThreadMain3", serverThread);
1434 /* Try server #4 */
1435 SetLastError(0xdeadbeef);
1436 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1437 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1438 exerciseServer(PIPENAME "serverThreadMain4", serverThread);
1440 /* Try server #5 */
1441 SetLastError(0xdeadbeef);
1442 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1443 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1444 exerciseServer(PIPENAME "serverThreadMain5", serverThread);
1446 ok(SetEvent( alarm_event ), "SetEvent\n");
1447 CloseHandle( alarm_event );
1448 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1451 static int test_DisconnectNamedPipe(void)
1453 HANDLE hnp;
1454 HANDLE hFile;
1455 static const char obuf[] = "Bit Bucket";
1456 char ibuf[32];
1457 DWORD written;
1458 DWORD readden;
1459 DWORD ret;
1461 SetLastError(0xdeadbeef);
1462 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1463 /* nMaxInstances */ 1,
1464 /* nOutBufSize */ 1024,
1465 /* nInBufSize */ 1024,
1466 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1467 /* lpSecurityAttrib */ NULL);
1468 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1469 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1471 win_skip("Named pipes are not implemented\n");
1472 return 1;
1475 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1476 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1477 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1478 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1480 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1481 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1483 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1484 if (hFile != INVALID_HANDLE_VALUE) {
1486 /* see what happens if server calls DisconnectNamedPipe
1487 * when there are bytes in the pipe
1490 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1491 ok(written == sizeof(obuf), "write file len\n");
1492 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1493 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1494 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1495 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1496 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1497 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL) == 0
1498 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1499 "ReadFile from disconnected pipe with bytes waiting\n");
1500 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1501 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1502 "ReadFile from disconnected pipe with bytes waiting\n");
1504 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1505 "DisconnectNamedPipe worked twice\n");
1506 ret = WaitForSingleObject(hFile, 0);
1507 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1509 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1510 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %x (%u)\n",
1511 ret, GetLastError());
1512 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1513 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
1514 ret, GetLastError());
1515 ok(CloseHandle(hFile), "CloseHandle\n");
1518 ok(CloseHandle(hnp), "CloseHandle\n");
1520 return 0;
1522 static void test_CreatePipe(void)
1524 SECURITY_ATTRIBUTES pipe_attr;
1525 HANDLE piperead, pipewrite;
1526 DWORD written;
1527 DWORD read;
1528 DWORD i, size;
1529 BYTE *buffer;
1530 char readbuf[32];
1532 user_apc_ran = FALSE;
1533 ok(QueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1535 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1536 pipe_attr.bInheritHandle = TRUE;
1537 pipe_attr.lpSecurityDescriptor = NULL;
1538 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1539 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1540 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1541 test_file_access(piperead, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1542 | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES | FILE_READ_DATA);
1543 test_file_access(pipewrite, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1544 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA
1545 | FILE_WRITE_DATA);
1547 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1548 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1549 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1550 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1551 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1552 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1554 /* Now write another chunk*/
1555 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1556 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1557 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1558 /* and close the write end, read should still succeed*/
1559 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1560 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1561 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1562 /* But now we need to get informed that the pipe is closed */
1563 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1564 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1566 /* Try bigger chunks */
1567 size = 32768;
1568 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1569 for (i = 0; i < size; i++) buffer[i] = i;
1570 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1571 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1572 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1573 /* and close the write end, read should still succeed*/
1574 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1575 memset( buffer, 0, size );
1576 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1577 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1578 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1579 /* But now we need to get informed that the pipe is closed */
1580 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1581 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1582 HeapFree(GetProcessHeap(), 0, buffer);
1584 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1585 SleepEx(0, TRUE); /* get rid of apc */
1587 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1588 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1589 test_pipe_info(pipewrite, 0, 1, 1, 1);
1590 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1591 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1594 static void test_CloseHandle(void)
1596 static const char testdata[] = "Hello World";
1597 DWORD state, numbytes;
1598 HANDLE hpipe, hfile;
1599 char buffer[32];
1600 BOOL ret;
1602 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1603 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1604 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1605 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1607 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1608 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1610 numbytes = 0xdeadbeef;
1611 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1612 ok(ret, "WriteFile failed with %u\n", GetLastError());
1613 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1615 numbytes = 0xdeadbeef;
1616 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1617 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1618 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1620 ret = CloseHandle(hpipe);
1621 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1623 numbytes = 0xdeadbeef;
1624 memset(buffer, 0, sizeof(buffer));
1625 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1626 ok(ret, "ReadFile failed with %u\n", GetLastError());
1627 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1629 numbytes = 0xdeadbeef;
1630 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1631 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1632 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1634 numbytes = 0xdeadbeef;
1635 memset(buffer, 0, sizeof(buffer));
1636 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1637 ok(ret, "ReadFile failed with %u\n", GetLastError());
1638 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1640 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1641 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1642 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1643 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1644 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1646 SetLastError(0xdeadbeef);
1647 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1648 ok(!ret, "ReadFile unexpectedly succeeded\n");
1649 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1651 numbytes = 0xdeadbeef;
1652 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1653 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1654 ret, GetLastError());
1655 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1657 SetLastError(0xdeadbeef);
1658 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1659 ok(!ret, "WriteFile unexpectedly succeeded\n");
1660 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1662 CloseHandle(hfile);
1664 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1665 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1666 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1667 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1669 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1670 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1672 numbytes = 0xdeadbeef;
1673 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1674 ok(ret, "WriteFile failed with %u\n", GetLastError());
1675 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1677 ret = CloseHandle(hpipe);
1678 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1680 numbytes = 0xdeadbeef;
1681 memset(buffer, 0, sizeof(buffer));
1682 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1683 ok(ret, "ReadFile failed with %u\n", GetLastError());
1684 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1686 SetLastError(0xdeadbeef);
1687 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1688 ok(!ret, "ReadFile unexpectedly succeeded\n");
1689 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1691 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1692 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1693 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1694 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1695 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1697 SetLastError(0xdeadbeef);
1698 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1699 ok(!ret, "ReadFile unexpectedly succeeded\n");
1700 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1702 SetLastError(0xdeadbeef);
1703 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1704 ok(!ret, "WriteFile unexpectedly succeeded\n");
1705 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1707 CloseHandle(hfile);
1709 /* repeat test with hpipe <-> hfile swapped */
1711 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1712 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1713 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1714 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1716 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1717 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1719 numbytes = 0xdeadbeef;
1720 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1721 ok(ret, "WriteFile failed with %u\n", GetLastError());
1722 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1724 numbytes = 0xdeadbeef;
1725 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1726 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1727 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1729 ret = CloseHandle(hfile);
1730 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1732 numbytes = 0xdeadbeef;
1733 memset(buffer, 0, sizeof(buffer));
1734 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1735 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1736 "ReadFile failed with %u\n", GetLastError());
1737 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1739 numbytes = 0xdeadbeef;
1740 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1741 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1742 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1744 numbytes = 0xdeadbeef;
1745 memset(buffer, 0, sizeof(buffer));
1746 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1747 ok(ret, "ReadFile failed with %u\n", GetLastError());
1748 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1750 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1751 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1752 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1753 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1754 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1756 SetLastError(0xdeadbeef);
1757 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1758 ok(!ret, "ReadFile unexpectedly succeeded\n");
1759 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1761 numbytes = 0xdeadbeef;
1762 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1763 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1764 ret, GetLastError());
1765 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1767 SetLastError(0xdeadbeef);
1768 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1769 ok(!ret, "WriteFile unexpectedly succeeded\n");
1770 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1772 CloseHandle(hpipe);
1774 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1775 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1776 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1777 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1779 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1780 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1782 numbytes = 0xdeadbeef;
1783 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1784 ok(ret, "WriteFile failed with %u\n", GetLastError());
1785 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1787 ret = CloseHandle(hfile);
1788 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1790 numbytes = 0xdeadbeef;
1791 memset(buffer, 0, sizeof(buffer));
1792 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1793 ok(ret, "ReadFile failed with %u\n", GetLastError());
1794 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1796 SetLastError(0xdeadbeef);
1797 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1798 ok(!ret, "ReadFile unexpectedly succeeded\n");
1799 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1801 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1802 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1803 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1804 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1805 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1807 SetLastError(0xdeadbeef);
1808 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1809 ok(!ret, "ReadFile unexpectedly succeeded\n");
1810 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1812 SetLastError(0xdeadbeef);
1813 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1814 ok(!ret, "WriteFile unexpectedly succeeded\n");
1815 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1817 CloseHandle(hpipe);
1820 struct named_pipe_client_params
1822 DWORD security_flags;
1823 HANDLE token;
1824 BOOL revert;
1827 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1829 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1831 struct named_pipe_client_params *params = p;
1832 HANDLE pipe;
1833 BOOL ret;
1834 const char message[] = "Test";
1835 DWORD bytes_read, bytes_written;
1836 char dummy;
1837 TOKEN_PRIVILEGES *Privileges = NULL;
1839 if (params->token)
1841 if (params->revert)
1843 /* modify the token so we can tell if the pipe impersonation
1844 * token reverts to the process token */
1845 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1846 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1848 ret = SetThreadToken(NULL, params->token);
1849 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1851 else
1853 DWORD Size = 0;
1854 HANDLE process_token;
1856 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1857 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1859 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1860 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1861 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1862 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1863 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1865 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1866 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1868 CloseHandle(process_token);
1871 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1872 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1874 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1875 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1877 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1878 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1880 if (params->token)
1882 if (params->revert)
1884 ret = RevertToSelf();
1885 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1887 else
1889 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1890 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1893 else
1895 HANDLE process_token;
1897 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1898 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1900 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1901 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1903 HeapFree(GetProcessHeap(), 0, Privileges);
1905 CloseHandle(process_token);
1908 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1909 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1911 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1912 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1914 CloseHandle(pipe);
1916 return 0;
1919 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1921 HANDLE ProcessToken;
1922 HANDLE Token = NULL;
1923 BOOL ret;
1925 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1926 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1928 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1929 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1931 CloseHandle(ProcessToken);
1933 return Token;
1936 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1938 HANDLE hPipeServer;
1939 BOOL ret;
1940 DWORD dwTid;
1941 HANDLE hThread;
1942 char buffer[256];
1943 DWORD dwBytesRead;
1944 DWORD error;
1945 struct named_pipe_client_params params;
1946 char dummy = 0;
1947 DWORD dwBytesWritten;
1948 HANDLE hToken = NULL;
1949 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1950 DWORD size;
1952 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1953 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1955 params.security_flags = security_flags;
1956 params.token = hClientToken;
1957 params.revert = revert;
1958 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1959 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1961 SetLastError(0xdeadbeef);
1962 ret = ImpersonateNamedPipeClient(hPipeServer);
1963 error = GetLastError();
1964 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1965 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1967 ret = ConnectNamedPipe(hPipeServer, NULL);
1968 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1970 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1971 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1973 ret = ImpersonateNamedPipeClient(hPipeServer);
1974 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1976 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1977 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1979 (*test_func)(0, hToken);
1981 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1982 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1983 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1984 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1986 CloseHandle(hToken);
1988 RevertToSelf();
1990 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1991 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1993 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1994 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1996 ret = ImpersonateNamedPipeClient(hPipeServer);
1997 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1999 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
2000 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
2002 (*test_func)(1, hToken);
2004 CloseHandle(hToken);
2006 RevertToSelf();
2008 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
2009 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2011 WaitForSingleObject(hThread, INFINITE);
2013 ret = ImpersonateNamedPipeClient(hPipeServer);
2014 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
2016 RevertToSelf();
2018 CloseHandle(hThread);
2019 CloseHandle(hPipeServer);
2022 static BOOL are_all_privileges_disabled(HANDLE hToken)
2024 BOOL ret;
2025 TOKEN_PRIVILEGES *Privileges = NULL;
2026 DWORD Size = 0;
2027 BOOL all_privs_disabled = TRUE;
2028 DWORD i;
2030 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
2031 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2033 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
2034 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
2035 if (!ret)
2037 HeapFree(GetProcessHeap(), 0, Privileges);
2038 return FALSE;
2041 else
2042 return FALSE;
2044 for (i = 0; i < Privileges->PrivilegeCount; i++)
2046 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
2048 all_privs_disabled = FALSE;
2049 break;
2053 HeapFree(GetProcessHeap(), 0, Privileges);
2055 return all_privs_disabled;
2058 static DWORD get_privilege_count(HANDLE hToken)
2060 TOKEN_STATISTICS Statistics;
2061 DWORD Size = sizeof(Statistics);
2062 BOOL ret;
2064 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
2065 ok(ret, "GetTokenInformation(TokenStatistics)\n");
2066 if (!ret) return -1;
2068 return Statistics.PrivilegeCount;
2071 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
2073 DWORD priv_count;
2075 switch (call_index)
2077 case 0:
2078 priv_count = get_privilege_count(hToken);
2079 todo_wine
2080 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2081 break;
2082 case 1:
2083 priv_count = get_privilege_count(hToken);
2084 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2085 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2086 break;
2087 default:
2088 ok(0, "shouldn't happen\n");
2092 static void test_no_sqos(int call_index, HANDLE hToken)
2094 switch (call_index)
2096 case 0:
2097 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2098 break;
2099 case 1:
2100 todo_wine
2101 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2102 break;
2103 default:
2104 ok(0, "shouldn't happen\n");
2108 static void test_static_context(int call_index, HANDLE hToken)
2110 switch (call_index)
2112 case 0:
2113 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2114 break;
2115 case 1:
2116 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2117 break;
2118 default:
2119 ok(0, "shouldn't happen\n");
2123 static void test_dynamic_context(int call_index, HANDLE hToken)
2125 switch (call_index)
2127 case 0:
2128 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2129 break;
2130 case 1:
2131 todo_wine
2132 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2133 break;
2134 default:
2135 ok(0, "shouldn't happen\n");
2139 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2141 switch (call_index)
2143 case 0:
2144 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2145 break;
2146 case 1:
2147 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2148 break;
2149 default:
2150 ok(0, "shouldn't happen\n");
2154 static void test_no_sqos_revert(int call_index, HANDLE hToken)
2156 DWORD priv_count;
2157 switch (call_index)
2159 case 0:
2160 priv_count = get_privilege_count(hToken);
2161 todo_wine
2162 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2163 break;
2164 case 1:
2165 priv_count = get_privilege_count(hToken);
2166 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2167 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2168 break;
2169 default:
2170 ok(0, "shouldn't happen\n");
2174 static void test_static_context_revert(int call_index, HANDLE hToken)
2176 switch (call_index)
2178 case 0:
2179 todo_wine
2180 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2181 break;
2182 case 1:
2183 todo_wine
2184 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2185 break;
2186 default:
2187 ok(0, "shouldn't happen\n");
2191 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2193 switch (call_index)
2195 case 0:
2196 todo_wine
2197 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2198 break;
2199 case 1:
2200 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2201 break;
2202 default:
2203 ok(0, "shouldn't happen\n");
2207 static void test_impersonation(void)
2209 HANDLE hClientToken;
2210 HANDLE hProcessToken;
2211 BOOL ret;
2213 if( !pDuplicateTokenEx ) {
2214 skip("DuplicateTokenEx not found\n");
2215 return;
2218 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2219 if (!ret)
2221 skip("couldn't open process token, skipping impersonation tests\n");
2222 return;
2225 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2227 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2228 CloseHandle(hProcessToken);
2229 return;
2231 CloseHandle(hProcessToken);
2233 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2234 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2235 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2236 CloseHandle(hClientToken);
2237 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2238 test_ImpersonateNamedPipeClient(hClientToken,
2239 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2240 test_static_context);
2241 CloseHandle(hClientToken);
2242 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2243 test_ImpersonateNamedPipeClient(hClientToken,
2244 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2245 FALSE, test_dynamic_context);
2246 CloseHandle(hClientToken);
2247 test_ImpersonateNamedPipeClient(NULL,
2248 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2249 FALSE, test_dynamic_context_no_token);
2251 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2252 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2253 CloseHandle(hClientToken);
2254 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2255 test_ImpersonateNamedPipeClient(hClientToken,
2256 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2257 test_static_context_revert);
2258 CloseHandle(hClientToken);
2259 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2260 test_ImpersonateNamedPipeClient(hClientToken,
2261 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2262 TRUE, test_dynamic_context_revert);
2263 CloseHandle(hClientToken);
2266 struct overlapped_server_args
2268 HANDLE pipe_created;
2271 static DWORD CALLBACK overlapped_server(LPVOID arg)
2273 OVERLAPPED ol;
2274 HANDLE pipe;
2275 int ret, err;
2276 struct overlapped_server_args *a = arg;
2277 DWORD num;
2278 char buf[100];
2280 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2281 ok(pipe != NULL, "pipe NULL\n");
2283 ol.hEvent = CreateEventA(0, 1, 0, 0);
2284 ok(ol.hEvent != NULL, "event NULL\n");
2285 ret = ConnectNamedPipe(pipe, &ol);
2286 err = GetLastError();
2287 ok(ret == 0, "ret %d\n", ret);
2288 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2289 SetEvent(a->pipe_created);
2291 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2292 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2294 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2295 ok(ret == 1, "ret %d\n", ret);
2297 /* This should block */
2298 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2299 ok(ret == 1, "ret %d\n", ret);
2301 DisconnectNamedPipe(pipe);
2303 ret = ConnectNamedPipe(pipe, &ol);
2304 err = GetLastError();
2305 ok(ret == 0, "ret %d\n", ret);
2306 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2307 CancelIo(pipe);
2308 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2309 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2311 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2312 err = GetLastError();
2313 ok(ret == 0, "ret %d\n", ret);
2314 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2316 CloseHandle(ol.hEvent);
2317 CloseHandle(pipe);
2318 return 1;
2321 static void test_overlapped(void)
2323 DWORD tid, num;
2324 HANDLE thread, pipe;
2325 BOOL ret;
2326 struct overlapped_server_args args;
2328 args.pipe_created = CreateEventA(0, 1, 0, 0);
2329 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2331 WaitForSingleObject(args.pipe_created, INFINITE);
2332 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2333 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2335 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2336 Sleep(1);
2338 ret = WriteFile(pipe, "x", 1, &num, NULL);
2339 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2341 WaitForSingleObject(thread, INFINITE);
2342 CloseHandle(pipe);
2343 CloseHandle(args.pipe_created);
2344 CloseHandle(thread);
2347 static void test_overlapped_error(void)
2349 HANDLE pipe, file, event;
2350 DWORD err, numbytes;
2351 OVERLAPPED overlapped;
2352 BOOL ret;
2354 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2355 ok(event != NULL, "CreateEventA failed with %u\n", GetLastError());
2357 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2358 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2359 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2360 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2362 memset(&overlapped, 0, sizeof(overlapped));
2363 overlapped.hEvent = event;
2364 ret = ConnectNamedPipe(pipe, &overlapped);
2365 err = GetLastError();
2366 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2367 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", err);
2369 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2370 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2371 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2373 numbytes = 0xdeadbeef;
2374 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2375 ok(ret == TRUE, "GetOverlappedResult failed\n");
2376 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
2377 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", overlapped.Internal);
2379 CloseHandle(file);
2380 CloseHandle(pipe);
2382 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2383 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2384 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2385 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2387 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2388 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2389 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2391 memset(&overlapped, 0, sizeof(overlapped));
2392 overlapped.hEvent = event;
2393 ret = ConnectNamedPipe(pipe, &overlapped);
2394 err = GetLastError();
2395 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2396 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", err);
2397 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
2399 CloseHandle(file);
2400 CloseHandle(pipe);
2402 CloseHandle(event);
2405 static void test_NamedPipeHandleState(void)
2407 HANDLE server, client;
2408 BOOL ret;
2409 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2410 char userName[MAX_PATH];
2412 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2413 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2414 /* nMaxInstances */ 1,
2415 /* nOutBufSize */ 1024,
2416 /* nInBufSize */ 1024,
2417 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2418 /* lpSecurityAttrib */ NULL);
2419 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2420 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2421 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2422 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2424 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2425 if (ret)
2427 ok(state == 0, "unexpected state %08x\n", state);
2428 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2430 /* Some parameters have no meaning, and therefore can't be retrieved,
2431 * on a local pipe.
2433 SetLastError(0xdeadbeef);
2434 ret = GetNamedPipeHandleStateA(server, &state, &instances, &maxCollectionCount,
2435 &collectDataTimeout, userName, ARRAY_SIZE(userName));
2436 todo_wine
2437 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2438 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2439 /* A byte-mode pipe server can't be changed to message mode. */
2440 state = PIPE_READMODE_MESSAGE;
2441 SetLastError(0xdeadbeef);
2442 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2443 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2444 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2446 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2447 OPEN_EXISTING, 0, NULL);
2448 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2450 state = PIPE_READMODE_BYTE;
2451 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2452 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2453 /* A byte-mode pipe client can't be changed to message mode, either. */
2454 state = PIPE_READMODE_MESSAGE;
2455 SetLastError(0xdeadbeef);
2456 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2457 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2458 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2460 CloseHandle(client);
2461 CloseHandle(server);
2463 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2464 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2465 /* nMaxInstances */ 1,
2466 /* nOutBufSize */ 1024,
2467 /* nInBufSize */ 1024,
2468 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2469 /* lpSecurityAttrib */ NULL);
2470 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2471 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2472 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2473 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2475 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2476 if (ret)
2478 ok(state == 0, "unexpected state %08x\n", state);
2479 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2481 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2482 * changed to byte mode.
2484 state = PIPE_READMODE_BYTE;
2485 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2486 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2488 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2489 OPEN_EXISTING, 0, NULL);
2490 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2492 state = PIPE_READMODE_MESSAGE;
2493 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2494 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2495 /* A message-mode pipe client can also be changed to byte mode.
2497 state = PIPE_READMODE_BYTE;
2498 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2499 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2501 CloseHandle(client);
2502 CloseHandle(server);
2505 static void test_GetNamedPipeInfo(void)
2507 HANDLE server;
2509 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2510 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2511 /* nMaxInstances */ 1,
2512 /* nOutBufSize */ 1024,
2513 /* nInBufSize */ 1024,
2514 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2515 /* lpSecurityAttrib */ NULL);
2516 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2518 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2520 CloseHandle(server);
2522 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2523 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2524 /* nMaxInstances */ 3,
2525 /* nOutBufSize */ 1024,
2526 /* nInBufSize */ 1024,
2527 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2528 /* lpSecurityAttrib */ NULL);
2529 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2531 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2533 CloseHandle(server);
2535 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2536 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2537 /* nMaxInstances */ 1,
2538 /* nOutBufSize */ 0,
2539 /* nInBufSize */ 0,
2540 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2541 /* lpSecurityAttrib */ NULL);
2542 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2544 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2546 CloseHandle(server);
2548 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2549 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2550 /* nMaxInstances */ 1,
2551 /* nOutBufSize */ 0xf000,
2552 /* nInBufSize */ 0xf000,
2553 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2554 /* lpSecurityAttrib */ NULL);
2555 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2557 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2559 CloseHandle(server);
2562 static void test_readfileex_pending(void)
2564 HANDLE server, client, event;
2565 BOOL ret;
2566 DWORD err, wait, num_bytes;
2567 OVERLAPPED overlapped;
2568 char read_buf[1024];
2569 char write_buf[1024];
2570 const char test_string[] = "test";
2571 int i;
2573 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2574 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2575 /* nMaxInstances */ 1,
2576 /* nOutBufSize */ 1024,
2577 /* nInBufSize */ 1024,
2578 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2579 /* lpSecurityAttrib */ NULL);
2580 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2582 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2583 ok(event != NULL, "CreateEventA failed\n");
2585 memset(&overlapped, 0, sizeof(overlapped));
2586 overlapped.hEvent = event;
2588 ret = ConnectNamedPipe(server, &overlapped);
2589 err = GetLastError();
2590 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2591 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
2593 wait = WaitForSingleObject(event, 0);
2594 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2596 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2597 OPEN_EXISTING, 0, NULL);
2598 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2600 wait = WaitForSingleObject(event, 0);
2601 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2603 /* Start a read that can't complete immediately. */
2604 completion_called = 0;
2605 ResetEvent(event);
2606 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2607 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
2608 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2610 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2611 ok(ret == TRUE, "WriteFile failed\n");
2612 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
2614 ok(completion_called == 0, "completion routine called during WriteFile\n");
2616 wait = WaitForSingleObjectEx(event, 0, TRUE);
2617 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
2619 ok(completion_called == 1, "completion not called after writing pipe\n");
2620 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2621 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
2622 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2623 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2625 /* Make writes until the pipe is full and the write fails */
2626 memset(write_buf, 0xaa, sizeof(write_buf));
2627 for (i=0; i<256; i++)
2629 completion_called = 0;
2630 ResetEvent(event);
2631 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2632 err = GetLastError();
2634 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2636 wait = WaitForSingleObjectEx(event, 0, TRUE);
2638 if (wait == WAIT_TIMEOUT)
2639 /* write couldn't complete immediately, presumably the pipe is full */
2640 break;
2642 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2644 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2645 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2646 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2649 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2650 ok(completion_called == 0, "completion routine called but wait timed out\n");
2651 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2652 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2654 /* free up some space in the pipe */
2655 for (i=0; i<256; i++)
2657 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2658 ok(ret == TRUE, "ReadFile failed\n");
2660 ok(completion_called == 0, "completion routine called during ReadFile\n");
2662 wait = WaitForSingleObjectEx(event, 0, TRUE);
2663 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2664 "WaitForSingleObject returned %x\n", wait);
2665 if (wait != WAIT_TIMEOUT) break;
2668 ok(completion_called == 1, "completion routine not called\n");
2669 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2670 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2672 num_bytes = 0xdeadbeef;
2673 SetLastError(0xdeadbeef);
2674 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2675 ok(!ret, "ReadFile should fail\n");
2676 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
2677 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
2679 S(U(overlapped)).Offset = 0;
2680 S(U(overlapped)).OffsetHigh = 0;
2681 overlapped.Internal = -1;
2682 overlapped.InternalHigh = -1;
2683 overlapped.hEvent = event;
2684 num_bytes = 0xdeadbeef;
2685 SetLastError(0xdeadbeef);
2686 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2687 ok(!ret, "ReadFile should fail\n");
2688 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2689 ok(num_bytes == 0, "bytes %u\n", num_bytes);
2690 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
2691 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
2693 wait = WaitForSingleObject(event, 100);
2694 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2696 num_bytes = 0xdeadbeef;
2697 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2698 ok(ret, "WriteFile failed\n");
2699 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2701 wait = WaitForSingleObject(event, 100);
2702 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2704 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2705 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
2706 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
2708 /* read the pending byte and clear the pipe */
2709 num_bytes = 0xdeadbeef;
2710 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2711 ok(ret, "ReadFile failed\n");
2712 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2714 CloseHandle(client);
2715 CloseHandle(server);
2716 CloseHandle(event);
2719 #define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
2720 static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
2722 DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
2723 char buf[12000];
2724 FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
2725 IO_STATUS_BLOCK io;
2726 NTSTATUS status;
2727 BOOL r;
2729 r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
2730 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2731 ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2732 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2733 ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %d, expected %d\n",
2734 left, expected_message_length - expected_read);
2736 status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
2737 ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x\n", status);
2738 ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
2739 "io.Information = %lu\n", io.Information);
2740 ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %u, expected %u\n",
2741 peek_buf->ReadDataAvailable, expected_avail);
2742 ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %u, expected %u\n",
2743 peek_buf->MessageLength, expected_message_length);
2745 if (expected_read)
2747 r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
2748 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2749 ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2750 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2751 ok_(__FILE__,line)(left == expected_message_length-1, "left = %d, expected %d\n", left, expected_message_length-1);
2755 #define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
2756 static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
2758 DWORD read_bytes = 0xdeadbeef;
2759 OVERLAPPED overlapped;
2760 BOOL res;
2762 memset(&overlapped, 0, sizeof(overlapped));
2763 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2764 res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
2765 if (partial_read)
2766 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%u)\n", res, GetLastError());
2767 else
2768 ok_(__FILE__,line)(res, "ReadFile failed: %u\n", GetLastError());
2769 if(partial_read)
2770 ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2771 else
2772 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2774 read_bytes = 0xdeadbeef;
2775 res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
2776 if (partial_read)
2777 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
2778 "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2779 else
2780 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2781 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2782 CloseHandle(overlapped.hEvent);
2785 #define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
2786 static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
2788 DWORD read_bytes = 0xdeadbeef;
2789 BOOL res;
2791 memset(overlapped, 0, sizeof(*overlapped));
2792 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2793 res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
2794 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%u)\n", res, GetLastError());
2795 ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2797 _test_not_signaled(line, overlapped->hEvent);
2800 #define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
2801 static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
2803 DWORD written_bytes = 0xdeadbeef;
2804 OVERLAPPED overlapped;
2805 BOOL res;
2807 memset(&overlapped, 0, sizeof(overlapped));
2808 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2809 res = WriteFile(writer, buf, size, &written_bytes, &overlapped);
2810 ok_(__FILE__,line)(res, "WriteFile returned %x(%u)\n", res, GetLastError());
2811 ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %u\n", written_bytes);
2813 written_bytes = 0xdeadbeef;
2814 res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
2815 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2816 ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %u expected %u\n", written_bytes, size);
2818 CloseHandle(overlapped.hEvent);
2821 #define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
2822 static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
2824 DWORD written_bytes = 0xdeadbeef;
2825 BOOL res;
2827 memset(overlapped, 0, sizeof(*overlapped));
2828 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2829 res = WriteFile(writer, buf, size, &written_bytes, overlapped);
2830 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
2831 ok_(__FILE__,line)(!written_bytes, "written_bytes = %u\n", written_bytes);
2833 _test_not_signaled(line, overlapped->hEvent);
2836 #define test_flush_sync(a) _test_flush_sync(__LINE__,a)
2837 static void _test_flush_sync(unsigned line, HANDLE pipe)
2839 BOOL res;
2841 res = FlushFileBuffers(pipe);
2842 ok_(__FILE__,line)(res, "FlushFileBuffers failed: %u\n", GetLastError());
2845 static DWORD expected_flush_error;
2847 static DWORD CALLBACK flush_proc(HANDLE pipe)
2849 BOOL res;
2851 res = FlushFileBuffers(pipe);
2852 if (expected_flush_error == ERROR_SUCCESS)
2853 ok(res, "FlushFileBuffers failed: %u\n", GetLastError());
2854 else
2855 ok(!res && GetLastError() == expected_flush_error, "FlushFileBuffers failed: %u\n", GetLastError());
2856 return 0;
2859 #define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
2860 static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
2862 HANDLE thread;
2863 DWORD tid;
2865 expected_flush_error = error;
2866 thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
2867 ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %u\n", GetLastError());
2869 Sleep(50);
2870 _test_not_signaled(line, thread);
2871 return thread;
2874 #define test_flush_done(a) _test_flush_done(__LINE__,a)
2875 static void _test_flush_done(unsigned line, HANDLE thread)
2877 DWORD res = WaitForSingleObject(thread, 1000);
2878 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
2879 CloseHandle(thread);
2882 #define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
2883 static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
2885 DWORD result = 0xdeadbeef;
2886 BOOL res;
2888 _test_signaled(line, overlapped->hEvent);
2890 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2891 if (partial_read)
2892 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2893 else
2894 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2895 ok_(__FILE__,line)(result == expected_result, "read_bytes = %u, expected %u\n", result, expected_result);
2896 CloseHandle(overlapped->hEvent);
2899 #define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
2900 static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
2902 DWORD result;
2903 BOOL res;
2905 _test_signaled(line, overlapped->hEvent);
2907 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2908 ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%u), expected error %u\n",
2909 res, GetLastError(), error);
2910 ok_(__FILE__,line)(!result, "result = %u\n", result);
2911 CloseHandle(overlapped->hEvent);
2914 #define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
2915 static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
2917 BOOL res;
2919 res = pCancelIoEx(handle, overlapped);
2920 ok_(__FILE__,line)(res, "CancelIoEx failed: %u\n", GetLastError());
2922 _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
2925 static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
2927 OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
2928 char buf[10000], read_buf[10000];
2929 HANDLE flush_thread;
2931 memset(buf, 0xaa, sizeof(buf));
2933 /* test pending read with overlapped event */
2934 overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
2935 test_flush_sync(writer);
2936 test_peek_pipe(reader, 0, 0, 0);
2938 /* write more data than needed for read */
2939 overlapped_write_sync(writer, buf, 4000);
2940 test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
2941 test_peek_pipe(reader, 3000, 3000, msg_mode ? 3000 : 0);
2943 /* test pending write with overlapped event */
2944 overlapped_write_async(writer, buf, buf_size, &write_overlapped);
2945 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size), 3000 + buf_size, msg_mode ? 3000 : 0);
2947 /* write one more byte */
2948 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2949 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2950 test_not_signaled(write_overlapped.hEvent);
2951 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2952 msg_mode ? 3000 : 0);
2954 /* empty write will not block */
2955 overlapped_write_sync(writer, buf, 0);
2956 test_not_signaled(write_overlapped.hEvent);
2957 test_not_signaled(write_overlapped2.hEvent);
2958 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2959 msg_mode ? 3000 : 0);
2961 /* read remaining data from the first write */
2962 overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
2963 test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
2964 test_not_signaled(write_overlapped2.hEvent);
2965 test_not_signaled(flush_thread);
2966 test_peek_pipe(reader, buf_size + (msg_mode ? 0 : 1), buf_size + 1, msg_mode ? buf_size : 0);
2968 /* read one byte so that the next write fits the buffer */
2969 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2970 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2971 test_peek_pipe(reader, buf_size + (msg_mode ? -1 : 0), buf_size, msg_mode ? buf_size - 1 : 0);
2973 /* read the whole buffer */
2974 overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
2975 test_peek_pipe(reader, msg_read ? 1 : 0, msg_read ? 1 : 0, msg_read ? 1 : 0);
2977 if(msg_read)
2979 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
2980 test_peek_pipe(reader, 0, 0, 0);
2983 if(msg_mode)
2985 /* we still have an empty message in queue */
2986 overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
2987 test_peek_pipe(reader, 0, 0, 0);
2989 test_flush_done(flush_thread);
2991 /* pipe is empty, the next read will block */
2992 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
2993 overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
2995 /* write one byte */
2996 overlapped_write_sync(writer, buf, 1);
2997 test_overlapped_result(reader, &read_overlapped, 0, msg_read);
2998 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
2999 test_peek_pipe(reader, 0, 0, 0);
3001 /* write a message larger than buffer */
3002 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3003 test_peek_pipe(reader, buf_size + 2000, buf_size + 2000, msg_mode ? buf_size + 2000 : 0);
3005 /* read so that pending write is still larger than the buffer */
3006 overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
3007 test_not_signaled(write_overlapped.hEvent);
3008 test_peek_pipe(reader, buf_size + 1, buf_size + 1, msg_mode ? buf_size + 1 : 0);
3010 /* read one more byte */
3011 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
3012 test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
3013 test_peek_pipe(reader, buf_size, buf_size, msg_mode ? buf_size : 0);
3015 /* read remaining data */
3016 overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
3017 test_peek_pipe(reader, 0, 0, 0);
3019 /* simple pass of empty message */
3020 overlapped_write_sync(writer, buf, 0);
3021 test_peek_pipe(reader, 0, 0, 0);
3022 if(msg_mode)
3023 overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
3025 /* pipe is empty, the next read will block */
3026 test_flush_sync(writer);
3027 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
3028 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3030 /* 0 length write wakes one read in msg mode */
3031 overlapped_write_sync(writer, buf, 0);
3032 if(msg_mode)
3033 test_overlapped_result(reader, &read_overlapped, 0, FALSE);
3034 else
3035 test_not_signaled(read_overlapped.hEvent);
3036 test_not_signaled(read_overlapped2.hEvent);
3037 overlapped_write_sync(writer, buf, 1);
3038 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
3040 overlapped_write_sync(writer, buf, 20);
3041 test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
3042 overlapped_write_sync(writer, buf, 15);
3043 test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
3044 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3045 test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
3046 overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
3047 test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
3048 overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
3050 if(!pCancelIoEx) {
3051 win_skip("CancelIoEx not available\n");
3052 return;
3055 /* add one more pending read, then cancel the first one */
3056 overlapped_read_async(reader, read_buf, 1, &read_overlapped);
3057 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3058 cancel_overlapped(reader, &read_overlapped2);
3059 test_not_signaled(read_overlapped.hEvent);
3060 overlapped_write_sync(writer, buf, 1);
3061 test_overlapped_result(reader, &read_overlapped, 1, FALSE);
3063 /* make two async writes, cancel the first one and make sure that we read from the second one */
3064 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3065 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3066 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3067 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3068 cancel_overlapped(writer, &write_overlapped);
3069 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3070 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3071 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3072 test_peek_pipe(reader, 0, 0, 0);
3074 /* same as above, but partially read written data before canceling */
3075 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3076 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3077 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3078 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3079 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3080 test_not_signaled(write_overlapped.hEvent);
3081 cancel_overlapped(writer, &write_overlapped);
3082 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3083 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3084 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3085 test_peek_pipe(reader, 0, 0, 0);
3087 /* empty queue by canceling write and make sure that flush is signaled */
3088 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3089 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
3090 test_not_signaled(flush_thread);
3091 cancel_overlapped(writer, &write_overlapped);
3092 test_peek_pipe(reader, 0, 0, 0);
3093 test_flush_done(flush_thread);
3096 #define overlapped_transact(a,b,c,d,e,f) _overlapped_transact(__LINE__,a,b,c,d,e,f)
3097 static void _overlapped_transact(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3098 void *read_buf, DWORD read_size, OVERLAPPED *overlapped)
3100 BOOL res;
3102 memset(overlapped, 0, sizeof(*overlapped));
3103 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3104 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, overlapped);
3105 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING,
3106 "TransactNamedPipe returned: %x(%u)\n", res, GetLastError());
3109 #define overlapped_transact_failure(a,b,c,d,e,f) _overlapped_transact_failure(__LINE__,a,b,c,d,e,f)
3110 static void _overlapped_transact_failure(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3111 void *read_buf, DWORD read_size, DWORD expected_error)
3113 OVERLAPPED overlapped;
3114 BOOL res;
3116 memset(&overlapped, 0, sizeof(overlapped));
3117 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3118 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, &overlapped);
3119 ok_(__FILE__,line)(!res, "TransactNamedPipe succeeded\n");
3121 if (GetLastError() == ERROR_IO_PENDING) /* win8+ */
3123 _test_overlapped_failure(line, caller, &overlapped, expected_error);
3125 else
3127 ok_(__FILE__,line)(GetLastError() == expected_error,
3128 "TransactNamedPipe returned error %u, expected %u\n",
3129 GetLastError(), expected_error);
3130 CloseHandle(overlapped.hEvent);
3134 static void child_process_write_pipe(HANDLE pipe)
3136 OVERLAPPED overlapped;
3137 char buf[10000];
3139 memset(buf, 'x', sizeof(buf));
3140 overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
3142 /* sleep until parent process terminates this process */
3143 Sleep(INFINITE);
3146 static HANDLE create_writepipe_process(HANDLE pipe)
3148 STARTUPINFOA si = { sizeof(si) };
3149 PROCESS_INFORMATION info;
3150 char **argv, buf[MAX_PATH];
3151 BOOL res;
3153 winetest_get_mainargs(&argv);
3154 sprintf(buf, "\"%s\" pipe writepipe %lx", argv[0], (UINT_PTR)pipe);
3155 res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
3156 ok(res, "CreateProcess failed: %u\n", GetLastError());
3157 CloseHandle(info.hThread);
3159 return info.hProcess;
3162 static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
3164 SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
3165 DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
3166 OVERLAPPED overlapped;
3167 BOOL res;
3169 *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3170 PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3171 ok(*server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError());
3172 test_signaled(*server);
3174 memset(&overlapped, 0, sizeof(overlapped));
3175 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3176 res = ConnectNamedPipe(*server, &overlapped);
3177 ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
3178 test_not_signaled(*server);
3179 test_not_signaled(overlapped.hEvent);
3181 *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
3182 ok(*client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
3184 res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
3185 ok(res, "SetNamedPipeHandleState failed: %u\n", GetLastError());
3187 test_signaled(*client);
3188 test_not_signaled(*server);
3189 test_overlapped_result(*server, &overlapped, 0, FALSE);
3192 static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
3194 OVERLAPPED overlapped, overlapped2;
3195 HANDLE server, client, flush;
3196 DWORD read_bytes;
3197 HANDLE process;
3198 char buf[60000];
3199 BOOL res;
3201 DWORD create_flags =
3202 (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
3203 (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
3205 create_overlapped_pipe(create_flags, &client, &server);
3207 trace("testing %s, %s server->client writes...\n",
3208 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3209 test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
3210 trace("testing %s, %s client->server writes...\n",
3211 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3212 test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
3214 CloseHandle(client);
3215 CloseHandle(server);
3217 /* close client with pending writes */
3218 memset(buf, 0xaa, sizeof(buf));
3219 create_overlapped_pipe(create_flags, &client, &server);
3220 overlapped_write_async(server, buf, 7000, &overlapped);
3221 flush = test_flush_async(server, ERROR_BROKEN_PIPE);
3222 CloseHandle(client);
3223 test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
3224 test_flush_done(flush);
3225 CloseHandle(server);
3227 /* close server with pending writes */
3228 create_overlapped_pipe(create_flags, &client, &server);
3229 overlapped_write_async(client, buf, 7000, &overlapped);
3230 flush = test_flush_async(client, ERROR_BROKEN_PIPE);
3231 CloseHandle(server);
3232 test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
3233 test_flush_done(flush);
3234 CloseHandle(client);
3236 /* disconnect with pending writes */
3237 create_overlapped_pipe(create_flags, &client, &server);
3238 overlapped_write_async(client, buf, 7000, &overlapped);
3239 overlapped_write_async(server, buf, 7000, &overlapped2);
3240 flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
3241 res = DisconnectNamedPipe(server);
3242 ok(res, "DisconnectNamedPipe failed: %u\n", GetLastError());
3243 test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
3244 test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
3245 test_flush_done(flush);
3246 CloseHandle(server);
3247 CloseHandle(client);
3249 /* terminate process with pending write */
3250 create_overlapped_pipe(create_flags, &client, &server);
3251 process = create_writepipe_process(client);
3252 /* successfully read part of write that is pending in child process */
3253 res = ReadFile(server, buf, 10, &read_bytes, NULL);
3254 if(!msg_read_mode)
3255 ok(res, "ReadFile failed: %u\n", GetLastError());
3256 else
3257 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError());
3258 ok(read_bytes == 10, "read_bytes = %u\n", read_bytes);
3259 TerminateProcess(process, 0);
3260 wait_child_process(process);
3261 /* after terminating process, there is no pending write and pipe buffer is empty */
3262 overlapped_read_async(server, buf, 10, &overlapped);
3263 overlapped_write_sync(client, buf, 1);
3264 test_overlapped_result(server, &overlapped, 1, FALSE);
3265 CloseHandle(process);
3266 CloseHandle(server);
3267 CloseHandle(client);
3270 static void test_transact(HANDLE caller, HANDLE callee, DWORD write_buf_size, DWORD read_buf_size)
3272 OVERLAPPED overlapped, overlapped2, read_overlapped, write_overlapped;
3273 char buf[10000], read_buf[10000];
3275 memset(buf, 0xaa, sizeof(buf));
3277 /* simple transact call */
3278 overlapped_transact(caller, (BYTE*)"abc", 3, read_buf, 100, &overlapped);
3279 overlapped_write_sync(callee, (BYTE*)"test", 4);
3280 test_overlapped_result(caller, &overlapped, 4, FALSE);
3281 ok(!memcmp(read_buf, "test", 4), "unexpected read_buf\n");
3282 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3283 ok(!memcmp(read_buf, "abc", 3), "unexpected read_buf\n");
3285 /* transact fails if there is already data in read buffer */
3286 overlapped_write_sync(callee, buf, 1);
3287 overlapped_transact_failure(caller, buf, 2, read_buf, 1, ERROR_PIPE_BUSY);
3288 overlapped_read_sync(caller, read_buf, 1000, 1, FALSE);
3290 /* transact doesn't block on write */
3291 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3292 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3293 test_not_signaled(overlapped.hEvent);
3294 overlapped_write_sync(callee, buf, 1);
3295 test_overlapped_result(caller, &overlapped, 1, FALSE);
3296 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3297 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3298 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3300 /* transact with already pending read */
3301 overlapped_read_async(callee, read_buf, 10, &read_overlapped);
3302 overlapped_transact(caller, buf, 5, read_buf, 6, &overlapped);
3303 test_overlapped_result(callee, &read_overlapped, 5, FALSE);
3304 test_not_signaled(overlapped.hEvent);
3305 overlapped_write_sync(callee, buf, 10);
3306 test_overlapped_result(caller, &overlapped, 6, TRUE);
3307 overlapped_read_sync(caller, read_buf, sizeof(read_buf), 4, FALSE);
3309 /* 0-size messages */
3310 overlapped_transact(caller, buf, 5, read_buf, 0, &overlapped);
3311 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 5, FALSE);
3312 overlapped_write_sync(callee, buf, 0);
3313 test_overlapped_result(caller, &overlapped, 0, FALSE);
3315 overlapped_transact(caller, buf, 0, read_buf, 0, &overlapped);
3316 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 0, FALSE);
3317 test_not_signaled(overlapped.hEvent);
3318 overlapped_write_sync(callee, buf, 0);
3319 test_overlapped_result(caller, &overlapped, 0, FALSE);
3321 /* reply transact with another transact */
3322 overlapped_transact(caller, buf, 3, read_buf, 100, &overlapped);
3323 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3324 overlapped_transact(callee, buf, 4, read_buf, 100, &overlapped2);
3325 test_overlapped_result(caller, &overlapped, 4, FALSE);
3326 overlapped_write_sync(caller, buf, 1);
3327 test_overlapped_result(caller, &overlapped2, 1, FALSE);
3329 if (!pCancelIoEx) return;
3331 /* cancel keeps written data */
3332 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3333 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3334 test_not_signaled(overlapped.hEvent);
3335 cancel_overlapped(caller, &overlapped);
3336 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3337 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3338 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3341 static void test_TransactNamedPipe(void)
3343 HANDLE client, server;
3344 BYTE buf[10];
3346 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3347 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3348 CloseHandle(client);
3349 CloseHandle(server);
3351 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, &client, &server);
3352 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3353 CloseHandle(client);
3354 CloseHandle(server);
3356 trace("testing server->client transaction...\n");
3357 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3358 test_transact(server, client, 5000, 6000);
3359 CloseHandle(client);
3360 CloseHandle(server);
3362 trace("testing client->server transaction...\n");
3363 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3364 test_transact(client, server, 6000, 5000);
3365 CloseHandle(client);
3366 CloseHandle(server);
3369 static HANDLE create_overlapped_server( OVERLAPPED *overlapped )
3371 HANDLE pipe;
3372 BOOL ret;
3374 pipe = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT,
3375 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3376 ok(pipe != INVALID_HANDLE_VALUE, "got %u\n", GetLastError());
3377 ret = ConnectNamedPipe(pipe, overlapped);
3378 ok(!ret && GetLastError() == ERROR_IO_PENDING, "got %u\n", GetLastError());
3379 return pipe;
3382 static void child_process_check_pid(DWORD server_pid)
3384 DWORD current = GetProcessId(GetCurrentProcess());
3385 HANDLE pipe;
3386 ULONG pid;
3387 BOOL ret;
3389 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3390 ok(pipe != INVALID_HANDLE_VALUE, "got %u\n", GetLastError());
3392 pid = 0;
3393 ret = pGetNamedPipeClientProcessId(pipe, &pid);
3394 ok(ret, "got %u\n", GetLastError());
3395 ok(pid == current, "got %04x\n", pid);
3397 pid = 0;
3398 ret = pGetNamedPipeServerProcessId(pipe, &pid);
3399 ok(ret, "got %u\n", GetLastError());
3400 ok(pid == server_pid, "got %04x expected %04x\n", pid, server_pid);
3401 CloseHandle(pipe);
3404 static HANDLE create_check_id_process(const char *verb, DWORD id)
3406 STARTUPINFOA si = {sizeof(si)};
3407 PROCESS_INFORMATION info;
3408 char **argv, buf[MAX_PATH];
3409 BOOL ret;
3411 winetest_get_mainargs(&argv);
3412 sprintf(buf, "\"%s\" pipe %s %x", argv[0], verb, id);
3413 ret = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &info);
3414 ok(ret, "got %u\n", GetLastError());
3415 CloseHandle(info.hThread);
3416 return info.hProcess;
3419 static void test_namedpipe_process_id(void)
3421 HANDLE client, server, process;
3422 DWORD current = GetProcessId(GetCurrentProcess());
3423 OVERLAPPED overlapped;
3424 ULONG pid;
3425 BOOL ret;
3427 if (!pGetNamedPipeClientProcessId)
3429 win_skip("GetNamedPipeClientProcessId not available\n");
3430 return;
3433 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3435 SetLastError(0xdeadbeef);
3436 ret = pGetNamedPipeClientProcessId(server, NULL);
3437 ok(!ret, "success\n");
3438 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
3440 pid = 0;
3441 ret = pGetNamedPipeClientProcessId(server, &pid);
3442 ok(ret, "got %u\n", GetLastError());
3443 ok(pid == current, "got %04x expected %04x\n", pid, current);
3445 pid = 0;
3446 ret = pGetNamedPipeClientProcessId(client, &pid);
3447 ok(ret, "got %u\n", GetLastError());
3448 ok(pid == current, "got %04x expected %04x\n", pid, current);
3450 SetLastError(0xdeadbeef);
3451 ret = pGetNamedPipeServerProcessId(server, NULL);
3452 ok(!ret, "success\n");
3453 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
3455 pid = 0;
3456 ret = pGetNamedPipeServerProcessId(client, &pid);
3457 ok(ret, "got %u\n", GetLastError());
3458 ok(pid == current, "got %04x expected %04x\n", pid, current);
3460 pid = 0;
3461 ret = pGetNamedPipeServerProcessId(server, &pid);
3462 ok(ret, "got %u\n", GetLastError());
3463 ok(pid == current, "got %04x expected %04x\n", pid, current);
3465 /* closed client handle */
3466 CloseHandle(client);
3467 pid = 0;
3468 ret = pGetNamedPipeClientProcessId(server, &pid);
3469 ok(ret, "got %u\n", GetLastError());
3470 ok(pid == current, "got %04x expected %04x\n", pid, current);
3472 pid = 0;
3473 ret = pGetNamedPipeServerProcessId(server, &pid);
3474 ok(ret, "got %u\n", GetLastError());
3475 ok(pid == current, "got %04x expected %04x\n", pid, current);
3476 CloseHandle(server);
3478 /* disconnected server */
3479 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3480 DisconnectNamedPipe(server);
3482 SetLastError(0xdeadbeef);
3483 ret = pGetNamedPipeClientProcessId(server, &pid);
3484 todo_wine ok(!ret, "success\n");
3485 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %u\n", GetLastError());
3487 pid = 0;
3488 ret = pGetNamedPipeServerProcessId(server, &pid);
3489 ok(ret, "got %u\n", GetLastError());
3490 ok(pid == current, "got %04x expected %04x\n", pid, current);
3492 SetLastError(0xdeadbeef);
3493 ret = pGetNamedPipeClientProcessId(client, &pid);
3494 todo_wine ok(!ret, "success\n");
3495 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %u\n", GetLastError());
3497 SetLastError(0xdeadbeef);
3498 ret = pGetNamedPipeServerProcessId(client, &pid);
3499 todo_wine ok(!ret, "success\n");
3500 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %u\n", GetLastError());
3501 CloseHandle(client);
3502 CloseHandle(server);
3504 /* closed server handle */
3505 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3506 CloseHandle(server);
3508 pid = 0;
3509 ret = pGetNamedPipeClientProcessId(client, &pid);
3510 ok(ret, "got %u\n", GetLastError());
3511 ok(pid == current, "got %04x expected %04x\n", pid, current);
3513 pid = 0;
3514 ret = pGetNamedPipeServerProcessId(client, &pid);
3515 ok(ret, "got %u\n", GetLastError());
3516 ok(pid == current, "got %04x expected %04x\n", pid, current);
3517 CloseHandle(client);
3519 /* different process */
3520 memset(&overlapped, 0, sizeof(overlapped));
3521 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3522 server = create_overlapped_server( &overlapped );
3523 ok(server != INVALID_HANDLE_VALUE, "got %u\n", GetLastError());
3525 process = create_check_id_process("checkpid", GetProcessId(GetCurrentProcess()));
3526 wait_child_process(process);
3528 CloseHandle(overlapped.hEvent);
3529 CloseHandle(process);
3530 CloseHandle(server);
3533 static void child_process_check_session_id(DWORD server_id)
3535 DWORD current;
3536 HANDLE pipe;
3537 ULONG id;
3538 BOOL ret;
3540 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &current);
3542 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3543 ok(pipe != INVALID_HANDLE_VALUE, "got %u\n", GetLastError());
3545 id = 0;
3546 ret = pGetNamedPipeClientSessionId(pipe, &id);
3547 ok(ret, "got %u\n", GetLastError());
3548 ok(id == current, "got %04x\n", id);
3550 id = 0;
3551 ret = pGetNamedPipeServerSessionId(pipe, &id);
3552 ok(ret, "got %u\n", GetLastError());
3553 ok(id == server_id, "got %04x expected %04x\n", id, server_id);
3554 CloseHandle(pipe);
3557 static void test_namedpipe_session_id(void)
3559 HANDLE client, server, process;
3560 OVERLAPPED overlapped;
3561 DWORD current;
3562 ULONG id;
3563 BOOL ret;
3565 if (!pGetNamedPipeClientSessionId)
3567 win_skip("GetNamedPipeClientSessionId not available\n");
3568 return;
3571 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &current);
3573 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3575 if (0) /* crashes on recent Windows */
3577 SetLastError(0xdeadbeef);
3578 ret = pGetNamedPipeClientSessionId(server, NULL);
3579 ok(!ret, "success\n");
3582 id = 0;
3583 ret = pGetNamedPipeClientSessionId(server, &id);
3584 ok(ret, "got %u\n", GetLastError());
3585 ok(id == current, "got %u expected %u\n", id, current);
3587 id = 0;
3588 ret = pGetNamedPipeClientSessionId(client, &id);
3589 ok(ret, "got %u\n", GetLastError());
3590 ok(id == current, "got %u expected %u\n", id, current);
3592 SetLastError(0xdeadbeef);
3593 ret = pGetNamedPipeServerSessionId(server, NULL);
3594 ok(!ret, "success\n");
3595 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
3597 id = 0;
3598 ret = pGetNamedPipeServerSessionId(client, &id);
3599 ok(ret, "got %u\n", GetLastError());
3600 ok(id == current, "got %u expected %u\n", id, current);
3602 id = 0;
3603 ret = pGetNamedPipeServerSessionId(server, &id);
3604 ok(ret, "got %u\n", GetLastError());
3605 ok(id == current, "got %u expected %u\n", id, current);
3607 /* closed client handle */
3608 CloseHandle(client);
3610 id = 0;
3611 ret = pGetNamedPipeClientSessionId(server, &id);
3612 ok(ret, "got %u\n", GetLastError());
3613 ok(id == current, "got %04x expected %04x\n", id, current);
3615 id = 0;
3616 ret = pGetNamedPipeServerSessionId(server, &id);
3617 ok(ret, "got %u\n", GetLastError());
3618 ok(id == current, "got %04x expected %04x\n", id, current);
3619 CloseHandle(server);
3621 /* disconnected server */
3622 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3623 DisconnectNamedPipe(server);
3625 SetLastError(0xdeadbeef);
3626 ret = pGetNamedPipeClientSessionId(server, &id);
3627 todo_wine ok(!ret, "success\n");
3628 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %u\n", GetLastError());
3630 id = 0;
3631 ret = pGetNamedPipeServerSessionId(server, &id);
3632 ok(ret, "got %u\n", GetLastError());
3633 ok(id == current, "got %04x expected %04x\n", id, current);
3635 SetLastError(0xdeadbeef);
3636 ret = pGetNamedPipeClientSessionId(client, &id);
3637 todo_wine ok(!ret, "success\n");
3638 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %u\n", GetLastError());
3640 SetLastError(0xdeadbeef);
3641 ret = pGetNamedPipeServerSessionId(client, &id);
3642 todo_wine ok(!ret, "success\n");
3643 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %u\n", GetLastError());
3644 CloseHandle(client);
3645 CloseHandle(server);
3647 /* closed server handle */
3648 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3649 CloseHandle(server);
3651 id = 0;
3652 ret = pGetNamedPipeClientSessionId(client, &id);
3653 ok(ret, "got %u\n", GetLastError());
3654 ok(id == current, "got %04x expected %04x\n", id, current);
3656 id = 0;
3657 ret = pGetNamedPipeServerSessionId(client, &id);
3658 ok(ret, "got %u\n", GetLastError());
3659 ok(id == current, "got %04x expected %04x\n", id, current);
3660 CloseHandle(client);
3662 /* different process */
3663 memset(&overlapped, 0, sizeof(overlapped));
3664 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3665 server = create_overlapped_server( &overlapped );
3666 ok(server != INVALID_HANDLE_VALUE, "got %u\n", GetLastError());
3668 process = create_check_id_process("checksessionid", current);
3669 wait_child_process(process);
3671 CloseHandle(overlapped.hEvent);
3672 CloseHandle(process);
3673 CloseHandle(server);
3676 static void test_multiple_instances(void)
3678 HANDLE server[4], client;
3679 int i;
3680 BOOL ret;
3681 OVERLAPPED ov;
3683 if(!pCancelIoEx)
3685 win_skip("Skipping multiple instance tests on too old Windows\n");
3686 return;
3689 for (i = 0; i < ARRAY_SIZE(server); i++)
3691 server[i] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3692 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3693 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3694 ok(server[i] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3697 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3698 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3700 /* Show that this has connected to server[0] not any other one */
3702 memset(&ov, 0, sizeof(ov));
3703 ret = ConnectNamedPipe(server[2], &ov);
3704 ok(ret == FALSE, "got %d\n", ret);
3705 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3707 memset(&ov, 0, sizeof(ov));
3708 ret = ConnectNamedPipe(server[0], &ov);
3709 ok(ret == FALSE, "got %d\n", ret);
3710 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3712 CloseHandle(client);
3714 /* The next connected server is server[1], doesn't matter that server[2] has pending listeners */
3716 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3717 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3719 memset(&ov, 0, sizeof(ov));
3720 ret = ConnectNamedPipe(server[2], &ov);
3721 ok(ret == FALSE, "got %d\n", ret);
3722 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3724 memset(&ov, 0, sizeof(ov));
3725 ret = ConnectNamedPipe(server[1], &ov);
3726 ok(ret == FALSE, "got %d\n", ret);
3727 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3729 CloseHandle(client);
3731 /* server[2] is connected next */
3733 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3734 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3736 memset(&ov, 0, sizeof(ov));
3737 ret = ConnectNamedPipe(server[2], &ov);
3738 ok(ret == FALSE, "got %d\n", ret);
3739 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3741 CloseHandle(client);
3743 /* Disconnect in order server[0] and server[2] */
3745 DisconnectNamedPipe(server[0]);
3746 DisconnectNamedPipe(server[2]);
3748 /* Put into listening state server[2] and server[0] */
3750 memset(&ov, 0, sizeof(ov));
3751 ret = ConnectNamedPipe(server[2], &ov);
3752 ok(ret == FALSE, "got %d\n", ret);
3753 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3755 memset(&ov, 0, sizeof(ov));
3756 ret = ConnectNamedPipe(server[0], &ov);
3757 ok(ret == FALSE, "got %d\n", ret);
3758 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3760 /* server[3] is connected next */
3762 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3763 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3765 memset(&ov, 0, sizeof(ov));
3766 ret = ConnectNamedPipe(server[3], &ov);
3767 ok(ret == FALSE, "got %d\n", ret);
3768 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3770 CloseHandle(client);
3772 /* server[2], which stasted listening first, will be connected next */
3774 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3775 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3777 memset(&ov, 0, sizeof(ov));
3778 ret = ConnectNamedPipe(server[2], &ov);
3779 ok(ret == FALSE, "got %d\n", ret);
3780 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3782 memset(&ov, 0, sizeof(ov));
3783 ret = ConnectNamedPipe(server[0], &ov);
3784 ok(ret == FALSE, "got %d\n", ret);
3785 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3787 CloseHandle(client);
3789 /* Finally server[0] is connected */
3791 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3792 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3794 memset(&ov, 0, sizeof(ov));
3795 ret = ConnectNamedPipe(server[0], &ov);
3796 ok(ret == FALSE, "got %d\n", ret);
3797 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %d\n", GetLastError());
3799 CloseHandle(client);
3801 /* No more listening pipes available */
3802 DisconnectNamedPipe(server[0]);
3803 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3804 ok(client == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY, "got %p(%u)\n", client, GetLastError());
3806 for (i = 0; i < ARRAY_SIZE(server); i++)
3808 DisconnectNamedPipe(server[i]);
3809 CloseHandle(server[i]);
3813 static DWORD WINAPI wait_pipe_proc(void *arg)
3815 BOOL ret;
3816 ret = WaitNamedPipeA(PIPENAME, 1000);
3817 ok(ret, "WaitNamedPipe failed (%u)\n", GetLastError());
3818 return 0;
3821 static HANDLE async_wait_pipe(void)
3823 HANDLE thread;
3824 BOOL ret;
3826 thread = CreateThread(NULL, 0, wait_pipe_proc, NULL, 0, NULL);
3827 ok(thread != NULL, "CreateThread failed: %u\n", GetLastError());
3829 ret = WaitNamedPipeA(PIPENAME, 1);
3830 ok(!ret && GetLastError() == ERROR_SEM_TIMEOUT, "WaitNamedPipe failed %x(%u)\n", ret, GetLastError());
3832 return thread;
3835 static void test_wait_pipe(void)
3837 HANDLE server[2], client, wait;
3838 OVERLAPPED ov;
3839 DWORD res;
3840 BOOL ret;
3842 ret = WaitNamedPipeA(PIPENAME, 0);
3843 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "WaitNamedPipe failed %x(%u)\n", ret, GetLastError());
3845 server[0] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3846 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3847 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3848 ok(server[0] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3850 ret = WaitNamedPipeA(PIPENAME, 1);
3851 ok(ret, "WaitNamedPipe failed (%u)\n", GetLastError());
3853 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3854 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3856 /* Creating a new pipe server wakes waiters */
3857 wait = async_wait_pipe();
3858 server[1] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3859 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3860 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3861 ok(server[1] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3863 res = WaitForSingleObject(wait, 100);
3864 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
3866 CloseHandle(wait);
3867 CloseHandle(server[1]);
3869 CloseHandle(client);
3870 ret = DisconnectNamedPipe(server[0]);
3871 ok(ret, "DisconnectNamedPipe failed (%u)\n", GetLastError());
3873 /* Putting pipe server into waiting listening state wakes waiters */
3874 wait = async_wait_pipe();
3875 memset(&ov, 0, sizeof(ov));
3876 ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3877 ret = ConnectNamedPipe(server[0], &ov);
3878 ok(ret == FALSE, "got %d\n", ret);
3879 ok(GetLastError() == ERROR_IO_PENDING, "got %d\n", GetLastError());
3881 res = WaitForSingleObject(wait, 100);
3882 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
3883 CloseHandle(server[0]);
3885 res = WaitForSingleObject(ov.hEvent, 0);
3886 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
3887 CloseHandle(ov.hEvent);
3890 static void test_nowait(DWORD pipe_type)
3892 HANDLE piperead, pipewrite, file;
3893 OVERLAPPED ol, ol2;
3894 DWORD read, write;
3895 char readbuf[32768];
3896 static const char teststring[] = "bits";
3898 /* CreateNamedPipe with PIPE_NOWAIT, and read from empty pipe */
3899 piperead = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3900 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3901 /* nMaxInstances */ 1,
3902 /* nOutBufSize */ 512,
3903 /* nInBufSize */ 512,
3904 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3905 /* lpSecurityAttrib */ NULL);
3906 ok(piperead != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3907 pipewrite = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3908 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3909 memset(&ol, 0, sizeof(ol));
3910 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3911 SetLastError(0xdeadbeef);
3912 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol) == FALSE, "ReadFile should fail\n");
3913 ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError());
3914 if (GetLastError() == ERROR_IO_PENDING)
3915 CancelIo(piperead);
3917 /* test a small write/read */
3918 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, NULL), "WriteFile should succeed\n");
3919 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol), "ReadFile should succeed\n");
3920 ok(read == write, "read/write bytes should match\n");
3921 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
3922 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
3923 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
3926 /* create write side with PIPE_NOWAIT, read side PIPE_WAIT, and test writes */
3927 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3928 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3929 /* nMaxInstances */ 1,
3930 /* nOutBufSize */ 512,
3931 /* nInBufSize */ 512,
3932 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3933 /* lpSecurityAttrib */ NULL);
3934 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3935 piperead = CreateFileA(PIPENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
3936 ok(piperead != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3937 memset(&ol, 0, sizeof(ol));
3938 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3939 memset(&ol2, 0, sizeof(ol2));
3940 ol2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3942 /* write one byte larger than the buffer size, should fail */
3943 SetLastError(0xdeadbeef);
3944 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
3945 /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows
3946 * doesn't seem to do partial writes ('write == 0' always)
3948 ok(write < sizeof(readbuf), "WriteFile should fail to write the whole buffer\n");
3949 ok(write == 0, "WriteFile doesn't do partial writes here\n");
3950 if (GetLastError() == ERROR_IO_PENDING)
3951 CancelIo(piperead);
3953 /* overlapped read of 32768, non-blocking write of 512 */
3954 SetLastError(0xdeadbeef);
3955 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
3956 ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError());
3957 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, &ol), "WriteFile should succeed\n");
3958 ok(write == sizeof(teststring), "got %d\n", write);
3959 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
3960 ok(read == sizeof(teststring), "got %d\n", read);
3961 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
3962 CancelIo(piperead);
3964 /* overlapped read of 32768, non-blocking write of 513 */
3965 SetLastError(0xdeadbeef);
3966 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
3967 ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError());
3968 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
3969 ok(write == 513, "got %d, write should be %d\n", write, 513);
3970 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
3971 ok(read == 513, "got %d, read should be %d\n", read, 513);
3972 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
3973 CancelIo(piperead);
3975 /* overlapped read of 1 byte, non-blocking write of 513 bytes */
3976 SetLastError(0xdeadbeef);
3977 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
3978 ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError());
3979 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
3980 ok(write == 513, "got %d, write should be %d\n", write, 513);
3981 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
3982 ok(read == 1, "got %d, read should be %d\n", read, 1);
3983 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
3984 CancelIo(piperead);
3985 /* read the remaining 512 bytes */
3986 SetLastError(0xdeadbeef);
3987 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2), "ReadFile should succeed\n");
3988 ok(read == 512, "got %d, write should be %d\n", write, 512);
3989 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
3990 CancelIo(piperead);
3992 /* overlapped read of 1 byte, non-blocking write of 514 bytes */
3993 SetLastError(0xdeadbeef);
3994 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
3995 ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError());
3996 ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n");
3997 if (pipe_type == PIPE_TYPE_MESSAGE)
3999 todo_wine
4000 ok(write == 0, "got %d\n", write);
4001 todo_wine
4002 ok(!GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4003 todo_wine
4004 ok(GetLastError() == ERROR_IO_INCOMPLETE, "got %d should be ERROR_IO_PENDING\n", GetLastError());
4005 todo_wine
4006 ok(read == 0, "got %d, read should be %d\n", read, 1);
4008 else
4010 ok(write == 1, "got %d\n", write);
4011 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4012 ok(read == 1, "got %d, read should be %d\n", read, 1);
4014 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4015 CancelIo(piperead);
4017 /* write the exact buffer size, should succeed */
4018 SetLastError(0xdeadbeef);
4019 ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n");
4020 ok(write == 512, "WriteFile should write the whole buffer\n");
4021 if (GetLastError() == ERROR_IO_PENDING)
4022 CancelIo(piperead);
4024 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4025 ok(CloseHandle(ol2.hEvent), "CloseHandle for the event failed\n");
4026 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4027 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
4030 /* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */
4031 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
4032 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
4033 /* nMaxInstances */ 1,
4034 /* nOutBufSize */ 512,
4035 /* nInBufSize */ 512,
4036 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
4037 /* lpSecurityAttrib */ NULL);
4038 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
4039 memset(&ol, 0, sizeof(ol));
4040 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4041 SetLastError(0xdeadbeef);
4042 ok(ConnectNamedPipe(pipewrite, &ol) == FALSE, "ConnectNamedPipe should fail\n");
4043 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError());
4044 if (GetLastError() == ERROR_IO_PENDING)
4045 CancelIo(pipewrite);
4047 /* connect and disconnect, then test ConnectNamedPipe again */
4048 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
4049 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
4050 ok(CloseHandle(file), "CloseHandle failed\n");
4051 SetLastError(0xdeadbeef);
4052 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4053 ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError());
4054 if (GetLastError() == ERROR_IO_PENDING)
4055 CancelIo(pipewrite);
4057 /* call DisconnectNamedPipe and test ConnectNamedPipe again */
4058 ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n");
4059 SetLastError(0xdeadbeef);
4060 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4061 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError());
4062 if (GetLastError() == ERROR_IO_PENDING)
4063 CancelIo(pipewrite);
4064 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4065 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4068 static void test_GetOverlappedResultEx(void)
4070 HANDLE client, server;
4071 OVERLAPPED ovl;
4072 char buffer[8000];
4073 DWORD ret_size;
4074 BOOL ret;
4076 if (!pGetOverlappedResultEx)
4078 win_skip("GetOverlappedResultEx() is not available\n");
4079 return;
4082 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4084 overlapped_write_async(client, buffer, sizeof(buffer), &ovl);
4086 user_apc_ran = FALSE;
4087 QueueUserAPC(user_apc, GetCurrentThread(), 0);
4089 SetLastError(0xdeadbeef);
4090 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, FALSE);
4091 ok(!ret, "expected failure\n");
4092 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError());
4093 ok(!user_apc_ran, "APC should not have run\n");
4095 SetLastError(0xdeadbeef);
4096 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, TRUE);
4097 ok(!ret, "expected failure\n");
4098 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError());
4099 ok(!user_apc_ran, "APC should not have run\n");
4101 SetLastError(0xdeadbeef);
4102 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, FALSE);
4103 ok(!ret, "expected failure\n");
4104 ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError());
4105 ok(!user_apc_ran, "APC should not have run\n");
4107 SetLastError(0xdeadbeef);
4108 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, TRUE);
4109 ok(!ret, "expected failure\n");
4110 ok(GetLastError() == WAIT_IO_COMPLETION, "wrong error %u\n", GetLastError());
4111 ok(user_apc_ran, "APC should have run\n");
4113 CloseHandle(ovl.hEvent);
4115 CloseHandle(client);
4116 CloseHandle(server);
4119 static void child_process_exit_process_async(DWORD parent_pid, HANDLE parent_pipe)
4121 OVERLAPPED overlapped = {0};
4122 static char buffer[1];
4123 HANDLE parent, pipe;
4124 BOOL ret;
4126 parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, parent_pid);
4127 ok(!!parent, "got parent %p\n", parent);
4129 ret = DuplicateHandle(parent, parent_pipe, GetCurrentProcess(), &pipe, 0,
4130 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
4131 ok(ret, "got error %u\n", GetLastError());
4133 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4135 ret = ReadFile(pipe, buffer, sizeof(buffer), NULL, &overlapped);
4136 ok(!ret, "expected failure\n");
4137 ok(GetLastError() == ERROR_IO_PENDING, "got error %u\n", GetLastError());
4139 /* exit without closing the pipe handle */
4142 static void test_exit_process_async(void)
4144 HANDLE client, server, port;
4145 OVERLAPPED *overlapped;
4146 PROCESS_INFORMATION pi;
4147 STARTUPINFOA si = {0};
4148 char cmdline[300];
4149 ULONG_PTR key;
4150 char **argv;
4151 DWORD size;
4152 BOOL ret;
4154 winetest_get_mainargs(&argv);
4156 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4157 port = CreateIoCompletionPort(client, NULL, 123, 0);
4159 sprintf(cmdline, "%s pipe exit_process_async %x %p", argv[0], GetCurrentProcessId(), client);
4160 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
4161 ok(ret, "got error %u\n", GetLastError());
4162 ret = WaitForSingleObject(pi.hProcess, 1000);
4163 ok(!ret, "wait timed out\n");
4164 CloseHandle(pi.hThread);
4165 CloseHandle(pi.hProcess);
4167 key = 0xdeadbeef;
4168 size = 0xdeadbeef;
4169 ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped, 1000);
4170 ok(!ret, "expected failure\n");
4171 ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %u\n", GetLastError());
4172 ok(!size, "got size %u\n", size);
4173 ok(key == 123, "got key %Iu\n", key);
4175 CloseHandle(port);
4176 CloseHandle(server);
4179 START_TEST(pipe)
4181 char **argv;
4182 int argc;
4183 HMODULE hmod;
4185 hmod = GetModuleHandleA("advapi32.dll");
4186 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
4187 hmod = GetModuleHandleA("kernel32.dll");
4188 pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
4189 pGetNamedPipeClientProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeClientProcessId");
4190 pGetNamedPipeServerProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeServerProcessId");
4191 pGetNamedPipeClientSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeClientSessionId");
4192 pGetNamedPipeServerSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeServerSessionId");
4193 pGetOverlappedResultEx = (void *)GetProcAddress(hmod, "GetOverlappedResultEx");
4195 argc = winetest_get_mainargs(&argv);
4197 if (argc > 3)
4199 if (!strcmp(argv[2], "writepipe"))
4201 UINT_PTR handle;
4202 sscanf(argv[3], "%lx", &handle);
4203 child_process_write_pipe((HANDLE)handle);
4204 return;
4206 if (!strcmp(argv[2], "checkpid"))
4208 DWORD pid = GetProcessId(GetCurrentProcess());
4209 sscanf(argv[3], "%x", &pid);
4210 child_process_check_pid(pid);
4211 return;
4213 if (!strcmp(argv[2], "checksessionid"))
4215 DWORD id;
4216 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &id);
4217 sscanf(argv[3], "%x", &id);
4218 child_process_check_session_id(id);
4219 return;
4221 if (!strcmp(argv[2], "exit_process_async"))
4223 HANDLE handle;
4224 DWORD pid;
4225 sscanf(argv[3], "%x", &pid);
4226 sscanf(argv[4], "%p", &handle);
4227 child_process_exit_process_async(pid, handle);
4228 return;
4232 if (test_DisconnectNamedPipe())
4233 return;
4234 test_CreateNamedPipe_instances_must_match();
4235 test_NamedPipe_2();
4236 test_CreateNamedPipe(PIPE_TYPE_BYTE);
4237 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
4238 test_CreatePipe();
4239 test_ReadFile();
4240 test_CloseHandle();
4241 test_impersonation();
4242 test_overlapped();
4243 test_overlapped_error();
4244 test_NamedPipeHandleState();
4245 test_GetNamedPipeInfo();
4246 test_readfileex_pending();
4247 test_overlapped_transport(TRUE, FALSE);
4248 test_overlapped_transport(TRUE, TRUE);
4249 test_overlapped_transport(FALSE, FALSE);
4250 test_TransactNamedPipe();
4251 test_namedpipe_process_id();
4252 test_namedpipe_session_id();
4253 test_multiple_instances();
4254 test_wait_pipe();
4255 test_nowait(PIPE_TYPE_BYTE);
4256 test_nowait(PIPE_TYPE_MESSAGE);
4257 test_GetOverlappedResultEx();
4258 test_exit_process_async();