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