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);