update for HEAD-2003021201
[reactos.git] / lib / kernel32 / file / npipe.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/file/npipe.c
6  * PURPOSE:         Directory functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <k32.h>
14
15
16 #define NDEBUG
17 #include <kernel32/kernel32.h>
18
19 /* FUNCTIONS ****************************************************************/
20
21 HANDLE STDCALL
22 CreateNamedPipeA(LPCSTR lpName,
23                  DWORD dwOpenMode,
24                  DWORD dwPipeMode,
25                  DWORD nMaxInstances,
26                  DWORD nOutBufferSize,
27                  DWORD nInBufferSize,
28                  DWORD nDefaultTimeOut,
29                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
30 {
31    HANDLE NamedPipeHandle;
32    UNICODE_STRING NameU;
33    ANSI_STRING NameA;
34    
35    RtlInitAnsiString(&NameA, (LPSTR)lpName);
36    RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
37    
38    NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
39                                       dwOpenMode,
40                                       dwPipeMode,
41                                       nMaxInstances,
42                                       nOutBufferSize,
43                                       nInBufferSize,
44                                       nDefaultTimeOut,
45                                       lpSecurityAttributes);
46    
47    RtlFreeUnicodeString(&NameU);
48    
49    return(NamedPipeHandle);
50 }
51
52
53 HANDLE STDCALL
54 CreateNamedPipeW(LPCWSTR lpName,
55                  DWORD dwOpenMode,
56                  DWORD dwPipeMode,
57                  DWORD nMaxInstances,
58                  DWORD nOutBufferSize,
59                  DWORD nInBufferSize,
60                  DWORD nDefaultTimeOut,
61                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
62 {
63    UNICODE_STRING NamedPipeName;
64    BOOL Result;
65    NTSTATUS Status;
66    OBJECT_ATTRIBUTES ObjectAttributes;
67    HANDLE PipeHandle;
68    ACCESS_MASK DesiredAccess;
69    ULONG CreateOptions;
70    ULONG CreateDisposition;
71    BOOLEAN WriteModeMessage;
72    BOOLEAN ReadModeMessage;
73    BOOLEAN NonBlocking;
74    IO_STATUS_BLOCK Iosb;
75    ULONG ShareAccess;
76    LARGE_INTEGER DefaultTimeOut;
77    
78    Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
79                                          &NamedPipeName,
80                                          NULL,
81                                          NULL);
82    if (!Result)
83      {
84         SetLastError(ERROR_PATH_NOT_FOUND);
85         return(INVALID_HANDLE_VALUE);
86      }
87    
88    DPRINT("Pipe name: %wZ\n", &NamedPipeName);
89    DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
90    
91    InitializeObjectAttributes(&ObjectAttributes,
92                               &NamedPipeName,
93                               OBJ_CASE_INSENSITIVE,
94                               NULL,
95                               NULL);
96    
97    DesiredAccess = 0;
98    
99    ShareAccess = 0;
100    
101    CreateDisposition = FILE_OPEN_IF;
102    
103    CreateOptions = 0;
104    if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
105      {
106         CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
107      }
108    if (dwOpenMode & FILE_FLAG_OVERLAPPED)
109      {
110         CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_ALERT;
111      }
112    if (dwOpenMode & PIPE_ACCESS_DUPLEX)
113      {
114         CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX;
115      }
116    else if (dwOpenMode & PIPE_ACCESS_INBOUND)
117      {
118         CreateOptions = CreateOptions | FILE_PIPE_INBOUND;
119      }
120    else if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
121      {
122         CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND;
123      }
124    
125    if (dwPipeMode & PIPE_TYPE_BYTE)
126      {
127         WriteModeMessage = FALSE;
128      }
129    else if (dwPipeMode & PIPE_TYPE_MESSAGE)
130      {
131         WriteModeMessage = TRUE;
132      }
133    else
134      {
135         WriteModeMessage = FALSE;
136      }
137    
138    if (dwPipeMode & PIPE_READMODE_BYTE)
139      {
140         ReadModeMessage = FALSE;
141      }
142    else if (dwPipeMode & PIPE_READMODE_MESSAGE)
143      {
144         ReadModeMessage = TRUE;
145      }
146    else
147      {
148         ReadModeMessage = FALSE;
149      }
150    
151    if (dwPipeMode & PIPE_WAIT)
152      {
153         NonBlocking = FALSE;
154      }
155    else if (dwPipeMode & PIPE_NOWAIT)
156      {
157         NonBlocking = TRUE;
158      }
159    else
160      {
161         NonBlocking = FALSE;
162      }
163    
164    if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES)
165      {
166         nMaxInstances = ULONG_MAX;
167      }
168    
169    DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000;
170    
171    Status = NtCreateNamedPipeFile(&PipeHandle,
172                                   DesiredAccess,
173                                   &ObjectAttributes,
174                                   &Iosb,
175                                   ShareAccess,
176                                   CreateDisposition,
177                                   CreateOptions,
178                                   WriteModeMessage,
179                                   ReadModeMessage,
180                                   NonBlocking,
181                                   nMaxInstances,
182                                   nInBufferSize,
183                                   nOutBufferSize,
184                                   &DefaultTimeOut);
185    
186    RtlFreeUnicodeString(&NamedPipeName);
187    
188    if (!NT_SUCCESS(Status))
189      {
190         DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status);
191         SetLastErrorByStatus (Status);
192         return(INVALID_HANDLE_VALUE);
193      }
194    
195    return(PipeHandle);
196 }
197
198
199 BOOL STDCALL
200 WaitNamedPipeA(LPCSTR lpNamedPipeName,
201                DWORD nTimeOut)
202 {
203    BOOL r;
204    UNICODE_STRING NameU;
205    ANSI_STRING NameA;
206    
207    RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
208    RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
209    
210    r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
211    
212    RtlFreeUnicodeString(&NameU);
213    
214    return(r);
215 }
216
217
218 BOOL STDCALL
219 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
220                DWORD nTimeOut)
221 {
222    UNICODE_STRING NamedPipeName;
223    BOOL r;
224    NTSTATUS Status;
225    OBJECT_ATTRIBUTES ObjectAttributes;
226    NPFS_WAIT_PIPE WaitPipe;
227    HANDLE FileHandle;
228    IO_STATUS_BLOCK Iosb;
229    
230    r = RtlDosPathNameToNtPathName_U((LPWSTR)lpNamedPipeName,
231                                     &NamedPipeName,
232                                     NULL,
233                                     NULL);
234    
235    if (!r)
236      {
237         return(FALSE);
238      }
239    
240    InitializeObjectAttributes(&ObjectAttributes,
241                               &NamedPipeName,
242                               OBJ_CASE_INSENSITIVE,
243                               NULL,
244                               NULL);
245    Status = NtOpenFile(&FileHandle,
246                        FILE_GENERIC_READ,
247                        &ObjectAttributes,
248                        &Iosb,
249                        0,
250                        FILE_SYNCHRONOUS_IO_ALERT);
251    if (!NT_SUCCESS(Status))
252      {
253         SetLastErrorByStatus (Status);
254         return(FALSE);
255      }
256    
257    WaitPipe.Timeout.QuadPart = nTimeOut * -10000;
258    
259    Status = NtFsControlFile(FileHandle,
260                             NULL,
261                             NULL,
262                             NULL,
263                             &Iosb,
264                             FSCTL_PIPE_WAIT,
265                             &WaitPipe,
266                             sizeof(WaitPipe),
267                             NULL,
268                             0);
269    NtClose(FileHandle);
270    if (!NT_SUCCESS(Status))
271      {
272         SetLastErrorByStatus (Status);
273         return(FALSE);
274      }
275    
276    return(TRUE);
277 }
278
279
280 BOOL STDCALL
281 ConnectNamedPipe(HANDLE hNamedPipe,
282                  LPOVERLAPPED lpOverlapped)
283 {
284   PIO_STATUS_BLOCK IoStatusBlock;
285   IO_STATUS_BLOCK Iosb;
286   HANDLE hEvent;
287   NTSTATUS Status;
288
289   if (lpOverlapped != NULL)
290     {
291       lpOverlapped->Internal = STATUS_PENDING;
292       hEvent = lpOverlapped->hEvent;
293       IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
294     }
295   else
296     {
297       IoStatusBlock = &Iosb;
298       hEvent = NULL;
299     }
300
301   Status = NtFsControlFile(hNamedPipe,
302                            hEvent,
303                            NULL,
304                            NULL,
305                            IoStatusBlock,
306                            FSCTL_PIPE_LISTEN,
307                            NULL,
308                            0,
309                            NULL,
310                            0);
311   if ((lpOverlapped == NULL) && (Status == STATUS_PENDING))
312     {
313       Status = NtWaitForSingleObject(hNamedPipe,
314                                      FALSE,
315                                      NULL);
316       if (!NT_SUCCESS(Status))
317         {
318           SetLastErrorByStatus(Status);
319           return(FALSE);
320         }
321       Status = Iosb.Status;
322     }
323   if ((!NT_SUCCESS(Status) && Status != STATUS_PIPE_CONNECTED) ||
324       (Status == STATUS_PENDING))
325     {
326       SetLastErrorByStatus(Status);
327       return(FALSE);
328     }
329   return(TRUE);
330 }
331
332
333 BOOL STDCALL
334 SetNamedPipeHandleState(HANDLE hNamedPipe,
335                         LPDWORD lpMode,
336                         LPDWORD lpMaxCollectionCount,
337                         LPDWORD lpCollectDataTimeout)
338 {
339    NPFS_GET_STATE GetState;
340    NPFS_SET_STATE SetState;
341    IO_STATUS_BLOCK Iosb;
342    NTSTATUS Status;
343
344    Status = NtFsControlFile(hNamedPipe,
345                             NULL,
346                             NULL,
347                             NULL,
348                             &Iosb,
349                             FSCTL_PIPE_GET_STATE,
350                             NULL,
351                             0,
352                             &GetState,
353                             sizeof(NPFS_GET_STATE));
354    if (Status == STATUS_PENDING)
355      {
356         Status = NtWaitForSingleObject(hNamedPipe,
357                                        FALSE,
358                                        NULL);
359         if (!NT_SUCCESS(Status))
360           {
361              SetLastErrorByStatus(Status);
362              return(FALSE);
363           }
364      }
365
366    if (lpMode != NULL)
367      {
368         if ((*lpMode) & PIPE_READMODE_MESSAGE)
369           {
370              SetState.ReadModeMessage = TRUE;
371           }
372         else
373           {
374              SetState.ReadModeMessage = FALSE;
375           }
376         if ((*lpMode) & PIPE_NOWAIT)
377           {
378              SetState.NonBlocking = TRUE;
379           }
380         else
381           {
382              SetState.NonBlocking = FALSE;
383           }
384         SetState.WriteModeMessage = GetState.WriteModeMessage;
385      }
386    else
387      {
388         SetState.ReadModeMessage = GetState.ReadModeMessage;
389         SetState.WriteModeMessage = GetState.WriteModeMessage;
390         SetState.NonBlocking = SetState.NonBlocking;
391      }
392    
393    if (lpMaxCollectionCount != NULL)
394      {
395         SetState.InBufferSize = *lpMaxCollectionCount;
396      }
397    else
398      {
399         SetState.InBufferSize = GetState.InBufferSize;
400      }
401    
402    SetState.OutBufferSize = GetState.OutBufferSize;
403    
404    if (lpCollectDataTimeout != NULL)
405      {
406         SetState.Timeout.QuadPart = (*lpCollectDataTimeout) * -10000;
407      }
408    else
409      {
410         SetState.Timeout = GetState.Timeout;
411      }
412
413    Status = NtFsControlFile(hNamedPipe,
414                             NULL,
415                             NULL,
416                             NULL,
417                             &Iosb,
418                             FSCTL_PIPE_SET_STATE,
419                             &SetState,
420                             sizeof(NPFS_SET_STATE),
421                             NULL,
422                             0);
423    if (Status == STATUS_PENDING)
424      {
425         Status = NtWaitForSingleObject(hNamedPipe,
426                                        FALSE,
427                                        NULL);
428         if (!NT_SUCCESS(Status))
429           {
430              SetLastErrorByStatus(Status);
431              return(FALSE);
432           }
433      }
434
435   return(TRUE);
436 }
437
438
439 BOOL STDCALL
440 CallNamedPipeA(LPCSTR lpNamedPipeName,
441                LPVOID lpInBuffer,
442                DWORD nInBufferSize,
443                LPVOID lpOutBuffer,
444                DWORD nOutBufferSize,
445                LPDWORD lpBytesRead,
446                DWORD nTimeOut)
447 {
448   UNICODE_STRING PipeName;
449   BOOL Result;
450   
451   RtlCreateUnicodeStringFromAsciiz(&PipeName,
452                                    (LPSTR)lpNamedPipeName);
453   
454   Result = CallNamedPipeW(PipeName.Buffer,
455                           lpInBuffer,
456                           nInBufferSize,
457                           lpOutBuffer,
458                           nOutBufferSize,
459                           lpBytesRead,
460                           nTimeOut);
461   
462   RtlFreeUnicodeString(&PipeName);
463   
464   return(Result);
465 }
466
467
468 BOOL STDCALL
469 CallNamedPipeW(LPCWSTR lpNamedPipeName,
470                LPVOID lpInBuffer,
471                DWORD nInBufferSize,
472                LPVOID lpOutBuffer,
473                DWORD nOutBufferSize,
474                LPDWORD lpBytesRead,
475                DWORD nTimeOut)
476 {
477   HANDLE hPipe = INVALID_HANDLE_VALUE;
478   BOOL bRetry = TRUE;
479   BOOL bError = FALSE;
480   DWORD dwPipeMode;
481
482   while (TRUE)
483     {
484       hPipe = CreateFileW(lpNamedPipeName,
485                           GENERIC_READ | GENERIC_WRITE,
486                           FILE_SHARE_READ | FILE_SHARE_WRITE,
487                           NULL,
488                           OPEN_EXISTING,
489                           FILE_ATTRIBUTE_NORMAL,
490                           NULL);
491       if (hPipe != INVALID_HANDLE_VALUE)
492         break;
493
494       if (bRetry == FALSE)
495         return(FALSE);
496
497       WaitNamedPipeW(lpNamedPipeName,
498                      nTimeOut);
499
500       bRetry = FALSE;
501     }
502
503   dwPipeMode = PIPE_READMODE_MESSAGE;
504   bError = SetNamedPipeHandleState(hPipe,
505                                    &dwPipeMode,
506                                    NULL,
507                                    NULL);
508   if (!bError)
509     {
510       CloseHandle(hPipe);
511       return(FALSE);
512     }
513
514   bError = TransactNamedPipe(hPipe,
515                              lpInBuffer,
516                              nInBufferSize,
517                              lpOutBuffer,
518                              nOutBufferSize,
519                              lpBytesRead,
520                              NULL);
521   CloseHandle(hPipe);
522
523   return(bError);
524 }
525
526
527 BOOL STDCALL
528 DisconnectNamedPipe(HANDLE hNamedPipe)
529 {
530   IO_STATUS_BLOCK Iosb;
531   NTSTATUS Status;
532
533   Status = NtFsControlFile(hNamedPipe,
534                            NULL,
535                            NULL,
536                            NULL,
537                            &Iosb,
538                            FSCTL_PIPE_DISCONNECT,
539                            NULL,
540                            0,
541                            NULL,
542                            0);
543   if (Status == STATUS_PENDING)
544     {
545       Status = NtWaitForSingleObject(hNamedPipe,
546                                      FALSE,
547                                      NULL);
548       if (!NT_SUCCESS(Status))
549         {
550           SetLastErrorByStatus(Status);
551           return(FALSE);
552         }
553     }
554
555   if (!NT_SUCCESS(Status))
556     {
557       SetLastErrorByStatus(Status);
558       return(FALSE);
559     }
560   return(TRUE);
561 }
562
563
564 WINBOOL STDCALL
565 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
566                          LPDWORD lpState,
567                          LPDWORD lpCurInstances,
568                          LPDWORD lpMaxCollectionCount,
569                          LPDWORD lpCollectDataTimeout,
570                          LPWSTR lpUserName,
571                          DWORD nMaxUserNameSize)
572 {
573   FILE_PIPE_LOCAL_INFORMATION LocalInfo;
574   FILE_PIPE_INFORMATION PipeInfo;
575   IO_STATUS_BLOCK StatusBlock;
576   NTSTATUS Status;
577
578   if (lpState != NULL)
579     {
580       Status = NtQueryInformationFile(hNamedPipe,
581                                       &StatusBlock,
582                                       &PipeInfo,
583                                       sizeof(FILE_PIPE_INFORMATION),
584                                       FilePipeInformation);
585       if (!NT_SUCCESS(Status))
586         {
587           SetLastErrorByStatus(Status);
588           return(FALSE);
589         }
590       *lpState = 0; /* FIXME */
591     }
592
593   if (lpCurInstances != NULL)
594     {
595       Status = NtQueryInformationFile(hNamedPipe,
596                                       &StatusBlock,
597                                       &LocalInfo,
598                                       sizeof(FILE_PIPE_LOCAL_INFORMATION),
599                                       FilePipeLocalInformation);
600       if (!NT_SUCCESS(Status))
601         {
602           SetLastErrorByStatus(Status);
603           return(FALSE);
604         }
605       *lpCurInstances = min(LocalInfo.CurrentInstances, 255);
606     }
607
608
609   /* FIXME: retrieve remaining information */
610
611
612   return(TRUE);
613 }
614
615
616 WINBOOL STDCALL
617 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
618                          LPDWORD lpState,
619                          LPDWORD lpCurInstances,
620                          LPDWORD lpMaxCollectionCount,
621                          LPDWORD lpCollectDataTimeout,
622                          LPSTR lpUserName,
623                          DWORD nMaxUserNameSize)
624 {
625         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
626         return FALSE;
627 }
628
629
630 WINBOOL STDCALL
631 GetNamedPipeInfo(HANDLE hNamedPipe,
632                  LPDWORD lpFlags,
633                  LPDWORD lpOutBufferSize,
634                  LPDWORD lpInBufferSize,
635                  LPDWORD lpMaxInstances)
636 {
637   FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
638   IO_STATUS_BLOCK StatusBlock;
639   NTSTATUS Status;
640   
641   Status = NtQueryInformationFile(hNamedPipe,
642                                   &StatusBlock,
643                                   &PipeLocalInformation,
644                                   sizeof(FILE_PIPE_LOCAL_INFORMATION),
645                                   FilePipeLocalInformation);
646   if (!NT_SUCCESS(Status))
647     {
648       SetLastErrorByStatus(Status);
649       return(FALSE);
650     }
651   
652   if (lpFlags != NULL)
653     {
654       *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
655       *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
656     }
657   
658   if (lpOutBufferSize != NULL)
659     *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
660   
661   if (lpInBufferSize != NULL)
662     *lpInBufferSize = PipeLocalInformation.InboundQuota;
663   
664   if (lpMaxInstances != NULL)
665     {
666       if (PipeLocalInformation.MaximumInstances >= 255)
667         *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
668       else
669         *lpMaxInstances = PipeLocalInformation.MaximumInstances;
670     }
671   
672   return(TRUE);
673 }
674
675
676 BOOL STDCALL
677 PeekNamedPipe(HANDLE hNamedPipe,
678               LPVOID lpBuffer,
679               DWORD nBufferSize,
680               LPDWORD lpBytesRead,
681               LPDWORD lpTotalBytesAvail,
682               LPDWORD lpBytesLeftThisMessage)
683 {
684   PFILE_PIPE_PEEK_BUFFER Buffer;
685   IO_STATUS_BLOCK Iosb;
686   ULONG BufferSize;
687   NTSTATUS Status;
688
689   BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
690   Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
691                            0,
692                            BufferSize);
693
694   Status = NtFsControlFile(hNamedPipe,
695                            NULL,
696                            NULL,
697                            NULL,
698                            &Iosb,
699                            FSCTL_PIPE_PEEK,
700                            NULL,
701                            0,
702                            Buffer,
703                            BufferSize);
704   if (Status == STATUS_PENDING)
705     {
706       Status = NtWaitForSingleObject(hNamedPipe,
707                                      FALSE,
708                                      NULL);
709       if (NT_SUCCESS(Status))
710         Status = Iosb.Status;
711     }
712
713   if (Status == STATUS_BUFFER_OVERFLOW)
714     {
715       Status = STATUS_SUCCESS;
716     }
717
718   if (!NT_SUCCESS(Status))
719     {
720       RtlFreeHeap(RtlGetProcessHeap(),
721                   0,
722                   Buffer);
723       SetLastErrorByStatus(Status);
724       return(FALSE);
725     }
726
727   if (lpTotalBytesAvail != NULL)
728     {
729       *lpTotalBytesAvail = Buffer->ReadDataAvailable;
730     }
731
732   if (lpBytesRead != NULL)
733     {
734       *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
735     }
736
737   if (lpBytesLeftThisMessage != NULL)
738     {
739       *lpBytesLeftThisMessage = Buffer->MessageLength -
740         (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
741     }
742
743   if (lpBuffer != NULL)
744     {
745       memcpy(lpBuffer, Buffer->Data,
746              min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
747     }
748
749   RtlFreeHeap(RtlGetProcessHeap(),
750               0,
751               Buffer);
752
753   return(TRUE);
754 }
755
756
757 BOOL STDCALL
758 TransactNamedPipe(HANDLE hNamedPipe,
759                   LPVOID lpInBuffer,
760                   DWORD nInBufferSize,
761                   LPVOID lpOutBuffer,
762                   DWORD nOutBufferSize,
763                   LPDWORD lpBytesRead,
764                   LPOVERLAPPED lpOverlapped)
765 {
766   IO_STATUS_BLOCK IoStatusBlock;
767   NTSTATUS Status;
768
769   if (lpOverlapped == NULL)
770     {
771       Status = NtFsControlFile(hNamedPipe,
772                                NULL,
773                                NULL,
774                                NULL,
775                                &IoStatusBlock,
776                                FSCTL_PIPE_TRANSCEIVE,
777                                lpInBuffer,
778                                nInBufferSize,
779                                lpOutBuffer,
780                                nOutBufferSize);
781       if (Status == STATUS_PENDING)
782         {
783           NtWaitForSingleObject(hNamedPipe,
784                                 0,
785                                 FALSE);
786           Status = IoStatusBlock.Status;
787         }
788       if (NT_SUCCESS(Status))
789         {
790           *lpBytesRead = IoStatusBlock.Information;
791         }
792     }
793   else
794     {
795       lpOverlapped->Internal = STATUS_PENDING;
796
797       Status = NtFsControlFile(hNamedPipe,
798                                lpOverlapped->hEvent,
799                                NULL,
800                                NULL,
801                                (PIO_STATUS_BLOCK)lpOverlapped,
802                                FSCTL_PIPE_TRANSCEIVE,
803                                lpInBuffer,
804                                nInBufferSize,
805                                lpOutBuffer,
806                                nOutBufferSize);
807     }
808
809   if (!NT_SUCCESS(Status))
810     {
811       SetLastErrorByStatus(Status);
812       return(FALSE);
813     }
814
815   return(TRUE);
816 }
817
818 /* EOF */