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
))
335 Status
= NtWaitForSingleObject(hNamedPipe
,
338 if (!NT_SUCCESS(Status
))
340 SetLastErrorByStatus(Status
);
343 Status
= Iosb
.Status
;
345 if ((!NT_SUCCESS(Status
) && Status
!= STATUS_PIPE_CONNECTED
) ||
346 (Status
== STATUS_PENDING
))
348 SetLastErrorByStatus(Status
);
359 SetNamedPipeHandleState(HANDLE hNamedPipe
,
361 LPDWORD lpMaxCollectionCount
,
362 LPDWORD lpCollectDataTimeout
)
364 NPFS_GET_STATE GetState
;
365 NPFS_SET_STATE SetState
;
366 IO_STATUS_BLOCK Iosb
;
369 Status
= NtFsControlFile(hNamedPipe
,
374 FSCTL_PIPE_GET_STATE
,
378 sizeof(NPFS_GET_STATE
));
379 if (Status
== STATUS_PENDING
)
381 Status
= NtWaitForSingleObject(hNamedPipe
,
384 if (!NT_SUCCESS(Status
))
386 SetLastErrorByStatus(Status
);
393 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
395 SetState
.ReadModeMessage
= TRUE
;
399 SetState
.ReadModeMessage
= FALSE
;
401 if ((*lpMode
) & PIPE_NOWAIT
)
403 SetState
.NonBlocking
= TRUE
;
407 SetState
.NonBlocking
= FALSE
;
409 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
413 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
414 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
415 SetState
.NonBlocking
= SetState
.NonBlocking
;
418 if (lpMaxCollectionCount
!= NULL
)
420 SetState
.InBufferSize
= *lpMaxCollectionCount
;
424 SetState
.InBufferSize
= GetState
.InBufferSize
;
427 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
429 if (lpCollectDataTimeout
!= NULL
)
431 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000;
435 SetState
.Timeout
= GetState
.Timeout
;
438 Status
= NtFsControlFile(hNamedPipe
,
443 FSCTL_PIPE_SET_STATE
,
445 sizeof(NPFS_SET_STATE
),
448 if (Status
== STATUS_PENDING
)
450 Status
= NtWaitForSingleObject(hNamedPipe
,
453 if (!NT_SUCCESS(Status
))
455 SetLastErrorByStatus(Status
);
468 CallNamedPipeA(LPCSTR lpNamedPipeName
,
472 DWORD nOutBufferSize
,
476 UNICODE_STRING PipeName
;
479 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
480 (LPSTR
)lpNamedPipeName
);
482 Result
= CallNamedPipeW(PipeName
.Buffer
,
490 RtlFreeUnicodeString(&PipeName
);
500 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
504 DWORD nOutBufferSize
,
508 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
515 hPipe
= CreateFileW(lpNamedPipeName
,
516 GENERIC_READ
| GENERIC_WRITE
,
517 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
520 FILE_ATTRIBUTE_NORMAL
,
522 if (hPipe
!= INVALID_HANDLE_VALUE
)
528 WaitNamedPipeW(lpNamedPipeName
,
534 dwPipeMode
= PIPE_READMODE_MESSAGE
;
535 bError
= SetNamedPipeHandleState(hPipe
,
545 bError
= TransactNamedPipe(hPipe
,
562 DisconnectNamedPipe(HANDLE hNamedPipe
)
564 IO_STATUS_BLOCK Iosb
;
567 Status
= NtFsControlFile(hNamedPipe
,
572 FSCTL_PIPE_DISCONNECT
,
577 if (Status
== STATUS_PENDING
)
579 Status
= NtWaitForSingleObject(hNamedPipe
,
582 if (!NT_SUCCESS(Status
))
584 SetLastErrorByStatus(Status
);
589 if (!NT_SUCCESS(Status
))
591 SetLastErrorByStatus(Status
);
602 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
604 LPDWORD lpCurInstances
,
605 LPDWORD lpMaxCollectionCount
,
606 LPDWORD lpCollectDataTimeout
,
608 DWORD nMaxUserNameSize
)
610 IO_STATUS_BLOCK StatusBlock
;
615 FILE_PIPE_INFORMATION PipeInfo
;
617 Status
= NtQueryInformationFile(hNamedPipe
,
620 sizeof(FILE_PIPE_INFORMATION
),
621 FilePipeInformation
);
622 if (!NT_SUCCESS(Status
))
624 SetLastErrorByStatus(Status
);
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
);
632 if(lpCurInstances
!= NULL
)
634 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
636 Status
= NtQueryInformationFile(hNamedPipe
,
639 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
640 FilePipeLocalInformation
);
641 if(!NT_SUCCESS(Status
))
643 SetLastErrorByStatus(Status
);
647 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
650 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
652 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
654 Status
= NtQueryInformationFile(hNamedPipe
,
657 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
658 FilePipeRemoteInformation
);
659 if(!NT_SUCCESS(Status
))
661 SetLastErrorByStatus(Status
);
665 if(lpMaxCollectionCount
!= NULL
)
667 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
670 if(lpCollectDataTimeout
!= NULL
)
673 *lpCollectDataTimeout
= 0;
677 if(lpUserName
!= NULL
)
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 */
692 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
694 LPDWORD lpCurInstances
,
695 LPDWORD lpMaxCollectionCount
,
696 LPDWORD lpCollectDataTimeout
,
698 DWORD nMaxUserNameSize
)
700 UNICODE_STRING UserNameW
;
701 ANSI_STRING UserNameA
;
704 if(lpUserName
!= NULL
)
706 UserNameW
.Length
= 0;
707 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
708 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
710 UserNameA
.Buffer
= lpUserName
;
711 UserNameA
.Length
= 0;
712 UserNameA
.MaximumLength
= nMaxUserNameSize
;
715 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
718 lpMaxCollectionCount
,
719 lpCollectDataTimeout
,
723 if(Ret
&& lpUserName
!= NULL
)
725 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
726 if(!NT_SUCCESS(Status
))
728 SetLastErrorByStatus(Status
);
733 if(UserNameW
.Buffer
!= NULL
)
735 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
746 GetNamedPipeInfo(HANDLE hNamedPipe
,
748 LPDWORD lpOutBufferSize
,
749 LPDWORD lpInBufferSize
,
750 LPDWORD lpMaxInstances
)
752 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
753 IO_STATUS_BLOCK StatusBlock
;
756 Status
= NtQueryInformationFile(hNamedPipe
,
758 &PipeLocalInformation
,
759 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
760 FilePipeLocalInformation
);
761 if (!NT_SUCCESS(Status
))
763 SetLastErrorByStatus(Status
);
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
;
773 if (lpOutBufferSize
!= NULL
)
774 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
776 if (lpInBufferSize
!= NULL
)
777 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
779 if (lpMaxInstances
!= NULL
)
781 if (PipeLocalInformation
.MaximumInstances
>= 255)
782 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
784 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
795 PeekNamedPipe(HANDLE hNamedPipe
,
799 LPDWORD lpTotalBytesAvail
,
800 LPDWORD lpBytesLeftThisMessage
)
802 PFILE_PIPE_PEEK_BUFFER Buffer
;
803 IO_STATUS_BLOCK Iosb
;
807 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
808 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
812 Status
= NtFsControlFile(hNamedPipe
,
822 if (Status
== STATUS_PENDING
)
824 Status
= NtWaitForSingleObject(hNamedPipe
,
827 if (NT_SUCCESS(Status
))
828 Status
= Iosb
.Status
;
831 if (Status
== STATUS_BUFFER_OVERFLOW
)
833 Status
= STATUS_SUCCESS
;
836 if (!NT_SUCCESS(Status
))
838 RtlFreeHeap(RtlGetProcessHeap(),
841 SetLastErrorByStatus(Status
);
845 if (lpTotalBytesAvail
!= NULL
)
847 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
850 if (lpBytesRead
!= NULL
)
852 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
855 if (lpBytesLeftThisMessage
!= NULL
)
857 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
858 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
861 if (lpBuffer
!= NULL
)
863 memcpy(lpBuffer
, Buffer
->Data
,
864 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
867 RtlFreeHeap(RtlGetProcessHeap(),
879 TransactNamedPipe(HANDLE hNamedPipe
,
883 DWORD nOutBufferSize
,
885 LPOVERLAPPED lpOverlapped
)
887 IO_STATUS_BLOCK IoStatusBlock
;
890 if (lpOverlapped
== NULL
)
892 Status
= NtFsControlFile(hNamedPipe
,
897 FSCTL_PIPE_TRANSCEIVE
,
902 if (Status
== STATUS_PENDING
)
904 NtWaitForSingleObject(hNamedPipe
,
907 Status
= IoStatusBlock
.Status
;
909 if (NT_SUCCESS(Status
))
911 *lpBytesRead
= IoStatusBlock
.Information
;
916 lpOverlapped
->Internal
= STATUS_PENDING
;
918 Status
= NtFsControlFile(hNamedPipe
,
919 lpOverlapped
->hEvent
,
922 (PIO_STATUS_BLOCK
)lpOverlapped
,
923 FSCTL_PIPE_TRANSCEIVE
,
930 if (!NT_SUCCESS(Status
))
932 SetLastErrorByStatus(Status
);