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
* -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 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
* -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
);
375 SetNamedPipeHandleState(HANDLE hNamedPipe
,
377 LPDWORD lpMaxCollectionCount
,
378 LPDWORD lpCollectDataTimeout
)
380 NPFS_GET_STATE GetState
;
381 NPFS_SET_STATE SetState
;
382 IO_STATUS_BLOCK Iosb
;
385 Status
= NtFsControlFile(hNamedPipe
,
390 FSCTL_PIPE_GET_STATE
,
394 sizeof(NPFS_GET_STATE
));
395 if (Status
== STATUS_PENDING
)
397 Status
= NtWaitForSingleObject(hNamedPipe
,
400 if (!NT_SUCCESS(Status
))
402 SetLastErrorByStatus(Status
);
409 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
411 SetState
.ReadModeMessage
= TRUE
;
415 SetState
.ReadModeMessage
= FALSE
;
417 if ((*lpMode
) & PIPE_NOWAIT
)
419 SetState
.NonBlocking
= TRUE
;
423 SetState
.NonBlocking
= FALSE
;
425 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
429 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
430 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
431 SetState
.NonBlocking
= SetState
.NonBlocking
;
434 if (lpMaxCollectionCount
!= NULL
)
436 SetState
.InBufferSize
= *lpMaxCollectionCount
;
440 SetState
.InBufferSize
= GetState
.InBufferSize
;
443 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
445 if (lpCollectDataTimeout
!= NULL
)
447 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000LL;
451 SetState
.Timeout
= GetState
.Timeout
;
454 Status
= NtFsControlFile(hNamedPipe
,
459 FSCTL_PIPE_SET_STATE
,
461 sizeof(NPFS_SET_STATE
),
464 if (Status
== STATUS_PENDING
)
466 Status
= NtWaitForSingleObject(hNamedPipe
,
469 if (!NT_SUCCESS(Status
))
471 SetLastErrorByStatus(Status
);
484 CallNamedPipeA(LPCSTR lpNamedPipeName
,
488 DWORD nOutBufferSize
,
492 UNICODE_STRING PipeName
;
495 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
496 (LPSTR
)lpNamedPipeName
);
498 Result
= CallNamedPipeW(PipeName
.Buffer
,
506 RtlFreeUnicodeString(&PipeName
);
516 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
520 DWORD nOutBufferSize
,
524 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
531 hPipe
= CreateFileW(lpNamedPipeName
,
532 GENERIC_READ
| GENERIC_WRITE
,
533 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
536 FILE_ATTRIBUTE_NORMAL
,
538 if (hPipe
!= INVALID_HANDLE_VALUE
)
544 WaitNamedPipeW(lpNamedPipeName
,
550 dwPipeMode
= PIPE_READMODE_MESSAGE
;
551 bError
= SetNamedPipeHandleState(hPipe
,
561 bError
= TransactNamedPipe(hPipe
,
578 DisconnectNamedPipe(HANDLE hNamedPipe
)
580 IO_STATUS_BLOCK Iosb
;
583 Status
= NtFsControlFile(hNamedPipe
,
588 FSCTL_PIPE_DISCONNECT
,
593 if (Status
== STATUS_PENDING
)
595 Status
= NtWaitForSingleObject(hNamedPipe
,
598 if (!NT_SUCCESS(Status
))
600 SetLastErrorByStatus(Status
);
605 if (!NT_SUCCESS(Status
))
607 SetLastErrorByStatus(Status
);
618 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
620 LPDWORD lpCurInstances
,
621 LPDWORD lpMaxCollectionCount
,
622 LPDWORD lpCollectDataTimeout
,
624 DWORD nMaxUserNameSize
)
626 IO_STATUS_BLOCK StatusBlock
;
631 FILE_PIPE_INFORMATION PipeInfo
;
633 Status
= NtQueryInformationFile(hNamedPipe
,
636 sizeof(FILE_PIPE_INFORMATION
),
637 FilePipeInformation
);
638 if (!NT_SUCCESS(Status
))
640 SetLastErrorByStatus(Status
);
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
);
648 if(lpCurInstances
!= NULL
)
650 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
652 Status
= NtQueryInformationFile(hNamedPipe
,
655 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
656 FilePipeLocalInformation
);
657 if(!NT_SUCCESS(Status
))
659 SetLastErrorByStatus(Status
);
663 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
666 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
668 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
670 Status
= NtQueryInformationFile(hNamedPipe
,
673 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
674 FilePipeRemoteInformation
);
675 if(!NT_SUCCESS(Status
))
677 SetLastErrorByStatus(Status
);
681 if(lpMaxCollectionCount
!= NULL
)
683 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
686 if(lpCollectDataTimeout
!= NULL
)
689 *lpCollectDataTimeout
= 0;
693 if(lpUserName
!= NULL
)
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 */
708 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
710 LPDWORD lpCurInstances
,
711 LPDWORD lpMaxCollectionCount
,
712 LPDWORD lpCollectDataTimeout
,
714 DWORD nMaxUserNameSize
)
716 UNICODE_STRING UserNameW
;
717 ANSI_STRING UserNameA
;
720 if(lpUserName
!= NULL
)
722 UserNameW
.Length
= 0;
723 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
724 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
726 UserNameA
.Buffer
= lpUserName
;
727 UserNameA
.Length
= 0;
728 UserNameA
.MaximumLength
= nMaxUserNameSize
;
731 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
734 lpMaxCollectionCount
,
735 lpCollectDataTimeout
,
739 if(Ret
&& lpUserName
!= NULL
)
741 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
742 if(!NT_SUCCESS(Status
))
744 SetLastErrorByStatus(Status
);
749 if(UserNameW
.Buffer
!= NULL
)
751 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
762 GetNamedPipeInfo(HANDLE hNamedPipe
,
764 LPDWORD lpOutBufferSize
,
765 LPDWORD lpInBufferSize
,
766 LPDWORD lpMaxInstances
)
768 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
769 IO_STATUS_BLOCK StatusBlock
;
772 Status
= NtQueryInformationFile(hNamedPipe
,
774 &PipeLocalInformation
,
775 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
776 FilePipeLocalInformation
);
777 if (!NT_SUCCESS(Status
))
779 SetLastErrorByStatus(Status
);
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
;
789 if (lpOutBufferSize
!= NULL
)
790 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
792 if (lpInBufferSize
!= NULL
)
793 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
795 if (lpMaxInstances
!= NULL
)
797 if (PipeLocalInformation
.MaximumInstances
>= 255)
798 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
800 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
811 PeekNamedPipe(HANDLE hNamedPipe
,
815 LPDWORD lpTotalBytesAvail
,
816 LPDWORD lpBytesLeftThisMessage
)
818 PFILE_PIPE_PEEK_BUFFER Buffer
;
819 IO_STATUS_BLOCK Iosb
;
823 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
824 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
828 Status
= NtFsControlFile(hNamedPipe
,
838 if (Status
== STATUS_PENDING
)
840 Status
= NtWaitForSingleObject(hNamedPipe
,
843 if (NT_SUCCESS(Status
))
844 Status
= Iosb
.Status
;
847 if (Status
== STATUS_BUFFER_OVERFLOW
)
849 Status
= STATUS_SUCCESS
;
852 if (!NT_SUCCESS(Status
))
854 RtlFreeHeap(RtlGetProcessHeap(),
857 SetLastErrorByStatus(Status
);
861 if (lpTotalBytesAvail
!= NULL
)
863 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
866 if (lpBytesRead
!= NULL
)
868 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
871 if (lpBytesLeftThisMessage
!= NULL
)
873 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
874 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
877 if (lpBuffer
!= NULL
)
879 memcpy(lpBuffer
, Buffer
->Data
,
880 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
883 RtlFreeHeap(RtlGetProcessHeap(),
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
)
905 if (lpBytesRead
!= NULL
)
910 if (lpOverlapped
!= NULL
)
914 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
915 lpOverlapped
->Internal
= STATUS_PENDING
;
917 Status
= NtFsControlFile(hNamedPipe
,
918 lpOverlapped
->hEvent
,
921 (PIO_STATUS_BLOCK
)lpOverlapped
,
922 FSCTL_PIPE_TRANSCEIVE
,
928 /* return FALSE in case of failure and pending operations! */
929 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
931 SetLastErrorByStatus(Status
);
935 if (lpBytesRead
!= NULL
)
937 *lpBytesRead
= lpOverlapped
->InternalHigh
;
942 IO_STATUS_BLOCK Iosb
;
944 Status
= NtFsControlFile(hNamedPipe
,
949 FSCTL_PIPE_TRANSCEIVE
,
955 /* wait in case operation is pending */
956 if (Status
== STATUS_PENDING
)
958 Status
= NtWaitForSingleObject(hNamedPipe
,
961 if (NT_SUCCESS(Status
))
963 Status
= Iosb
.Status
;
967 if (NT_SUCCESS(Status
))
969 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
970 check that case either and crashes (only after the operation
972 *lpBytesRead
= Iosb
.Information
;
976 SetLastErrorByStatus(Status
);