wow64: In wow64_NtSetInformationToken forward TokenIntegrityLevel.
[wine.git] / dlls / kernel32 / tests / pipe.c
blobaff65fe2864249825ef3ad6602c5e7f8e5375f18
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 *pCancelSynchronousIo)(HANDLE handle);
41 static BOOL (WINAPI *pGetNamedPipeClientProcessId)(HANDLE,ULONG*);
42 static BOOL (WINAPI *pGetNamedPipeServerProcessId)(HANDLE,ULONG*);
43 static BOOL (WINAPI *pGetNamedPipeClientSessionId)(HANDLE,ULONG*);
44 static BOOL (WINAPI *pGetNamedPipeServerSessionId)(HANDLE,ULONG*);
45 static BOOL (WINAPI *pGetOverlappedResultEx)(HANDLE,OVERLAPPED *,DWORD *,DWORD,BOOL);
47 static BOOL user_apc_ran;
48 static void CALLBACK user_apc(ULONG_PTR param)
50 user_apc_ran = TRUE;
54 enum rpcThreadOp
56 RPC_READFILE
59 struct rpcThreadArgs
61 ULONG_PTR returnValue;
62 DWORD lastError;
63 enum rpcThreadOp op;
64 ULONG_PTR args[5];
67 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
69 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
70 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
71 SetLastError( rpcargs->lastError );
73 switch (rpcargs->op)
75 case RPC_READFILE:
76 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
77 (LPVOID)rpcargs->args[1], /* buffer */
78 (DWORD)rpcargs->args[2], /* bytesToRead */
79 (LPDWORD)rpcargs->args[3], /* bytesRead */
80 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
81 break;
83 default:
84 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
85 rpcargs->returnValue = 0;
86 break;
89 rpcargs->lastError = GetLastError();
90 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
91 return 0;
94 /* Runs ReadFile(...) from a different thread */
95 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
97 struct rpcThreadArgs rpcargs;
98 HANDLE thread;
99 DWORD threadId, ret;
101 rpcargs.returnValue = 0;
102 rpcargs.lastError = GetLastError();
103 rpcargs.op = RPC_READFILE;
104 rpcargs.args[0] = (ULONG_PTR)hFile;
105 rpcargs.args[1] = (ULONG_PTR)buffer;
106 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
107 rpcargs.args[3] = (ULONG_PTR)bytesRead;
108 rpcargs.args[4] = (ULONG_PTR)overlapped;
110 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
111 ok(thread != NULL, "CreateThread failed. %ld\n", GetLastError());
112 ret = WaitForSingleObject(thread, INFINITE);
113 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %ld.\n", GetLastError());
114 CloseHandle(thread);
116 SetLastError(rpcargs.lastError);
117 return (BOOL)rpcargs.returnValue;
120 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
121 static void _test_not_signaled(unsigned line, HANDLE handle)
123 DWORD res = WaitForSingleObject(handle, 0);
124 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (%lu)\n", res, GetLastError());
127 #define test_signaled(h) _test_signaled(__LINE__,h)
128 static void _test_signaled(unsigned line, HANDLE handle)
130 DWORD res = WaitForSingleObject(handle, 0);
131 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
134 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
135 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)
137 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
138 BOOL res;
140 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
141 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
142 ok_(__FILE__,line)(flags == ex_flags, "flags = %lx, expected %lx\n", flags, ex_flags);
143 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %lx, expected %lu\n", out_buf_size, ex_out_buf_size);
144 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %lx, expected %lu\n", in_buf_size, ex_in_buf_size);
145 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %lx, expected %lu\n", max_instances, ex_max_instances);
148 #define test_file_access(a,b) _test_file_access(__LINE__,a,b)
149 static void _test_file_access(unsigned line, HANDLE handle, DWORD expected_access)
151 FILE_ACCESS_INFORMATION info;
152 IO_STATUS_BLOCK io;
153 NTSTATUS status;
155 memset(&info, 0x11, sizeof(info));
156 status = NtQueryInformationFile(handle, &io, &info, sizeof(info), FileAccessInformation);
157 ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
158 ok_(__FILE__,line)(info.AccessFlags == expected_access, "got access %08lx expected %08lx\n",
159 info.AccessFlags, expected_access);
162 static void test_CreateNamedPipe(int pipemode)
164 HANDLE hnp;
165 HANDLE hFile;
166 static const char obuf[] = "Bit Bucket";
167 static const char obuf2[] = "More bits";
168 char ibuf[32], *pbuf;
169 DWORD written;
170 DWORD readden;
171 DWORD avail;
172 DWORD left;
173 DWORD lpmode;
174 BOOL ret;
176 if (pipemode == PIPE_TYPE_BYTE)
177 trace("test_CreateNamedPipe starting in byte mode\n");
178 else
179 trace("test_CreateNamedPipe starting in message mode\n");
181 /* Wait for nonexistent pipe */
182 ret = WaitNamedPipeA(PIPENAME, 2000);
183 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
184 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
186 /* Bad parameter checks */
187 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
188 /* nMaxInstances */ 1,
189 /* nOutBufSize */ 1024,
190 /* nInBufSize */ 1024,
191 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
192 /* lpSecurityAttrib */ NULL);
193 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
194 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
196 if (pipemode == PIPE_TYPE_BYTE)
198 /* Bad parameter checks */
199 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
200 /* nMaxInstances */ 1,
201 /* nOutBufSize */ 1024,
202 /* nInBufSize */ 1024,
203 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
204 /* lpSecurityAttrib */ NULL);
205 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
206 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
209 hnp = CreateNamedPipeA(NULL,
210 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
211 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
212 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
213 "CreateNamedPipe should fail if name is NULL\n");
215 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
216 ok(hFile == INVALID_HANDLE_VALUE
217 && GetLastError() == ERROR_FILE_NOT_FOUND,
218 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
220 /* Functional checks */
222 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
223 /* nMaxInstances */ 1,
224 /* nOutBufSize */ 1024,
225 /* nInBufSize */ 1024,
226 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
227 /* lpSecurityAttrib */ NULL);
228 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
229 test_signaled(hnp);
231 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
232 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES
233 | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA);
235 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
236 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%lu)\n",
237 ret, GetLastError());
239 ret = WaitNamedPipeA(PIPENAME, 2000);
240 ok(ret, "WaitNamedPipe failed (%ld)\n", GetLastError());
242 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
243 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%ld)\n", GetLastError());
245 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
247 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %lu\n", GetLastError());
249 /* Test ConnectNamedPipe() in both directions */
250 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
251 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %lu\n", GetLastError());
252 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
253 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %lu\n", GetLastError());
255 /* don't try to do i/o if one side couldn't be opened, as it hangs */
256 if (hFile != INVALID_HANDLE_VALUE) {
257 HANDLE hFile2;
259 /* Make sure we can read and write a few bytes in both directions */
260 memset(ibuf, 0, sizeof(ibuf));
261 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
262 ok(written == sizeof(obuf), "write file len\n");
263 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
264 ok(readden == sizeof(obuf), "read got %ld bytes\n", readden);
265 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
267 memset(ibuf, 0, sizeof(ibuf));
268 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
269 ok(written == sizeof(obuf2), "write file len\n");
270 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
271 ok(readden == sizeof(obuf2), "read got %ld bytes\n", readden);
272 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
274 /* Now the same again, but with an additional call to PeekNamedPipe */
275 memset(ibuf, 0, sizeof(ibuf));
276 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
277 ok(written == sizeof(obuf), "write file len 1\n");
278 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
279 ok(avail == sizeof(obuf), "peek 1 got %ld bytes\n", avail);
280 if (pipemode == PIPE_TYPE_BYTE)
281 ok(left == 0, "peek 1 got %ld bytes left\n", left);
282 else
283 ok(left == sizeof(obuf), "peek 1 got %ld bytes left\n", left);
284 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
285 ok(readden == sizeof(obuf), "read 1 got %ld bytes\n", readden);
286 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
288 memset(ibuf, 0, sizeof(ibuf));
289 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
290 ok(written == sizeof(obuf2), "write file len 2\n");
291 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
292 ok(avail == sizeof(obuf2), "peek 2 got %ld bytes\n", avail);
293 if (pipemode == PIPE_TYPE_BYTE)
294 ok(left == 0, "peek 2 got %ld bytes left\n", left);
295 else
296 ok(left == sizeof(obuf2), "peek 2 got %ld bytes left\n", left);
297 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
298 ok(avail == sizeof(obuf2), "peek 2 got %ld bytes\n", avail);
299 if (pipemode == PIPE_TYPE_BYTE)
300 ok(left == 0, "peek 2 got %ld bytes left\n", left);
301 else
302 ok(left == sizeof(obuf2), "peek 2 got %ld bytes left\n", left);
303 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
304 ok(readden == sizeof(obuf2), "read 2 got %ld bytes\n", readden);
305 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
307 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
308 memset(ibuf, 0, sizeof(ibuf));
309 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
310 ok(written == sizeof(obuf2), "write file len\n");
311 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
312 ok(readden == 4, "peek got %ld bytes\n", readden);
313 ok(avail == sizeof(obuf2), "peek got %ld bytes available\n", avail);
314 if (pipemode == PIPE_TYPE_BYTE)
315 ok(left == -4, "peek got %ld bytes left\n", left);
316 else
317 ok(left == sizeof(obuf2)-4, "peek got %ld bytes left\n", left);
318 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
319 ok(readden == 4, "read got %ld bytes\n", readden);
320 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
321 ok(readden == sizeof(obuf2) - 4, "read got %ld bytes\n", readden);
322 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
324 memset(ibuf, 0, sizeof(ibuf));
325 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
326 ok(written == sizeof(obuf), "write file len\n");
327 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
328 ok(readden == 4, "peek got %ld bytes\n", readden);
329 ok(avail == sizeof(obuf), "peek got %ld bytes available\n", avail);
330 if (pipemode == PIPE_TYPE_BYTE)
332 ok(left == -4, "peek got %ld bytes left\n", left);
333 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
335 else
337 ok(left == sizeof(obuf)-4, "peek got %ld bytes left\n", left);
338 SetLastError(0xdeadbeef);
339 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
340 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
342 ok(readden == 4, "read got %ld bytes\n", readden);
343 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
344 ok(readden == sizeof(obuf) - 4, "read got %ld bytes\n", readden);
345 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
347 /* Similar to above, but use a read buffer size small enough to read in three parts */
348 memset(ibuf, 0, sizeof(ibuf));
349 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
350 ok(written == sizeof(obuf2), "write file len\n");
351 if (pipemode == PIPE_TYPE_BYTE)
353 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
354 ok(readden == 4, "read got %ld bytes\n", readden);
355 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
357 else
359 SetLastError(0xdeadbeef);
360 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
361 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
362 ok(readden == 4, "read got %ld bytes\n", readden);
363 SetLastError(0xdeadbeef);
364 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
365 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
367 ok(readden == 4, "read got %ld bytes\n", readden);
368 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
369 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes\n", readden);
370 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
372 /* Test reading of multiple writes */
373 memset(ibuf, 0, sizeof(ibuf));
374 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
375 ok(written == sizeof(obuf), "write file len 3a\n");
376 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
377 ok(written == sizeof(obuf2), "write file len 3b\n");
378 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
379 ok(readden == 4, "peek3 got %ld bytes\n", readden);
380 if (pipemode == PIPE_TYPE_BYTE)
381 ok(left == -4, "peek3 got %ld bytes left\n", left);
382 else
383 ok(left == sizeof(obuf)-4, "peek3 got %ld bytes left\n", left);
384 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
385 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
386 if (pipemode == PIPE_TYPE_BYTE) {
387 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes\n", readden);
388 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %ld bytes left\n", left);
390 else
392 ok(readden == sizeof(obuf), "peek3 got %ld bytes\n", readden);
393 ok(left == 0, "peek3 got %ld bytes left\n", left);
395 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
396 pbuf = ibuf;
397 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
398 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
399 pbuf += sizeof(obuf);
400 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
402 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
403 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %ld bytes\n", readden);
404 pbuf = ibuf;
405 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
406 pbuf += sizeof(obuf);
407 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
409 /* Multiple writes in the reverse direction */
410 memset(ibuf, 0, sizeof(ibuf));
411 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
412 ok(written == sizeof(obuf), "write file len 4a\n");
413 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
414 ok(written == sizeof(obuf2), "write file len 4b\n");
415 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
416 ok(readden == 4, "peek3 got %ld bytes\n", readden);
417 if (pipemode == PIPE_TYPE_BYTE)
418 ok(left == -4, "peek3 got %ld bytes left\n", left);
419 else
420 ok(left == sizeof(obuf)-4, "peek3 got %ld bytes left\n", left);
421 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
422 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
423 if (pipemode == PIPE_TYPE_BYTE) {
424 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes\n", readden);
425 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %ld bytes left\n", left);
427 else
429 ok(readden == sizeof(obuf), "peek4 got %ld bytes\n", readden);
430 ok(left == 0, "peek4 got %ld bytes left\n", left);
432 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes available\n", avail);
433 pbuf = ibuf;
434 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
435 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
436 pbuf += sizeof(obuf);
437 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
439 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
440 if (pipemode == PIPE_TYPE_BYTE) {
441 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %ld bytes\n", readden);
443 else {
444 ok(readden == sizeof(obuf), "read 4 got %ld bytes\n", readden);
446 pbuf = ibuf;
447 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
448 if (pipemode == PIPE_TYPE_BYTE) {
449 pbuf += sizeof(obuf);
450 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
453 /* Test reading of multiple writes after a mode change
454 (CreateFile always creates a byte mode pipe) */
455 lpmode = PIPE_READMODE_MESSAGE;
456 if (pipemode == PIPE_TYPE_BYTE) {
457 /* trying to change the client end of a byte pipe to message mode should fail */
458 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
460 else {
461 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
463 memset(ibuf, 0, sizeof(ibuf));
464 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
465 ok(written == sizeof(obuf), "write file len 3a\n");
466 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
467 ok(written == sizeof(obuf2), "write file len 3b\n");
468 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
469 ok(readden == sizeof(obuf), "peek5 got %ld bytes\n", readden);
470 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %ld bytes available\n", avail);
471 ok(left == 0, "peek5 got %ld bytes left\n", left);
472 pbuf = ibuf;
473 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
474 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
475 ok(readden == sizeof(obuf), "read 5 got %ld bytes\n", readden);
476 pbuf = ibuf;
477 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
478 if (readden <= sizeof(obuf))
479 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
481 /* Multiple writes in the reverse direction */
482 /* the write of obuf2 from write4 should still be in the buffer */
483 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
484 ok(readden == sizeof(obuf2), "peek6a got %ld bytes\n", readden);
485 ok(avail == sizeof(obuf2), "peek6a got %ld bytes available\n", avail);
486 if (avail > 0) {
487 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
488 ok(readden == sizeof(obuf2), "read 6a got %ld bytes\n", readden);
489 pbuf = ibuf;
490 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
492 memset(ibuf, 0, sizeof(ibuf));
493 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
494 ok(written == sizeof(obuf), "write file len 6a\n");
495 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
496 ok(written == sizeof(obuf2), "write file len 6b\n");
497 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
498 ok(readden == sizeof(obuf), "peek6 got %ld bytes\n", readden);
500 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %ld bytes available\n", avail);
501 pbuf = ibuf;
502 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
503 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
504 ok(readden == sizeof(obuf), "read 6b got %ld bytes\n", readden);
505 pbuf = ibuf;
506 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
507 if (readden <= sizeof(obuf))
508 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
510 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
511 memset(ibuf, 0, sizeof(ibuf));
512 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
513 ok(written == sizeof(obuf2), "write file len 7\n");
514 SetLastError(0xdeadbeef);
515 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
516 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
517 ok(readden == 4, "read got %ld bytes 7\n", readden);
518 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
519 ok(readden == sizeof(obuf2) - 4, "read got %ld bytes 7\n", readden);
520 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
522 memset(ibuf, 0, sizeof(ibuf));
523 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
524 ok(written == sizeof(obuf), "write file len 8\n");
525 SetLastError(0xdeadbeef);
526 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
527 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
528 ok(readden == 4, "read got %ld bytes 8\n", readden);
529 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
530 ok(readden == sizeof(obuf) - 4, "read got %ld bytes 8\n", readden);
531 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
533 /* The following test shows that when doing a partial read of a message, the rest
534 * is still in the pipe, and can be received from a second thread. This shows
535 * especially that the content is _not_ stored in thread-local-storage until it is
536 * completely transmitted. The same method works even across multiple processes. */
537 memset(ibuf, 0, sizeof(ibuf));
538 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
539 ok(written == sizeof(obuf), "write file len 9\n");
540 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
541 ok(written == sizeof(obuf2), "write file len 9\n");
542 SetLastError(0xdeadbeef);
543 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
544 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
545 ok(readden == 4, "read got %ld bytes 9\n", readden);
546 SetLastError(0xdeadbeef);
547 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
548 ok(!ret, "RpcReadFile 9\n");
549 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
550 ok(readden == 4, "read got %ld bytes 9\n", readden);
551 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
552 ok(ret, "RpcReadFile 9\n");
553 ok(readden == sizeof(obuf) - 8, "read got %ld bytes 9\n", readden);
554 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
555 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
557 memset(ibuf, 0, sizeof(ibuf));
558 SetLastError(0xdeadbeef);
559 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
560 ok(!ret, "RpcReadFile 9\n");
561 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
562 ok(readden == 4, "read got %ld bytes 9\n", readden);
563 SetLastError(0xdeadbeef);
564 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
565 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
566 ok(readden == 4, "read got %ld bytes 9\n", readden);
567 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
568 ok(ret, "RpcReadFile 9\n");
569 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes 9\n", readden);
570 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
573 /* Now the reverse direction */
574 memset(ibuf, 0, sizeof(ibuf));
575 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
576 ok(written == sizeof(obuf2), "write file len 10\n");
577 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
578 ok(written == sizeof(obuf), "write file len 10\n");
579 SetLastError(0xdeadbeef);
580 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
581 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
582 ok(readden == 4, "read got %ld bytes 10\n", readden);
583 SetLastError(0xdeadbeef);
584 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
585 ok(!ret, "RpcReadFile 10\n");
586 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
587 ok(readden == 4, "read got %ld bytes 10\n", readden);
588 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
589 ok(ret, "RpcReadFile 10\n");
590 ok(readden == sizeof(obuf2) - 8, "read got %ld bytes 10\n", readden);
591 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
592 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
594 memset(ibuf, 0, sizeof(ibuf));
595 SetLastError(0xdeadbeef);
596 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
597 ok(!ret, "RpcReadFile 10\n");
598 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
599 ok(readden == 4, "read got %ld bytes 10\n", readden);
600 SetLastError(0xdeadbeef);
601 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
602 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
603 ok(readden == 4, "read got %ld bytes 10\n", readden);
604 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
605 ok(ret, "RpcReadFile 10\n");
606 ok(readden == sizeof(obuf) - 8, "read got %ld bytes 10\n", readden);
607 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
612 /* Picky conformance tests */
614 /* Verify that you can't connect to pipe again
615 * until server calls DisconnectNamedPipe+ConnectNamedPipe
616 * or creates a new pipe
617 * case 1: other client not yet closed
619 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
620 ok(hFile2 == INVALID_HANDLE_VALUE,
621 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
622 ok(GetLastError() == ERROR_PIPE_BUSY,
623 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
625 ok(CloseHandle(hFile), "CloseHandle\n");
627 /* case 2: other client already closed */
628 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
629 ok(hFile == INVALID_HANDLE_VALUE,
630 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
631 ok(GetLastError() == ERROR_PIPE_BUSY,
632 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
634 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
636 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
637 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
638 ok(hFile == INVALID_HANDLE_VALUE,
639 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
640 ok(GetLastError() == ERROR_PIPE_BUSY,
641 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
643 /* to be complete, we'd call ConnectNamedPipe here and loop,
644 * but by default that's blocking, so we'd either have
645 * to turn on the uncommon nonblocking mode, or
646 * use another thread.
650 ok(CloseHandle(hnp), "CloseHandle\n");
652 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, pipemode | PIPE_WAIT,
653 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
654 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
655 test_signaled(hnp);
657 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES
658 | FILE_READ_DATA);
660 CloseHandle(hnp);
662 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_OUTBOUND, pipemode | PIPE_WAIT,
663 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
664 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
665 test_signaled(hnp);
667 test_file_access(hnp, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
668 | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA);
670 hFile = CreateFileA(PIPENAME, 0, 0, NULL, OPEN_EXISTING, 0, 0);
671 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
672 test_file_access(hFile, SYNCHRONIZE | FILE_READ_ATTRIBUTES);
673 CloseHandle(hFile);
675 CloseHandle(hnp);
677 hnp = CreateNamedPipeA("\\\\.\\pipe\\a<>*?|\"/b", PIPE_ACCESS_DUPLEX,
678 PIPE_TYPE_BYTE, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
679 ok(hnp != INVALID_HANDLE_VALUE, "failed to create pipe, error %lu\n", GetLastError());
680 hFile = CreateFileA("\\\\.\\pipe\\a<>*?|\"/b", 0, 0, NULL, OPEN_EXISTING, 0, 0);
681 ok(hFile != INVALID_HANDLE_VALUE, "failed to open pipe, error %lu\n", GetLastError());
682 CloseHandle(hFile);
683 CloseHandle(hnp);
685 hnp = CreateNamedPipeA("\\\\.\\pipe\\trailingslash\\", PIPE_ACCESS_DUPLEX,
686 PIPE_TYPE_BYTE, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
687 ok(hnp != INVALID_HANDLE_VALUE, "failed to create pipe, error %lu\n", GetLastError());
688 hFile = CreateFileA("\\\\.\\pipe\\trailingslash", 0, 0, NULL, OPEN_EXISTING, 0, 0);
689 ok(hFile == INVALID_HANDLE_VALUE, "expected opening pipe to fail\n");
690 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %lu\n", GetLastError());
691 hFile = CreateFileA("\\\\.\\pipe\\trailingslash\\", 0, 0, NULL, OPEN_EXISTING, 0, 0);
692 ok(hFile != INVALID_HANDLE_VALUE, "failed to open pipe, error %lu\n", GetLastError());
693 CloseHandle(hFile);
694 CloseHandle(hnp);
696 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
699 static void test_CreateNamedPipe_instances_must_match(void)
701 HANDLE hnp, hnp2;
703 /* Check no mismatch */
704 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
705 /* nMaxInstances */ 2,
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 */ 2,
714 /* nOutBufSize */ 1024,
715 /* nInBufSize */ 1024,
716 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
717 /* lpSecurityAttrib */ NULL);
718 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
720 ok(CloseHandle(hnp), "CloseHandle\n");
721 ok(CloseHandle(hnp2), "CloseHandle\n");
723 /* Check nMaxInstances */
724 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
725 /* nMaxInstances */ 1,
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_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
733 /* nMaxInstances */ 1,
734 /* nOutBufSize */ 1024,
735 /* nInBufSize */ 1024,
736 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
737 /* lpSecurityAttrib */ NULL);
738 ok(hnp2 == INVALID_HANDLE_VALUE
739 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
741 ok(CloseHandle(hnp), "CloseHandle\n");
743 /* Check PIPE_ACCESS_* */
744 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
745 /* nMaxInstances */ 2,
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_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
753 /* nMaxInstances */ 2,
754 /* nOutBufSize */ 1024,
755 /* nInBufSize */ 1024,
756 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
757 /* lpSecurityAttrib */ NULL);
758 ok(hnp2 == INVALID_HANDLE_VALUE
759 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
761 ok(CloseHandle(hnp), "CloseHandle\n");
763 /* check everything else */
764 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
765 /* nMaxInstances */ 4,
766 /* nOutBufSize */ 1024,
767 /* nInBufSize */ 1024,
768 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
769 /* lpSecurityAttrib */ NULL);
770 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
772 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
773 /* nMaxInstances */ 3,
774 /* nOutBufSize */ 102,
775 /* nInBufSize */ 24,
776 /* nDefaultWait */ 1234,
777 /* lpSecurityAttrib */ NULL);
778 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
780 ok(CloseHandle(hnp), "CloseHandle\n");
781 ok(CloseHandle(hnp2), "CloseHandle\n");
784 static void test_ReadFile(void)
786 HANDLE server, client;
787 OVERLAPPED overlapped;
788 DWORD size;
789 BOOL res;
791 static char buf[512];
793 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
794 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
795 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
796 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
798 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
799 OPEN_EXISTING, 0, 0);
800 ok(client != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
802 ok(WriteFile(client, buf, sizeof(buf), &size, NULL), "WriteFile\n");
804 res = ReadFile(server, buf, 1, &size, NULL);
805 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%lu)\n", res, GetLastError());
806 ok(size == 1, "size = %lu\n", size);
808 /* pass both overlapped and ret read */
809 memset(&overlapped, 0, sizeof(overlapped));
810 res = ReadFile(server, buf, 1, &size, &overlapped);
811 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned %x(%lu)\n", res, GetLastError());
812 ok(size == 0, "size = %lu\n", size);
813 ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "Internal = %Ix\n", overlapped.Internal);
814 ok(overlapped.InternalHigh == 1, "InternalHigh = %Ix\n", overlapped.InternalHigh);
816 DisconnectNamedPipe(server);
818 memset(&overlapped, 0, sizeof(overlapped));
819 overlapped.InternalHigh = 0xdeadbeef;
820 res = ReadFile(server, buf, 1, &size, &overlapped);
821 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%lu)\n", res, GetLastError());
822 ok(size == 0, "size = %lu\n", size);
823 ok(overlapped.Internal == STATUS_PENDING, "Internal = %Ix\n", overlapped.Internal);
824 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %Ix\n", overlapped.InternalHigh);
826 memset(&overlapped, 0, sizeof(overlapped));
827 overlapped.InternalHigh = 0xdeadbeef;
828 res = WriteFile(server, buf, 1, &size, &overlapped);
829 ok(!res && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "ReadFile returned %x(%lu)\n", res, GetLastError());
830 ok(size == 0, "size = %lu\n", size);
831 ok(overlapped.Internal == STATUS_PENDING, "Internal = %Ix\n", overlapped.Internal);
832 ok(overlapped.InternalHigh == 0xdeadbeef, "InternalHigh = %Ix\n", overlapped.InternalHigh);
834 CloseHandle(server);
835 CloseHandle(client);
838 /** implementation of alarm() */
839 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
841 DWORD_PTR timeout = (DWORD_PTR) arg;
842 if (winetest_debug > 1) trace("alarmThreadMain\n");
843 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
845 ok(FALSE, "alarm\n");
846 ExitProcess(1);
848 return 1;
851 static HANDLE hnp = INVALID_HANDLE_VALUE;
853 /** Trivial byte echo server - disconnects after each session */
854 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
856 int i;
858 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
859 /* Set up a simple echo server */
860 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
861 PIPE_TYPE_BYTE | PIPE_WAIT,
862 /* nMaxInstances */ 1,
863 /* nOutBufSize */ 1024,
864 /* nInBufSize */ 1024,
865 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
866 /* lpSecurityAttrib */ NULL);
868 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
869 for (i = 0; i < NB_SERVER_LOOPS; i++) {
870 char buf[512];
871 DWORD written;
872 DWORD readden;
873 BOOL success;
875 /* Wait for client to connect */
876 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
877 ok(ConnectNamedPipe(hnp, NULL)
878 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
879 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
881 /* Echo bytes once */
882 memset(buf, 0, sizeof(buf));
884 if (winetest_debug > 1) trace("Server reading...\n");
885 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
886 if (winetest_debug > 1) trace("Server done reading.\n");
887 ok(success, "ReadFile\n");
888 ok(readden, "short read\n");
890 if (winetest_debug > 1) trace("Server writing...\n");
891 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
892 if (winetest_debug > 1) trace("Server done writing.\n");
893 ok(written == readden, "write file len\n");
895 /* finish this connection, wait for next one */
896 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
897 if (winetest_debug > 1) trace("Server done flushing.\n");
898 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
899 if (winetest_debug > 1) trace("Server done disconnecting.\n");
901 return 0;
904 /** Trivial byte echo server - closes after each connection */
905 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
907 int i;
908 HANDLE hnpNext = 0;
910 trace("serverThreadMain2\n");
911 /* Set up a simple echo server */
912 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
913 PIPE_TYPE_BYTE | PIPE_WAIT,
914 /* nMaxInstances */ 2,
915 /* nOutBufSize */ 1024,
916 /* nInBufSize */ 1024,
917 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
918 /* lpSecurityAttrib */ NULL);
919 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
921 for (i = 0; i < NB_SERVER_LOOPS; i++) {
922 char buf[512];
923 DWORD written;
924 DWORD readden;
925 DWORD ret;
926 BOOL success;
929 user_apc_ran = FALSE;
930 if (i == 0)
932 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
933 ret = QueueUserAPC(&user_apc, GetCurrentThread(), 0);
934 ok(ret, "QueueUserAPC failed: %ld\n", GetLastError());
937 /* Wait for client to connect */
938 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
939 ok(ConnectNamedPipe(hnp, NULL)
940 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
941 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
943 /* Echo bytes once */
944 memset(buf, 0, sizeof(buf));
946 if (winetest_debug > 1) trace("Server reading...\n");
947 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
948 if (winetest_debug > 1) trace("Server done reading.\n");
949 ok(success, "ReadFile\n");
951 if (winetest_debug > 1) trace("Server writing...\n");
952 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
953 if (winetest_debug > 1) trace("Server done writing.\n");
954 ok(written == readden, "write file len\n");
956 /* finish this connection, wait for next one */
957 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
958 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
960 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
962 if (i == 0)
963 SleepEx(0, TRUE); /* get rid of apc */
965 /* Set up next echo server */
966 hnpNext =
967 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
968 PIPE_TYPE_BYTE | PIPE_WAIT,
969 /* nMaxInstances */ 2,
970 /* nOutBufSize */ 1024,
971 /* nInBufSize */ 1024,
972 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
973 /* lpSecurityAttrib */ NULL);
975 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
977 ok(CloseHandle(hnp), "CloseHandle\n");
978 hnp = hnpNext;
980 return 0;
983 /** Trivial byte echo server - uses overlapped named pipe calls */
984 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
986 int i;
987 HANDLE hEvent;
989 if (winetest_debug > 1) trace("serverThreadMain3\n");
990 /* Set up a simple echo server */
991 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
992 PIPE_TYPE_BYTE | PIPE_WAIT,
993 /* nMaxInstances */ 1,
994 /* nOutBufSize */ 1024,
995 /* nInBufSize */ 1024,
996 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
997 /* lpSecurityAttrib */ NULL);
998 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1000 hEvent = CreateEventW(NULL, /* security attribute */
1001 TRUE, /* manual reset event */
1002 FALSE, /* initial state */
1003 NULL); /* name */
1004 ok(hEvent != NULL, "CreateEvent\n");
1006 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1007 char buf[512];
1008 DWORD written;
1009 DWORD readden;
1010 DWORD dummy;
1011 BOOL success;
1012 OVERLAPPED oOverlap;
1013 int letWFSOEwait = (i & 2);
1014 int letGORwait = (i & 1);
1015 DWORD err;
1017 memset(&oOverlap, 0, sizeof(oOverlap));
1018 oOverlap.hEvent = hEvent;
1020 /* Wait for client to connect */
1021 if (i == 0) {
1022 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
1023 success = ConnectNamedPipe(hnp, NULL);
1024 err = GetLastError();
1025 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %ld\n", err);
1026 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1027 } else {
1028 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1029 success = ConnectNamedPipe(hnp, &oOverlap);
1030 err = GetLastError();
1031 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
1032 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
1033 if (!success && (err == ERROR_IO_PENDING)) {
1034 if (letWFSOEwait)
1036 DWORD ret;
1037 do {
1038 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1039 } while (ret == WAIT_IO_COMPLETION);
1040 ok(ret == 0, "wait ConnectNamedPipe returned %lx\n", ret);
1042 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
1043 if (!letGORwait && !letWFSOEwait && !success) {
1044 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1045 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
1048 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
1049 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1052 /* Echo bytes once */
1053 memset(buf, 0, sizeof(buf));
1055 if (winetest_debug > 1) trace("Server reading...\n");
1056 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
1057 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1058 err = GetLastError();
1059 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
1060 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
1061 if (!success && (err == ERROR_IO_PENDING)) {
1062 if (letWFSOEwait)
1064 DWORD ret;
1065 do {
1066 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1067 } while (ret == WAIT_IO_COMPLETION);
1068 ok(ret == 0, "wait ReadFile returned %lx\n", ret);
1070 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
1071 if (!letGORwait && !letWFSOEwait && !success) {
1072 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1073 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
1076 if (winetest_debug > 1) trace("Server done reading.\n");
1077 ok(success, "overlapped ReadFile\n");
1079 if (winetest_debug > 1) trace("Server writing...\n");
1080 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
1081 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1082 err = GetLastError();
1083 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
1084 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1085 if (!success && (err == ERROR_IO_PENDING)) {
1086 if (letWFSOEwait)
1088 DWORD ret;
1089 do {
1090 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1091 } while (ret == WAIT_IO_COMPLETION);
1092 ok(ret == 0, "wait WriteFile returned %lx\n", ret);
1094 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
1095 if (!letGORwait && !letWFSOEwait && !success) {
1096 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
1097 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
1100 if (winetest_debug > 1) trace("Server done writing.\n");
1101 ok(success, "overlapped WriteFile\n");
1102 ok(written == readden, "write file len\n");
1104 /* finish this connection, wait for next one */
1105 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1106 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1108 return 0;
1111 /** Trivial byte echo server - uses i/o completion ports */
1112 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
1114 int i;
1115 HANDLE hcompletion;
1116 BOOL ret;
1118 if (winetest_debug > 1) trace("serverThreadMain4\n");
1119 /* Set up a simple echo server */
1120 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1121 PIPE_TYPE_BYTE | PIPE_WAIT,
1122 /* nMaxInstances */ 1,
1123 /* nOutBufSize */ 1024,
1124 /* nInBufSize */ 1024,
1125 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1126 /* lpSecurityAttrib */ NULL);
1127 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1129 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1130 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%li\n", GetLastError());
1132 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1133 char buf[512];
1134 DWORD written;
1135 DWORD readden;
1136 DWORD dummy;
1137 BOOL success;
1138 OVERLAPPED oConnect;
1139 OVERLAPPED oRead;
1140 OVERLAPPED oWrite;
1141 OVERLAPPED *oResult;
1142 DWORD err;
1143 ULONG_PTR compkey;
1145 memset(&oConnect, 0, sizeof(oConnect));
1146 memset(&oRead, 0, sizeof(oRead));
1147 memset(&oWrite, 0, sizeof(oWrite));
1149 /* Wait for client to connect */
1150 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1151 success = ConnectNamedPipe(hnp, &oConnect);
1152 err = GetLastError();
1153 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1154 "overlapped ConnectNamedPipe got %u err %lu\n", success, err );
1155 if (!success && err == ERROR_IO_PENDING) {
1156 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1157 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1158 if (!success)
1160 ok( GetLastError() == WAIT_TIMEOUT,
1161 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %lu\n", GetLastError());
1162 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1164 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1165 if (success)
1167 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1168 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1171 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
1173 /* Echo bytes once */
1174 memset(buf, 0, sizeof(buf));
1176 if (winetest_debug > 1) trace("Server reading...\n");
1177 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1178 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1179 err = GetLastError();
1180 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%li\n", err);
1181 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1182 &oResult, 10000);
1183 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1184 if (success)
1186 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1187 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1189 if (winetest_debug > 1) trace("Server done reading.\n");
1191 if (winetest_debug > 1) trace("Server writing...\n");
1192 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1193 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1194 err = GetLastError();
1195 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%lu\n", err);
1196 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1197 &oResult, 10000);
1198 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%li\n", GetLastError());
1199 if (success)
1201 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1202 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1203 ok(written == readden, "write file len\n");
1205 if (winetest_debug > 1) trace("Server done writing.\n");
1207 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1209 /* Wait for the pipe to break. */
1210 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1212 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1213 SetLastError(ERROR_SUCCESS);
1214 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1215 err = GetLastError();
1216 ok(!success && err == ERROR_NO_DATA,
1217 "overlapped WriteFile on disconnected pipe returned %u, err=%li\n", success, err);
1219 /* No completion status is queued on immediate error. */
1220 SetLastError(ERROR_SUCCESS);
1221 oResult = (OVERLAPPED *)0xdeadbeef;
1222 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1223 &oResult, 0);
1224 err = GetLastError();
1225 ok(!success && err == WAIT_TIMEOUT && !oResult,
1226 "WriteFile GetQueuedCompletionStatus returned %u, err=%li, oResult %p\n",
1227 success, err, oResult);
1229 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1230 SetLastError(ERROR_SUCCESS);
1231 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1232 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1233 err = GetLastError();
1234 ok(!success && err == ERROR_BROKEN_PIPE,
1235 "overlapped ReadFile on disconnected pipe returned %u, err=%li\n", success, err);
1237 SetLastError(ERROR_SUCCESS);
1238 oResult = (OVERLAPPED *)0xdeadbeef;
1239 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1240 &oResult, 0);
1241 err = GetLastError();
1242 ok(!success && err == WAIT_TIMEOUT && !oResult,
1243 "ReadFile GetQueuedCompletionStatus returned %u, err=%li, oResult %p\n",
1244 success, err, oResult);
1246 /* finish this connection, wait for next one */
1247 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1248 success = DisconnectNamedPipe(hnp);
1249 ok(success, "DisconnectNamedPipe failed, err %lu\n", GetLastError());
1252 ret = CloseHandle(hnp);
1253 ok(ret, "CloseHandle named pipe failed, err=%li\n", GetLastError());
1254 ret = CloseHandle(hcompletion);
1255 ok(ret, "CloseHandle completion failed, err=%li\n", GetLastError());
1257 return 0;
1260 static int completion_called;
1261 static DWORD completion_errorcode;
1262 static DWORD completion_num_bytes;
1263 static LPOVERLAPPED completion_lpoverlapped;
1265 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1267 completion_called++;
1268 completion_errorcode = errorcode;
1269 completion_num_bytes = num_bytes;
1270 completion_lpoverlapped = lpoverlapped;
1271 SetEvent(lpoverlapped->hEvent);
1274 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1275 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1277 int i;
1278 HANDLE hEvent;
1280 if (winetest_debug > 1) trace("serverThreadMain5\n");
1281 /* Set up a simple echo server */
1282 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1283 PIPE_TYPE_BYTE | PIPE_WAIT,
1284 /* nMaxInstances */ 1,
1285 /* nOutBufSize */ 1024,
1286 /* nInBufSize */ 1024,
1287 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1288 /* lpSecurityAttrib */ NULL);
1289 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1291 hEvent = CreateEventW(NULL, /* security attribute */
1292 TRUE, /* manual reset event */
1293 FALSE, /* initial state */
1294 NULL); /* name */
1295 ok(hEvent != NULL, "CreateEvent\n");
1297 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1298 char buf[512];
1299 DWORD readden;
1300 BOOL success;
1301 OVERLAPPED oOverlap;
1302 DWORD err;
1304 memset(&oOverlap, 0, sizeof(oOverlap));
1305 oOverlap.hEvent = hEvent;
1307 /* Wait for client to connect */
1308 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1309 success = ConnectNamedPipe(hnp, NULL);
1310 err = GetLastError();
1311 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %ld\n", err);
1312 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1314 /* Echo bytes once */
1315 memset(buf, 0, sizeof(buf));
1317 if (winetest_debug > 1) trace("Server reading...\n");
1318 completion_called = 0;
1319 ResetEvent(hEvent);
1320 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1321 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1322 ok(success, "ReadFileEx failed, err=%li\n", GetLastError());
1323 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1324 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1325 if (success) {
1326 DWORD ret;
1327 do {
1328 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1329 } while (ret == WAIT_IO_COMPLETION);
1330 ok(ret == 0, "wait ReadFileEx returned %lx\n", ret);
1332 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1333 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %ld\n", completion_errorcode);
1334 ok(completion_num_bytes != 0, "read 0 bytes\n");
1335 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1336 readden = completion_num_bytes;
1337 if (winetest_debug > 1) trace("Server done reading.\n");
1339 if (winetest_debug > 1) trace("Server writing...\n");
1340 completion_called = 0;
1341 ResetEvent(hEvent);
1342 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1343 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1344 ok(success, "WriteFileEx failed, err=%li\n", GetLastError());
1345 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1346 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1347 if (success) {
1348 DWORD ret;
1349 do {
1350 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1351 } while (ret == WAIT_IO_COMPLETION);
1352 ok(ret == 0, "wait WriteFileEx returned %lx\n", ret);
1354 if (winetest_debug > 1) trace("Server done writing.\n");
1355 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1356 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %ld\n", completion_errorcode);
1357 ok(completion_num_bytes == readden, "read %li bytes wrote %li\n", readden, completion_num_bytes);
1358 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1360 /* finish this connection, wait for next one */
1361 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1362 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1364 return 0;
1367 static void exerciseServer(const char *pipename, HANDLE serverThread)
1369 int i;
1371 if (winetest_debug > 1) trace("exerciseServer starting\n");
1372 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1373 HANDLE hFile=INVALID_HANDLE_VALUE;
1374 static const char obuf[] = "Bit Bucket";
1375 char ibuf[32];
1376 DWORD written;
1377 DWORD readden;
1378 int loop;
1380 for (loop = 0; loop < 3; loop++) {
1381 DWORD err;
1382 if (winetest_debug > 1) trace("Client connecting...\n");
1383 /* Connect to the server */
1384 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1385 NULL, OPEN_EXISTING, 0, 0);
1386 if (hFile != INVALID_HANDLE_VALUE)
1387 break;
1388 err = GetLastError();
1389 if (loop == 0)
1390 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1391 else
1392 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1393 if (winetest_debug > 1) trace("connect failed, retrying\n");
1394 Sleep(200);
1396 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1398 /* Make sure it can echo */
1399 memset(ibuf, 0, sizeof(ibuf));
1400 if (winetest_debug > 1) trace("Client writing...\n");
1401 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1402 ok(written == sizeof(obuf), "write file len\n");
1403 if (winetest_debug > 1) trace("Client reading...\n");
1404 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1405 ok(readden == sizeof(obuf), "read file len\n");
1406 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1408 if (winetest_debug > 1) trace("Client closing...\n");
1409 ok(CloseHandle(hFile), "CloseHandle\n");
1412 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1413 CloseHandle(hnp);
1414 if (winetest_debug > 1) trace("exerciseServer returning\n");
1417 static void test_NamedPipe_2(void)
1419 HANDLE serverThread;
1420 DWORD serverThreadId;
1421 HANDLE alarmThread;
1422 DWORD alarmThreadId;
1424 trace("test_NamedPipe_2 starting\n");
1425 /* Set up a twenty second timeout */
1426 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1427 SetLastError(0xdeadbeef);
1428 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1429 ok(alarmThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1431 /* The servers we're about to exercise do try to clean up carefully,
1432 * but to reduce the chance of a test failure due to a pipe handle
1433 * leak in the test code, we'll use a different pipe name for each server.
1436 /* Try server #1 */
1437 SetLastError(0xdeadbeef);
1438 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1439 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1440 exerciseServer(PIPENAME "serverThreadMain1", serverThread);
1442 /* Try server #2 */
1443 SetLastError(0xdeadbeef);
1444 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1445 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1446 exerciseServer(PIPENAME "serverThreadMain2", serverThread);
1448 /* Try server #3 */
1449 SetLastError(0xdeadbeef);
1450 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1451 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1452 exerciseServer(PIPENAME "serverThreadMain3", serverThread);
1454 /* Try server #4 */
1455 SetLastError(0xdeadbeef);
1456 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1457 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1458 exerciseServer(PIPENAME "serverThreadMain4", serverThread);
1460 /* Try server #5 */
1461 SetLastError(0xdeadbeef);
1462 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1463 ok(serverThread != NULL, "CreateThread failed: %ld\n", GetLastError());
1464 exerciseServer(PIPENAME "serverThreadMain5", serverThread);
1466 ok(SetEvent( alarm_event ), "SetEvent\n");
1467 CloseHandle( alarm_event );
1468 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1471 static int test_DisconnectNamedPipe(void)
1473 HANDLE hnp;
1474 HANDLE hFile;
1475 static const char obuf[] = "Bit Bucket";
1476 char ibuf[32];
1477 DWORD written;
1478 DWORD readden;
1479 DWORD ret;
1481 SetLastError(0xdeadbeef);
1482 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1483 /* nMaxInstances */ 1,
1484 /* nOutBufSize */ 1024,
1485 /* nInBufSize */ 1024,
1486 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1487 /* lpSecurityAttrib */ NULL);
1488 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1489 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1491 win_skip("Named pipes are not implemented\n");
1492 return 1;
1495 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1496 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1497 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1498 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1500 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1501 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1503 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1504 if (hFile != INVALID_HANDLE_VALUE) {
1506 /* see what happens if server calls DisconnectNamedPipe
1507 * when there are bytes in the pipe
1510 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1511 ok(written == sizeof(obuf), "write file len\n");
1512 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1513 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1514 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1515 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1516 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1517 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL) == 0
1518 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1519 "ReadFile from disconnected pipe with bytes waiting\n");
1520 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1521 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1522 "ReadFile from disconnected pipe with bytes waiting\n");
1524 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1525 "DisconnectNamedPipe worked twice\n");
1526 ret = WaitForSingleObject(hFile, 0);
1527 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lX\n", ret);
1529 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1530 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %lx (%lu)\n",
1531 ret, GetLastError());
1532 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1533 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %lx (%lu)\n",
1534 ret, GetLastError());
1535 ok(CloseHandle(hFile), "CloseHandle\n");
1538 ok(CloseHandle(hnp), "CloseHandle\n");
1540 return 0;
1542 static void test_CreatePipe(void)
1544 SECURITY_ATTRIBUTES pipe_attr;
1545 HANDLE piperead, pipewrite;
1546 DWORD written;
1547 DWORD read;
1548 DWORD i, size;
1549 BYTE *buffer;
1550 char readbuf[32];
1552 user_apc_ran = FALSE;
1553 ok(QueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1555 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1556 pipe_attr.bInheritHandle = TRUE;
1557 pipe_attr.lpSecurityDescriptor = NULL;
1558 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1559 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1560 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1561 test_file_access(piperead, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1562 | FILE_READ_ATTRIBUTES | FILE_READ_PROPERTIES | FILE_READ_DATA);
1563 test_file_access(pipewrite, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES
1564 | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_APPEND_DATA
1565 | FILE_WRITE_DATA);
1567 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1568 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes\n", written);
1569 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1570 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes\n", read);
1571 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1572 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1574 /* Now write another chunk*/
1575 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1576 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1577 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes\n", written);
1578 /* and close the write end, read should still succeed*/
1579 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1580 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1581 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes\n", read);
1582 /* But now we need to get informed that the pipe is closed */
1583 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1584 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1586 /* Try bigger chunks */
1587 size = 32768;
1588 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1589 for (i = 0; i < size; i++) buffer[i] = i;
1590 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1591 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1592 ok(written == size, "Write to anonymous pipe wrote %ld bytes\n", written);
1593 /* and close the write end, read should still succeed*/
1594 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1595 memset( buffer, 0, size );
1596 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1597 ok(read == size, "Read from anonymous pipe got %ld bytes\n", read);
1598 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %lx\n", buffer[i], i );
1599 /* But now we need to get informed that the pipe is closed */
1600 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1601 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1602 HeapFree(GetProcessHeap(), 0, buffer);
1604 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1605 SleepEx(0, TRUE); /* get rid of apc */
1607 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1608 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1609 test_pipe_info(pipewrite, 0, 1, 1, 1);
1610 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1611 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1614 static void test_CloseHandle(void)
1616 static const char testdata[] = "Hello World";
1617 DWORD state, numbytes;
1618 HANDLE hpipe, hfile;
1619 char buffer[32];
1620 BOOL ret;
1622 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1623 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1624 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1625 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1627 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1628 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1630 numbytes = 0xdeadbeef;
1631 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1632 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1633 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1635 numbytes = 0xdeadbeef;
1636 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1637 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1638 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1640 ret = CloseHandle(hpipe);
1641 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1643 numbytes = 0xdeadbeef;
1644 memset(buffer, 0, sizeof(buffer));
1645 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1646 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1647 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1649 numbytes = 0xdeadbeef;
1650 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1651 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1652 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1654 numbytes = 0xdeadbeef;
1655 memset(buffer, 0, sizeof(buffer));
1656 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1657 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1658 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1660 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1661 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1662 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1663 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1664 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1666 SetLastError(0xdeadbeef);
1667 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1668 ok(!ret, "ReadFile unexpectedly succeeded\n");
1669 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1671 numbytes = 0xdeadbeef;
1672 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1673 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%lu)\n",
1674 ret, GetLastError());
1675 ok(numbytes == 0xdeadbeef, "numbytes = %lu\n", numbytes);
1677 SetLastError(0xdeadbeef);
1678 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1679 ok(!ret, "WriteFile unexpectedly succeeded\n");
1680 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1682 CloseHandle(hfile);
1684 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1685 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1686 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1687 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1689 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1690 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1692 numbytes = 0xdeadbeef;
1693 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1694 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1695 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1697 ret = CloseHandle(hpipe);
1698 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1700 numbytes = 0xdeadbeef;
1701 memset(buffer, 0, sizeof(buffer));
1702 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1703 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1704 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1706 SetLastError(0xdeadbeef);
1707 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1708 ok(!ret, "ReadFile unexpectedly succeeded\n");
1709 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1711 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1712 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1713 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1714 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1715 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1717 SetLastError(0xdeadbeef);
1718 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1719 ok(!ret, "ReadFile unexpectedly succeeded\n");
1720 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1722 SetLastError(0xdeadbeef);
1723 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1724 ok(!ret, "WriteFile unexpectedly succeeded\n");
1725 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1727 CloseHandle(hfile);
1729 /* repeat test with hpipe <-> hfile swapped */
1731 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1732 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1733 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1734 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1736 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1737 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1739 numbytes = 0xdeadbeef;
1740 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1741 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1742 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1744 numbytes = 0xdeadbeef;
1745 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1746 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1747 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1749 ret = CloseHandle(hfile);
1750 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1752 numbytes = 0xdeadbeef;
1753 memset(buffer, 0, sizeof(buffer));
1754 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1755 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1756 "ReadFile failed with %lu\n", GetLastError());
1757 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1759 numbytes = 0xdeadbeef;
1760 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1761 ok(ret, "PeekNamedPipe failed with %lu\n", GetLastError());
1762 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1764 numbytes = 0xdeadbeef;
1765 memset(buffer, 0, sizeof(buffer));
1766 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1767 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1768 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %lu\n", numbytes);
1770 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1771 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1772 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1773 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1774 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1776 SetLastError(0xdeadbeef);
1777 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1778 ok(!ret, "ReadFile unexpectedly succeeded\n");
1779 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1781 numbytes = 0xdeadbeef;
1782 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1783 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%lu)\n",
1784 ret, GetLastError());
1785 ok(numbytes == 0xdeadbeef, "numbytes = %lu\n", numbytes);
1787 SetLastError(0xdeadbeef);
1788 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1789 ok(!ret, "WriteFile unexpectedly succeeded\n");
1790 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1792 CloseHandle(hpipe);
1794 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1795 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1796 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1797 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
1799 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1800 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
1802 numbytes = 0xdeadbeef;
1803 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1804 ok(ret, "WriteFile failed with %lu\n", GetLastError());
1805 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1807 ret = CloseHandle(hfile);
1808 ok(ret, "CloseHandle failed with %lu\n", GetLastError());
1810 numbytes = 0xdeadbeef;
1811 memset(buffer, 0, sizeof(buffer));
1812 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1813 ok(ret, "ReadFile failed with %lu\n", GetLastError());
1814 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
1816 SetLastError(0xdeadbeef);
1817 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1818 ok(!ret, "ReadFile unexpectedly succeeded\n");
1819 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1821 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1822 ok(ret, "GetNamedPipeHandleState failed with %lu\n", GetLastError());
1823 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1824 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1825 ok(ret, "SetNamedPipeHandleState failed with %lu\n", GetLastError());
1827 SetLastError(0xdeadbeef);
1828 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1829 ok(!ret, "ReadFile unexpectedly succeeded\n");
1830 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %lu\n", GetLastError());
1832 SetLastError(0xdeadbeef);
1833 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1834 ok(!ret, "WriteFile unexpectedly succeeded\n");
1835 ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %lu\n", GetLastError());
1837 CloseHandle(hpipe);
1840 struct named_pipe_client_params
1842 DWORD security_flags;
1843 HANDLE token;
1844 BOOL revert;
1847 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1849 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1851 struct named_pipe_client_params *params = p;
1852 HANDLE pipe;
1853 BOOL ret;
1854 const char message[] = "Test";
1855 DWORD bytes_read, bytes_written;
1856 char dummy;
1857 TOKEN_PRIVILEGES *Privileges = NULL;
1859 if (params->token)
1861 if (params->revert)
1863 /* modify the token so we can tell if the pipe impersonation
1864 * token reverts to the process token */
1865 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1866 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1868 ret = SetThreadToken(NULL, params->token);
1869 ok(ret, "SetThreadToken failed with error %ld\n", GetLastError());
1871 else
1873 DWORD Size = 0;
1874 HANDLE process_token;
1876 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1877 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1879 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1880 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %ld\n", GetLastError());
1881 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1882 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1883 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %ld\n", GetLastError());
1885 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1886 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1888 CloseHandle(process_token);
1891 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1892 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %ld\n", GetLastError());
1894 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1895 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
1897 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1898 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1900 if (params->token)
1902 if (params->revert)
1904 ret = RevertToSelf();
1905 ok(ret, "RevertToSelf failed with error %ld\n", GetLastError());
1907 else
1909 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1910 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1913 else
1915 HANDLE process_token;
1917 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1918 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1920 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1921 ok(ret, "AdjustTokenPrivileges failed with error %ld\n", GetLastError());
1923 HeapFree(GetProcessHeap(), 0, Privileges);
1925 CloseHandle(process_token);
1928 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1929 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
1931 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1932 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1934 CloseHandle(pipe);
1936 return 0;
1939 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1941 HANDLE ProcessToken;
1942 HANDLE Token = NULL;
1943 BOOL ret;
1945 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1946 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1948 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1949 ok(ret, "DuplicateToken failed with error %ld\n", GetLastError());
1951 CloseHandle(ProcessToken);
1953 return Token;
1956 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1958 HANDLE hPipeServer;
1959 BOOL ret;
1960 DWORD dwTid;
1961 HANDLE hThread;
1962 char buffer[256];
1963 DWORD dwBytesRead;
1964 DWORD error;
1965 struct named_pipe_client_params params;
1966 char dummy = 0;
1967 DWORD dwBytesWritten;
1968 HANDLE hToken = NULL;
1969 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1970 DWORD size;
1972 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1973 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %ld\n", GetLastError());
1975 params.security_flags = security_flags;
1976 params.token = hClientToken;
1977 params.revert = revert;
1978 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1979 ok(hThread != NULL, "CreateThread failed with error %ld\n", GetLastError());
1981 SetLastError(0xdeadbeef);
1982 ret = ImpersonateNamedPipeClient(hPipeServer);
1983 error = GetLastError();
1984 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1985 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %ld\n", GetLastError());
1987 ret = ConnectNamedPipe(hPipeServer, NULL);
1988 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %ld\n", GetLastError());
1990 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1991 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
1993 ret = ImpersonateNamedPipeClient(hPipeServer);
1994 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
1996 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1997 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
1999 (*test_func)(0, hToken);
2001 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
2002 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
2003 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %ld\n", GetLastError());
2004 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
2006 CloseHandle(hToken);
2008 RevertToSelf();
2010 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
2011 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2013 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
2014 ok(ret, "ReadFile failed with error %ld\n", GetLastError());
2016 ret = ImpersonateNamedPipeClient(hPipeServer);
2017 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
2019 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
2020 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
2022 (*test_func)(1, hToken);
2024 CloseHandle(hToken);
2026 RevertToSelf();
2028 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
2029 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2031 WaitForSingleObject(hThread, INFINITE);
2033 ret = ImpersonateNamedPipeClient(hPipeServer);
2034 ok(ret, "ImpersonateNamedPipeClient failed with error %ld\n", GetLastError());
2036 RevertToSelf();
2038 CloseHandle(hThread);
2039 CloseHandle(hPipeServer);
2042 static BOOL are_all_privileges_disabled(HANDLE hToken)
2044 BOOL ret;
2045 TOKEN_PRIVILEGES *Privileges = NULL;
2046 DWORD Size = 0;
2047 BOOL all_privs_disabled = TRUE;
2048 DWORD i;
2050 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
2051 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2053 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
2054 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
2055 if (!ret)
2057 HeapFree(GetProcessHeap(), 0, Privileges);
2058 return FALSE;
2061 else
2062 return FALSE;
2064 for (i = 0; i < Privileges->PrivilegeCount; i++)
2066 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
2068 all_privs_disabled = FALSE;
2069 break;
2073 HeapFree(GetProcessHeap(), 0, Privileges);
2075 return all_privs_disabled;
2078 static DWORD get_privilege_count(HANDLE hToken)
2080 TOKEN_STATISTICS Statistics;
2081 DWORD Size = sizeof(Statistics);
2082 BOOL ret;
2084 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
2085 ok(ret, "GetTokenInformation(TokenStatistics)\n");
2086 if (!ret) return -1;
2088 return Statistics.PrivilegeCount;
2091 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
2093 DWORD priv_count;
2095 switch (call_index)
2097 case 0:
2098 priv_count = get_privilege_count(hToken);
2099 todo_wine
2100 ok(priv_count == 0, "privilege count should have been 0 instead of %ld\n", priv_count);
2101 break;
2102 case 1:
2103 priv_count = get_privilege_count(hToken);
2104 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2105 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2106 break;
2107 default:
2108 ok(0, "shouldn't happen\n");
2112 static void test_no_sqos(int call_index, HANDLE hToken)
2114 switch (call_index)
2116 case 0:
2117 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2118 break;
2119 case 1:
2120 todo_wine
2121 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2122 break;
2123 default:
2124 ok(0, "shouldn't happen\n");
2128 static void test_static_context(int call_index, HANDLE hToken)
2130 switch (call_index)
2132 case 0:
2133 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2134 break;
2135 case 1:
2136 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2137 break;
2138 default:
2139 ok(0, "shouldn't happen\n");
2143 static void test_dynamic_context(int call_index, HANDLE hToken)
2145 switch (call_index)
2147 case 0:
2148 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2149 break;
2150 case 1:
2151 todo_wine
2152 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2153 break;
2154 default:
2155 ok(0, "shouldn't happen\n");
2159 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2161 switch (call_index)
2163 case 0:
2164 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2165 break;
2166 case 1:
2167 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2168 break;
2169 default:
2170 ok(0, "shouldn't happen\n");
2174 static void test_no_sqos_revert(int call_index, HANDLE hToken)
2176 DWORD priv_count;
2177 switch (call_index)
2179 case 0:
2180 priv_count = get_privilege_count(hToken);
2181 todo_wine
2182 ok(priv_count == 0, "privilege count should have been 0 instead of %ld\n", priv_count);
2183 break;
2184 case 1:
2185 priv_count = get_privilege_count(hToken);
2186 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2187 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2188 break;
2189 default:
2190 ok(0, "shouldn't happen\n");
2194 static void test_static_context_revert(int call_index, HANDLE hToken)
2196 switch (call_index)
2198 case 0:
2199 todo_wine
2200 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2201 break;
2202 case 1:
2203 todo_wine
2204 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2205 break;
2206 default:
2207 ok(0, "shouldn't happen\n");
2211 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2213 switch (call_index)
2215 case 0:
2216 todo_wine
2217 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2218 break;
2219 case 1:
2220 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2221 break;
2222 default:
2223 ok(0, "shouldn't happen\n");
2227 static void test_impersonation(void)
2229 HANDLE hClientToken;
2230 HANDLE hProcessToken;
2231 BOOL ret;
2233 if( !pDuplicateTokenEx ) {
2234 skip("DuplicateTokenEx not found\n");
2235 return;
2238 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2239 if (!ret)
2241 skip("couldn't open process token, skipping impersonation tests\n");
2242 return;
2245 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2247 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2248 CloseHandle(hProcessToken);
2249 return;
2251 CloseHandle(hProcessToken);
2253 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2254 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2255 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2256 CloseHandle(hClientToken);
2257 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2258 test_ImpersonateNamedPipeClient(hClientToken,
2259 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2260 test_static_context);
2261 CloseHandle(hClientToken);
2262 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2263 test_ImpersonateNamedPipeClient(hClientToken,
2264 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2265 FALSE, test_dynamic_context);
2266 CloseHandle(hClientToken);
2267 test_ImpersonateNamedPipeClient(NULL,
2268 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2269 FALSE, test_dynamic_context_no_token);
2271 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2272 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2273 CloseHandle(hClientToken);
2274 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2275 test_ImpersonateNamedPipeClient(hClientToken,
2276 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2277 test_static_context_revert);
2278 CloseHandle(hClientToken);
2279 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2280 test_ImpersonateNamedPipeClient(hClientToken,
2281 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2282 TRUE, test_dynamic_context_revert);
2283 CloseHandle(hClientToken);
2286 struct overlapped_server_args
2288 HANDLE pipe_created;
2291 static DWORD CALLBACK overlapped_server(LPVOID arg)
2293 OVERLAPPED ol;
2294 HANDLE pipe;
2295 int ret, err;
2296 struct overlapped_server_args *a = arg;
2297 DWORD num;
2298 char buf[100];
2300 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2301 ok(pipe != NULL, "pipe NULL\n");
2303 ol.hEvent = CreateEventA(0, 1, 0, 0);
2304 ok(ol.hEvent != NULL, "event NULL\n");
2305 ret = ConnectNamedPipe(pipe, &ol);
2306 err = GetLastError();
2307 ok(ret == 0, "ret %d\n", ret);
2308 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2309 SetEvent(a->pipe_created);
2311 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2312 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2314 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2315 ok(ret == 1, "ret %d\n", ret);
2317 /* This should block */
2318 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2319 ok(ret == 1, "ret %d\n", ret);
2321 DisconnectNamedPipe(pipe);
2323 ret = ConnectNamedPipe(pipe, &ol);
2324 err = GetLastError();
2325 ok(ret == 0, "ret %d\n", ret);
2326 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2327 CancelIo(pipe);
2328 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2329 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2331 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2332 err = GetLastError();
2333 ok(ret == 0, "ret %d\n", ret);
2334 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2336 CloseHandle(ol.hEvent);
2337 CloseHandle(pipe);
2338 return 1;
2341 static void test_overlapped(void)
2343 DWORD tid, num;
2344 HANDLE thread, pipe;
2345 BOOL ret;
2346 struct overlapped_server_args args;
2348 args.pipe_created = CreateEventA(0, 1, 0, 0);
2349 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2351 WaitForSingleObject(args.pipe_created, INFINITE);
2352 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2353 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2355 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2356 Sleep(1);
2358 ret = WriteFile(pipe, "x", 1, &num, NULL);
2359 ok(ret, "WriteFile failed with error %ld\n", GetLastError());
2361 WaitForSingleObject(thread, INFINITE);
2362 CloseHandle(pipe);
2363 CloseHandle(args.pipe_created);
2364 CloseHandle(thread);
2367 static void test_overlapped_error(void)
2369 HANDLE pipe, file, event;
2370 DWORD err, numbytes;
2371 OVERLAPPED overlapped;
2372 BOOL ret;
2374 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2375 ok(event != NULL, "CreateEventA failed with %lu\n", GetLastError());
2377 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2378 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2379 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2380 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
2382 memset(&overlapped, 0, sizeof(overlapped));
2383 overlapped.hEvent = event;
2384 ret = ConnectNamedPipe(pipe, &overlapped);
2385 err = GetLastError();
2386 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2387 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %lu\n", err);
2389 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2390 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2391 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
2393 numbytes = 0xdeadbeef;
2394 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2395 ok(ret == TRUE, "GetOverlappedResult failed\n");
2396 ok(numbytes == 0, "expected 0, got %lu\n", numbytes);
2397 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08Ix\n", overlapped.Internal);
2399 CloseHandle(file);
2400 CloseHandle(pipe);
2402 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2403 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2404 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2405 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
2407 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2408 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2409 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %lu\n", GetLastError());
2411 memset(&overlapped, 0, sizeof(overlapped));
2412 overlapped.hEvent = event;
2413 ret = ConnectNamedPipe(pipe, &overlapped);
2414 err = GetLastError();
2415 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2416 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %lu\n", err);
2417 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08Ix\n", overlapped.Internal);
2419 CloseHandle(file);
2420 CloseHandle(pipe);
2422 CloseHandle(event);
2425 static void test_NamedPipeHandleState(void)
2427 HANDLE server, client;
2428 BOOL ret;
2429 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2430 char userName[MAX_PATH];
2432 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2433 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2434 /* nMaxInstances */ 1,
2435 /* nOutBufSize */ 1024,
2436 /* nInBufSize */ 1024,
2437 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2438 /* lpSecurityAttrib */ NULL);
2439 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2440 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2441 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2442 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2444 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2445 if (ret)
2447 ok(state == 0, "unexpected state %08lx\n", state);
2448 ok(instances == 1, "expected 1 instances, got %ld\n", instances);
2450 /* Some parameters have no meaning, and therefore can't be retrieved,
2451 * on a local pipe.
2453 SetLastError(0xdeadbeef);
2454 ret = GetNamedPipeHandleStateA(server, &state, &instances, &maxCollectionCount,
2455 &collectDataTimeout, userName, ARRAY_SIZE(userName));
2456 todo_wine
2457 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2458 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2459 /* A byte-mode pipe server can't be changed to message mode. */
2460 state = PIPE_READMODE_MESSAGE;
2461 SetLastError(0xdeadbeef);
2462 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2463 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2464 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2466 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2467 OPEN_EXISTING, 0, NULL);
2468 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2470 state = PIPE_READMODE_BYTE;
2471 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2472 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2473 /* A byte-mode pipe client can't be changed to message mode, either. */
2474 state = PIPE_READMODE_MESSAGE;
2475 SetLastError(0xdeadbeef);
2476 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2477 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2478 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
2480 CloseHandle(client);
2481 CloseHandle(server);
2483 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2484 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2485 /* nMaxInstances */ 1,
2486 /* nOutBufSize */ 1024,
2487 /* nInBufSize */ 1024,
2488 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2489 /* lpSecurityAttrib */ NULL);
2490 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2491 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2492 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2493 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2495 ok(ret, "GetNamedPipeHandleState failed: %ld\n", GetLastError());
2496 if (ret)
2498 ok(state == 0, "unexpected state %08lx\n", state);
2499 ok(instances == 1, "expected 1 instances, got %ld\n", instances);
2501 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2502 * changed to byte mode.
2504 state = PIPE_READMODE_BYTE;
2505 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2506 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2508 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2509 OPEN_EXISTING, 0, NULL);
2510 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2512 state = PIPE_READMODE_MESSAGE;
2513 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2514 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2515 /* A message-mode pipe client can also be changed to byte mode.
2517 state = PIPE_READMODE_BYTE;
2518 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2519 ok(ret, "SetNamedPipeHandleState failed: %ld\n", GetLastError());
2521 CloseHandle(client);
2522 CloseHandle(server);
2525 static void test_GetNamedPipeInfo(void)
2527 HANDLE server;
2529 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2530 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2531 /* nMaxInstances */ 1,
2532 /* nOutBufSize */ 1024,
2533 /* nInBufSize */ 1024,
2534 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2535 /* lpSecurityAttrib */ NULL);
2536 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2538 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2540 CloseHandle(server);
2542 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2543 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2544 /* nMaxInstances */ 3,
2545 /* nOutBufSize */ 1024,
2546 /* nInBufSize */ 1024,
2547 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2548 /* lpSecurityAttrib */ NULL);
2549 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2551 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2553 CloseHandle(server);
2555 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2556 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2557 /* nMaxInstances */ 1,
2558 /* nOutBufSize */ 0,
2559 /* nInBufSize */ 0,
2560 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2561 /* lpSecurityAttrib */ NULL);
2562 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2564 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2566 CloseHandle(server);
2568 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2569 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2570 /* nMaxInstances */ 1,
2571 /* nOutBufSize */ 0xf000,
2572 /* nInBufSize */ 0xf000,
2573 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2574 /* lpSecurityAttrib */ NULL);
2575 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2577 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2579 CloseHandle(server);
2582 static void test_readfileex_pending(void)
2584 HANDLE server, client, event;
2585 BOOL ret;
2586 DWORD err, wait, num_bytes;
2587 OVERLAPPED overlapped;
2588 char read_buf[1024];
2589 char write_buf[1024];
2590 const char test_string[] = "test";
2591 int i;
2593 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2594 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2595 /* nMaxInstances */ 1,
2596 /* nOutBufSize */ 1024,
2597 /* nInBufSize */ 1024,
2598 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2599 /* lpSecurityAttrib */ NULL);
2600 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2602 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2603 ok(event != NULL, "CreateEventA failed\n");
2605 memset(&overlapped, 0, sizeof(overlapped));
2606 overlapped.hEvent = event;
2608 ret = ConnectNamedPipe(server, &overlapped);
2609 err = GetLastError();
2610 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2611 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %li\n", err);
2613 wait = WaitForSingleObject(event, 0);
2614 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lx\n", wait);
2616 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2617 OPEN_EXISTING, 0, NULL);
2618 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2620 wait = WaitForSingleObject(event, 0);
2621 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2623 /* Start a read that can't complete immediately. */
2624 completion_called = 0;
2625 ResetEvent(event);
2626 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2627 ok(ret == TRUE, "ReadFileEx failed, err=%li\n", GetLastError());
2628 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2630 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2631 ok(ret == TRUE, "WriteFile failed\n");
2632 ok(num_bytes == strlen(test_string), "only %li bytes written\n", num_bytes);
2634 ok(completion_called == 0, "completion routine called during WriteFile\n");
2636 wait = WaitForSingleObjectEx(event, 0, TRUE);
2637 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %lx\n", wait);
2639 ok(completion_called == 1, "completion not called after writing pipe\n");
2640 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2641 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %ld bytes\n", completion_num_bytes);
2642 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2643 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2645 /* Make writes until the pipe is full and the write fails */
2646 memset(write_buf, 0xaa, sizeof(write_buf));
2647 for (i=0; i<256; i++)
2649 completion_called = 0;
2650 ResetEvent(event);
2651 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2652 err = GetLastError();
2654 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2656 wait = WaitForSingleObjectEx(event, 0, TRUE);
2658 if (wait == WAIT_TIMEOUT)
2659 /* write couldn't complete immediately, presumably the pipe is full */
2660 break;
2662 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2664 ok(ret == TRUE, "WriteFileEx failed, err=%li\n", err);
2665 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2666 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2669 ok(ret == TRUE, "WriteFileEx failed, err=%li\n", err);
2670 ok(completion_called == 0, "completion routine called but wait timed out\n");
2671 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2672 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2674 /* free up some space in the pipe */
2675 for (i=0; i<256; i++)
2677 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2678 ok(ret == TRUE, "ReadFile failed\n");
2680 ok(completion_called == 0, "completion routine called during ReadFile\n");
2682 wait = WaitForSingleObjectEx(event, 0, TRUE);
2683 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2684 "WaitForSingleObject returned %lx\n", wait);
2685 if (wait != WAIT_TIMEOUT) break;
2688 ok(completion_called == 1, "completion routine not called\n");
2689 ok(completion_errorcode == 0, "completion called with error %lx\n", completion_errorcode);
2690 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2692 num_bytes = 0xdeadbeef;
2693 SetLastError(0xdeadbeef);
2694 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2695 ok(!ret, "ReadFile should fail\n");
2696 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError());
2697 ok(num_bytes == 0, "expected 0, got %lu\n", num_bytes);
2699 overlapped.Offset = 0;
2700 overlapped.OffsetHigh = 0;
2701 overlapped.Internal = -1;
2702 overlapped.InternalHigh = -1;
2703 overlapped.hEvent = event;
2704 num_bytes = 0xdeadbeef;
2705 SetLastError(0xdeadbeef);
2706 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2707 ok(!ret, "ReadFile should fail\n");
2708 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %ld\n", GetLastError());
2709 ok(num_bytes == 0, "bytes %lu\n", num_bytes);
2710 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#Ix\n", overlapped.Internal);
2711 ok(overlapped.InternalHigh == -1, "expected -1, got %Iu\n", overlapped.InternalHigh);
2713 wait = WaitForSingleObject(event, 100);
2714 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lx\n", wait);
2716 num_bytes = 0xdeadbeef;
2717 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2718 ok(ret, "WriteFile failed\n");
2719 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2721 wait = WaitForSingleObject(event, 100);
2722 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
2724 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2725 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#Ix\n", overlapped.Internal);
2726 ok(overlapped.InternalHigh == 0, "expected 0, got %Iu\n", overlapped.InternalHigh);
2728 /* read the pending byte and clear the pipe */
2729 num_bytes = 0xdeadbeef;
2730 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2731 ok(ret, "ReadFile failed\n");
2732 ok(num_bytes == 1, "bytes %lu\n", num_bytes);
2734 CloseHandle(client);
2735 CloseHandle(server);
2736 CloseHandle(event);
2739 #define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
2740 static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
2742 DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
2743 char buf[12000];
2744 FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
2745 IO_STATUS_BLOCK io;
2746 NTSTATUS status;
2747 BOOL r;
2749 r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
2750 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %lu\n", GetLastError());
2751 ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %lu, expected %lu\n", bytes_read, expected_read);
2752 ok_(__FILE__,line)(avail == expected_avail, "avail = %lu, expected %lu\n", avail, expected_avail);
2753 ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %ld, expected %ld\n",
2754 left, expected_message_length - expected_read);
2756 status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
2757 ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %lx\n", status);
2758 ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
2759 "io.Information = %Iu\n", io.Information);
2760 ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %lu, expected %lu\n",
2761 peek_buf->ReadDataAvailable, expected_avail);
2762 ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %lu, expected %lu\n",
2763 peek_buf->MessageLength, expected_message_length);
2765 if (expected_read)
2767 r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
2768 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %lu\n", GetLastError());
2769 ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %lu, expected %lu\n", bytes_read, expected_read);
2770 ok_(__FILE__,line)(avail == expected_avail, "avail = %lu, expected %lu\n", avail, expected_avail);
2771 ok_(__FILE__,line)(left == expected_message_length-1, "left = %ld, expected %ld\n", left, expected_message_length-1);
2775 #define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
2776 static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
2778 DWORD read_bytes = 0xdeadbeef;
2779 OVERLAPPED overlapped;
2780 BOOL res;
2782 memset(&overlapped, 0, sizeof(overlapped));
2783 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2784 res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
2785 if (partial_read)
2786 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%lu)\n", res, GetLastError());
2787 else
2788 ok_(__FILE__,line)(res, "ReadFile failed: %lu\n", GetLastError());
2789 if(partial_read)
2790 ok_(__FILE__,line)(!read_bytes, "read_bytes %lu expected 0\n", read_bytes);
2791 else
2792 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %lu expected %lu\n", read_bytes, expected_result);
2794 read_bytes = 0xdeadbeef;
2795 res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
2796 if (partial_read)
2797 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
2798 "GetOverlappedResult returned: %x (%lu)\n", res, GetLastError());
2799 else
2800 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2801 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %lu expected %lu\n", read_bytes, expected_result);
2802 CloseHandle(overlapped.hEvent);
2805 #define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
2806 static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
2808 DWORD read_bytes = 0xdeadbeef;
2809 BOOL res;
2811 memset(overlapped, 0, sizeof(*overlapped));
2812 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2813 res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
2814 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%lu)\n", res, GetLastError());
2815 ok_(__FILE__,line)(!read_bytes, "read_bytes %lu expected 0\n", read_bytes);
2817 _test_not_signaled(line, overlapped->hEvent);
2820 #define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
2821 static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
2823 DWORD written_bytes = 0xdeadbeef;
2824 OVERLAPPED overlapped;
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, "WriteFile returned %x(%lu)\n", res, GetLastError());
2831 ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %lu\n", written_bytes);
2833 written_bytes = 0xdeadbeef;
2834 res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
2835 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2836 ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %lu expected %lu\n", written_bytes, size);
2838 CloseHandle(overlapped.hEvent);
2841 #define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
2842 static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
2844 DWORD written_bytes = 0xdeadbeef;
2845 BOOL res;
2847 memset(overlapped, 0, sizeof(*overlapped));
2848 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2849 res = WriteFile(writer, buf, size, &written_bytes, overlapped);
2850 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%lu)\n", res, GetLastError());
2851 ok_(__FILE__,line)(!written_bytes, "written_bytes = %lu\n", written_bytes);
2853 _test_not_signaled(line, overlapped->hEvent);
2856 #define test_flush_sync(a) _test_flush_sync(__LINE__,a)
2857 static void _test_flush_sync(unsigned line, HANDLE pipe)
2859 BOOL res;
2861 res = FlushFileBuffers(pipe);
2862 ok_(__FILE__,line)(res, "FlushFileBuffers failed: %lu\n", GetLastError());
2865 static DWORD expected_flush_error;
2867 static DWORD CALLBACK flush_proc(HANDLE pipe)
2869 BOOL res;
2871 res = FlushFileBuffers(pipe);
2872 if (expected_flush_error == ERROR_SUCCESS)
2874 ok(res, "FlushFileBuffers failed: %lu\n", GetLastError());
2876 else
2878 ok(!res, "FlushFileBuffers should have failed\n");
2879 ok(GetLastError() == expected_flush_error,
2880 "FlushFileBuffers set error %lu, expected %lu\n", GetLastError(), expected_flush_error);
2882 return 0;
2885 #define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
2886 static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
2888 HANDLE thread;
2889 DWORD tid;
2891 expected_flush_error = error;
2892 thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
2893 ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %lu\n", GetLastError());
2895 Sleep(50);
2896 _test_not_signaled(line, thread);
2897 return thread;
2900 #define test_flush_done(a) _test_flush_done(__LINE__,a)
2901 static void _test_flush_done(unsigned line, HANDLE thread)
2903 DWORD res = WaitForSingleObject(thread, 1000);
2904 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (%lu)\n", res, GetLastError());
2905 CloseHandle(thread);
2908 #define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
2909 static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
2911 DWORD result = 0xdeadbeef;
2912 BOOL res;
2914 _test_signaled(line, overlapped->hEvent);
2916 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2917 if (partial_read)
2918 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%lu)\n", res, GetLastError());
2919 else
2920 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %lu\n", GetLastError());
2921 ok_(__FILE__,line)(result == expected_result, "read_bytes = %lu, expected %lu\n", result, expected_result);
2922 CloseHandle(overlapped->hEvent);
2925 #define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
2926 static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
2928 DWORD result;
2929 BOOL res;
2931 _test_signaled(line, overlapped->hEvent);
2933 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2934 ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%lu), expected error %lu\n",
2935 res, GetLastError(), error);
2936 ok_(__FILE__,line)(!result, "result = %lu\n", result);
2937 CloseHandle(overlapped->hEvent);
2940 #define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
2941 static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
2943 BOOL res;
2945 res = pCancelIoEx(handle, overlapped);
2946 ok_(__FILE__,line)(res, "CancelIoEx failed: %lu\n", GetLastError());
2948 _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
2951 static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
2953 OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
2954 char buf[10000], read_buf[10000];
2955 HANDLE flush_thread;
2956 BOOL res;
2958 memset(buf, 0xaa, sizeof(buf));
2960 /* test pending read with overlapped event */
2961 overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
2962 test_flush_sync(writer);
2963 test_peek_pipe(reader, 0, 0, 0);
2965 /* write more data than needed for read */
2966 overlapped_write_sync(writer, buf, 4000);
2967 test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
2968 test_peek_pipe(reader, 3000, 3000, msg_mode ? 3000 : 0);
2970 /* test pending write with overlapped event */
2971 overlapped_write_async(writer, buf, buf_size, &write_overlapped);
2972 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size), 3000 + buf_size, msg_mode ? 3000 : 0);
2974 /* write one more byte */
2975 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2976 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2977 test_not_signaled(write_overlapped.hEvent);
2978 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2979 msg_mode ? 3000 : 0);
2981 /* empty write will not block */
2982 overlapped_write_sync(writer, buf, 0);
2983 test_not_signaled(write_overlapped.hEvent);
2984 test_not_signaled(write_overlapped2.hEvent);
2985 test_peek_pipe(reader, 3000 + (msg_mode ? 0 : buf_size + 1), 3000 + buf_size + 1,
2986 msg_mode ? 3000 : 0);
2988 /* read remaining data from the first write */
2989 overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
2990 test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
2991 test_not_signaled(write_overlapped2.hEvent);
2992 test_not_signaled(flush_thread);
2993 test_peek_pipe(reader, buf_size + (msg_mode ? 0 : 1), buf_size + 1, msg_mode ? buf_size : 0);
2995 /* read one byte so that the next write fits the buffer */
2996 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2997 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2998 test_peek_pipe(reader, buf_size + (msg_mode ? -1 : 0), buf_size, msg_mode ? buf_size - 1 : 0);
3000 /* read the whole buffer */
3001 overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
3002 test_peek_pipe(reader, msg_read ? 1 : 0, msg_read ? 1 : 0, msg_read ? 1 : 0);
3004 if(msg_read)
3006 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3007 test_peek_pipe(reader, 0, 0, 0);
3010 if(msg_mode)
3012 /* we still have an empty message in queue */
3013 overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
3014 test_peek_pipe(reader, 0, 0, 0);
3016 test_flush_done(flush_thread);
3018 /* pipe is empty, the next read will block */
3019 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
3020 overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
3022 /* write one byte */
3023 overlapped_write_sync(writer, buf, 1);
3024 test_overlapped_result(reader, &read_overlapped, 0, msg_read);
3025 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
3026 test_peek_pipe(reader, 0, 0, 0);
3028 /* write a message larger than buffer */
3029 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3030 test_peek_pipe(reader, buf_size + 2000, buf_size + 2000, msg_mode ? buf_size + 2000 : 0);
3032 /* read so that pending write is still larger than the buffer */
3033 overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
3034 test_not_signaled(write_overlapped.hEvent);
3035 test_peek_pipe(reader, buf_size + 1, buf_size + 1, msg_mode ? buf_size + 1 : 0);
3037 /* read one more byte */
3038 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
3039 test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
3040 test_peek_pipe(reader, buf_size, buf_size, msg_mode ? buf_size : 0);
3042 /* read remaining data */
3043 overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
3044 test_peek_pipe(reader, 0, 0, 0);
3046 /* simple pass of empty message */
3047 overlapped_write_sync(writer, buf, 0);
3048 test_peek_pipe(reader, 0, 0, 0);
3049 if(msg_mode)
3050 overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
3052 /* pipe is empty, the next read will block */
3053 test_flush_sync(writer);
3054 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
3055 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3057 /* 0 length write wakes one read in msg mode */
3058 overlapped_write_sync(writer, buf, 0);
3059 if(msg_mode)
3060 test_overlapped_result(reader, &read_overlapped, 0, FALSE);
3061 else
3062 test_not_signaled(read_overlapped.hEvent);
3063 test_not_signaled(read_overlapped2.hEvent);
3064 overlapped_write_sync(writer, buf, 1);
3065 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
3067 overlapped_write_sync(writer, buf, 20);
3068 test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
3069 overlapped_write_sync(writer, buf, 15);
3070 test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
3071 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3072 test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
3073 overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
3074 test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
3075 overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
3077 if(!pCancelIoEx) {
3078 win_skip("CancelIoEx not available\n");
3079 return;
3082 /* add one more pending read, then cancel the first one */
3083 overlapped_read_async(reader, read_buf, 1, &read_overlapped);
3084 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3085 cancel_overlapped(reader, &read_overlapped2);
3086 test_not_signaled(read_overlapped.hEvent);
3087 overlapped_write_sync(writer, buf, 1);
3088 test_overlapped_result(reader, &read_overlapped, 1, FALSE);
3090 /* Test that canceling the same operation twice gives a sensible error */
3091 SetLastError(0xdeadbeef);
3092 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
3093 res = pCancelIoEx(reader, &read_overlapped2);
3094 ok(res, "CancelIoEx failed with error %ld\n", GetLastError());
3095 res = pCancelIoEx(reader, &read_overlapped2);
3096 ok(!res, "CancelIOEx succeeded unexpectedly\n");
3097 ok(GetLastError() == ERROR_NOT_FOUND,
3098 "In CancelIoEx failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
3099 test_overlapped_failure(reader, &read_overlapped2, ERROR_OPERATION_ABORTED);
3101 /* make two async writes, cancel the first one and make sure that we read from the second one */
3102 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3103 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3104 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3105 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3106 cancel_overlapped(writer, &write_overlapped);
3107 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3108 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3109 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3110 test_peek_pipe(reader, 0, 0, 0);
3112 /* same as above, but partially read written data before canceling */
3113 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3114 overlapped_write_async(writer, buf, 1, &write_overlapped2);
3115 test_peek_pipe(reader, buf_size + 2000 + (msg_mode ? 0 : 1),
3116 buf_size + 2001, msg_mode ? buf_size + 2000 : 0);
3117 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
3118 test_not_signaled(write_overlapped.hEvent);
3119 cancel_overlapped(writer, &write_overlapped);
3120 test_peek_pipe(reader, 1, 1, msg_mode ? 1 : 0);
3121 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
3122 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
3123 test_peek_pipe(reader, 0, 0, 0);
3125 /* empty queue by canceling write and make sure that flush is signaled */
3126 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
3127 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
3128 test_not_signaled(flush_thread);
3129 cancel_overlapped(writer, &write_overlapped);
3130 test_peek_pipe(reader, 0, 0, 0);
3131 test_flush_done(flush_thread);
3134 #define overlapped_transact(a,b,c,d,e,f) _overlapped_transact(__LINE__,a,b,c,d,e,f)
3135 static void _overlapped_transact(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3136 void *read_buf, DWORD read_size, OVERLAPPED *overlapped)
3138 BOOL res;
3140 memset(overlapped, 0, sizeof(*overlapped));
3141 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3142 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, overlapped);
3143 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING,
3144 "TransactNamedPipe returned: %x(%lu)\n", res, GetLastError());
3147 #define overlapped_transact_failure(a,b,c,d,e,f) _overlapped_transact_failure(__LINE__,a,b,c,d,e,f)
3148 static void _overlapped_transact_failure(unsigned line, HANDLE caller, void *write_buf, DWORD write_size,
3149 void *read_buf, DWORD read_size, DWORD expected_error)
3151 OVERLAPPED overlapped;
3152 BOOL res;
3154 memset(&overlapped, 0, sizeof(overlapped));
3155 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3156 res = TransactNamedPipe(caller, write_buf, write_size, read_buf, read_size, NULL, &overlapped);
3157 ok_(__FILE__,line)(!res, "TransactNamedPipe succeeded\n");
3159 if (GetLastError() == ERROR_IO_PENDING) /* win8+ */
3161 _test_overlapped_failure(line, caller, &overlapped, expected_error);
3163 else
3165 ok_(__FILE__,line)(GetLastError() == expected_error,
3166 "TransactNamedPipe returned error %lu, expected %lu\n",
3167 GetLastError(), expected_error);
3168 CloseHandle(overlapped.hEvent);
3172 static void child_process_write_pipe(HANDLE pipe)
3174 OVERLAPPED overlapped;
3175 char buf[10000];
3177 memset(buf, 'x', sizeof(buf));
3178 overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
3180 /* sleep until parent process terminates this process */
3181 Sleep(INFINITE);
3184 static HANDLE create_writepipe_process(HANDLE pipe)
3186 STARTUPINFOA si = { sizeof(si) };
3187 PROCESS_INFORMATION info;
3188 char **argv, buf[MAX_PATH];
3189 BOOL res;
3191 winetest_get_mainargs(&argv);
3192 sprintf(buf, "\"%s\" pipe writepipe %Ix", argv[0], (UINT_PTR)pipe);
3193 res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
3194 ok(res, "CreateProcess failed: %lu\n", GetLastError());
3195 CloseHandle(info.hThread);
3197 return info.hProcess;
3200 static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
3202 SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
3203 DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
3204 OVERLAPPED overlapped;
3205 BOOL res;
3207 *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3208 PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3209 ok(*server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %lu\n", GetLastError());
3210 test_signaled(*server);
3212 memset(&overlapped, 0, sizeof(overlapped));
3213 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3214 res = ConnectNamedPipe(*server, &overlapped);
3215 ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%lu)\n", res, GetLastError());
3216 test_not_signaled(*server);
3217 test_not_signaled(overlapped.hEvent);
3219 *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
3220 ok(*client != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
3222 res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
3223 ok(res, "SetNamedPipeHandleState failed: %lu\n", GetLastError());
3225 test_signaled(*client);
3226 test_not_signaled(*server);
3227 test_overlapped_result(*server, &overlapped, 0, FALSE);
3230 static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
3232 OVERLAPPED overlapped, overlapped2;
3233 HANDLE server, client, flush;
3234 DWORD read_bytes;
3235 HANDLE process;
3236 char buf[60000];
3237 BOOL res;
3239 DWORD create_flags =
3240 (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
3241 (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
3243 create_overlapped_pipe(create_flags, &client, &server);
3245 trace("testing %s, %s server->client writes...\n",
3246 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3247 test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
3248 trace("testing %s, %s client->server writes...\n",
3249 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3250 test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
3252 CloseHandle(client);
3253 CloseHandle(server);
3255 /* close client with pending writes */
3256 memset(buf, 0xaa, sizeof(buf));
3257 create_overlapped_pipe(create_flags, &client, &server);
3258 overlapped_write_async(server, buf, 7000, &overlapped);
3259 flush = test_flush_async(server, ERROR_BROKEN_PIPE);
3260 CloseHandle(client);
3261 test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
3262 test_flush_done(flush);
3263 CloseHandle(server);
3265 /* close server with pending writes */
3266 create_overlapped_pipe(create_flags, &client, &server);
3267 overlapped_write_async(client, buf, 7000, &overlapped);
3268 flush = test_flush_async(client, ERROR_BROKEN_PIPE);
3269 CloseHandle(server);
3270 test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
3271 test_flush_done(flush);
3272 CloseHandle(client);
3274 /* disconnect with pending writes */
3275 create_overlapped_pipe(create_flags, &client, &server);
3276 overlapped_write_async(client, buf, 7000, &overlapped);
3277 overlapped_write_async(server, buf, 7000, &overlapped2);
3278 flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
3279 res = DisconnectNamedPipe(server);
3280 ok(res, "DisconnectNamedPipe failed: %lu\n", GetLastError());
3281 test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
3282 test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
3283 test_flush_done(flush);
3284 CloseHandle(server);
3285 CloseHandle(client);
3287 /* terminate process with pending write */
3288 create_overlapped_pipe(create_flags, &client, &server);
3289 process = create_writepipe_process(client);
3290 /* successfully read part of write that is pending in child process */
3291 res = ReadFile(server, buf, 10, &read_bytes, NULL);
3292 if(!msg_read_mode)
3293 ok(res, "ReadFile failed: %lu\n", GetLastError());
3294 else
3295 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %lu\n", res, GetLastError());
3296 ok(read_bytes == 10, "read_bytes = %lu\n", read_bytes);
3297 TerminateProcess(process, 0);
3298 wait_child_process(process);
3299 /* after terminating process, there is no pending write and pipe buffer is empty */
3300 overlapped_read_async(server, buf, 10, &overlapped);
3301 overlapped_write_sync(client, buf, 1);
3302 test_overlapped_result(server, &overlapped, 1, FALSE);
3303 CloseHandle(process);
3304 CloseHandle(server);
3305 CloseHandle(client);
3308 static void test_transact(HANDLE caller, HANDLE callee, DWORD write_buf_size, DWORD read_buf_size)
3310 OVERLAPPED overlapped, overlapped2, read_overlapped, write_overlapped;
3311 char buf[10000], read_buf[10000];
3313 memset(buf, 0xaa, sizeof(buf));
3315 /* simple transact call */
3316 overlapped_transact(caller, (BYTE*)"abc", 3, read_buf, 100, &overlapped);
3317 overlapped_write_sync(callee, (BYTE*)"test", 4);
3318 test_overlapped_result(caller, &overlapped, 4, FALSE);
3319 ok(!memcmp(read_buf, "test", 4), "unexpected read_buf\n");
3320 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3321 ok(!memcmp(read_buf, "abc", 3), "unexpected read_buf\n");
3323 /* transact fails if there is already data in read buffer */
3324 overlapped_write_sync(callee, buf, 1);
3325 overlapped_transact_failure(caller, buf, 2, read_buf, 1, ERROR_PIPE_BUSY);
3326 overlapped_read_sync(caller, read_buf, 1000, 1, FALSE);
3328 /* transact doesn't block on write */
3329 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3330 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3331 test_not_signaled(overlapped.hEvent);
3332 overlapped_write_sync(callee, buf, 1);
3333 test_overlapped_result(caller, &overlapped, 1, FALSE);
3334 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3335 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3336 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3338 /* transact with already pending read */
3339 overlapped_read_async(callee, read_buf, 10, &read_overlapped);
3340 overlapped_transact(caller, buf, 5, read_buf, 6, &overlapped);
3341 test_overlapped_result(callee, &read_overlapped, 5, FALSE);
3342 test_not_signaled(overlapped.hEvent);
3343 overlapped_write_sync(callee, buf, 10);
3344 test_overlapped_result(caller, &overlapped, 6, TRUE);
3345 overlapped_read_sync(caller, read_buf, sizeof(read_buf), 4, FALSE);
3347 /* 0-size messages */
3348 overlapped_transact(caller, buf, 5, read_buf, 0, &overlapped);
3349 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 5, FALSE);
3350 overlapped_write_sync(callee, buf, 0);
3351 test_overlapped_result(caller, &overlapped, 0, FALSE);
3353 overlapped_transact(caller, buf, 0, read_buf, 0, &overlapped);
3354 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 0, FALSE);
3355 test_not_signaled(overlapped.hEvent);
3356 overlapped_write_sync(callee, buf, 0);
3357 test_overlapped_result(caller, &overlapped, 0, FALSE);
3359 /* reply transact with another transact */
3360 overlapped_transact(caller, buf, 3, read_buf, 100, &overlapped);
3361 overlapped_read_sync(callee, read_buf, 1000, 3, FALSE);
3362 overlapped_transact(callee, buf, 4, read_buf, 100, &overlapped2);
3363 test_overlapped_result(caller, &overlapped, 4, FALSE);
3364 overlapped_write_sync(caller, buf, 1);
3365 test_overlapped_result(caller, &overlapped2, 1, FALSE);
3367 if (!pCancelIoEx) return;
3369 /* cancel keeps written data */
3370 overlapped_write_async(caller, buf, write_buf_size+2000, &write_overlapped);
3371 overlapped_transact(caller, buf, 2, read_buf, 1, &overlapped);
3372 test_not_signaled(overlapped.hEvent);
3373 cancel_overlapped(caller, &overlapped);
3374 overlapped_read_sync(callee, read_buf, sizeof(read_buf), write_buf_size+2000, FALSE);
3375 test_overlapped_result(caller, &write_overlapped, write_buf_size+2000, FALSE);
3376 overlapped_read_sync(callee, read_buf, sizeof(read_buf), 2, FALSE);
3379 static void test_TransactNamedPipe(void)
3381 HANDLE client, server;
3382 BYTE buf[10];
3384 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3385 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3386 CloseHandle(client);
3387 CloseHandle(server);
3389 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, &client, &server);
3390 overlapped_transact_failure(client, buf, 2, buf, 1, ERROR_BAD_PIPE);
3391 CloseHandle(client);
3392 CloseHandle(server);
3394 trace("testing server->client transaction...\n");
3395 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3396 test_transact(server, client, 5000, 6000);
3397 CloseHandle(client);
3398 CloseHandle(server);
3400 trace("testing client->server transaction...\n");
3401 create_overlapped_pipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, &client, &server);
3402 test_transact(client, server, 6000, 5000);
3403 CloseHandle(client);
3404 CloseHandle(server);
3407 static HANDLE create_overlapped_server( OVERLAPPED *overlapped )
3409 HANDLE pipe;
3410 BOOL ret;
3412 pipe = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT,
3413 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
3414 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3415 ret = ConnectNamedPipe(pipe, overlapped);
3416 ok(!ret && GetLastError() == ERROR_IO_PENDING, "got %lu\n", GetLastError());
3417 return pipe;
3420 static void child_process_check_pid(DWORD server_pid)
3422 DWORD current = GetProcessId(GetCurrentProcess());
3423 HANDLE pipe;
3424 ULONG pid;
3425 BOOL ret;
3427 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3428 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3430 pid = 0;
3431 ret = pGetNamedPipeClientProcessId(pipe, &pid);
3432 ok(ret, "got %lu\n", GetLastError());
3433 ok(pid == current, "got %04lx\n", pid);
3435 pid = 0;
3436 ret = pGetNamedPipeServerProcessId(pipe, &pid);
3437 ok(ret, "got %lu\n", GetLastError());
3438 ok(pid == server_pid, "got %04lx expected %04lx\n", pid, server_pid);
3439 CloseHandle(pipe);
3442 static HANDLE create_check_id_process(const char *verb, DWORD id)
3444 STARTUPINFOA si = {sizeof(si)};
3445 PROCESS_INFORMATION info;
3446 char **argv, buf[MAX_PATH];
3447 BOOL ret;
3449 winetest_get_mainargs(&argv);
3450 sprintf(buf, "\"%s\" pipe %s %lx", argv[0], verb, id);
3451 ret = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &info);
3452 ok(ret, "got %lu\n", GetLastError());
3453 CloseHandle(info.hThread);
3454 return info.hProcess;
3457 static void test_namedpipe_process_id(void)
3459 HANDLE client, server, process;
3460 DWORD current = GetProcessId(GetCurrentProcess());
3461 OVERLAPPED overlapped;
3462 ULONG pid;
3463 BOOL ret;
3465 if (!pGetNamedPipeClientProcessId)
3467 win_skip("GetNamedPipeClientProcessId not available\n");
3468 return;
3471 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3473 SetLastError(0xdeadbeef);
3474 ret = pGetNamedPipeClientProcessId(server, NULL);
3475 ok(!ret, "success\n");
3476 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3478 pid = 0;
3479 ret = pGetNamedPipeClientProcessId(server, &pid);
3480 ok(ret, "got %lu\n", GetLastError());
3481 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3483 pid = 0;
3484 ret = pGetNamedPipeClientProcessId(client, &pid);
3485 ok(ret, "got %lu\n", GetLastError());
3486 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3488 SetLastError(0xdeadbeef);
3489 ret = pGetNamedPipeServerProcessId(server, NULL);
3490 ok(!ret, "success\n");
3491 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3493 pid = 0;
3494 ret = pGetNamedPipeServerProcessId(client, &pid);
3495 ok(ret, "got %lu\n", GetLastError());
3496 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3498 pid = 0;
3499 ret = pGetNamedPipeServerProcessId(server, &pid);
3500 ok(ret, "got %lu\n", GetLastError());
3501 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3503 /* closed client handle */
3504 CloseHandle(client);
3505 pid = 0;
3506 ret = pGetNamedPipeClientProcessId(server, &pid);
3507 ok(ret, "got %lu\n", GetLastError());
3508 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3510 pid = 0;
3511 ret = pGetNamedPipeServerProcessId(server, &pid);
3512 ok(ret, "got %lu\n", GetLastError());
3513 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3514 CloseHandle(server);
3516 /* disconnected server */
3517 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3518 DisconnectNamedPipe(server);
3520 SetLastError(0xdeadbeef);
3521 ret = pGetNamedPipeClientProcessId(server, &pid);
3522 todo_wine ok(!ret, "success\n");
3523 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %lu\n", GetLastError());
3525 pid = 0;
3526 ret = pGetNamedPipeServerProcessId(server, &pid);
3527 ok(ret, "got %lu\n", GetLastError());
3528 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3530 SetLastError(0xdeadbeef);
3531 ret = pGetNamedPipeClientProcessId(client, &pid);
3532 todo_wine ok(!ret, "success\n");
3533 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3535 SetLastError(0xdeadbeef);
3536 ret = pGetNamedPipeServerProcessId(client, &pid);
3537 todo_wine ok(!ret, "success\n");
3538 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3539 CloseHandle(client);
3540 CloseHandle(server);
3542 /* closed server handle */
3543 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3544 CloseHandle(server);
3546 pid = 0;
3547 ret = pGetNamedPipeClientProcessId(client, &pid);
3548 ok(ret, "got %lu\n", GetLastError());
3549 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3551 pid = 0;
3552 ret = pGetNamedPipeServerProcessId(client, &pid);
3553 ok(ret, "got %lu\n", GetLastError());
3554 ok(pid == current, "got %04lx expected %04lx\n", pid, current);
3555 CloseHandle(client);
3557 /* different process */
3558 memset(&overlapped, 0, sizeof(overlapped));
3559 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3560 server = create_overlapped_server( &overlapped );
3561 ok(server != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3563 process = create_check_id_process("checkpid", GetProcessId(GetCurrentProcess()));
3564 wait_child_process(process);
3566 CloseHandle(overlapped.hEvent);
3567 CloseHandle(process);
3568 CloseHandle(server);
3571 static void child_process_check_session_id(DWORD server_id)
3573 DWORD current;
3574 HANDLE pipe;
3575 ULONG id;
3576 BOOL ret;
3578 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &current);
3580 pipe = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
3581 ok(pipe != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3583 id = 0;
3584 ret = pGetNamedPipeClientSessionId(pipe, &id);
3585 ok(ret, "got %lu\n", GetLastError());
3586 ok(id == current, "got %04lx\n", id);
3588 id = 0;
3589 ret = pGetNamedPipeServerSessionId(pipe, &id);
3590 ok(ret, "got %lu\n", GetLastError());
3591 ok(id == server_id, "got %04lx expected %04lx\n", id, server_id);
3592 CloseHandle(pipe);
3595 static void test_namedpipe_session_id(void)
3597 HANDLE client, server, process;
3598 OVERLAPPED overlapped;
3599 DWORD current;
3600 ULONG id;
3601 BOOL ret;
3603 if (!pGetNamedPipeClientSessionId)
3605 win_skip("GetNamedPipeClientSessionId not available\n");
3606 return;
3609 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &current);
3611 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3613 if (0) /* crashes on recent Windows */
3615 SetLastError(0xdeadbeef);
3616 ret = pGetNamedPipeClientSessionId(server, NULL);
3617 ok(!ret, "success\n");
3620 id = 0;
3621 ret = pGetNamedPipeClientSessionId(server, &id);
3622 ok(ret, "got %lu\n", GetLastError());
3623 ok(id == current, "got %lu expected %lu\n", id, current);
3625 id = 0;
3626 ret = pGetNamedPipeClientSessionId(client, &id);
3627 ok(ret, "got %lu\n", GetLastError());
3628 ok(id == current, "got %lu expected %lu\n", id, current);
3630 SetLastError(0xdeadbeef);
3631 ret = pGetNamedPipeServerSessionId(server, NULL);
3632 ok(!ret, "success\n");
3633 todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
3635 id = 0;
3636 ret = pGetNamedPipeServerSessionId(client, &id);
3637 ok(ret, "got %lu\n", GetLastError());
3638 ok(id == current, "got %lu expected %lu\n", id, current);
3640 id = 0;
3641 ret = pGetNamedPipeServerSessionId(server, &id);
3642 ok(ret, "got %lu\n", GetLastError());
3643 ok(id == current, "got %lu expected %lu\n", id, current);
3645 /* closed client handle */
3646 CloseHandle(client);
3648 id = 0;
3649 ret = pGetNamedPipeClientSessionId(server, &id);
3650 ok(ret, "got %lu\n", GetLastError());
3651 ok(id == current, "got %04lx expected %04lx\n", id, current);
3653 id = 0;
3654 ret = pGetNamedPipeServerSessionId(server, &id);
3655 ok(ret, "got %lu\n", GetLastError());
3656 ok(id == current, "got %04lx expected %04lx\n", id, current);
3657 CloseHandle(server);
3659 /* disconnected server */
3660 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3661 DisconnectNamedPipe(server);
3663 SetLastError(0xdeadbeef);
3664 ret = pGetNamedPipeClientSessionId(server, &id);
3665 todo_wine ok(!ret, "success\n");
3666 todo_wine ok(GetLastError() == ERROR_NOT_FOUND, "got %lu\n", GetLastError());
3668 id = 0;
3669 ret = pGetNamedPipeServerSessionId(server, &id);
3670 ok(ret, "got %lu\n", GetLastError());
3671 ok(id == current, "got %04lx expected %04lx\n", id, current);
3673 SetLastError(0xdeadbeef);
3674 ret = pGetNamedPipeClientSessionId(client, &id);
3675 todo_wine ok(!ret, "success\n");
3676 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3678 SetLastError(0xdeadbeef);
3679 ret = pGetNamedPipeServerSessionId(client, &id);
3680 todo_wine ok(!ret, "success\n");
3681 todo_wine ok(GetLastError() == ERROR_PIPE_NOT_CONNECTED, "got %lu\n", GetLastError());
3682 CloseHandle(client);
3683 CloseHandle(server);
3685 /* closed server handle */
3686 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
3687 CloseHandle(server);
3689 id = 0;
3690 ret = pGetNamedPipeClientSessionId(client, &id);
3691 ok(ret, "got %lu\n", GetLastError());
3692 ok(id == current, "got %04lx expected %04lx\n", id, current);
3694 id = 0;
3695 ret = pGetNamedPipeServerSessionId(client, &id);
3696 ok(ret, "got %lu\n", GetLastError());
3697 ok(id == current, "got %04lx expected %04lx\n", id, current);
3698 CloseHandle(client);
3700 /* different process */
3701 memset(&overlapped, 0, sizeof(overlapped));
3702 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3703 server = create_overlapped_server( &overlapped );
3704 ok(server != INVALID_HANDLE_VALUE, "got %lu\n", GetLastError());
3706 process = create_check_id_process("checksessionid", current);
3707 wait_child_process(process);
3709 CloseHandle(overlapped.hEvent);
3710 CloseHandle(process);
3711 CloseHandle(server);
3714 static void test_multiple_instances(void)
3716 HANDLE server[4], client;
3717 int i;
3718 BOOL ret;
3719 OVERLAPPED ov;
3721 if(!pCancelIoEx)
3723 win_skip("Skipping multiple instance tests on too old Windows\n");
3724 return;
3727 for (i = 0; i < ARRAY_SIZE(server); i++)
3729 server[i] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3730 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3731 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3732 ok(server[i] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3735 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3736 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3738 /* Show that this has connected to server[0] not any other one */
3740 memset(&ov, 0, sizeof(ov));
3741 ret = ConnectNamedPipe(server[2], &ov);
3742 ok(ret == FALSE, "got %d\n", ret);
3743 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3745 memset(&ov, 0, sizeof(ov));
3746 ret = ConnectNamedPipe(server[0], &ov);
3747 ok(ret == FALSE, "got %d\n", ret);
3748 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3750 CloseHandle(client);
3752 /* The next connected server is server[1], doesn't matter that server[2] has pending listeners */
3754 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3755 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3757 memset(&ov, 0, sizeof(ov));
3758 ret = ConnectNamedPipe(server[2], &ov);
3759 ok(ret == FALSE, "got %d\n", ret);
3760 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3762 memset(&ov, 0, sizeof(ov));
3763 ret = ConnectNamedPipe(server[1], &ov);
3764 ok(ret == FALSE, "got %d\n", ret);
3765 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3767 CloseHandle(client);
3769 /* server[2] is connected next */
3771 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3772 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3774 memset(&ov, 0, sizeof(ov));
3775 ret = ConnectNamedPipe(server[2], &ov);
3776 ok(ret == FALSE, "got %d\n", ret);
3777 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3779 CloseHandle(client);
3781 /* Disconnect in order server[0] and server[2] */
3783 DisconnectNamedPipe(server[0]);
3784 DisconnectNamedPipe(server[2]);
3786 /* Put into listening state server[2] and server[0] */
3788 memset(&ov, 0, sizeof(ov));
3789 ret = ConnectNamedPipe(server[2], &ov);
3790 ok(ret == FALSE, "got %d\n", ret);
3791 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3793 memset(&ov, 0, sizeof(ov));
3794 ret = ConnectNamedPipe(server[0], &ov);
3795 ok(ret == FALSE, "got %d\n", ret);
3796 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3798 /* server[3] is connected next */
3800 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3801 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3803 memset(&ov, 0, sizeof(ov));
3804 ret = ConnectNamedPipe(server[3], &ov);
3805 ok(ret == FALSE, "got %d\n", ret);
3806 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3808 CloseHandle(client);
3810 /* server[2], which stasted listening first, will be connected next */
3812 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3813 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3815 memset(&ov, 0, sizeof(ov));
3816 ret = ConnectNamedPipe(server[2], &ov);
3817 ok(ret == FALSE, "got %d\n", ret);
3818 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3820 memset(&ov, 0, sizeof(ov));
3821 ret = ConnectNamedPipe(server[0], &ov);
3822 ok(ret == FALSE, "got %d\n", ret);
3823 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3825 CloseHandle(client);
3827 /* Finally server[0] is connected */
3829 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3830 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3832 memset(&ov, 0, sizeof(ov));
3833 ret = ConnectNamedPipe(server[0], &ov);
3834 ok(ret == FALSE, "got %d\n", ret);
3835 ok(GetLastError() == ERROR_PIPE_CONNECTED, "got %ld\n", GetLastError());
3837 CloseHandle(client);
3839 /* No more listening pipes available */
3840 DisconnectNamedPipe(server[0]);
3841 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3842 ok(client == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY, "got %p(%lu)\n", client, GetLastError());
3844 for (i = 0; i < ARRAY_SIZE(server); i++)
3846 DisconnectNamedPipe(server[i]);
3847 CloseHandle(server[i]);
3851 static DWORD WINAPI wait_pipe_proc(void *arg)
3853 BOOL ret;
3854 ret = WaitNamedPipeA(PIPENAME, 1000);
3855 ok(ret, "WaitNamedPipe failed (%lu)\n", GetLastError());
3856 return 0;
3859 static HANDLE async_wait_pipe(void)
3861 HANDLE thread;
3862 BOOL ret;
3864 thread = CreateThread(NULL, 0, wait_pipe_proc, NULL, 0, NULL);
3865 ok(thread != NULL, "CreateThread failed: %lu\n", GetLastError());
3867 ret = WaitNamedPipeA(PIPENAME, 1);
3868 ok(!ret && GetLastError() == ERROR_SEM_TIMEOUT, "WaitNamedPipe failed %x(%lu)\n", ret, GetLastError());
3870 return thread;
3873 static void test_wait_pipe(void)
3875 HANDLE server[2], client, wait;
3876 OVERLAPPED ov;
3877 DWORD res;
3878 BOOL ret;
3880 ret = WaitNamedPipeA(PIPENAME, 0);
3881 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "WaitNamedPipe failed %x(%lu)\n", ret, GetLastError());
3883 server[0] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3884 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3885 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3886 ok(server[0] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3888 ret = WaitNamedPipeA(PIPENAME, 1);
3889 ok(ret, "WaitNamedPipe failed (%lu)\n", GetLastError());
3891 client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3892 ok(client != INVALID_HANDLE_VALUE, "got invalid handle\n");
3894 /* Creating a new pipe server wakes waiters */
3895 wait = async_wait_pipe();
3896 server[1] = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
3897 PIPE_READMODE_BYTE | PIPE_WAIT, ARRAY_SIZE(server), 1024, 1024,
3898 NMPWAIT_USE_DEFAULT_WAIT, NULL);
3899 ok(server[1] != INVALID_HANDLE_VALUE, "got invalid handle\n");
3901 res = WaitForSingleObject(wait, 100);
3902 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3904 CloseHandle(wait);
3905 CloseHandle(server[1]);
3907 CloseHandle(client);
3908 ret = DisconnectNamedPipe(server[0]);
3909 ok(ret, "DisconnectNamedPipe failed (%lu)\n", GetLastError());
3911 /* Putting pipe server into waiting listening state wakes waiters */
3912 wait = async_wait_pipe();
3913 memset(&ov, 0, sizeof(ov));
3914 ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3915 ret = ConnectNamedPipe(server[0], &ov);
3916 ok(ret == FALSE, "got %d\n", ret);
3917 ok(GetLastError() == ERROR_IO_PENDING, "got %ld\n", GetLastError());
3919 res = WaitForSingleObject(wait, 100);
3920 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3921 CloseHandle(server[0]);
3923 res = WaitForSingleObject(ov.hEvent, 0);
3924 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", res);
3925 CloseHandle(ov.hEvent);
3928 static void test_nowait(DWORD pipe_type)
3930 HANDLE piperead, pipewrite, file;
3931 OVERLAPPED ol, ol2;
3932 DWORD read, write;
3933 char readbuf[32768];
3934 static const char teststring[] = "bits";
3936 /* CreateNamedPipe with PIPE_NOWAIT, and read from empty pipe */
3937 piperead = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3938 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3939 /* nMaxInstances */ 1,
3940 /* nOutBufSize */ 512,
3941 /* nInBufSize */ 512,
3942 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3943 /* lpSecurityAttrib */ NULL);
3944 ok(piperead != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3945 pipewrite = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3946 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3947 memset(&ol, 0, sizeof(ol));
3948 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3949 SetLastError(0xdeadbeef);
3950 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol) == FALSE, "ReadFile should fail\n");
3951 ok(GetLastError() == ERROR_NO_DATA, "got %ld should be ERROR_NO_DATA\n", GetLastError());
3952 if (GetLastError() == ERROR_IO_PENDING)
3953 CancelIo(piperead);
3955 /* test a small write/read */
3956 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, NULL), "WriteFile should succeed\n");
3957 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol), "ReadFile should succeed\n");
3958 ok(read == write, "read/write bytes should match\n");
3959 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
3960 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
3961 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
3964 /* create write side with PIPE_NOWAIT, read side PIPE_WAIT, and test writes */
3965 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
3966 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
3967 /* nMaxInstances */ 1,
3968 /* nOutBufSize */ 512,
3969 /* nInBufSize */ 512,
3970 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
3971 /* lpSecurityAttrib */ NULL);
3972 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
3973 piperead = CreateFileA(PIPENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
3974 ok(piperead != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
3975 memset(&ol, 0, sizeof(ol));
3976 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3977 memset(&ol2, 0, sizeof(ol2));
3978 ol2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3980 /* write one byte larger than the buffer size, should fail */
3981 SetLastError(0xdeadbeef);
3982 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
3983 /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows
3984 * doesn't seem to do partial writes ('write == 0' always)
3986 ok(write < sizeof(readbuf), "WriteFile should fail to write the whole buffer\n");
3987 ok(write == 0, "WriteFile doesn't do partial writes here\n");
3988 if (GetLastError() == ERROR_IO_PENDING)
3989 CancelIo(piperead);
3991 /* overlapped read of 32768, non-blocking write of 512 */
3992 SetLastError(0xdeadbeef);
3993 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
3994 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
3995 ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, &ol), "WriteFile should succeed\n");
3996 ok(write == sizeof(teststring), "got %ld\n", write);
3997 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
3998 ok(read == sizeof(teststring), "got %ld\n", read);
3999 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4000 CancelIo(piperead);
4002 /* overlapped read of 32768, non-blocking write of 513 */
4003 SetLastError(0xdeadbeef);
4004 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n");
4005 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4006 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
4007 ok(write == 513, "got %ld, write should be %d\n", write, 513);
4008 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
4009 ok(read == 513, "got %ld, read should be %d\n", read, 513);
4010 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4011 CancelIo(piperead);
4013 /* overlapped read of 1 byte, non-blocking write of 513 bytes */
4014 SetLastError(0xdeadbeef);
4015 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
4016 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4017 ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n");
4018 ok(write == 513, "got %ld, write should be %d\n", write, 513);
4019 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n");
4020 ok(read == 1, "got %ld, read should be %d\n", read, 1);
4021 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4022 CancelIo(piperead);
4023 /* read the remaining 512 bytes */
4024 SetLastError(0xdeadbeef);
4025 ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2), "ReadFile should succeed\n");
4026 ok(read == 512, "got %ld, write should be %d\n", write, 512);
4027 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4028 CancelIo(piperead);
4030 /* overlapped read of 1 byte, non-blocking write of 514 bytes */
4031 SetLastError(0xdeadbeef);
4032 ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n");
4033 ok(GetLastError() == ERROR_IO_PENDING, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4034 ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n");
4035 if (pipe_type == PIPE_TYPE_MESSAGE)
4037 todo_wine
4038 ok(write == 0, "got %ld\n", write);
4039 todo_wine
4040 ok(!GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4041 todo_wine
4042 ok(GetLastError() == ERROR_IO_INCOMPLETE, "got %ld should be ERROR_IO_PENDING\n", GetLastError());
4043 todo_wine
4044 ok(read == 0, "got %ld, read should be %d\n", read, 1);
4046 else
4048 ok(write == 1, "got %ld\n", write);
4049 ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should fail\n");
4050 ok(read == 1, "got %ld, read should be %d\n", read, 1);
4052 if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE)
4053 CancelIo(piperead);
4055 /* write the exact buffer size, should succeed */
4056 SetLastError(0xdeadbeef);
4057 ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n");
4058 ok(write == 512, "WriteFile should write the whole buffer\n");
4059 if (GetLastError() == ERROR_IO_PENDING)
4060 CancelIo(piperead);
4062 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4063 ok(CloseHandle(ol2.hEvent), "CloseHandle for the event failed\n");
4064 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4065 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
4068 /* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */
4069 pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
4070 /* dwPipeMode */ pipe_type | PIPE_NOWAIT,
4071 /* nMaxInstances */ 1,
4072 /* nOutBufSize */ 512,
4073 /* nInBufSize */ 512,
4074 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
4075 /* lpSecurityAttrib */ NULL);
4076 ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
4077 memset(&ol, 0, sizeof(ol));
4078 ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4079 SetLastError(0xdeadbeef);
4080 ok(ConnectNamedPipe(pipewrite, &ol) == FALSE, "ConnectNamedPipe should fail\n");
4081 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %ld should be ERROR_PIPE_LISTENING\n", GetLastError());
4082 if (GetLastError() == ERROR_IO_PENDING)
4083 CancelIo(pipewrite);
4085 /* connect and disconnect, then test ConnectNamedPipe again */
4086 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
4087 ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
4088 ok(CloseHandle(file), "CloseHandle failed\n");
4089 SetLastError(0xdeadbeef);
4090 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4091 ok(GetLastError() == ERROR_NO_DATA, "got %ld should be ERROR_NO_DATA\n", GetLastError());
4092 if (GetLastError() == ERROR_IO_PENDING)
4093 CancelIo(pipewrite);
4095 /* call DisconnectNamedPipe and test ConnectNamedPipe again */
4096 ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n");
4097 SetLastError(0xdeadbeef);
4098 ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n");
4099 ok(GetLastError() == ERROR_PIPE_LISTENING, "got %ld should be ERROR_PIPE_LISTENING\n", GetLastError());
4100 if (GetLastError() == ERROR_IO_PENDING)
4101 CancelIo(pipewrite);
4102 ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n");
4103 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
4106 static void test_GetOverlappedResultEx(void)
4108 HANDLE client, server;
4109 OVERLAPPED ovl;
4110 char buffer[8000];
4111 DWORD ret_size;
4112 BOOL ret;
4114 if (!pGetOverlappedResultEx)
4116 win_skip("GetOverlappedResultEx() is not available\n");
4117 return;
4120 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4122 overlapped_write_async(client, buffer, sizeof(buffer), &ovl);
4124 user_apc_ran = FALSE;
4125 QueueUserAPC(user_apc, GetCurrentThread(), 0);
4127 SetLastError(0xdeadbeef);
4128 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, FALSE);
4129 ok(!ret, "expected failure\n");
4130 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %lu\n", GetLastError());
4131 ok(!user_apc_ran, "APC should not have run\n");
4133 SetLastError(0xdeadbeef);
4134 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, TRUE);
4135 ok(!ret, "expected failure\n");
4136 ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %lu\n", GetLastError());
4137 ok(!user_apc_ran, "APC should not have run\n");
4139 SetLastError(0xdeadbeef);
4140 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, FALSE);
4141 ok(!ret, "expected failure\n");
4142 ok(GetLastError() == WAIT_TIMEOUT, "wrong error %lu\n", GetLastError());
4143 ok(!user_apc_ran, "APC should not have run\n");
4145 SetLastError(0xdeadbeef);
4146 ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, TRUE);
4147 ok(!ret, "expected failure\n");
4148 ok(GetLastError() == WAIT_IO_COMPLETION, "wrong error %lu\n", GetLastError());
4149 ok(user_apc_ran, "APC should have run\n");
4151 CloseHandle(ovl.hEvent);
4153 CloseHandle(client);
4154 CloseHandle(server);
4157 static void child_process_exit_process_async(DWORD parent_pid, HANDLE parent_pipe)
4159 OVERLAPPED overlapped = {0};
4160 static char buffer[1];
4161 HANDLE parent, pipe;
4162 BOOL ret;
4164 parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, parent_pid);
4165 ok(!!parent, "got parent %p\n", parent);
4167 ret = DuplicateHandle(parent, parent_pipe, GetCurrentProcess(), &pipe, 0,
4168 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
4169 ok(ret, "got error %lu\n", GetLastError());
4171 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4173 ret = ReadFile(pipe, buffer, sizeof(buffer), NULL, &overlapped);
4174 ok(!ret, "expected failure\n");
4175 ok(GetLastError() == ERROR_IO_PENDING, "got error %lu\n", GetLastError());
4177 /* exit without closing the pipe handle */
4180 static void test_exit_process_async(void)
4182 HANDLE client, server, port;
4183 OVERLAPPED *overlapped;
4184 PROCESS_INFORMATION pi;
4185 STARTUPINFOA si = {0};
4186 char cmdline[300];
4187 ULONG_PTR key;
4188 char **argv;
4189 DWORD size;
4190 BOOL ret;
4192 winetest_get_mainargs(&argv);
4194 create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server);
4195 port = CreateIoCompletionPort(client, NULL, 123, 0);
4197 sprintf(cmdline, "%s pipe exit_process_async %lx %p", argv[0], GetCurrentProcessId(), client);
4198 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
4199 ok(ret, "got error %lu\n", GetLastError());
4200 ret = WaitForSingleObject(pi.hProcess, 1000);
4201 ok(!ret, "wait timed out\n");
4202 CloseHandle(pi.hThread);
4203 CloseHandle(pi.hProcess);
4205 key = 0xdeadbeef;
4206 size = 0xdeadbeef;
4207 ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped, 1000);
4208 ok(!ret, "expected failure\n");
4209 ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %lu\n", GetLastError());
4210 ok(!size, "got size %lu\n", size);
4211 ok(key == 123, "got key %Iu\n", key);
4213 CloseHandle(port);
4214 CloseHandle(server);
4217 static DWORD CALLBACK synchronousIoThreadMain(void *arg)
4219 HANDLE pipe;
4220 BOOL ret;
4222 pipe = arg;
4223 SetLastError(0xdeadbeef);
4224 ret = ConnectNamedPipe(pipe, NULL);
4225 ok(!ret, "expected failure\n");
4226 ok(GetLastError() == ERROR_OPERATION_ABORTED, "got error %lu\n", GetLastError());
4227 return 0;
4230 static DWORD CALLBACK synchronousIoThreadMain2(void *arg)
4232 OVERLAPPED ov;
4233 HANDLE pipe;
4234 BOOL ret;
4236 pipe = arg;
4237 memset(&ov, 0, sizeof(ov));
4238 ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
4239 SetLastError(0xdeadbeef);
4240 ret = ConnectNamedPipe(pipe, &ov);
4241 ok(!ret, "expected failure\n");
4242 ok(GetLastError() == ERROR_IO_PENDING, "got error %lu\n", GetLastError());
4243 ret = WaitForSingleObject(ov.hEvent, 1000);
4244 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", ret);
4245 CloseHandle(ov.hEvent);
4246 return 0;
4249 static void test_CancelSynchronousIo(void)
4251 BOOL res;
4252 DWORD wait;
4253 HANDLE file;
4254 HANDLE pipe;
4255 HANDLE thread;
4257 /* bogus values */
4258 SetLastError(0xdeadbeef);
4259 res = pCancelSynchronousIo((HANDLE)0xdeadbeef);
4260 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4261 ok(GetLastError() == ERROR_INVALID_HANDLE,
4262 "In CancelSynchronousIo failure, expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
4264 SetLastError(0xdeadbeef);
4265 res = pCancelSynchronousIo(GetCurrentThread());
4266 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4267 ok(GetLastError() == ERROR_NOT_FOUND,
4268 "In CancelSynchronousIo failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
4270 /* synchronous i/o */
4271 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
4272 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4273 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
4274 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
4275 thread = CreateThread(NULL, 0, synchronousIoThreadMain, pipe, 0, NULL);
4276 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
4277 while ((wait = WaitForSingleObject(pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
4278 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", wait, GetLastError());
4279 SetLastError(0xdeadbeef);
4280 res = pCancelSynchronousIo(thread);
4281 ok(res, "CancelSynchronousIo failed with error %ld\n", GetLastError());
4282 ok(GetLastError() == 0xdeadbeef,
4283 "In CancelSynchronousIo failure, expected 0xdeadbeef got %ld\n", GetLastError());
4284 wait = WaitForSingleObject(thread, 1000);
4285 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", wait);
4286 CloseHandle(thread);
4287 CloseHandle(pipe);
4289 /* asynchronous i/o */
4290 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
4291 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
4292 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
4293 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %lu\n", GetLastError());
4294 thread = CreateThread(NULL, 0, synchronousIoThreadMain2, pipe, 0, NULL);
4295 /* wait for I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
4296 while ((wait = WaitForSingleObject(pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
4297 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", wait, GetLastError());
4298 SetLastError(0xdeadbeef);
4299 res = pCancelSynchronousIo(thread);
4300 ok(!res, "CancelSynchronousIo succeeded unexpectedly\n");
4301 ok(GetLastError() == ERROR_NOT_FOUND,
4302 "In CancelSynchronousIo failure, expected ERROR_NOT_FOUND, got %ld\n", GetLastError());
4303 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
4304 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed (%ld)\n", GetLastError());
4305 WaitForSingleObject(thread, INFINITE);
4306 CloseHandle(thread);
4307 CloseHandle(file);
4308 CloseHandle(pipe);
4311 START_TEST(pipe)
4313 char **argv;
4314 int argc;
4315 HMODULE hmod;
4317 hmod = GetModuleHandleA("advapi32.dll");
4318 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
4319 hmod = GetModuleHandleA("kernel32.dll");
4320 pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
4321 pCancelSynchronousIo = (void *) GetProcAddress(hmod, "CancelSynchronousIo");
4322 pGetNamedPipeClientProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeClientProcessId");
4323 pGetNamedPipeServerProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeServerProcessId");
4324 pGetNamedPipeClientSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeClientSessionId");
4325 pGetNamedPipeServerSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeServerSessionId");
4326 pGetOverlappedResultEx = (void *)GetProcAddress(hmod, "GetOverlappedResultEx");
4328 argc = winetest_get_mainargs(&argv);
4330 if (argc > 3)
4332 if (!strcmp(argv[2], "writepipe"))
4334 ULONG handle;
4335 sscanf(argv[3], "%lx", &handle);
4336 child_process_write_pipe(ULongToHandle(handle));
4337 return;
4339 if (!strcmp(argv[2], "checkpid"))
4341 DWORD pid = GetProcessId(GetCurrentProcess());
4342 sscanf(argv[3], "%lx", &pid);
4343 child_process_check_pid(pid);
4344 return;
4346 if (!strcmp(argv[2], "checksessionid"))
4348 DWORD id;
4349 ProcessIdToSessionId(GetProcessId(GetCurrentProcess()), &id);
4350 sscanf(argv[3], "%lx", &id);
4351 child_process_check_session_id(id);
4352 return;
4354 if (!strcmp(argv[2], "exit_process_async"))
4356 HANDLE handle;
4357 DWORD pid;
4358 sscanf(argv[3], "%lx", &pid);
4359 sscanf(argv[4], "%p", &handle);
4360 child_process_exit_process_async(pid, handle);
4361 return;
4365 if (test_DisconnectNamedPipe())
4366 return;
4367 test_CreateNamedPipe_instances_must_match();
4368 test_NamedPipe_2();
4369 test_CreateNamedPipe(PIPE_TYPE_BYTE);
4370 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
4371 test_CreatePipe();
4372 test_ReadFile();
4373 test_CloseHandle();
4374 test_impersonation();
4375 test_overlapped();
4376 test_overlapped_error();
4377 test_NamedPipeHandleState();
4378 test_GetNamedPipeInfo();
4379 test_readfileex_pending();
4380 test_overlapped_transport(TRUE, FALSE);
4381 test_overlapped_transport(TRUE, TRUE);
4382 test_overlapped_transport(FALSE, FALSE);
4383 test_TransactNamedPipe();
4384 test_namedpipe_process_id();
4385 test_namedpipe_session_id();
4386 test_multiple_instances();
4387 test_wait_pipe();
4388 test_nowait(PIPE_TYPE_BYTE);
4389 test_nowait(PIPE_TYPE_MESSAGE);
4390 test_GetOverlappedResultEx();
4391 test_exit_process_async();
4392 test_CancelSynchronousIo();