Implemented CallNamedPipeW() and TransactNamedPipe().
[reactos.git] / reactos / lib / kernel32 / file / npipe.c
1 /* $Id: npipe.c,v 1.10 2002/06/25 18:49:38 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 <ddk/ntddk.h>
14 #include <ntdll/rtl.h>
15 #include <windows.h>
16 #include <kernel32/error.h>
17 //#include <wchar.h>
18 //#include <string.h>
19 #include <limits.h>
20 #include <napi/npipe.h>
21
22 //#define NDEBUG
23 #include <kernel32/kernel32.h>
24
25 /* FUNCTIONS ****************************************************************/
26
27 HANDLE STDCALL
28 CreateNamedPipeA(LPCSTR lpName,
29 DWORD dwOpenMode,
30 DWORD dwPipeMode,
31 DWORD nMaxInstances,
32 DWORD nOutBufferSize,
33 DWORD nInBufferSize,
34 DWORD nDefaultTimeOut,
35 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
36 {
37 HANDLE NamedPipeHandle;
38 UNICODE_STRING NameU;
39 ANSI_STRING NameA;
40
41 RtlInitAnsiString(&NameA, (LPSTR)lpName);
42 RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
43
44 NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
45 dwOpenMode,
46 dwPipeMode,
47 nMaxInstances,
48 nOutBufferSize,
49 nInBufferSize,
50 nDefaultTimeOut,
51 lpSecurityAttributes);
52
53 RtlFreeUnicodeString(&NameU);
54
55 return(NamedPipeHandle);
56 }
57
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 BOOL STDCALL
206 WaitNamedPipeA(LPCSTR lpNamedPipeName,
207 DWORD nTimeOut)
208 {
209 BOOL r;
210 UNICODE_STRING NameU;
211 ANSI_STRING NameA;
212
213 RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
214 RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
215
216 r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
217
218 RtlFreeUnicodeString(&NameU);
219
220 return(r);
221 }
222
223
224 BOOL STDCALL
225 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
226 DWORD nTimeOut)
227 {
228 UNICODE_STRING NamedPipeName;
229 BOOL r;
230 NTSTATUS Status;
231 OBJECT_ATTRIBUTES ObjectAttributes;
232 NPFS_WAIT_PIPE WaitPipe;
233 HANDLE FileHandle;
234 IO_STATUS_BLOCK Iosb;
235
236 r = RtlDosPathNameToNtPathName_U((LPWSTR)lpNamedPipeName,
237 &NamedPipeName,
238 NULL,
239 NULL);
240
241 if (!r)
242 {
243 return(FALSE);
244 }
245
246 InitializeObjectAttributes(&ObjectAttributes,
247 &NamedPipeName,
248 OBJ_CASE_INSENSITIVE,
249 NULL,
250 NULL);
251 Status = NtOpenFile(&FileHandle,
252 FILE_GENERIC_READ,
253 &ObjectAttributes,
254 &Iosb,
255 0,
256 FILE_SYNCHRONOUS_IO_ALERT);
257 if (!NT_SUCCESS(Status))
258 {
259 SetLastErrorByStatus (Status);
260 return(FALSE);
261 }
262
263 WaitPipe.Timeout.QuadPart = nTimeOut * -10000;
264
265 Status = NtFsControlFile(FileHandle,
266 NULL,
267 NULL,
268 NULL,
269 &Iosb,
270 FSCTL_PIPE_WAIT,
271 &WaitPipe,
272 sizeof(WaitPipe),
273 NULL,
274 0);
275 NtClose(FileHandle);
276 if (!NT_SUCCESS(Status))
277 {
278 SetLastErrorByStatus (Status);
279 return(FALSE);
280 }
281
282 return(TRUE);
283 }
284
285
286 BOOL STDCALL
287 ConnectNamedPipe(HANDLE hNamedPipe,
288 LPOVERLAPPED lpOverlapped)
289 {
290 IO_STATUS_BLOCK Iosb;
291 HANDLE hEvent;
292 PIO_STATUS_BLOCK IoStatusBlock;
293 NTSTATUS Status;
294
295 if (lpOverlapped != NULL)
296 {
297 lpOverlapped->Internal = STATUS_PENDING;
298 hEvent = lpOverlapped->hEvent;
299 IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
300 }
301 else
302 {
303 IoStatusBlock = &Iosb;
304 hEvent = NULL;
305 }
306
307 Status = NtFsControlFile(hNamedPipe,
308 hEvent,
309 NULL,
310 NULL,
311 IoStatusBlock,
312 FSCTL_PIPE_LISTEN,
313 NULL,
314 0,
315 NULL,
316 0);
317 if ((lpOverlapped == NULL) && (Status == STATUS_PENDING))
318 {
319 Status = NtWaitForSingleObject(hNamedPipe,
320 FALSE,
321 NULL);
322 if (!NT_SUCCESS(Status))
323 {
324 SetLastErrorByStatus(Status);
325 return(FALSE);
326 }
327 Status = Iosb.Status;
328 }
329 if (!NT_SUCCESS(Status) || (Status == STATUS_PENDING))
330 {
331 SetLastErrorByStatus (Status);
332 return(FALSE);
333 }
334 return(TRUE);
335 }
336
337
338 BOOL STDCALL
339 SetNamedPipeHandleState(HANDLE hNamedPipe,
340 LPDWORD lpMode,
341 LPDWORD lpMaxCollectionCount,
342 LPDWORD lpCollectDataTimeout)
343 {
344 NPFS_GET_STATE GetState;
345 NPFS_SET_STATE SetState;
346 IO_STATUS_BLOCK Iosb;
347 NTSTATUS Status;
348
349 Status = NtFsControlFile(hNamedPipe,
350 NULL,
351 NULL,
352 NULL,
353 &Iosb,
354 FSCTL_PIPE_GET_STATE,
355 NULL,
356 0,
357 &GetState,
358 sizeof(NPFS_GET_STATE));
359 if (Status == STATUS_PENDING)
360 {
361 Status = NtWaitForSingleObject(hNamedPipe,
362 FALSE,
363 NULL);
364 if (!NT_SUCCESS(Status))
365 {
366 SetLastErrorByStatus(Status);
367 return(FALSE);
368 }
369 }
370
371 if (lpMode != NULL)
372 {
373 if ((*lpMode) & PIPE_READMODE_MESSAGE)
374 {
375 SetState.ReadModeMessage = TRUE;
376 }
377 else
378 {
379 SetState.ReadModeMessage = FALSE;
380 }
381 if ((*lpMode) & PIPE_NOWAIT)
382 {
383 SetState.NonBlocking = TRUE;
384 }
385 else
386 {
387 SetState.NonBlocking = FALSE;
388 }
389 SetState.WriteModeMessage = GetState.WriteModeMessage;
390 }
391 else
392 {
393 SetState.ReadModeMessage = GetState.ReadModeMessage;
394 SetState.WriteModeMessage = GetState.WriteModeMessage;
395 SetState.NonBlocking = SetState.NonBlocking;
396 }
397
398 if (lpMaxCollectionCount != NULL)
399 {
400 SetState.InBufferSize = *lpMaxCollectionCount;
401 }
402 else
403 {
404 SetState.InBufferSize = GetState.InBufferSize;
405 }
406
407 SetState.OutBufferSize = GetState.OutBufferSize;
408
409 if (lpCollectDataTimeout != NULL)
410 {
411 SetState.Timeout.QuadPart = (*lpCollectDataTimeout) * -10000;
412 }
413 else
414 {
415 SetState.Timeout = GetState.Timeout;
416 }
417
418 Status = NtFsControlFile(hNamedPipe,
419 NULL,
420 NULL,
421 NULL,
422 &Iosb,
423 FSCTL_PIPE_SET_STATE,
424 &SetState,
425 sizeof(NPFS_SET_STATE),
426 NULL,
427 0);
428 if (Status == STATUS_PENDING)
429 {
430 Status = NtWaitForSingleObject(hNamedPipe,
431 FALSE,
432 NULL);
433 if (!NT_SUCCESS(Status))
434 {
435 SetLastErrorByStatus(Status);
436 return(FALSE);
437 }
438 }
439
440 return(TRUE);
441 }
442
443
444 BOOL STDCALL
445 CallNamedPipeA(LPCSTR lpNamedPipeName,
446 LPVOID lpInBuffer,
447 DWORD nInBufferSize,
448 LPVOID lpOutBuffer,
449 DWORD nOutBufferSize,
450 LPDWORD lpBytesRead,
451 DWORD nTimeOut)
452 {
453 UNICODE_STRING PipeName;
454 BOOL Result;
455
456 RtlCreateUnicodeStringFromAsciiz(&PipeName,
457 (LPSTR)lpNamedPipeName);
458
459 Result = CallNamedPipeW(PipeName.Buffer,
460 lpInBuffer,
461 nInBufferSize,
462 lpOutBuffer,
463 nOutBufferSize,
464 lpBytesRead,
465 nTimeOut);
466
467 RtlFreeUnicodeString(&PipeName);
468
469 return(Result);
470 }
471
472
473 BOOL STDCALL
474 CallNamedPipeW(LPCWSTR lpNamedPipeName,
475 LPVOID lpInBuffer,
476 DWORD nInBufferSize,
477 LPVOID lpOutBuffer,
478 DWORD nOutBufferSize,
479 LPDWORD lpBytesRead,
480 DWORD nTimeOut)
481 {
482 HANDLE hPipe = INVALID_HANDLE_VALUE;
483 BOOL bRetry = TRUE;
484 BOOL bError = FALSE;
485 DWORD dwPipeMode;
486
487 while (TRUE)
488 {
489 hPipe = CreateFileW(lpNamedPipeName,
490 GENERIC_READ | GENERIC_WRITE,
491 FILE_SHARE_READ | FILE_SHARE_WRITE,
492 NULL,
493 OPEN_EXISTING,
494 FILE_ATTRIBUTE_NORMAL,
495 NULL);
496 if (hPipe != INVALID_HANDLE_VALUE)
497 break;
498
499 if (bRetry == FALSE)
500 return(FALSE);
501
502 WaitNamedPipeW(lpNamedPipeName,
503 nTimeOut);
504
505 bRetry = FALSE;
506 }
507
508 dwPipeMode = PIPE_READMODE_MESSAGE;
509 bError = SetNamedPipeHandleState(hPipe,
510 &dwPipeMode,
511 NULL,
512 NULL);
513 if (!bError)
514 {
515 CloseHandle(hPipe);
516 return(FALSE);
517 }
518
519 bError = TransactNamedPipe(hPipe,
520 lpInBuffer,
521 nInBufferSize,
522 lpOutBuffer,
523 nOutBufferSize,
524 lpBytesRead,
525 NULL);
526 CloseHandle(hPipe);
527
528 return(bError);
529 }
530
531
532 BOOL STDCALL
533 DisconnectNamedPipe(HANDLE hNamedPipe)
534 {
535 IO_STATUS_BLOCK Iosb;
536 NTSTATUS Status;
537
538 Status = NtFsControlFile(hNamedPipe,
539 NULL,
540 NULL,
541 NULL,
542 &Iosb,
543 FSCTL_PIPE_DISCONNECT,
544 NULL,
545 0,
546 NULL,
547 0);
548 if (Status == STATUS_PENDING)
549 {
550 Status = NtWaitForSingleObject(hNamedPipe,
551 FALSE,
552 NULL);
553 if (!NT_SUCCESS(Status))
554 {
555 SetLastErrorByStatus(Status);
556 return(FALSE);
557 }
558 }
559
560 if (!NT_SUCCESS(Status))
561 {
562 SetLastErrorByStatus(Status);
563 return(FALSE);
564 }
565 return(TRUE);
566 }
567
568
569 WINBOOL STDCALL
570 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
571 LPDWORD lpState,
572 LPDWORD lpCurInstances,
573 LPDWORD lpMaxCollectionCount,
574 LPDWORD lpCollectDataTimeout,
575 LPWSTR lpUserName,
576 DWORD nMaxUserNameSize)
577 {
578 FILE_PIPE_LOCAL_INFORMATION LocalInfo;
579 FILE_PIPE_INFORMATION PipeInfo;
580 IO_STATUS_BLOCK StatusBlock;
581 NTSTATUS Status;
582
583 if (lpState != NULL)
584 {
585 Status = NtQueryInformationFile(hNamedPipe,
586 &StatusBlock,
587 &PipeInfo,
588 sizeof(FILE_PIPE_INFORMATION),
589 FilePipeInformation);
590 if (!NT_SUCCESS(Status))
591 {
592 SetLastErrorByStatus(Status);
593 return(FALSE);
594 }
595 *lpState = 0; /* FIXME */
596 }
597
598 if (lpCurInstances != NULL)
599 {
600 Status = NtQueryInformationFile(hNamedPipe,
601 &StatusBlock,
602 &LocalInfo,
603 sizeof(FILE_PIPE_LOCAL_INFORMATION),
604 FilePipeLocalInformation);
605 if (!NT_SUCCESS(Status))
606 {
607 SetLastErrorByStatus(Status);
608 return(FALSE);
609 }
610 *lpCurInstances = min(LocalInfo.CurrentInstances, 255);
611 }
612
613
614 /* FIXME: retrieve remaining information */
615
616
617 return(TRUE);
618 }
619
620
621 WINBOOL STDCALL
622 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
623 LPDWORD lpState,
624 LPDWORD lpCurInstances,
625 LPDWORD lpMaxCollectionCount,
626 LPDWORD lpCollectDataTimeout,
627 LPSTR lpUserName,
628 DWORD nMaxUserNameSize)
629 {
630 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
631 return FALSE;
632 }
633
634
635 WINBOOL STDCALL
636 GetNamedPipeInfo(HANDLE hNamedPipe,
637 LPDWORD lpFlags,
638 LPDWORD lpOutBufferSize,
639 LPDWORD lpInBufferSize,
640 LPDWORD lpMaxInstances)
641 {
642 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
643 IO_STATUS_BLOCK StatusBlock;
644 NTSTATUS Status;
645
646 Status = NtQueryInformationFile(hNamedPipe,
647 &StatusBlock,
648 &PipeLocalInformation,
649 sizeof(FILE_PIPE_LOCAL_INFORMATION),
650 FilePipeLocalInformation);
651 if (!NT_SUCCESS(Status))
652 {
653 SetLastErrorByStatus(Status);
654 return(FALSE);
655 }
656
657 if (lpFlags != NULL)
658 {
659 *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
660 *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
661 }
662
663 if (lpOutBufferSize != NULL)
664 *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
665
666 if (lpInBufferSize != NULL)
667 *lpInBufferSize = PipeLocalInformation.InboundQuota;
668
669 if (lpMaxInstances != NULL)
670 {
671 if (PipeLocalInformation.MaximumInstances >= 255)
672 *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
673 else
674 *lpMaxInstances = PipeLocalInformation.MaximumInstances;
675 }
676
677 return(TRUE);
678 }
679
680
681 BOOL STDCALL
682 PeekNamedPipe(HANDLE hNamedPipe,
683 LPVOID lpBuffer,
684 DWORD nBufferSize,
685 LPDWORD lpBytesRead,
686 LPDWORD lpTotalBytesAvail,
687 LPDWORD lpBytesLeftThisMessage)
688 {
689 PFILE_PIPE_PEEK_BUFFER Buffer;
690 IO_STATUS_BLOCK Iosb;
691 ULONG BufferSize;
692 NTSTATUS Status;
693
694 BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
695 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
696 0,
697 BufferSize);
698
699 Status = NtFsControlFile(hNamedPipe,
700 NULL,
701 NULL,
702 NULL,
703 &Iosb,
704 FSCTL_PIPE_PEEK,
705 NULL,
706 0,
707 Buffer,
708 BufferSize);
709 if (Status == STATUS_PENDING)
710 {
711 Status = NtWaitForSingleObject(hNamedPipe,
712 FALSE,
713 NULL);
714 if (NT_SUCCESS(Status))
715 Status = Iosb.Status;
716 }
717
718 if (Status == STATUS_BUFFER_OVERFLOW)
719 {
720 Status = STATUS_SUCCESS;
721 }
722
723 if (!NT_SUCCESS(Status))
724 {
725 RtlFreeHeap(RtlGetProcessHeap(),
726 0,
727 Buffer);
728 SetLastErrorByStatus(Status);
729 return(FALSE);
730 }
731
732 if (lpTotalBytesAvail != NULL)
733 {
734 *lpTotalBytesAvail = Buffer->ReadDataAvailable;
735 }
736
737 if (lpBytesRead != NULL)
738 {
739 *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
740 }
741
742 if (lpBytesLeftThisMessage != NULL)
743 {
744 *lpBytesLeftThisMessage = Buffer->MessageLength -
745 (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
746 }
747
748 if (lpBuffer != NULL)
749 {
750 memcpy(lpBuffer, Buffer->Data,
751 min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
752 }
753
754 RtlFreeHeap(RtlGetProcessHeap(),
755 0,
756 Buffer);
757
758 return(TRUE);
759 }
760
761
762 BOOL STDCALL
763 TransactNamedPipe(HANDLE hNamedPipe,
764 LPVOID lpInBuffer,
765 DWORD nInBufferSize,
766 LPVOID lpOutBuffer,
767 DWORD nOutBufferSize,
768 LPDWORD lpBytesRead,
769 LPOVERLAPPED lpOverlapped)
770 {
771 IO_STATUS_BLOCK IoStatusBlock;
772 NTSTATUS Status;
773
774 if (lpOverlapped == NULL)
775 {
776 Status = NtFsControlFile(hNamedPipe,
777 NULL,
778 NULL,
779 NULL,
780 &IoStatusBlock,
781 FSCTL_PIPE_TRANSCEIVE,
782 lpInBuffer,
783 nInBufferSize,
784 lpOutBuffer,
785 nOutBufferSize);
786 if (Status == STATUS_PENDING)
787 {
788 NtWaitForSingleObject(hNamedPipe,
789 0,
790 FALSE);
791 Status = IoStatusBlock.Status;
792 }
793 if (NT_SUCCESS(Status))
794 {
795 *lpBytesRead = IoStatusBlock.Information;
796 }
797 }
798 else
799 {
800 lpOverlapped->Internal = STATUS_PENDING;
801
802 Status = NtFsControlFile(hNamedPipe,
803 lpOverlapped->hEvent,
804 NULL,
805 NULL,
806 (PIO_STATUS_BLOCK)lpOverlapped,
807 FSCTL_PIPE_TRANSCEIVE,
808 lpInBuffer,
809 nInBufferSize,
810 lpOutBuffer,
811 nOutBufferSize);
812 }
813
814 if (!NT_SUCCESS(Status))
815 {
816 SetLastErrorByStatus(Status);
817 return(FALSE);
818 }
819
820 return(TRUE);
821 }
822
823 /* EOF */