Added tests for FoldStringA/W.
[wine] / dlls / kernel / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <time.h>
26
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winsock.h>
30
31 #ifndef STANDALONE
32 #include "wine/test.h"
33 #else
34 #include <assert.h>
35 #define START_TEST(name) main(int argc, char **argv)
36 #define ok(condition, msg) \
37         do { \
38                 if(!(condition)) \
39                 { \
40                         fprintf(stderr,"failed at %d\n",__LINE__); \
41                         exit(0); \
42                 } \
43         } while(0)
44
45 #define todo_wine
46 #endif
47
48 #include <wtypes.h>
49 #include <winerror.h>
50
51 #define PIPENAME "\\\\.\\PiPe\\tests_" __FILE__
52
53 void test_CreateNamedPipe(void)
54 {
55     HANDLE hnp;
56     HANDLE hFile;
57     const char obuf[] = "Bit Bucket";
58     char ibuf[32];
59     DWORD written;
60     DWORD readden;
61
62     trace("test_CreateNamedPipe starting\n");
63     /* Bad parameter checks */
64     hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
65         /* nMaxInstances */ 1,
66         /* nOutBufSize */ 1024,
67         /* nInBufSize */ 1024,
68         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
69         /* lpSecurityAttrib */ NULL);
70
71     if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
72         /* Is this the right way to notify user of skipped tests? */
73         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
74             "CreateNamedPipe not supported on this platform, skipping tests.");
75         return;
76     }
77     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
78         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe");
79
80     hnp = CreateNamedPipe(NULL,
81         PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
82         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
83     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
84         "CreateNamedPipe should fail if name is NULL");
85
86     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
87     ok(hFile == INVALID_HANDLE_VALUE
88         && GetLastError() == ERROR_FILE_NOT_FOUND,
89         "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND");
90
91     /* Functional checks */
92
93     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
94         /* nMaxInstances */ 1,
95         /* nOutBufSize */ 1024,
96         /* nInBufSize */ 1024,
97         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
98         /* lpSecurityAttrib */ NULL);
99     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
100
101     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
102     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
103
104     /* don't try to do i/o if one side couldn't be opened, as it hangs */
105     if (hFile != INVALID_HANDLE_VALUE) {
106         HANDLE hFile2;
107
108         /* Make sure we can read and write a few bytes in both directions */
109         memset(ibuf, 0, sizeof(ibuf));
110         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile");
111         ok(written == sizeof(obuf), "write file len");
112         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile");
113         ok(readden == sizeof(obuf), "read file len");
114         ok(memcmp(obuf, ibuf, written) == 0, "content check");
115
116         memset(ibuf, 0, sizeof(ibuf));
117         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile");
118         ok(written == sizeof(obuf), "write file len");
119         ok(ReadFile(hnp, ibuf, sizeof(obuf), &readden, NULL), "ReadFile");
120         ok(readden == sizeof(obuf), "read file len");
121         ok(memcmp(obuf, ibuf, written) == 0, "content check");
122
123         /* Picky conformance tests */
124
125         /* Verify that you can't connect to pipe again
126          * until server calls DisconnectNamedPipe+ConnectNamedPipe
127          * or creates a new pipe
128          * case 1: other client not yet closed
129          */
130         hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
131         ok(hFile2 == INVALID_HANDLE_VALUE,
132             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
133         ok(GetLastError() == ERROR_PIPE_BUSY,
134             "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY");
135
136         ok(CloseHandle(hFile), "CloseHandle");
137
138         /* case 2: other client already closed */
139         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
140         ok(hFile == INVALID_HANDLE_VALUE,
141             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
142         ok(GetLastError() == ERROR_PIPE_BUSY,
143             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY");
144
145         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
146
147         /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
148         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
149         ok(hFile == INVALID_HANDLE_VALUE,
150             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail");
151         ok(GetLastError() == ERROR_PIPE_BUSY,
152             "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY");
153
154         /* to be complete, we'd call ConnectNamedPipe here and loop,
155          * but by default that's blocking, so we'd either have
156          * to turn on the uncommon nonblocking mode, or
157          * use another thread.
158          */
159     }
160
161     ok(CloseHandle(hnp), "CloseHandle");
162
163     trace("test_CreateNamedPipe returning\n");
164 }
165
166 void test_CreateNamedPipe_instances_must_match(void)
167 {
168     HANDLE hnp, hnp2;
169
170     /* Check no mismatch */
171     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
172         /* nMaxInstances */ 2,
173         /* nOutBufSize */ 1024,
174         /* nInBufSize */ 1024,
175         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
176         /* lpSecurityAttrib */ NULL);
177     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
178
179     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
180         /* nMaxInstances */ 2,
181         /* nOutBufSize */ 1024,
182         /* nInBufSize */ 1024,
183         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
184         /* lpSecurityAttrib */ NULL);
185     ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
186
187     ok(CloseHandle(hnp), "CloseHandle");
188     ok(CloseHandle(hnp2), "CloseHandle");
189
190     /* Check nMaxInstances */
191     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
192         /* nMaxInstances */ 1,
193         /* nOutBufSize */ 1024,
194         /* nInBufSize */ 1024,
195         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
196         /* lpSecurityAttrib */ NULL);
197     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
198
199     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
200         /* nMaxInstances */ 1,
201         /* nOutBufSize */ 1024,
202         /* nInBufSize */ 1024,
203         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
204         /* lpSecurityAttrib */ NULL);
205     ok(hnp2 == INVALID_HANDLE_VALUE
206         && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed");
207
208     ok(CloseHandle(hnp), "CloseHandle");
209
210     /* Check PIPE_ACCESS_* */
211     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
212         /* nMaxInstances */ 2,
213         /* nOutBufSize */ 1024,
214         /* nInBufSize */ 1024,
215         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
216         /* lpSecurityAttrib */ NULL);
217     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
218
219     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
220         /* nMaxInstances */ 1,
221         /* nOutBufSize */ 1024,
222         /* nInBufSize */ 1024,
223         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
224         /* lpSecurityAttrib */ NULL);
225     ok(hnp2 == INVALID_HANDLE_VALUE
226         && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed");
227
228     ok(CloseHandle(hnp), "CloseHandle");
229
230     /* etc, etc */
231 }
232
233 /** implementation of alarm() */
234 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
235 {
236     DWORD timeout = (DWORD) arg;
237     trace("alarmThreadMain\n");
238     Sleep(timeout);
239     ok(FALSE, "alarm");
240     ExitProcess(1);
241     return 1;
242 }
243
244 HANDLE hnp = INVALID_HANDLE_VALUE;
245
246 /** Trivial byte echo server - disconnects after each session */
247 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
248 {
249     int i;
250
251     trace("serverThreadMain1 start\n");
252     /* Set up a simple echo server */
253     hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
254         PIPE_TYPE_BYTE | PIPE_WAIT,
255         /* nMaxInstances */ 1,
256         /* nOutBufSize */ 1024,
257         /* nInBufSize */ 1024,
258         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
259         /* lpSecurityAttrib */ NULL);
260
261     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
262     for (i = 0; ; i++) {
263         char buf[512];
264         DWORD written;
265         DWORD readden;
266         DWORD success;
267
268         /* Wait for client to connect */
269         trace("Server calling ConnectNamedPipe...\n");
270         ok(ConnectNamedPipe(hnp, NULL)
271             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe");
272         trace("ConnectNamedPipe returned.\n");
273
274         /* Echo bytes once */
275         memset(buf, 0, sizeof(buf));
276
277         trace("Server reading...\n");
278         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
279         trace("Server done reading.\n");
280         ok(success, "ReadFile");
281                 ok(readden, "short read");
282
283         trace("Server writing...\n");
284         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile");
285         trace("Server done writing.\n");
286         ok(written == readden, "write file len");
287
288         /* finish this connection, wait for next one */
289         ok(FlushFileBuffers(hnp), "FlushFileBuffers");
290         trace("Server done flushing.\n");
291         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
292         trace("Server done disconnecting.\n");
293     }
294 }
295
296 /** Trivial byte echo server - closes after each connection */
297 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
298 {
299     int i;
300     HANDLE hnpNext = 0;
301
302     trace("serverThreadMain2\n");
303     /* Set up a simple echo server */
304     hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
305         PIPE_TYPE_BYTE | PIPE_WAIT,
306         /* nMaxInstances */ 2,
307         /* nOutBufSize */ 1024,
308         /* nInBufSize */ 1024,
309         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
310         /* lpSecurityAttrib */ NULL);
311     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
312
313     for (i = 0; ; i++) {
314         char buf[512];
315         DWORD written;
316         DWORD readden;
317         DWORD success;
318
319         /* Wait for client to connect */
320         trace("Server calling ConnectNamedPipe...\n");
321         ok(ConnectNamedPipe(hnp, NULL)
322             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe");
323         trace("ConnectNamedPipe returned.\n");
324
325         /* Echo bytes once */
326         memset(buf, 0, sizeof(buf));
327
328         trace("Server reading...\n");
329         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
330         trace("Server done reading.\n");
331         ok(success, "ReadFile");
332
333         trace("Server writing...\n");
334         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile");
335         trace("Server done writing.\n");
336         ok(written == readden, "write file len");
337
338         /* finish this connection, wait for next one */
339         ok(FlushFileBuffers(hnp), "FlushFileBuffers");
340         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
341
342         /* Set up next echo server */
343         hnpNext =
344             CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
345             PIPE_TYPE_BYTE | PIPE_WAIT,
346             /* nMaxInstances */ 2,
347             /* nOutBufSize */ 1024,
348             /* nInBufSize */ 1024,
349             /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
350             /* lpSecurityAttrib */ NULL);
351
352         ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
353
354         ok(CloseHandle(hnp), "CloseHandle");
355         hnp = hnpNext;
356     }
357 }
358
359 /** Trivial byte echo server - uses overlapped named pipe calls */
360 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
361 {
362     int i;
363     HANDLE hEvent;
364
365     trace("serverThreadMain3\n");
366     /* Set up a simple echo server */
367     hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
368         PIPE_TYPE_BYTE | PIPE_WAIT,
369         /* nMaxInstances */ 1,
370         /* nOutBufSize */ 1024,
371         /* nInBufSize */ 1024,
372         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
373         /* lpSecurityAttrib */ NULL);
374     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
375
376     hEvent = CreateEvent(NULL,  /* security attribute */
377         TRUE,                   /* manual reset event */
378         FALSE,                  /* initial state */
379         NULL);                  /* name */
380     ok(hEvent != NULL, "CreateEvent");
381
382     for (i = 0; ; i++) {
383         char buf[512];
384         DWORD written;
385         DWORD readden;
386         DWORD dummy;
387         DWORD success;
388         OVERLAPPED oOverlap;
389         int letWFSOEwait = (i & 2);
390         int letGORwait = (i & 1);
391         DWORD err;
392
393         memset(&oOverlap, 0, sizeof(oOverlap));
394         oOverlap.hEvent = hEvent;
395
396         /* Wait for client to connect */
397         trace("Server calling overlapped ConnectNamedPipe...\n");
398         success = ConnectNamedPipe(hnp, &oOverlap);
399         err = GetLastError();
400         ok(success || err == ERROR_IO_PENDING
401             || err == ERROR_PIPE_CONNECTED, "overlapped ConnectNamedPipe");
402         trace("overlapped ConnectNamedPipe returned.\n");
403         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
404             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ConnectNamedPipe");
405         success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
406         if (!letGORwait && !letWFSOEwait && !success) {
407             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult");
408             success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
409         }
410         ok(success, "GetOverlappedResult ConnectNamedPipe");
411         trace("overlapped ConnectNamedPipe operation complete.\n");
412
413         /* Echo bytes once */
414         memset(buf, 0, sizeof(buf));
415
416         trace("Server reading...\n");
417         success = ReadFile(hnp, buf, sizeof(buf), NULL, &oOverlap);
418         trace("Server ReadFile returned...\n");
419         err = GetLastError();
420         ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile");
421         trace("overlapped ReadFile returned.\n");
422         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
423             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ReadFile");
424         success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
425         if (!letGORwait && !letWFSOEwait && !success) {
426             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult");
427             success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
428         }
429         trace("Server done reading.\n");
430         ok(success, "overlapped ReadFile");
431
432         trace("Server writing...\n");
433         success = WriteFile(hnp, buf, readden, NULL, &oOverlap);
434         trace("Server WriteFile returned...\n");
435         err = GetLastError();
436         ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile");
437         trace("overlapped WriteFile returned.\n");
438         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
439             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait WriteFile");
440         success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
441         if (!letGORwait && !letWFSOEwait && !success) {
442             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult");
443             success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
444         }
445         trace("Server done writing.\n");
446         ok(success, "overlapped WriteFile");
447         ok(written == readden, "write file len");
448
449         /* finish this connection, wait for next one */
450         ok(FlushFileBuffers(hnp), "FlushFileBuffers");
451         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
452     }
453 }
454
455 static void exercizeServer(const char *pipename, HANDLE serverThread)
456 {
457     int i;
458
459     trace("exercizeServer starting\n");
460     for (i = 0; i < 8; i++) {
461         HANDLE hFile=INVALID_HANDLE_VALUE;
462         const char obuf[] = "Bit Bucket";
463         char ibuf[32];
464         DWORD written;
465         DWORD readden;
466         int loop;
467
468         for (loop = 0; loop < 3; loop++) {
469             DWORD err;
470             trace("Client connecting...\n");
471             /* Connect to the server */
472             hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
473                 NULL, OPEN_EXISTING, 0, 0);
474             if (hFile != INVALID_HANDLE_VALUE)
475                 break;
476             err = GetLastError();
477             if (loop == 0)
478                 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe");
479             else
480                 ok(err == ERROR_PIPE_BUSY, "connecting to pipe");
481             trace("connect failed, retrying\n");
482             Sleep(200);
483         }
484         ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe");
485
486         /* Make sure it can echo */
487         memset(ibuf, 0, sizeof(ibuf));
488         trace("Client writing...\n");
489         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe");
490         ok(written == sizeof(obuf), "write file len");
491         trace("Client reading...\n");
492         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe");
493         ok(readden == sizeof(obuf), "read file len");
494         ok(memcmp(obuf, ibuf, written) == 0, "content check");
495
496         trace("Client closing...\n");
497         ok(CloseHandle(hFile), "CloseHandle");
498     }
499
500     ok(TerminateThread(serverThread, 0), "TerminateThread");
501     CloseHandle(hnp);
502     trace("exercizeServer returning\n");
503 }
504
505 void test_NamedPipe_2(void)
506 {
507     HANDLE serverThread;
508     DWORD serverThreadId;
509     HANDLE alarmThread;
510     DWORD alarmThreadId;
511
512     trace("test_NamedPipe_2 starting\n");
513     /* Set up a ten second timeout */
514     alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 10000, 0, &alarmThreadId);
515
516     /* The servers we're about to exercize do try to clean up carefully,
517      * but to reduce the change of a test failure due to a pipe handle
518      * leak in the test code, we'll use a different pipe name for each server.
519      */
520
521     /* Try server #1 */
522     serverThread = CreateThread(NULL, 0, serverThreadMain1, 0, 0, &serverThreadId);
523     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
524     exercizeServer(PIPENAME "serverThreadMain1", serverThread);
525
526     /* Try server #2 */
527     serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
528     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
529     exercizeServer(PIPENAME "serverThreadMain2", serverThread);
530
531     if( 0 ) /* overlapped pipe server doesn't work yet - it randomly fails */
532     {
533     /* Try server #3 */
534     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
535     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
536     exercizeServer(PIPENAME "serverThreadMain3", serverThread);
537     }
538
539     ok(TerminateThread(alarmThread, 0), "TerminateThread");
540     trace("test_NamedPipe_2 returning\n");
541 }
542
543 void test_DisconnectNamedPipe(void)
544 {
545     HANDLE hnp;
546     HANDLE hFile;
547     const char obuf[] = "Bit Bucket";
548     char ibuf[32];
549     DWORD written;
550     DWORD readden;
551
552     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
553         /* nMaxInstances */ 1,
554         /* nOutBufSize */ 1024,
555         /* nInBufSize */ 1024,
556         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
557         /* lpSecurityAttrib */ NULL);
558     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
559
560     ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
561         && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe");
562     ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
563         && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe");
564
565     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
566     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
567
568     /* don't try to do i/o if one side couldn't be opened, as it hangs */
569     if (hFile != INVALID_HANDLE_VALUE) {
570
571         /* see what happens if server calls DisconnectNamedPipe
572          * when there are bytes in the pipe
573          */
574
575         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile");
576         ok(written == sizeof(obuf), "write file len");
577         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting");
578         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
579             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe");
580         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
581             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,
582             "ReadFile from disconnected pipe with bytes waiting");
583         ok(CloseHandle(hFile), "CloseHandle");
584     }
585
586     ok(CloseHandle(hnp), "CloseHandle");
587
588 }
589
590 START_TEST(pipe)
591 {
592     trace("test 1 of 4:\n");
593     test_DisconnectNamedPipe();
594     trace("test 2 of 4:\n");
595     test_CreateNamedPipe_instances_must_match();
596     trace("test 3 of 4:\n");
597     test_NamedPipe_2();
598     trace("test 4 of 4:\n");
599     test_CreateNamedPipe();
600     trace("all tests done\n");
601 }