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