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 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
128 ShareAccess
|= FILE_SHARE_READ
;
129 DesiredAccess
|= GENERIC_WRITE
;
131 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
133 ShareAccess
|= FILE_SHARE_WRITE
;
134 DesiredAccess
|= GENERIC_READ
;
136 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
137 WriteModeMessage
= FILE_PIPE_MESSAGE_MODE
;
139 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
141 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
142 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
144 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
146 if (dwPipeMode
& PIPE_NOWAIT
)
147 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
149 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
151 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000LL;
153 Status
= NtCreateNamedPipeFile(&PipeHandle
,
168 RtlFreeUnicodeString(&NamedPipeName
);
170 if (!NT_SUCCESS(Status
))
172 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status
);
173 SetLastErrorByStatus (Status
);
174 return INVALID_HANDLE_VALUE
;
185 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
189 UNICODE_STRING NameU
;
192 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
193 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
195 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
197 RtlFreeUnicodeString(&NameU
);
207 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
210 UNICODE_STRING NamedPipeName
;
213 OBJECT_ATTRIBUTES ObjectAttributes
;
214 FILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
216 IO_STATUS_BLOCK Iosb
;
218 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
227 InitializeObjectAttributes(&ObjectAttributes
,
229 OBJ_CASE_INSENSITIVE
,
232 Status
= NtOpenFile(&FileHandle
,
233 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
236 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
237 FILE_SYNCHRONOUS_IO_NONALERT
);
238 if (!NT_SUCCESS(Status
))
240 SetLastErrorByStatus (Status
);
244 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000LL;
246 Status
= NtFsControlFile(FileHandle
,
257 if (!NT_SUCCESS(Status
))
259 SetLastErrorByStatus (Status
);
271 ConnectNamedPipe(IN HANDLE hNamedPipe
,
272 IN LPOVERLAPPED lpOverlapped
)
276 if (lpOverlapped
!= NULL
)
280 lpOverlapped
->Internal
= STATUS_PENDING
;
281 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
283 Status
= NtFsControlFile(hNamedPipe
,
284 lpOverlapped
->hEvent
,
287 (PIO_STATUS_BLOCK
)lpOverlapped
,
294 /* return FALSE in case of failure and pending operations! */
295 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
297 SetLastErrorByStatus(Status
);
303 IO_STATUS_BLOCK Iosb
;
305 Status
= NtFsControlFile(hNamedPipe
,
316 /* wait in case operation is pending */
317 if (Status
== STATUS_PENDING
)
319 Status
= NtWaitForSingleObject(hNamedPipe
,
322 if (NT_SUCCESS(Status
))
324 Status
= Iosb
.Status
;
328 if (!NT_SUCCESS(Status
))
330 SetLastErrorByStatus(Status
);
344 SetNamedPipeHandleState(HANDLE hNamedPipe
,
346 LPDWORD lpMaxCollectionCount
,
347 LPDWORD lpCollectDataTimeout
)
349 IO_STATUS_BLOCK Iosb
;
352 /* Check if the Mode is being changed */
355 FILE_PIPE_INFORMATION Settings
;
357 /* Set the Completion Mode */
358 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
359 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
361 /* Set the Read Mode */
362 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
363 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
365 /* Send the changes to the Driver */
366 Status
= NtSetInformationFile(hNamedPipe
,
369 sizeof(FILE_PIPE_INFORMATION
),
370 FilePipeInformation
);
371 if (!NT_SUCCESS(Status
))
373 SetLastErrorByStatus(Status
);
378 /* Check if the Collection count or Timeout are being changed */
379 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
381 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
383 /* Setting one without the other would delete it, so we read old one */
384 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
386 Status
= NtQueryInformationFile(hNamedPipe
,
389 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
390 FilePipeRemoteInformation
);
392 if (!NT_SUCCESS(Status
))
394 SetLastErrorByStatus(Status
);
399 /* Now set the new settings */
400 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
401 *lpMaxCollectionCount
:
402 RemoteSettings
.MaximumCollectionCount
;
403 if (lpCollectDataTimeout
)
405 /* Convert it to Quad */
406 RemoteSettings
.CollectDataTime
.QuadPart
= -(LONGLONG
)
408 *lpCollectDataTimeout
);
411 /* Tell the driver to change them */
412 Status
= NtSetInformationFile(hNamedPipe
,
415 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
416 FilePipeRemoteInformation
);
418 if (!NT_SUCCESS(Status
))
420 SetLastErrorByStatus(Status
);
433 CallNamedPipeA(LPCSTR lpNamedPipeName
,
437 DWORD nOutBufferSize
,
441 UNICODE_STRING PipeName
;
444 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
445 (LPSTR
)lpNamedPipeName
);
447 Result
= CallNamedPipeW(PipeName
.Buffer
,
455 RtlFreeUnicodeString(&PipeName
);
465 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
469 DWORD nOutBufferSize
,
473 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
480 hPipe
= CreateFileW(lpNamedPipeName
,
481 GENERIC_READ
| GENERIC_WRITE
,
482 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
485 FILE_ATTRIBUTE_NORMAL
,
487 if (hPipe
!= INVALID_HANDLE_VALUE
)
493 WaitNamedPipeW(lpNamedPipeName
,
499 dwPipeMode
= PIPE_READMODE_MESSAGE
;
500 bError
= SetNamedPipeHandleState(hPipe
,
510 bError
= TransactNamedPipe(hPipe
,
527 DisconnectNamedPipe(HANDLE hNamedPipe
)
529 IO_STATUS_BLOCK Iosb
;
532 Status
= NtFsControlFile(hNamedPipe
,
537 FSCTL_PIPE_DISCONNECT
,
542 if (Status
== STATUS_PENDING
)
544 Status
= NtWaitForSingleObject(hNamedPipe
,
547 if (!NT_SUCCESS(Status
))
549 SetLastErrorByStatus(Status
);
554 if (!NT_SUCCESS(Status
))
556 SetLastErrorByStatus(Status
);
567 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
569 LPDWORD lpCurInstances
,
570 LPDWORD lpMaxCollectionCount
,
571 LPDWORD lpCollectDataTimeout
,
573 DWORD nMaxUserNameSize
)
575 IO_STATUS_BLOCK StatusBlock
;
580 FILE_PIPE_INFORMATION PipeInfo
;
582 Status
= NtQueryInformationFile(hNamedPipe
,
585 sizeof(FILE_PIPE_INFORMATION
),
586 FilePipeInformation
);
587 if (!NT_SUCCESS(Status
))
589 SetLastErrorByStatus(Status
);
593 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
594 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
597 if(lpCurInstances
!= NULL
)
599 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
601 Status
= NtQueryInformationFile(hNamedPipe
,
604 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
605 FilePipeLocalInformation
);
606 if(!NT_SUCCESS(Status
))
608 SetLastErrorByStatus(Status
);
612 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
615 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
617 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
619 Status
= NtQueryInformationFile(hNamedPipe
,
622 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
623 FilePipeRemoteInformation
);
624 if(!NT_SUCCESS(Status
))
626 SetLastErrorByStatus(Status
);
630 if(lpMaxCollectionCount
!= NULL
)
632 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
635 if(lpCollectDataTimeout
!= NULL
)
638 *lpCollectDataTimeout
= 0;
642 if(lpUserName
!= NULL
)
644 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
645 retreive the user name with GetUserName(), revert the impersonation
646 and finally restore the thread token */
657 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
659 LPDWORD lpCurInstances
,
660 LPDWORD lpMaxCollectionCount
,
661 LPDWORD lpCollectDataTimeout
,
663 DWORD nMaxUserNameSize
)
665 UNICODE_STRING UserNameW
;
666 ANSI_STRING UserNameA
;
669 if(lpUserName
!= NULL
)
671 UserNameW
.Length
= 0;
672 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
673 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
675 UserNameA
.Buffer
= lpUserName
;
676 UserNameA
.Length
= 0;
677 UserNameA
.MaximumLength
= nMaxUserNameSize
;
680 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
683 lpMaxCollectionCount
,
684 lpCollectDataTimeout
,
688 if(Ret
&& lpUserName
!= NULL
)
690 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
691 if(!NT_SUCCESS(Status
))
693 SetLastErrorByStatus(Status
);
698 if(UserNameW
.Buffer
!= NULL
)
700 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
711 GetNamedPipeInfo(HANDLE hNamedPipe
,
713 LPDWORD lpOutBufferSize
,
714 LPDWORD lpInBufferSize
,
715 LPDWORD lpMaxInstances
)
717 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
718 IO_STATUS_BLOCK StatusBlock
;
721 Status
= NtQueryInformationFile(hNamedPipe
,
723 &PipeLocalInformation
,
724 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
725 FilePipeLocalInformation
);
726 if (!NT_SUCCESS(Status
))
728 SetLastErrorByStatus(Status
);
734 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
735 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
738 if (lpOutBufferSize
!= NULL
)
739 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
741 if (lpInBufferSize
!= NULL
)
742 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
744 if (lpMaxInstances
!= NULL
)
746 if (PipeLocalInformation
.MaximumInstances
>= 255)
747 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
749 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
760 PeekNamedPipe(HANDLE hNamedPipe
,
764 LPDWORD lpTotalBytesAvail
,
765 LPDWORD lpBytesLeftThisMessage
)
767 PFILE_PIPE_PEEK_BUFFER Buffer
;
768 IO_STATUS_BLOCK Iosb
;
772 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
773 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
777 Status
= NtFsControlFile(hNamedPipe
,
787 if (Status
== STATUS_PENDING
)
789 Status
= NtWaitForSingleObject(hNamedPipe
,
792 if (NT_SUCCESS(Status
))
793 Status
= Iosb
.Status
;
796 if (Status
== STATUS_BUFFER_OVERFLOW
)
798 Status
= STATUS_SUCCESS
;
801 if (!NT_SUCCESS(Status
))
803 RtlFreeHeap(RtlGetProcessHeap(),
806 SetLastErrorByStatus(Status
);
810 if (lpTotalBytesAvail
!= NULL
)
812 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
815 if (lpBytesRead
!= NULL
)
817 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
820 if (lpBytesLeftThisMessage
!= NULL
)
822 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
823 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
826 if (lpBuffer
!= NULL
)
828 memcpy(lpBuffer
, Buffer
->Data
,
829 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
832 RtlFreeHeap(RtlGetProcessHeap(),
844 TransactNamedPipe(IN HANDLE hNamedPipe
,
845 IN LPVOID lpInBuffer
,
846 IN DWORD nInBufferSize
,
847 OUT LPVOID lpOutBuffer
,
848 IN DWORD nOutBufferSize
,
849 OUT LPDWORD lpBytesRead OPTIONAL
,
850 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
854 if (lpBytesRead
!= NULL
)
859 if (lpOverlapped
!= NULL
)
863 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
864 lpOverlapped
->Internal
= STATUS_PENDING
;
866 Status
= NtFsControlFile(hNamedPipe
,
867 lpOverlapped
->hEvent
,
870 (PIO_STATUS_BLOCK
)lpOverlapped
,
871 FSCTL_PIPE_TRANSCEIVE
,
877 /* return FALSE in case of failure and pending operations! */
878 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
880 SetLastErrorByStatus(Status
);
884 if (lpBytesRead
!= NULL
)
886 *lpBytesRead
= lpOverlapped
->InternalHigh
;
891 IO_STATUS_BLOCK Iosb
;
893 Status
= NtFsControlFile(hNamedPipe
,
898 FSCTL_PIPE_TRANSCEIVE
,
904 /* wait in case operation is pending */
905 if (Status
== STATUS_PENDING
)
907 Status
= NtWaitForSingleObject(hNamedPipe
,
910 if (NT_SUCCESS(Status
))
912 Status
= Iosb
.Status
;
916 if (NT_SUCCESS(Status
))
918 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
919 check that case either and crashes (only after the operation
921 *lpBytesRead
= Iosb
.Information
;
925 SetLastErrorByStatus(Status
);