2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32 Kernel Library
4 * FILE: dll/win32/kernel32/client/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 ******************************************************************/
25 NpGetUserNamep(HANDLE hNamedPipe
,
27 DWORD nMaxUserNameSize
)
29 /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
30 retrieve the user name with GetUserName(), revert the impersonation
31 and finally restore the thread token */
42 CreatePipe(PHANDLE hReadPipe
,
44 LPSECURITY_ATTRIBUTES lpPipeAttributes
,
48 UNICODE_STRING PipeName
;
49 OBJECT_ATTRIBUTES ObjectAttributes
;
50 IO_STATUS_BLOCK StatusBlock
;
51 LARGE_INTEGER DefaultTimeout
;
53 HANDLE ReadPipeHandle
;
54 HANDLE WritePipeHandle
;
57 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
59 /* Set the timeout to 120 seconds */
60 DefaultTimeout
.QuadPart
= -1200000000;
62 /* Use default buffer size if desired */
63 if (!nSize
) nSize
= 0x1000;
65 /* Increase the Pipe ID */
66 PipeId
= InterlockedIncrement(&ProcessPipeId
);
68 /* Create the pipe name */
70 L
"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
71 NtCurrentTeb()->ClientId
.UniqueProcess
,
73 RtlInitUnicodeString(&PipeName
, Buffer
);
75 /* Always use case insensitive */
76 Attributes
= OBJ_CASE_INSENSITIVE
;
78 /* Check if we got attributes */
81 /* Use the attributes' SD instead */
82 SecurityDescriptor
= lpPipeAttributes
->lpSecurityDescriptor
;
84 /* Set OBJ_INHERIT if requested */
85 if (lpPipeAttributes
->bInheritHandle
) Attributes
|= OBJ_INHERIT
;
88 /* Initialize the attributes */
89 InitializeObjectAttributes(&ObjectAttributes
,
95 /* Create the named pipe */
96 Status
= NtCreateNamedPipeFile(&ReadPipeHandle
,
97 GENERIC_READ
|FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
100 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
102 FILE_SYNCHRONOUS_IO_NONALERT
,
103 FILE_PIPE_BYTE_STREAM_TYPE
,
104 FILE_PIPE_BYTE_STREAM_MODE
,
105 FILE_PIPE_QUEUE_OPERATION
,
110 if (!NT_SUCCESS(Status
))
112 /* Convert error and fail */
113 WARN("Status: %lx\n", Status
);
114 BaseSetLastNTError(Status
);
118 /* Now try opening it for write access */
119 Status
= NtOpenFile(&WritePipeHandle
,
124 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
125 if (!NT_SUCCESS(Status
))
127 /* Convert error and fail */
128 WARN("Status: %lx\n", Status
);
129 NtClose(ReadPipeHandle
);
130 BaseSetLastNTError(Status
);
134 /* Return both handles */
135 *hReadPipe
= ReadPipeHandle
;
136 *hWritePipe
= WritePipeHandle
;
145 CreateNamedPipeA(LPCSTR lpName
,
149 DWORD nOutBufferSize
,
151 DWORD nDefaultTimeOut
,
152 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
154 /* Call the W(ide) function */
155 ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe
,
163 lpSecurityAttributes
);
171 CreateNamedPipeW(LPCWSTR lpName
,
175 DWORD nOutBufferSize
,
177 DWORD nDefaultTimeOut
,
178 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
180 UNICODE_STRING NamedPipeName
;
183 OBJECT_ATTRIBUTES ObjectAttributes
;
185 ACCESS_MASK DesiredAccess
;
186 ULONG CreateOptions
= 0;
187 ULONG WriteModeMessage
;
188 ULONG ReadModeMessage
;
190 IO_STATUS_BLOCK Iosb
;
191 ULONG ShareAccess
= 0, Attributes
;
192 LARGE_INTEGER DefaultTimeOut
;
193 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
195 /* Check for valid instances */
196 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
199 SetLastError(ERROR_INVALID_PARAMETER
);
200 return INVALID_HANDLE_VALUE
;
203 /* Convert to NT syntax */
204 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
)
207 /* Convert the name */
208 Result
= RtlDosPathNameToNtPathName_U(lpName
,
214 /* Conversion failed */
215 SetLastError(ERROR_PATH_NOT_FOUND
);
216 return INVALID_HANDLE_VALUE
;
219 TRACE("Pipe name: %wZ\n", &NamedPipeName
);
220 TRACE("Pipe name: %S\n", NamedPipeName
.Buffer
);
222 /* Always case insensitive, check if we got extra attributes */
223 Attributes
= OBJ_CASE_INSENSITIVE
;
224 if(lpSecurityAttributes
)
226 /* We did; get the security descriptor */
227 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
229 /* And check if this is pipe's handle will beinheritable */
230 if (lpSecurityAttributes
->bInheritHandle
)
231 Attributes
|= OBJ_INHERIT
;
234 /* Now we can initialize the object attributes */
235 InitializeObjectAttributes(&ObjectAttributes
,
241 /* Setup the default Desired Access */
242 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
244 ACCESS_SYSTEM_SECURITY
));
246 /* Convert to NT Create Flags */
247 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
249 CreateOptions
|= FILE_WRITE_THROUGH
;
252 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
254 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
257 /* Handle all open modes */
258 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
260 ShareAccess
|= FILE_SHARE_READ
;
261 DesiredAccess
|= GENERIC_WRITE
;
264 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
266 ShareAccess
|= FILE_SHARE_WRITE
;
267 DesiredAccess
|= GENERIC_READ
;
270 /* Handle the type flags */
271 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
273 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
277 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
280 /* Handle the mode flags */
281 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
283 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
287 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
290 /* Handle the blocking mode */
291 if (dwPipeMode
& PIPE_NOWAIT
)
293 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
297 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
300 /* Check if we have a timeout */
303 /* Convert the time to NT format */
304 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000LL;
308 /* Use default timeout of 50 ms */
309 DefaultTimeOut
.QuadPart
= -500000;
312 /* Now create the pipe */
313 Status
= NtCreateNamedPipeFile(&PipeHandle
,
328 /* Normalize special error codes */
329 if ((Status
== STATUS_INVALID_DEVICE_REQUEST
) ||
330 (Status
== STATUS_NOT_SUPPORTED
))
332 Status
= STATUS_OBJECT_NAME_INVALID
;
336 RtlFreeHeap(RtlGetProcessHeap(),
338 NamedPipeName
.Buffer
);
341 if (!NT_SUCCESS(Status
))
343 /* Failed to create it */
344 WARN("NtCreateNamedPipe failed (Status %x)!\n", Status
);
345 BaseSetLastNTError (Status
);
346 return INVALID_HANDLE_VALUE
;
349 /* Return the handle */
358 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
362 UNICODE_STRING NameU
;
364 /* Convert the name to Unicode */
365 if (Basep8BitStringToDynamicUnicodeString(&NameU
, lpNamedPipeName
))
367 /* Call the Unicode API */
368 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
370 /* Free the Unicode string */
371 RtlFreeUnicodeString(&NameU
);
383 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
386 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
391 OBJECT_ATTRIBUTES ObjectAttributes
;
394 IO_STATUS_BLOCK IoStatusBlock
;
395 ULONG WaitPipeInfoSize
;
396 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
398 /* Start by making a unicode string of the name */
399 TRACE("Sent path: %S\n", lpNamedPipeName
);
400 if (!RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
))
402 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
405 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
407 /* All slashes must become backslashes */
408 for (i
= 0; i
< NameLength
; i
++)
410 /* Check and convert */
411 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
414 /* Find the path type of the name we were given */
415 NewName
= NamedPipeName
;
416 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
418 /* Check if this was a device path, ie : "\\.\pipe\name" */
419 if (Type
== RtlPathTypeLocalDevice
)
421 /* Make sure it's a valid prefix */
422 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
423 if (!RtlPrefixUnicodeString(&PipePrefix
, &NewName
, TRUE
))
425 /* The name is invalid */
426 WARN("Invalid name!\n");
427 RtlFreeUnicodeString(&NamedPipeName
);
428 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
433 NewName
.Buffer
+= PipePrefix
.Length
/ sizeof(WCHAR
);
434 NewName
.Length
-= PipePrefix
.Length
;
435 NewName
.MaximumLength
-= PipePrefix
.Length
;
437 /* Initialize the Dos Devices name */
438 TRACE("NewName: %wZ\n", &NewName
);
439 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
441 else if (Type
== RtlPathTypeUncAbsolute
)
443 /* The path is \\server\\pipe\name; find the pipename itself */
444 p
= &NewName
.Buffer
[2];
446 /* First loop to get past the server name */
449 /* Check if this is a backslash */
450 if (*p
== L
'\\') break;
456 /* Now make sure the full name contains "pipe\" */
457 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL
))))
459 /* Get to the pipe name itself now */
460 p
+= sizeof("pipe\\") - sizeof(ANSI_NULL
);
464 /* The name is invalid */
465 WARN("Invalid name!\n");
466 RtlFreeUnicodeString(&NamedPipeName
);
467 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
471 /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
475 WARN("Invalid path type\n");
476 RtlFreeUnicodeString(&NamedPipeName
);
477 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
481 /* Now calculate the total length of the structure and allocate it */
482 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
484 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
485 if (WaitPipeInfo
== NULL
)
487 RtlFreeUnicodeString(&NamedPipeName
);
488 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
492 /* Initialize the object attributes */
493 TRACE("Opening: %wZ\n", &DevicePath
);
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_CASE_INSENSITIVE
,
501 Status
= NtOpenFile(&FileHandle
,
502 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
505 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
506 FILE_SYNCHRONOUS_IO_NONALERT
);
507 if (!NT_SUCCESS(Status
))
509 /* Fail; couldn't open */
510 WARN("Status: %lx\n", Status
);
511 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
512 RtlFreeUnicodeString(&NamedPipeName
);
513 BaseSetLastNTError(Status
);
517 /* Check what timeout we got */
518 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
520 /* Don't use a timeout */
521 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
525 /* Check if we should wait forever */
526 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
529 WaitPipeInfo
->Timeout
.LowPart
= 0;
530 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
534 /* Convert to NT format */
535 WaitPipeInfo
->Timeout
.QuadPart
= nTimeOut
* -10000LL;
538 /* In both cases, we do have a timeout */
539 WaitPipeInfo
->TimeoutSpecified
= TRUE
;
542 /* Set the length and copy the name */
543 WaitPipeInfo
->NameLength
= NewName
.Length
;
544 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
546 /* Get rid of the full name */
547 RtlFreeUnicodeString(&NamedPipeName
);
549 /* Let NPFS know of our request */
550 Status
= NtFsControlFile(FileHandle
,
561 /* Free our pipe info data and close the handle */
562 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
565 /* Check the status */
566 if (!NT_SUCCESS(Status
))
568 /* Failure to wait on the pipe */
569 WARN("Status: %lx\n", Status
);
570 BaseSetLastNTError(Status
);
583 ConnectNamedPipe(IN HANDLE hNamedPipe
,
584 IN LPOVERLAPPED lpOverlapped
)
588 if (lpOverlapped
!= NULL
)
592 lpOverlapped
->Internal
= STATUS_PENDING
;
593 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
595 Status
= NtFsControlFile(hNamedPipe
,
596 lpOverlapped
->hEvent
,
599 (PIO_STATUS_BLOCK
)lpOverlapped
,
606 /* return FALSE in case of failure and pending operations! */
607 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
609 BaseSetLastNTError(Status
);
615 IO_STATUS_BLOCK Iosb
;
617 Status
= NtFsControlFile(hNamedPipe
,
628 /* wait in case operation is pending */
629 if (Status
== STATUS_PENDING
)
631 Status
= NtWaitForSingleObject(hNamedPipe
,
634 if (NT_SUCCESS(Status
))
636 Status
= Iosb
.Status
;
640 if (!NT_SUCCESS(Status
))
642 BaseSetLastNTError(Status
);
656 SetNamedPipeHandleState(HANDLE hNamedPipe
,
658 LPDWORD lpMaxCollectionCount
,
659 LPDWORD lpCollectDataTimeout
)
661 IO_STATUS_BLOCK Iosb
;
664 /* Check if the Mode is being changed */
667 FILE_PIPE_INFORMATION Settings
;
669 /* Set the Completion Mode */
670 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
671 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
673 /* Set the Read Mode */
674 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
675 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
677 /* Send the changes to the Driver */
678 Status
= NtSetInformationFile(hNamedPipe
,
681 sizeof(FILE_PIPE_INFORMATION
),
682 FilePipeInformation
);
683 if (!NT_SUCCESS(Status
))
685 BaseSetLastNTError(Status
);
690 /* Check if the Collection count or Timeout are being changed */
691 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
693 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
695 /* Setting one without the other would delete it, so we read old one */
696 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
698 Status
= NtQueryInformationFile(hNamedPipe
,
701 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
702 FilePipeRemoteInformation
);
703 if (!NT_SUCCESS(Status
))
705 BaseSetLastNTError(Status
);
710 /* Now set the new settings */
711 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
712 *lpMaxCollectionCount
:
713 RemoteSettings
.MaximumCollectionCount
;
714 if (lpCollectDataTimeout
)
716 /* Convert it to Quad */
717 RemoteSettings
.CollectDataTime
.QuadPart
= *lpCollectDataTimeout
* -10000LL;
720 /* Tell the driver to change them */
721 Status
= NtSetInformationFile(hNamedPipe
,
724 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
725 FilePipeRemoteInformation
);
726 if (!NT_SUCCESS(Status
))
728 BaseSetLastNTError(Status
);
742 CallNamedPipeA(LPCSTR lpNamedPipeName
,
746 DWORD nOutBufferSize
,
750 PUNICODE_STRING PipeName
= &NtCurrentTeb()->StaticUnicodeString
;
751 ANSI_STRING AnsiPipe
;
753 /* Initialize the string as ANSI_STRING and convert to Unicode */
754 RtlInitAnsiString(&AnsiPipe
, (LPSTR
)lpNamedPipeName
);
755 RtlAnsiStringToUnicodeString(PipeName
, &AnsiPipe
, FALSE
);
757 /* Call the Unicode function */
758 return CallNamedPipeW(PipeName
->Buffer
,
773 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
777 DWORD nOutBufferSize
,
788 /* Try creating it */
789 hPipe
= CreateFileW(lpNamedPipeName
,
790 GENERIC_READ
| GENERIC_WRITE
,
791 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
794 FILE_ATTRIBUTE_NORMAL
,
797 /* Success, break out */
798 if (hPipe
!= INVALID_HANDLE_VALUE
)
801 /* Already tried twice, give up */
806 WaitNamedPipeW(lpNamedPipeName
, nTimeOut
);
808 /* Get ready to try again */
812 /* Set the pipe mode */
813 dwPipeMode
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
814 bError
= SetNamedPipeHandleState(hPipe
, &dwPipeMode
, NULL
, NULL
);
817 /* Couldn't change state, fail */
822 /* Do the transact */
823 bError
= TransactNamedPipe(hPipe
,
831 /* Close the handle */
843 DisconnectNamedPipe(HANDLE hNamedPipe
)
845 IO_STATUS_BLOCK Iosb
;
848 /* Send the FSCTL to the driver */
849 Status
= NtFsControlFile(hNamedPipe
,
854 FSCTL_PIPE_DISCONNECT
,
859 if (Status
== STATUS_PENDING
)
861 /* Wait on NPFS to finish and get updated status */
862 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
863 if (NT_SUCCESS(Status
))
864 Status
= Iosb
.Status
;
867 /* Check for error */
868 if (!NT_SUCCESS(Status
))
871 BaseSetLastNTError(Status
);
884 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
886 LPDWORD lpCurInstances
,
887 LPDWORD lpMaxCollectionCount
,
888 LPDWORD lpCollectDataTimeout
,
890 DWORD nMaxUserNameSize
)
892 IO_STATUS_BLOCK StatusBlock
;
897 FILE_PIPE_INFORMATION PipeInfo
;
899 Status
= NtQueryInformationFile(hNamedPipe
,
902 sizeof(FILE_PIPE_INFORMATION
),
903 FilePipeInformation
);
904 if (!NT_SUCCESS(Status
))
906 BaseSetLastNTError(Status
);
910 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
911 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
914 if(lpCurInstances
!= NULL
)
916 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
918 Status
= NtQueryInformationFile(hNamedPipe
,
921 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
922 FilePipeLocalInformation
);
923 if (!NT_SUCCESS(Status
))
925 BaseSetLastNTError(Status
);
929 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
932 if (lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
934 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
936 Status
= NtQueryInformationFile(hNamedPipe
,
939 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
940 FilePipeRemoteInformation
);
941 if (!NT_SUCCESS(Status
))
943 BaseSetLastNTError(Status
);
947 if (lpMaxCollectionCount
!= NULL
)
949 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
952 if (lpCollectDataTimeout
!= NULL
)
954 LARGE_INTEGER CollectDataTime
;
956 /* Convert time and return it */
957 RemoteInfo
.CollectDataTime
.QuadPart
*= -1;
958 CollectDataTime
= RtlExtendedLargeIntegerDivide(RemoteInfo
.CollectDataTime
, 10000, NULL
);
959 /* In case of overflow, just return MAX - 1 */
960 if (CollectDataTime
.HighPart
!= 0)
962 *lpCollectDataTimeout
= -2;
966 *lpCollectDataTimeout
= CollectDataTime
.LowPart
;
971 if (lpUserName
!= NULL
)
973 return NpGetUserNamep(hNamedPipe
, lpUserName
, nMaxUserNameSize
);
985 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
987 LPDWORD lpCurInstances
,
988 LPDWORD lpMaxCollectionCount
,
989 LPDWORD lpCollectDataTimeout
,
991 DWORD nMaxUserNameSize
)
993 UNICODE_STRING UserNameW
= { 0, 0, NULL
};
994 ANSI_STRING UserNameA
;
997 if(lpUserName
!= NULL
)
999 UserNameW
.MaximumLength
= (USHORT
)nMaxUserNameSize
* sizeof(WCHAR
);
1000 UserNameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW
.MaximumLength
);
1001 if (UserNameW
.Buffer
== NULL
)
1003 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1007 UserNameA
.Buffer
= lpUserName
;
1008 UserNameA
.Length
= 0;
1009 UserNameA
.MaximumLength
= (USHORT
)nMaxUserNameSize
;
1012 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
1015 lpMaxCollectionCount
,
1016 lpCollectDataTimeout
,
1019 if (Ret
&& lpUserName
!= NULL
)
1023 RtlInitUnicodeString(&UserNameW
, UserNameW
.Buffer
);
1024 Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
1025 if (!NT_SUCCESS(Status
))
1027 BaseSetLastNTError(Status
);
1032 if (UserNameW
.Buffer
!= NULL
)
1034 RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW
.Buffer
);
1046 GetNamedPipeInfo(HANDLE hNamedPipe
,
1048 LPDWORD lpOutBufferSize
,
1049 LPDWORD lpInBufferSize
,
1050 LPDWORD lpMaxInstances
)
1052 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
1053 IO_STATUS_BLOCK StatusBlock
;
1056 Status
= NtQueryInformationFile(hNamedPipe
,
1058 &PipeLocalInformation
,
1059 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
1060 FilePipeLocalInformation
);
1061 if (!NT_SUCCESS(Status
))
1063 BaseSetLastNTError(Status
);
1067 if (lpFlags
!= NULL
)
1069 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
1070 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
1073 if (lpOutBufferSize
!= NULL
)
1074 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
1076 if (lpInBufferSize
!= NULL
)
1077 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
1079 if (lpMaxInstances
!= NULL
)
1081 if (PipeLocalInformation
.MaximumInstances
>= 255)
1082 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
1084 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
1096 PeekNamedPipe(HANDLE hNamedPipe
,
1099 LPDWORD lpBytesRead
,
1100 LPDWORD lpTotalBytesAvail
,
1101 LPDWORD lpBytesLeftThisMessage
)
1103 PFILE_PIPE_PEEK_BUFFER Buffer
;
1104 IO_STATUS_BLOCK Iosb
;
1109 /* Calculate the buffer space that we'll need and allocate it */
1110 BufferSize
= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[nBufferSize
]);
1111 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
1114 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1118 /* Tell the driver to seek */
1119 Status
= NtFsControlFile(hNamedPipe
,
1129 if (Status
== STATUS_PENDING
)
1131 /* Wait for npfs to be done, and update the status */
1132 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
1133 if (NT_SUCCESS(Status
))
1134 Status
= Iosb
.Status
;
1137 /* Overflow is success for us */
1138 if (Status
== STATUS_BUFFER_OVERFLOW
)
1139 Status
= STATUS_SUCCESS
;
1142 if (!NT_SUCCESS(Status
))
1144 /* Free the buffer and return failure */
1145 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1146 BaseSetLastNTError(Status
);
1150 /* Check if caller requested bytes available */
1151 if (lpTotalBytesAvail
)
1153 /* Return bytes available */
1154 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1157 /* Calculate the bytes returned, minus our structure overhead */
1158 BytesRead
= (ULONG
)(Iosb
.Information
-
1159 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[0]));
1160 ASSERT(BytesRead
<= nBufferSize
);
1162 /* Check if caller requested bytes read */
1165 /* Return the bytes read */
1166 *lpBytesRead
= BytesRead
;
1169 /* Check if caller requested bytes left */
1170 if (lpBytesLeftThisMessage
)
1172 /* Calculate total minus what we returned and our structure overhead */
1173 *lpBytesLeftThisMessage
= Buffer
->MessageLength
- BytesRead
;
1176 /* Check if the caller wanted to see the actual data */
1179 /* Give him what he wants */
1180 RtlCopyMemory(lpBuffer
,
1185 /* Free the buffer */
1186 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1197 TransactNamedPipe(IN HANDLE hNamedPipe
,
1198 IN LPVOID lpInBuffer
,
1199 IN DWORD nInBufferSize
,
1200 OUT LPVOID lpOutBuffer
,
1201 IN DWORD nOutBufferSize
,
1202 OUT LPDWORD lpBytesRead OPTIONAL
,
1203 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1207 if (lpBytesRead
!= NULL
)
1212 if (lpOverlapped
!= NULL
)
1216 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1217 lpOverlapped
->Internal
= STATUS_PENDING
;
1219 Status
= NtFsControlFile(hNamedPipe
,
1220 lpOverlapped
->hEvent
,
1223 (PIO_STATUS_BLOCK
)lpOverlapped
,
1224 FSCTL_PIPE_TRANSCEIVE
,
1229 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1231 BaseSetLastNTError(Status
);
1235 if (lpBytesRead
!= NULL
)
1237 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1242 IO_STATUS_BLOCK Iosb
;
1244 Status
= NtFsControlFile(hNamedPipe
,
1249 FSCTL_PIPE_TRANSCEIVE
,
1254 if (Status
== STATUS_PENDING
)
1256 Status
= NtWaitForSingleObject(hNamedPipe
,
1259 if (NT_SUCCESS(Status
))
1260 Status
= Iosb
.Status
;
1263 if (NT_SUCCESS(Status
))
1265 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1266 check that case either and crashes (only after the operation
1268 *lpBytesRead
= Iosb
.Information
;
1272 BaseSetLastNTError(Status
);