1 /* $Id: npipe.c,v 1.10 2002/06/25 18:49:38 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 *****************************************************************/
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 IO_STATUS_BLOCK Iosb
;
292 PIO_STATUS_BLOCK IoStatusBlock
;
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_PENDING
))
331 SetLastErrorByStatus (Status
);
339 SetNamedPipeHandleState(HANDLE hNamedPipe
,
341 LPDWORD lpMaxCollectionCount
,
342 LPDWORD lpCollectDataTimeout
)
344 NPFS_GET_STATE GetState
;
345 NPFS_SET_STATE SetState
;
346 IO_STATUS_BLOCK Iosb
;
349 Status
= NtFsControlFile(hNamedPipe
,
354 FSCTL_PIPE_GET_STATE
,
358 sizeof(NPFS_GET_STATE
));
359 if (Status
== STATUS_PENDING
)
361 Status
= NtWaitForSingleObject(hNamedPipe
,
364 if (!NT_SUCCESS(Status
))
366 SetLastErrorByStatus(Status
);
373 if ((*lpMode
) & PIPE_READMODE_MESSAGE
)
375 SetState
.ReadModeMessage
= TRUE
;
379 SetState
.ReadModeMessage
= FALSE
;
381 if ((*lpMode
) & PIPE_NOWAIT
)
383 SetState
.NonBlocking
= TRUE
;
387 SetState
.NonBlocking
= FALSE
;
389 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
393 SetState
.ReadModeMessage
= GetState
.ReadModeMessage
;
394 SetState
.WriteModeMessage
= GetState
.WriteModeMessage
;
395 SetState
.NonBlocking
= SetState
.NonBlocking
;
398 if (lpMaxCollectionCount
!= NULL
)
400 SetState
.InBufferSize
= *lpMaxCollectionCount
;
404 SetState
.InBufferSize
= GetState
.InBufferSize
;
407 SetState
.OutBufferSize
= GetState
.OutBufferSize
;
409 if (lpCollectDataTimeout
!= NULL
)
411 SetState
.Timeout
.QuadPart
= (*lpCollectDataTimeout
) * -10000;
415 SetState
.Timeout
= GetState
.Timeout
;
418 Status
= NtFsControlFile(hNamedPipe
,
423 FSCTL_PIPE_SET_STATE
,
425 sizeof(NPFS_SET_STATE
),
428 if (Status
== STATUS_PENDING
)
430 Status
= NtWaitForSingleObject(hNamedPipe
,
433 if (!NT_SUCCESS(Status
))
435 SetLastErrorByStatus(Status
);
445 CallNamedPipeA(LPCSTR lpNamedPipeName
,
449 DWORD nOutBufferSize
,
453 UNICODE_STRING PipeName
;
456 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
457 (LPSTR
)lpNamedPipeName
);
459 Result
= CallNamedPipeW(PipeName
.Buffer
,
467 RtlFreeUnicodeString(&PipeName
);
474 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
478 DWORD nOutBufferSize
,
482 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
489 hPipe
= CreateFileW(lpNamedPipeName
,
490 GENERIC_READ
| GENERIC_WRITE
,
491 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
494 FILE_ATTRIBUTE_NORMAL
,
496 if (hPipe
!= INVALID_HANDLE_VALUE
)
502 WaitNamedPipeW(lpNamedPipeName
,
508 dwPipeMode
= PIPE_READMODE_MESSAGE
;
509 bError
= SetNamedPipeHandleState(hPipe
,
519 bError
= TransactNamedPipe(hPipe
,
533 DisconnectNamedPipe(HANDLE hNamedPipe
)
535 IO_STATUS_BLOCK Iosb
;
538 Status
= NtFsControlFile(hNamedPipe
,
543 FSCTL_PIPE_DISCONNECT
,
548 if (Status
== STATUS_PENDING
)
550 Status
= NtWaitForSingleObject(hNamedPipe
,
553 if (!NT_SUCCESS(Status
))
555 SetLastErrorByStatus(Status
);
560 if (!NT_SUCCESS(Status
))
562 SetLastErrorByStatus(Status
);
570 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
572 LPDWORD lpCurInstances
,
573 LPDWORD lpMaxCollectionCount
,
574 LPDWORD lpCollectDataTimeout
,
576 DWORD nMaxUserNameSize
)
578 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
579 FILE_PIPE_INFORMATION PipeInfo
;
580 IO_STATUS_BLOCK StatusBlock
;
585 Status
= NtQueryInformationFile(hNamedPipe
,
588 sizeof(FILE_PIPE_INFORMATION
),
589 FilePipeInformation
);
590 if (!NT_SUCCESS(Status
))
592 SetLastErrorByStatus(Status
);
595 *lpState
= 0; /* FIXME */
598 if (lpCurInstances
!= NULL
)
600 Status
= NtQueryInformationFile(hNamedPipe
,
603 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
604 FilePipeLocalInformation
);
605 if (!NT_SUCCESS(Status
))
607 SetLastErrorByStatus(Status
);
610 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, 255);
614 /* FIXME: retrieve remaining information */
622 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
624 LPDWORD lpCurInstances
,
625 LPDWORD lpMaxCollectionCount
,
626 LPDWORD lpCollectDataTimeout
,
628 DWORD nMaxUserNameSize
)
630 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
636 GetNamedPipeInfo(HANDLE hNamedPipe
,
638 LPDWORD lpOutBufferSize
,
639 LPDWORD lpInBufferSize
,
640 LPDWORD lpMaxInstances
)
642 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
643 IO_STATUS_BLOCK StatusBlock
;
646 Status
= NtQueryInformationFile(hNamedPipe
,
648 &PipeLocalInformation
,
649 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
650 FilePipeLocalInformation
);
651 if (!NT_SUCCESS(Status
))
653 SetLastErrorByStatus(Status
);
659 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
660 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
663 if (lpOutBufferSize
!= NULL
)
664 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
666 if (lpInBufferSize
!= NULL
)
667 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
669 if (lpMaxInstances
!= NULL
)
671 if (PipeLocalInformation
.MaximumInstances
>= 255)
672 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
674 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
682 PeekNamedPipe(HANDLE hNamedPipe
,
686 LPDWORD lpTotalBytesAvail
,
687 LPDWORD lpBytesLeftThisMessage
)
689 PFILE_PIPE_PEEK_BUFFER Buffer
;
690 IO_STATUS_BLOCK Iosb
;
694 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
695 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
699 Status
= NtFsControlFile(hNamedPipe
,
709 if (Status
== STATUS_PENDING
)
711 Status
= NtWaitForSingleObject(hNamedPipe
,
714 if (NT_SUCCESS(Status
))
715 Status
= Iosb
.Status
;
718 if (Status
== STATUS_BUFFER_OVERFLOW
)
720 Status
= STATUS_SUCCESS
;
723 if (!NT_SUCCESS(Status
))
725 RtlFreeHeap(RtlGetProcessHeap(),
728 SetLastErrorByStatus(Status
);
732 if (lpTotalBytesAvail
!= NULL
)
734 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
737 if (lpBytesRead
!= NULL
)
739 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
742 if (lpBytesLeftThisMessage
!= NULL
)
744 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
745 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
748 if (lpBuffer
!= NULL
)
750 memcpy(lpBuffer
, Buffer
->Data
,
751 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
754 RtlFreeHeap(RtlGetProcessHeap(),
763 TransactNamedPipe(HANDLE hNamedPipe
,
767 DWORD nOutBufferSize
,
769 LPOVERLAPPED lpOverlapped
)
771 IO_STATUS_BLOCK IoStatusBlock
;
774 if (lpOverlapped
== NULL
)
776 Status
= NtFsControlFile(hNamedPipe
,
781 FSCTL_PIPE_TRANSCEIVE
,
786 if (Status
== STATUS_PENDING
)
788 NtWaitForSingleObject(hNamedPipe
,
791 Status
= IoStatusBlock
.Status
;
793 if (NT_SUCCESS(Status
))
795 *lpBytesRead
= IoStatusBlock
.Information
;
800 lpOverlapped
->Internal
= STATUS_PENDING
;
802 Status
= NtFsControlFile(hNamedPipe
,
803 lpOverlapped
->hEvent
,
806 (PIO_STATUS_BLOCK
)lpOverlapped
,
807 FSCTL_PIPE_TRANSCEIVE
,
814 if (!NT_SUCCESS(Status
))
816 SetLastErrorByStatus(Status
);