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