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