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