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