Revert 18883 and 18912, as they break named pipes
[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 = 0xFFFFFFFF;
181 }
182
183 DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
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 FILE_PIPE_WAIT_FOR_BUFFER 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_READ_ATTRIBUTES | SYNCHRONIZE,
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 * -10000LL;
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(IN HANDLE hNamedPipe,
304 IN LPOVERLAPPED lpOverlapped)
305 {
306 NTSTATUS Status;
307
308 if (lpOverlapped != NULL)
309 {
310 PVOID ApcContext;
311
312 lpOverlapped->Internal = STATUS_PENDING;
313 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
314
315 Status = NtFsControlFile(hNamedPipe,
316 lpOverlapped->hEvent,
317 NULL,
318 ApcContext,
319 (PIO_STATUS_BLOCK)lpOverlapped,
320 FSCTL_PIPE_LISTEN,
321 NULL,
322 0,
323 NULL,
324 0);
325
326 /* return FALSE in case of failure and pending operations! */
327 if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
328 {
329 SetLastErrorByStatus(Status);
330 return FALSE;
331 }
332 }
333 else
334 {
335 IO_STATUS_BLOCK Iosb;
336
337 Status = NtFsControlFile(hNamedPipe,
338 NULL,
339 NULL,
340 NULL,
341 &Iosb,
342 FSCTL_PIPE_LISTEN,
343 NULL,
344 0,
345 NULL,
346 0);
347
348 /* wait in case operation is pending */
349 if (Status == STATUS_PENDING)
350 {
351 Status = NtWaitForSingleObject(hNamedPipe,
352 FALSE,
353 NULL);
354 if (NT_SUCCESS(Status))
355 {
356 Status = Iosb.Status;
357 }
358 }
359
360 if (!NT_SUCCESS(Status))
361 {
362 SetLastErrorByStatus(Status);
363 return FALSE;
364 }
365 }
366
367 return TRUE;
368 }
369
370
371 /*
372 * @implemented
373 */
374 BOOL
375 STDCALL
376 SetNamedPipeHandleState(HANDLE hNamedPipe,
377 LPDWORD lpMode,
378 LPDWORD lpMaxCollectionCount,
379 LPDWORD lpCollectDataTimeout)
380 {
381 IO_STATUS_BLOCK Iosb;
382 NTSTATUS Status;
383
384 /* Check if the Mode is being changed */
385 if (lpMode)
386 {
387 FILE_PIPE_INFORMATION Settings;
388
389 /* Set the Completion Mode */
390 Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
391 FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
392
393 /* Set the Read Mode */
394 Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
395 FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
396
397 /* Send the changes to the Driver */
398 Status = NtSetInformationFile(hNamedPipe,
399 &Iosb,
400 &Settings,
401 sizeof(FILE_PIPE_INFORMATION),
402 FilePipeInformation);
403 if (!NT_SUCCESS(Status))
404 {
405 SetLastErrorByStatus(Status);
406 return(FALSE);
407 }
408 }
409
410 /* Check if the Collection count or Timeout are being changed */
411 if (lpMaxCollectionCount || lpCollectDataTimeout)
412 {
413 FILE_PIPE_REMOTE_INFORMATION RemoteSettings;
414
415 /* Setting one without the other would delete it, so we read old one */
416 if (!lpMaxCollectionCount || !lpCollectDataTimeout)
417 {
418 Status = NtQueryInformationFile(hNamedPipe,
419 &Iosb,
420 &RemoteSettings,
421 sizeof(FILE_PIPE_REMOTE_INFORMATION),
422 FilePipeRemoteInformation);
423
424 if (!NT_SUCCESS(Status))
425 {
426 SetLastErrorByStatus(Status);
427 return(FALSE);
428 }
429 }
430
431 /* Now set the new settings */
432 RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
433 *lpMaxCollectionCount :
434 RemoteSettings.MaximumCollectionCount;
435 if (lpCollectDataTimeout)
436 {
437 /* Convert it to Quad */
438 RemoteSettings.CollectDataTime.QuadPart = -(LONGLONG)
439 UInt32x32To64(10000,
440 *lpCollectDataTimeout);
441 }
442
443 /* Tell the driver to change them */
444 Status = NtSetInformationFile(hNamedPipe,
445 &Iosb,
446 &RemoteSettings,
447 sizeof(FILE_PIPE_REMOTE_INFORMATION),
448 FilePipeRemoteInformation);
449
450 if (!NT_SUCCESS(Status))
451 {
452 SetLastErrorByStatus(Status);
453 return(FALSE);
454 }
455 }
456
457 /* All done */
458 return TRUE;
459 }
460
461 /*
462 * @implemented
463 */
464 BOOL STDCALL
465 CallNamedPipeA(LPCSTR lpNamedPipeName,
466 LPVOID lpInBuffer,
467 DWORD nInBufferSize,
468 LPVOID lpOutBuffer,
469 DWORD nOutBufferSize,
470 LPDWORD lpBytesRead,
471 DWORD nTimeOut)
472 {
473 UNICODE_STRING PipeName;
474 BOOL Result;
475
476 RtlCreateUnicodeStringFromAsciiz(&PipeName,
477 (LPSTR)lpNamedPipeName);
478
479 Result = CallNamedPipeW(PipeName.Buffer,
480 lpInBuffer,
481 nInBufferSize,
482 lpOutBuffer,
483 nOutBufferSize,
484 lpBytesRead,
485 nTimeOut);
486
487 RtlFreeUnicodeString(&PipeName);
488
489 return(Result);
490 }
491
492
493 /*
494 * @implemented
495 */
496 BOOL STDCALL
497 CallNamedPipeW(LPCWSTR lpNamedPipeName,
498 LPVOID lpInBuffer,
499 DWORD nInBufferSize,
500 LPVOID lpOutBuffer,
501 DWORD nOutBufferSize,
502 LPDWORD lpBytesRead,
503 DWORD nTimeOut)
504 {
505 HANDLE hPipe = INVALID_HANDLE_VALUE;
506 BOOL bRetry = TRUE;
507 BOOL bError = FALSE;
508 DWORD dwPipeMode;
509
510 while (TRUE)
511 {
512 hPipe = CreateFileW(lpNamedPipeName,
513 GENERIC_READ | GENERIC_WRITE,
514 FILE_SHARE_READ | FILE_SHARE_WRITE,
515 NULL,
516 OPEN_EXISTING,
517 FILE_ATTRIBUTE_NORMAL,
518 NULL);
519 if (hPipe != INVALID_HANDLE_VALUE)
520 break;
521
522 if (bRetry == FALSE)
523 return(FALSE);
524
525 WaitNamedPipeW(lpNamedPipeName,
526 nTimeOut);
527
528 bRetry = FALSE;
529 }
530
531 dwPipeMode = PIPE_READMODE_MESSAGE;
532 bError = SetNamedPipeHandleState(hPipe,
533 &dwPipeMode,
534 NULL,
535 NULL);
536 if (!bError)
537 {
538 CloseHandle(hPipe);
539 return(FALSE);
540 }
541
542 bError = TransactNamedPipe(hPipe,
543 lpInBuffer,
544 nInBufferSize,
545 lpOutBuffer,
546 nOutBufferSize,
547 lpBytesRead,
548 NULL);
549 CloseHandle(hPipe);
550
551 return(bError);
552 }
553
554
555 /*
556 * @implemented
557 */
558 BOOL STDCALL
559 DisconnectNamedPipe(HANDLE hNamedPipe)
560 {
561 IO_STATUS_BLOCK Iosb;
562 NTSTATUS Status;
563
564 Status = NtFsControlFile(hNamedPipe,
565 NULL,
566 NULL,
567 NULL,
568 &Iosb,
569 FSCTL_PIPE_DISCONNECT,
570 NULL,
571 0,
572 NULL,
573 0);
574 if (Status == STATUS_PENDING)
575 {
576 Status = NtWaitForSingleObject(hNamedPipe,
577 FALSE,
578 NULL);
579 if (!NT_SUCCESS(Status))
580 {
581 SetLastErrorByStatus(Status);
582 return(FALSE);
583 }
584 }
585
586 if (!NT_SUCCESS(Status))
587 {
588 SetLastErrorByStatus(Status);
589 return(FALSE);
590 }
591 return(TRUE);
592 }
593
594
595 /*
596 * @unimplemented
597 */
598 BOOL STDCALL
599 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
600 LPDWORD lpState,
601 LPDWORD lpCurInstances,
602 LPDWORD lpMaxCollectionCount,
603 LPDWORD lpCollectDataTimeout,
604 LPWSTR lpUserName,
605 DWORD nMaxUserNameSize)
606 {
607 IO_STATUS_BLOCK StatusBlock;
608 NTSTATUS Status;
609
610 if (lpState != NULL)
611 {
612 FILE_PIPE_INFORMATION PipeInfo;
613
614 Status = NtQueryInformationFile(hNamedPipe,
615 &StatusBlock,
616 &PipeInfo,
617 sizeof(FILE_PIPE_INFORMATION),
618 FilePipeInformation);
619 if (!NT_SUCCESS(Status))
620 {
621 SetLastErrorByStatus(Status);
622 return FALSE;
623 }
624
625 *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
626 *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
627 }
628
629 if(lpCurInstances != NULL)
630 {
631 FILE_PIPE_LOCAL_INFORMATION LocalInfo;
632
633 Status = NtQueryInformationFile(hNamedPipe,
634 &StatusBlock,
635 &LocalInfo,
636 sizeof(FILE_PIPE_LOCAL_INFORMATION),
637 FilePipeLocalInformation);
638 if(!NT_SUCCESS(Status))
639 {
640 SetLastErrorByStatus(Status);
641 return FALSE;
642 }
643
644 *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
645 }
646
647 if(lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
648 {
649 FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
650
651 Status = NtQueryInformationFile(hNamedPipe,
652 &StatusBlock,
653 &RemoteInfo,
654 sizeof(FILE_PIPE_REMOTE_INFORMATION),
655 FilePipeRemoteInformation);
656 if(!NT_SUCCESS(Status))
657 {
658 SetLastErrorByStatus(Status);
659 return FALSE;
660 }
661
662 if(lpMaxCollectionCount != NULL)
663 {
664 *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
665 }
666
667 if(lpCollectDataTimeout != NULL)
668 {
669 /* FIXME */
670 *lpCollectDataTimeout = 0;
671 }
672 }
673
674 if(lpUserName != NULL)
675 {
676 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
677 retreive the user name with GetUserName(), revert the impersonation
678 and finally restore the thread token */
679 }
680
681 return TRUE;
682 }
683
684
685 /*
686 * @implemented
687 */
688 BOOL STDCALL
689 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
690 LPDWORD lpState,
691 LPDWORD lpCurInstances,
692 LPDWORD lpMaxCollectionCount,
693 LPDWORD lpCollectDataTimeout,
694 LPSTR lpUserName,
695 DWORD nMaxUserNameSize)
696 {
697 UNICODE_STRING UserNameW;
698 ANSI_STRING UserNameA;
699 BOOL Ret;
700
701 if(lpUserName != NULL)
702 {
703 UserNameW.Length = 0;
704 UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
705 UserNameW.Buffer = HeapAlloc(GetCurrentProcess(), 0, UserNameW.MaximumLength);
706
707 UserNameA.Buffer = lpUserName;
708 UserNameA.Length = 0;
709 UserNameA.MaximumLength = nMaxUserNameSize;
710 }
711
712 Ret = GetNamedPipeHandleStateW(hNamedPipe,
713 lpState,
714 lpCurInstances,
715 lpMaxCollectionCount,
716 lpCollectDataTimeout,
717 UserNameW.Buffer,
718 nMaxUserNameSize);
719
720 if(Ret && lpUserName != NULL)
721 {
722 NTSTATUS Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
723 if(!NT_SUCCESS(Status))
724 {
725 SetLastErrorByStatus(Status);
726 Ret = FALSE;
727 }
728 }
729
730 if(UserNameW.Buffer != NULL)
731 {
732 HeapFree(GetCurrentProcess(), 0, UserNameW.Buffer);
733 }
734
735 return Ret;
736 }
737
738
739 /*
740 * @implemented
741 */
742 BOOL STDCALL
743 GetNamedPipeInfo(HANDLE hNamedPipe,
744 LPDWORD lpFlags,
745 LPDWORD lpOutBufferSize,
746 LPDWORD lpInBufferSize,
747 LPDWORD lpMaxInstances)
748 {
749 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
750 IO_STATUS_BLOCK StatusBlock;
751 NTSTATUS Status;
752
753 Status = NtQueryInformationFile(hNamedPipe,
754 &StatusBlock,
755 &PipeLocalInformation,
756 sizeof(FILE_PIPE_LOCAL_INFORMATION),
757 FilePipeLocalInformation);
758 if (!NT_SUCCESS(Status))
759 {
760 SetLastErrorByStatus(Status);
761 return(FALSE);
762 }
763
764 if (lpFlags != NULL)
765 {
766 *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
767 *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
768 }
769
770 if (lpOutBufferSize != NULL)
771 *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
772
773 if (lpInBufferSize != NULL)
774 *lpInBufferSize = PipeLocalInformation.InboundQuota;
775
776 if (lpMaxInstances != NULL)
777 {
778 if (PipeLocalInformation.MaximumInstances >= 255)
779 *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
780 else
781 *lpMaxInstances = PipeLocalInformation.MaximumInstances;
782 }
783
784 return(TRUE);
785 }
786
787
788 /*
789 * @implemented
790 */
791 BOOL STDCALL
792 PeekNamedPipe(HANDLE hNamedPipe,
793 LPVOID lpBuffer,
794 DWORD nBufferSize,
795 LPDWORD lpBytesRead,
796 LPDWORD lpTotalBytesAvail,
797 LPDWORD lpBytesLeftThisMessage)
798 {
799 PFILE_PIPE_PEEK_BUFFER Buffer;
800 IO_STATUS_BLOCK Iosb;
801 ULONG BufferSize;
802 NTSTATUS Status;
803
804 BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
805 Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
806 0,
807 BufferSize);
808
809 Status = NtFsControlFile(hNamedPipe,
810 NULL,
811 NULL,
812 NULL,
813 &Iosb,
814 FSCTL_PIPE_PEEK,
815 NULL,
816 0,
817 Buffer,
818 BufferSize);
819 if (Status == STATUS_PENDING)
820 {
821 Status = NtWaitForSingleObject(hNamedPipe,
822 FALSE,
823 NULL);
824 if (NT_SUCCESS(Status))
825 Status = Iosb.Status;
826 }
827
828 if (Status == STATUS_BUFFER_OVERFLOW)
829 {
830 Status = STATUS_SUCCESS;
831 }
832
833 if (!NT_SUCCESS(Status))
834 {
835 RtlFreeHeap(RtlGetProcessHeap(),
836 0,
837 Buffer);
838 SetLastErrorByStatus(Status);
839 return(FALSE);
840 }
841
842 if (lpTotalBytesAvail != NULL)
843 {
844 *lpTotalBytesAvail = Buffer->ReadDataAvailable;
845 }
846
847 if (lpBytesRead != NULL)
848 {
849 *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
850 }
851
852 if (lpBytesLeftThisMessage != NULL)
853 {
854 *lpBytesLeftThisMessage = Buffer->MessageLength -
855 (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
856 }
857
858 if (lpBuffer != NULL)
859 {
860 memcpy(lpBuffer, Buffer->Data,
861 min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
862 }
863
864 RtlFreeHeap(RtlGetProcessHeap(),
865 0,
866 Buffer);
867
868 return(TRUE);
869 }
870
871
872 /*
873 * @implemented
874 */
875 BOOL STDCALL
876 TransactNamedPipe(IN HANDLE hNamedPipe,
877 IN LPVOID lpInBuffer,
878 IN DWORD nInBufferSize,
879 OUT LPVOID lpOutBuffer,
880 IN DWORD nOutBufferSize,
881 OUT LPDWORD lpBytesRead OPTIONAL,
882 IN LPOVERLAPPED lpOverlapped OPTIONAL)
883 {
884 NTSTATUS Status;
885
886 if (lpBytesRead != NULL)
887 {
888 *lpBytesRead = 0;
889 }
890
891 if (lpOverlapped != NULL)
892 {
893 PVOID ApcContext;
894
895 ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
896 lpOverlapped->Internal = STATUS_PENDING;
897
898 Status = NtFsControlFile(hNamedPipe,
899 lpOverlapped->hEvent,
900 NULL,
901 ApcContext,
902 (PIO_STATUS_BLOCK)lpOverlapped,
903 FSCTL_PIPE_TRANSCEIVE,
904 lpInBuffer,
905 nInBufferSize,
906 lpOutBuffer,
907 nOutBufferSize);
908
909 /* return FALSE in case of failure and pending operations! */
910 if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
911 {
912 SetLastErrorByStatus(Status);
913 return FALSE;
914 }
915
916 if (lpBytesRead != NULL)
917 {
918 *lpBytesRead = lpOverlapped->InternalHigh;
919 }
920 }
921 else
922 {
923 IO_STATUS_BLOCK Iosb;
924
925 Status = NtFsControlFile(hNamedPipe,
926 NULL,
927 NULL,
928 NULL,
929 &Iosb,
930 FSCTL_PIPE_TRANSCEIVE,
931 lpInBuffer,
932 nInBufferSize,
933 lpOutBuffer,
934 nOutBufferSize);
935
936 /* wait in case operation is pending */
937 if (Status == STATUS_PENDING)
938 {
939 Status = NtWaitForSingleObject(hNamedPipe,
940 FALSE,
941 NULL);
942 if (NT_SUCCESS(Status))
943 {
944 Status = Iosb.Status;
945 }
946 }
947
948 if (NT_SUCCESS(Status))
949 {
950 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
951 check that case either and crashes (only after the operation
952 completed) */
953 *lpBytesRead = Iosb.Information;
954 }
955 else
956 {
957 SetLastErrorByStatus(Status);
958 return FALSE;
959 }
960 }
961
962 return TRUE;
963 }
964
965 /* EOF */