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
);
157 CreateNamedPipeW(LPCWSTR lpName
,
161 DWORD nOutBufferSize
,
163 DWORD nDefaultTimeOut
,
164 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
166 UNICODE_STRING NamedPipeName
;
169 OBJECT_ATTRIBUTES ObjectAttributes
;
171 ACCESS_MASK DesiredAccess
;
172 ULONG CreateOptions
= 0;
173 ULONG WriteModeMessage
;
174 ULONG ReadModeMessage
;
176 IO_STATUS_BLOCK Iosb
;
177 ULONG ShareAccess
= 0, Attributes
;
178 LARGE_INTEGER DefaultTimeOut
;
179 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
181 /* Check for valid instances */
182 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
185 SetLastError(ERROR_INVALID_PARAMETER
);
186 return INVALID_HANDLE_VALUE
;
189 /* Convert to NT syntax */
190 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
)
193 /* Convert the name */
194 Result
= RtlDosPathNameToNtPathName_U(lpName
,
200 /* Conversion failed */
201 SetLastError(ERROR_PATH_NOT_FOUND
);
202 return INVALID_HANDLE_VALUE
;
205 TRACE("Pipe name: %wZ\n", &NamedPipeName
);
206 TRACE("Pipe name: %S\n", NamedPipeName
.Buffer
);
208 /* Always case insensitive, check if we got extra attributes */
209 Attributes
= OBJ_CASE_INSENSITIVE
;
210 if(lpSecurityAttributes
)
212 /* We did; get the security descriptor */
213 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
215 /* And check if this is pipe's handle will beinheritable */
216 if (lpSecurityAttributes
->bInheritHandle
)
217 Attributes
|= OBJ_INHERIT
;
220 /* Now we can initialize the object attributes */
221 InitializeObjectAttributes(&ObjectAttributes
,
227 /* Setup the default Desired Access */
228 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
230 ACCESS_SYSTEM_SECURITY
));
232 /* Convert to NT Create Flags */
233 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
235 CreateOptions
|= FILE_WRITE_THROUGH
;
238 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
240 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
243 /* Handle all open modes */
244 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
246 ShareAccess
|= FILE_SHARE_READ
;
247 DesiredAccess
|= GENERIC_WRITE
;
250 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
252 ShareAccess
|= FILE_SHARE_WRITE
;
253 DesiredAccess
|= GENERIC_READ
;
256 /* Handle the type flags */
257 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
259 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
263 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
266 /* Handle the mode flags */
267 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
269 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
273 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
276 /* Handle the blocking mode */
277 if (dwPipeMode
& PIPE_NOWAIT
)
279 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
283 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
286 /* Check if we have a timeout */
289 /* Convert the time to NT format */
290 DefaultTimeOut
.QuadPart
= UInt32x32To64(nDefaultTimeOut
, -10000);
294 /* Use default timeout of 50 ms */
295 DefaultTimeOut
.QuadPart
= -500000;
298 /* Now create the pipe */
299 Status
= NtCreateNamedPipeFile(&PipeHandle
,
314 /* Normalize special error codes */
315 if ((Status
== STATUS_INVALID_DEVICE_REQUEST
) ||
316 (Status
== STATUS_NOT_SUPPORTED
))
318 Status
= STATUS_OBJECT_NAME_INVALID
;
322 RtlFreeHeap(RtlGetProcessHeap(),
324 NamedPipeName
.Buffer
);
327 if (!NT_SUCCESS(Status
))
329 /* Failed to create it */
330 WARN("NtCreateNamedPipe failed (Status %x)!\n", Status
);
331 BaseSetLastNTError (Status
);
332 return INVALID_HANDLE_VALUE
;
335 /* Return the handle */
344 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
348 UNICODE_STRING NameU
;
350 /* Convert the name to Unicode */
351 Basep8BitStringToDynamicUnicodeString(&NameU
, lpNamedPipeName
);
353 /* Call the Unicode API */
354 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
356 /* Free the Unicode string */
357 RtlFreeUnicodeString(&NameU
);
368 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
371 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
376 OBJECT_ATTRIBUTES ObjectAttributes
;
379 IO_STATUS_BLOCK IoStatusBlock
;
380 ULONG WaitPipeInfoSize
;
381 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
383 /* Start by making a unicode string of the name */
384 TRACE("Sent path: %S\n", lpNamedPipeName
);
385 if (!RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
))
387 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
390 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
392 /* All slashes must become backslashes */
393 for (i
= 0; i
< NameLength
; i
++)
395 /* Check and convert */
396 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
399 /* Find the path type of the name we were given */
400 NewName
= NamedPipeName
;
401 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
403 /* Check if this was a device path, ie : "\\.\pipe\name" */
404 if (Type
== RtlPathTypeLocalDevice
)
406 /* Make sure it's a valid prefix */
407 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
408 if (!RtlPrefixUnicodeString(&PipePrefix
, &NewName
, TRUE
))
410 /* The name is invalid */
411 WARN("Invalid name!\n");
412 RtlFreeUnicodeString(&NamedPipeName
);
413 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
418 NewName
.Buffer
+= PipePrefix
.Length
/ sizeof(WCHAR
);
419 NewName
.Length
-= PipePrefix
.Length
;
420 NewName
.MaximumLength
-= PipePrefix
.Length
;
422 /* Initialize the Dos Devices name */
423 TRACE("NewName: %wZ\n", &NewName
);
424 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
426 else if (Type
== RtlPathTypeUncAbsolute
)
428 /* The path is \\server\\pipe\name; find the pipename itself */
429 p
= &NewName
.Buffer
[2];
431 /* First loop to get past the server name */
434 /* Check if this is a backslash */
435 if (*p
== L
'\\') break;
441 /* Now make sure the full name contains "pipe\" */
442 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL
))))
444 /* Get to the pipe name itself now */
445 p
+= sizeof("pipe\\") - sizeof(ANSI_NULL
);
449 /* The name is invalid */
450 WARN("Invalid name!\n");
451 RtlFreeUnicodeString(&NamedPipeName
);
452 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
456 /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
460 WARN("Invalid path type\n");
461 RtlFreeUnicodeString(&NamedPipeName
);
462 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
466 /* Now calculate the total length of the structure and allocate it */
467 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
469 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
470 if (WaitPipeInfo
== NULL
)
472 RtlFreeUnicodeString(&NamedPipeName
);
473 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
477 /* Initialize the object attributes */
478 TRACE("Opening: %wZ\n", &DevicePath
);
479 InitializeObjectAttributes(&ObjectAttributes
,
481 OBJ_CASE_INSENSITIVE
,
486 Status
= NtOpenFile(&FileHandle
,
487 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
490 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
491 FILE_SYNCHRONOUS_IO_NONALERT
);
492 if (!NT_SUCCESS(Status
))
494 /* Fail; couldn't open */
495 WARN("Status: %lx\n", Status
);
496 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
497 RtlFreeUnicodeString(&NamedPipeName
);
498 BaseSetLastNTError(Status
);
502 /* Check what timeout we got */
503 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
505 /* Don't use a timeout */
506 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
510 /* Check if we should wait forever */
511 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
514 WaitPipeInfo
->Timeout
.LowPart
= 0;
515 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
519 /* Convert to NT format */
520 WaitPipeInfo
->Timeout
.QuadPart
= UInt32x32To64(-10000, nTimeOut
);
523 /* In both cases, we do have a timeout */
524 WaitPipeInfo
->TimeoutSpecified
= TRUE
;
527 /* Set the length and copy the name */
528 WaitPipeInfo
->NameLength
= NewName
.Length
;
529 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
531 /* Get rid of the full name */
532 RtlFreeUnicodeString(&NamedPipeName
);
534 /* Let NPFS know of our request */
535 Status
= NtFsControlFile(FileHandle
,
546 /* Free our pipe info data and close the handle */
547 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
550 /* Check the status */
551 if (!NT_SUCCESS(Status
))
553 /* Failure to wait on the pipe */
554 WARN("Status: %lx\n", Status
);
555 BaseSetLastNTError(Status
);
568 ConnectNamedPipe(IN HANDLE hNamedPipe
,
569 IN LPOVERLAPPED lpOverlapped
)
573 if (lpOverlapped
!= NULL
)
577 lpOverlapped
->Internal
= STATUS_PENDING
;
578 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
580 Status
= NtFsControlFile(hNamedPipe
,
581 lpOverlapped
->hEvent
,
584 (PIO_STATUS_BLOCK
)lpOverlapped
,
591 /* return FALSE in case of failure and pending operations! */
592 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
594 BaseSetLastNTError(Status
);
600 IO_STATUS_BLOCK Iosb
;
602 Status
= NtFsControlFile(hNamedPipe
,
613 /* wait in case operation is pending */
614 if (Status
== STATUS_PENDING
)
616 Status
= NtWaitForSingleObject(hNamedPipe
,
619 if (NT_SUCCESS(Status
))
621 Status
= Iosb
.Status
;
625 if (!NT_SUCCESS(Status
))
627 BaseSetLastNTError(Status
);
641 SetNamedPipeHandleState(HANDLE hNamedPipe
,
643 LPDWORD lpMaxCollectionCount
,
644 LPDWORD lpCollectDataTimeout
)
646 IO_STATUS_BLOCK Iosb
;
649 /* Check if the Mode is being changed */
652 FILE_PIPE_INFORMATION Settings
;
654 /* Set the Completion Mode */
655 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
656 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
658 /* Set the Read Mode */
659 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
660 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
662 /* Send the changes to the Driver */
663 Status
= NtSetInformationFile(hNamedPipe
,
666 sizeof(FILE_PIPE_INFORMATION
),
667 FilePipeInformation
);
668 if (!NT_SUCCESS(Status
))
670 BaseSetLastNTError(Status
);
675 /* Check if the Collection count or Timeout are being changed */
676 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
678 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
680 /* Setting one without the other would delete it, so we read old one */
681 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
683 Status
= NtQueryInformationFile(hNamedPipe
,
686 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
687 FilePipeRemoteInformation
);
688 if (!NT_SUCCESS(Status
))
690 BaseSetLastNTError(Status
);
695 /* Now set the new settings */
696 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
697 *lpMaxCollectionCount
:
698 RemoteSettings
.MaximumCollectionCount
;
699 if (lpCollectDataTimeout
)
701 /* Convert it to Quad */
702 RemoteSettings
.CollectDataTime
.QuadPart
=
703 -(LONGLONG
)UInt32x32To64(10000, *lpCollectDataTimeout
);
706 /* Tell the driver to change them */
707 Status
= NtSetInformationFile(hNamedPipe
,
710 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
711 FilePipeRemoteInformation
);
712 if (!NT_SUCCESS(Status
))
714 BaseSetLastNTError(Status
);
728 CallNamedPipeA(LPCSTR lpNamedPipeName
,
732 DWORD nOutBufferSize
,
736 PUNICODE_STRING PipeName
= &NtCurrentTeb()->StaticUnicodeString
;
737 ANSI_STRING AnsiPipe
;
739 /* Initialize the string as ANSI_STRING and convert to Unicode */
740 RtlInitAnsiString(&AnsiPipe
, (LPSTR
)lpNamedPipeName
);
741 RtlAnsiStringToUnicodeString(PipeName
, &AnsiPipe
, FALSE
);
743 /* Call the Unicode function */
744 return CallNamedPipeW(PipeName
->Buffer
,
759 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
763 DWORD nOutBufferSize
,
774 /* Try creating it */
775 hPipe
= CreateFileW(lpNamedPipeName
,
776 GENERIC_READ
| GENERIC_WRITE
,
777 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
780 FILE_ATTRIBUTE_NORMAL
,
783 /* Success, break out */
784 if (hPipe
!= INVALID_HANDLE_VALUE
)
787 /* Already tried twice, give up */
792 WaitNamedPipeW(lpNamedPipeName
, nTimeOut
);
794 /* Get ready to try again */
798 /* Set the pipe mode */
799 dwPipeMode
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
800 bError
= SetNamedPipeHandleState(hPipe
, &dwPipeMode
, NULL
, NULL
);
803 /* Couldn't change state, fail */
808 /* Do the transact */
809 bError
= TransactNamedPipe(hPipe
,
817 /* Close the handle */
829 DisconnectNamedPipe(HANDLE hNamedPipe
)
831 IO_STATUS_BLOCK Iosb
;
834 /* Send the FSCTL to the driver */
835 Status
= NtFsControlFile(hNamedPipe
,
840 FSCTL_PIPE_DISCONNECT
,
845 if (Status
== STATUS_PENDING
)
847 /* Wait on NPFS to finish and get updated status */
848 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
849 if (NT_SUCCESS(Status
))
850 Status
= Iosb
.Status
;
853 /* Check for error */
854 if (!NT_SUCCESS(Status
))
857 BaseSetLastNTError(Status
);
870 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
872 LPDWORD lpCurInstances
,
873 LPDWORD lpMaxCollectionCount
,
874 LPDWORD lpCollectDataTimeout
,
876 DWORD nMaxUserNameSize
)
878 IO_STATUS_BLOCK StatusBlock
;
883 FILE_PIPE_INFORMATION PipeInfo
;
885 Status
= NtQueryInformationFile(hNamedPipe
,
888 sizeof(FILE_PIPE_INFORMATION
),
889 FilePipeInformation
);
890 if (!NT_SUCCESS(Status
))
892 BaseSetLastNTError(Status
);
896 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
897 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
900 if(lpCurInstances
!= NULL
)
902 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
904 Status
= NtQueryInformationFile(hNamedPipe
,
907 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
908 FilePipeLocalInformation
);
909 if (!NT_SUCCESS(Status
))
911 BaseSetLastNTError(Status
);
915 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
918 if (lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
920 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
922 Status
= NtQueryInformationFile(hNamedPipe
,
925 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
926 FilePipeRemoteInformation
);
927 if (!NT_SUCCESS(Status
))
929 BaseSetLastNTError(Status
);
933 if (lpMaxCollectionCount
!= NULL
)
935 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
938 if(lpCollectDataTimeout
!= NULL
)
941 *lpCollectDataTimeout
= 0;
945 if (lpUserName
!= NULL
)
947 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
948 retreive the user name with GetUserName(), revert the impersonation
949 and finally restore the thread token */
961 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
963 LPDWORD lpCurInstances
,
964 LPDWORD lpMaxCollectionCount
,
965 LPDWORD lpCollectDataTimeout
,
967 DWORD nMaxUserNameSize
)
969 UNICODE_STRING UserNameW
= { 0, 0, NULL
};
970 ANSI_STRING UserNameA
;
973 if(lpUserName
!= NULL
)
975 UserNameW
.MaximumLength
= (USHORT
)nMaxUserNameSize
* sizeof(WCHAR
);
976 UserNameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW
.MaximumLength
);
977 if (UserNameW
.Buffer
== NULL
)
979 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
983 UserNameA
.Buffer
= lpUserName
;
984 UserNameA
.Length
= 0;
985 UserNameA
.MaximumLength
= (USHORT
)nMaxUserNameSize
;
988 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
991 lpMaxCollectionCount
,
992 lpCollectDataTimeout
,
995 if (Ret
&& lpUserName
!= NULL
)
999 RtlInitUnicodeString(&UserNameW
, UserNameW
.Buffer
);
1000 Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
1001 if (!NT_SUCCESS(Status
))
1003 BaseSetLastNTError(Status
);
1008 if (UserNameW
.Buffer
!= NULL
)
1010 RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW
.Buffer
);
1022 GetNamedPipeInfo(HANDLE hNamedPipe
,
1024 LPDWORD lpOutBufferSize
,
1025 LPDWORD lpInBufferSize
,
1026 LPDWORD lpMaxInstances
)
1028 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
1029 IO_STATUS_BLOCK StatusBlock
;
1032 Status
= NtQueryInformationFile(hNamedPipe
,
1034 &PipeLocalInformation
,
1035 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
1036 FilePipeLocalInformation
);
1037 if (!NT_SUCCESS(Status
))
1039 BaseSetLastNTError(Status
);
1043 if (lpFlags
!= NULL
)
1045 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
1046 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
1049 if (lpOutBufferSize
!= NULL
)
1050 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
1052 if (lpInBufferSize
!= NULL
)
1053 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
1055 if (lpMaxInstances
!= NULL
)
1057 if (PipeLocalInformation
.MaximumInstances
>= 255)
1058 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
1060 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
1072 PeekNamedPipe(HANDLE hNamedPipe
,
1075 LPDWORD lpBytesRead
,
1076 LPDWORD lpTotalBytesAvail
,
1077 LPDWORD lpBytesLeftThisMessage
)
1079 PFILE_PIPE_PEEK_BUFFER Buffer
;
1080 IO_STATUS_BLOCK Iosb
;
1085 /* Calculate the buffer space that we'll need and allocate it */
1086 BufferSize
= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[nBufferSize
]);
1087 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
1090 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1094 /* Tell the driver to seek */
1095 Status
= NtFsControlFile(hNamedPipe
,
1105 if (Status
== STATUS_PENDING
)
1107 /* Wait for npfs to be done, and update the status */
1108 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
1109 if (NT_SUCCESS(Status
))
1110 Status
= Iosb
.Status
;
1113 /* Overflow is success for us */
1114 if (Status
== STATUS_BUFFER_OVERFLOW
)
1115 Status
= STATUS_SUCCESS
;
1118 if (!NT_SUCCESS(Status
))
1120 /* Free the buffer and return failure */
1121 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1122 BaseSetLastNTError(Status
);
1126 /* Check if caller requested bytes available */
1127 if (lpTotalBytesAvail
)
1129 /* Return bytes available */
1130 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1133 /* Calculate the bytes returned, minus our structure overhead */
1134 BytesRead
= (ULONG
)(Iosb
.Information
-
1135 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[0]));
1136 ASSERT(BytesRead
<= nBufferSize
);
1138 /* Check if caller requested bytes read */
1141 /* Return the bytes read */
1142 *lpBytesRead
= BytesRead
;
1145 /* Check if caller requested bytes left */
1146 if (lpBytesLeftThisMessage
)
1148 /* Calculate total minus what we returned and our structure overhead */
1149 *lpBytesLeftThisMessage
= Buffer
->MessageLength
- BytesRead
;
1152 /* Check if the caller wanted to see the actual data */
1155 /* Give him what he wants */
1156 RtlCopyMemory(lpBuffer
,
1161 /* Free the buffer */
1162 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1173 TransactNamedPipe(IN HANDLE hNamedPipe
,
1174 IN LPVOID lpInBuffer
,
1175 IN DWORD nInBufferSize
,
1176 OUT LPVOID lpOutBuffer
,
1177 IN DWORD nOutBufferSize
,
1178 OUT LPDWORD lpBytesRead OPTIONAL
,
1179 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1183 if (lpBytesRead
!= NULL
)
1188 if (lpOverlapped
!= NULL
)
1192 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1193 lpOverlapped
->Internal
= STATUS_PENDING
;
1195 Status
= NtFsControlFile(hNamedPipe
,
1196 lpOverlapped
->hEvent
,
1199 (PIO_STATUS_BLOCK
)lpOverlapped
,
1200 FSCTL_PIPE_TRANSCEIVE
,
1205 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1207 BaseSetLastNTError(Status
);
1211 if (lpBytesRead
!= NULL
)
1213 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1218 IO_STATUS_BLOCK Iosb
;
1220 Status
= NtFsControlFile(hNamedPipe
,
1225 FSCTL_PIPE_TRANSCEIVE
,
1230 if (Status
== STATUS_PENDING
)
1232 Status
= NtWaitForSingleObject(hNamedPipe
,
1235 if (NT_SUCCESS(Status
))
1236 Status
= Iosb
.Status
;
1239 if (NT_SUCCESS(Status
))
1241 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1242 check that case either and crashes (only after the operation
1244 *lpBytesRead
= Iosb
.Information
;
1248 BaseSetLastNTError(Status
);