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 WriteModeMessage
;
76 ULONG ReadModeMessage
;
79 ULONG ShareAccess
, Attributes
;
80 LARGE_INTEGER DefaultTimeOut
;
81 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
83 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
85 SetLastError(ERROR_INVALID_PARAMETER
);
86 return INVALID_HANDLE_VALUE
;
89 Result
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpName
,
95 SetLastError(ERROR_PATH_NOT_FOUND
);
96 return(INVALID_HANDLE_VALUE
);
99 DPRINT("Pipe name: %wZ\n", &NamedPipeName
);
100 DPRINT("Pipe name: %S\n", NamedPipeName
.Buffer
);
102 Attributes
= OBJ_CASE_INSENSITIVE
;
103 if(lpSecurityAttributes
)
105 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
106 if(lpSecurityAttributes
->bInheritHandle
)
107 Attributes
|= OBJ_INHERIT
;
110 InitializeObjectAttributes(&ObjectAttributes
,
116 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
| WRITE_OWNER
| ACCESS_SYSTEM_SECURITY
));
120 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
121 CreateOptions
= CreateOptions
| FILE_WRITE_THROUGH
;
123 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
124 CreateOptions
= CreateOptions
| FILE_SYNCHRONOUS_IO_NONALERT
;
126 switch (dwOpenMode
& PIPE_ACCESS_DUPLEX
)
128 case PIPE_ACCESS_INBOUND
:
129 CreateOptions
|= FILE_PIPE_INBOUND
;
130 ShareAccess
|= FILE_SHARE_WRITE
;
131 DesiredAccess
|= GENERIC_READ
;
134 case PIPE_ACCESS_OUTBOUND
:
135 CreateOptions
|= FILE_PIPE_OUTBOUND
;
136 ShareAccess
|= FILE_SHARE_READ
;
137 DesiredAccess
|= GENERIC_WRITE
;
140 case PIPE_ACCESS_DUPLEX
:
141 CreateOptions
|= FILE_PIPE_FULL_DUPLEX
;
142 ShareAccess
|= (FILE_SHARE_READ
| FILE_SHARE_WRITE
);
143 DesiredAccess
|= (GENERIC_READ
| GENERIC_WRITE
);
147 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
148 WriteModeMessage
= FILE_PIPE_MESSAGE_MODE
;
150 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
152 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
153 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
155 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
157 if (dwPipeMode
& PIPE_NOWAIT
)
158 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
160 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
162 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000LL;
164 Status
= NtCreateNamedPipeFile(&PipeHandle
,
179 RtlFreeUnicodeString(&NamedPipeName
);
181 if (!NT_SUCCESS(Status
))
183 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status
);
184 SetLastErrorByStatus (Status
);
185 return INVALID_HANDLE_VALUE
;
196 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
200 UNICODE_STRING NameU
;
203 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
204 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
206 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
208 RtlFreeUnicodeString(&NameU
);
218 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
221 UNICODE_STRING NamedPipeName
;
224 OBJECT_ATTRIBUTES ObjectAttributes
;
225 FILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
227 IO_STATUS_BLOCK Iosb
;
229 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
238 InitializeObjectAttributes(&ObjectAttributes
,
240 OBJ_CASE_INSENSITIVE
,
243 Status
= NtOpenFile(&FileHandle
,
244 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
247 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
248 FILE_SYNCHRONOUS_IO_NONALERT
);
249 if (!NT_SUCCESS(Status
))
251 SetLastErrorByStatus (Status
);
255 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000LL;
257 Status
= NtFsControlFile(FileHandle
,
268 if (!NT_SUCCESS(Status
))
270 SetLastErrorByStatus (Status
);
282 ConnectNamedPipe(IN HANDLE hNamedPipe
,
283 IN LPOVERLAPPED lpOverlapped
)
287 if (lpOverlapped
!= NULL
)
291 lpOverlapped
->Internal
= STATUS_PENDING
;
292 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
294 Status
= NtFsControlFile(hNamedPipe
,
295 lpOverlapped
->hEvent
,
298 (PIO_STATUS_BLOCK
)lpOverlapped
,
305 /* return FALSE in case of failure and pending operations! */
306 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
308 SetLastErrorByStatus(Status
);
314 IO_STATUS_BLOCK Iosb
;
316 Status
= NtFsControlFile(hNamedPipe
,
327 /* wait in case operation is pending */
328 if (Status
== STATUS_PENDING
)
330 Status
= NtWaitForSingleObject(hNamedPipe
,
333 if (NT_SUCCESS(Status
))
335 Status
= Iosb
.Status
;
339 if (!NT_SUCCESS(Status
))
341 SetLastErrorByStatus(Status
);
355 SetNamedPipeHandleState(HANDLE hNamedPipe
,
357 LPDWORD lpMaxCollectionCount
,
358 LPDWORD lpCollectDataTimeout
)
360 IO_STATUS_BLOCK Iosb
;
363 /* Check if the Mode is being changed */
366 FILE_PIPE_INFORMATION Settings
;
368 /* Set the Completion Mode */
369 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
370 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
372 /* Set the Read Mode */
373 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
374 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
376 /* Send the changes to the Driver */
377 Status
= NtSetInformationFile(hNamedPipe
,
380 sizeof(FILE_PIPE_INFORMATION
),
381 FilePipeInformation
);
382 if (!NT_SUCCESS(Status
))
384 SetLastErrorByStatus(Status
);
389 /* Check if the Collection count or Timeout are being changed */
390 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
392 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
394 /* Setting one without the other would delete it, so we read old one */
395 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
397 Status
= NtQueryInformationFile(hNamedPipe
,
400 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
401 FilePipeRemoteInformation
);
403 if (!NT_SUCCESS(Status
))
405 SetLastErrorByStatus(Status
);
410 /* Now set the new settings */
411 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
412 *lpMaxCollectionCount
:
413 RemoteSettings
.MaximumCollectionCount
;
414 if (lpCollectDataTimeout
)
416 /* Convert it to Quad */
417 RemoteSettings
.CollectDataTime
.QuadPart
= -(LONGLONG
)
419 *lpCollectDataTimeout
);
422 /* Tell the driver to change them */
423 Status
= NtSetInformationFile(hNamedPipe
,
426 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
427 FilePipeRemoteInformation
);
429 if (!NT_SUCCESS(Status
))
431 SetLastErrorByStatus(Status
);
444 CallNamedPipeA(LPCSTR lpNamedPipeName
,
448 DWORD nOutBufferSize
,
452 UNICODE_STRING PipeName
;
455 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
456 (LPSTR
)lpNamedPipeName
);
458 Result
= CallNamedPipeW(PipeName
.Buffer
,
466 RtlFreeUnicodeString(&PipeName
);
476 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
480 DWORD nOutBufferSize
,
484 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
491 hPipe
= CreateFileW(lpNamedPipeName
,
492 GENERIC_READ
| GENERIC_WRITE
,
493 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
496 FILE_ATTRIBUTE_NORMAL
,
498 if (hPipe
!= INVALID_HANDLE_VALUE
)
504 WaitNamedPipeW(lpNamedPipeName
,
510 dwPipeMode
= PIPE_READMODE_MESSAGE
;
511 bError
= SetNamedPipeHandleState(hPipe
,
521 bError
= TransactNamedPipe(hPipe
,
538 DisconnectNamedPipe(HANDLE hNamedPipe
)
540 IO_STATUS_BLOCK Iosb
;
543 Status
= NtFsControlFile(hNamedPipe
,
548 FSCTL_PIPE_DISCONNECT
,
553 if (Status
== STATUS_PENDING
)
555 Status
= NtWaitForSingleObject(hNamedPipe
,
558 if (!NT_SUCCESS(Status
))
560 SetLastErrorByStatus(Status
);
565 if (!NT_SUCCESS(Status
))
567 SetLastErrorByStatus(Status
);
578 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
580 LPDWORD lpCurInstances
,
581 LPDWORD lpMaxCollectionCount
,
582 LPDWORD lpCollectDataTimeout
,
584 DWORD nMaxUserNameSize
)
586 IO_STATUS_BLOCK StatusBlock
;
591 FILE_PIPE_INFORMATION PipeInfo
;
593 Status
= NtQueryInformationFile(hNamedPipe
,
596 sizeof(FILE_PIPE_INFORMATION
),
597 FilePipeInformation
);
598 if (!NT_SUCCESS(Status
))
600 SetLastErrorByStatus(Status
);
604 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
605 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
608 if(lpCurInstances
!= NULL
)
610 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
612 Status
= NtQueryInformationFile(hNamedPipe
,
615 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
616 FilePipeLocalInformation
);
617 if(!NT_SUCCESS(Status
))
619 SetLastErrorByStatus(Status
);
623 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
626 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
628 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
630 Status
= NtQueryInformationFile(hNamedPipe
,
633 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
634 FilePipeRemoteInformation
);
635 if(!NT_SUCCESS(Status
))
637 SetLastErrorByStatus(Status
);
641 if(lpMaxCollectionCount
!= NULL
)
643 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
646 if(lpCollectDataTimeout
!= NULL
)
649 *lpCollectDataTimeout
= 0;
653 if(lpUserName
!= NULL
)
655 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
656 retreive the user name with GetUserName(), revert the impersonation
657 and finally restore the thread token */
668 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
670 LPDWORD lpCurInstances
,
671 LPDWORD lpMaxCollectionCount
,
672 LPDWORD lpCollectDataTimeout
,
674 DWORD nMaxUserNameSize
)
676 UNICODE_STRING UserNameW
;
677 ANSI_STRING UserNameA
;
680 if(lpUserName
!= NULL
)
682 UserNameW
.Length
= 0;
683 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
684 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
686 UserNameA
.Buffer
= lpUserName
;
687 UserNameA
.Length
= 0;
688 UserNameA
.MaximumLength
= nMaxUserNameSize
;
691 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
694 lpMaxCollectionCount
,
695 lpCollectDataTimeout
,
699 if(Ret
&& lpUserName
!= NULL
)
701 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
702 if(!NT_SUCCESS(Status
))
704 SetLastErrorByStatus(Status
);
709 if(UserNameW
.Buffer
!= NULL
)
711 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
722 GetNamedPipeInfo(HANDLE hNamedPipe
,
724 LPDWORD lpOutBufferSize
,
725 LPDWORD lpInBufferSize
,
726 LPDWORD lpMaxInstances
)
728 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
729 IO_STATUS_BLOCK StatusBlock
;
732 Status
= NtQueryInformationFile(hNamedPipe
,
734 &PipeLocalInformation
,
735 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
736 FilePipeLocalInformation
);
737 if (!NT_SUCCESS(Status
))
739 SetLastErrorByStatus(Status
);
745 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
746 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
749 if (lpOutBufferSize
!= NULL
)
750 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
752 if (lpInBufferSize
!= NULL
)
753 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
755 if (lpMaxInstances
!= NULL
)
757 if (PipeLocalInformation
.MaximumInstances
>= 255)
758 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
760 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
771 PeekNamedPipe(HANDLE hNamedPipe
,
775 LPDWORD lpTotalBytesAvail
,
776 LPDWORD lpBytesLeftThisMessage
)
778 PFILE_PIPE_PEEK_BUFFER Buffer
;
779 IO_STATUS_BLOCK Iosb
;
783 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
784 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
788 Status
= NtFsControlFile(hNamedPipe
,
798 if (Status
== STATUS_PENDING
)
800 Status
= NtWaitForSingleObject(hNamedPipe
,
803 if (NT_SUCCESS(Status
))
804 Status
= Iosb
.Status
;
807 if (Status
== STATUS_BUFFER_OVERFLOW
)
809 Status
= STATUS_SUCCESS
;
812 if (!NT_SUCCESS(Status
))
814 RtlFreeHeap(RtlGetProcessHeap(),
817 SetLastErrorByStatus(Status
);
821 if (lpTotalBytesAvail
!= NULL
)
823 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
826 if (lpBytesRead
!= NULL
)
828 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
831 if (lpBytesLeftThisMessage
!= NULL
)
833 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
834 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
837 if (lpBuffer
!= NULL
)
839 memcpy(lpBuffer
, Buffer
->Data
,
840 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
843 RtlFreeHeap(RtlGetProcessHeap(),
855 TransactNamedPipe(IN HANDLE hNamedPipe
,
856 IN LPVOID lpInBuffer
,
857 IN DWORD nInBufferSize
,
858 OUT LPVOID lpOutBuffer
,
859 IN DWORD nOutBufferSize
,
860 OUT LPDWORD lpBytesRead OPTIONAL
,
861 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
865 if (lpBytesRead
!= NULL
)
870 if (lpOverlapped
!= NULL
)
874 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
875 lpOverlapped
->Internal
= STATUS_PENDING
;
877 Status
= NtFsControlFile(hNamedPipe
,
878 lpOverlapped
->hEvent
,
881 (PIO_STATUS_BLOCK
)lpOverlapped
,
882 FSCTL_PIPE_TRANSCEIVE
,
888 /* return FALSE in case of failure and pending operations! */
889 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
891 SetLastErrorByStatus(Status
);
895 if (lpBytesRead
!= NULL
)
897 *lpBytesRead
= lpOverlapped
->InternalHigh
;
902 IO_STATUS_BLOCK Iosb
;
904 Status
= NtFsControlFile(hNamedPipe
,
909 FSCTL_PIPE_TRANSCEIVE
,
915 /* wait in case operation is pending */
916 if (Status
== STATUS_PENDING
)
918 Status
= NtWaitForSingleObject(hNamedPipe
,
921 if (NT_SUCCESS(Status
))
923 Status
= Iosb
.Status
;
927 if (NT_SUCCESS(Status
))
929 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
930 check that case either and crashes (only after the operation
932 *lpBytesRead
= Iosb
.Information
;
936 SetLastErrorByStatus(Status
);