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)
11 /* INCLUDES *****************************************************************/
16 #include "../include/debug.h"
18 /* FUNCTIONS ****************************************************************/
24 CreateNamedPipeA(LPCSTR lpName
,
30 DWORD nDefaultTimeOut
,
31 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
33 HANDLE NamedPipeHandle
;
37 RtlInitAnsiString(&NameA
, (LPSTR
)lpName
);
38 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
40 NamedPipeHandle
= CreateNamedPipeW(NameU
.Buffer
,
47 lpSecurityAttributes
);
49 RtlFreeUnicodeString(&NameU
);
51 return(NamedPipeHandle
);
59 CreateNamedPipeW(LPCWSTR lpName
,
65 DWORD nDefaultTimeOut
,
66 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
68 UNICODE_STRING NamedPipeName
;
71 OBJECT_ATTRIBUTES ObjectAttributes
;
73 ACCESS_MASK DesiredAccess
;
75 ULONG CreateDisposition
;
76 ULONG WriteModeMessage
;
77 ULONG ReadModeMessage
;
80 ULONG ShareAccess
, Attributes
;
81 LARGE_INTEGER DefaultTimeOut
;
82 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
84 Result
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpName
,
90 SetLastError(ERROR_PATH_NOT_FOUND
);
91 return(INVALID_HANDLE_VALUE
);
94 DPRINT("Pipe name: %wZ\n", &NamedPipeName
);
95 DPRINT("Pipe name: %S\n", NamedPipeName
.Buffer
);
97 Attributes
= OBJ_CASE_INSENSITIVE
;
98 if(lpSecurityAttributes
)
100 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
101 if(lpSecurityAttributes
->bInheritHandle
)
102 Attributes
|= OBJ_INHERIT
;
105 InitializeObjectAttributes(&ObjectAttributes
,
113 CreateDisposition
= FILE_OPEN_IF
;
115 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
117 CreateOptions
= CreateOptions
| FILE_WRITE_THROUGH
;
119 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
121 CreateOptions
= CreateOptions
| FILE_SYNCHRONOUS_IO_NONALERT
;
123 if (dwOpenMode
& PIPE_ACCESS_DUPLEX
)
125 CreateOptions
= CreateOptions
| FILE_PIPE_FULL_DUPLEX
;
126 DesiredAccess
|= (FILE_GENERIC_READ
| FILE_GENERIC_WRITE
);
128 else if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
130 CreateOptions
= CreateOptions
| FILE_PIPE_INBOUND
;
131 DesiredAccess
|= FILE_GENERIC_READ
;
133 else if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
135 CreateOptions
= CreateOptions
| FILE_PIPE_OUTBOUND
;
136 DesiredAccess
|= FILE_GENERIC_WRITE
;
139 if (dwPipeMode
& PIPE_TYPE_BYTE
)
141 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
143 else if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
145 WriteModeMessage
= FILE_PIPE_MESSAGE_MODE
;
149 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
152 if (dwPipeMode
& PIPE_READMODE_BYTE
)
154 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
156 else if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
158 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
162 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
165 if (dwPipeMode
& PIPE_WAIT
)
167 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
169 else if (dwPipeMode
& PIPE_NOWAIT
)
171 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
175 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
178 if (nMaxInstances
>= PIPE_UNLIMITED_INSTANCES
)
180 nMaxInstances
= ULONG_MAX
;
183 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000;
185 Status
= NtCreateNamedPipeFile(&PipeHandle
,
200 RtlFreeUnicodeString(&NamedPipeName
);
202 if (!NT_SUCCESS(Status
))
204 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status
);
205 SetLastErrorByStatus (Status
);
206 return INVALID_HANDLE_VALUE
;
217 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
221 UNICODE_STRING NameU
;
224 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
225 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
227 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
229 RtlFreeUnicodeString(&NameU
);
239 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
242 UNICODE_STRING NamedPipeName
;
245 OBJECT_ATTRIBUTES ObjectAttributes
;
246 NPFS_WAIT_PIPE WaitPipe
;
248 IO_STATUS_BLOCK Iosb
;
250 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
259 InitializeObjectAttributes(&ObjectAttributes
,
261 OBJ_CASE_INSENSITIVE
,
264 Status
= NtOpenFile(&FileHandle
,
268 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
269 FILE_SYNCHRONOUS_IO_NONALERT
);
270 if (!NT_SUCCESS(Status
))
272 SetLastErrorByStatus (Status
);
276 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000;
278 Status
= NtFsControlFile(FileHandle
,
289 if (!NT_SUCCESS(Status
))
291 SetLastErrorByStatus (Status
);
303 ConnectNamedPipe(HANDLE hNamedPipe
,
304 LPOVERLAPPED lpOverlapped
)
306 PIO_STATUS_BLOCK IoStatusBlock
;
307 IO_STATUS_BLOCK Iosb
;
311 if (lpOverlapped
!= NULL
)
313 lpOverlapped
->Internal
= STATUS_PENDING
;
314 hEvent
= lpOverlapped
->hEvent
;
315 IoStatusBlock
= (PIO_STATUS_BLOCK
)lpOverlapped
;
319 IoStatusBlock
= &Iosb
;
323 Status
= NtFsControlFile(hNamedPipe
,
333 if ((lpOverlapped
!= NULL
) && (Status
== STATUS_PENDING
))
336 if ((lpOverlapped
== NULL
) && (Status
== STATUS_PENDING
))
338 Status
= NtWaitForSingleObject(hNamedPipe
,
341 if (!NT_SUCCESS(Status
))
343 SetLastErrorByStatus(Status
);
346 Status
= Iosb
.Status
;
349 if ((!NT_SUCCESS(Status
) && Status
!= STATUS_PIPE_CONNECTED
) ||
350 (Status
== STATUS_PENDING
))
352 SetLastErrorByStatus(Status
);
364 SetNamedPipeHandleState(HANDLE hNamedPipe
,
366 LPDWORD lpMaxCollectionCount
,
367 LPDWORD lpCollectDataTimeout
)
369 NPFS_GET_STATE GetState
;
370 NPFS_SET_STATE SetState
;
371 IO_STATUS_BLOCK Iosb
;
374 Status
= NtFsControlFile(hNamedPipe
,
379 FSCTL_PIPE_GET_STATE
,
383 sizeof(NPFS_GET_STATE
));
384 if (Status
== STATUS_PENDING
)
386 Status
= NtWaitForSingleObject(hNamedPipe
,
389 if (!NT_SUCCESS(Status
))
391 SetLastErrorByStatus(Status
);
398 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
400 SetState
.ReadModeMessage
= TRUE
;
404 SetState
.ReadModeMessage
= FALSE
;
406 if ((*lpMode
) & PIPE_NOWAIT
)
408 SetState
.NonBlocking
= TRUE
;
412 SetState
.NonBlocking
= FALSE
;
414 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
418 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
419 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
420 SetState
.NonBlocking
= SetState
.NonBlocking
;
423 if (lpMaxCollectionCount
!= NULL
)
425 SetState
.InBufferSize
= *lpMaxCollectionCount
;
429 SetState
.InBufferSize
= GetState
.InBufferSize
;
432 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
434 if (lpCollectDataTimeout
!= NULL
)
436 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000;
440 SetState
.Timeout
= GetState
.Timeout
;
443 Status
= NtFsControlFile(hNamedPipe
,
448 FSCTL_PIPE_SET_STATE
,
450 sizeof(NPFS_SET_STATE
),
453 if (Status
== STATUS_PENDING
)
455 Status
= NtWaitForSingleObject(hNamedPipe
,
458 if (!NT_SUCCESS(Status
))
460 SetLastErrorByStatus(Status
);
473 CallNamedPipeA(LPCSTR lpNamedPipeName
,
477 DWORD nOutBufferSize
,
481 UNICODE_STRING PipeName
;
484 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
485 (LPSTR
)lpNamedPipeName
);
487 Result
= CallNamedPipeW(PipeName
.Buffer
,
495 RtlFreeUnicodeString(&PipeName
);
505 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
509 DWORD nOutBufferSize
,
513 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
520 hPipe
= CreateFileW(lpNamedPipeName
,
521 GENERIC_READ
| GENERIC_WRITE
,
522 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
525 FILE_ATTRIBUTE_NORMAL
,
527 if (hPipe
!= INVALID_HANDLE_VALUE
)
533 WaitNamedPipeW(lpNamedPipeName
,
539 dwPipeMode
= PIPE_READMODE_MESSAGE
;
540 bError
= SetNamedPipeHandleState(hPipe
,
550 bError
= TransactNamedPipe(hPipe
,
567 DisconnectNamedPipe(HANDLE hNamedPipe
)
569 IO_STATUS_BLOCK Iosb
;
572 Status
= NtFsControlFile(hNamedPipe
,
577 FSCTL_PIPE_DISCONNECT
,
582 if (Status
== STATUS_PENDING
)
584 Status
= NtWaitForSingleObject(hNamedPipe
,
587 if (!NT_SUCCESS(Status
))
589 SetLastErrorByStatus(Status
);
594 if (!NT_SUCCESS(Status
))
596 SetLastErrorByStatus(Status
);
607 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
609 LPDWORD lpCurInstances
,
610 LPDWORD lpMaxCollectionCount
,
611 LPDWORD lpCollectDataTimeout
,
613 DWORD nMaxUserNameSize
)
615 IO_STATUS_BLOCK StatusBlock
;
620 FILE_PIPE_INFORMATION PipeInfo
;
622 Status
= NtQueryInformationFile(hNamedPipe
,
625 sizeof(FILE_PIPE_INFORMATION
),
626 FilePipeInformation
);
627 if (!NT_SUCCESS(Status
))
629 SetLastErrorByStatus(Status
);
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
);
637 if(lpCurInstances
!= NULL
)
639 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
641 Status
= NtQueryInformationFile(hNamedPipe
,
644 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
645 FilePipeLocalInformation
);
646 if(!NT_SUCCESS(Status
))
648 SetLastErrorByStatus(Status
);
652 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
655 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
657 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
659 Status
= NtQueryInformationFile(hNamedPipe
,
662 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
663 FilePipeRemoteInformation
);
664 if(!NT_SUCCESS(Status
))
666 SetLastErrorByStatus(Status
);
670 if(lpMaxCollectionCount
!= NULL
)
672 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
675 if(lpCollectDataTimeout
!= NULL
)
678 *lpCollectDataTimeout
= 0;
682 if(lpUserName
!= NULL
)
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 */
697 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
699 LPDWORD lpCurInstances
,
700 LPDWORD lpMaxCollectionCount
,
701 LPDWORD lpCollectDataTimeout
,
703 DWORD nMaxUserNameSize
)
705 UNICODE_STRING UserNameW
;
706 ANSI_STRING UserNameA
;
709 if(lpUserName
!= NULL
)
711 UserNameW
.Length
= 0;
712 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
713 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
715 UserNameA
.Buffer
= lpUserName
;
716 UserNameA
.Length
= 0;
717 UserNameA
.MaximumLength
= nMaxUserNameSize
;
720 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
723 lpMaxCollectionCount
,
724 lpCollectDataTimeout
,
728 if(Ret
&& lpUserName
!= NULL
)
730 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
731 if(!NT_SUCCESS(Status
))
733 SetLastErrorByStatus(Status
);
738 if(UserNameW
.Buffer
!= NULL
)
740 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
751 GetNamedPipeInfo(HANDLE hNamedPipe
,
753 LPDWORD lpOutBufferSize
,
754 LPDWORD lpInBufferSize
,
755 LPDWORD lpMaxInstances
)
757 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
758 IO_STATUS_BLOCK StatusBlock
;
761 Status
= NtQueryInformationFile(hNamedPipe
,
763 &PipeLocalInformation
,
764 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
765 FilePipeLocalInformation
);
766 if (!NT_SUCCESS(Status
))
768 SetLastErrorByStatus(Status
);
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
;
778 if (lpOutBufferSize
!= NULL
)
779 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
781 if (lpInBufferSize
!= NULL
)
782 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
784 if (lpMaxInstances
!= NULL
)
786 if (PipeLocalInformation
.MaximumInstances
>= 255)
787 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
789 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
800 PeekNamedPipe(HANDLE hNamedPipe
,
804 LPDWORD lpTotalBytesAvail
,
805 LPDWORD lpBytesLeftThisMessage
)
807 PFILE_PIPE_PEEK_BUFFER Buffer
;
808 IO_STATUS_BLOCK Iosb
;
812 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
813 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
817 Status
= NtFsControlFile(hNamedPipe
,
827 if (Status
== STATUS_PENDING
)
829 Status
= NtWaitForSingleObject(hNamedPipe
,
832 if (NT_SUCCESS(Status
))
833 Status
= Iosb
.Status
;
836 if (Status
== STATUS_BUFFER_OVERFLOW
)
838 Status
= STATUS_SUCCESS
;
841 if (!NT_SUCCESS(Status
))
843 RtlFreeHeap(RtlGetProcessHeap(),
846 SetLastErrorByStatus(Status
);
850 if (lpTotalBytesAvail
!= NULL
)
852 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
855 if (lpBytesRead
!= NULL
)
857 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
860 if (lpBytesLeftThisMessage
!= NULL
)
862 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
863 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
866 if (lpBuffer
!= NULL
)
868 memcpy(lpBuffer
, Buffer
->Data
,
869 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
872 RtlFreeHeap(RtlGetProcessHeap(),
884 TransactNamedPipe(HANDLE hNamedPipe
,
888 DWORD nOutBufferSize
,
890 LPOVERLAPPED lpOverlapped
)
892 IO_STATUS_BLOCK IoStatusBlock
;
895 if (lpOverlapped
== NULL
)
897 Status
= NtFsControlFile(hNamedPipe
,
902 FSCTL_PIPE_TRANSCEIVE
,
907 if (Status
== STATUS_PENDING
)
909 NtWaitForSingleObject(hNamedPipe
,
912 Status
= IoStatusBlock
.Status
;
914 if (NT_SUCCESS(Status
))
916 *lpBytesRead
= IoStatusBlock
.Information
;
921 lpOverlapped
->Internal
= STATUS_PENDING
;
923 Status
= NtFsControlFile(hNamedPipe
,
924 lpOverlapped
->hEvent
,
927 (PIO_STATUS_BLOCK
)lpOverlapped
,
928 FSCTL_PIPE_TRANSCEIVE
,
935 if (!NT_SUCCESS(Status
))
937 SetLastErrorByStatus(Status
);