kernel32: Conditional variable tests.
[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 int completion_called;
802 static DWORD completion_errorcode;
803 static DWORD completion_num_bytes;
804 static LPOVERLAPPED completion_lpoverlapped;
805
806 static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
807 {
808     completion_called++;
809     completion_errorcode = errorcode;
810     completion_num_bytes = num_bytes;
811     completion_lpoverlapped = lpoverlapped;
812     SetEvent(lpoverlapped->hEvent);
813 }
814
815 /** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
816 static DWORD CALLBACK serverThreadMain5(LPVOID arg)
817 {
818     int i;
819     HANDLE hEvent;
820
821     trace("serverThreadMain5\n");
822     /* Set up a simple echo server */
823     hnp = CreateNamedPipe(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
824         PIPE_TYPE_BYTE | PIPE_WAIT,
825         /* nMaxInstances */ 1,
826         /* nOutBufSize */ 1024,
827         /* nInBufSize */ 1024,
828         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
829         /* lpSecurityAttrib */ NULL);
830     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
831
832     hEvent = CreateEvent(NULL,  /* security attribute */
833         TRUE,                   /* manual reset event */
834         FALSE,                  /* initial state */
835         NULL);                  /* name */
836     ok(hEvent != NULL, "CreateEvent\n");
837
838     for (i = 0; i < NB_SERVER_LOOPS; i++) {
839         char buf[512];
840         DWORD readden;
841         DWORD success;
842         OVERLAPPED oOverlap;
843         DWORD err;
844
845         memset(&oOverlap, 0, sizeof(oOverlap));
846         oOverlap.hEvent = hEvent;
847
848         /* Wait for client to connect */
849         trace("Server calling ConnectNamedPipe...\n");
850         success = ConnectNamedPipe(hnp, NULL);
851         err = GetLastError();
852         ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
853         trace("ConnectNamedPipe operation complete.\n");
854
855         /* Echo bytes once */
856         memset(buf, 0, sizeof(buf));
857
858         trace("Server reading...\n");
859         completion_called = 0;
860         ResetEvent(hEvent);
861         success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
862         trace("Server ReadFileEx returned...\n");
863         ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
864         ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
865         trace("ReadFileEx returned.\n");
866         if (success) {
867             DWORD ret;
868             do {
869                 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
870             } while (ret == WAIT_IO_COMPLETION);
871             ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
872         }
873         ok(completion_called == 1, "completion routine called %i times\n", completion_called);
874         ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
875         ok(completion_num_bytes != 0, "read 0 bytes\n");
876         ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
877         readden = completion_num_bytes;
878         trace("Server done reading.\n");
879
880         trace("Server writing...\n");
881         completion_called = 0;
882         ResetEvent(hEvent);
883         success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
884         trace("Server WriteFileEx returned...\n");
885         ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
886         ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
887         trace("overlapped WriteFile returned.\n");
888         if (success) {
889             DWORD ret;
890             do {
891                 ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
892             } while (ret == WAIT_IO_COMPLETION);
893             ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
894         }
895         trace("Server done writing.\n");
896         ok(completion_called == 1, "completion routine called %i times\n", completion_called);
897         ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
898         ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
899         ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
900
901         /* finish this connection, wait for next one */
902         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
903         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
904     }
905     return 0;
906 }
907
908 static void exercizeServer(const char *pipename, HANDLE serverThread)
909 {
910     int i;
911
912     trace("exercizeServer starting\n");
913     for (i = 0; i < NB_SERVER_LOOPS; i++) {
914         HANDLE hFile=INVALID_HANDLE_VALUE;
915         static const char obuf[] = "Bit Bucket";
916         char ibuf[32];
917         DWORD written;
918         DWORD readden;
919         int loop;
920
921         for (loop = 0; loop < 3; loop++) {
922             DWORD err;
923             trace("Client connecting...\n");
924             /* Connect to the server */
925             hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
926                 NULL, OPEN_EXISTING, 0, 0);
927             if (hFile != INVALID_HANDLE_VALUE)
928                 break;
929             err = GetLastError();
930             if (loop == 0)
931                 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
932             else
933                 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
934             trace("connect failed, retrying\n");
935             Sleep(200);
936         }
937         ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
938
939         /* Make sure it can echo */
940         memset(ibuf, 0, sizeof(ibuf));
941         trace("Client writing...\n");
942         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
943         ok(written == sizeof(obuf), "write file len\n");
944         trace("Client reading...\n");
945         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
946         ok(readden == sizeof(obuf), "read file len\n");
947         ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
948
949         trace("Client closing...\n");
950         ok(CloseHandle(hFile), "CloseHandle\n");
951     }
952
953     ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
954     CloseHandle(hnp);
955     trace("exercizeServer returning\n");
956 }
957
958 static void test_NamedPipe_2(void)
959 {
960     HANDLE serverThread;
961     DWORD serverThreadId;
962     HANDLE alarmThread;
963     DWORD alarmThreadId;
964
965     trace("test_NamedPipe_2 starting\n");
966     /* Set up a twenty second timeout */
967     alarm_event = CreateEvent( NULL, TRUE, FALSE, NULL );
968     SetLastError(0xdeadbeef);
969     alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 20000, 0, &alarmThreadId);
970     ok(alarmThread != NULL, "CreateThread failed: %d\n", GetLastError());
971
972     /* The servers we're about to exercise do try to clean up carefully,
973      * but to reduce the chance of a test failure due to a pipe handle
974      * leak in the test code, we'll use a different pipe name for each server.
975      */
976
977     /* Try server #1 */
978     SetLastError(0xdeadbeef);
979     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
980     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
981     exercizeServer(PIPENAME "serverThreadMain1", serverThread);
982
983     /* Try server #2 */
984     SetLastError(0xdeadbeef);
985     serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
986     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
987     exercizeServer(PIPENAME "serverThreadMain2", serverThread);
988
989     /* Try server #3 */
990     SetLastError(0xdeadbeef);
991     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
992     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
993     exercizeServer(PIPENAME "serverThreadMain3", serverThread);
994
995     /* Try server #4 */
996     SetLastError(0xdeadbeef);
997     serverThread = CreateThread(NULL, 0, serverThreadMain4, 0, 0, &serverThreadId);
998     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
999     exercizeServer(PIPENAME "serverThreadMain4", serverThread);
1000
1001     /* Try server #5 */
1002     SetLastError(0xdeadbeef);
1003     serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
1004     ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
1005     exercizeServer(PIPENAME "serverThreadMain5", serverThread);
1006
1007     ok(SetEvent( alarm_event ), "SetEvent\n");
1008     CloseHandle( alarm_event );
1009     trace("test_NamedPipe_2 returning\n");
1010 }
1011
1012 static int test_DisconnectNamedPipe(void)
1013 {
1014     HANDLE hnp;
1015     HANDLE hFile;
1016     static const char obuf[] = "Bit Bucket";
1017     char ibuf[32];
1018     DWORD written;
1019     DWORD readden;
1020     DWORD ret;
1021
1022     SetLastError(0xdeadbeef);
1023     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
1024         /* nMaxInstances */ 1,
1025         /* nOutBufSize */ 1024,
1026         /* nInBufSize */ 1024,
1027         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1028         /* lpSecurityAttrib */ NULL);
1029     if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
1030         && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
1031
1032         win_skip("Named pipes are not implemented\n");
1033         return 1;
1034     }
1035
1036     ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
1037         && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
1038     ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1039         && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
1040
1041     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1042     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1043
1044     /* don't try to do i/o if one side couldn't be opened, as it hangs */
1045     if (hFile != INVALID_HANDLE_VALUE) {
1046
1047         /* see what happens if server calls DisconnectNamedPipe
1048          * when there are bytes in the pipe
1049          */
1050
1051         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
1052         ok(written == sizeof(obuf), "write file len\n");
1053         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
1054         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
1055             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
1056         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
1057             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1058             "ReadFile from disconnected pipe with bytes waiting\n");
1059         ok(!DisconnectNamedPipe(hnp) && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
1060            "DisconnectNamedPipe worked twice\n");
1061         ret = WaitForSingleObject(hFile, 0);
1062         ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %X\n", ret);
1063         ok(CloseHandle(hFile), "CloseHandle\n");
1064     }
1065
1066     ok(CloseHandle(hnp), "CloseHandle\n");
1067
1068     return 0;
1069 }
1070 static void test_CreatePipe(void)
1071 {
1072     SECURITY_ATTRIBUTES pipe_attr;
1073     HANDLE piperead, pipewrite;
1074     DWORD written;
1075     DWORD read;
1076     DWORD i, size;
1077     BYTE *buffer;
1078     char readbuf[32];
1079
1080     user_apc_ran = FALSE;
1081     if (pQueueUserAPC)
1082         ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
1083
1084     pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES); 
1085     pipe_attr.bInheritHandle = TRUE; 
1086     pipe_attr.lpSecurityDescriptor = NULL;
1087     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1088     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1089     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1090     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
1091     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
1092     ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
1093     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1094
1095     /* Now write another chunk*/
1096     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
1097     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
1098     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
1099     /* and close the write end, read should still succeed*/
1100     ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1101     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
1102     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
1103     /* But now we need to get informed that the pipe is closed */
1104     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1105     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1106
1107     /* Try bigger chunks */
1108     size = 32768;
1109     buffer = HeapAlloc( GetProcessHeap(), 0, size );
1110     for (i = 0; i < size; i++) buffer[i] = i;
1111     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
1112     ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
1113     ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
1114     /* and close the write end, read should still succeed*/
1115     ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
1116     memset( buffer, 0, size );
1117     ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
1118     ok(read == size, "Read from  anonymous pipe got %d bytes\n", read);
1119     for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
1120     /* But now we need to get informed that the pipe is closed */
1121     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
1122     ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
1123     HeapFree(GetProcessHeap(), 0, buffer);
1124
1125     ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
1126     SleepEx(0, TRUE); /* get rid of apc */
1127 }
1128
1129 struct named_pipe_client_params
1130 {
1131     DWORD security_flags;
1132     HANDLE token;
1133     BOOL revert;
1134 };
1135
1136 #define PIPE_NAME "\\\\.\\pipe\\named_pipe_test"
1137
1138 static DWORD CALLBACK named_pipe_client_func(LPVOID p)
1139 {
1140     struct named_pipe_client_params *params = p;
1141     HANDLE pipe;
1142     BOOL ret;
1143     const char message[] = "Test";
1144     DWORD bytes_read, bytes_written;
1145     char dummy;
1146     TOKEN_PRIVILEGES *Privileges = NULL;
1147
1148     if (params->token)
1149     {
1150         if (params->revert)
1151         {
1152             /* modify the token so we can tell if the pipe impersonation
1153              * token reverts to the process token */
1154             ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1155             ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1156         }
1157         ret = SetThreadToken(NULL, params->token);
1158         ok(ret, "SetThreadToken failed with error %d\n", GetLastError());
1159     }
1160     else
1161     {
1162         DWORD Size = 0;
1163         HANDLE process_token;
1164
1165         ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &process_token);
1166         ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1167
1168         ret = GetTokenInformation(process_token, TokenPrivileges, NULL, 0, &Size);
1169         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1170         Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1171         ret = GetTokenInformation(process_token, TokenPrivileges, Privileges, Size, &Size);
1172         ok(ret, "GetTokenInformation(TokenPrivileges) failed with %d\n", GetLastError());
1173
1174         ret = AdjustTokenPrivileges(process_token, TRUE, NULL, 0, NULL, NULL);
1175         ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1176
1177         CloseHandle(process_token);
1178     }
1179
1180     pipe = CreateFile(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, params->security_flags, NULL);
1181     ok(pipe != INVALID_HANDLE_VALUE, "CreateFile for pipe failed with error %d\n", GetLastError());
1182
1183     ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1184     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1185
1186     ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1187     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1188
1189     if (params->token)
1190     {
1191         if (params->revert)
1192         {
1193             ret = RevertToSelf();
1194             ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1195         }
1196         else
1197         {
1198             ret = AdjustTokenPrivileges(params->token, TRUE, NULL, 0, NULL, NULL);
1199             ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1200         }
1201     }
1202     else
1203     {
1204         HANDLE process_token;
1205
1206         ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &process_token);
1207         ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1208
1209         ret = AdjustTokenPrivileges(process_token, FALSE, Privileges, 0, NULL, NULL);
1210         ok(ret, "AdjustTokenPrivileges failed with error %d\n", GetLastError());
1211
1212         HeapFree(GetProcessHeap(), 0, Privileges);
1213
1214         CloseHandle(process_token);
1215     }
1216
1217     ret = WriteFile(pipe, message, sizeof(message), &bytes_written, NULL);
1218     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1219
1220     ret = ReadFile(pipe, &dummy, sizeof(dummy), &bytes_read, NULL);
1221     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1222
1223     CloseHandle(pipe);
1224
1225     return 0;
1226 }
1227
1228 static HANDLE make_impersonation_token(DWORD Access, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1229 {
1230     HANDLE ProcessToken;
1231     HANDLE Token = NULL;
1232     BOOL ret;
1233
1234     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1235     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1236
1237     ret = pDuplicateTokenEx(ProcessToken, Access, NULL, ImpersonationLevel, TokenImpersonation, &Token);
1238     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1239
1240     CloseHandle(ProcessToken);
1241
1242     return Token;
1243 }
1244
1245 static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_flags, BOOL revert, void (*test_func)(int, HANDLE))
1246 {
1247     HANDLE hPipeServer;
1248     BOOL ret;
1249     DWORD dwTid;
1250     HANDLE hThread;
1251     char buffer[256];
1252     DWORD dwBytesRead;
1253     DWORD error;
1254     struct named_pipe_client_params params;
1255     char dummy = 0;
1256     DWORD dwBytesWritten;
1257     HANDLE hToken = NULL;
1258     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1259     DWORD size;
1260
1261     hPipeServer = CreateNamedPipe(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 100, 100, NMPWAIT_USE_DEFAULT_WAIT, NULL);
1262     ok(hPipeServer != INVALID_HANDLE_VALUE, "CreateNamedPipe failed with error %d\n", GetLastError());
1263
1264     params.security_flags = security_flags;
1265     params.token = hClientToken;
1266     params.revert = revert;
1267     hThread = CreateThread(NULL, 0, named_pipe_client_func, &params, 0, &dwTid);
1268     ok(hThread != NULL, "CreateThread failed with error %d\n", GetLastError());
1269
1270     SetLastError(0xdeadbeef);
1271     ret = ImpersonateNamedPipeClient(hPipeServer);
1272     error = GetLastError();
1273     ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
1274        "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
1275
1276     ret = ConnectNamedPipe(hPipeServer, NULL);
1277     ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
1278
1279     ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1280     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1281
1282     ret = ImpersonateNamedPipeClient(hPipeServer);
1283     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1284
1285     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1286     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1287
1288     (*test_func)(0, hToken);
1289
1290     ImpersonationLevel = 0xdeadbeef; /* to avoid false positives */
1291     ret = GetTokenInformation(hToken, TokenImpersonationLevel, &ImpersonationLevel, sizeof(ImpersonationLevel), &size);
1292     ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1293     ok(ImpersonationLevel == SecurityImpersonation, "ImpersonationLevel should have been SecurityImpersonation(%d) instead of %d\n", SecurityImpersonation, ImpersonationLevel);
1294
1295     CloseHandle(hToken);
1296
1297     RevertToSelf();
1298
1299     ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1300     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1301
1302     ret = ReadFile(hPipeServer, buffer, sizeof(buffer), &dwBytesRead, NULL);
1303     ok(ret, "ReadFile failed with error %d\n", GetLastError());
1304
1305     ret = ImpersonateNamedPipeClient(hPipeServer);
1306     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1307
1308     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken);
1309     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1310
1311     (*test_func)(1, hToken);
1312
1313     CloseHandle(hToken);
1314
1315     RevertToSelf();
1316
1317     ret = WriteFile(hPipeServer, &dummy, sizeof(dummy), &dwBytesWritten, NULL);
1318     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1319
1320     WaitForSingleObject(hThread, INFINITE);
1321
1322     ret = ImpersonateNamedPipeClient(hPipeServer);
1323     ok(ret, "ImpersonateNamedPipeClient failed with error %d\n", GetLastError());
1324
1325     RevertToSelf();
1326
1327     CloseHandle(hThread);
1328     CloseHandle(hPipeServer);
1329 }
1330
1331 static BOOL are_all_privileges_disabled(HANDLE hToken)
1332 {
1333     BOOL ret;
1334     TOKEN_PRIVILEGES *Privileges = NULL;
1335     DWORD Size = 0;
1336     BOOL all_privs_disabled = TRUE;
1337     DWORD i;
1338
1339     ret = GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &Size);
1340     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1341     {
1342         Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1343         ret = GetTokenInformation(hToken, TokenPrivileges, Privileges, Size, &Size);
1344         if (!ret)
1345         {
1346             HeapFree(GetProcessHeap(), 0, Privileges);
1347             return FALSE;
1348         }
1349     }
1350     else
1351         return FALSE;
1352
1353     for (i = 0; i < Privileges->PrivilegeCount; i++)
1354     {
1355         if (Privileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
1356         {
1357             all_privs_disabled = FALSE;
1358             break;
1359         }
1360     }
1361
1362     HeapFree(GetProcessHeap(), 0, Privileges);
1363
1364     return all_privs_disabled;
1365 }
1366
1367 static DWORD get_privilege_count(HANDLE hToken)
1368 {
1369     TOKEN_STATISTICS Statistics;
1370     DWORD Size = sizeof(Statistics);
1371     BOOL ret;
1372
1373     ret = GetTokenInformation(hToken, TokenStatistics, &Statistics, Size, &Size);
1374     ok(ret, "GetTokenInformation(TokenStatistics)\n");
1375     if (!ret) return -1;
1376
1377     return Statistics.PrivilegeCount;
1378 }
1379
1380 static void test_no_sqos_no_token(int call_index, HANDLE hToken)
1381 {
1382     DWORD priv_count;
1383
1384     switch (call_index)
1385     {
1386     case 0:
1387         priv_count = get_privilege_count(hToken);
1388         todo_wine
1389         ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1390         break;
1391     case 1:
1392         priv_count = get_privilege_count(hToken);
1393         ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1394         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1395         break;
1396     default:
1397         ok(0, "shouldn't happen\n");
1398     }
1399 }
1400
1401 static void test_no_sqos(int call_index, HANDLE hToken)
1402 {
1403     switch (call_index)
1404     {
1405     case 0:
1406         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1407         break;
1408     case 1:
1409         todo_wine
1410         ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1411         break;
1412     default:
1413         ok(0, "shouldn't happen\n");
1414     }
1415 }
1416
1417 static void test_static_context(int call_index, HANDLE hToken)
1418 {
1419     switch (call_index)
1420     {
1421     case 0:
1422         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1423         break;
1424     case 1:
1425         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1426         break;
1427     default:
1428         ok(0, "shouldn't happen\n");
1429     }
1430 }
1431
1432 static void test_dynamic_context(int call_index, HANDLE hToken)
1433 {
1434     switch (call_index)
1435     {
1436     case 0:
1437         ok(!are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1438         break;
1439     case 1:
1440         todo_wine
1441         ok(are_all_privileges_disabled(hToken), "impersonated token should have been modified\n");
1442         break;
1443     default:
1444         ok(0, "shouldn't happen\n");
1445     }
1446 }
1447
1448 static void test_dynamic_context_no_token(int call_index, HANDLE hToken)
1449 {
1450     switch (call_index)
1451     {
1452     case 0:
1453         ok(are_all_privileges_disabled(hToken), "token should be a copy of the process one\n");
1454         break;
1455     case 1:
1456         ok(!are_all_privileges_disabled(hToken), "process token modification should have been detected and impersonation token updated\n");
1457         break;
1458     default:
1459         ok(0, "shouldn't happen\n");
1460     }
1461 }
1462
1463 static void test_no_sqos_revert(int call_index, HANDLE hToken)
1464 {
1465     DWORD priv_count;
1466     switch (call_index)
1467     {
1468     case 0:
1469         priv_count = get_privilege_count(hToken);
1470         todo_wine
1471         ok(priv_count == 0, "privilege count should have been 0 instead of %d\n", priv_count);
1472         break;
1473     case 1:
1474         priv_count = get_privilege_count(hToken);
1475         ok(priv_count > 0, "privilege count should now be > 0 instead of 0\n");
1476         ok(!are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1477         break;
1478     default:
1479         ok(0, "shouldn't happen\n");
1480     }
1481 }
1482
1483 static void test_static_context_revert(int call_index, HANDLE hToken)
1484 {
1485     switch (call_index)
1486     {
1487     case 0:
1488         todo_wine
1489         ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1490         break;
1491     case 1:
1492         todo_wine
1493         ok(are_all_privileges_disabled(hToken), "impersonated token should not have been modified\n");
1494         break;
1495     default:
1496         ok(0, "shouldn't happen\n");
1497     }
1498 }
1499
1500 static void test_dynamic_context_revert(int call_index, HANDLE hToken)
1501 {
1502     switch (call_index)
1503     {
1504     case 0:
1505         todo_wine
1506         ok(are_all_privileges_disabled(hToken), "privileges should have been disabled\n");
1507         break;
1508     case 1:
1509         ok(!are_all_privileges_disabled(hToken), "impersonated token should now be process token\n");
1510         break;
1511     default:
1512         ok(0, "shouldn't happen\n");
1513     }
1514 }
1515
1516 static void test_impersonation(void)
1517 {
1518     HANDLE hClientToken;
1519     HANDLE hProcessToken;
1520     BOOL ret;
1521
1522     if( !pDuplicateTokenEx ) {
1523         skip("DuplicateTokenEx not found\n");
1524         return;
1525     }
1526
1527     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
1528     if (!ret)
1529     {
1530         skip("couldn't open process token, skipping impersonation tests\n");
1531         return;
1532     }
1533
1534     if (!get_privilege_count(hProcessToken) || are_all_privileges_disabled(hProcessToken))
1535     {
1536         skip("token didn't have any privileges or they were all disabled. token not suitable for impersonation tests\n");
1537         CloseHandle(hProcessToken);
1538         return;
1539     }
1540     CloseHandle(hProcessToken);
1541
1542     test_ImpersonateNamedPipeClient(NULL, 0, FALSE, test_no_sqos_no_token);
1543     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1544     test_ImpersonateNamedPipeClient(hClientToken, 0, FALSE, test_no_sqos);
1545     CloseHandle(hClientToken);
1546     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1547     test_ImpersonateNamedPipeClient(hClientToken,
1548         SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, FALSE,
1549         test_static_context);
1550     CloseHandle(hClientToken);
1551     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1552     test_ImpersonateNamedPipeClient(hClientToken,
1553         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1554         FALSE, test_dynamic_context);
1555     CloseHandle(hClientToken);
1556     test_ImpersonateNamedPipeClient(NULL,
1557         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1558         FALSE, test_dynamic_context_no_token);
1559
1560     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1561     test_ImpersonateNamedPipeClient(hClientToken, 0, TRUE, test_no_sqos_revert);
1562     CloseHandle(hClientToken);
1563     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1564     test_ImpersonateNamedPipeClient(hClientToken,
1565         SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, TRUE,
1566         test_static_context_revert);
1567     CloseHandle(hClientToken);
1568     hClientToken = make_impersonation_token(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, SecurityImpersonation);
1569     test_ImpersonateNamedPipeClient(hClientToken,
1570         SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING | SECURITY_IMPERSONATION,
1571         TRUE, test_dynamic_context_revert);
1572     CloseHandle(hClientToken);
1573 }
1574
1575 struct overlapped_server_args
1576 {
1577     HANDLE pipe_created;
1578 };
1579
1580 static DWORD CALLBACK overlapped_server(LPVOID arg)
1581 {
1582     OVERLAPPED ol;
1583     HANDLE pipe;
1584     int ret, err;
1585     struct overlapped_server_args *a = arg;
1586     DWORD num;
1587     char buf[100];
1588
1589     pipe = CreateNamedPipeA("\\\\.\\pipe\\my pipe", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 0, 0, 100000, NULL);
1590     ok(pipe != NULL, "pipe NULL\n");
1591
1592     ol.hEvent = CreateEventA(0, 1, 0, 0);
1593     ok(ol.hEvent != NULL, "event NULL\n");
1594     ret = ConnectNamedPipe(pipe, &ol);
1595     err = GetLastError();
1596     ok(ret == 0, "ret %d\n", ret);
1597     ok(err == ERROR_IO_PENDING, "gle %d\n", err);
1598     SetEvent(a->pipe_created);
1599
1600     ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
1601     ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
1602
1603     ret = GetOverlappedResult(pipe, &ol, &num, 1);
1604     ok(ret == 1, "ret %d\n", ret);
1605
1606     /* This should block */
1607     ret = ReadFile(pipe, buf, sizeof(buf), &num, NULL);
1608     ok(ret == 1, "ret %d\n", ret);
1609
1610     DisconnectNamedPipe(pipe);
1611     CloseHandle(ol.hEvent);
1612     CloseHandle(pipe);
1613     return 1;
1614 }
1615
1616 static void test_overlapped(void)
1617 {
1618     DWORD tid, num;
1619     HANDLE thread, pipe;
1620     BOOL ret;
1621     struct overlapped_server_args args;
1622
1623     args.pipe_created = CreateEventA(0, 1, 0, 0);
1624     thread = CreateThread(NULL, 0, overlapped_server, &args, 0, &tid);
1625
1626     WaitForSingleObject(args.pipe_created, INFINITE);
1627     pipe = CreateFileA("\\\\.\\pipe\\my pipe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1628     ok(pipe != INVALID_HANDLE_VALUE, "cf failed\n");
1629
1630     /* Sleep to try to get the ReadFile in the server to occur before the following WriteFile */
1631     Sleep(1);
1632
1633     ret = WriteFile(pipe, "x", 1, &num, NULL);
1634     ok(ret, "WriteFile failed with error %d\n", GetLastError());
1635
1636     WaitForSingleObject(thread, INFINITE);
1637     CloseHandle(pipe);
1638     CloseHandle(args.pipe_created);
1639     CloseHandle(thread);
1640 }
1641
1642 static void test_NamedPipeHandleState(void)
1643 {
1644     HANDLE server, client;
1645     BOOL ret;
1646     DWORD state, instances, maxCollectionCount, collectDataTimeout;
1647     char userName[MAX_PATH];
1648
1649     server = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX,
1650         /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1651         /* nMaxInstances */ 1,
1652         /* nOutBufSize */ 1024,
1653         /* nInBufSize */ 1024,
1654         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1655         /* lpSecurityAttrib */ NULL);
1656     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1657     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
1658     todo_wine
1659     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1660     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
1661         0);
1662     todo_wine
1663     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1664     if (ret)
1665     {
1666         ok(state == 0, "unexpected state %08x\n", state);
1667         ok(instances == 1, "expected 1 instances, got %d\n", instances);
1668     }
1669     /* Some parameters have no meaning, and therefore can't be retrieved,
1670      * on a local pipe.
1671      */
1672     SetLastError(0xdeadbeef);
1673     ret = GetNamedPipeHandleState(server, &state, &instances,
1674         &maxCollectionCount, &collectDataTimeout, userName,
1675         sizeof(userName) / sizeof(userName[0]));
1676     todo_wine
1677     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1678        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1679     /* A byte-mode pipe server can't be changed to message mode. */
1680     state = PIPE_READMODE_MESSAGE;
1681     SetLastError(0xdeadbeef);
1682     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1683     todo_wine
1684     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1685        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1686
1687     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1688         OPEN_EXISTING, 0, NULL);
1689     ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1690
1691     state = PIPE_READMODE_BYTE;
1692     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1693     todo_wine
1694     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1695     /* A byte-mode pipe client can't be changed to message mode, either. */
1696     state = PIPE_READMODE_MESSAGE;
1697     SetLastError(0xdeadbeef);
1698     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1699     todo_wine
1700     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1701        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1702
1703     CloseHandle(client);
1704     CloseHandle(server);
1705
1706     server = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX,
1707         /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
1708         /* nMaxInstances */ 1,
1709         /* nOutBufSize */ 1024,
1710         /* nInBufSize */ 1024,
1711         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1712         /* lpSecurityAttrib */ NULL);
1713     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1714     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
1715     todo_wine
1716     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1717     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
1718         0);
1719     todo_wine
1720     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
1721     if (ret)
1722     {
1723         ok(state == 0, "unexpected state %08x\n", state);
1724         ok(instances == 1, "expected 1 instances, got %d\n", instances);
1725     }
1726     /* In contrast to byte-mode pipes, a message-mode pipe server can be
1727      * changed to byte mode.
1728      */
1729     state = PIPE_READMODE_BYTE;
1730     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
1731     todo_wine
1732     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1733
1734     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1735         OPEN_EXISTING, 0, NULL);
1736     ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1737
1738     state = PIPE_READMODE_MESSAGE;
1739     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1740     todo_wine
1741     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1742     /* A message-mode pipe client can also be changed to byte mode.
1743      */
1744     state = PIPE_READMODE_BYTE;
1745     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
1746     todo_wine
1747     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
1748
1749     CloseHandle(client);
1750     CloseHandle(server);
1751 }
1752
1753 static void test_readfileex_pending(void)
1754 {
1755     HANDLE server, client, event;
1756     BOOL ret;
1757     DWORD err, wait, num_bytes;
1758     OVERLAPPED overlapped;
1759     char read_buf[1024];
1760     char write_buf[1024];
1761     const char test_string[] = "test";
1762     int i;
1763
1764     server = CreateNamedPipe(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
1765         /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
1766         /* nMaxInstances */ 1,
1767         /* nOutBufSize */ 1024,
1768         /* nInBufSize */ 1024,
1769         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
1770         /* lpSecurityAttrib */ NULL);
1771     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
1772
1773     event = CreateEventA(NULL, TRUE, FALSE, NULL);
1774     ok(event != NULL, "CreateEventA failed\n");
1775
1776     memset(&overlapped, 0, sizeof(overlapped));
1777     overlapped.hEvent = event;
1778
1779     ret = ConnectNamedPipe(server, &overlapped);
1780     err = GetLastError();
1781     ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
1782     ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
1783
1784     wait = WaitForSingleObject(event, 0);
1785     ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
1786
1787     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1788         OPEN_EXISTING, 0, NULL);
1789     ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
1790
1791     wait = WaitForSingleObject(event, 0);
1792     ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1793
1794     /* Start a read that can't complete immediately. */
1795     completion_called = 0;
1796     ResetEvent(event);
1797     ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
1798     ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
1799     ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
1800
1801     ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
1802     ok(ret == TRUE, "WriteFile failed\n");
1803     ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
1804
1805     ok(completion_called == 0, "completion routine called during WriteFile\n");
1806
1807     wait = WaitForSingleObjectEx(event, 0, TRUE);
1808     ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
1809
1810     ok(completion_called == 1, "completion not called after writing pipe\n");
1811     ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1812     ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
1813     ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1814     ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
1815
1816     /* Make writes until the pipe is full and the write fails */
1817     memset(write_buf, 0xaa, sizeof(write_buf));
1818     for (i=0; i<256; i++)
1819     {
1820         completion_called = 0;
1821         ResetEvent(event);
1822         ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
1823         err = GetLastError();
1824
1825         ok(completion_called == 0, "completion routine called during WriteFileEx\n");
1826
1827         wait = WaitForSingleObjectEx(event, 0, TRUE);
1828
1829         if (wait == WAIT_TIMEOUT)
1830             /* write couldn't complete immediately, presumably the pipe is full */
1831             break;
1832
1833         ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1834
1835         ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1836         ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1837         ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1838     }
1839
1840     ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
1841     ok(completion_called == 0, "completion routine called but wait timed out\n");
1842     ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1843     ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1844
1845     /* free up some space in the pipe */
1846     ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
1847     ok(ret == TRUE, "ReadFile failed\n");
1848
1849     ok(completion_called == 0, "completion routine called during ReadFile\n");
1850
1851     wait = WaitForSingleObjectEx(event, 0, TRUE);
1852     ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
1853
1854     ok(completion_called == 1, "completion routine not called\n");
1855     ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
1856     ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
1857
1858     CloseHandle(client);
1859     CloseHandle(server);
1860     CloseHandle(event);
1861 }
1862
1863 START_TEST(pipe)
1864 {
1865     HMODULE hmod;
1866
1867     hmod = GetModuleHandle("advapi32.dll");
1868     pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
1869     hmod = GetModuleHandle("kernel32.dll");
1870     pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
1871
1872     if (test_DisconnectNamedPipe())
1873         return;
1874     test_CreateNamedPipe_instances_must_match();
1875     test_NamedPipe_2();
1876     test_CreateNamedPipe(PIPE_TYPE_BYTE);
1877     test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
1878     test_CreatePipe();
1879     test_impersonation();
1880     test_overlapped();
1881     test_NamedPipeHandleState();
1882     test_readfileex_pending();
1883 }