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 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
17 #include "../include/debug.h"
19 /* FUNCTIONS ****************************************************************/
25 CreateNamedPipeA(LPCSTR lpName
,
31 DWORD nDefaultTimeOut
,
32 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
34 HANDLE NamedPipeHandle
;
38 RtlInitAnsiString(&NameA
, (LPSTR
)lpName
);
39 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
41 NamedPipeHandle
= CreateNamedPipeW(NameU
.Buffer
,
48 lpSecurityAttributes
);
50 RtlFreeUnicodeString(&NameU
);
52 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
;
75 ULONG CreateOptions
= 0;
76 ULONG WriteModeMessage
;
77 ULONG ReadModeMessage
;
80 ULONG ShareAccess
= 0, Attributes
;
81 LARGE_INTEGER DefaultTimeOut
;
82 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
84 /* Check for valid instances */
85 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
88 SetLastError(ERROR_INVALID_PARAMETER
);
89 return INVALID_HANDLE_VALUE
;
92 /* Convert to NT syntax */
93 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
) nMaxInstances
= -1;
95 /* Convert the name */
96 Result
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpName
,
102 /* Conversion failed */
103 SetLastError(ERROR_PATH_NOT_FOUND
);
104 return(INVALID_HANDLE_VALUE
);
107 DPRINT1("Pipe name: %wZ\n", &NamedPipeName
);
108 DPRINT1("Pipe name: %S\n", NamedPipeName
.Buffer
);
110 /* Always case insensitive, check if we got extra attributes */
111 Attributes
= OBJ_CASE_INSENSITIVE
;
112 if(lpSecurityAttributes
)
114 /* We did; get the security descriptor */
115 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
117 /* And check if this is pipe's handle will beinheritable */
118 if(lpSecurityAttributes
->bInheritHandle
) Attributes
|= OBJ_INHERIT
;
121 /* Now we can initialize the object attributes */
122 InitializeObjectAttributes(&ObjectAttributes
,
128 /* Setup the default Desired Access */
129 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
131 ACCESS_SYSTEM_SECURITY
));
133 /* Convert to NT Create Flags */
134 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
136 CreateOptions
|= FILE_WRITE_THROUGH
;
138 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
140 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
143 /* Handle all open modes */
144 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
146 ShareAccess
|= FILE_SHARE_READ
;
147 DesiredAccess
|= GENERIC_WRITE
;
149 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
151 ShareAccess
|= FILE_SHARE_WRITE
;
152 DesiredAccess
|= GENERIC_READ
;
155 /* Handle the type flags */
156 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
158 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
162 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
165 /* Handle the mode flags */
166 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
168 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
172 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
175 /* Handle the blocking mode */
176 if (dwPipeMode
& PIPE_NOWAIT
)
178 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
182 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
185 /* Check if we have a timeout */
188 /* Convert the time to NT format */
189 DefaultTimeOut
.QuadPart
= UInt32x32To64(nDefaultTimeOut
, -10000);
193 /* Use default timeout of 50 ms */
194 DefaultTimeOut
.QuadPart
= -500000;
197 /* Now create the pipe */
198 Status
= NtCreateNamedPipeFile(&PipeHandle
,
214 RtlFreeUnicodeString(&NamedPipeName
);
217 if (!NT_SUCCESS(Status
))
219 /* Failed to create it */
220 DPRINT1("NtCreateNamedPipe failed (Status %x)!\n", Status
);
221 SetLastErrorByStatus (Status
);
222 return INVALID_HANDLE_VALUE
;
225 /* Return the handle */
234 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
238 UNICODE_STRING NameU
;
241 RtlInitAnsiString(&NameA
, (LPSTR
)lpNamedPipeName
);
242 RtlAnsiStringToUnicodeString(&NameU
, &NameA
, TRUE
);
244 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
246 RtlFreeUnicodeString(&NameU
);
252 * When NPFS will work properly, use this code instead. It is compatible with
253 * Microsoft's NPFS.SYS. The main difference is that:
254 * - This code actually respects the timeout instead of ignoring it!
255 * - This code validates and creates the proper names for both UNC and local pipes
256 * - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or
257 * \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the
258 * FILE_PIPE_WAIT_FOR_BUFFER structure.
260 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
266 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
269 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
274 OBJECT_ATTRIBUTES ObjectAttributes
;
277 IO_STATUS_BLOCK IoStatusBlock
;
278 ULONG WaitPipeInfoSize
;
279 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
281 /* Start by making a unicode string of the name */
282 DPRINT("Sent path: %S\n", lpNamedPipeName
);
283 RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
);
284 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
286 /* All slashes must become backslashes */
287 for (i
= 0; i
< NameLength
; i
++)
289 /* Check and convert */
290 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
293 /* Find the path type of the name we were given */
294 NewName
= NamedPipeName
;
295 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
297 /* Check if this was a device path, ie : "\\.\pipe\name" */
298 if (Type
== DEVICE_PATH
)
300 /* Make sure it's a valid prefix */
301 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
302 RtlPrefixString((PANSI_STRING
)&PipePrefix
, (PANSI_STRING
)&NewName
, TRUE
);
306 NewName
.Length
-= 9 * sizeof(WCHAR
);
308 /* Initialize the Dos Devices name */
309 DPRINT("NewName: %wZ\n", &NewName
);
310 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
312 else if (Type
== UNC_PATH
)
314 /* The path is \\server\\pipe\name; find the pipename itself */
315 p
= &NewName
.Buffer
[2];
317 /* First loop to get past the server name */
320 /* Check if this is a backslash */
321 if (*p
== L
'\\') break;
327 /* Now make sure the full name contains "pipe\" */
328 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\"))))
330 /* Get to the pipe name itself now */
331 p
+= sizeof("pipe\\") - 1;
335 /* The name is invalid */
336 DPRINT1("Invalid name!\n");
337 SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD
);
341 /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
345 DPRINT1("Invalid path type\n");
346 SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD
);
350 /* Initialize the object attributes */
351 DPRINT("Opening: %wZ\n", &DevicePath
);
352 InitializeObjectAttributes(&ObjectAttributes
,
354 OBJ_CASE_INSENSITIVE
,
359 Status
= NtOpenFile(&FileHandle
,
360 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
363 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
364 FILE_SYNCHRONOUS_IO_NONALERT
);
365 if (!NT_SUCCESS(Status
))
367 /* Fail; couldn't open */
368 DPRINT1("Status: %lx\n", Status
);
369 SetLastErrorByStatus(Status
);
370 RtlFreeUnicodeString(&NamedPipeName
);
374 /* Now calculate the total length of the structure and allocate it */
375 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
377 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
379 /* Check what timeout we got */
380 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
382 /* Don't use a timeout */
383 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
387 /* Check if we should wait forever */
388 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
391 WaitPipeInfo
->Timeout
.LowPart
= 0;
392 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
396 /* Convert to NT format */
397 WaitPipeInfo
->Timeout
.QuadPart
= UInt32x32To64(-10000, nTimeOut
);
400 /* In both cases, we do have a timeout */
401 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
404 /* Set the length and copy the name */
405 WaitPipeInfo
->NameLength
= NewName
.Length
;
406 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
408 /* Get rid of the full name */
409 RtlFreeUnicodeString(&NamedPipeName
);
411 /* Let NPFS know of our request */
412 Status
= NtFsControlFile(FileHandle
,
423 /* Free our pipe info data and close the handle */
424 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
427 /* Check the status */
428 if (!NT_SUCCESS(Status
))
430 /* Failure to wait on the pipe */
431 DPRINT1("Status: %lx\n", Status
);
432 SetLastErrorByStatus (Status
);
444 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
447 UNICODE_STRING NamedPipeName
;
450 OBJECT_ATTRIBUTES ObjectAttributes
;
451 FILE_PIPE_WAIT_FOR_BUFFER WaitPipe
;
453 IO_STATUS_BLOCK Iosb
;
455 r
= RtlDosPathNameToNtPathName_U((LPWSTR
)lpNamedPipeName
,
464 InitializeObjectAttributes(&ObjectAttributes
,
466 OBJ_CASE_INSENSITIVE
,
469 Status
= NtOpenFile(&FileHandle
,
470 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
473 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
474 FILE_SYNCHRONOUS_IO_NONALERT
);
475 if (!NT_SUCCESS(Status
))
477 SetLastErrorByStatus (Status
);
481 WaitPipe
.Timeout
.QuadPart
= nTimeOut
* -10000LL;
483 Status
= NtFsControlFile(FileHandle
,
494 if (!NT_SUCCESS(Status
))
496 SetLastErrorByStatus (Status
);
508 ConnectNamedPipe(IN HANDLE hNamedPipe
,
509 IN LPOVERLAPPED lpOverlapped
)
513 if (lpOverlapped
!= NULL
)
517 lpOverlapped
->Internal
= STATUS_PENDING
;
518 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
520 Status
= NtFsControlFile(hNamedPipe
,
521 lpOverlapped
->hEvent
,
524 (PIO_STATUS_BLOCK
)lpOverlapped
,
531 /* return FALSE in case of failure and pending operations! */
532 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
534 SetLastErrorByStatus(Status
);
540 IO_STATUS_BLOCK Iosb
;
542 Status
= NtFsControlFile(hNamedPipe
,
553 /* wait in case operation is pending */
554 if (Status
== STATUS_PENDING
)
556 Status
= NtWaitForSingleObject(hNamedPipe
,
559 if (NT_SUCCESS(Status
))
561 Status
= Iosb
.Status
;
565 if (!NT_SUCCESS(Status
))
567 SetLastErrorByStatus(Status
);
580 SetNamedPipeHandleState(HANDLE hNamedPipe
,
582 LPDWORD lpMaxCollectionCount
,
583 LPDWORD lpCollectDataTimeout
)
585 IO_STATUS_BLOCK Iosb
;
588 /* Check if the Mode is being changed */
591 FILE_PIPE_INFORMATION Settings
;
593 /* Set the Completion Mode */
594 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
595 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
597 /* Set the Read Mode */
598 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
599 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
601 /* Send the changes to the Driver */
602 Status
= NtSetInformationFile(hNamedPipe
,
605 sizeof(FILE_PIPE_INFORMATION
),
606 FilePipeInformation
);
607 if (!NT_SUCCESS(Status
))
609 SetLastErrorByStatus(Status
);
614 /* Check if the Collection count or Timeout are being changed */
615 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
617 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
619 /* Setting one without the other would delete it, so we read old one */
620 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
622 Status
= NtQueryInformationFile(hNamedPipe
,
625 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
626 FilePipeRemoteInformation
);
628 if (!NT_SUCCESS(Status
))
630 SetLastErrorByStatus(Status
);
635 /* Now set the new settings */
636 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
637 *lpMaxCollectionCount
:
638 RemoteSettings
.MaximumCollectionCount
;
639 if (lpCollectDataTimeout
)
641 /* Convert it to Quad */
642 RemoteSettings
.CollectDataTime
.QuadPart
= -(LONGLONG
)
644 *lpCollectDataTimeout
);
647 /* Tell the driver to change them */
648 Status
= NtSetInformationFile(hNamedPipe
,
651 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
652 FilePipeRemoteInformation
);
654 if (!NT_SUCCESS(Status
))
656 SetLastErrorByStatus(Status
);
669 CallNamedPipeA(LPCSTR lpNamedPipeName
,
673 DWORD nOutBufferSize
,
677 UNICODE_STRING PipeName
;
680 RtlCreateUnicodeStringFromAsciiz(&PipeName
,
681 (LPSTR
)lpNamedPipeName
);
683 Result
= CallNamedPipeW(PipeName
.Buffer
,
691 RtlFreeUnicodeString(&PipeName
);
701 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
705 DWORD nOutBufferSize
,
709 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
716 hPipe
= CreateFileW(lpNamedPipeName
,
717 GENERIC_READ
| GENERIC_WRITE
,
718 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
721 FILE_ATTRIBUTE_NORMAL
,
723 if (hPipe
!= INVALID_HANDLE_VALUE
)
729 WaitNamedPipeW(lpNamedPipeName
,
735 dwPipeMode
= PIPE_READMODE_MESSAGE
;
736 bError
= SetNamedPipeHandleState(hPipe
,
746 bError
= TransactNamedPipe(hPipe
,
763 DisconnectNamedPipe(HANDLE hNamedPipe
)
765 IO_STATUS_BLOCK Iosb
;
768 Status
= NtFsControlFile(hNamedPipe
,
773 FSCTL_PIPE_DISCONNECT
,
778 if (Status
== STATUS_PENDING
)
780 Status
= NtWaitForSingleObject(hNamedPipe
,
783 if (!NT_SUCCESS(Status
))
785 SetLastErrorByStatus(Status
);
790 if (!NT_SUCCESS(Status
))
792 SetLastErrorByStatus(Status
);
803 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
805 LPDWORD lpCurInstances
,
806 LPDWORD lpMaxCollectionCount
,
807 LPDWORD lpCollectDataTimeout
,
809 DWORD nMaxUserNameSize
)
811 IO_STATUS_BLOCK StatusBlock
;
816 FILE_PIPE_INFORMATION PipeInfo
;
818 Status
= NtQueryInformationFile(hNamedPipe
,
821 sizeof(FILE_PIPE_INFORMATION
),
822 FilePipeInformation
);
823 if (!NT_SUCCESS(Status
))
825 SetLastErrorByStatus(Status
);
829 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
830 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
833 if(lpCurInstances
!= NULL
)
835 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
837 Status
= NtQueryInformationFile(hNamedPipe
,
840 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
841 FilePipeLocalInformation
);
842 if(!NT_SUCCESS(Status
))
844 SetLastErrorByStatus(Status
);
848 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
851 if(lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
853 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
855 Status
= NtQueryInformationFile(hNamedPipe
,
858 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
859 FilePipeRemoteInformation
);
860 if(!NT_SUCCESS(Status
))
862 SetLastErrorByStatus(Status
);
866 if(lpMaxCollectionCount
!= NULL
)
868 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
871 if(lpCollectDataTimeout
!= NULL
)
874 *lpCollectDataTimeout
= 0;
878 if(lpUserName
!= NULL
)
880 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
881 retreive the user name with GetUserName(), revert the impersonation
882 and finally restore the thread token */
893 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
895 LPDWORD lpCurInstances
,
896 LPDWORD lpMaxCollectionCount
,
897 LPDWORD lpCollectDataTimeout
,
899 DWORD nMaxUserNameSize
)
901 UNICODE_STRING UserNameW
;
902 ANSI_STRING UserNameA
;
905 if(lpUserName
!= NULL
)
907 UserNameW
.Length
= 0;
908 UserNameW
.MaximumLength
= nMaxUserNameSize
* sizeof(WCHAR
);
909 UserNameW
.Buffer
= HeapAlloc(GetCurrentProcess(), 0, UserNameW
.MaximumLength
);
911 UserNameA
.Buffer
= lpUserName
;
912 UserNameA
.Length
= 0;
913 UserNameA
.MaximumLength
= nMaxUserNameSize
;
916 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
919 lpMaxCollectionCount
,
920 lpCollectDataTimeout
,
924 if(Ret
&& lpUserName
!= NULL
)
926 NTSTATUS Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
927 if(!NT_SUCCESS(Status
))
929 SetLastErrorByStatus(Status
);
934 if(UserNameW
.Buffer
!= NULL
)
936 HeapFree(GetCurrentProcess(), 0, UserNameW
.Buffer
);
947 GetNamedPipeInfo(HANDLE hNamedPipe
,
949 LPDWORD lpOutBufferSize
,
950 LPDWORD lpInBufferSize
,
951 LPDWORD lpMaxInstances
)
953 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
954 IO_STATUS_BLOCK StatusBlock
;
957 Status
= NtQueryInformationFile(hNamedPipe
,
959 &PipeLocalInformation
,
960 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
961 FilePipeLocalInformation
);
962 if (!NT_SUCCESS(Status
))
964 SetLastErrorByStatus(Status
);
970 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
971 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
974 if (lpOutBufferSize
!= NULL
)
975 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
977 if (lpInBufferSize
!= NULL
)
978 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
980 if (lpMaxInstances
!= NULL
)
982 if (PipeLocalInformation
.MaximumInstances
>= 255)
983 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
985 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
996 PeekNamedPipe(HANDLE hNamedPipe
,
1000 LPDWORD lpTotalBytesAvail
,
1001 LPDWORD lpBytesLeftThisMessage
)
1003 PFILE_PIPE_PEEK_BUFFER Buffer
;
1004 IO_STATUS_BLOCK Iosb
;
1008 BufferSize
= nBufferSize
+ sizeof(FILE_PIPE_PEEK_BUFFER
);
1009 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
1013 Status
= NtFsControlFile(hNamedPipe
,
1023 if (Status
== STATUS_PENDING
)
1025 Status
= NtWaitForSingleObject(hNamedPipe
,
1028 if (NT_SUCCESS(Status
))
1029 Status
= Iosb
.Status
;
1032 if (Status
== STATUS_BUFFER_OVERFLOW
)
1034 Status
= STATUS_SUCCESS
;
1037 if (!NT_SUCCESS(Status
))
1039 RtlFreeHeap(RtlGetProcessHeap(),
1042 SetLastErrorByStatus(Status
);
1046 if (lpTotalBytesAvail
!= NULL
)
1048 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1051 if (lpBytesRead
!= NULL
)
1053 *lpBytesRead
= Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
);
1056 if (lpBytesLeftThisMessage
!= NULL
)
1058 *lpBytesLeftThisMessage
= Buffer
->MessageLength
-
1059 (Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
));
1062 if (lpBuffer
!= NULL
)
1064 memcpy(lpBuffer
, Buffer
->Data
,
1065 min(nBufferSize
, Iosb
.Information
- sizeof(FILE_PIPE_PEEK_BUFFER
)));
1068 RtlFreeHeap(RtlGetProcessHeap(),
1080 TransactNamedPipe(IN HANDLE hNamedPipe
,
1081 IN LPVOID lpInBuffer
,
1082 IN DWORD nInBufferSize
,
1083 OUT LPVOID lpOutBuffer
,
1084 IN DWORD nOutBufferSize
,
1085 OUT LPDWORD lpBytesRead OPTIONAL
,
1086 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1090 if (lpBytesRead
!= NULL
)
1095 if (lpOverlapped
!= NULL
)
1099 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1100 lpOverlapped
->Internal
= STATUS_PENDING
;
1102 Status
= NtFsControlFile(hNamedPipe
,
1103 lpOverlapped
->hEvent
,
1106 (PIO_STATUS_BLOCK
)lpOverlapped
,
1107 FSCTL_PIPE_TRANSCEIVE
,
1113 /* return FALSE in case of failure and pending operations! */
1114 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1116 SetLastErrorByStatus(Status
);
1120 if (lpBytesRead
!= NULL
)
1122 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1127 IO_STATUS_BLOCK Iosb
;
1129 Status
= NtFsControlFile(hNamedPipe
,
1134 FSCTL_PIPE_TRANSCEIVE
,
1140 /* wait in case operation is pending */
1141 if (Status
== STATUS_PENDING
)
1143 Status
= NtWaitForSingleObject(hNamedPipe
,
1146 if (NT_SUCCESS(Status
))
1148 Status
= Iosb
.Status
;
1152 if (NT_SUCCESS(Status
))
1154 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1155 check that case either and crashes (only after the operation
1157 *lpBytesRead
= Iosb
.Information
;
1161 SetLastErrorByStatus(Status
);