2 * Unit tests for named pipe functions in Wine
4 * Copyright (c) 2002 Dan Kegel
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.
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.
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
32 #include "wine/test.h"
35 #define START_TEST(name) main(int argc, char **argv)
36 #define ok(condition, msg) \
40 fprintf(stderr,"failed at %d\n",__LINE__); \
51 #define PIPENAME "\\\\.\\PiPe\\tests_" __FILE__
53 void test_CreateNamedPipe(void)
57 const char obuf[] = "Bit Bucket";
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);
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.");
77 ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
78 "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe");
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");
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");
91 /* Functional checks */
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");
101 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
102 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
104 /* don't try to do i/o if one side couldn't be opened, as it hangs */
105 if (hFile != INVALID_HANDLE_VALUE) {
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");
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");
123 /* Picky conformance tests */
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
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");
136 ok(CloseHandle(hFile), "CloseHandle");
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");
145 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
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");
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.
161 ok(CloseHandle(hnp), "CloseHandle");
163 trace("test_CreateNamedPipe returning\n");
166 void test_CreateNamedPipe_instances_must_match(void)
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");
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");
187 ok(CloseHandle(hnp), "CloseHandle");
188 ok(CloseHandle(hnp2), "CloseHandle");
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");
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");
208 ok(CloseHandle(hnp), "CloseHandle");
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");
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");
228 ok(CloseHandle(hnp), "CloseHandle");
233 /** implementation of alarm() */
234 static DWORD CALLBACK alarmThreadMain(LPVOID arg)
236 DWORD timeout = (DWORD) arg;
237 trace("alarmThreadMain\n");
244 HANDLE hnp = INVALID_HANDLE_VALUE;
246 /** Trivial byte echo server - disconnects after each session */
247 static DWORD CALLBACK serverThreadMain1(LPVOID arg)
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);
261 ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
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");
274 /* Echo bytes once */
275 memset(buf, 0, sizeof(buf));
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");
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");
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");
296 /** Trivial byte echo server - closes after each connection */
297 static DWORD CALLBACK serverThreadMain2(LPVOID arg)
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");
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");
325 /* Echo bytes once */
326 memset(buf, 0, sizeof(buf));
328 trace("Server reading...\n");
329 success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
330 trace("Server done reading.\n");
331 ok(success, "ReadFile");
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");
338 /* finish this connection, wait for next one */
339 ok(FlushFileBuffers(hnp), "FlushFileBuffers");
340 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
342 /* Set up next echo server */
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);
352 ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed");
354 ok(CloseHandle(hnp), "CloseHandle");
359 /** Trivial byte echo server - uses overlapped named pipe calls */
360 static DWORD CALLBACK serverThreadMain3(LPVOID arg)
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");
376 hEvent = CreateEvent(NULL, /* security attribute */
377 TRUE, /* manual reset event */
378 FALSE, /* initial state */
380 ok(hEvent != NULL, "CreateEvent");
389 int letWFSOEwait = (i & 2);
390 int letGORwait = (i & 1);
393 memset(&oOverlap, 0, sizeof(oOverlap));
394 oOverlap.hEvent = hEvent;
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);
410 ok(success, "GetOverlappedResult ConnectNamedPipe");
411 trace("overlapped ConnectNamedPipe operation complete.\n");
413 /* Echo bytes once */
414 memset(buf, 0, sizeof(buf));
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);
429 trace("Server done reading.\n");
430 ok(success, "overlapped ReadFile");
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);
445 trace("Server done writing.\n");
446 ok(success, "overlapped WriteFile");
447 ok(written == readden, "write file len");
449 /* finish this connection, wait for next one */
450 ok(FlushFileBuffers(hnp), "FlushFileBuffers");
451 ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe");
455 static void exercizeServer(const char *pipename, HANDLE serverThread)
459 trace("exercizeServer starting\n");
460 for (i = 0; i < 8; i++) {
461 HANDLE hFile=INVALID_HANDLE_VALUE;
462 const char obuf[] = "Bit Bucket";
468 for (loop = 0; loop < 3; loop++) {
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)
476 err = GetLastError();
478 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe");
480 ok(err == ERROR_PIPE_BUSY, "connecting to pipe");
481 trace("connect failed, retrying\n");
484 ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe");
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");
496 trace("Client closing...\n");
497 ok(CloseHandle(hFile), "CloseHandle");
500 ok(TerminateThread(serverThread, 0), "TerminateThread");
502 trace("exercizeServer returning\n");
505 void test_NamedPipe_2(void)
508 DWORD serverThreadId;
512 trace("test_NamedPipe_2 starting\n");
513 /* Set up a ten second timeout */
514 alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 10000, 0, &alarmThreadId);
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.
522 serverThread = CreateThread(NULL, 0, serverThreadMain1, 0, 0, &serverThreadId);
523 ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
524 exercizeServer(PIPENAME "serverThreadMain1", serverThread);
527 serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
528 ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
529 exercizeServer(PIPENAME "serverThreadMain2", serverThread);
531 if( 0 ) /* overlapped pipe server doesn't work yet - it randomly fails */
534 serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
535 ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread");
536 exercizeServer(PIPENAME "serverThreadMain3", serverThread);
539 ok(TerminateThread(alarmThread, 0), "TerminateThread");
540 trace("test_NamedPipe_2 returning\n");
543 void test_DisconnectNamedPipe(void)
547 const char obuf[] = "Bit Bucket";
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");
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");
565 hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
566 ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed");
568 /* don't try to do i/o if one side couldn't be opened, as it hangs */
569 if (hFile != INVALID_HANDLE_VALUE) {
571 /* see what happens if server calls DisconnectNamedPipe
572 * when there are bytes in the pipe
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");
586 ok(CloseHandle(hnp), "CloseHandle");
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");
598 trace("test 4 of 4:\n");
599 test_CreateNamedPipe();
600 trace("all tests done\n");