2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32 Kernel Library
4 * FILE: lib/kernel32/file/npipe.c
5 * PURPOSE: Named Pipe Functions
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 * Ariadne ( ariadne@xs4all.nl)
10 /* INCLUDES *****************************************************************/
15 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
16 #include "../include/debug.h"
18 /* FUNCTIONS ****************************************************************/
25 CreateNamedPipeA(LPCSTR lpName
,
31 DWORD nDefaultTimeOut
,
32 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
34 PUNICODE_STRING NameU
= &NtCurrentTeb()->StaticUnicodeString
;
37 /* Initialize the string as ANSI_STRING and convert to Unicode */
38 RtlInitAnsiString(&NameA
, (LPSTR
)lpName
);
39 RtlAnsiStringToUnicodeString(NameU
, &NameA
, FALSE
);
41 /* Call the Unicode API */
42 return CreateNamedPipeW(NameU
->Buffer
,
49 lpSecurityAttributes
);
57 CreateNamedPipeW(LPCWSTR lpName
,
63 DWORD nDefaultTimeOut
,
64 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
66 UNICODE_STRING NamedPipeName
;
69 OBJECT_ATTRIBUTES ObjectAttributes
;
71 ACCESS_MASK DesiredAccess
;
72 ULONG CreateOptions
= 0;
73 ULONG WriteModeMessage
;
74 ULONG ReadModeMessage
;
77 ULONG ShareAccess
= 0, Attributes
;
78 LARGE_INTEGER DefaultTimeOut
;
79 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
81 /* Check for valid instances */
82 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
85 SetLastError(ERROR_INVALID_PARAMETER
);
86 return INVALID_HANDLE_VALUE
;
89 /* Convert to NT syntax */
90 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
) nMaxInstances
= -1;
92 /* Convert the name */
93 Result
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpName
,
99 /* Conversion failed */
100 SetLastError(ERROR_PATH_NOT_FOUND
);
101 return(INVALID_HANDLE_VALUE
);
104 DPRINT("Pipe name: %wZ\n", &NamedPipeName
);
105 DPRINT("Pipe name: %S\n", NamedPipeName
.Buffer
);
107 /* Always case insensitive, check if we got extra attributes */
108 Attributes
= OBJ_CASE_INSENSITIVE
;
109 if(lpSecurityAttributes
)
111 /* We did; get the security descriptor */
112 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
114 /* And check if this is pipe's handle will beinheritable */
115 if(lpSecurityAttributes
->bInheritHandle
) Attributes
|= OBJ_INHERIT
;
118 /* Now we can initialize the object attributes */
119 InitializeObjectAttributes(&ObjectAttributes
,
125 /* Setup the default Desired Access */
126 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
128 ACCESS_SYSTEM_SECURITY
));
130 /* Convert to NT Create Flags */
131 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
133 CreateOptions
|= FILE_WRITE_THROUGH
;
135 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
137 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
140 /* Handle all open modes */
141 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
143 ShareAccess
|= FILE_SHARE_READ
;
144 DesiredAccess
|= GENERIC_WRITE
;
146 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
148 ShareAccess
|= FILE_SHARE_WRITE
;
149 DesiredAccess
|= GENERIC_READ
;
152 /* Handle the type flags */
153 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
155 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
159 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
162 /* Handle the mode flags */
163 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
165 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
169 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
172 /* Handle the blocking mode */
173 if (dwPipeMode
& PIPE_NOWAIT
)
175 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
179 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
182 /* Check if we have a timeout */
185 /* Convert the time to NT format */
186 DefaultTimeOut
.QuadPart
= UInt32x32To64(nDefaultTimeOut
, -10000);
190 /* Use default timeout of 50 ms */
191 DefaultTimeOut
.QuadPart
= -500000;
194 /* Now create the pipe */
195 Status
= NtCreateNamedPipeFile(&PipeHandle
,
211 RtlFreeUnicodeString(&NamedPipeName
);
214 if (!NT_SUCCESS(Status
))
216 /* Failed to create it */
217 DPRINT1("NtCreateNamedPipe failed (Status %x)!\n", Status
);
218 SetLastErrorByStatus (Status
);
219 return INVALID_HANDLE_VALUE
;
222 /* Return the handle */
231 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
235 UNICODE_STRING NameU
;
237 /* Convert the name to Unicode */
238 Basep8BitStringToLiveUnicodeString(&NameU
, lpNamedPipeName
);
240 /* Call the Unicode API */
241 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
243 /* Free the Unicode string */
244 RtlFreeUnicodeString(&NameU
);
251 * When NPFS will work properly, use this code instead. It is compatible with
252 * Microsoft's NPFS.SYS. The main difference is that:
253 * - This code actually respects the timeout instead of ignoring it!
254 * - This code validates and creates the proper names for both UNC and local pipes
255 * - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or
256 * \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the
257 * FILE_PIPE_WAIT_FOR_BUFFER structure.
259 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
265 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
268 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
273 OBJECT_ATTRIBUTES ObjectAttributes
;
276 IO_STATUS_BLOCK IoStatusBlock
;
277 ULONG WaitPipeInfoSize
;
278 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
280 /* Start by making a unicode string of the name */
281 DPRINT("Sent path: %S\n", lpNamedPipeName
);
282 RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
);
283 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
285 /* All slashes must become backslashes */
286 for (i
= 0; i
< NameLength
; i
++)
288 /* Check and convert */
289 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
292 /* Find the path type of the name we were given */
293 NewName
= NamedPipeName
;
294 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
296 /* Check if this was a device path, ie : "\\.\pipe\name" */
297 if (Type
== DEVICE_PATH
)
299 /* Make sure it's a valid prefix */
300 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
301 RtlPrefixString((PANSI_STRING
)&PipePrefix
, (PANSI_STRING
)&NewName
, TRUE
);
305 NewName
.Length
-= 9 * sizeof(WCHAR
);
307 /* Initialize the Dos Devices name */
308 DPRINT("NewName: %wZ\n", &NewName
);
309 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
311 else if (Type
== UNC_PATH
)
313 /* The path is \\server\\pipe\name; find the pipename itself */
314 p
= &NewName
.Buffer
[2];
316 /* First loop to get past the server name */
319 /* Check if this is a backslash */
320 if (*p
== L
'\\') break;
326 /* Now make sure the full name contains "pipe\" */
327 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\"))))
329 /* Get to the pipe name itself now */
330 p
+= sizeof("pipe\\") - 1;
334 /* The name is invalid */
335 DPRINT1("Invalid name!\n");
336 SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD
);
340 /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
344 DPRINT1("Invalid path type\n");
345 SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD
);
349 /* Initialize the object attributes */
350 DPRINT("Opening: %wZ\n", &DevicePath
);
351 InitializeObjectAttributes(&ObjectAttributes
,
353 OBJ_CASE_INSENSITIVE
,
358 Status
= NtOpenFile(&FileHandle
,
359 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
362 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
363 FILE_SYNCHRONOUS_IO_NONALERT
);
364 if (!NT_SUCCESS(Status
))
366 /* Fail; couldn't open */
367 DPRINT1("Status: %lx\n", Status
);
368 SetLastErrorByStatus(Status
);
369 RtlFreeUnicodeString(&NamedPipeName
);
373 /* Now calculate the total length of the structure and allocate it */
374 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
376 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
378 /* Check what timeout we got */
379 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
381 /* Don't use a timeout */
382 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
386 /* Check if we should wait forever */
387 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
390 WaitPipeInfo
->Timeout
.LowPart
= 0;
391 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
395 /* Convert to NT format */
396 WaitPipeInfo
->Timeout
.QuadPart
= UInt32x32To64(-10000, nTimeOut
);
399 /* In both cases, we do have a timeout */
400 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
403 /* Set the length and copy the name */
404 WaitPipeInfo
->NameLength
= NewName
.Length
;
405 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
407 /* Get rid of the full name */
408 RtlFreeUnicodeString(&NamedPipeName
);
410 /* Let NPFS know of our request */
411 Status
= NtFsControlFile(FileHandle
,
422 /* Free our pipe info data and close the handle */
423 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
426 /* Check the status */
427 if (!NT_SUCCESS(Status
))
429 /* Failure to wait on the pipe */
430 DPRINT1("Status: %lx\n", Status
);
431 SetLastErrorByStatus (Status
);
443 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
446 UNICODE_STRING NamedPipeName
;
449 OBJECT_ATTRIBUTES ObjectAttributes
;
450 FILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
452 IO_STATUS_BLOCK Iosb
;
454 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
463 InitializeObjectAttributes(&ObjectAttributes
,
465 OBJ_CASE_INSENSITIVE
,
468 Status
= NtOpenFile(&FileHandle
,
469 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
472 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
473 FILE_SYNCHRONOUS_IO_NONALERT
);
474 if (!NT_SUCCESS(Status
))
476 SetLastErrorByStatus (Status
);
480 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000LL;
482 Status
= NtFsControlFile(FileHandle
,
493 if (!NT_SUCCESS(Status
))
495 SetLastErrorByStatus (Status
);
507 ConnectNamedPipe(IN HANDLE hNamedPipe
,
508 IN LPOVERLAPPED lpOverlapped
)
512 if (lpOverlapped
!= NULL
)
516 lpOverlapped
->Internal
= STATUS_PENDING
;
517 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
519 Status
= NtFsControlFile(hNamedPipe
,
520 lpOverlapped
->hEvent
,
523 (PIO_STATUS_BLOCK
)lpOverlapped
,
530 /* return FALSE in case of failure and pending operations! */
531 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
533 SetLastErrorByStatus(Status
);
539 IO_STATUS_BLOCK Iosb
;
541 Status
= NtFsControlFile(hNamedPipe
,
552 /* wait in case operation is pending */
553 if (Status
== STATUS_PENDING
)
555 Status
= NtWaitForSingleObject(hNamedPipe
,
558 if (NT_SUCCESS(Status
))
560 Status
= Iosb
.Status
;
564 if (!NT_SUCCESS(Status
))
566 SetLastErrorByStatus(Status
);
579 SetNamedPipeHandleState(HANDLE hNamedPipe
,
581 LPDWORD lpMaxCollectionCount
,
582 LPDWORD lpCollectDataTimeout
)
584 IO_STATUS_BLOCK Iosb
;
587 /* Check if the Mode is being changed */
590 FILE_PIPE_INFORMATION Settings
;
592 /* Set the Completion Mode */
593 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
594 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
596 /* Set the Read Mode */
597 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
598 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
600 /* Send the changes to the Driver */
601 Status
= NtSetInformationFile(hNamedPipe
,
604 sizeof(FILE_PIPE_INFORMATION
),
605 FilePipeInformation
);
606 if (!NT_SUCCESS(Status
))
608 SetLastErrorByStatus(Status
);
613 /* Check if the Collection count or Timeout are being changed */
614 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
616 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
618 /* Setting one without the other would delete it, so we read old one */
619 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
621 Status
= NtQueryInformationFile(hNamedPipe
,
624 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
625 FilePipeRemoteInformation
);
627 if (!NT_SUCCESS(Status
))
629 SetLastErrorByStatus(Status
);
634 /* Now set the new settings */
635 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
636 *lpMaxCollectionCount
:
637 RemoteSettings
.MaximumCollectionCount
;
638 if (lpCollectDataTimeout
)
640 /* Convert it to Quad */
641 RemoteSettings
.CollectDataTime
.QuadPart
= -(LONGLONG
)
643 *lpCollectDataTimeout
);
646 /* Tell the driver to change them */
647 Status
= NtSetInformationFile(hNamedPipe
,
650 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
651 FilePipeRemoteInformation
);
653 if (!NT_SUCCESS(Status
))
655 SetLastErrorByStatus(Status
);
669 CallNamedPipeA(LPCSTR lpNamedPipeName
,
673 DWORD nOutBufferSize
,
677 UNICODE_STRING PipeName
= &NtCurrentTeb()->StaticUnicodeString
;
678 ANSI_STRING AnsiPipe
;
680 /* Initialize the string as ANSI_STRING and convert to Unicode */
681 RtlInitAnsiString(&NameA
, (LPSTR
)lpName
);
682 RtlAnsiStringToUnicodeString(NameU
, &NameA
, FALSE
);
684 /* Call the Unicode function */
685 return CallNamedPipeW(PipeName
->Buffer
,
698 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
702 DWORD nOutBufferSize
,
706 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
713 hPipe
= CreateFileW(lpNamedPipeName
,
714 GENERIC_READ
| GENERIC_WRITE
,
715 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
718 FILE_ATTRIBUTE_NORMAL
,
720 if (hPipe
!= INVALID_HANDLE_VALUE
)
726 WaitNamedPipeW(lpNamedPipeName
,
732 dwPipeMode
= PIPE_READMODE_MESSAGE
;
733 bError
= SetNamedPipeHandleState(hPipe
,
743 bError
= TransactNamedPipe(hPipe
,
760 DisconnectNamedPipe(HANDLE hNamedPipe
)
762 IO_STATUS_BLOCK Iosb
;
765 Status
= NtFsControlFile(hNamedPipe
,
770 FSCTL_PIPE_DISCONNECT
,
775 if (Status
== STATUS_PENDING
)
777 Status
= NtWaitForSingleObject(hNamedPipe
,
780 if (!NT_SUCCESS(Status
))
782 SetLastErrorByStatus(Status
);
787 if (!NT_SUCCESS(Status
))
789 SetLastErrorByStatus(Status
);
800 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
802 LPDWORD lpCurInstances
,
803 LPDWORD lpMaxCollectionCount
,
804 LPDWORD lpCollectDataTimeout
,
806 DWORD nMaxUserNameSize
)
808 IO_STATUS_BLOCK StatusBlock
;
813 FILE_PIPE_INFORMATION PipeInfo
;
815 Status
= NtQueryInformationFile(hNamedPipe
,
818 sizeof(FILE_PIPE_INFORMATION
),
819 FilePipeInformation
);
820 if (!NT_SUCCESS(Status
))
822 SetLastErrorByStatus(Status
);
826 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
827 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
830 if(lpCurInstances
!= NULL
)
832 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
834 Status
= NtQueryInformationFile(hNamedPipe
,
837 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
838 FilePipeLocalInformation
);
839 if(!NT_SUCCESS(Status
))
841 SetLastErrorByStatus(Status
);
845 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
848 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
850 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
852 Status
= NtQueryInformationFile(hNamedPipe
,
855 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
856 FilePipeRemoteInformation
);
857 if(!NT_SUCCESS(Status
))
859 SetLastErrorByStatus(Status
);
863 if(lpMaxCollectionCount
!= NULL
)
865 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
868 if(lpCollectDataTimeout
!= NULL
)
871 *lpCollectDataTimeout
= 0;
875 if(lpUserName
!= NULL
)
877 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
878 retreive the user name with GetUserName(), revert the impersonation
879 and finally restore the thread token */
890 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
892 LPDWORD lpCurInstances
,
893 LPDWORD lpMaxCollectionCount
,
894 LPDWORD lpCollectDataTimeout
,
896 DWORD nMaxUserNameSize
)
898 UNICODE_STRING UserNameW
;
899 ANSI_STRING UserNameA
;
902 if(lpUserName
!= NULL
)
904 UserNameW
.Length
= 0;
905 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
906 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
908 UserNameA
.Buffer
= lpUserName
;
909 UserNameA
.Length
= 0;
910 UserNameA
.MaximumLength
= nMaxUserNameSize
;
913 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
916 lpMaxCollectionCount
,
917 lpCollectDataTimeout
,
921 if(Ret
&& lpUserName
!= NULL
)
923 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
924 if(!NT_SUCCESS(Status
))
926 SetLastErrorByStatus(Status
);
931 if(UserNameW
.Buffer
!= NULL
)
933 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
944 GetNamedPipeInfo(HANDLE hNamedPipe
,
946 LPDWORD lpOutBufferSize
,
947 LPDWORD lpInBufferSize
,
948 LPDWORD lpMaxInstances
)
950 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
951 IO_STATUS_BLOCK StatusBlock
;
954 Status
= NtQueryInformationFile(hNamedPipe
,
956 &PipeLocalInformation
,
957 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
958 FilePipeLocalInformation
);
959 if (!NT_SUCCESS(Status
))
961 SetLastErrorByStatus(Status
);
967 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
968 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
971 if (lpOutBufferSize
!= NULL
)
972 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
974 if (lpInBufferSize
!= NULL
)
975 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
977 if (lpMaxInstances
!= NULL
)
979 if (PipeLocalInformation
.MaximumInstances
>= 255)
980 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
982 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
993 PeekNamedPipe(HANDLE hNamedPipe
,
997 LPDWORD lpTotalBytesAvail
,
998 LPDWORD lpBytesLeftThisMessage
)
1000 PFILE_PIPE_PEEK_BUFFER Buffer
;
1001 IO_STATUS_BLOCK Iosb
;
1005 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
1006 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
1010 Status
= NtFsControlFile(hNamedPipe
,
1020 if (Status
== STATUS_PENDING
)
1022 Status
= NtWaitForSingleObject(hNamedPipe
,
1025 if (NT_SUCCESS(Status
))
1026 Status
= Iosb
.Status
;
1029 if (Status
== STATUS_BUFFER_OVERFLOW
)
1031 Status
= STATUS_SUCCESS
;
1034 if (!NT_SUCCESS(Status
))
1036 RtlFreeHeap(RtlGetProcessHeap(),
1039 SetLastErrorByStatus(Status
);
1043 if (lpTotalBytesAvail
!= NULL
)
1045 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1048 if (lpBytesRead
!= NULL
)
1050 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
1053 if (lpBytesLeftThisMessage
!= NULL
)
1055 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
1056 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
1059 if (lpBuffer
!= NULL
)
1061 memcpy(lpBuffer
, Buffer
->Data
,
1062 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
1065 RtlFreeHeap(RtlGetProcessHeap(),
1077 TransactNamedPipe(IN HANDLE hNamedPipe
,
1078 IN LPVOID lpInBuffer
,
1079 IN DWORD nInBufferSize
,
1080 OUT LPVOID lpOutBuffer
,
1081 IN DWORD nOutBufferSize
,
1082 OUT LPDWORD lpBytesRead OPTIONAL
,
1083 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1087 if (lpBytesRead
!= NULL
)
1092 if (lpOverlapped
!= NULL
)
1096 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1097 lpOverlapped
->Internal
= STATUS_PENDING
;
1099 Status
= NtFsControlFile(hNamedPipe
,
1100 lpOverlapped
->hEvent
,
1103 (PIO_STATUS_BLOCK
)lpOverlapped
,
1104 FSCTL_PIPE_TRANSCEIVE
,
1110 /* return FALSE in case of failure and pending operations! */
1111 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1113 SetLastErrorByStatus(Status
);
1117 if (lpBytesRead
!= NULL
)
1119 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1124 IO_STATUS_BLOCK Iosb
;
1126 Status
= NtFsControlFile(hNamedPipe
,
1131 FSCTL_PIPE_TRANSCEIVE
,
1137 /* wait in case operation is pending */
1138 if (Status
== STATUS_PENDING
)
1140 Status
= NtWaitForSingleObject(hNamedPipe
,
1143 if (NT_SUCCESS(Status
))
1145 Status
= Iosb
.Status
;
1149 if (NT_SUCCESS(Status
))
1151 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1152 check that case either and crashes (only after the operation
1154 *lpBytesRead
= Iosb
.Information
;
1158 SetLastErrorByStatus(Status
);