1 /* $Id: npipe.c,v 1.17 2004/01/23 21:16:03 ekohl Exp $
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 BOOLEAN WriteModeMessage
;
77 BOOLEAN ReadModeMessage
;
81 LARGE_INTEGER DefaultTimeOut
;
83 Result
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpName
,
89 SetLastError(ERROR_PATH_NOT_FOUND
);
90 return(INVALID_HANDLE_VALUE
);
93 DPRINT("Pipe name: %wZ\n", &NamedPipeName
);
94 DPRINT("Pipe name: %S\n", NamedPipeName
.Buffer
);
96 InitializeObjectAttributes(&ObjectAttributes
,
106 CreateDisposition
= FILE_OPEN_IF
;
109 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
111 CreateOptions
= CreateOptions
| FILE_WRITE_THROUGH
;
113 if (dwOpenMode
& FILE_FLAG_OVERLAPPED
)
115 CreateOptions
= CreateOptions
| FILE_SYNCHRONOUS_IO_ALERT
;
117 if (dwOpenMode
& PIPE_ACCESS_DUPLEX
)
119 CreateOptions
= CreateOptions
| FILE_PIPE_FULL_DUPLEX
;
121 else if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
123 CreateOptions
= CreateOptions
| FILE_PIPE_INBOUND
;
125 else if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
127 CreateOptions
= CreateOptions
| FILE_PIPE_OUTBOUND
;
130 if (dwPipeMode
& PIPE_TYPE_BYTE
)
132 WriteModeMessage
= FALSE
;
134 else if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
136 WriteModeMessage
= TRUE
;
140 WriteModeMessage
= FALSE
;
143 if (dwPipeMode
& PIPE_READMODE_BYTE
)
145 ReadModeMessage
= FALSE
;
147 else if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
149 ReadModeMessage
= TRUE
;
153 ReadModeMessage
= FALSE
;
156 if (dwPipeMode
& PIPE_WAIT
)
160 else if (dwPipeMode
& PIPE_NOWAIT
)
169 if (nMaxInstances
>= PIPE_UNLIMITED_INSTANCES
)
171 nMaxInstances
= ULONG_MAX
;
174 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000;
176 Status
= NtCreateNamedPipeFile(&PipeHandle
,
191 RtlFreeUnicodeString(&NamedPipeName
);
193 if (!NT_SUCCESS(Status
))
195 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status
);
196 SetLastErrorByStatus (Status
);
197 return(INVALID_HANDLE_VALUE
);
208 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
212 UNICODE_STRING NameU
;
215 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
216 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
218 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
220 RtlFreeUnicodeString(&NameU
);
230 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
233 UNICODE_STRING NamedPipeName
;
236 OBJECT_ATTRIBUTES ObjectAttributes
;
237 NPFS_WAIT_PIPE WaitPipe
;
239 IO_STATUS_BLOCK Iosb
;
241 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
251 InitializeObjectAttributes(&ObjectAttributes
,
253 OBJ_CASE_INSENSITIVE
,
256 Status
= NtOpenFile(&FileHandle
,
261 FILE_SYNCHRONOUS_IO_ALERT
);
262 if (!NT_SUCCESS(Status
))
264 SetLastErrorByStatus (Status
);
268 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000;
270 Status
= NtFsControlFile(FileHandle
,
281 if (!NT_SUCCESS(Status
))
283 SetLastErrorByStatus (Status
);
295 ConnectNamedPipe(HANDLE hNamedPipe
,
296 LPOVERLAPPED lpOverlapped
)
298 PIO_STATUS_BLOCK IoStatusBlock
;
299 IO_STATUS_BLOCK Iosb
;
303 if (lpOverlapped
!= NULL
)
305 lpOverlapped
->Internal
= STATUS_PENDING
;
306 hEvent
= lpOverlapped
->hEvent
;
307 IoStatusBlock
= (PIO_STATUS_BLOCK
)lpOverlapped
;
311 IoStatusBlock
= &Iosb
;
315 Status
= NtFsControlFile(hNamedPipe
,
325 if ((lpOverlapped
== NULL
) && (Status
== STATUS_PENDING
))
327 Status
= NtWaitForSingleObject(hNamedPipe
,
330 if (!NT_SUCCESS(Status
))
332 SetLastErrorByStatus(Status
);
335 Status
= Iosb
.Status
;
337 if ((!NT_SUCCESS(Status
) && Status
!= STATUS_PIPE_CONNECTED
) ||
338 (Status
== STATUS_PENDING
))
340 SetLastErrorByStatus(Status
);
351 SetNamedPipeHandleState(HANDLE hNamedPipe
,
353 LPDWORD lpMaxCollectionCount
,
354 LPDWORD lpCollectDataTimeout
)
356 NPFS_GET_STATE GetState
;
357 NPFS_SET_STATE SetState
;
358 IO_STATUS_BLOCK Iosb
;
361 Status
= NtFsControlFile(hNamedPipe
,
366 FSCTL_PIPE_GET_STATE
,
370 sizeof(NPFS_GET_STATE
));
371 if (Status
== STATUS_PENDING
)
373 Status
= NtWaitForSingleObject(hNamedPipe
,
376 if (!NT_SUCCESS(Status
))
378 SetLastErrorByStatus(Status
);
385 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
387 SetState
.ReadModeMessage
= TRUE
;
391 SetState
.ReadModeMessage
= FALSE
;
393 if ((*lpMode
) & PIPE_NOWAIT
)
395 SetState
.NonBlocking
= TRUE
;
399 SetState
.NonBlocking
= FALSE
;
401 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
405 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
406 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
407 SetState
.NonBlocking
= SetState
.NonBlocking
;
410 if (lpMaxCollectionCount
!= NULL
)
412 SetState
.InBufferSize
= *lpMaxCollectionCount
;
416 SetState
.InBufferSize
= GetState
.InBufferSize
;
419 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
421 if (lpCollectDataTimeout
!= NULL
)
423 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000;
427 SetState
.Timeout
= GetState
.Timeout
;
430 Status
= NtFsControlFile(hNamedPipe
,
435 FSCTL_PIPE_SET_STATE
,
437 sizeof(NPFS_SET_STATE
),
440 if (Status
== STATUS_PENDING
)
442 Status
= NtWaitForSingleObject(hNamedPipe
,
445 if (!NT_SUCCESS(Status
))
447 SetLastErrorByStatus(Status
);
460 CallNamedPipeA(LPCSTR lpNamedPipeName
,
464 DWORD nOutBufferSize
,
468 UNICODE_STRING PipeName
;
471 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
472 (LPSTR
)lpNamedPipeName
);
474 Result
= CallNamedPipeW(PipeName
.Buffer
,
482 RtlFreeUnicodeString(&PipeName
);
492 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
496 DWORD nOutBufferSize
,
500 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
507 hPipe
= CreateFileW(lpNamedPipeName
,
508 GENERIC_READ
| GENERIC_WRITE
,
509 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
512 FILE_ATTRIBUTE_NORMAL
,
514 if (hPipe
!= INVALID_HANDLE_VALUE
)
520 WaitNamedPipeW(lpNamedPipeName
,
526 dwPipeMode
= PIPE_READMODE_MESSAGE
;
527 bError
= SetNamedPipeHandleState(hPipe
,
537 bError
= TransactNamedPipe(hPipe
,
554 DisconnectNamedPipe(HANDLE hNamedPipe
)
556 IO_STATUS_BLOCK Iosb
;
559 Status
= NtFsControlFile(hNamedPipe
,
564 FSCTL_PIPE_DISCONNECT
,
569 if (Status
== STATUS_PENDING
)
571 Status
= NtWaitForSingleObject(hNamedPipe
,
574 if (!NT_SUCCESS(Status
))
576 SetLastErrorByStatus(Status
);
581 if (!NT_SUCCESS(Status
))
583 SetLastErrorByStatus(Status
);
594 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
596 LPDWORD lpCurInstances
,
597 LPDWORD lpMaxCollectionCount
,
598 LPDWORD lpCollectDataTimeout
,
600 DWORD nMaxUserNameSize
)
602 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
603 FILE_PIPE_INFORMATION PipeInfo
;
604 IO_STATUS_BLOCK StatusBlock
;
609 Status
= NtQueryInformationFile(hNamedPipe
,
612 sizeof(FILE_PIPE_INFORMATION
),
613 FilePipeInformation
);
614 if (!NT_SUCCESS(Status
))
616 SetLastErrorByStatus(Status
);
619 *lpState
= 0; /* FIXME */
622 if (lpCurInstances
!= NULL
)
624 Status
= NtQueryInformationFile(hNamedPipe
,
627 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
628 FilePipeLocalInformation
);
629 if (!NT_SUCCESS(Status
))
631 SetLastErrorByStatus(Status
);
634 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, 255);
638 /* FIXME: retrieve remaining information */
649 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
651 LPDWORD lpCurInstances
,
652 LPDWORD lpMaxCollectionCount
,
653 LPDWORD lpCollectDataTimeout
,
655 DWORD nMaxUserNameSize
)
657 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
666 GetNamedPipeInfo(HANDLE hNamedPipe
,
668 LPDWORD lpOutBufferSize
,
669 LPDWORD lpInBufferSize
,
670 LPDWORD lpMaxInstances
)
672 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
673 IO_STATUS_BLOCK StatusBlock
;
676 Status
= NtQueryInformationFile(hNamedPipe
,
678 &PipeLocalInformation
,
679 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
680 FilePipeLocalInformation
);
681 if (!NT_SUCCESS(Status
))
683 SetLastErrorByStatus(Status
);
689 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
690 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
693 if (lpOutBufferSize
!= NULL
)
694 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
696 if (lpInBufferSize
!= NULL
)
697 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
699 if (lpMaxInstances
!= NULL
)
701 if (PipeLocalInformation
.MaximumInstances
>= 255)
702 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
704 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
715 PeekNamedPipe(HANDLE hNamedPipe
,
719 LPDWORD lpTotalBytesAvail
,
720 LPDWORD lpBytesLeftThisMessage
)
722 PFILE_PIPE_PEEK_BUFFER Buffer
;
723 IO_STATUS_BLOCK Iosb
;
727 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
728 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
732 Status
= NtFsControlFile(hNamedPipe
,
742 if (Status
== STATUS_PENDING
)
744 Status
= NtWaitForSingleObject(hNamedPipe
,
747 if (NT_SUCCESS(Status
))
748 Status
= Iosb
.Status
;
751 if (Status
== STATUS_BUFFER_OVERFLOW
)
753 Status
= STATUS_SUCCESS
;
756 if (!NT_SUCCESS(Status
))
758 RtlFreeHeap(RtlGetProcessHeap(),
761 SetLastErrorByStatus(Status
);
765 if (lpTotalBytesAvail
!= NULL
)
767 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
770 if (lpBytesRead
!= NULL
)
772 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
775 if (lpBytesLeftThisMessage
!= NULL
)
777 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
778 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
781 if (lpBuffer
!= NULL
)
783 memcpy(lpBuffer
, Buffer
->Data
,
784 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
787 RtlFreeHeap(RtlGetProcessHeap(),
799 TransactNamedPipe(HANDLE hNamedPipe
,
803 DWORD nOutBufferSize
,
805 LPOVERLAPPED lpOverlapped
)
807 IO_STATUS_BLOCK IoStatusBlock
;
810 if (lpOverlapped
== NULL
)
812 Status
= NtFsControlFile(hNamedPipe
,
817 FSCTL_PIPE_TRANSCEIVE
,
822 if (Status
== STATUS_PENDING
)
824 NtWaitForSingleObject(hNamedPipe
,
827 Status
= IoStatusBlock
.Status
;
829 if (NT_SUCCESS(Status
))
831 *lpBytesRead
= IoStatusBlock
.Information
;
836 lpOverlapped
->Internal
= STATUS_PENDING
;
838 Status
= NtFsControlFile(hNamedPipe
,
839 lpOverlapped
->hEvent
,
842 (PIO_STATUS_BLOCK
)lpOverlapped
,
843 FSCTL_PIPE_TRANSCEIVE
,
850 if (!NT_SUCCESS(Status
))
852 SetLastErrorByStatus(Status
);