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
= 0xFFFFFFFF;
183 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000LL;
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 FILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
248 IO_STATUS_BLOCK Iosb
;
250 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
259 InitializeObjectAttributes(&ObjectAttributes
,
261 OBJ_CASE_INSENSITIVE
,
264 Status
= NtOpenFile(&FileHandle
,
265 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
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
* -10000LL;
278 Status
= NtFsControlFile(FileHandle
,
289 if (!NT_SUCCESS(Status
))
291 SetLastErrorByStatus (Status
);
303 ConnectNamedPipe(IN HANDLE hNamedPipe
,
304 IN LPOVERLAPPED lpOverlapped
)
308 if (lpOverlapped
!= NULL
)
312 lpOverlapped
->Internal
= STATUS_PENDING
;
313 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
315 Status
= NtFsControlFile(hNamedPipe
,
316 lpOverlapped
->hEvent
,
319 (PIO_STATUS_BLOCK
)lpOverlapped
,
326 /* return FALSE in case of failure and pending operations! */
327 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
329 SetLastErrorByStatus(Status
);
335 IO_STATUS_BLOCK Iosb
;
337 Status
= NtFsControlFile(hNamedPipe
,
348 /* wait in case operation is pending */
349 if (Status
== STATUS_PENDING
)
351 Status
= NtWaitForSingleObject(hNamedPipe
,
354 if (NT_SUCCESS(Status
))
356 Status
= Iosb
.Status
;
360 if (!NT_SUCCESS(Status
))
362 SetLastErrorByStatus(Status
);
376 SetNamedPipeHandleState(HANDLE hNamedPipe
,
378 LPDWORD lpMaxCollectionCount
,
379 LPDWORD lpCollectDataTimeout
)
381 IO_STATUS_BLOCK Iosb
;
384 /* Check if the Mode is being changed */
387 FILE_PIPE_INFORMATION Settings
;
389 /* Set the Completion Mode */
390 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
391 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
393 /* Set the Read Mode */
394 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
395 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
397 /* Send the changes to the Driver */
398 Status
= NtSetInformationFile(hNamedPipe
,
401 sizeof(FILE_PIPE_INFORMATION
),
402 FilePipeInformation
);
403 if (!NT_SUCCESS(Status
))
405 SetLastErrorByStatus(Status
);
410 /* Check if the Collection count or Timeout are being changed */
411 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
413 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
415 /* Setting one without the other would delete it, so we read old one */
416 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
418 Status
= NtQueryInformationFile(hNamedPipe
,
421 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
422 FilePipeRemoteInformation
);
424 if (!NT_SUCCESS(Status
))
426 SetLastErrorByStatus(Status
);
431 /* Now set the new settings */
432 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
433 *lpMaxCollectionCount
:
434 RemoteSettings
.MaximumCollectionCount
;
435 if (lpCollectDataTimeout
)
437 /* Convert it to Quad */
438 RemoteSettings
.CollectDataTime
.QuadPart
= -(LONGLONG
)
440 *lpCollectDataTimeout
);
443 /* Tell the driver to change them */
444 Status
= NtSetInformationFile(hNamedPipe
,
447 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
448 FilePipeRemoteInformation
);
450 if (!NT_SUCCESS(Status
))
452 SetLastErrorByStatus(Status
);
465 CallNamedPipeA(LPCSTR lpNamedPipeName
,
469 DWORD nOutBufferSize
,
473 UNICODE_STRING PipeName
;
476 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
477 (LPSTR
)lpNamedPipeName
);
479 Result
= CallNamedPipeW(PipeName
.Buffer
,
487 RtlFreeUnicodeString(&PipeName
);
497 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
501 DWORD nOutBufferSize
,
505 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
512 hPipe
= CreateFileW(lpNamedPipeName
,
513 GENERIC_READ
| GENERIC_WRITE
,
514 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
517 FILE_ATTRIBUTE_NORMAL
,
519 if (hPipe
!= INVALID_HANDLE_VALUE
)
525 WaitNamedPipeW(lpNamedPipeName
,
531 dwPipeMode
= PIPE_READMODE_MESSAGE
;
532 bError
= SetNamedPipeHandleState(hPipe
,
542 bError
= TransactNamedPipe(hPipe
,
559 DisconnectNamedPipe(HANDLE hNamedPipe
)
561 IO_STATUS_BLOCK Iosb
;
564 Status
= NtFsControlFile(hNamedPipe
,
569 FSCTL_PIPE_DISCONNECT
,
574 if (Status
== STATUS_PENDING
)
576 Status
= NtWaitForSingleObject(hNamedPipe
,
579 if (!NT_SUCCESS(Status
))
581 SetLastErrorByStatus(Status
);
586 if (!NT_SUCCESS(Status
))
588 SetLastErrorByStatus(Status
);
599 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
601 LPDWORD lpCurInstances
,
602 LPDWORD lpMaxCollectionCount
,
603 LPDWORD lpCollectDataTimeout
,
605 DWORD nMaxUserNameSize
)
607 IO_STATUS_BLOCK StatusBlock
;
612 FILE_PIPE_INFORMATION PipeInfo
;
614 Status
= NtQueryInformationFile(hNamedPipe
,
617 sizeof(FILE_PIPE_INFORMATION
),
618 FilePipeInformation
);
619 if (!NT_SUCCESS(Status
))
621 SetLastErrorByStatus(Status
);
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
);
629 if(lpCurInstances
!= NULL
)
631 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
633 Status
= NtQueryInformationFile(hNamedPipe
,
636 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
637 FilePipeLocalInformation
);
638 if(!NT_SUCCESS(Status
))
640 SetLastErrorByStatus(Status
);
644 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
647 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
649 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
651 Status
= NtQueryInformationFile(hNamedPipe
,
654 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
655 FilePipeRemoteInformation
);
656 if(!NT_SUCCESS(Status
))
658 SetLastErrorByStatus(Status
);
662 if(lpMaxCollectionCount
!= NULL
)
664 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
667 if(lpCollectDataTimeout
!= NULL
)
670 *lpCollectDataTimeout
= 0;
674 if(lpUserName
!= NULL
)
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 */
689 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
691 LPDWORD lpCurInstances
,
692 LPDWORD lpMaxCollectionCount
,
693 LPDWORD lpCollectDataTimeout
,
695 DWORD nMaxUserNameSize
)
697 UNICODE_STRING UserNameW
;
698 ANSI_STRING UserNameA
;
701 if(lpUserName
!= NULL
)
703 UserNameW
.Length
= 0;
704 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
705 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
707 UserNameA
.Buffer
= lpUserName
;
708 UserNameA
.Length
= 0;
709 UserNameA
.MaximumLength
= nMaxUserNameSize
;
712 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
715 lpMaxCollectionCount
,
716 lpCollectDataTimeout
,
720 if(Ret
&& lpUserName
!= NULL
)
722 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
723 if(!NT_SUCCESS(Status
))
725 SetLastErrorByStatus(Status
);
730 if(UserNameW
.Buffer
!= NULL
)
732 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
743 GetNamedPipeInfo(HANDLE hNamedPipe
,
745 LPDWORD lpOutBufferSize
,
746 LPDWORD lpInBufferSize
,
747 LPDWORD lpMaxInstances
)
749 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
750 IO_STATUS_BLOCK StatusBlock
;
753 Status
= NtQueryInformationFile(hNamedPipe
,
755 &PipeLocalInformation
,
756 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
757 FilePipeLocalInformation
);
758 if (!NT_SUCCESS(Status
))
760 SetLastErrorByStatus(Status
);
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
;
770 if (lpOutBufferSize
!= NULL
)
771 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
773 if (lpInBufferSize
!= NULL
)
774 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
776 if (lpMaxInstances
!= NULL
)
778 if (PipeLocalInformation
.MaximumInstances
>= 255)
779 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
781 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
792 PeekNamedPipe(HANDLE hNamedPipe
,
796 LPDWORD lpTotalBytesAvail
,
797 LPDWORD lpBytesLeftThisMessage
)
799 PFILE_PIPE_PEEK_BUFFER Buffer
;
800 IO_STATUS_BLOCK Iosb
;
804 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
805 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
809 Status
= NtFsControlFile(hNamedPipe
,
819 if (Status
== STATUS_PENDING
)
821 Status
= NtWaitForSingleObject(hNamedPipe
,
824 if (NT_SUCCESS(Status
))
825 Status
= Iosb
.Status
;
828 if (Status
== STATUS_BUFFER_OVERFLOW
)
830 Status
= STATUS_SUCCESS
;
833 if (!NT_SUCCESS(Status
))
835 RtlFreeHeap(RtlGetProcessHeap(),
838 SetLastErrorByStatus(Status
);
842 if (lpTotalBytesAvail
!= NULL
)
844 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
847 if (lpBytesRead
!= NULL
)
849 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
852 if (lpBytesLeftThisMessage
!= NULL
)
854 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
855 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
858 if (lpBuffer
!= NULL
)
860 memcpy(lpBuffer
, Buffer
->Data
,
861 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
864 RtlFreeHeap(RtlGetProcessHeap(),
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
)
886 if (lpBytesRead
!= NULL
)
891 if (lpOverlapped
!= NULL
)
895 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
896 lpOverlapped
->Internal
= STATUS_PENDING
;
898 Status
= NtFsControlFile(hNamedPipe
,
899 lpOverlapped
->hEvent
,
902 (PIO_STATUS_BLOCK
)lpOverlapped
,
903 FSCTL_PIPE_TRANSCEIVE
,
909 /* return FALSE in case of failure and pending operations! */
910 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
912 SetLastErrorByStatus(Status
);
916 if (lpBytesRead
!= NULL
)
918 *lpBytesRead
= lpOverlapped
->InternalHigh
;
923 IO_STATUS_BLOCK Iosb
;
925 Status
= NtFsControlFile(hNamedPipe
,
930 FSCTL_PIPE_TRANSCEIVE
,
936 /* wait in case operation is pending */
937 if (Status
== STATUS_PENDING
)
939 Status
= NtWaitForSingleObject(hNamedPipe
,
942 if (NT_SUCCESS(Status
))
944 Status
= Iosb
.Status
;
948 if (NT_SUCCESS(Status
))
950 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
951 check that case either and crashes (only after the operation
953 *lpBytesRead
= Iosb
.Information
;
957 SetLastErrorByStatus(Status
);