1 /* $Id: npipe.c,v 1.13 2002/09/08 10:22:42 chorns 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 *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <ntdll/rtl.h>
16 #include <kernel32/error.h>
20 #include <napi/npipe.h>
23 #include <kernel32/kernel32.h>
25 /* FUNCTIONS ****************************************************************/
28 CreateNamedPipeA(LPCSTR lpName
,
34 DWORD nDefaultTimeOut
,
35 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
37 HANDLE NamedPipeHandle
;
41 RtlInitAnsiString(&NameA
, (LPSTR
)lpName
);
42 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
44 NamedPipeHandle
= CreateNamedPipeW(NameU
.Buffer
,
51 lpSecurityAttributes
);
53 RtlFreeUnicodeString(&NameU
);
55 return(NamedPipeHandle
);
60 CreateNamedPipeW(LPCWSTR lpName
,
66 DWORD nDefaultTimeOut
,
67 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
69 UNICODE_STRING NamedPipeName
;
72 OBJECT_ATTRIBUTES ObjectAttributes
;
74 ACCESS_MASK DesiredAccess
;
76 ULONG CreateDisposition
;
77 BOOLEAN WriteModeMessage
;
78 BOOLEAN ReadModeMessage
;
82 LARGE_INTEGER DefaultTimeOut
;
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 InitializeObjectAttributes(&ObjectAttributes
,
107 CreateDisposition
= FILE_OPEN_IF
;
110 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
112 CreateOptions
= CreateOptions
| FILE_WRITE_THROUGH
;
114 if (dwOpenMode
& FILE_FLAG_OVERLAPPED
)
116 CreateOptions
= CreateOptions
| FILE_SYNCHRONOUS_IO_ALERT
;
118 if (dwOpenMode
& PIPE_ACCESS_DUPLEX
)
120 CreateOptions
= CreateOptions
| FILE_PIPE_FULL_DUPLEX
;
122 else if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
124 CreateOptions
= CreateOptions
| FILE_PIPE_INBOUND
;
126 else if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
128 CreateOptions
= CreateOptions
| FILE_PIPE_OUTBOUND
;
131 if (dwPipeMode
& PIPE_TYPE_BYTE
)
133 WriteModeMessage
= FALSE
;
135 else if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
137 WriteModeMessage
= TRUE
;
141 WriteModeMessage
= FALSE
;
144 if (dwPipeMode
& PIPE_READMODE_BYTE
)
146 ReadModeMessage
= FALSE
;
148 else if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
150 ReadModeMessage
= TRUE
;
154 ReadModeMessage
= FALSE
;
157 if (dwPipeMode
& PIPE_WAIT
)
161 else if (dwPipeMode
& PIPE_NOWAIT
)
170 if (nMaxInstances
>= PIPE_UNLIMITED_INSTANCES
)
172 nMaxInstances
= ULONG_MAX
;
175 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000;
177 Status
= NtCreateNamedPipeFile(&PipeHandle
,
192 RtlFreeUnicodeString(&NamedPipeName
);
194 if (!NT_SUCCESS(Status
))
196 DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status
);
197 SetLastErrorByStatus (Status
);
198 return(INVALID_HANDLE_VALUE
);
206 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
210 UNICODE_STRING NameU
;
213 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
214 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
216 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
218 RtlFreeUnicodeString(&NameU
);
225 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
228 UNICODE_STRING NamedPipeName
;
231 OBJECT_ATTRIBUTES ObjectAttributes
;
232 NPFS_WAIT_PIPE WaitPipe
;
234 IO_STATUS_BLOCK Iosb
;
236 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
246 InitializeObjectAttributes(&ObjectAttributes
,
248 OBJ_CASE_INSENSITIVE
,
251 Status
= NtOpenFile(&FileHandle
,
256 FILE_SYNCHRONOUS_IO_ALERT
);
257 if (!NT_SUCCESS(Status
))
259 SetLastErrorByStatus (Status
);
263 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000;
265 Status
= NtFsControlFile(FileHandle
,
276 if (!NT_SUCCESS(Status
))
278 SetLastErrorByStatus (Status
);
287 ConnectNamedPipe(HANDLE hNamedPipe
,
288 LPOVERLAPPED lpOverlapped
)
290 PIO_STATUS_BLOCK IoStatusBlock
;
291 IO_STATUS_BLOCK Iosb
;
295 if (lpOverlapped
!= NULL
)
297 lpOverlapped
->Internal
= STATUS_PENDING
;
298 hEvent
= lpOverlapped
->hEvent
;
299 IoStatusBlock
= (PIO_STATUS_BLOCK
)lpOverlapped
;
303 IoStatusBlock
= &Iosb
;
307 Status
= NtFsControlFile(hNamedPipe
,
317 if ((lpOverlapped
== NULL
) && (Status
== STATUS_PENDING
))
319 Status
= NtWaitForSingleObject(hNamedPipe
,
322 if (!NT_SUCCESS(Status
))
324 SetLastErrorByStatus(Status
);
327 Status
= Iosb
.Status
;
329 if ((!NT_SUCCESS(Status
) && Status
!= STATUS_PIPE_CONNECTED
) ||
330 (Status
== STATUS_PENDING
))
332 SetLastErrorByStatus(Status
);
340 SetNamedPipeHandleState(HANDLE hNamedPipe
,
342 LPDWORD lpMaxCollectionCount
,
343 LPDWORD lpCollectDataTimeout
)
345 NPFS_GET_STATE GetState
;
346 NPFS_SET_STATE SetState
;
347 IO_STATUS_BLOCK Iosb
;
350 Status
= NtFsControlFile(hNamedPipe
,
355 FSCTL_PIPE_GET_STATE
,
359 sizeof(NPFS_GET_STATE
));
360 if (Status
== STATUS_PENDING
)
362 Status
= NtWaitForSingleObject(hNamedPipe
,
365 if (!NT_SUCCESS(Status
))
367 SetLastErrorByStatus(Status
);
374 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
376 SetState
.ReadModeMessage
= TRUE
;
380 SetState
.ReadModeMessage
= FALSE
;
382 if ((*lpMode
) & PIPE_NOWAIT
)
384 SetState
.NonBlocking
= TRUE
;
388 SetState
.NonBlocking
= FALSE
;
390 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
394 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
395 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
396 SetState
.NonBlocking
= SetState
.NonBlocking
;
399 if (lpMaxCollectionCount
!= NULL
)
401 SetState
.InBufferSize
= *lpMaxCollectionCount
;
405 SetState
.InBufferSize
= GetState
.InBufferSize
;
408 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
410 if (lpCollectDataTimeout
!= NULL
)
412 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000;
416 SetState
.Timeout
= GetState
.Timeout
;
419 Status
= NtFsControlFile(hNamedPipe
,
424 FSCTL_PIPE_SET_STATE
,
426 sizeof(NPFS_SET_STATE
),
429 if (Status
== STATUS_PENDING
)
431 Status
= NtWaitForSingleObject(hNamedPipe
,
434 if (!NT_SUCCESS(Status
))
436 SetLastErrorByStatus(Status
);
446 CallNamedPipeA(LPCSTR lpNamedPipeName
,
450 DWORD nOutBufferSize
,
454 UNICODE_STRING PipeName
;
457 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
458 (LPSTR
)lpNamedPipeName
);
460 Result
= CallNamedPipeW(PipeName
.Buffer
,
468 RtlFreeUnicodeString(&PipeName
);
475 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
479 DWORD nOutBufferSize
,
483 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
490 hPipe
= CreateFileW(lpNamedPipeName
,
491 GENERIC_READ
| GENERIC_WRITE
,
492 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
495 FILE_ATTRIBUTE_NORMAL
,
497 if (hPipe
!= INVALID_HANDLE_VALUE
)
503 WaitNamedPipeW(lpNamedPipeName
,
509 dwPipeMode
= PIPE_READMODE_MESSAGE
;
510 bError
= SetNamedPipeHandleState(hPipe
,
520 bError
= TransactNamedPipe(hPipe
,
534 DisconnectNamedPipe(HANDLE hNamedPipe
)
536 IO_STATUS_BLOCK Iosb
;
539 Status
= NtFsControlFile(hNamedPipe
,
544 FSCTL_PIPE_DISCONNECT
,
549 if (Status
== STATUS_PENDING
)
551 Status
= NtWaitForSingleObject(hNamedPipe
,
554 if (!NT_SUCCESS(Status
))
556 SetLastErrorByStatus(Status
);
561 if (!NT_SUCCESS(Status
))
563 SetLastErrorByStatus(Status
);
571 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
573 LPDWORD lpCurInstances
,
574 LPDWORD lpMaxCollectionCount
,
575 LPDWORD lpCollectDataTimeout
,
577 DWORD nMaxUserNameSize
)
579 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
580 FILE_PIPE_INFORMATION PipeInfo
;
581 IO_STATUS_BLOCK StatusBlock
;
586 Status
= NtQueryInformationFile(hNamedPipe
,
589 sizeof(FILE_PIPE_INFORMATION
),
590 FilePipeInformation
);
591 if (!NT_SUCCESS(Status
))
593 SetLastErrorByStatus(Status
);
596 *lpState
= 0; /* FIXME */
599 if (lpCurInstances
!= NULL
)
601 Status
= NtQueryInformationFile(hNamedPipe
,
604 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
605 FilePipeLocalInformation
);
606 if (!NT_SUCCESS(Status
))
608 SetLastErrorByStatus(Status
);
611 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, 255);
615 /* FIXME: retrieve remaining information */
623 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
625 LPDWORD lpCurInstances
,
626 LPDWORD lpMaxCollectionCount
,
627 LPDWORD lpCollectDataTimeout
,
629 DWORD nMaxUserNameSize
)
631 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
637 GetNamedPipeInfo(HANDLE hNamedPipe
,
639 LPDWORD lpOutBufferSize
,
640 LPDWORD lpInBufferSize
,
641 LPDWORD lpMaxInstances
)
643 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
644 IO_STATUS_BLOCK StatusBlock
;
647 Status
= NtQueryInformationFile(hNamedPipe
,
649 &PipeLocalInformation
,
650 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
651 FilePipeLocalInformation
);
652 if (!NT_SUCCESS(Status
))
654 SetLastErrorByStatus(Status
);
660 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
661 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
664 if (lpOutBufferSize
!= NULL
)
665 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
667 if (lpInBufferSize
!= NULL
)
668 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
670 if (lpMaxInstances
!= NULL
)
672 if (PipeLocalInformation
.MaximumInstances
>= 255)
673 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
675 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
683 PeekNamedPipe(HANDLE hNamedPipe
,
687 LPDWORD lpTotalBytesAvail
,
688 LPDWORD lpBytesLeftThisMessage
)
690 PFILE_PIPE_PEEK_BUFFER Buffer
;
691 IO_STATUS_BLOCK Iosb
;
695 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
696 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
700 Status
= NtFsControlFile(hNamedPipe
,
710 if (Status
== STATUS_PENDING
)
712 Status
= NtWaitForSingleObject(hNamedPipe
,
715 if (NT_SUCCESS(Status
))
716 Status
= Iosb
.Status
;
719 if (Status
== STATUS_BUFFER_OVERFLOW
)
721 Status
= STATUS_SUCCESS
;
724 if (!NT_SUCCESS(Status
))
726 RtlFreeHeap(RtlGetProcessHeap(),
729 SetLastErrorByStatus(Status
);
733 if (lpTotalBytesAvail
!= NULL
)
735 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
738 if (lpBytesRead
!= NULL
)
740 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
743 if (lpBytesLeftThisMessage
!= NULL
)
745 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
746 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
749 if (lpBuffer
!= NULL
)
751 memcpy(lpBuffer
, Buffer
->Data
,
752 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
755 RtlFreeHeap(RtlGetProcessHeap(),
764 TransactNamedPipe(HANDLE hNamedPipe
,
768 DWORD nOutBufferSize
,
770 LPOVERLAPPED lpOverlapped
)
772 IO_STATUS_BLOCK IoStatusBlock
;
775 if (lpOverlapped
== NULL
)
777 Status
= NtFsControlFile(hNamedPipe
,
782 FSCTL_PIPE_TRANSCEIVE
,
787 if (Status
== STATUS_PENDING
)
789 NtWaitForSingleObject(hNamedPipe
,
792 Status
= IoStatusBlock
.Status
;
794 if (NT_SUCCESS(Status
))
796 *lpBytesRead
= IoStatusBlock
.Information
;
801 lpOverlapped
->Internal
= STATUS_PENDING
;
803 Status
= NtFsControlFile(hNamedPipe
,
804 lpOverlapped
->hEvent
,
807 (PIO_STATUS_BLOCK
)lpOverlapped
,
808 FSCTL_PIPE_TRANSCEIVE
,
815 if (!NT_SUCCESS(Status
))
817 SetLastErrorByStatus(Status
);