winhttp: Fix up headers with wrong termination.
[wine] / dlls / kernel32 / tests / pipe.c
1 /*
2  * Unit tests for named pipe functions in Wine
3  *
4  * Copyright (c) 2002 Dan Kegel
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winsock.h>
27 #include <wtypes.h>
28 #include <winerror.h>
29
30 #include "wine/test.h"
31
32 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
33
34 #define NB_SERVER_LOOPS 8
35
36 static HANDLE alarm_event;
37 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
38                                         SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
39 static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
40
41 static BOOL user_apc_ran;
42 static void CALLBACK user_apc(ULONG_PTR param)
43 {
44     user_apc_ran = TRUE;
45 }
46
47 static void test_CreateNamedPipe(int pipemode)
48 {
49     HANDLE hnp;
50     HANDLE hFile;
51     static const char obuf[] = "Bit Bucket";
52     static const char obuf2[] = "More bits";
53     char ibuf[32], *pbuf;
54     DWORD written;
55     DWORD readden;
56     DWORD avail;
57     DWORD lpmode;
58     BOOL ret;
59
60     if (pipemode == PIPE_TYPE_BYTE)
61         trace("test_CreateNamedPipe starting in byte mode\n");
62     else
63         trace("test_CreateNamedPipe starting in message mode\n");
64     /* Bad parameter checks */
65     hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
66         /* nMaxInstances */ 1,
67         /* nOutBufSize */ 1024,
68         /* nInBufSize */ 1024,
69         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
70         /* lpSecurityAttrib */ NULL);
71     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
72         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
73
74     if (pipemode == PIPE_TYPE_BYTE)
75     {
76         /* Bad parameter checks */
77         hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE,
78             /* nMaxInstances */ 1,
79             /* nOutBufSize */ 1024,
80             /* nInBufSize */ 1024,
81             /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
82             /* lpSecurityAttrib */ NULL);
83         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
84             "CreateNamedPipe should fail with PIPE_TYPE_BYTE | PIPE_READMODE_MESSAGE\n");
85     }
86
87     hnp = CreateNamedPipe(NULL,
88         PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
89         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
90     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
91         "CreateNamedPipe should fail if name is NULL\n");
92
93     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
94     ok(hFile == INVALID_HANDLE_VALUE
95         && GetLastError() == ERROR_FILE_NOT_FOUND,
96         "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
97
98     /* Functional checks */
99
100     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
101         /* nMaxInstances */ 1,
102         /* nOutBufSize */ 1024,
103         /* nInBufSize */ 1024,
104         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
105         /* lpSecurityAttrib */ NULL);
106     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
107
108     ret = WaitNamedPipeA(PIPENAME, 2000);
109     ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
110
111     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
112     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
113
114     ok(!WaitNamedPipeA(PIPENAME, 1000), "WaitNamedPipe succeeded\n");
115
116     ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
117
118     /* don't try to do i/o if one side couldn't be opened, as it hangs */
119     if (hFile != INVALID_HANDLE_VALUE) {
120         HANDLE hFile2;
121
122         /* Make sure we can read and write a few bytes in both directions */
123         memset(ibuf, 0, sizeof(ibuf));
124         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
125         ok(written == sizeof(obuf), "write file len 1\n");
126         ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
127         ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
128         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
129         ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
130         ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
131
132         memset(ibuf, 0, sizeof(ibuf));
133         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
134         ok(written == sizeof(obuf2), "write file len 2\n");
135         ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
136         ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
137         ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
138         ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
139         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
140         ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
141         ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
142
143         /* Test reading of multiple writes */
144         memset(ibuf, 0, sizeof(ibuf));
145         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
146         ok(written == sizeof(obuf), "write file len 3a\n");
147         ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
148         ok(written == sizeof(obuf2), "write file len 3b\n");
149         ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
150         if (pipemode == PIPE_TYPE_BYTE) {
151             if (readden != sizeof(obuf))  /* Linux only returns the first message */
152                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
153             else
154                 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
155         }
156         else
157         {
158             if (readden != sizeof(obuf) + sizeof(obuf2))  /* MacOS returns both messages */
159                 ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
160             else
161                 todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
162         }
163         if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
164             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
165         pbuf = ibuf;
166         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
167         if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
168             pbuf += sizeof(obuf);
169             ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
170         }
171         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
172         ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
173         pbuf = ibuf;
174         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
175         pbuf += sizeof(obuf);
176         ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
177
178         /* Multiple writes in the reverse direction */
179         memset(ibuf, 0, sizeof(ibuf));
180         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
181         ok(written == sizeof(obuf), "write file len 4a\n");
182         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
183         ok(written == sizeof(obuf2), "write file len 4b\n");
184         ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
185         if (pipemode == PIPE_TYPE_BYTE) {
186             if (readden != sizeof(obuf))  /* Linux only returns the first message */
187                 /* should return all 23 bytes */
188                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
189             else
190                 todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
191         }
192         else
193         {
194             if (readden != sizeof(obuf) + sizeof(obuf2))  /* MacOS returns both messages */
195                 ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
196             else
197                 todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
198         }
199         if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
200             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
201         pbuf = ibuf;
202         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
203         if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
204             pbuf += sizeof(obuf);
205             ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
206         }
207         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
208         if (pipemode == PIPE_TYPE_BYTE) {
209             ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
210         }
211         else {
212             todo_wine {
213                 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
214             }
215         }
216         pbuf = ibuf;
217         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
218         if (pipemode == PIPE_TYPE_BYTE) {
219             pbuf += sizeof(obuf);
220             ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
221         }
222
223         /* Test reading of multiple writes after a mode change
224           (CreateFile always creates a byte mode pipe) */
225         lpmode = PIPE_READMODE_MESSAGE;
226         if (pipemode == PIPE_TYPE_BYTE) {
227             /* trying to change the client end of a byte pipe to message mode should fail */
228             ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
229         }
230         else {
231             todo_wine {
232                 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
233             }
234         
235             memset(ibuf, 0, sizeof(ibuf));
236             ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
237             ok(written == sizeof(obuf), "write file len 3a\n");
238             ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
239             ok(written == sizeof(obuf2), "write file len 3b\n");
240             ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
241             if (readden != sizeof(obuf) + sizeof(obuf2))  /* MacOS returns both writes */
242                 ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
243             else
244                 todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
245             if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
246                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
247             else
248                 todo_wine ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
249             pbuf = ibuf;
250             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
251             ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
252             todo_wine {
253                 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
254             }
255             pbuf = ibuf;
256             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
257     
258             /* Multiple writes in the reverse direction */
259             /* the write of obuf2 from write4 should still be in the buffer */
260             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
261             todo_wine {
262                 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
263                 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
264             }
265             if (avail > 0) {
266                 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
267                 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
268                 pbuf = ibuf;
269                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
270             }
271             memset(ibuf, 0, sizeof(ibuf));
272             ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
273             ok(written == sizeof(obuf), "write file len 6a\n");
274             ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
275             ok(written == sizeof(obuf2), "write file len 6b\n");
276             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
277             if (readden != sizeof(obuf) + sizeof(obuf2))  /* MacOS returns both writes */
278                 ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
279             else
280                 todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
281             if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
282                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
283             pbuf = ibuf;
284             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
285             ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
286             todo_wine {
287                 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
288             }
289             pbuf = ibuf;
290             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
291         }
292
293         /* Picky conformance tests */
294
295         /* Verify that you can't connect to pipe again
296          * until server calls DisconnectNamedPipe+ConnectNamedPipe
297          * or creates a new pipe
298          * case 1: other client not yet closed
299          */
300         hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
301         ok(hFile2 == INVALID_HANDLE_VALUE,
302             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
303         ok(GetLastError() == ERROR_PIPE_BUSY,
304             "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
305
306         ok(CloseHandle(hFile), "CloseHandle\n");
307
308         /* case 2: other client already closed */
309         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
310         ok(hFile == INVALID_HANDLE_VALUE,
311             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
312         ok(GetLastError() == ERROR_PIPE_BUSY,
313             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
314
315         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
316
317         /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
318         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
319         ok(hFile == INVALID_HANDLE_VALUE,
320             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
321         ok(GetLastError() == ERROR_PIPE_BUSY,
322             "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
323
324         /* to be complete, we'd call ConnectNamedPipe here and loop,
325          * but by default that's blocking, so we'd either have
326          * to turn on the uncommon nonblocking mode, or
327          * use another thread.
328          */
329     }
330
331     ok(CloseHandle(hnp), "CloseHandle\n");
332
333     trace("test_CreateNamedPipe returning\n");
334 }
335
336 static void test_CreateNamedPipe_instances_must_match(void)
337 {
338     HANDLE hnp, hnp2;
339
340     /* Check no mismatch */
341     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
342         /* nMaxInstances */ 2,
343         /* nOutBufSize */ 1024,
344         /* nInBufSize */ 1024,
345         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
346         /* lpSecurityAttrib */ NULL);
347     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
348
349     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
350         /* nMaxInstances */ 2,
351         /* nOutBufSize */ 1024,
352         /* nInBufSize */ 1024,
353         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
354         /* lpSecurityAttrib */ NULL);
355     ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
356
357     ok(CloseHandle(hnp), "CloseHandle\n");
358     ok(CloseHandle(hnp2), "CloseHandle\n");
359
360     /* Check nMaxInstances */
361     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
362         /* nMaxInstances */ 1,
363         /* nOutBufSize */ 1024,
364         /* nInBufSize */ 1024,
365         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
366         /* lpSecurityAttrib */ NULL);
367     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
368
369     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
370         /* nMaxInstances */ 1,
371         /* nOutBufSize */ 1024,
372         /* nInBufSize */ 1024,
373         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
374         /* lpSecurityAttrib */ NULL);
375     ok(hnp2 == INVALID_HANDLE_VALUE
376         && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
377
378     ok(CloseHandle(hnp), "CloseHandle\n");
379
380     /* Check PIPE_ACCESS_* */
381     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
382         /* nMaxInstances */ 2,
383         /* nOutBufSize */ 1024,
384         /* nInBufSize */ 1024,
385         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
386         /* lpSecurityAttrib */ NULL);
387     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
388
389     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
390         /* nMaxInstances */ 2,
391         /* nOutBufSize */ 1024,
392         /* nInBufSize */ 1024,
393         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
394         /* lpSecurityAttrib */ NULL);
395     ok(hnp2 == INVALID_HANDLE_VALUE
396         && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
397
398     ok(CloseHandle(hnp), "CloseHandle\n");
399
400     /* check everything else */
401     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
402         /* nMaxInstances */ 4,
403         /* nOutBufSize */ 1024,
404         /* nInBufSize */ 1024,
405         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
406         /* lpSecurityAttrib */ NULL);
407     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
408
409     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE,
410         /* nMaxInstances */ 3,
411         /* nOutBufSize */ 102,
412         /* nInBufSize */ 24,
413         /* nDefaultWait */ 1234,
414         /* lpSecurityAttrib */ NULL);
415     ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
416
417     ok(CloseHandle(hnp), "CloseHandle\n");
418     ok(CloseHandle(hnp2), "CloseHandle\n");
419 }
420
421 /** implementation of alarm() */
422 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
423 {
424     DWORD_PTR timeout = (DWORD_PTR) arg;
425     trace("alarmThreadMain\n");
426     if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
427     {
428         ok(FALSE, "alarm\n");
429         ExitProcess(1);
430     }
431     return 1;
432 }
433
434 static HANDLE hnp = INVALID_HANDLE_VALUE;
435
436 /** Trivial byte echo server - disconnects after each session */
437 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
438 {
439     int i;
440
441     trace("serverThreadMain1 start\n");
442     /* Set up a simple echo server */
443     hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
444         PIPE_TYPE_BYTE | PIPE_WAIT,
445         /* nMaxInstances */ 1,
446         /* nOutBufSize */ 1024,
447         /* nInBufSize */ 1024,
448         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
449         /* lpSecurityAttrib */ NULL);
450
451     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
452     for (i = 0; i < NB_SERVER_LOOPS; i++) {
453         char buf[512];
454         DWORD written;
455         DWORD readden;
456         DWORD success;
457
458         /* Wait for client to connect */
459         trace("Server calling ConnectNamedPipe...\n");
460         ok(ConnectNamedPipe(hnp, NULL)
461             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
462         trace("ConnectNamedPipe returned.\n");
463
464         /* Echo bytes once */
465         memset(buf, 0, sizeof(buf));
466
467         trace("Server reading...\n");
468         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
469         trace("Server done reading.\n");
470         ok(success, "ReadFile\n");
471         ok(readden, "short read\n");
472
473         trace("Server writing...\n");
474         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
475         trace("Server done writing.\n");
476         ok(written == readden, "write file len\n");
477
478         /* finish this connection, wait for next one */
479         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
480         trace("Server done flushing.\n");
481         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
482         trace("Server done disconnecting.\n");
483     }
484     return 0;
485 }
486
487 /** Trivial byte echo server - closes after each connection */
488 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
489 {
490     int i;
491     HANDLE hnpNext = 0;
492
493     trace("serverThreadMain2\n");
494     /* Set up a simple echo server */
495     hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
496         PIPE_TYPE_BYTE | PIPE_WAIT,
497         /* nMaxInstances */ 2,
498         /* nOutBufSize */ 1024,
499         /* nInBufSize */ 1024,
500         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
501         /* lpSecurityAttrib */ NULL);
502     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
503
504     for (i = 0; i < NB_SERVER_LOOPS; i++) {
505         char buf[512];
506         DWORD written;
507         DWORD readden;
508         DWORD success;
509
510         user_apc_ran = FALSE;
511         if (i == 0 && pQueueUserAPC) {
512             trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
513             success = pQueueUserAPC(&user_apc, GetCurrentThread(), 0);
514             ok(success, "QueueUserAPC failed: %d\n", GetLastError());
515         }
516
517         /* Wait for client to connect */
518         trace("Server calling ConnectNamedPipe...\n");
519         ok(ConnectNamedPipe(hnp, NULL)
520             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
521         trace("ConnectNamedPipe returned.\n");
522
523         /* Echo bytes once */
524         memset(buf, 0, sizeof(buf));
525
526         trace("Server reading...\n");
527         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
528         trace("Server done reading.\n");
529         ok(success, "ReadFile\n");
530
531         trace("Server writing...\n");
532         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
533         trace("Server done writing.\n");
534         ok(written == readden, "write file len\n");
535
536         /* finish this connection, wait for next one */
537         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
538         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
539
540         ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
541
542         if (i == 0 && pQueueUserAPC)
543             SleepEx(0, TRUE); /* get rid of apc */
544
545         /* Set up next echo server */
546         hnpNext =
547             CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
548             PIPE_TYPE_BYTE | PIPE_WAIT,
549             /* nMaxInstances */ 2,
550             /* nOutBufSize */ 1024,
551             /* nInBufSize */ 1024,
552             /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
553             /* lpSecurityAttrib */ NULL);
554
555         ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
556
557         ok(CloseHandle(hnp), "CloseHandle\n");
558         hnp = hnpNext;
559     }
560     return 0;
561 }
562
563 /** Trivial byte echo server - uses overlapped named pipe calls */
564 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
565 {
566     int i;
567     HANDLE hEvent;
568
569     trace("serverThreadMain3\n");
570     /* Set up a simple echo server */
571     hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
572         PIPE_TYPE_BYTE | PIPE_WAIT,
573         /* nMaxInstances */ 1,
574         /* nOutBufSize */ 1024,
575         /* nInBufSize */ 1024,
576         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
577         /* lpSecurityAttrib */ NULL);
578     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
579
580     hEvent = CreateEvent(NULL,  /* security attribute */
581         TRUE,                   /* manual reset event */
582         FALSE,                  /* initial state */
583         NULL);                  /* name */
584     ok(hEvent != NULL, "CreateEvent\n");
585
586     for (i = 0; i < NB_SERVER_LOOPS; i++) {
587         char buf[512];
588         DWORD written;
589         DWORD readden;
590         DWORD dummy;
591         DWORD success;
592         OVERLAPPED oOverlap;
593         int letWFSOEwait = (i & 2);
594         int letGORwait = (i & 1);
595         DWORD err;
596
597         memset(&oOverlap, 0, sizeof(oOverlap));
598         oOverlap.hEvent = hEvent;
599
600         /* Wait for client to connect */
601         if (i == 0) {
602             trace("Server calling non-overlapped ConnectNamedPipe on overlapped pipe...\n");
603             success = ConnectNamedPipe(hnp, NULL);
604             err = GetLastError();
605             ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
606             trace("ConnectNamedPipe operation complete.\n");
607         } else {
608             trace("Server calling overlapped ConnectNamedPipe...\n");
609             success = ConnectNamedPipe(hnp, &oOverlap);
610             err = GetLastError();
611             ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED), "overlapped ConnectNamedPipe\n");
612             trace("overlapped ConnectNamedPipe returned.\n");
613             if (!success && (err == ERROR_IO_PENDING)) {
614                 if (letWFSOEwait)
615                 {
616                     DWORD ret;
617                     do {
618                         ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
619                     } while (ret == WAIT_IO_COMPLETION);
620                     ok(ret == 0, "wait ConnectNamedPipe returned %x\n", ret);
621                 }
622                 success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
623                 if (!letGORwait && !letWFSOEwait && !success) {
624                     ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
625                     success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
626                 }
627             }
628             ok(success || (err == ERROR_PIPE_CONNECTED), "GetOverlappedResult ConnectNamedPipe\n");
629             trace("overlapped ConnectNamedPipe operation complete.\n");
630         }
631
632         /* Echo bytes once */
633         memset(buf, 0, sizeof(buf));
634
635         trace("Server reading...\n");
636         success = ReadFile(hnp, buf, sizeof(buf), &readden, &oOverlap);
637         trace("Server ReadFile returned...\n");
638         err = GetLastError();
639         ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
640         trace("overlapped ReadFile returned.\n");
641         if (!success && (err == ERROR_IO_PENDING)) {
642             if (letWFSOEwait)
643             {
644                 DWORD ret;
645                 do {
646                     ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
647                 } while (ret == WAIT_IO_COMPLETION);
648                 ok(ret == 0, "wait ReadFile returned %x\n", ret);
649             }
650             success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
651             if (!letGORwait && !letWFSOEwait && !success) {
652                 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
653                 success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
654             }
655         }
656         trace("Server done reading.\n");
657         ok(success, "overlapped ReadFile\n");
658
659         trace("Server writing...\n");
660         success = WriteFile(hnp, buf, readden, &written, &oOverlap);
661         trace("Server WriteFile returned...\n");
662         err = GetLastError();
663         ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
664         trace("overlapped WriteFile returned.\n");
665         if (!success && (err == ERROR_IO_PENDING)) {
666             if (letWFSOEwait)
667             {
668                 DWORD ret;
669                 do {
670                     ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
671                 } while (ret == WAIT_IO_COMPLETION);
672                 ok(ret == 0, "wait WriteFile returned %x\n", ret);
673             }
674             success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
675             if (!letGORwait && !letWFSOEwait && !success) {
676                 ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
677                 success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
678             }
679         }
680         trace("Server done writing.\n");
681         ok(success, "overlapped WriteFile\n");
682         ok(written == readden, "write file len\n");
683
684         /* finish this connection, wait for next one */
685         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
686         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
687     }
688     return 0;
689 }
690
691 /** Trivial byte echo server - uses i/o completion ports */
692 static DWORD CALLBACK serverThreadMain4(LPVOID arg)
693 {
694     int i;
695     HANDLE hcompletion;
696     BOOL ret;
697
698     trace("serverThreadMain4\n");
699     /* Set up a simple echo server */
700     hnp = CreateNamedPipe(PIPENAME "serverThreadMain4", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
701         PIPE_TYPE_BYTE | PIPE_WAIT,
702         /* nMaxInstances */ 1,
703         /* nOutBufSize */ 1024,
704         /* nInBufSize */ 1024,
705         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
706         /* lpSecurityAttrib */ NULL);
707     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
708
709     hcompletion = CreateIoCompletionPort(hnp, NULL, 12345, 1);
710     ok(hcompletion != NULL, "CreateIoCompletionPort failed, error=%i\n", GetLastError());
711
712     for (i = 0; i < NB_SERVER_LOOPS; i++) {
713         char buf[512];
714         DWORD written;
715         DWORD readden;
716         DWORD dummy;
717         DWORD success;
718         OVERLAPPED oConnect;
719         OVERLAPPED oRead;
720         OVERLAPPED oWrite;
721         OVERLAPPED *oResult;
722         DWORD err;
723         ULONG_PTR compkey;
724
725         memset(&oConnect, 0, sizeof(oConnect));
726         memset(&oRead, 0, sizeof(oRead));
727         memset(&oWrite, 0, sizeof(oWrite));
728
729         /* Wait for client to connect */
730         trace("Server calling overlapped ConnectNamedPipe...\n");
731         success = ConnectNamedPipe(hnp, &oConnect);
732         err = GetLastError();
733         ok(!success && (err == ERROR_IO_PENDING || err == ERROR_PIPE_CONNECTED),
734            "overlapped ConnectNamedPipe got %u err %u\n", success, err );
735         if (!success && err == ERROR_IO_PENDING) {
736             trace("ConnectNamedPipe GetQueuedCompletionStatus\n");
737             success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 0);
738             if (!success)
739             {
740                 ok( GetLastError() == WAIT_TIMEOUT,
741                     "ConnectNamedPipe GetQueuedCompletionStatus wrong error %u\n", GetLastError());
742                 success = GetQueuedCompletionStatus(hcompletion, &dummy, &compkey, &oResult, 10000);
743             }
744             ok(success, "ConnectNamedPipe GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
745             if (success)
746             {
747                 ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
748                 ok(oResult == &oConnect, "got overlapped pointer %p instead of %p\n", oResult, &oConnect);
749             }
750         }
751         trace("overlapped ConnectNamedPipe operation complete.\n");
752
753         /* Echo bytes once */
754         memset(buf, 0, sizeof(buf));
755
756         trace("Server reading...\n");
757         success = ReadFile(hnp, buf, sizeof(buf), &readden, &oRead);
758         trace("Server ReadFile returned...\n");
759         err = GetLastError();
760         ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile, err=%i\n", err);
761         success = GetQueuedCompletionStatus(hcompletion, &readden, &compkey,
762             &oResult, 10000);
763         ok(success, "ReadFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
764         if (success)
765         {
766             ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
767             ok(oResult == &oRead, "got overlapped pointer %p instead of %p\n", oResult, &oRead);
768         }
769         trace("Server done reading.\n");
770
771         trace("Server writing...\n");
772         success = WriteFile(hnp, buf, readden, &written, &oWrite);
773         trace("Server WriteFile returned...\n");
774         err = GetLastError();
775         ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile failed, err=%u\n", err);
776         success = GetQueuedCompletionStatus(hcompletion, &written, &compkey,
777             &oResult, 10000);
778         ok(success, "WriteFile GetQueuedCompletionStatus failed, errno=%i\n", GetLastError());
779         if (success)
780         {
781             ok(compkey == 12345, "got completion key %i instead of 12345\n", (int)compkey);
782             ok(oResult == &oWrite, "got overlapped pointer %p instead of %p\n", oResult, &oWrite);
783             ok(written == readden, "write file len\n");
784         }
785         trace("Server done writing.\n");
786
787         /* finish this connection, wait for next one */
788         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
789         success = DisconnectNamedPipe(hnp);
790         ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
791     }
792
793     ret = CloseHandle(hnp);
794     ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
795     ret = CloseHandle(hcompletion);
796     ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
797
798     return 0;
799 }
800
801 static void exercizeServer(const char *pipename, HANDLE serverThread)
802 {
803     int i;
804
805     trace("exercizeServer starting\n");
806     for (i = 0; i < NB_SERVER_LOOPS; i++) {
807         HANDLE hFile=INVALID_HANDLE_VALUE;
808         static const char obuf[] = "Bit Bucket";
809         char ibuf[32];
810         DWORD written;
811         DWORD readden;
812         int loop;
813
814         for (loop = 0; loop < 3; loop++) {
815             DWORD err;
816             trace("Client connecting...\n");
817             /* Connect to the server */
818             hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
819                 NULL, OPEN_EXISTING, 0, 0);
820             if (hFile != INVALID_HANDLE_VALUE)
821                 break;
822             err = GetLastError();
823             if (loop == 0)
824                 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
825             else
826                 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
827             trace("connect failed, retrying\n");
828             Sleep(200);
829         }
830         ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
831
832         /* Make sure it can echo */
833         memset(ibuf, 0, sizeof(ibuf));
834         trace("Client writing...\n");
835         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
836         ok(written == sizeof(obuf), "write file len\n");
837         trace("Client reading...\n");
838         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
839         ok(readden == sizeof(obuf), "read file len\n");
840         ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
841
842         trace("Client closing...\n");
843         ok(CloseHandle(hFile), "CloseHandle\n");
844     }
845
846     ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
847     CloseHandle(hnp);
848     trace("exercizeServer returning\n");
849 }
850
851 static void test_NamedPipe_2(void)
852 {
853     HANDLE serverThread;
854     DWORD serverThreadId;
855     HANDLE alarmThread;
856     DWORD alarmThreadId;
857
858     trace("test_NamedPipe_2 starting\n");
859     /* Set up a twenty second timeout */
860     alarm_event = CreateEvent( NULL, TRUE, FALSE, NULL );
861     SetLastError(0xdeadbeef);
862     alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
863     ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
864
865     /* The servers we're about to exercise do try to clean up carefully,
866      * but to reduce the chance of a test failure due to a pipe handle
867      * leak in the test code, we'll use a different pipe name for each server.
868      */
869
870     /* Try server #1 */
871     SetLastError(0xdeadbeef);
872     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
873     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
874     exercizeServer(PIPENAME "serverThreadMain1", serverThread);
875
876     /* Try server #2 */
877     SetLastError(0xdeadbeef);
878     serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
879     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
880     exercizeServer(PIPENAME "serverThreadMain2", serverThread);
881
882     /* Try server #3 */
883     SetLastError(0xdeadbeef);
884     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
885     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
886     exercizeServer(PIPENAME "serverThreadMain3", serverThread);
887
888     /* Try server #4 */
889     SetLastError(0xdeadbeef);
890     serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
891     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
892     exercizeServer(PIPENAME "serverThreadMain4", serverThread);
893
894     ok(SetEvent( alarm_event ), "SetEvent\n");
895     CloseHandle( alarm_event );
896     trace("test_NamedPipe_2 returning\n");
897 }
898
899 static int test_DisconnectNamedPipe(void)
900 {
901     HANDLE hnp;
902     HANDLE hFile;
903     static const char obuf[] = "Bit Bucket";
904     char ibuf[32];
905     DWORD written;
906     DWORD readden;
907     DWORD ret;
908
909     SetLastError(0xdeadbeef);
910     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
911         /* nMaxInstances */ 1,
912         /* nOutBufSize */ 1024,
913         /* nInBufSize */ 1024,
914         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
915         /* lpSecurityAttrib */ NULL);
916     if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
917         && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
918
919         win_skip("Named pipes are not implemented\n");
920         return 1;
921     }
922
923     ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
924         && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
925     ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
926         && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
927
928     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
929     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
930
931     /* don't try to do i/o if one side couldn't be opened, as it hangs */
932     if (hFile != INVALID_HANDLE_VALUE) {
933
934         /* see what happens if server calls DisconnectNamedPipe
935          * when there are bytes in the pipe
936          */
937
938         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
939         ok(written == sizeof(obuf), "write file len\n");
940         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
941         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
942             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
943         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
944             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
945             "ReadFile from disconnected pipe with bytes waiting\n");
946         ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
947            "DisconnectNamedPipe worked twice\n");
948         ret = WaitForSingleObject(hFile, 0);
949         ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
950         ok(CloseHandle(hFile), "CloseHandle\n");
951     }
952
953     ok(CloseHandle(hnp), "CloseHandle\n");
954
955     return 0;
956 }
957 static void test_CreatePipe(void)
958 {
959     SECURITY_ATTRIBUTES pipe_attr;
960     HANDLE piperead, pipewrite;
961     DWORD written;
962     DWORD read;
963     DWORD i, size;
964     BYTE *buffer;
965     char readbuf[32];
966
967     user_apc_ran = FALSE;
968     if (pQueueUserAPC)
969         ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
970
971     pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES); 
972     pipe_attr.bInheritHandle = TRUE; 
973     pipe_attr.lpSecurityDescriptor = NULL;
974     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
975     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
976     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
977     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
978     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
979     ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
980     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
981
982     /* Now write another chunk*/
983     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
984     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
985     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
986     /* and close the write end, read should still succeed*/
987     ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
988     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
989     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
990     /* But now we need to get informed that the pipe is closed */
991     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
992     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
993
994     /* Try bigger chunks */
995     size = 32768;
996     buffer = HeapAlloc( GetProcessHeap(), 0, size );
997     for (i = 0; i < size; i++) buffer[i] = i;
998     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
999     ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1000     ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1001     /* and close the write end, read should still succeed*/
1002     ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1003     memset( buffer, 0, size );
1004     ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
1005     ok(read == size, "Read from  anonymous pipe got %d bytes\n", read);
1006     for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1007     /* But now we need to get informed that the pipe is closed */
1008     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1009     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1010     HeapFree(GetProcessHeap(), 0, buffer);
1011
1012     ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1013     SleepEx(0, TRUE); /* get rid of apc */
1014 }
1015
1016 struct named_pipe_client_params
1017 {
1018     DWORD security_flags;
1019     HANDLE token;
1020     BOOL revert;
1021 };
1022
1023 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1024
1025 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1026 {
1027     struct named_pipe_client_params *params = p;
1028     HANDLE pipe;
1029     BOOL ret;
1030     const char message[] = "Test";
1031     DWORD bytes_read, bytes_written;
1032     char dummy;
1033     TOKEN_PRIVILEGES *Privileges = NULL;
1034
1035     if (params->token)
1036     {
1037         if (params->revert)
1038         {
1039             /* modify the token so we can tell if the pipe impersonation
1040              * token reverts to the process token */
1041             ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1042             ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1043         }
1044         ret = SetThreadToken(NULL, params->token);
1045         ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1046     }
1047     else
1048     {
1049         DWORD Size = 0;
1050         HANDLE process_token;
1051
1052         ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1053         ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1054
1055         ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1056         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1057         Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1058         ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1059         ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1060
1061         ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1062         ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1063
1064         CloseHandle(process_token);
1065     }
1066
1067     pipe = CreateFile(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1068     ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1069
1070     ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1071     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1072
1073     ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1074     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1075
1076     if (params->token)
1077     {
1078         if (params->revert)
1079         {
1080             ret = RevertToSelf();
1081             ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1082         }
1083         else
1084         {
1085             ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1086             ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1087         }
1088     }
1089     else
1090     {
1091         HANDLE process_token;
1092
1093         ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1094         ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1095
1096         ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1097         ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1098
1099         HeapFree(GetProcessHeap(), 0, Privileges);
1100
1101         CloseHandle(process_token);
1102     }
1103
1104     ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1105     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1106
1107     ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1108     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1109
1110     CloseHandle(pipe);
1111
1112     return 0;
1113 }
1114
1115 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1116 {
1117     HANDLE ProcessToken;
1118     HANDLE Token = NULL;
1119     BOOL ret;
1120
1121     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1122     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1123
1124     ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1125     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1126
1127     CloseHandle(ProcessToken);
1128
1129     return Token;
1130 }
1131
1132 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1133 {
1134     HANDLE hPipeServer;
1135     BOOL ret;
1136     DWORD dwTid;
1137     HANDLE hThread;
1138     char buffer[256];
1139     DWORD dwBytesRead;
1140     DWORD error;
1141     struct named_pipe_client_params params;
1142     char dummy = 0;
1143     DWORD dwBytesWritten;
1144     HANDLE hToken = NULL;
1145     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1146     DWORD size;
1147
1148     hPipeServer = CreateNamedPipe(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1149     ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1150
1151     params.security_flags = security_flags;
1152     params.token = hClientToken;
1153     params.revert = revert;
1154     hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1155     ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1156
1157     SetLastError(0xdeadbeef);
1158     ret = ImpersonateNamedPipeClient(hPipeServer);
1159     error = GetLastError();
1160     ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1161        "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1162
1163     ret = ConnectNamedPipe(hPipeServer, NULL);
1164     ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1165
1166     ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1167     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1168
1169     ret = ImpersonateNamedPipeClient(hPipeServer);
1170     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1171
1172     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1173     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1174
1175     (*test_func)(0, hToken);
1176
1177     ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1178     ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1179     ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1180     ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1181
1182     CloseHandle(hToken);
1183
1184     RevertToSelf();
1185
1186     ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1187     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1188
1189     ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1190     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1191
1192     ret = ImpersonateNamedPipeClient(hPipeServer);
1193     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1194
1195     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1196     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1197
1198     (*test_func)(1, hToken);
1199
1200     CloseHandle(hToken);
1201
1202     RevertToSelf();
1203
1204     ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1205     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1206
1207     WaitForSingleObject(hThread, INFINITE);
1208
1209     ret = ImpersonateNamedPipeClient(hPipeServer);
1210     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1211
1212     RevertToSelf();
1213
1214     CloseHandle(hThread);
1215     CloseHandle(hPipeServer);
1216 }
1217
1218 static BOOL are_all_privileges_disabled(HANDLE hToken)
1219 {
1220     BOOL ret;
1221     TOKEN_PRIVILEGES *Privileges = NULL;
1222     DWORD Size = 0;
1223     BOOL all_privs_disabled = TRUE;
1224     DWORD i;
1225
1226     ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1227     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1228     {
1229         Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1230         ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1231         if (!ret)
1232         {
1233             HeapFree(GetProcessHeap(), 0, Privileges);
1234             return FALSE;
1235         }
1236     }
1237     else
1238         return FALSE;
1239
1240     for (i = 0; i < Privileges->PrivilegeCount; i++)
1241     {
1242         if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1243         {
1244             all_privs_disabled = FALSE;
1245             break;
1246         }
1247     }
1248
1249     HeapFree(GetProcessHeap(), 0, Privileges);
1250
1251     return all_privs_disabled;
1252 }
1253
1254 static DWORD get_privilege_count(HANDLE hToken)
1255 {
1256     TOKEN_STATISTICS Statistics;
1257     DWORD Size = sizeof(Statistics);
1258     BOOL ret;
1259
1260     ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1261     ok(ret, "GetTokenInformation(TokenStatistics)\n");
1262     if (!ret) return -1;
1263
1264     return Statistics.PrivilegeCount;
1265 }
1266
1267 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1268 {
1269     DWORD priv_count;
1270
1271     switch (call_index)
1272     {
1273     case 0:
1274         priv_count = get_privilege_count(hToken);
1275         todo_wine
1276         ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1277         break;
1278     case 1:
1279         priv_count = get_privilege_count(hToken);
1280         ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1281         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1282         break;
1283     default:
1284         ok(0, "shouldn't happen\n");
1285     }
1286 }
1287
1288 static void test_no_sqos(int call_index, HANDLE hToken)
1289 {
1290     switch (call_index)
1291     {
1292     case 0:
1293         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1294         break;
1295     case 1:
1296         todo_wine
1297         ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1298         break;
1299     default:
1300         ok(0, "shouldn't happen\n");
1301     }
1302 }
1303
1304 static void test_static_context(int call_index, HANDLE hToken)
1305 {
1306     switch (call_index)
1307     {
1308     case 0:
1309         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1310         break;
1311     case 1:
1312         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1313         break;
1314     default:
1315         ok(0, "shouldn't happen\n");
1316     }
1317 }
1318
1319 static void test_dynamic_context(int call_index, HANDLE hToken)
1320 {
1321     switch (call_index)
1322     {
1323     case 0:
1324         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1325         break;
1326     case 1:
1327         todo_wine
1328         ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1329         break;
1330     default:
1331         ok(0, "shouldn't happen\n");
1332     }
1333 }
1334
1335 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1336 {
1337     switch (call_index)
1338     {
1339     case 0:
1340         ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1341         break;
1342     case 1:
1343         ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1344         break;
1345     default:
1346         ok(0, "shouldn't happen\n");
1347     }
1348 }
1349
1350 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1351 {
1352     DWORD priv_count;
1353     switch (call_index)
1354     {
1355     case 0:
1356         priv_count = get_privilege_count(hToken);
1357         todo_wine
1358         ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1359         break;
1360     case 1:
1361         priv_count = get_privilege_count(hToken);
1362         ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1363         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1364         break;
1365     default:
1366         ok(0, "shouldn't happen\n");
1367     }
1368 }
1369
1370 static void test_static_context_revert(int call_index, HANDLE hToken)
1371 {
1372     switch (call_index)
1373     {
1374     case 0:
1375         todo_wine
1376         ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1377         break;
1378     case 1:
1379         todo_wine
1380         ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1381         break;
1382     default:
1383         ok(0, "shouldn't happen\n");
1384     }
1385 }
1386
1387 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1388 {
1389     switch (call_index)
1390     {
1391     case 0:
1392         todo_wine
1393         ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1394         break;
1395     case 1:
1396         ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1397         break;
1398     default:
1399         ok(0, "shouldn't happen\n");
1400     }
1401 }
1402
1403 static void test_impersonation(void)
1404 {
1405     HANDLE hClientToken;
1406     HANDLE hProcessToken;
1407     BOOL ret;
1408
1409     if( !pDuplicateTokenEx ) {
1410         skip("DuplicateTokenEx not found\n");
1411         return;
1412     }
1413
1414     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1415     if (!ret)
1416     {
1417         skip("couldn't open process token, skipping impersonation tests\n");
1418         return;
1419     }
1420
1421     if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
1422     {
1423         skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
1424         CloseHandle(hProcessToken);
1425         return;
1426     }
1427     CloseHandle(hProcessToken);
1428
1429     test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
1430     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1431     test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
1432     CloseHandle(hClientToken);
1433     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1434     test_ImpersonateNamedPipeClient(hClientToken,
1435         SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
1436         test_static_context);
1437     CloseHandle(hClientToken);
1438     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1439     test_ImpersonateNamedPipeClient(hClientToken,
1440         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1441         FALSE, test_dynamic_context);
1442     CloseHandle(hClientToken);
1443     test_ImpersonateNamedPipeClient(NULL,
1444         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1445         FALSE, test_dynamic_context_no_token);
1446
1447     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1448     test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
1449     CloseHandle(hClientToken);
1450     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1451     test_ImpersonateNamedPipeClient(hClientToken,
1452         SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
1453         test_static_context_revert);
1454     CloseHandle(hClientToken);
1455     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1456     test_ImpersonateNamedPipeClient(hClientToken,
1457         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1458         TRUE, test_dynamic_context_revert);
1459     CloseHandle(hClientToken);
1460 }
1461
1462 struct overlapped_server_args
1463 {
1464     HANDLE pipe_created;
1465 };
1466
1467 static DWORD CALLBACK overlapped_server(LPVOID arg)
1468 {
1469     OVERLAPPED ol;
1470     HANDLE pipe;
1471     int ret, err;
1472     struct overlapped_server_args *a = arg;
1473     DWORD num;
1474     char buf[100];
1475
1476     pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
1477     ok(pipe != NULL, "pipe NULL\n");
1478
1479     ol.hEvent = CreateEventA(0, 1, 0, 0);
1480     ok(ol.hEvent != NULL, "event NULL\n");
1481     ret = ConnectNamedPipe(pipe, &ol);
1482     err = GetLastError();
1483     ok(ret == 0, "ret %d\n", ret);
1484     ok(err == ERROR_IO_PENDING, "gle %d\n", err);
1485     SetEvent(a->pipe_created);
1486
1487     ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
1488     ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
1489
1490     ret = GetOverlappedResult(pipe, &ol, &num, 1);
1491     ok(ret == 1, "ret %d\n", ret);
1492
1493     /* This should block */
1494     ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
1495     ok(ret == 1, "ret %d\n", ret);
1496
1497     DisconnectNamedPipe(pipe);
1498     CloseHandle(ol.hEvent);
1499     CloseHandle(pipe);
1500     return 1;
1501 }
1502
1503 static void test_overlapped(void)
1504 {
1505     DWORD tid, num;
1506     HANDLE thread, pipe;
1507     BOOL ret;
1508     struct overlapped_server_args args;
1509
1510     args.pipe_created = CreateEventA(0, 1, 0, 0);
1511     thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
1512
1513     WaitForSingleObject(args.pipe_created, INFINITE);
1514     pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1515     ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
1516
1517     /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
1518     Sleep(1);
1519
1520     ret = WriteFile(pipe, "x", 1, &num, NULL);
1521     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1522
1523     WaitForSingleObject(thread, INFINITE);
1524     CloseHandle(pipe);
1525     CloseHandle(args.pipe_created);
1526     CloseHandle(thread);
1527 }
1528
1529 static void test_NamedPipeHandleState(void)
1530 {
1531     HANDLE server, client;
1532     BOOL ret;
1533     DWORD state, instances, maxCollectionCount, collectDataTimeout;
1534     char userName[MAX_PATH];
1535
1536     server = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX,
1537         /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1538         /* nMaxInstances */ 1,
1539         /* nOutBufSize */ 1024,
1540         /* nInBufSize */ 1024,
1541         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1542         /* lpSecurityAttrib */ NULL);
1543     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1544     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
1545     todo_wine
1546     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1547     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
1548         0);
1549     todo_wine
1550     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1551     if (ret)
1552     {
1553         ok(state == 0, "unexpected state %08x\n", state);
1554         ok(instances == 1, "expected 1 instances, got %d\n", instances);
1555     }
1556     /* Some parameters have no meaning, and therefore can't be retrieved,
1557      * on a local pipe.
1558      */
1559     SetLastError(0xdeadbeef);
1560     ret = GetNamedPipeHandleState(server, &state, &instances,
1561         &maxCollectionCount, &collectDataTimeout, userName,
1562         sizeof(userName) / sizeof(userName[0]));
1563     todo_wine
1564     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1565        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1566     /* A byte-mode pipe server can't be changed to message mode. */
1567     state = PIPE_READMODE_MESSAGE;
1568     SetLastError(0xdeadbeef);
1569     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1570     todo_wine
1571     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1572        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1573
1574     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1575         OPEN_EXISTING, 0, NULL);
1576     ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1577
1578     state = PIPE_READMODE_BYTE;
1579     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1580     todo_wine
1581     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1582     /* A byte-mode pipe client can't be changed to message mode, either. */
1583     state = PIPE_READMODE_MESSAGE;
1584     SetLastError(0xdeadbeef);
1585     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1586     todo_wine
1587     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1588        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1589
1590     CloseHandle(client);
1591     CloseHandle(server);
1592
1593     server = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX,
1594         /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
1595         /* nMaxInstances */ 1,
1596         /* nOutBufSize */ 1024,
1597         /* nInBufSize */ 1024,
1598         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1599         /* lpSecurityAttrib */ NULL);
1600     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1601     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
1602     todo_wine
1603     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1604     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
1605         0);
1606     todo_wine
1607     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1608     if (ret)
1609     {
1610         ok(state == 0, "unexpected state %08x\n", state);
1611         ok(instances == 1, "expected 1 instances, got %d\n", instances);
1612     }
1613     /* In contrast to byte-mode pipes, a message-mode pipe server can be
1614      * changed to byte mode.
1615      */
1616     state = PIPE_READMODE_BYTE;
1617     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1618     todo_wine
1619     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1620
1621     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1622         OPEN_EXISTING, 0, NULL);
1623     ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1624
1625     state = PIPE_READMODE_MESSAGE;
1626     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1627     todo_wine
1628     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1629     /* A message-mode pipe client can also be changed to byte mode.
1630      */
1631     state = PIPE_READMODE_BYTE;
1632     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1633     todo_wine
1634     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1635
1636     CloseHandle(client);
1637     CloseHandle(server);
1638 }
1639
1640 START_TEST(pipe)
1641 {
1642     HMODULE hmod;
1643
1644     hmod = GetModuleHandle("advapi32.dll");
1645     pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
1646     hmod = GetModuleHandle("kernel32.dll");
1647     pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
1648
1649     if (test_DisconnectNamedPipe())
1650         return;
1651     test_CreateNamedPipe_instances_must_match();
1652     test_NamedPipe_2();
1653     test_CreateNamedPipe(PIPE_TYPE_BYTE);
1654     test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1655     test_CreatePipe();
1656     test_impersonation();
1657     test_overlapped();
1658     test_NamedPipeHandleState();
1659 }