mshtml: Print wine_gecko version in load_wine_gecko.
[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 <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <time.h>
25
26 #include <windef.h>
27 #include <winbase.h>
28 #include <winsock.h>
29 #include <wtypes.h>
30 #include <winerror.h>
31
32 #include "wine/test.h"
33
34 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
35
36 #define NB_SERVER_LOOPS 8
37
38 static HANDLE alarm_event;
39
40 static void test_CreateNamedPipe(int pipemode)
41 {
42     HANDLE hnp;
43     HANDLE hFile;
44     static const char obuf[] = "Bit Bucket";
45     static const char obuf2[] = "More bits";
46     char ibuf[32], *pbuf;
47     DWORD written;
48     DWORD readden;
49     DWORD avail;
50     DWORD lpmode;
51
52     if (pipemode == PIPE_TYPE_BYTE)
53         trace("test_CreateNamedPipe starting in byte mode\n");
54     else
55         trace("test_CreateNamedPipe starting in message mode\n");
56     /* Bad parameter checks */
57     hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
58         /* nMaxInstances */ 1,
59         /* nOutBufSize */ 1024,
60         /* nInBufSize */ 1024,
61         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
62         /* lpSecurityAttrib */ NULL);
63
64     if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
65         /* Is this the right way to notify user of skipped tests? */
66         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
67             "CreateNamedPipe not supported on this platform, skipping tests.\n");
68         return;
69     }
70     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
71         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
72
73     hnp = CreateNamedPipe(NULL,
74         PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
75         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
76     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
77         "CreateNamedPipe should fail if name is NULL\n");
78
79     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
80     ok(hFile == INVALID_HANDLE_VALUE
81         && GetLastError() == ERROR_FILE_NOT_FOUND,
82         "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
83
84     /* Functional checks */
85
86     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
87         /* nMaxInstances */ 1,
88         /* nOutBufSize */ 1024,
89         /* nInBufSize */ 1024,
90         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
91         /* lpSecurityAttrib */ NULL);
92     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
93
94     ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%08x)\n", GetLastError());
95
96     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
97     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08x)\n", GetLastError());
98
99     /* don't try to do i/o if one side couldn't be opened, as it hangs */
100     if (hFile != INVALID_HANDLE_VALUE) {
101         HANDLE hFile2;
102
103         /* Make sure we can read and write a few bytes in both directions */
104         memset(ibuf, 0, sizeof(ibuf));
105         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
106         ok(written == sizeof(obuf), "write file len 1\n");
107         ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
108         ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
109         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
110         ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
111         ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
112
113         memset(ibuf, 0, sizeof(ibuf));
114         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
115         ok(written == sizeof(obuf2), "write file len 2\n");
116         ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
117         ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
118         ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
119         ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
120         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
121         ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
122         ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
123
124         /* Test reading of multiple writes */
125         memset(ibuf, 0, sizeof(ibuf));
126         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
127         ok(written == sizeof(obuf), "write file len 3a\n");
128         ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
129         ok(written == sizeof(obuf2), "write file len 3b\n");
130         ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
131         if (pipemode == PIPE_TYPE_BYTE) {
132             todo_wine {
133                 /* should return all 23 bytes */
134                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
135             }
136         }
137         else
138             ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
139         if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
140             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
141         pbuf = ibuf;
142         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
143         if (pipemode == PIPE_TYPE_BYTE) {
144             todo_wine {
145                 pbuf += sizeof(obuf);
146                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
147             }
148         }
149         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
150         ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %d bytes\n", readden);
151         pbuf = ibuf;
152         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
153         pbuf += sizeof(obuf);
154         ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
155
156         /* Multiple writes in the reverse direction */
157         memset(ibuf, 0, sizeof(ibuf));
158         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
159         ok(written == sizeof(obuf), "write file len 4a\n");
160         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
161         ok(written == sizeof(obuf2), "write file len 4b\n");
162         ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
163         if (pipemode == PIPE_TYPE_BYTE) {
164             todo_wine {
165                 /* should return all 23 bytes */
166                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
167             }
168         }
169         else
170             ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
171         if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
172             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
173         pbuf = ibuf;
174         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
175         if (pipemode == PIPE_TYPE_BYTE) {
176             todo_wine {
177                 pbuf += sizeof(obuf);
178                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
179             }
180         }
181         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
182         if (pipemode == PIPE_TYPE_BYTE) {
183             ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
184         }
185         else {
186             todo_wine {
187                 ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
188             }
189         }
190         pbuf = ibuf;
191         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
192         if (pipemode == PIPE_TYPE_BYTE) {
193             pbuf += sizeof(obuf);
194             ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
195         }
196
197         /* Test reading of multiple writes after a mode change
198           (CreateFile always creates a byte mode pipe) */
199         lpmode = PIPE_READMODE_MESSAGE;
200         if (pipemode == PIPE_TYPE_BYTE) {
201             /* trying to change the client end of a byte pipe to message mode should fail */
202             ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
203         }
204         else {
205             todo_wine {
206                 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
207             }
208         
209             memset(ibuf, 0, sizeof(ibuf));
210             ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
211             ok(written == sizeof(obuf), "write file len 3a\n");
212             ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
213             ok(written == sizeof(obuf2), "write file len 3b\n");
214             ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
215             ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
216             if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
217                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
218             pbuf = ibuf;
219             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
220             ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
221             todo_wine {
222                 ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
223             }
224             pbuf = ibuf;
225             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
226     
227             /* Multiple writes in the reverse direction */
228             /* the write of obuf2 from write4 should still be in the buffer */
229             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
230             todo_wine {
231                 ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
232                 ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
233             }
234             if (avail > 0) {
235                 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
236                 ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
237                 pbuf = ibuf;
238                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
239             }
240             memset(ibuf, 0, sizeof(ibuf));
241             ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
242             ok(written == sizeof(obuf), "write file len 6a\n");
243             ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
244             ok(written == sizeof(obuf2), "write file len 6b\n");
245             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
246             ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
247             if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
248                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
249             pbuf = ibuf;
250             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
251             ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
252             todo_wine {
253                 ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
254             }
255             pbuf = ibuf;
256             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
257         }
258
259         /* Picky conformance tests */
260
261         /* Verify that you can't connect to pipe again
262          * until server calls DisconnectNamedPipe+ConnectNamedPipe
263          * or creates a new pipe
264          * case 1: other client not yet closed
265          */
266         hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
267         ok(hFile2 == INVALID_HANDLE_VALUE,
268             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
269         ok(GetLastError() == ERROR_PIPE_BUSY,
270             "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
271
272         ok(CloseHandle(hFile), "CloseHandle\n");
273
274         /* case 2: other client already closed */
275         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
276         ok(hFile == INVALID_HANDLE_VALUE,
277             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
278         ok(GetLastError() == ERROR_PIPE_BUSY,
279             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
280
281         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
282
283         /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
284         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
285         ok(hFile == INVALID_HANDLE_VALUE,
286             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
287         ok(GetLastError() == ERROR_PIPE_BUSY,
288             "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
289
290         /* to be complete, we'd call ConnectNamedPipe here and loop,
291          * but by default that's blocking, so we'd either have
292          * to turn on the uncommon nonblocking mode, or
293          * use another thread.
294          */
295     }
296
297     ok(CloseHandle(hnp), "CloseHandle\n");
298
299     trace("test_CreateNamedPipe returning\n");
300 }
301
302 static void test_CreateNamedPipe_instances_must_match(void)
303 {
304     HANDLE hnp, hnp2;
305
306     /* Check no mismatch */
307     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
308         /* nMaxInstances */ 2,
309         /* nOutBufSize */ 1024,
310         /* nInBufSize */ 1024,
311         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
312         /* lpSecurityAttrib */ NULL);
313     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
314
315     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
316         /* nMaxInstances */ 2,
317         /* nOutBufSize */ 1024,
318         /* nInBufSize */ 1024,
319         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
320         /* lpSecurityAttrib */ NULL);
321     ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
322
323     ok(CloseHandle(hnp), "CloseHandle\n");
324     ok(CloseHandle(hnp2), "CloseHandle\n");
325
326     /* Check nMaxInstances */
327     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
328         /* nMaxInstances */ 1,
329         /* nOutBufSize */ 1024,
330         /* nInBufSize */ 1024,
331         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
332         /* lpSecurityAttrib */ NULL);
333     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
334
335     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
336         /* nMaxInstances */ 1,
337         /* nOutBufSize */ 1024,
338         /* nInBufSize */ 1024,
339         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
340         /* lpSecurityAttrib */ NULL);
341     ok(hnp2 == INVALID_HANDLE_VALUE
342         && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
343
344     ok(CloseHandle(hnp), "CloseHandle\n");
345
346     /* Check PIPE_ACCESS_* */
347     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
348         /* nMaxInstances */ 2,
349         /* nOutBufSize */ 1024,
350         /* nInBufSize */ 1024,
351         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
352         /* lpSecurityAttrib */ NULL);
353     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
354
355     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
356         /* nMaxInstances */ 1,
357         /* nOutBufSize */ 1024,
358         /* nInBufSize */ 1024,
359         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
360         /* lpSecurityAttrib */ NULL);
361     ok(hnp2 == INVALID_HANDLE_VALUE
362         && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
363
364     ok(CloseHandle(hnp), "CloseHandle\n");
365
366     /* etc, etc */
367 }
368
369 /** implementation of alarm() */
370 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
371 {
372     DWORD timeout = (DWORD) arg;
373     trace("alarmThreadMain\n");
374     if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
375     {
376         ok(FALSE, "alarm\n");
377         ExitProcess(1);
378     }
379     return 1;
380 }
381
382 HANDLE hnp = INVALID_HANDLE_VALUE;
383
384 /** Trivial byte echo server - disconnects after each session */
385 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
386 {
387     int i;
388
389     trace("serverThreadMain1 start\n");
390     /* Set up a simple echo server */
391     hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
392         PIPE_TYPE_BYTE | PIPE_WAIT,
393         /* nMaxInstances */ 1,
394         /* nOutBufSize */ 1024,
395         /* nInBufSize */ 1024,
396         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
397         /* lpSecurityAttrib */ NULL);
398
399     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
400     for (i = 0; i < NB_SERVER_LOOPS; i++) {
401         char buf[512];
402         DWORD written;
403         DWORD readden;
404         DWORD success;
405
406         /* Wait for client to connect */
407         trace("Server calling ConnectNamedPipe...\n");
408         ok(ConnectNamedPipe(hnp, NULL)
409             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
410         trace("ConnectNamedPipe returned.\n");
411
412         /* Echo bytes once */
413         memset(buf, 0, sizeof(buf));
414
415         trace("Server reading...\n");
416         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
417         trace("Server done reading.\n");
418         ok(success, "ReadFile\n");
419         ok(readden, "short read\n");
420
421         trace("Server writing...\n");
422         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
423         trace("Server done writing.\n");
424         ok(written == readden, "write file len\n");
425
426         /* finish this connection, wait for next one */
427         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
428         trace("Server done flushing.\n");
429         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
430         trace("Server done disconnecting.\n");
431     }
432     return 0;
433 }
434
435 /** Trivial byte echo server - closes after each connection */
436 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
437 {
438     int i;
439     HANDLE hnpNext = 0;
440
441     trace("serverThreadMain2\n");
442     /* Set up a simple echo server */
443     hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
444         PIPE_TYPE_BYTE | PIPE_WAIT,
445         /* nMaxInstances */ 2,
446         /* nOutBufSize */ 1024,
447         /* nInBufSize */ 1024,
448         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
449         /* lpSecurityAttrib */ NULL);
450     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
451
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
472         trace("Server writing...\n");
473         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
474         trace("Server done writing.\n");
475         ok(written == readden, "write file len\n");
476
477         /* finish this connection, wait for next one */
478         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
479         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
480
481         /* Set up next echo server */
482         hnpNext =
483             CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
484             PIPE_TYPE_BYTE | PIPE_WAIT,
485             /* nMaxInstances */ 2,
486             /* nOutBufSize */ 1024,
487             /* nInBufSize */ 1024,
488             /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
489             /* lpSecurityAttrib */ NULL);
490
491         ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
492
493         ok(CloseHandle(hnp), "CloseHandle\n");
494         hnp = hnpNext;
495     }
496     return 0;
497 }
498
499 /** Trivial byte echo server - uses overlapped named pipe calls */
500 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
501 {
502     int i;
503     HANDLE hEvent;
504
505     trace("serverThreadMain3\n");
506     /* Set up a simple echo server */
507     hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
508         PIPE_TYPE_BYTE | PIPE_WAIT,
509         /* nMaxInstances */ 1,
510         /* nOutBufSize */ 1024,
511         /* nInBufSize */ 1024,
512         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
513         /* lpSecurityAttrib */ NULL);
514     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
515
516     hEvent = CreateEvent(NULL,  /* security attribute */
517         TRUE,                   /* manual reset event */
518         FALSE,                  /* initial state */
519         NULL);                  /* name */
520     ok(hEvent != NULL, "CreateEvent\n");
521
522     for (i = 0; i < NB_SERVER_LOOPS; i++) {
523         char buf[512];
524         DWORD written;
525         DWORD readden;
526         DWORD dummy;
527         DWORD success;
528         OVERLAPPED oOverlap;
529         int letWFSOEwait = (i & 2);
530         int letGORwait = (i & 1);
531         DWORD err;
532
533         memset(&oOverlap, 0, sizeof(oOverlap));
534         oOverlap.hEvent = hEvent;
535
536         /* Wait for client to connect */
537         trace("Server calling overlapped ConnectNamedPipe...\n");
538         success = ConnectNamedPipe(hnp, &oOverlap);
539         err = GetLastError();
540         ok(success || err == ERROR_IO_PENDING
541             || err == ERROR_PIPE_CONNECTED, "overlapped ConnectNamedPipe\n");
542         trace("overlapped ConnectNamedPipe returned.\n");
543         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
544             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ConnectNamedPipe\n");
545         success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
546         if (!letGORwait && !letWFSOEwait && !success) {
547             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
548             success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
549         }
550         ok(success, "GetOverlappedResult ConnectNamedPipe\n");
551         trace("overlapped ConnectNamedPipe operation complete.\n");
552
553         /* Echo bytes once */
554         memset(buf, 0, sizeof(buf));
555
556         trace("Server reading...\n");
557         success = ReadFile(hnp, buf, sizeof(buf), NULL, &oOverlap);
558         trace("Server ReadFile returned...\n");
559         err = GetLastError();
560         ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
561         trace("overlapped ReadFile returned.\n");
562         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
563             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ReadFile\n");
564         success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
565         if (!letGORwait && !letWFSOEwait && !success) {
566             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
567             success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
568         }
569         trace("Server done reading.\n");
570         ok(success, "overlapped ReadFile\n");
571
572         trace("Server writing...\n");
573         success = WriteFile(hnp, buf, readden, NULL, &oOverlap);
574         trace("Server WriteFile returned...\n");
575         err = GetLastError();
576         ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
577         trace("overlapped WriteFile returned.\n");
578         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
579             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait WriteFile\n");
580         success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
581         if (!letGORwait && !letWFSOEwait && !success) {
582             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
583             success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
584         }
585         trace("Server done writing.\n");
586         ok(success, "overlapped WriteFile\n");
587         ok(written == readden, "write file len\n");
588
589         /* finish this connection, wait for next one */
590         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
591         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
592     }
593     return 0;
594 }
595
596 static void exercizeServer(const char *pipename, HANDLE serverThread)
597 {
598     int i;
599
600     trace("exercizeServer starting\n");
601     for (i = 0; i < NB_SERVER_LOOPS; i++) {
602         HANDLE hFile=INVALID_HANDLE_VALUE;
603         static const char obuf[] = "Bit Bucket";
604         char ibuf[32];
605         DWORD written;
606         DWORD readden;
607         int loop;
608
609         for (loop = 0; loop < 3; loop++) {
610             DWORD err;
611             trace("Client connecting...\n");
612             /* Connect to the server */
613             hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
614                 NULL, OPEN_EXISTING, 0, 0);
615             if (hFile != INVALID_HANDLE_VALUE)
616                 break;
617             err = GetLastError();
618             if (loop == 0)
619                 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
620             else
621                 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
622             trace("connect failed, retrying\n");
623             Sleep(200);
624         }
625         ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
626
627         /* Make sure it can echo */
628         memset(ibuf, 0, sizeof(ibuf));
629         trace("Client writing...\n");
630         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
631         ok(written == sizeof(obuf), "write file len\n");
632         trace("Client reading...\n");
633         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
634         ok(readden == sizeof(obuf), "read file len\n");
635         ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
636
637         trace("Client closing...\n");
638         ok(CloseHandle(hFile), "CloseHandle\n");
639     }
640
641     ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
642     CloseHandle(hnp);
643     trace("exercizeServer returning\n");
644 }
645
646 static void test_NamedPipe_2(void)
647 {
648     HANDLE serverThread;
649     DWORD serverThreadId;
650     HANDLE alarmThread;
651     DWORD alarmThreadId;
652
653     trace("test_NamedPipe_2 starting\n");
654     /* Set up a ten second timeout */
655     alarm_event = CreateEvent( NULL, TRUE, FALSE, NULL );
656     alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 10000, 0, &alarmThreadId);
657
658     /* The servers we're about to exercize do try to clean up carefully,
659      * but to reduce the change of a test failure due to a pipe handle
660      * leak in the test code, we'll use a different pipe name for each server.
661      */
662
663     /* Try server #1 */
664     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
665     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
666     exercizeServer(PIPENAME "serverThreadMain1", serverThread);
667
668     /* Try server #2 */
669     serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
670     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
671     exercizeServer(PIPENAME "serverThreadMain2", serverThread);
672
673     if( 0 ) /* overlapped pipe server doesn't work yet - it randomly fails */
674     {
675     /* Try server #3 */
676     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
677     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
678     exercizeServer(PIPENAME "serverThreadMain3", serverThread);
679     }
680
681     ok(SetEvent( alarm_event ), "SetEvent\n");
682     CloseHandle( alarm_event );
683     trace("test_NamedPipe_2 returning\n");
684 }
685
686 static int test_DisconnectNamedPipe(void)
687 {
688     HANDLE hnp;
689     HANDLE hFile;
690     static const char obuf[] = "Bit Bucket";
691     char ibuf[32];
692     DWORD written;
693     DWORD readden;
694
695     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
696         /* nMaxInstances */ 1,
697         /* nOutBufSize */ 1024,
698         /* nInBufSize */ 1024,
699         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
700         /* lpSecurityAttrib */ NULL);
701     if (INVALID_HANDLE_VALUE == hnp) {
702         trace ("Seems we have no named pipes.\n");
703         return 1;
704     }
705
706     ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
707         && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
708     ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
709         && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
710
711     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
712     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
713
714     /* don't try to do i/o if one side couldn't be opened, as it hangs */
715     if (hFile != INVALID_HANDLE_VALUE) {
716
717         /* see what happens if server calls DisconnectNamedPipe
718          * when there are bytes in the pipe
719          */
720
721         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
722         ok(written == sizeof(obuf), "write file len\n");
723         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
724         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
725             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
726         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
727             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
728             "ReadFile from disconnected pipe with bytes waiting\n");
729         ok(CloseHandle(hFile), "CloseHandle\n");
730     }
731
732     ok(CloseHandle(hnp), "CloseHandle\n");
733
734     return 0;
735 }
736 static void test_CreatePipe(void)
737 {
738     SECURITY_ATTRIBUTES pipe_attr;
739     HANDLE piperead, pipewrite;
740     DWORD written;
741     DWORD read;
742     char readbuf[32];
743
744     pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES); 
745     pipe_attr.bInheritHandle = TRUE; 
746     pipe_attr.lpSecurityDescriptor = NULL; 
747     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
748     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
749     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
750     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
751     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
752
753     /* Now write another chunk*/
754     ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
755     ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
756     ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
757     /* and close the write end, read should still succeed*/
758     ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
759     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
760     ok(read == sizeof(PIPENAME), "Read from  anonymous pipe got %d bytes\n", read);
761     /* But now we need to get informed that the pipe is closed */
762     ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
763 }
764
765 START_TEST(pipe)
766 {
767     trace("test 1 of 6:\n");
768     if (test_DisconnectNamedPipe())
769         return;
770     trace("test 2 of 6:\n");
771     test_CreateNamedPipe_instances_must_match();
772     trace("test 3 of 6:\n");
773     test_NamedPipe_2();
774     trace("test 4 of 6:\n");
775     test_CreateNamedPipe(PIPE_TYPE_BYTE);
776     trace("test 5 of 6\n");
777     test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
778     trace("test 6 of 6\n");
779     test_CreatePipe();
780     trace("all tests done\n");
781 }