ddraw/tests: Rewrite LimitTest().
[wine.git] / dlls / kernel32 / tests / pipe.c
blob922eed9a574682980fb4c926ab4ec5d329950f41
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 DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
40 static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
42 static BOOL user_apc_ran;
43 static void CALLBACK user_apc(ULONG_PTR param)
45 user_apc_ran = TRUE;
49 enum rpcThreadOp
51 RPC_READFILE
54 struct rpcThreadArgs
56 ULONG_PTR returnValue;
57 DWORD lastError;
58 enum rpcThreadOp op;
59 ULONG_PTR args[5];
62 static DWORD CALLBACK rpcThreadMain(LPVOID arg)
64 struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
65 if (winetest_debug > 1) trace("rpcThreadMain starting\n");
66 SetLastError( rpcargs->lastError );
68 switch (rpcargs->op)
70 case RPC_READFILE:
71 rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
72 (LPVOID)rpcargs->args[1], /* buffer */
73 (DWORD)rpcargs->args[2], /* bytesToRead */
74 (LPDWORD)rpcargs->args[3], /* bytesRead */
75 (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
76 break;
78 default:
79 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
80 rpcargs->returnValue = 0;
81 break;
84 rpcargs->lastError = GetLastError();
85 if (winetest_debug > 1) trace("rpcThreadMain returning\n");
86 return 0;
89 /* Runs ReadFile(...) from a different thread */
90 static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
92 struct rpcThreadArgs rpcargs;
93 HANDLE thread;
94 DWORD threadId, ret;
96 rpcargs.returnValue = 0;
97 rpcargs.lastError = GetLastError();
98 rpcargs.op = RPC_READFILE;
99 rpcargs.args[0] = (ULONG_PTR)hFile;
100 rpcargs.args[1] = (ULONG_PTR)buffer;
101 rpcargs.args[2] = (ULONG_PTR)bytesToRead;
102 rpcargs.args[3] = (ULONG_PTR)bytesRead;
103 rpcargs.args[4] = (ULONG_PTR)overlapped;
105 thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
106 ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
107 ret = WaitForSingleObject(thread, INFINITE);
108 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
109 CloseHandle(thread);
111 SetLastError(rpcargs.lastError);
112 return (BOOL)rpcargs.returnValue;
115 #define test_not_signaled(h) _test_not_signaled(__LINE__,h)
116 static void _test_not_signaled(unsigned line, HANDLE handle)
118 DWORD res = WaitForSingleObject(handle, 0);
119 ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
122 #define test_signaled(h) _test_signaled(__LINE__,h)
123 static void _test_signaled(unsigned line, HANDLE handle)
125 DWORD res = WaitForSingleObject(handle, 0);
126 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
129 #define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
130 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)
132 DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
133 BOOL res;
135 res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
136 ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
137 ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
138 ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
139 ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
140 ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
143 static void test_CreateNamedPipe(int pipemode)
145 HANDLE hnp;
146 HANDLE hFile;
147 static const char obuf[] = "Bit Bucket";
148 static const char obuf2[] = "More bits";
149 char ibuf[32], *pbuf;
150 DWORD written;
151 DWORD readden;
152 DWORD avail;
153 DWORD left;
154 DWORD lpmode;
155 BOOL ret;
157 if (pipemode == PIPE_TYPE_BYTE)
158 trace("test_CreateNamedPipe starting in byte mode\n");
159 else
160 trace("test_CreateNamedPipe starting in message mode\n");
162 /* Wait for nonexistent pipe */
163 ret = WaitNamedPipeA(PIPENAME, 2000);
164 ok(ret == 0, "WaitNamedPipe returned %d for nonexistent pipe\n", ret);
165 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
167 /* Bad parameter checks */
168 hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
169 /* nMaxInstances */ 1,
170 /* nOutBufSize */ 1024,
171 /* nInBufSize */ 1024,
172 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
173 /* lpSecurityAttrib */ NULL);
174 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
175 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
177 if (pipemode == PIPE_TYPE_BYTE)
179 /* Bad parameter checks */
180 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
181 /* nMaxInstances */ 1,
182 /* nOutBufSize */ 1024,
183 /* nInBufSize */ 1024,
184 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
185 /* lpSecurityAttrib */ NULL);
186 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
187 "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
190 hnp = CreateNamedPipeA(NULL,
191 PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
192 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
193 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
194 "CreateNamedPipe should fail if name is NULL\n");
196 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
197 ok(hFile == INVALID_HANDLE_VALUE
198 && GetLastError() == ERROR_FILE_NOT_FOUND,
199 "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
201 /* Functional checks */
203 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
204 /* nMaxInstances */ 1,
205 /* nOutBufSize */ 1024,
206 /* nInBufSize */ 1024,
207 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
208 /* lpSecurityAttrib */ NULL);
209 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
210 test_signaled(hnp);
212 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
213 todo_wine
214 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
215 ret, GetLastError());
217 ret = WaitNamedPipeA(PIPENAME, 2000);
218 ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
220 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
221 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
223 ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
225 ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
227 /* Test ConnectNamedPipe() in both directions */
228 ok(!ConnectNamedPipe(hnp, NULL), "ConnectNamedPipe(server) succeeded\n");
229 ok(GetLastError() == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", GetLastError());
230 ok(!ConnectNamedPipe(hFile, NULL), "ConnectNamedPipe(client) succeeded\n");
231 ok(GetLastError() == ERROR_INVALID_FUNCTION, "expected ERROR_INVALID_FUNCTION, got %u\n", GetLastError());
233 /* don't try to do i/o if one side couldn't be opened, as it hangs */
234 if (hFile != INVALID_HANDLE_VALUE) {
235 HANDLE hFile2;
237 /* Make sure we can read and write a few bytes in both directions */
238 memset(ibuf, 0, sizeof(ibuf));
239 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
240 ok(written == sizeof(obuf), "write file len\n");
241 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
242 ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
243 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
245 memset(ibuf, 0, sizeof(ibuf));
246 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
247 ok(written == sizeof(obuf2), "write file len\n");
248 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
249 ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
250 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
252 /* Now the same again, but with an additional call to PeekNamedPipe */
253 memset(ibuf, 0, sizeof(ibuf));
254 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
255 ok(written == sizeof(obuf), "write file len 1\n");
256 ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
257 ok(avail == sizeof(obuf), "peek 1 got %d bytes\n", avail);
258 if (pipemode == PIPE_TYPE_BYTE)
259 ok(left == 0, "peek 1 got %d bytes left\n", left);
260 else
261 ok(left == sizeof(obuf), "peek 1 got %d bytes left\n", left);
262 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
263 ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
264 ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
266 memset(ibuf, 0, sizeof(ibuf));
267 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
268 ok(written == sizeof(obuf2), "write file len 2\n");
269 ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
270 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
271 if (pipemode == PIPE_TYPE_BYTE)
272 ok(left == 0, "peek 2 got %d bytes left\n", left);
273 else
274 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
275 ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
276 ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
277 if (pipemode == PIPE_TYPE_BYTE)
278 ok(left == 0, "peek 2 got %d bytes left\n", left);
279 else
280 ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
281 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
282 ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
283 ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
285 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
286 memset(ibuf, 0, sizeof(ibuf));
287 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
288 ok(written == sizeof(obuf2), "write file len\n");
289 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
290 ok(readden == 4, "peek got %d bytes\n", readden);
291 ok(avail == sizeof(obuf2), "peek got %d bytes available\n", avail);
292 if (pipemode == PIPE_TYPE_BYTE)
293 ok(left == -4, "peek got %d bytes left\n", left);
294 else
295 ok(left == sizeof(obuf2)-4, "peek got %d bytes left\n", left);
296 ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
297 ok(readden == 4, "read got %d bytes\n", readden);
298 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
299 ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
300 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
302 memset(ibuf, 0, sizeof(ibuf));
303 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
304 ok(written == sizeof(obuf), "write file len\n");
305 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
306 ok(readden == 4, "peek got %d bytes\n", readden);
307 ok(avail == sizeof(obuf), "peek got %d bytes available\n", avail);
308 if (pipemode == PIPE_TYPE_BYTE)
310 ok(left == -4, "peek got %d bytes left\n", left);
311 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
313 else
315 ok(left == sizeof(obuf)-4, "peek got %d bytes left\n", left);
316 SetLastError(0xdeadbeef);
317 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
318 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
320 ok(readden == 4, "read got %d bytes\n", readden);
321 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
322 ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden);
323 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
325 /* Similar to above, but use a read buffer size small enough to read in three parts */
326 memset(ibuf, 0, sizeof(ibuf));
327 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
328 ok(written == sizeof(obuf2), "write file len\n");
329 if (pipemode == PIPE_TYPE_BYTE)
331 ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
332 ok(readden == 4, "read got %d bytes\n", readden);
333 ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
335 else
337 SetLastError(0xdeadbeef);
338 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
339 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
340 ok(readden == 4, "read got %d bytes\n", readden);
341 SetLastError(0xdeadbeef);
342 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
343 ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
345 ok(readden == 4, "read got %d bytes\n", readden);
346 ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n");
347 ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
348 ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
350 /* Test reading of multiple writes */
351 memset(ibuf, 0, sizeof(ibuf));
352 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
353 ok(written == sizeof(obuf), "write file len 3a\n");
354 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
355 ok(written == sizeof(obuf2), "write file len 3b\n");
356 ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
357 ok(readden == 4, "peek3 got %d bytes\n", readden);
358 if (pipemode == PIPE_TYPE_BYTE)
359 ok(left == -4, "peek3 got %d bytes left\n", left);
360 else
361 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
362 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
363 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
364 if (pipemode == PIPE_TYPE_BYTE) {
365 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
366 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %d bytes left\n", left);
368 else
370 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
371 ok(left == 0, "peek3 got %d bytes left\n", left);
373 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
374 pbuf = ibuf;
375 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
376 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
377 pbuf += sizeof(obuf);
378 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
380 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
381 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
382 pbuf = ibuf;
383 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
384 pbuf += sizeof(obuf);
385 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
387 /* Multiple writes in the reverse direction */
388 memset(ibuf, 0, sizeof(ibuf));
389 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
390 ok(written == sizeof(obuf), "write file len 4a\n");
391 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
392 ok(written == sizeof(obuf2), "write file len 4b\n");
393 ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
394 ok(readden == 4, "peek3 got %d bytes\n", readden);
395 if (pipemode == PIPE_TYPE_BYTE)
396 ok(left == -4, "peek3 got %d bytes left\n", left);
397 else
398 ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
399 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
400 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
401 if (pipemode == PIPE_TYPE_BYTE) {
402 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
403 ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %d bytes left\n", left);
405 else
407 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
408 ok(left == 0, "peek4 got %d bytes left\n", left);
410 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
411 pbuf = ibuf;
412 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
413 if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
414 pbuf += sizeof(obuf);
415 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
417 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
418 if (pipemode == PIPE_TYPE_BYTE) {
419 ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
421 else {
422 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
424 pbuf = ibuf;
425 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
426 if (pipemode == PIPE_TYPE_BYTE) {
427 pbuf += sizeof(obuf);
428 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
431 /* Test reading of multiple writes after a mode change
432 (CreateFile always creates a byte mode pipe) */
433 lpmode = PIPE_READMODE_MESSAGE;
434 if (pipemode == PIPE_TYPE_BYTE) {
435 /* trying to change the client end of a byte pipe to message mode should fail */
436 ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
438 else {
439 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
441 memset(ibuf, 0, sizeof(ibuf));
442 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
443 ok(written == sizeof(obuf), "write file len 3a\n");
444 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
445 ok(written == sizeof(obuf2), "write file len 3b\n");
446 ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
447 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
448 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
449 ok(left == 0, "peek5 got %d bytes left\n", left);
450 pbuf = ibuf;
451 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
452 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
453 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
454 pbuf = ibuf;
455 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
456 if (readden <= sizeof(obuf))
457 ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
459 /* Multiple writes in the reverse direction */
460 /* the write of obuf2 from write4 should still be in the buffer */
461 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
462 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
463 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
464 if (avail > 0) {
465 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
466 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
467 pbuf = ibuf;
468 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
470 memset(ibuf, 0, sizeof(ibuf));
471 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
472 ok(written == sizeof(obuf), "write file len 6a\n");
473 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
474 ok(written == sizeof(obuf2), "write file len 6b\n");
475 ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
476 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
478 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
479 pbuf = ibuf;
480 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
481 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
482 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
483 pbuf = ibuf;
484 ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
485 if (readden <= sizeof(obuf))
486 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
488 /* Test how ReadFile behaves when the buffer is not big enough for the whole message */
489 memset(ibuf, 0, sizeof(ibuf));
490 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
491 ok(written == sizeof(obuf2), "write file len 7\n");
492 SetLastError(0xdeadbeef);
493 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
494 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
495 ok(readden == 4, "read got %d bytes 7\n", readden);
496 ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
497 ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden);
498 ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n");
500 memset(ibuf, 0, sizeof(ibuf));
501 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
502 ok(written == sizeof(obuf), "write file len 8\n");
503 SetLastError(0xdeadbeef);
504 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
505 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
506 ok(readden == 4, "read got %d bytes 8\n", readden);
507 ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
508 ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
509 ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
511 /* The following test shows that when doing a partial read of a message, the rest
512 * is still in the pipe, and can be received from a second thread. This shows
513 * especially that the content is _not_ stored in thread-local-storage until it is
514 * completely transmitted. The same method works even across multiple processes. */
515 memset(ibuf, 0, sizeof(ibuf));
516 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
517 ok(written == sizeof(obuf), "write file len 9\n");
518 ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
519 ok(written == sizeof(obuf2), "write file len 9\n");
520 SetLastError(0xdeadbeef);
521 ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
522 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
523 ok(readden == 4, "read got %d bytes 9\n", readden);
524 SetLastError(0xdeadbeef);
525 ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
526 ok(!ret, "RpcReadFile 9\n");
527 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
528 ok(readden == 4, "read got %d bytes 9\n", readden);
529 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
530 ok(ret, "RpcReadFile 9\n");
531 ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
532 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
533 if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
535 memset(ibuf, 0, sizeof(ibuf));
536 SetLastError(0xdeadbeef);
537 ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
538 ok(!ret, "RpcReadFile 9\n");
539 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
540 ok(readden == 4, "read got %d bytes 9\n", readden);
541 SetLastError(0xdeadbeef);
542 ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
543 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
544 ok(readden == 4, "read got %d bytes 9\n", readden);
545 ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
546 ok(ret, "RpcReadFile 9\n");
547 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
548 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
551 /* Now the reverse direction */
552 memset(ibuf, 0, sizeof(ibuf));
553 ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
554 ok(written == sizeof(obuf2), "write file len 10\n");
555 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
556 ok(written == sizeof(obuf), "write file len 10\n");
557 SetLastError(0xdeadbeef);
558 ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
559 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
560 ok(readden == 4, "read got %d bytes 10\n", readden);
561 SetLastError(0xdeadbeef);
562 ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
563 ok(!ret, "RpcReadFile 10\n");
564 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
565 ok(readden == 4, "read got %d bytes 10\n", readden);
566 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
567 ok(ret, "RpcReadFile 10\n");
568 ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
569 ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
570 if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
572 memset(ibuf, 0, sizeof(ibuf));
573 SetLastError(0xdeadbeef);
574 ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
575 ok(!ret, "RpcReadFile 10\n");
576 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
577 ok(readden == 4, "read got %d bytes 10\n", readden);
578 SetLastError(0xdeadbeef);
579 ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
580 ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
581 ok(readden == 4, "read got %d bytes 10\n", readden);
582 ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
583 ok(ret, "RpcReadFile 10\n");
584 ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
585 ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
590 /* Picky conformance tests */
592 /* Verify that you can't connect to pipe again
593 * until server calls DisconnectNamedPipe+ConnectNamedPipe
594 * or creates a new pipe
595 * case 1: other client not yet closed
597 hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
598 ok(hFile2 == INVALID_HANDLE_VALUE,
599 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
600 ok(GetLastError() == ERROR_PIPE_BUSY,
601 "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
603 ok(CloseHandle(hFile), "CloseHandle\n");
605 /* case 2: other client already closed */
606 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
607 ok(hFile == INVALID_HANDLE_VALUE,
608 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
609 ok(GetLastError() == ERROR_PIPE_BUSY,
610 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
612 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
614 /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
615 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
616 ok(hFile == INVALID_HANDLE_VALUE,
617 "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
618 ok(GetLastError() == ERROR_PIPE_BUSY,
619 "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
621 /* to be complete, we'd call ConnectNamedPipe here and loop,
622 * but by default that's blocking, so we'd either have
623 * to turn on the uncommon nonblocking mode, or
624 * use another thread.
628 ok(CloseHandle(hnp), "CloseHandle\n");
630 if (winetest_debug > 1) trace("test_CreateNamedPipe returning\n");
633 static void test_CreateNamedPipe_instances_must_match(void)
635 HANDLE hnp, hnp2;
637 /* Check no mismatch */
638 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
639 /* nMaxInstances */ 2,
640 /* nOutBufSize */ 1024,
641 /* nInBufSize */ 1024,
642 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
643 /* lpSecurityAttrib */ NULL);
644 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
646 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
647 /* nMaxInstances */ 2,
648 /* nOutBufSize */ 1024,
649 /* nInBufSize */ 1024,
650 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
651 /* lpSecurityAttrib */ NULL);
652 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
654 ok(CloseHandle(hnp), "CloseHandle\n");
655 ok(CloseHandle(hnp2), "CloseHandle\n");
657 /* Check nMaxInstances */
658 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
659 /* nMaxInstances */ 1,
660 /* nOutBufSize */ 1024,
661 /* nInBufSize */ 1024,
662 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
663 /* lpSecurityAttrib */ NULL);
664 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
666 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
667 /* nMaxInstances */ 1,
668 /* nOutBufSize */ 1024,
669 /* nInBufSize */ 1024,
670 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
671 /* lpSecurityAttrib */ NULL);
672 ok(hnp2 == INVALID_HANDLE_VALUE
673 && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
675 ok(CloseHandle(hnp), "CloseHandle\n");
677 /* Check PIPE_ACCESS_* */
678 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
679 /* nMaxInstances */ 2,
680 /* nOutBufSize */ 1024,
681 /* nInBufSize */ 1024,
682 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
683 /* lpSecurityAttrib */ NULL);
684 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
686 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
687 /* nMaxInstances */ 2,
688 /* nOutBufSize */ 1024,
689 /* nInBufSize */ 1024,
690 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
691 /* lpSecurityAttrib */ NULL);
692 ok(hnp2 == INVALID_HANDLE_VALUE
693 && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
695 ok(CloseHandle(hnp), "CloseHandle\n");
697 /* check everything else */
698 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
699 /* nMaxInstances */ 4,
700 /* nOutBufSize */ 1024,
701 /* nInBufSize */ 1024,
702 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
703 /* lpSecurityAttrib */ NULL);
704 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
706 hnp2 = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
707 /* nMaxInstances */ 3,
708 /* nOutBufSize */ 102,
709 /* nInBufSize */ 24,
710 /* nDefaultWait */ 1234,
711 /* lpSecurityAttrib */ NULL);
712 ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
714 ok(CloseHandle(hnp), "CloseHandle\n");
715 ok(CloseHandle(hnp2), "CloseHandle\n");
718 /** implementation of alarm() */
719 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
721 DWORD_PTR timeout = (DWORD_PTR) arg;
722 if (winetest_debug > 1) trace("alarmThreadMain\n");
723 if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
725 ok(FALSE, "alarm\n");
726 ExitProcess(1);
728 return 1;
731 static HANDLE hnp = INVALID_HANDLE_VALUE;
733 /** Trivial byte echo server - disconnects after each session */
734 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
736 int i;
738 if (winetest_debug > 1) trace("serverThreadMain1 start\n");
739 /* Set up a simple echo server */
740 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
741 PIPE_TYPE_BYTE | PIPE_WAIT,
742 /* nMaxInstances */ 1,
743 /* nOutBufSize */ 1024,
744 /* nInBufSize */ 1024,
745 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
746 /* lpSecurityAttrib */ NULL);
748 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
749 for (i = 0; i < NB_SERVER_LOOPS; i++) {
750 char buf[512];
751 DWORD written;
752 DWORD readden;
753 BOOL success;
755 /* Wait for client to connect */
756 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
757 ok(ConnectNamedPipe(hnp, NULL)
758 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
759 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
761 /* Echo bytes once */
762 memset(buf, 0, sizeof(buf));
764 if (winetest_debug > 1) trace("Server reading...\n");
765 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
766 if (winetest_debug > 1) trace("Server done reading.\n");
767 ok(success, "ReadFile\n");
768 ok(readden, "short read\n");
770 if (winetest_debug > 1) trace("Server writing...\n");
771 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
772 if (winetest_debug > 1) trace("Server done writing.\n");
773 ok(written == readden, "write file len\n");
775 /* finish this connection, wait for next one */
776 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
777 if (winetest_debug > 1) trace("Server done flushing.\n");
778 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
779 if (winetest_debug > 1) trace("Server done disconnecting.\n");
781 return 0;
784 /** Trivial byte echo server - closes after each connection */
785 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
787 int i;
788 HANDLE hnpNext = 0;
790 trace("serverThreadMain2\n");
791 /* Set up a simple echo server */
792 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
793 PIPE_TYPE_BYTE | PIPE_WAIT,
794 /* nMaxInstances */ 2,
795 /* nOutBufSize */ 1024,
796 /* nInBufSize */ 1024,
797 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
798 /* lpSecurityAttrib */ NULL);
799 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
801 for (i = 0; i < NB_SERVER_LOOPS; i++) {
802 char buf[512];
803 DWORD written;
804 DWORD readden;
805 DWORD ret;
806 BOOL success;
809 user_apc_ran = FALSE;
810 if (i == 0 && pQueueUserAPC) {
811 if (winetest_debug > 1) trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
812 ret = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
813 ok(ret, "QueueUserAPC failed: %d\n", GetLastError());
816 /* Wait for client to connect */
817 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
818 ok(ConnectNamedPipe(hnp, NULL)
819 || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
820 if (winetest_debug > 1) trace("ConnectNamedPipe returned.\n");
822 /* Echo bytes once */
823 memset(buf, 0, sizeof(buf));
825 if (winetest_debug > 1) trace("Server reading...\n");
826 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
827 if (winetest_debug > 1) trace("Server done reading.\n");
828 ok(success, "ReadFile\n");
830 if (winetest_debug > 1) trace("Server writing...\n");
831 ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
832 if (winetest_debug > 1) trace("Server done writing.\n");
833 ok(written == readden, "write file len\n");
835 /* finish this connection, wait for next one */
836 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
837 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
839 ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
841 if (i == 0 && pQueueUserAPC)
842 SleepEx(0, TRUE); /* get rid of apc */
844 /* Set up next echo server */
845 hnpNext =
846 CreateNamedPipeA(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
847 PIPE_TYPE_BYTE | PIPE_WAIT,
848 /* nMaxInstances */ 2,
849 /* nOutBufSize */ 1024,
850 /* nInBufSize */ 1024,
851 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
852 /* lpSecurityAttrib */ NULL);
854 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
856 ok(CloseHandle(hnp), "CloseHandle\n");
857 hnp = hnpNext;
859 return 0;
862 /** Trivial byte echo server - uses overlapped named pipe calls */
863 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
865 int i;
866 HANDLE hEvent;
868 if (winetest_debug > 1) trace("serverThreadMain3\n");
869 /* Set up a simple echo server */
870 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
871 PIPE_TYPE_BYTE | PIPE_WAIT,
872 /* nMaxInstances */ 1,
873 /* nOutBufSize */ 1024,
874 /* nInBufSize */ 1024,
875 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
876 /* lpSecurityAttrib */ NULL);
877 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
879 hEvent = CreateEventW(NULL, /* security attribute */
880 TRUE, /* manual reset event */
881 FALSE, /* initial state */
882 NULL); /* name */
883 ok(hEvent != NULL, "CreateEvent\n");
885 for (i = 0; i < NB_SERVER_LOOPS; i++) {
886 char buf[512];
887 DWORD written;
888 DWORD readden;
889 DWORD dummy;
890 BOOL success;
891 OVERLAPPED oOverlap;
892 int letWFSOEwait = (i & 2);
893 int letGORwait = (i & 1);
894 DWORD err;
896 memset(&oOverlap, 0, sizeof(oOverlap));
897 oOverlap.hEvent = hEvent;
899 /* Wait for client to connect */
900 if (i == 0) {
901 if (winetest_debug > 1) trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
902 success = ConnectNamedPipe(hnp, NULL);
903 err = GetLastError();
904 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
905 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
906 } else {
907 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
908 success = ConnectNamedPipe(hnp, &oOverlap);
909 err = GetLastError();
910 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
911 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe returned.\n");
912 if (!success && (err == ERROR_IO_PENDING)) {
913 if (letWFSOEwait)
915 DWORD ret;
916 do {
917 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
918 } while (ret == WAIT_IO_COMPLETION);
919 ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
921 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
922 if (!letGORwait && !letWFSOEwait && !success) {
923 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
924 success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
927 ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
928 if (winetest_debug > 1) trace("overlapped ConnectNamedPipe operation complete.\n");
931 /* Echo bytes once */
932 memset(buf, 0, sizeof(buf));
934 if (winetest_debug > 1) trace("Server reading...\n");
935 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
936 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
937 err = GetLastError();
938 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
939 if (winetest_debug > 1) trace("overlapped ReadFile returned.\n");
940 if (!success && (err == ERROR_IO_PENDING)) {
941 if (letWFSOEwait)
943 DWORD ret;
944 do {
945 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
946 } while (ret == WAIT_IO_COMPLETION);
947 ok(ret == 0, "wait ReadFile returned %x\n", ret);
949 success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
950 if (!letGORwait && !letWFSOEwait && !success) {
951 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
952 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
955 if (winetest_debug > 1) trace("Server done reading.\n");
956 ok(success, "overlapped ReadFile\n");
958 if (winetest_debug > 1) trace("Server writing...\n");
959 success = WriteFile(hnp, buf, readden, &written, &oOverlap);
960 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
961 err = GetLastError();
962 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
963 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
964 if (!success && (err == ERROR_IO_PENDING)) {
965 if (letWFSOEwait)
967 DWORD ret;
968 do {
969 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
970 } while (ret == WAIT_IO_COMPLETION);
971 ok(ret == 0, "wait WriteFile returned %x\n", ret);
973 success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
974 if (!letGORwait && !letWFSOEwait && !success) {
975 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
976 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
979 if (winetest_debug > 1) trace("Server done writing.\n");
980 ok(success, "overlapped WriteFile\n");
981 ok(written == readden, "write file len\n");
983 /* finish this connection, wait for next one */
984 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
985 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
987 return 0;
990 /** Trivial byte echo server - uses i/o completion ports */
991 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
993 int i;
994 HANDLE hcompletion;
995 BOOL ret;
997 if (winetest_debug > 1) trace("serverThreadMain4\n");
998 /* Set up a simple echo server */
999 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1000 PIPE_TYPE_BYTE | PIPE_WAIT,
1001 /* nMaxInstances */ 1,
1002 /* nOutBufSize */ 1024,
1003 /* nInBufSize */ 1024,
1004 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1005 /* lpSecurityAttrib */ NULL);
1006 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1008 hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
1009 ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
1011 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1012 char buf[512];
1013 DWORD written;
1014 DWORD readden;
1015 DWORD dummy;
1016 BOOL success;
1017 OVERLAPPED oConnect;
1018 OVERLAPPED oRead;
1019 OVERLAPPED oWrite;
1020 OVERLAPPED *oResult;
1021 DWORD err;
1022 ULONG_PTR compkey;
1024 memset(&oConnect, 0, sizeof(oConnect));
1025 memset(&oRead, 0, sizeof(oRead));
1026 memset(&oWrite, 0, sizeof(oWrite));
1028 /* Wait for client to connect */
1029 if (winetest_debug > 1) trace("Server calling overlapped ConnectNamedPipe...\n");
1030 success = ConnectNamedPipe(hnp, &oConnect);
1031 err = GetLastError();
1032 ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
1033 "overlapped ConnectNamedPipe got %u err %u\n", success, err );
1034 if (!success && err == ERROR_IO_PENDING) {
1035 if (winetest_debug > 1) trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
1036 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
1037 if (!success)
1039 ok( GetLastError() == WAIT_TIMEOUT,
1040 "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
1041 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
1043 ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1044 if (success)
1046 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1047 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
1050 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, &oRead);
1057 if (winetest_debug > 1) trace("Server ReadFile returned...\n");
1058 err = GetLastError();
1059 ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
1060 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1061 &oResult, 10000);
1062 ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1063 if (success)
1065 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1066 ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
1068 if (winetest_debug > 1) trace("Server done reading.\n");
1070 if (winetest_debug > 1) trace("Server writing...\n");
1071 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1072 if (winetest_debug > 1) trace("Server WriteFile returned...\n");
1073 err = GetLastError();
1074 ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
1075 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1076 &oResult, 10000);
1077 ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
1078 if (success)
1080 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
1081 ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
1082 ok(written == readden, "write file len\n");
1084 if (winetest_debug > 1) trace("Server done writing.\n");
1086 /* Client will finish this connection, the following ops will trigger broken pipe errors. */
1088 /* Wait for the pipe to break. */
1089 while (PeekNamedPipe(hnp, NULL, 0, NULL, &written, &written));
1091 if (winetest_debug > 1) trace("Server writing on disconnected pipe...\n");
1092 SetLastError(ERROR_SUCCESS);
1093 success = WriteFile(hnp, buf, readden, &written, &oWrite);
1094 err = GetLastError();
1095 todo_wine_if (!success && err == ERROR_PIPE_NOT_CONNECTED) ok(!success && err == ERROR_NO_DATA,
1096 "overlapped WriteFile on disconnected pipe returned %u, err=%i\n", success, err);
1098 /* No completion status is queued on immediate error. */
1099 SetLastError(ERROR_SUCCESS);
1100 oResult = (OVERLAPPED *)0xdeadbeef;
1101 success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
1102 &oResult, 0);
1103 err = GetLastError();
1104 ok(!success && err == WAIT_TIMEOUT && !oResult,
1105 "WriteFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1106 success, err, oResult);
1108 if (winetest_debug > 1) trace("Server reading from disconnected pipe...\n");
1109 SetLastError(ERROR_SUCCESS);
1110 success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
1111 if (winetest_debug > 1) trace("Server ReadFile from disconnected pipe returned...\n");
1112 err = GetLastError();
1113 ok(!success && err == ERROR_BROKEN_PIPE,
1114 "overlapped ReadFile on disconnected pipe returned %u, err=%i\n", success, err);
1116 SetLastError(ERROR_SUCCESS);
1117 oResult = (OVERLAPPED *)0xdeadbeef;
1118 success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
1119 &oResult, 0);
1120 err = GetLastError();
1121 ok(!success && err == WAIT_TIMEOUT && !oResult,
1122 "ReadFile GetQueuedCompletionStatus returned %u, err=%i, oResult %p\n",
1123 success, err, oResult);
1125 /* finish this connection, wait for next one */
1126 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1127 success = DisconnectNamedPipe(hnp);
1128 ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
1131 ret = CloseHandle(hnp);
1132 ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
1133 ret = CloseHandle(hcompletion);
1134 ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
1136 return 0;
1139 static int completion_called;
1140 static DWORD completion_errorcode;
1141 static DWORD completion_num_bytes;
1142 static LPOVERLAPPED completion_lpoverlapped;
1144 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
1146 completion_called++;
1147 completion_errorcode = errorcode;
1148 completion_num_bytes = num_bytes;
1149 completion_lpoverlapped = lpoverlapped;
1150 SetEvent(lpoverlapped->hEvent);
1153 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
1154 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
1156 int i;
1157 HANDLE hEvent;
1159 if (winetest_debug > 1) trace("serverThreadMain5\n");
1160 /* Set up a simple echo server */
1161 hnp = CreateNamedPipeA(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
1162 PIPE_TYPE_BYTE | PIPE_WAIT,
1163 /* nMaxInstances */ 1,
1164 /* nOutBufSize */ 1024,
1165 /* nInBufSize */ 1024,
1166 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1167 /* lpSecurityAttrib */ NULL);
1168 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
1170 hEvent = CreateEventW(NULL, /* security attribute */
1171 TRUE, /* manual reset event */
1172 FALSE, /* initial state */
1173 NULL); /* name */
1174 ok(hEvent != NULL, "CreateEvent\n");
1176 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1177 char buf[512];
1178 DWORD readden;
1179 BOOL success;
1180 OVERLAPPED oOverlap;
1181 DWORD err;
1183 memset(&oOverlap, 0, sizeof(oOverlap));
1184 oOverlap.hEvent = hEvent;
1186 /* Wait for client to connect */
1187 if (winetest_debug > 1) trace("Server calling ConnectNamedPipe...\n");
1188 success = ConnectNamedPipe(hnp, NULL);
1189 err = GetLastError();
1190 ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
1191 if (winetest_debug > 1) trace("ConnectNamedPipe operation complete.\n");
1193 /* Echo bytes once */
1194 memset(buf, 0, sizeof(buf));
1196 if (winetest_debug > 1) trace("Server reading...\n");
1197 completion_called = 0;
1198 ResetEvent(hEvent);
1199 success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
1200 if (winetest_debug > 1) trace("Server ReadFileEx returned...\n");
1201 ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
1202 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1203 if (winetest_debug > 1) trace("ReadFileEx returned.\n");
1204 if (success) {
1205 DWORD ret;
1206 do {
1207 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1208 } while (ret == WAIT_IO_COMPLETION);
1209 ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
1211 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1212 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1213 ok(completion_num_bytes != 0, "read 0 bytes\n");
1214 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1215 readden = completion_num_bytes;
1216 if (winetest_debug > 1) trace("Server done reading.\n");
1218 if (winetest_debug > 1) trace("Server writing...\n");
1219 completion_called = 0;
1220 ResetEvent(hEvent);
1221 success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
1222 if (winetest_debug > 1) trace("Server WriteFileEx returned...\n");
1223 ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
1224 ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
1225 if (winetest_debug > 1) trace("overlapped WriteFile returned.\n");
1226 if (success) {
1227 DWORD ret;
1228 do {
1229 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
1230 } while (ret == WAIT_IO_COMPLETION);
1231 ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
1233 if (winetest_debug > 1) trace("Server done writing.\n");
1234 ok(completion_called == 1, "completion routine called %i times\n", completion_called);
1235 ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
1236 ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
1237 ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
1239 /* finish this connection, wait for next one */
1240 ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
1241 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
1243 return 0;
1246 static void exercizeServer(const char *pipename, HANDLE serverThread)
1248 int i;
1250 if (winetest_debug > 1) trace("exercizeServer starting\n");
1251 for (i = 0; i < NB_SERVER_LOOPS; i++) {
1252 HANDLE hFile=INVALID_HANDLE_VALUE;
1253 static const char obuf[] = "Bit Bucket";
1254 char ibuf[32];
1255 DWORD written;
1256 DWORD readden;
1257 int loop;
1259 for (loop = 0; loop < 3; loop++) {
1260 DWORD err;
1261 if (winetest_debug > 1) trace("Client connecting...\n");
1262 /* Connect to the server */
1263 hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
1264 NULL, OPEN_EXISTING, 0, 0);
1265 if (hFile != INVALID_HANDLE_VALUE)
1266 break;
1267 err = GetLastError();
1268 if (loop == 0)
1269 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
1270 else
1271 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
1272 if (winetest_debug > 1) trace("connect failed, retrying\n");
1273 Sleep(200);
1275 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
1277 /* Make sure it can echo */
1278 memset(ibuf, 0, sizeof(ibuf));
1279 if (winetest_debug > 1) trace("Client writing...\n");
1280 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
1281 ok(written == sizeof(obuf), "write file len\n");
1282 if (winetest_debug > 1) trace("Client reading...\n");
1283 ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
1284 ok(readden == sizeof(obuf), "read file len\n");
1285 ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
1287 if (winetest_debug > 1) trace("Client closing...\n");
1288 ok(CloseHandle(hFile), "CloseHandle\n");
1291 ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
1292 CloseHandle(hnp);
1293 if (winetest_debug > 1) trace("exercizeServer returning\n");
1296 static void test_NamedPipe_2(void)
1298 HANDLE serverThread;
1299 DWORD serverThreadId;
1300 HANDLE alarmThread;
1301 DWORD alarmThreadId;
1303 trace("test_NamedPipe_2 starting\n");
1304 /* Set up a twenty second timeout */
1305 alarm_event = CreateEventW( NULL, TRUE, FALSE, NULL );
1306 SetLastError(0xdeadbeef);
1307 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
1308 ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
1310 /* The servers we're about to exercise do try to clean up carefully,
1311 * but to reduce the chance of a test failure due to a pipe handle
1312 * leak in the test code, we'll use a different pipe name for each server.
1315 /* Try server #1 */
1316 SetLastError(0xdeadbeef);
1317 serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
1318 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1319 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
1321 /* Try server #2 */
1322 SetLastError(0xdeadbeef);
1323 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
1324 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1325 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
1327 /* Try server #3 */
1328 SetLastError(0xdeadbeef);
1329 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
1330 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1331 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
1333 /* Try server #4 */
1334 SetLastError(0xdeadbeef);
1335 serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
1336 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1337 exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1339 /* Try server #5 */
1340 SetLastError(0xdeadbeef);
1341 serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1342 ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1343 exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1345 ok(SetEvent( alarm_event ), "SetEvent\n");
1346 CloseHandle( alarm_event );
1347 if (winetest_debug > 1) trace("test_NamedPipe_2 returning\n");
1350 static int test_DisconnectNamedPipe(void)
1352 HANDLE hnp;
1353 HANDLE hFile;
1354 static const char obuf[] = "Bit Bucket";
1355 char ibuf[32];
1356 DWORD written;
1357 DWORD readden;
1358 DWORD ret;
1360 SetLastError(0xdeadbeef);
1361 hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1362 /* nMaxInstances */ 1,
1363 /* nOutBufSize */ 1024,
1364 /* nInBufSize */ 1024,
1365 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1366 /* lpSecurityAttrib */ NULL);
1367 if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1368 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1370 win_skip("Named pipes are not implemented\n");
1371 return 1;
1374 ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1375 && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1376 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1377 && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1379 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1380 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1382 /* don't try to do i/o if one side couldn't be opened, as it hangs */
1383 if (hFile != INVALID_HANDLE_VALUE) {
1385 /* see what happens if server calls DisconnectNamedPipe
1386 * when there are bytes in the pipe
1389 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1390 ok(written == sizeof(obuf), "write file len\n");
1391 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1392 ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1393 && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1394 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1395 && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1396 "ReadFile from disconnected pipe with bytes waiting\n");
1398 ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1399 "DisconnectNamedPipe worked twice\n");
1400 ret = WaitForSingleObject(hFile, 0);
1401 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1403 ret = PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL);
1404 todo_wine
1405 ok(!ret && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "PeekNamedPipe returned %x (%u)\n",
1406 ret, GetLastError());
1407 ret = PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL);
1408 todo_wine
1409 ok(!ret && GetLastError() == ERROR_BAD_PIPE, "PeekNamedPipe returned %x (%u)\n",
1410 ret, GetLastError());
1411 ok(CloseHandle(hFile), "CloseHandle\n");
1414 ok(CloseHandle(hnp), "CloseHandle\n");
1416 return 0;
1418 static void test_CreatePipe(void)
1420 SECURITY_ATTRIBUTES pipe_attr;
1421 HANDLE piperead, pipewrite;
1422 DWORD written;
1423 DWORD read;
1424 DWORD i, size;
1425 BYTE *buffer;
1426 char readbuf[32];
1428 user_apc_ran = FALSE;
1429 if (pQueueUserAPC)
1430 ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1432 pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
1433 pipe_attr.bInheritHandle = TRUE;
1434 pipe_attr.lpSecurityDescriptor = NULL;
1435 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1436 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
1437 test_pipe_info(pipewrite, 0, 4096, 4096, 1);
1439 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1440 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1441 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1442 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1443 ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1444 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1446 /* Now write another chunk*/
1447 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1448 ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1449 ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1450 /* and close the write end, read should still succeed*/
1451 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1452 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
1453 ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
1454 /* But now we need to get informed that the pipe is closed */
1455 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1456 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1458 /* Try bigger chunks */
1459 size = 32768;
1460 buffer = HeapAlloc( GetProcessHeap(), 0, size );
1461 for (i = 0; i < size; i++) buffer[i] = i;
1462 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1463 ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1464 ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1465 /* and close the write end, read should still succeed*/
1466 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1467 memset( buffer, 0, size );
1468 ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
1469 ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
1470 for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1471 /* But now we need to get informed that the pipe is closed */
1472 ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1473 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1474 HeapFree(GetProcessHeap(), 0, buffer);
1476 ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1477 SleepEx(0, TRUE); /* get rid of apc */
1479 ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
1480 test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
1481 test_pipe_info(pipewrite, 0, 1, 1, 1);
1482 ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1483 ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1486 static void test_CloseHandle(void)
1488 static const char testdata[] = "Hello World";
1489 DWORD state, numbytes;
1490 HANDLE hpipe, hfile;
1491 char buffer[32];
1492 BOOL ret;
1494 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1495 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1496 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1497 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1499 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1500 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1502 numbytes = 0xdeadbeef;
1503 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1504 ok(ret, "WriteFile failed with %u\n", GetLastError());
1505 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1507 numbytes = 0xdeadbeef;
1508 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1509 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1510 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1512 ret = CloseHandle(hpipe);
1513 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1515 numbytes = 0xdeadbeef;
1516 memset(buffer, 0, sizeof(buffer));
1517 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1518 ok(ret, "ReadFile failed with %u\n", GetLastError());
1519 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1521 numbytes = 0xdeadbeef;
1522 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1523 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1524 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1526 numbytes = 0xdeadbeef;
1527 memset(buffer, 0, sizeof(buffer));
1528 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1529 ok(ret, "ReadFile failed with %u\n", GetLastError());
1530 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1532 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1533 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1534 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1535 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1536 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1538 SetLastError(0xdeadbeef);
1539 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1540 ok(!ret, "ReadFile unexpectedly succeeded\n");
1541 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1543 numbytes = 0xdeadbeef;
1544 ret = PeekNamedPipe(hfile, NULL, 0, NULL, &numbytes, NULL);
1545 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1546 ret, GetLastError());
1547 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1549 SetLastError(0xdeadbeef);
1550 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1551 ok(!ret, "WriteFile unexpectedly succeeded\n");
1552 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1554 CloseHandle(hfile);
1556 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1557 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1558 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1559 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1561 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1562 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1564 numbytes = 0xdeadbeef;
1565 ret = WriteFile(hpipe, testdata, 0, &numbytes, NULL);
1566 ok(ret, "WriteFile failed with %u\n", GetLastError());
1567 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1569 ret = CloseHandle(hpipe);
1570 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1572 numbytes = 0xdeadbeef;
1573 memset(buffer, 0, sizeof(buffer));
1574 ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
1575 ok(ret, "ReadFile failed with %u\n", GetLastError());
1576 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1578 SetLastError(0xdeadbeef);
1579 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1580 ok(!ret, "ReadFile unexpectedly succeeded\n");
1581 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1583 ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
1584 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1585 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1586 ret = SetNamedPipeHandleState(hfile, &state, NULL, NULL);
1587 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1589 SetLastError(0xdeadbeef);
1590 ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
1591 ok(!ret, "ReadFile unexpectedly succeeded\n");
1592 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1594 SetLastError(0xdeadbeef);
1595 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1596 ok(!ret, "WriteFile unexpectedly succeeded\n");
1597 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1599 CloseHandle(hfile);
1601 /* repeat test with hpipe <-> hfile swapped */
1603 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1604 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1605 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1606 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1608 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1609 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1611 numbytes = 0xdeadbeef;
1612 ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
1613 ok(ret, "WriteFile failed with %u\n", GetLastError());
1614 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1616 numbytes = 0xdeadbeef;
1617 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1618 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1619 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1621 ret = CloseHandle(hfile);
1622 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1624 numbytes = 0xdeadbeef;
1625 memset(buffer, 0, sizeof(buffer));
1626 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1627 ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
1628 "ReadFile failed with %u\n", GetLastError());
1629 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1631 numbytes = 0xdeadbeef;
1632 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1633 ok(ret, "PeekNamedPipe failed with %u\n", GetLastError());
1634 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1636 numbytes = 0xdeadbeef;
1637 memset(buffer, 0, sizeof(buffer));
1638 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1639 ok(ret, "ReadFile failed with %u\n", GetLastError());
1640 ok(numbytes == sizeof(testdata), "expected sizeof(testdata), got %u\n", numbytes);
1642 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1643 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1644 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1645 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1646 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1648 SetLastError(0xdeadbeef);
1649 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1650 ok(!ret, "ReadFile unexpectedly succeeded\n");
1651 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1653 numbytes = 0xdeadbeef;
1654 ret = PeekNamedPipe(hpipe, NULL, 0, NULL, &numbytes, NULL);
1655 ok(!ret && GetLastError() == ERROR_BROKEN_PIPE, "PeekNamedPipe returned %x (%u)\n",
1656 ret, GetLastError());
1657 ok(numbytes == 0xdeadbeef, "numbytes = %u\n", numbytes);
1659 SetLastError(0xdeadbeef);
1660 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1661 ok(!ret, "WriteFile unexpectedly succeeded\n");
1662 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1664 CloseHandle(hpipe);
1666 hpipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
1667 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1668 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1669 ok(hpipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
1671 hfile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1672 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
1674 numbytes = 0xdeadbeef;
1675 ret = WriteFile(hfile, testdata, 0, &numbytes, NULL);
1676 ok(ret, "WriteFile failed with %u\n", GetLastError());
1677 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1679 ret = CloseHandle(hfile);
1680 ok(ret, "CloseHandle failed with %u\n", GetLastError());
1682 numbytes = 0xdeadbeef;
1683 memset(buffer, 0, sizeof(buffer));
1684 ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
1685 ok(ret, "ReadFile failed with %u\n", GetLastError());
1686 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
1688 SetLastError(0xdeadbeef);
1689 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1690 ok(!ret, "ReadFile unexpectedly succeeded\n");
1691 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1693 ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
1694 ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
1695 state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
1696 ret = SetNamedPipeHandleState(hpipe, &state, NULL, NULL);
1697 ok(ret, "SetNamedPipeHandleState failed with %u\n", GetLastError());
1699 SetLastError(0xdeadbeef);
1700 ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
1701 ok(!ret, "ReadFile unexpectedly succeeded\n");
1702 ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
1704 SetLastError(0xdeadbeef);
1705 ret = WriteFile(hpipe, testdata, sizeof(testdata), &numbytes, NULL);
1706 ok(!ret, "WriteFile unexpectedly succeeded\n");
1707 todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
1709 CloseHandle(hpipe);
1712 struct named_pipe_client_params
1714 DWORD security_flags;
1715 HANDLE token;
1716 BOOL revert;
1719 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1721 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1723 struct named_pipe_client_params *params = p;
1724 HANDLE pipe;
1725 BOOL ret;
1726 const char message[] = "Test";
1727 DWORD bytes_read, bytes_written;
1728 char dummy;
1729 TOKEN_PRIVILEGES *Privileges = NULL;
1731 if (params->token)
1733 if (params->revert)
1735 /* modify the token so we can tell if the pipe impersonation
1736 * token reverts to the process token */
1737 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1738 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1740 ret = SetThreadToken(NULL, params->token);
1741 ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1743 else
1745 DWORD Size = 0;
1746 HANDLE process_token;
1748 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1749 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1751 ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1752 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1753 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1754 ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1755 ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1757 ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1758 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1760 CloseHandle(process_token);
1763 pipe = CreateFileA(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1764 ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1766 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1767 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1769 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1770 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1772 if (params->token)
1774 if (params->revert)
1776 ret = RevertToSelf();
1777 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1779 else
1781 ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1782 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1785 else
1787 HANDLE process_token;
1789 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1790 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1792 ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1793 ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1795 HeapFree(GetProcessHeap(), 0, Privileges);
1797 CloseHandle(process_token);
1800 ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1801 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1803 ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1804 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1806 CloseHandle(pipe);
1808 return 0;
1811 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1813 HANDLE ProcessToken;
1814 HANDLE Token = NULL;
1815 BOOL ret;
1817 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1818 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1820 ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1821 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1823 CloseHandle(ProcessToken);
1825 return Token;
1828 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1830 HANDLE hPipeServer;
1831 BOOL ret;
1832 DWORD dwTid;
1833 HANDLE hThread;
1834 char buffer[256];
1835 DWORD dwBytesRead;
1836 DWORD error;
1837 struct named_pipe_client_params params;
1838 char dummy = 0;
1839 DWORD dwBytesWritten;
1840 HANDLE hToken = NULL;
1841 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1842 DWORD size;
1844 hPipeServer = CreateNamedPipeA(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1845 ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1847 params.security_flags = security_flags;
1848 params.token = hClientToken;
1849 params.revert = revert;
1850 hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1851 ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1853 SetLastError(0xdeadbeef);
1854 ret = ImpersonateNamedPipeClient(hPipeServer);
1855 error = GetLastError();
1856 ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1857 "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1859 ret = ConnectNamedPipe(hPipeServer, NULL);
1860 ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1862 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1863 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1865 ret = ImpersonateNamedPipeClient(hPipeServer);
1866 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1868 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1869 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1871 (*test_func)(0, hToken);
1873 ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1874 ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1875 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1876 ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1878 CloseHandle(hToken);
1880 RevertToSelf();
1882 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1883 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1885 ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1886 ok(ret, "ReadFile failed with error %d\n", GetLastError());
1888 ret = ImpersonateNamedPipeClient(hPipeServer);
1889 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1891 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1892 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1894 (*test_func)(1, hToken);
1896 CloseHandle(hToken);
1898 RevertToSelf();
1900 ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1901 ok(ret, "WriteFile failed with error %d\n", GetLastError());
1903 WaitForSingleObject(hThread, INFINITE);
1905 ret = ImpersonateNamedPipeClient(hPipeServer);
1906 ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1908 RevertToSelf();
1910 CloseHandle(hThread);
1911 CloseHandle(hPipeServer);
1914 static BOOL are_all_privileges_disabled(HANDLE hToken)
1916 BOOL ret;
1917 TOKEN_PRIVILEGES *Privileges = NULL;
1918 DWORD Size = 0;
1919 BOOL all_privs_disabled = TRUE;
1920 DWORD i;
1922 ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1923 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1925 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1926 ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1927 if (!ret)
1929 HeapFree(GetProcessHeap(), 0, Privileges);
1930 return FALSE;
1933 else
1934 return FALSE;
1936 for (i = 0; i < Privileges->PrivilegeCount; i++)
1938 if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1940 all_privs_disabled = FALSE;
1941 break;
1945 HeapFree(GetProcessHeap(), 0, Privileges);
1947 return all_privs_disabled;
1950 static DWORD get_privilege_count(HANDLE hToken)
1952 TOKEN_STATISTICS Statistics;
1953 DWORD Size = sizeof(Statistics);
1954 BOOL ret;
1956 ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1957 ok(ret, "GetTokenInformation(TokenStatistics)\n");
1958 if (!ret) return -1;
1960 return Statistics.PrivilegeCount;
1963 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1965 DWORD priv_count;
1967 switch (call_index)
1969 case 0:
1970 priv_count = get_privilege_count(hToken);
1971 todo_wine
1972 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1973 break;
1974 case 1:
1975 priv_count = get_privilege_count(hToken);
1976 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1977 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1978 break;
1979 default:
1980 ok(0, "shouldn't happen\n");
1984 static void test_no_sqos(int call_index, HANDLE hToken)
1986 switch (call_index)
1988 case 0:
1989 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1990 break;
1991 case 1:
1992 todo_wine
1993 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1994 break;
1995 default:
1996 ok(0, "shouldn't happen\n");
2000 static void test_static_context(int call_index, HANDLE hToken)
2002 switch (call_index)
2004 case 0:
2005 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2006 break;
2007 case 1:
2008 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2009 break;
2010 default:
2011 ok(0, "shouldn't happen\n");
2015 static void test_dynamic_context(int call_index, HANDLE hToken)
2017 switch (call_index)
2019 case 0:
2020 ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2021 break;
2022 case 1:
2023 todo_wine
2024 ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
2025 break;
2026 default:
2027 ok(0, "shouldn't happen\n");
2031 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
2033 switch (call_index)
2035 case 0:
2036 ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
2037 break;
2038 case 1:
2039 ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
2040 break;
2041 default:
2042 ok(0, "shouldn't happen\n");
2046 static void test_no_sqos_revert(int call_index, HANDLE hToken)
2048 DWORD priv_count;
2049 switch (call_index)
2051 case 0:
2052 priv_count = get_privilege_count(hToken);
2053 todo_wine
2054 ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
2055 break;
2056 case 1:
2057 priv_count = get_privilege_count(hToken);
2058 ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
2059 ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2060 break;
2061 default:
2062 ok(0, "shouldn't happen\n");
2066 static void test_static_context_revert(int call_index, HANDLE hToken)
2068 switch (call_index)
2070 case 0:
2071 todo_wine
2072 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2073 break;
2074 case 1:
2075 todo_wine
2076 ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
2077 break;
2078 default:
2079 ok(0, "shouldn't happen\n");
2083 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
2085 switch (call_index)
2087 case 0:
2088 todo_wine
2089 ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
2090 break;
2091 case 1:
2092 ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
2093 break;
2094 default:
2095 ok(0, "shouldn't happen\n");
2099 static void test_impersonation(void)
2101 HANDLE hClientToken;
2102 HANDLE hProcessToken;
2103 BOOL ret;
2105 if( !pDuplicateTokenEx ) {
2106 skip("DuplicateTokenEx not found\n");
2107 return;
2110 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
2111 if (!ret)
2113 skip("couldn't open process token, skipping impersonation tests\n");
2114 return;
2117 if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
2119 skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
2120 CloseHandle(hProcessToken);
2121 return;
2123 CloseHandle(hProcessToken);
2125 test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
2126 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2127 test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
2128 CloseHandle(hClientToken);
2129 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2130 test_ImpersonateNamedPipeClient(hClientToken,
2131 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
2132 test_static_context);
2133 CloseHandle(hClientToken);
2134 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2135 test_ImpersonateNamedPipeClient(hClientToken,
2136 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2137 FALSE, test_dynamic_context);
2138 CloseHandle(hClientToken);
2139 test_ImpersonateNamedPipeClient(NULL,
2140 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2141 FALSE, test_dynamic_context_no_token);
2143 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2144 test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
2145 CloseHandle(hClientToken);
2146 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2147 test_ImpersonateNamedPipeClient(hClientToken,
2148 SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
2149 test_static_context_revert);
2150 CloseHandle(hClientToken);
2151 hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
2152 test_ImpersonateNamedPipeClient(hClientToken,
2153 SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
2154 TRUE, test_dynamic_context_revert);
2155 CloseHandle(hClientToken);
2158 struct overlapped_server_args
2160 HANDLE pipe_created;
2163 static DWORD CALLBACK overlapped_server(LPVOID arg)
2165 OVERLAPPED ol;
2166 HANDLE pipe;
2167 int ret, err;
2168 struct overlapped_server_args *a = arg;
2169 DWORD num;
2170 char buf[100];
2172 pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
2173 ok(pipe != NULL, "pipe NULL\n");
2175 ol.hEvent = CreateEventA(0, 1, 0, 0);
2176 ok(ol.hEvent != NULL, "event NULL\n");
2177 ret = ConnectNamedPipe(pipe, &ol);
2178 err = GetLastError();
2179 ok(ret == 0, "ret %d\n", ret);
2180 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2181 SetEvent(a->pipe_created);
2183 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2184 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2186 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2187 ok(ret == 1, "ret %d\n", ret);
2189 /* This should block */
2190 ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
2191 ok(ret == 1, "ret %d\n", ret);
2193 DisconnectNamedPipe(pipe);
2195 ret = ConnectNamedPipe(pipe, &ol);
2196 err = GetLastError();
2197 ok(ret == 0, "ret %d\n", ret);
2198 ok(err == ERROR_IO_PENDING, "gle %d\n", err);
2199 CancelIo(pipe);
2200 ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
2201 ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
2203 ret = GetOverlappedResult(pipe, &ol, &num, 1);
2204 err = GetLastError();
2205 ok(ret == 0, "ret %d\n", ret);
2206 ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
2208 CloseHandle(ol.hEvent);
2209 CloseHandle(pipe);
2210 return 1;
2213 static void test_overlapped(void)
2215 DWORD tid, num;
2216 HANDLE thread, pipe;
2217 BOOL ret;
2218 struct overlapped_server_args args;
2220 args.pipe_created = CreateEventA(0, 1, 0, 0);
2221 thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
2223 WaitForSingleObject(args.pipe_created, INFINITE);
2224 pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
2225 ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
2227 /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
2228 Sleep(1);
2230 ret = WriteFile(pipe, "x", 1, &num, NULL);
2231 ok(ret, "WriteFile failed with error %d\n", GetLastError());
2233 WaitForSingleObject(thread, INFINITE);
2234 CloseHandle(pipe);
2235 CloseHandle(args.pipe_created);
2236 CloseHandle(thread);
2239 static void test_overlapped_error(void)
2241 HANDLE pipe, file, event;
2242 DWORD err, numbytes;
2243 OVERLAPPED overlapped;
2244 BOOL ret;
2246 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2247 ok(event != NULL, "CreateEventA failed with %u\n", GetLastError());
2249 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2250 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2251 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2252 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2254 memset(&overlapped, 0, sizeof(overlapped));
2255 overlapped.hEvent = event;
2256 ret = ConnectNamedPipe(pipe, &overlapped);
2257 err = GetLastError();
2258 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2259 ok(err == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", err);
2261 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2262 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2263 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2265 numbytes = 0xdeadbeef;
2266 ret = GetOverlappedResult(pipe, &overlapped, &numbytes, TRUE);
2267 ok(ret == TRUE, "GetOverlappedResult failed\n");
2268 ok(numbytes == 0, "expected 0, got %u\n", numbytes);
2269 ok(overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", overlapped.Internal);
2271 CloseHandle(file);
2272 CloseHandle(pipe);
2274 pipe = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
2275 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
2276 1, 1024, 1024, NMPWAIT_WAIT_FOREVER, NULL);
2277 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with %u\n", GetLastError());
2279 file = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2280 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
2281 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed with %u\n", GetLastError());
2283 memset(&overlapped, 0, sizeof(overlapped));
2284 overlapped.hEvent = event;
2285 ret = ConnectNamedPipe(pipe, &overlapped);
2286 err = GetLastError();
2287 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2288 ok(err == ERROR_PIPE_CONNECTED, "expected ERROR_PIPE_CONNECTED, got %u\n", err);
2289 ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
2291 CloseHandle(file);
2292 CloseHandle(pipe);
2294 CloseHandle(event);
2297 static void test_NamedPipeHandleState(void)
2299 HANDLE server, client;
2300 BOOL ret;
2301 DWORD state, instances, maxCollectionCount, collectDataTimeout;
2302 char userName[MAX_PATH];
2304 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2305 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2306 /* nMaxInstances */ 1,
2307 /* nOutBufSize */ 1024,
2308 /* nInBufSize */ 1024,
2309 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2310 /* lpSecurityAttrib */ NULL);
2311 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2312 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2313 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2314 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2316 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2317 if (ret)
2319 ok(state == 0, "unexpected state %08x\n", state);
2320 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2322 /* Some parameters have no meaning, and therefore can't be retrieved,
2323 * on a local pipe.
2325 SetLastError(0xdeadbeef);
2326 ret = GetNamedPipeHandleStateA(server, &state, &instances,
2327 &maxCollectionCount, &collectDataTimeout, userName,
2328 sizeof(userName) / sizeof(userName[0]));
2329 todo_wine
2330 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2331 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2332 /* A byte-mode pipe server can't be changed to message mode. */
2333 state = PIPE_READMODE_MESSAGE;
2334 SetLastError(0xdeadbeef);
2335 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2336 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2337 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2339 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2340 OPEN_EXISTING, 0, NULL);
2341 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2343 state = PIPE_READMODE_BYTE;
2344 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2345 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2346 /* A byte-mode pipe client can't be changed to message mode, either. */
2347 state = PIPE_READMODE_MESSAGE;
2348 SetLastError(0xdeadbeef);
2349 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2350 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2351 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2353 CloseHandle(client);
2354 CloseHandle(server);
2356 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2357 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2358 /* nMaxInstances */ 1,
2359 /* nOutBufSize */ 1024,
2360 /* nInBufSize */ 1024,
2361 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2362 /* lpSecurityAttrib */ NULL);
2363 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2364 ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
2365 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2366 ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
2368 ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
2369 if (ret)
2371 ok(state == 0, "unexpected state %08x\n", state);
2372 ok(instances == 1, "expected 1 instances, got %d\n", instances);
2374 /* In contrast to byte-mode pipes, a message-mode pipe server can be
2375 * changed to byte mode.
2377 state = PIPE_READMODE_BYTE;
2378 ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
2379 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2381 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2382 OPEN_EXISTING, 0, NULL);
2383 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2385 state = PIPE_READMODE_MESSAGE;
2386 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2387 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2388 /* A message-mode pipe client can also be changed to byte mode.
2390 state = PIPE_READMODE_BYTE;
2391 ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
2392 ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
2394 CloseHandle(client);
2395 CloseHandle(server);
2398 static void test_GetNamedPipeInfo(void)
2400 HANDLE server;
2402 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2403 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2404 /* nMaxInstances */ 1,
2405 /* nOutBufSize */ 1024,
2406 /* nInBufSize */ 1024,
2407 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2408 /* lpSecurityAttrib */ NULL);
2409 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2411 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
2413 CloseHandle(server);
2415 server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
2416 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
2417 /* nMaxInstances */ 3,
2418 /* nOutBufSize */ 1024,
2419 /* nInBufSize */ 1024,
2420 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2421 /* lpSecurityAttrib */ NULL);
2422 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2424 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
2426 CloseHandle(server);
2428 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2429 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2430 /* nMaxInstances */ 1,
2431 /* nOutBufSize */ 0,
2432 /* nInBufSize */ 0,
2433 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2434 /* lpSecurityAttrib */ NULL);
2435 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2437 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
2439 CloseHandle(server);
2441 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2442 /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
2443 /* nMaxInstances */ 1,
2444 /* nOutBufSize */ 0xf000,
2445 /* nInBufSize */ 0xf000,
2446 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2447 /* lpSecurityAttrib */ NULL);
2448 ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
2450 test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
2452 CloseHandle(server);
2455 static void test_readfileex_pending(void)
2457 HANDLE server, client, event;
2458 BOOL ret;
2459 DWORD err, wait, num_bytes;
2460 OVERLAPPED overlapped;
2461 char read_buf[1024];
2462 char write_buf[1024];
2463 const char test_string[] = "test";
2464 int i;
2466 server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2467 /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
2468 /* nMaxInstances */ 1,
2469 /* nOutBufSize */ 1024,
2470 /* nInBufSize */ 1024,
2471 /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
2472 /* lpSecurityAttrib */ NULL);
2473 ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
2475 event = CreateEventA(NULL, TRUE, FALSE, NULL);
2476 ok(event != NULL, "CreateEventA failed\n");
2478 memset(&overlapped, 0, sizeof(overlapped));
2479 overlapped.hEvent = event;
2481 ret = ConnectNamedPipe(server, &overlapped);
2482 err = GetLastError();
2483 ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
2484 ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
2486 wait = WaitForSingleObject(event, 0);
2487 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2489 client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
2490 OPEN_EXISTING, 0, NULL);
2491 ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
2493 wait = WaitForSingleObject(event, 0);
2494 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2496 /* Start a read that can't complete immediately. */
2497 completion_called = 0;
2498 ResetEvent(event);
2499 ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
2500 ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
2501 ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
2503 ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
2504 ok(ret == TRUE, "WriteFile failed\n");
2505 ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
2507 ok(completion_called == 0, "completion routine called during WriteFile\n");
2509 wait = WaitForSingleObjectEx(event, 0, TRUE);
2510 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
2512 ok(completion_called == 1, "completion not called after writing pipe\n");
2513 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2514 ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
2515 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2516 ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
2518 /* Make writes until the pipe is full and the write fails */
2519 memset(write_buf, 0xaa, sizeof(write_buf));
2520 for (i=0; i<256; i++)
2522 completion_called = 0;
2523 ResetEvent(event);
2524 ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
2525 err = GetLastError();
2527 ok(completion_called == 0, "completion routine called during WriteFileEx\n");
2529 wait = WaitForSingleObjectEx(event, 0, TRUE);
2531 if (wait == WAIT_TIMEOUT)
2532 /* write couldn't complete immediately, presumably the pipe is full */
2533 break;
2535 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2537 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2538 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2539 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2542 ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
2543 ok(completion_called == 0, "completion routine called but wait timed out\n");
2544 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2545 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2547 /* free up some space in the pipe */
2548 for (i=0; i<256; i++)
2550 ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
2551 ok(ret == TRUE, "ReadFile failed\n");
2553 ok(completion_called == 0, "completion routine called during ReadFile\n");
2555 wait = WaitForSingleObjectEx(event, 0, TRUE);
2556 ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
2557 "WaitForSingleObject returned %x\n", wait);
2558 if (wait != WAIT_TIMEOUT) break;
2561 ok(completion_called == 1, "completion routine not called\n");
2562 ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
2563 ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
2565 num_bytes = 0xdeadbeef;
2566 SetLastError(0xdeadbeef);
2567 ret = ReadFile(INVALID_HANDLE_VALUE, read_buf, 0, &num_bytes, NULL);
2568 ok(!ret, "ReadFile should fail\n");
2569 ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
2570 ok(num_bytes == 0, "expected 0, got %u\n", num_bytes);
2572 S(U(overlapped)).Offset = 0;
2573 S(U(overlapped)).OffsetHigh = 0;
2574 overlapped.Internal = -1;
2575 overlapped.InternalHigh = -1;
2576 overlapped.hEvent = event;
2577 num_bytes = 0xdeadbeef;
2578 SetLastError(0xdeadbeef);
2579 ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
2580 ok(!ret, "ReadFile should fail\n");
2581 ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
2582 ok(num_bytes == 0, "bytes %u\n", num_bytes);
2583 ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
2584 todo_wine
2585 ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
2587 wait = WaitForSingleObject(event, 100);
2588 ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
2590 num_bytes = 0xdeadbeef;
2591 ret = WriteFile(client, test_string, 1, &num_bytes, NULL);
2592 ok(ret, "WriteFile failed\n");
2593 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2595 wait = WaitForSingleObject(event, 100);
2596 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
2598 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2599 ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
2600 ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
2602 /* read the pending byte and clear the pipe */
2603 num_bytes = 0xdeadbeef;
2604 ret = ReadFile(server, read_buf, 1, &num_bytes, &overlapped);
2605 ok(ret, "ReadFile failed\n");
2606 ok(num_bytes == 1, "bytes %u\n", num_bytes);
2608 CloseHandle(client);
2609 CloseHandle(server);
2610 CloseHandle(event);
2613 #define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
2614 static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
2616 DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
2617 char buf[4000];
2618 FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
2619 IO_STATUS_BLOCK io;
2620 NTSTATUS status;
2621 BOOL r;
2623 r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
2624 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2625 ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2626 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2627 ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %d, expected %d\n",
2628 left, expected_message_length - expected_read);
2630 status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
2631 ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x\n", status);
2632 ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
2633 "io.Information = %lu\n", io.Information);
2634 ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %u, expected %u\n",
2635 peek_buf->ReadDataAvailable, expected_avail);
2636 ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %u, expected %u\n",
2637 peek_buf->MessageLength, expected_message_length);
2639 if (expected_read)
2641 r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
2642 ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
2643 ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
2644 ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
2645 ok_(__FILE__,line)(left == expected_message_length-1, "left = %d, expected %d\n", left, expected_message_length-1);
2649 #define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
2650 static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
2652 DWORD read_bytes = 0xdeadbeef;
2653 OVERLAPPED overlapped;
2654 BOOL res;
2656 memset(&overlapped, 0, sizeof(overlapped));
2657 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2658 res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
2659 if (partial_read)
2660 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%u)\n", res, GetLastError());
2661 else
2662 ok_(__FILE__,line)(res, "ReadFile failed: %u\n", GetLastError());
2663 if(partial_read)
2664 todo_wine ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2665 else
2666 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2668 read_bytes = 0xdeadbeef;
2669 res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
2670 if (partial_read)
2671 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
2672 "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2673 else
2674 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2675 ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
2676 CloseHandle(overlapped.hEvent);
2679 #define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
2680 static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
2682 DWORD read_bytes = 0xdeadbeef;
2683 BOOL res;
2685 memset(overlapped, 0, sizeof(*overlapped));
2686 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2687 res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
2688 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%u)\n", res, GetLastError());
2689 ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
2691 _test_not_signaled(line, overlapped->hEvent);
2694 #define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
2695 static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
2697 DWORD written_bytes = 0xdeadbeef;
2698 OVERLAPPED overlapped;
2699 BOOL res;
2701 memset(&overlapped, 0, sizeof(overlapped));
2702 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2703 res = WriteFile(writer, buf, size, &written_bytes, &overlapped);
2704 ok_(__FILE__,line)(res, "WriteFile returned %x(%u)\n", res, GetLastError());
2705 ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %u\n", written_bytes);
2707 written_bytes = 0xdeadbeef;
2708 res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
2709 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2710 ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %u expected %u\n", written_bytes, size);
2712 CloseHandle(overlapped.hEvent);
2715 #define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
2716 static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
2718 DWORD written_bytes = 0xdeadbeef;
2719 BOOL res;
2721 memset(overlapped, 0, sizeof(*overlapped));
2722 overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2723 res = WriteFile(writer, buf, size, &written_bytes, overlapped);
2724 ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
2725 todo_wine ok_(__FILE__,line)(!written_bytes, "written_bytes = %u\n", written_bytes);
2727 _test_not_signaled(line, overlapped->hEvent);
2730 #define test_flush_sync(a) _test_flush_sync(__LINE__,a)
2731 static void _test_flush_sync(unsigned line, HANDLE pipe)
2733 BOOL res;
2735 res = FlushFileBuffers(pipe);
2736 ok_(__FILE__,line)(res, "FlushFileBuffers failed: %u\n", GetLastError());
2739 static DWORD expected_flush_error;
2741 static DWORD CALLBACK flush_proc(HANDLE pipe)
2743 BOOL res;
2745 res = FlushFileBuffers(pipe);
2746 if (expected_flush_error == ERROR_SUCCESS)
2747 ok(res, "FlushFileBuffers failed: %u\n", GetLastError());
2748 else
2749 todo_wine ok(!res && GetLastError() == expected_flush_error, "FlushFileBuffers failed: %u\n", GetLastError());
2750 return 0;
2753 #define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
2754 static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
2756 HANDLE thread;
2757 DWORD tid;
2759 expected_flush_error = error;
2760 thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
2761 ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %u\n", GetLastError());
2763 Sleep(50);
2764 _test_not_signaled(line, thread);
2765 return thread;
2768 #define test_flush_done(a) _test_flush_done(__LINE__,a)
2769 static void _test_flush_done(unsigned line, HANDLE thread)
2771 DWORD res = WaitForSingleObject(thread, 1000);
2772 ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
2773 CloseHandle(thread);
2776 #define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
2777 static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
2779 DWORD result = 0xdeadbeef;
2780 BOOL res;
2782 _test_signaled(line, overlapped->hEvent);
2784 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2785 if (partial_read)
2786 ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
2787 else
2788 ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
2789 ok_(__FILE__,line)(result == expected_result, "read_bytes = %u, expected %u\n", result, expected_result);
2790 CloseHandle(overlapped->hEvent);
2793 #define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
2794 static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
2796 DWORD result;
2797 BOOL res;
2799 _test_signaled(line, overlapped->hEvent);
2801 res = GetOverlappedResult(handle, overlapped, &result, FALSE);
2802 ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%u), expected error %u\n",
2803 res, GetLastError(), error);
2804 ok_(__FILE__,line)(!result, "result = %u\n", result);
2805 CloseHandle(overlapped->hEvent);
2808 #define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
2809 static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
2811 BOOL res;
2813 res = pCancelIoEx(handle, overlapped);
2814 ok_(__FILE__,line)(res, "CancelIoEx failed: %u\n", GetLastError());
2816 _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
2819 static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
2821 OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
2822 char buf[10000], read_buf[10000];
2823 HANDLE flush_thread;
2825 memset(buf, 0xaa, sizeof(buf));
2827 /* test pending read with overlapped event */
2828 overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
2829 test_flush_sync(writer);
2830 test_peek_pipe(reader, 0, 0, 0);
2832 /* write more data than needed for read */
2833 overlapped_write_sync(writer, buf, 4000);
2834 test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
2836 /* test pending write with overlapped event */
2837 overlapped_write_async(writer, buf, buf_size, &write_overlapped);
2839 /* write one more byte */
2840 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2841 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2842 test_not_signaled(write_overlapped.hEvent);
2844 /* empty write will not block */
2845 overlapped_write_sync(writer, buf, 0);
2846 test_not_signaled(write_overlapped.hEvent);
2847 test_not_signaled(write_overlapped2.hEvent);
2849 /* read remaining data from the first write */
2850 overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
2851 test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
2852 test_not_signaled(write_overlapped2.hEvent);
2853 test_not_signaled(flush_thread);
2855 /* read one byte so that the next write fits the buffer */
2856 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2857 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2859 /* read the whole buffer */
2860 overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
2862 if(msg_read)
2863 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
2865 if(msg_mode) {
2866 /* we still have an empty message in queue */
2867 overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
2869 test_flush_done(flush_thread);
2871 /* pipe is empty, the next read will block */
2872 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
2873 overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
2875 /* write one byte */
2876 overlapped_write_sync(writer, buf, 1);
2877 test_overlapped_result(reader, &read_overlapped, 0, msg_read);
2878 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
2880 /* write a message larger than buffer */
2881 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
2883 /* read so that pending write is still larger than the buffer */
2884 overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
2885 test_not_signaled(write_overlapped.hEvent);
2887 /* read one more byte */
2888 overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
2889 test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
2891 /* read remaining data */
2892 overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
2894 /* simple pass of empty message */
2895 overlapped_write_sync(writer, buf, 0);
2896 if(msg_mode)
2897 overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
2899 /* pipe is empty, the next read will block */
2900 test_flush_sync(writer);
2901 overlapped_read_async(reader, read_buf, 0, &read_overlapped);
2902 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
2904 /* 0 length write wakes one read in msg mode */
2905 overlapped_write_sync(writer, buf, 0);
2906 if(msg_mode)
2907 test_overlapped_result(reader, &read_overlapped, 0, FALSE);
2908 else
2909 test_not_signaled(read_overlapped.hEvent);
2910 test_not_signaled(read_overlapped2.hEvent);
2911 overlapped_write_sync(writer, buf, 1);
2912 test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
2914 overlapped_write_sync(writer, buf, 20);
2915 test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
2916 overlapped_write_sync(writer, buf, 15);
2917 test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
2918 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
2919 test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
2920 overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
2921 test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
2922 overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
2924 if(!pCancelIoEx) {
2925 win_skip("CancelIoEx not available\n");
2926 return;
2929 /* add one more pending read, then cancel the first one */
2930 overlapped_read_async(reader, read_buf, 1, &read_overlapped);
2931 overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
2932 cancel_overlapped(reader, &read_overlapped2);
2933 test_not_signaled(read_overlapped.hEvent);
2934 overlapped_write_sync(writer, buf, 1);
2935 test_overlapped_result(reader, &read_overlapped, 1, FALSE);
2937 /* make two async writes, cancel the first one and make sure that we read from the second one */
2938 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
2939 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2940 cancel_overlapped(writer, &write_overlapped);
2941 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
2942 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2944 /* same as above, but parially read written data before canceling */
2945 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
2946 overlapped_write_async(writer, buf, 1, &write_overlapped2);
2947 overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
2948 test_not_signaled(write_overlapped.hEvent);
2949 cancel_overlapped(writer, &write_overlapped);
2950 overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
2951 test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
2953 /* empty queue by canceling write and make sure that flush is signaled */
2954 overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
2955 flush_thread = test_flush_async(writer, ERROR_SUCCESS);
2956 test_not_signaled(flush_thread);
2957 cancel_overlapped(writer, &write_overlapped);
2958 test_flush_done(flush_thread);
2961 static void child_process_write_pipe(HANDLE pipe)
2963 OVERLAPPED overlapped;
2964 char buf[10000];
2966 memset(buf, 'x', sizeof(buf));
2967 overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
2969 /* sleep until parent process terminates this process */
2970 Sleep(INFINITE);
2973 static HANDLE create_writepipe_process(HANDLE pipe)
2975 STARTUPINFOA si = { sizeof(si) };
2976 PROCESS_INFORMATION info;
2977 char **argv, buf[MAX_PATH];
2978 BOOL res;
2980 winetest_get_mainargs(&argv);
2981 sprintf(buf, "\"%s\" pipe writepipe %lx", argv[0], (UINT_PTR)pipe);
2982 res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
2983 ok(res, "CreateProcess failed: %u\n", GetLastError());
2984 CloseHandle(info.hThread);
2986 return info.hProcess;
2989 static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
2991 SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
2992 DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
2993 OVERLAPPED overlapped;
2994 BOOL res;
2996 *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
2997 PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
2998 ok(&server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError());
2999 test_signaled(*server);
3001 memset(&overlapped, 0, sizeof(overlapped));
3002 overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
3003 res = ConnectNamedPipe(*server, &overlapped);
3004 ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
3005 test_not_signaled(*server);
3006 test_not_signaled(overlapped.hEvent);
3008 *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
3009 ok(*server != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
3011 res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
3012 ok(res, "SetNamedPipeHandleState failed: %u\n", GetLastError());
3014 test_signaled(*client);
3015 test_not_signaled(*server);
3016 test_overlapped_result(*server, &overlapped, 0, FALSE);
3019 static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
3021 OVERLAPPED overlapped, overlapped2;
3022 HANDLE server, client, flush;
3023 DWORD read_bytes;
3024 HANDLE process;
3025 char buf[60000];
3026 BOOL res;
3028 DWORD create_flags =
3029 (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
3030 (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
3032 create_overlapped_pipe(create_flags, &client, &server);
3034 trace("testing %s, %s server->client writes...\n",
3035 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3036 test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
3037 trace("testing %s, %s client->server writes...\n",
3038 msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
3039 test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
3041 CloseHandle(client);
3042 CloseHandle(server);
3044 /* close client with pending writes */
3045 create_overlapped_pipe(create_flags, &client, &server);
3046 overlapped_write_async(server, buf, 7000, &overlapped);
3047 flush = test_flush_async(server, ERROR_BROKEN_PIPE);
3048 CloseHandle(client);
3049 test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
3050 test_flush_done(flush);
3051 CloseHandle(server);
3053 /* close server with pending writes */
3054 create_overlapped_pipe(create_flags, &client, &server);
3055 overlapped_write_async(client, buf, 7000, &overlapped);
3056 flush = test_flush_async(client, ERROR_BROKEN_PIPE);
3057 CloseHandle(server);
3058 test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
3059 test_flush_done(flush);
3060 CloseHandle(client);
3062 /* disconnect with pending writes */
3063 create_overlapped_pipe(create_flags, &client, &server);
3064 overlapped_write_async(client, buf, 7000, &overlapped);
3065 overlapped_write_async(server, buf, 7000, &overlapped2);
3066 flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
3067 res = DisconnectNamedPipe(server);
3068 ok(res, "DisconnectNamedPipe failed: %u\n", GetLastError());
3069 test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
3070 test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
3071 test_flush_done(flush);
3072 CloseHandle(server);
3073 CloseHandle(client);
3075 /* terminate process with pending write */
3076 create_overlapped_pipe(create_flags, &client, &server);
3077 process = create_writepipe_process(client);
3078 /* successfully read part of write that is pending in child process */
3079 res = ReadFile(server, buf, 10, &read_bytes, NULL);
3080 if(!msg_read_mode)
3081 ok(res, "ReadFile failed: %u\n", GetLastError());
3082 else
3083 ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError());
3084 ok(read_bytes == 10, "read_bytes = %u\n", read_bytes);
3085 TerminateProcess(process, 0);
3086 winetest_wait_child_process(process);
3087 /* after terminating process, there is no pending write and pipe buffer is empty */
3088 overlapped_read_async(server, buf, 10, &overlapped);
3089 overlapped_write_sync(client, buf, 1);
3090 test_overlapped_result(server, &overlapped, 1, FALSE);
3091 CloseHandle(process);
3092 CloseHandle(server);
3093 CloseHandle(client);
3096 START_TEST(pipe)
3098 char **argv;
3099 int argc;
3100 HMODULE hmod;
3102 hmod = GetModuleHandleA("advapi32.dll");
3103 pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
3104 hmod = GetModuleHandleA("kernel32.dll");
3105 pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
3106 pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
3108 argc = winetest_get_mainargs(&argv);
3110 if (argc > 3 && !strcmp(argv[2], "writepipe"))
3112 UINT_PTR handle;
3113 sscanf(argv[3], "%lx", &handle);
3114 child_process_write_pipe((HANDLE)handle);
3115 return;
3118 if (test_DisconnectNamedPipe())
3119 return;
3120 test_CreateNamedPipe_instances_must_match();
3121 test_NamedPipe_2();
3122 test_CreateNamedPipe(PIPE_TYPE_BYTE);
3123 test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
3124 test_CreatePipe();
3125 test_CloseHandle();
3126 test_impersonation();
3127 test_overlapped();
3128 test_overlapped_error();
3129 test_NamedPipeHandleState();
3130 test_GetNamedPipeInfo();
3131 test_readfileex_pending();
3132 test_overlapped_transport(TRUE, FALSE);
3133 test_overlapped_transport(TRUE, TRUE);
3134 test_overlapped_transport(FALSE, FALSE);