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 DEBUG_CHANNEL(kernel32file
);
17 /* GLOBALS ********************************************************************/
21 /* FUNCTIONS ******************************************************************/
28 CreatePipe(PHANDLE hReadPipe
,
30 LPSECURITY_ATTRIBUTES lpPipeAttributes
,
34 UNICODE_STRING PipeName
;
35 OBJECT_ATTRIBUTES ObjectAttributes
;
36 IO_STATUS_BLOCK StatusBlock
;
37 LARGE_INTEGER DefaultTimeout
;
39 HANDLE ReadPipeHandle
;
40 HANDLE WritePipeHandle
;
43 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
45 /* Set the timeout to 120 seconds */
46 DefaultTimeout
.QuadPart
= -1200000000;
48 /* Use default buffer size if desired */
49 if (!nSize
) nSize
= 0x1000;
51 /* Increase the Pipe ID */
52 PipeId
= InterlockedIncrement(&ProcessPipeId
);
54 /* Create the pipe name */
56 L
"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
57 NtCurrentTeb()->ClientId
.UniqueProcess
,
59 RtlInitUnicodeString(&PipeName
, Buffer
);
61 /* Always use case insensitive */
62 Attributes
= OBJ_CASE_INSENSITIVE
;
64 /* Check if we got attributes */
67 /* Use the attributes' SD instead */
68 SecurityDescriptor
= lpPipeAttributes
->lpSecurityDescriptor
;
70 /* Set OBJ_INHERIT if requested */
71 if (lpPipeAttributes
->bInheritHandle
) Attributes
|= OBJ_INHERIT
;
74 /* Initialize the attributes */
75 InitializeObjectAttributes(&ObjectAttributes
,
81 /* Create the named pipe */
82 Status
= NtCreateNamedPipeFile(&ReadPipeHandle
,
83 GENERIC_READ
|FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
86 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
88 FILE_SYNCHRONOUS_IO_NONALERT
,
89 FILE_PIPE_BYTE_STREAM_TYPE
,
90 FILE_PIPE_BYTE_STREAM_MODE
,
91 FILE_PIPE_QUEUE_OPERATION
,
96 if (!NT_SUCCESS(Status
))
98 /* Convert error and fail */
99 WARN("Status: %lx\n", Status
);
100 BaseSetLastNTError(Status
);
104 /* Now try opening it for write access */
105 Status
= NtOpenFile(&WritePipeHandle
,
110 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
111 if (!NT_SUCCESS(Status
))
113 /* Convert error and fail */
114 WARN("Status: %lx\n", Status
);
115 NtClose(ReadPipeHandle
);
116 BaseSetLastNTError(Status
);
120 /* Return both handles */
121 *hReadPipe
= ReadPipeHandle
;
122 *hWritePipe
= WritePipeHandle
;
131 CreateNamedPipeA(LPCSTR lpName
,
135 DWORD nOutBufferSize
,
137 DWORD nDefaultTimeOut
,
138 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
140 /* Call the W(ide) function */
141 ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe
,
149 lpSecurityAttributes
);
158 CreateNamedPipeW(LPCWSTR lpName
,
162 DWORD nOutBufferSize
,
164 DWORD nDefaultTimeOut
,
165 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
167 UNICODE_STRING NamedPipeName
;
170 OBJECT_ATTRIBUTES ObjectAttributes
;
172 ACCESS_MASK DesiredAccess
;
173 ULONG CreateOptions
= 0;
174 ULONG WriteModeMessage
;
175 ULONG ReadModeMessage
;
177 IO_STATUS_BLOCK Iosb
;
178 ULONG ShareAccess
= 0, Attributes
;
179 LARGE_INTEGER DefaultTimeOut
;
180 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
182 /* Check for valid instances */
183 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
186 SetLastError(ERROR_INVALID_PARAMETER
);
187 return INVALID_HANDLE_VALUE
;
190 /* Convert to NT syntax */
191 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
)
194 /* Convert the name */
195 Result
= RtlDosPathNameToNtPathName_U(lpName
,
201 /* Conversion failed */
202 SetLastError(ERROR_PATH_NOT_FOUND
);
203 return INVALID_HANDLE_VALUE
;
206 TRACE("Pipe name: %wZ\n", &NamedPipeName
);
207 TRACE("Pipe name: %S\n", NamedPipeName
.Buffer
);
209 /* Always case insensitive, check if we got extra attributes */
210 Attributes
= OBJ_CASE_INSENSITIVE
;
211 if(lpSecurityAttributes
)
213 /* We did; get the security descriptor */
214 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
216 /* And check if this is pipe's handle will beinheritable */
217 if (lpSecurityAttributes
->bInheritHandle
)
218 Attributes
|= OBJ_INHERIT
;
221 /* Now we can initialize the object attributes */
222 InitializeObjectAttributes(&ObjectAttributes
,
228 /* Setup the default Desired Access */
229 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
231 ACCESS_SYSTEM_SECURITY
));
233 /* Convert to NT Create Flags */
234 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
236 CreateOptions
|= FILE_WRITE_THROUGH
;
239 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
241 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
244 /* Handle all open modes */
245 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
247 ShareAccess
|= FILE_SHARE_READ
;
248 DesiredAccess
|= GENERIC_WRITE
;
251 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
253 ShareAccess
|= FILE_SHARE_WRITE
;
254 DesiredAccess
|= GENERIC_READ
;
257 /* Handle the type flags */
258 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
260 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
264 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
267 /* Handle the mode flags */
268 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
270 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
274 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
277 /* Handle the blocking mode */
278 if (dwPipeMode
& PIPE_NOWAIT
)
280 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
284 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
287 /* Check if we have a timeout */
290 /* Convert the time to NT format */
291 DefaultTimeOut
.QuadPart
= UInt32x32To64(nDefaultTimeOut
, -10000);
295 /* Use default timeout of 50 ms */
296 DefaultTimeOut
.QuadPart
= -500000;
299 /* Now create the pipe */
300 Status
= NtCreateNamedPipeFile(&PipeHandle
,
315 /* Normalize special error codes */
316 if ((Status
== STATUS_INVALID_DEVICE_REQUEST
) ||
317 (Status
== STATUS_NOT_SUPPORTED
))
319 Status
= STATUS_OBJECT_NAME_INVALID
;
323 RtlFreeHeap(RtlGetProcessHeap(),
325 NamedPipeName
.Buffer
);
328 if (!NT_SUCCESS(Status
))
330 /* Failed to create it */
331 WARN("NtCreateNamedPipe failed (Status %x)!\n", Status
);
332 BaseSetLastNTError (Status
);
333 return INVALID_HANDLE_VALUE
;
336 /* Return the handle */
346 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
350 UNICODE_STRING NameU
;
352 /* Convert the name to Unicode */
353 Basep8BitStringToDynamicUnicodeString(&NameU
, lpNamedPipeName
);
355 /* Call the Unicode API */
356 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
358 /* Free the Unicode string */
359 RtlFreeUnicodeString(&NameU
);
370 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
373 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
378 OBJECT_ATTRIBUTES ObjectAttributes
;
381 IO_STATUS_BLOCK IoStatusBlock
;
382 ULONG WaitPipeInfoSize
;
383 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
385 /* Start by making a unicode string of the name */
386 TRACE("Sent path: %S\n", lpNamedPipeName
);
387 RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
);
388 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
390 /* All slashes must become backslashes */
391 for (i
= 0; i
< NameLength
; i
++)
393 /* Check and convert */
394 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
397 /* Find the path type of the name we were given */
398 NewName
= NamedPipeName
;
399 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
401 /* Check if this was a device path, ie : "\\.\pipe\name" */
402 if (Type
== RtlPathTypeLocalDevice
)
404 /* Make sure it's a valid prefix */
405 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
406 RtlPrefixString((PANSI_STRING
)&PipePrefix
, (PANSI_STRING
)&NewName
, TRUE
);
410 NewName
.Length
-= 9 * sizeof(WCHAR
);
412 /* Initialize the Dos Devices name */
413 TRACE("NewName: %wZ\n", &NewName
);
414 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
416 else if (Type
== RtlPathTypeRootLocalDevice
)
418 /* The path is \\server\\pipe\name; find the pipename itself */
419 p
= &NewName
.Buffer
[2];
421 /* First loop to get past the server name */
424 /* Check if this is a backslash */
425 if (*p
== L
'\\') break;
431 /* Now make sure the full name contains "pipe\" */
432 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\"))))
434 /* Get to the pipe name itself now */
435 p
+= sizeof("pipe\\") - 1;
439 /* The name is invalid */
440 WARN("Invalid name!\n");
441 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
445 /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
449 WARN("Invalid path type\n");
450 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
454 /* Now calculate the total length of the structure and allocate it */
455 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
457 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
458 if (WaitPipeInfo
== NULL
)
460 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
464 /* Initialize the object attributes */
465 TRACE("Opening: %wZ\n", &DevicePath
);
466 InitializeObjectAttributes(&ObjectAttributes
,
468 OBJ_CASE_INSENSITIVE
,
473 Status
= NtOpenFile(&FileHandle
,
474 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
477 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
478 FILE_SYNCHRONOUS_IO_NONALERT
);
479 if (!NT_SUCCESS(Status
))
481 /* Fail; couldn't open */
482 WARN("Status: %lx\n", Status
);
483 BaseSetLastNTError(Status
);
484 RtlFreeUnicodeString(&NamedPipeName
);
485 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
489 /* Check what timeout we got */
490 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
492 /* Don't use a timeout */
493 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
497 /* Check if we should wait forever */
498 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
501 WaitPipeInfo
->Timeout
.LowPart
= 0;
502 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
506 /* Convert to NT format */
507 WaitPipeInfo
->Timeout
.QuadPart
= UInt32x32To64(-10000, nTimeOut
);
510 /* In both cases, we do have a timeout */
511 WaitPipeInfo
->TimeoutSpecified
= TRUE
;
514 /* Set the length and copy the name */
515 WaitPipeInfo
->NameLength
= NewName
.Length
;
516 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
518 /* Get rid of the full name */
519 RtlFreeUnicodeString(&NamedPipeName
);
521 /* Let NPFS know of our request */
522 Status
= NtFsControlFile(FileHandle
,
533 /* Free our pipe info data and close the handle */
534 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
537 /* Check the status */
538 if (!NT_SUCCESS(Status
))
540 /* Failure to wait on the pipe */
541 WARN("Status: %lx\n", Status
);
542 BaseSetLastNTError (Status
);
555 ConnectNamedPipe(IN HANDLE hNamedPipe
,
556 IN LPOVERLAPPED lpOverlapped
)
560 if (lpOverlapped
!= NULL
)
564 lpOverlapped
->Internal
= STATUS_PENDING
;
565 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
567 Status
= NtFsControlFile(hNamedPipe
,
568 lpOverlapped
->hEvent
,
571 (PIO_STATUS_BLOCK
)lpOverlapped
,
578 /* return FALSE in case of failure and pending operations! */
579 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
581 BaseSetLastNTError(Status
);
587 IO_STATUS_BLOCK Iosb
;
589 Status
= NtFsControlFile(hNamedPipe
,
600 /* wait in case operation is pending */
601 if (Status
== STATUS_PENDING
)
603 Status
= NtWaitForSingleObject(hNamedPipe
,
606 if (NT_SUCCESS(Status
))
608 Status
= Iosb
.Status
;
612 if (!NT_SUCCESS(Status
))
614 BaseSetLastNTError(Status
);
628 SetNamedPipeHandleState(HANDLE hNamedPipe
,
630 LPDWORD lpMaxCollectionCount
,
631 LPDWORD lpCollectDataTimeout
)
633 IO_STATUS_BLOCK Iosb
;
636 /* Check if the Mode is being changed */
639 FILE_PIPE_INFORMATION Settings
;
641 /* Set the Completion Mode */
642 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
643 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
645 /* Set the Read Mode */
646 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
647 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
649 /* Send the changes to the Driver */
650 Status
= NtSetInformationFile(hNamedPipe
,
653 sizeof(FILE_PIPE_INFORMATION
),
654 FilePipeInformation
);
655 if (!NT_SUCCESS(Status
))
657 BaseSetLastNTError(Status
);
662 /* Check if the Collection count or Timeout are being changed */
663 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
665 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
667 /* Setting one without the other would delete it, so we read old one */
668 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
670 Status
= NtQueryInformationFile(hNamedPipe
,
673 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
674 FilePipeRemoteInformation
);
675 if (!NT_SUCCESS(Status
))
677 BaseSetLastNTError(Status
);
682 /* Now set the new settings */
683 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
684 *lpMaxCollectionCount
:
685 RemoteSettings
.MaximumCollectionCount
;
686 if (lpCollectDataTimeout
)
688 /* Convert it to Quad */
689 RemoteSettings
.CollectDataTime
.QuadPart
=
690 -(LONGLONG
)UInt32x32To64(10000, *lpCollectDataTimeout
);
693 /* Tell the driver to change them */
694 Status
= NtSetInformationFile(hNamedPipe
,
697 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
698 FilePipeRemoteInformation
);
699 if (!NT_SUCCESS(Status
))
701 BaseSetLastNTError(Status
);
715 CallNamedPipeA(LPCSTR lpNamedPipeName
,
719 DWORD nOutBufferSize
,
723 PUNICODE_STRING PipeName
= &NtCurrentTeb()->StaticUnicodeString
;
724 ANSI_STRING AnsiPipe
;
726 /* Initialize the string as ANSI_STRING and convert to Unicode */
727 RtlInitAnsiString(&AnsiPipe
, (LPSTR
)lpNamedPipeName
);
728 RtlAnsiStringToUnicodeString(PipeName
, &AnsiPipe
, FALSE
);
730 /* Call the Unicode function */
731 return CallNamedPipeW(PipeName
->Buffer
,
746 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
750 DWORD nOutBufferSize
,
761 /* Try creating it */
762 hPipe
= CreateFileW(lpNamedPipeName
,
763 GENERIC_READ
| GENERIC_WRITE
,
764 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
767 FILE_ATTRIBUTE_NORMAL
,
770 /* Success, break out */
771 if (hPipe
!= INVALID_HANDLE_VALUE
)
774 /* Already tried twice, give up */
779 WaitNamedPipeW(lpNamedPipeName
, nTimeOut
);
781 /* Get ready to try again */
785 /* Set the pipe mode */
786 dwPipeMode
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
787 bError
= SetNamedPipeHandleState(hPipe
, &dwPipeMode
, NULL
, NULL
);
790 /* Couldn't change state, fail */
795 /* Do the transact */
796 bError
= TransactNamedPipe(hPipe
,
804 /* Close the handle */
816 DisconnectNamedPipe(HANDLE hNamedPipe
)
818 IO_STATUS_BLOCK Iosb
;
821 /* Send the FSCTL to the driver */
822 Status
= NtFsControlFile(hNamedPipe
,
827 FSCTL_PIPE_DISCONNECT
,
832 if (Status
== STATUS_PENDING
)
834 /* Wait on NPFS to finish and get updated status */
835 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
836 if (NT_SUCCESS(Status
))
837 Status
= Iosb
.Status
;
840 /* Check for error */
841 if (!NT_SUCCESS(Status
))
844 BaseSetLastNTError(Status
);
857 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
859 LPDWORD lpCurInstances
,
860 LPDWORD lpMaxCollectionCount
,
861 LPDWORD lpCollectDataTimeout
,
863 DWORD nMaxUserNameSize
)
865 IO_STATUS_BLOCK StatusBlock
;
870 FILE_PIPE_INFORMATION PipeInfo
;
872 Status
= NtQueryInformationFile(hNamedPipe
,
875 sizeof(FILE_PIPE_INFORMATION
),
876 FilePipeInformation
);
877 if (!NT_SUCCESS(Status
))
879 BaseSetLastNTError(Status
);
883 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
884 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
887 if(lpCurInstances
!= NULL
)
889 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
891 Status
= NtQueryInformationFile(hNamedPipe
,
894 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
895 FilePipeLocalInformation
);
896 if (!NT_SUCCESS(Status
))
898 BaseSetLastNTError(Status
);
902 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
905 if (lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
907 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
909 Status
= NtQueryInformationFile(hNamedPipe
,
912 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
913 FilePipeRemoteInformation
);
914 if (!NT_SUCCESS(Status
))
916 BaseSetLastNTError(Status
);
920 if (lpMaxCollectionCount
!= NULL
)
922 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
925 if(lpCollectDataTimeout
!= NULL
)
928 *lpCollectDataTimeout
= 0;
932 if (lpUserName
!= NULL
)
934 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
935 retreive the user name with GetUserName(), revert the impersonation
936 and finally restore the thread token */
948 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
950 LPDWORD lpCurInstances
,
951 LPDWORD lpMaxCollectionCount
,
952 LPDWORD lpCollectDataTimeout
,
954 DWORD nMaxUserNameSize
)
956 UNICODE_STRING UserNameW
= { 0, 0, NULL
};
957 ANSI_STRING UserNameA
;
960 if(lpUserName
!= NULL
)
962 UserNameW
.MaximumLength
= (USHORT
)nMaxUserNameSize
* sizeof(WCHAR
);
963 UserNameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW
.MaximumLength
);
964 if (UserNameW
.Buffer
== NULL
)
966 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
970 UserNameA
.Buffer
= lpUserName
;
971 UserNameA
.Length
= 0;
972 UserNameA
.MaximumLength
= (USHORT
)nMaxUserNameSize
;
975 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
978 lpMaxCollectionCount
,
979 lpCollectDataTimeout
,
982 if (Ret
&& lpUserName
!= NULL
)
986 RtlInitUnicodeString(&UserNameW
, UserNameW
.Buffer
);
987 Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
988 if (!NT_SUCCESS(Status
))
990 BaseSetLastNTError(Status
);
995 if (UserNameW
.Buffer
!= NULL
)
997 RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW
.Buffer
);
1009 GetNamedPipeInfo(HANDLE hNamedPipe
,
1011 LPDWORD lpOutBufferSize
,
1012 LPDWORD lpInBufferSize
,
1013 LPDWORD lpMaxInstances
)
1015 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
1016 IO_STATUS_BLOCK StatusBlock
;
1019 Status
= NtQueryInformationFile(hNamedPipe
,
1021 &PipeLocalInformation
,
1022 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
1023 FilePipeLocalInformation
);
1024 if (!NT_SUCCESS(Status
))
1026 BaseSetLastNTError(Status
);
1030 if (lpFlags
!= NULL
)
1032 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
1033 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
1036 if (lpOutBufferSize
!= NULL
)
1037 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
1039 if (lpInBufferSize
!= NULL
)
1040 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
1042 if (lpMaxInstances
!= NULL
)
1044 if (PipeLocalInformation
.MaximumInstances
>= 255)
1045 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
1047 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
1059 PeekNamedPipe(HANDLE hNamedPipe
,
1062 LPDWORD lpBytesRead
,
1063 LPDWORD lpTotalBytesAvail
,
1064 LPDWORD lpBytesLeftThisMessage
)
1066 PFILE_PIPE_PEEK_BUFFER Buffer
;
1067 IO_STATUS_BLOCK Iosb
;
1072 /* Calculate the buffer space that we'll need and allocate it */
1073 BufferSize
= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[nBufferSize
]);
1074 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
1077 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1081 /* Tell the driver to seek */
1082 Status
= NtFsControlFile(hNamedPipe
,
1092 if (Status
== STATUS_PENDING
)
1094 /* Wait for npfs to be done, and update the status */
1095 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
1096 if (NT_SUCCESS(Status
))
1097 Status
= Iosb
.Status
;
1100 /* Overflow is success for us */
1101 if (Status
== STATUS_BUFFER_OVERFLOW
)
1102 Status
= STATUS_SUCCESS
;
1105 if (!NT_SUCCESS(Status
))
1107 /* Free the buffer and return failure */
1108 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1109 BaseSetLastNTError(Status
);
1113 /* Check if caller requested bytes available */
1114 if (lpTotalBytesAvail
)
1116 /* Return bytes available */
1117 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1120 /* Calculate the bytes returned, minus our structure overhead */
1121 BytesRead
= (ULONG
)(Iosb
.Information
-
1122 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[0]));
1123 ASSERT(BytesRead
<= nBufferSize
);
1125 /* Check if caller requested bytes read */
1128 /* Return the bytes read */
1129 *lpBytesRead
= BytesRead
;
1132 /* Check if caller requested bytes left */
1133 if (lpBytesLeftThisMessage
)
1135 /* Calculate total minus what we returned and our structure overhead */
1136 *lpBytesLeftThisMessage
= Buffer
->MessageLength
- BytesRead
;
1139 /* Check if the caller wanted to see the actual data */
1142 /* Give him what he wants */
1143 RtlCopyMemory(lpBuffer
,
1148 /* Free the buffer */
1149 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1160 TransactNamedPipe(IN HANDLE hNamedPipe
,
1161 IN LPVOID lpInBuffer
,
1162 IN DWORD nInBufferSize
,
1163 OUT LPVOID lpOutBuffer
,
1164 IN DWORD nOutBufferSize
,
1165 OUT LPDWORD lpBytesRead OPTIONAL
,
1166 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1170 if (lpBytesRead
!= NULL
)
1175 if (lpOverlapped
!= NULL
)
1179 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1180 lpOverlapped
->Internal
= STATUS_PENDING
;
1182 Status
= NtFsControlFile(hNamedPipe
,
1183 lpOverlapped
->hEvent
,
1186 (PIO_STATUS_BLOCK
)lpOverlapped
,
1187 FSCTL_PIPE_TRANSCEIVE
,
1192 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1194 BaseSetLastNTError(Status
);
1198 if (lpBytesRead
!= NULL
)
1200 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1205 #if 0 /* We don't implement FSCTL_PIPE_TRANSCEIVE yet */
1206 IO_STATUS_BLOCK Iosb
;
1208 Status
= NtFsControlFile(hNamedPipe
,
1213 FSCTL_PIPE_TRANSCEIVE
,
1218 if (Status
== STATUS_PENDING
)
1220 Status
= NtWaitForSingleObject(hNamedPipe
,
1223 if (NT_SUCCESS(Status
))
1224 Status
= Iosb
.Status
;
1227 if (NT_SUCCESS(Status
))
1229 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1230 check that case either and crashes (only after the operation
1232 *lpBytesRead
= Iosb
.Information
;
1236 BaseSetLastNTError(Status
);
1239 #else /* Workaround while FSCTL_PIPE_TRANSCEIVE not available */
1242 while (0 != nInBufferSize
&&
1243 WriteFile(hNamedPipe
, lpInBuffer
, nInBufferSize
, &nActualBytes
,
1246 lpInBuffer
= (LPVOID
)((char *) lpInBuffer
+ nActualBytes
);
1247 nInBufferSize
-= nActualBytes
;
1250 if (0 != nInBufferSize
)
1252 /* Must have dropped out of the while 'cause WriteFile failed */
1256 if (!ReadFile(hNamedPipe
, lpOutBuffer
, nOutBufferSize
, &nActualBytes
,
1262 if (NULL
!= lpBytesRead
)
1264 *lpBytesRead
= nActualBytes
;