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