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