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 ******************************************************************/
28 NpGetUserNamep(HANDLE hNamedPipe
,
30 DWORD nMaxUserNameSize
)
36 BOOL (WINAPI
*pRevertToSelf
)(void);
37 BOOL (WINAPI
*pGetUserNameW
)(LPWSTR lpBuffer
, LPDWORD lpnSize
);
38 BOOL (WINAPI
*pImpersonateNamedPipeClient
)(HANDLE hNamedPipe
);
40 /* Open advapi, we'll funcs from it */
41 hAdvapi
= LoadLibraryW(L
"advapi32.dll");
47 /* Import the three required functions */
48 pRevertToSelf
= (BOOL (WINAPI
*)(void))GetProcAddress(hAdvapi
, "RevertToSelf");
49 pGetUserNameW
= (BOOL (WINAPI
*)(LPWSTR
, LPDWORD
))GetProcAddress(hAdvapi
, "GetUserNameW");
50 pImpersonateNamedPipeClient
= (BOOL (WINAPI
*)(HANDLE
))GetProcAddress(hAdvapi
, "ImpersonateNamedPipeClient");
51 /* If any couldn't be found, fail */
52 if (pRevertToSelf
== NULL
|| pGetUserNameW
== NULL
|| pImpersonateNamedPipeClient
== NULL
)
58 /* Now, open the thread token for impersonation */
59 Status
= NtOpenThreadToken(NtCurrentThread(), TOKEN_IMPERSONATE
, TRUE
, &hToken
);
60 /* Try to impersonate the pipe client */
61 if (pImpersonateNamedPipeClient(hNamedPipe
))
65 /* It worked, get the user name */
66 lpnSize
= nMaxUserNameSize
;
67 Ret
= pGetUserNameW(lpUserName
, &lpnSize
);
68 /* Failed to get the thread token? Revert to self */
69 if (!NT_SUCCESS(Status
))
77 /* Restore the thread token */
78 Status
= NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken
,
79 &hToken
, sizeof(HANDLE
));
80 /* We cannot fail closing the thread token! */
81 if (!CloseHandle(hToken
))
86 /* Set last error if it failed */
87 if (!NT_SUCCESS(Status
))
89 BaseSetLastNTError(Status
);
94 /* If opening the thread token succeed, close it */
95 if (NT_SUCCESS(Status
))
97 /* We cannot fail closing it! */
98 if (!CloseHandle(hToken
))
107 FreeLibrary(hAdvapi
);
117 CreatePipe(PHANDLE hReadPipe
,
119 LPSECURITY_ATTRIBUTES lpPipeAttributes
,
123 UNICODE_STRING PipeName
;
124 OBJECT_ATTRIBUTES ObjectAttributes
;
125 IO_STATUS_BLOCK StatusBlock
;
126 LARGE_INTEGER DefaultTimeout
;
128 HANDLE ReadPipeHandle
;
129 HANDLE WritePipeHandle
;
132 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
134 /* Set the timeout to 120 seconds */
135 DefaultTimeout
.QuadPart
= -1200000000;
137 /* Use default buffer size if desired */
138 if (!nSize
) nSize
= 0x1000;
140 /* Increase the Pipe ID */
141 PipeId
= InterlockedIncrement(&ProcessPipeId
);
143 /* Create the pipe name */
145 L
"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
146 NtCurrentTeb()->ClientId
.UniqueProcess
,
148 RtlInitUnicodeString(&PipeName
, Buffer
);
150 /* Always use case insensitive */
151 Attributes
= OBJ_CASE_INSENSITIVE
;
153 /* Check if we got attributes */
154 if (lpPipeAttributes
)
156 /* Use the attributes' SD instead */
157 SecurityDescriptor
= lpPipeAttributes
->lpSecurityDescriptor
;
159 /* Set OBJ_INHERIT if requested */
160 if (lpPipeAttributes
->bInheritHandle
) Attributes
|= OBJ_INHERIT
;
163 /* Initialize the attributes */
164 InitializeObjectAttributes(&ObjectAttributes
,
170 /* Create the named pipe */
171 Status
= NtCreateNamedPipeFile(&ReadPipeHandle
,
172 GENERIC_READ
|FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
,
175 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
177 FILE_SYNCHRONOUS_IO_NONALERT
,
178 FILE_PIPE_BYTE_STREAM_TYPE
,
179 FILE_PIPE_BYTE_STREAM_MODE
,
180 FILE_PIPE_QUEUE_OPERATION
,
185 if (!NT_SUCCESS(Status
))
187 /* Convert error and fail */
188 WARN("Status: %lx\n", Status
);
189 BaseSetLastNTError(Status
);
193 /* Now try opening it for write access */
194 Status
= NtOpenFile(&WritePipeHandle
,
199 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
200 if (!NT_SUCCESS(Status
))
202 /* Convert error and fail */
203 WARN("Status: %lx\n", Status
);
204 NtClose(ReadPipeHandle
);
205 BaseSetLastNTError(Status
);
209 /* Return both handles */
210 *hReadPipe
= ReadPipeHandle
;
211 *hWritePipe
= WritePipeHandle
;
220 CreateNamedPipeA(LPCSTR lpName
,
224 DWORD nOutBufferSize
,
226 DWORD nDefaultTimeOut
,
227 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
229 /* Call the W(ide) function */
230 ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe
,
238 lpSecurityAttributes
);
246 CreateNamedPipeW(LPCWSTR lpName
,
250 DWORD nOutBufferSize
,
252 DWORD nDefaultTimeOut
,
253 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
255 UNICODE_STRING NamedPipeName
;
258 OBJECT_ATTRIBUTES ObjectAttributes
;
260 ACCESS_MASK DesiredAccess
;
261 ULONG CreateOptions
= 0;
262 ULONG WriteModeMessage
;
263 ULONG ReadModeMessage
;
265 IO_STATUS_BLOCK Iosb
;
266 ULONG ShareAccess
= 0, Attributes
;
267 LARGE_INTEGER DefaultTimeOut
;
268 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
270 /* Check for valid instances */
271 if (nMaxInstances
== 0 || nMaxInstances
> PIPE_UNLIMITED_INSTANCES
)
274 SetLastError(ERROR_INVALID_PARAMETER
);
275 return INVALID_HANDLE_VALUE
;
278 /* Convert to NT syntax */
279 if (nMaxInstances
== PIPE_UNLIMITED_INSTANCES
)
282 /* Convert the name */
283 Result
= RtlDosPathNameToNtPathName_U(lpName
,
289 /* Conversion failed */
290 SetLastError(ERROR_PATH_NOT_FOUND
);
291 return INVALID_HANDLE_VALUE
;
294 TRACE("Pipe name: %wZ\n", &NamedPipeName
);
295 TRACE("Pipe name: %S\n", NamedPipeName
.Buffer
);
297 /* Always case insensitive, check if we got extra attributes */
298 Attributes
= OBJ_CASE_INSENSITIVE
;
299 if(lpSecurityAttributes
)
301 /* We did; get the security descriptor */
302 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
304 /* And check if this is pipe's handle will beinheritable */
305 if (lpSecurityAttributes
->bInheritHandle
)
306 Attributes
|= OBJ_INHERIT
;
309 /* Now we can initialize the object attributes */
310 InitializeObjectAttributes(&ObjectAttributes
,
316 /* Setup the default Desired Access */
317 DesiredAccess
= SYNCHRONIZE
| (dwOpenMode
& (WRITE_DAC
|
319 ACCESS_SYSTEM_SECURITY
));
321 /* Convert to NT Create Flags */
322 if (dwOpenMode
& FILE_FLAG_WRITE_THROUGH
)
324 CreateOptions
|= FILE_WRITE_THROUGH
;
327 if (!(dwOpenMode
& FILE_FLAG_OVERLAPPED
))
329 CreateOptions
|= FILE_SYNCHRONOUS_IO_NONALERT
;
332 /* Handle all open modes */
333 if (dwOpenMode
& PIPE_ACCESS_OUTBOUND
)
335 ShareAccess
|= FILE_SHARE_READ
;
336 DesiredAccess
|= GENERIC_WRITE
;
339 if (dwOpenMode
& PIPE_ACCESS_INBOUND
)
341 ShareAccess
|= FILE_SHARE_WRITE
;
342 DesiredAccess
|= GENERIC_READ
;
345 /* Handle the type flags */
346 if (dwPipeMode
& PIPE_TYPE_MESSAGE
)
348 WriteModeMessage
= FILE_PIPE_MESSAGE_TYPE
;
352 WriteModeMessage
= FILE_PIPE_BYTE_STREAM_TYPE
;
355 /* Handle the mode flags */
356 if (dwPipeMode
& PIPE_READMODE_MESSAGE
)
358 ReadModeMessage
= FILE_PIPE_MESSAGE_MODE
;
362 ReadModeMessage
= FILE_PIPE_BYTE_STREAM_MODE
;
365 /* Handle the blocking mode */
366 if (dwPipeMode
& PIPE_NOWAIT
)
368 NonBlocking
= FILE_PIPE_COMPLETE_OPERATION
;
372 NonBlocking
= FILE_PIPE_QUEUE_OPERATION
;
375 /* Check if we have a timeout */
378 /* Convert the time to NT format */
379 DefaultTimeOut
.QuadPart
= nDefaultTimeOut
* -10000LL;
383 /* Use default timeout of 50 ms */
384 DefaultTimeOut
.QuadPart
= -500000;
387 /* Now create the pipe */
388 Status
= NtCreateNamedPipeFile(&PipeHandle
,
403 /* Normalize special error codes */
404 if ((Status
== STATUS_INVALID_DEVICE_REQUEST
) ||
405 (Status
== STATUS_NOT_SUPPORTED
))
407 Status
= STATUS_OBJECT_NAME_INVALID
;
411 RtlFreeHeap(RtlGetProcessHeap(),
413 NamedPipeName
.Buffer
);
416 if (!NT_SUCCESS(Status
))
418 /* Failed to create it */
419 WARN("NtCreateNamedPipe failed (Status %x)!\n", Status
);
420 BaseSetLastNTError (Status
);
421 return INVALID_HANDLE_VALUE
;
424 /* Return the handle */
433 WaitNamedPipeA(LPCSTR lpNamedPipeName
,
437 UNICODE_STRING NameU
;
439 /* Convert the name to Unicode */
440 if (Basep8BitStringToDynamicUnicodeString(&NameU
, lpNamedPipeName
))
442 /* Call the Unicode API */
443 r
= WaitNamedPipeW(NameU
.Buffer
, nTimeOut
);
445 /* Free the Unicode string */
446 RtlFreeUnicodeString(&NameU
);
458 WaitNamedPipeW(LPCWSTR lpNamedPipeName
,
461 UNICODE_STRING NamedPipeName
, NewName
, DevicePath
, PipePrefix
;
466 OBJECT_ATTRIBUTES ObjectAttributes
;
469 IO_STATUS_BLOCK IoStatusBlock
;
470 ULONG WaitPipeInfoSize
;
471 PVOID DevicePathBuffer
;
472 PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo
;
474 /* Start by making a unicode string of the name */
475 TRACE("Sent path: %S\n", lpNamedPipeName
);
476 if (!RtlCreateUnicodeString(&NamedPipeName
, lpNamedPipeName
))
478 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
481 NameLength
= NamedPipeName
.Length
/ sizeof(WCHAR
);
483 /* All slashes must become backslashes */
484 for (i
= 0; i
< NameLength
; i
++)
486 /* Check and convert */
487 if (NamedPipeName
.Buffer
[i
] == L
'/') NamedPipeName
.Buffer
[i
] = L
'\\';
490 DevicePathBuffer
= NULL
;
492 /* Find the path type of the name we were given */
493 NewName
= NamedPipeName
;
494 Type
= RtlDetermineDosPathNameType_U(lpNamedPipeName
);
496 /* Check if this was a device path, ie : "\\.\pipe\name" */
497 if (Type
== RtlPathTypeLocalDevice
)
499 /* Make sure it's a valid prefix */
500 RtlInitUnicodeString(&PipePrefix
, L
"\\\\.\\pipe\\");
501 if (!RtlPrefixUnicodeString(&PipePrefix
, &NewName
, TRUE
))
503 /* The name is invalid */
504 WARN("Invalid name!\n");
505 RtlFreeUnicodeString(&NamedPipeName
);
506 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
511 NewName
.Buffer
+= PipePrefix
.Length
/ sizeof(WCHAR
);
512 NewName
.Length
-= PipePrefix
.Length
;
513 NewName
.MaximumLength
-= PipePrefix
.Length
;
515 /* Initialize the Dos Devices name */
516 TRACE("NewName: %wZ\n", &NewName
);
517 RtlInitUnicodeString(&DevicePath
, L
"\\DosDevices\\pipe\\");
519 else if (Type
== RtlPathTypeUncAbsolute
)
523 /* The path is \\server\\pipe\name; find the pipename itself */
524 p
= &NewName
.Buffer
[2];
526 /* First loop to get past the server name */
529 /* Check if this is a backslash */
530 if (*p
== L
'\\') break;
536 /* Now make sure the full name contains "pipe\" */
537 if ((*p
) && !(_wcsnicmp(p
+ 1, L
"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL
))))
539 /* Get to the pipe name itself now */
540 p
+= sizeof("pipe\\") - sizeof(ANSI_NULL
);
544 /* The name is invalid */
545 WARN("Invalid name!\n");
546 RtlFreeUnicodeString(&NamedPipeName
);
547 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
551 /* Skip first backslash */
553 /* And skip pipe for copying name */
554 PipeName
= p
+ ((sizeof(L
"pipe\\") - sizeof(UNICODE_NULL
)) / sizeof(WCHAR
));
555 /* Update the string */
556 NewName
.Length
= (USHORT
)((ULONG_PTR
)PipeName
- (ULONG_PTR
)NewName
.Buffer
);
557 NewName
.MaximumLength
= (USHORT
)((ULONG_PTR
)PipeName
- (ULONG_PTR
)NewName
.Buffer
);
559 /* DevicePath will contain the pipename + the DosDevice prefix */
560 DevicePath
.MaximumLength
= (USHORT
)((ULONG_PTR
)PipeName
- (ULONG_PTR
)NewName
.Buffer
) + sizeof(L
"\\DosDevices\\UNC\\");
562 /* Allocate the buffer for DevicePath */
563 DevicePathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, DevicePath
.MaximumLength
);
564 if (DevicePathBuffer
== NULL
)
566 RtlFreeUnicodeString(&NamedPipeName
);
567 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
571 /* Copy the prefix first */
572 DevicePath
.Buffer
= DevicePathBuffer
;
573 RtlCopyMemory(DevicePathBuffer
, L
"\\DosDevices\\UNC\\", sizeof(L
"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL
));
574 DevicePath
.Length
= sizeof(L
"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL
);
575 /* And append the rest */
576 RtlAppendUnicodeStringToString(&DevicePath
, &NewName
);
577 /* And fix pipe name without its prefix */
578 RtlInitUnicodeString(&NewName
, PipeName
+ 1);
582 WARN("Invalid path type\n");
583 RtlFreeUnicodeString(&NamedPipeName
);
584 BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD
);
588 /* Now calculate the total length of the structure and allocate it */
589 WaitPipeInfoSize
= FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER
, Name
[0]) +
591 WaitPipeInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize
);
592 if (WaitPipeInfo
== NULL
)
594 if (DevicePathBuffer
!= NULL
)
596 RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer
);
599 RtlFreeUnicodeString(&NamedPipeName
);
600 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
604 /* Initialize the object attributes */
605 TRACE("Opening: %wZ\n", &DevicePath
);
606 InitializeObjectAttributes(&ObjectAttributes
,
608 OBJ_CASE_INSENSITIVE
,
613 Status
= NtOpenFile(&FileHandle
,
614 FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
617 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
618 FILE_SYNCHRONOUS_IO_NONALERT
);
620 if (DevicePathBuffer
!= NULL
)
622 RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer
);
625 if (!NT_SUCCESS(Status
))
627 /* Fail; couldn't open */
628 WARN("Status: %lx\n", Status
);
629 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
630 RtlFreeUnicodeString(&NamedPipeName
);
631 BaseSetLastNTError(Status
);
635 /* Check what timeout we got */
636 if (nTimeOut
== NMPWAIT_USE_DEFAULT_WAIT
)
638 /* Don't use a timeout */
639 WaitPipeInfo
->TimeoutSpecified
= FALSE
;
643 /* Check if we should wait forever */
644 if (nTimeOut
== NMPWAIT_WAIT_FOREVER
)
647 WaitPipeInfo
->Timeout
.LowPart
= 0;
648 WaitPipeInfo
->Timeout
.HighPart
= 0x80000000;
652 /* Convert to NT format */
653 WaitPipeInfo
->Timeout
.QuadPart
= nTimeOut
* -10000LL;
656 /* In both cases, we do have a timeout */
657 WaitPipeInfo
->TimeoutSpecified
= TRUE
;
660 /* Set the length and copy the name */
661 WaitPipeInfo
->NameLength
= NewName
.Length
;
662 RtlCopyMemory(WaitPipeInfo
->Name
, NewName
.Buffer
, NewName
.Length
);
664 /* Get rid of the full name */
665 RtlFreeUnicodeString(&NamedPipeName
);
667 /* Let NPFS know of our request */
668 Status
= NtFsControlFile(FileHandle
,
679 /* Free our pipe info data and close the handle */
680 RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo
);
683 /* Check the status */
684 if (!NT_SUCCESS(Status
))
686 /* Failure to wait on the pipe */
687 WARN("Status: %lx\n", Status
);
688 BaseSetLastNTError(Status
);
701 ConnectNamedPipe(IN HANDLE hNamedPipe
,
702 IN LPOVERLAPPED lpOverlapped
)
706 if (lpOverlapped
!= NULL
)
710 lpOverlapped
->Internal
= STATUS_PENDING
;
711 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
713 Status
= NtFsControlFile(hNamedPipe
,
714 lpOverlapped
->hEvent
,
717 (PIO_STATUS_BLOCK
)lpOverlapped
,
724 /* return FALSE in case of failure and pending operations! */
725 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
727 BaseSetLastNTError(Status
);
733 IO_STATUS_BLOCK Iosb
;
735 Status
= NtFsControlFile(hNamedPipe
,
746 /* wait in case operation is pending */
747 if (Status
== STATUS_PENDING
)
749 Status
= NtWaitForSingleObject(hNamedPipe
,
752 if (NT_SUCCESS(Status
))
754 Status
= Iosb
.Status
;
758 if (!NT_SUCCESS(Status
))
760 BaseSetLastNTError(Status
);
774 SetNamedPipeHandleState(HANDLE hNamedPipe
,
776 LPDWORD lpMaxCollectionCount
,
777 LPDWORD lpCollectDataTimeout
)
779 IO_STATUS_BLOCK Iosb
;
782 /* Check if the Mode is being changed */
785 FILE_PIPE_INFORMATION Settings
;
787 /* Set the Completion Mode */
788 Settings
.CompletionMode
= (*lpMode
& PIPE_NOWAIT
) ?
789 FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION
;
791 /* Set the Read Mode */
792 Settings
.ReadMode
= (*lpMode
& PIPE_READMODE_MESSAGE
) ?
793 FILE_PIPE_MESSAGE_MODE
: FILE_PIPE_BYTE_STREAM_MODE
;
795 /* Send the changes to the Driver */
796 Status
= NtSetInformationFile(hNamedPipe
,
799 sizeof(FILE_PIPE_INFORMATION
),
800 FilePipeInformation
);
801 if (!NT_SUCCESS(Status
))
803 BaseSetLastNTError(Status
);
808 /* Check if the Collection count or Timeout are being changed */
809 if (lpMaxCollectionCount
|| lpCollectDataTimeout
)
811 FILE_PIPE_REMOTE_INFORMATION RemoteSettings
;
813 /* Setting one without the other would delete it, so we read old one */
814 if (!lpMaxCollectionCount
|| !lpCollectDataTimeout
)
816 Status
= NtQueryInformationFile(hNamedPipe
,
819 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
820 FilePipeRemoteInformation
);
821 if (!NT_SUCCESS(Status
))
823 BaseSetLastNTError(Status
);
828 /* Now set the new settings */
829 RemoteSettings
.MaximumCollectionCount
= (lpMaxCollectionCount
) ?
830 *lpMaxCollectionCount
:
831 RemoteSettings
.MaximumCollectionCount
;
832 if (lpCollectDataTimeout
)
834 /* Convert it to Quad */
835 RemoteSettings
.CollectDataTime
.QuadPart
= *lpCollectDataTimeout
* -10000LL;
838 /* Tell the driver to change them */
839 Status
= NtSetInformationFile(hNamedPipe
,
842 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
843 FilePipeRemoteInformation
);
844 if (!NT_SUCCESS(Status
))
846 BaseSetLastNTError(Status
);
860 CallNamedPipeA(LPCSTR lpNamedPipeName
,
864 DWORD nOutBufferSize
,
868 PUNICODE_STRING PipeName
= &NtCurrentTeb()->StaticUnicodeString
;
869 ANSI_STRING AnsiPipe
;
871 /* Initialize the string as ANSI_STRING and convert to Unicode */
872 RtlInitAnsiString(&AnsiPipe
, (LPSTR
)lpNamedPipeName
);
873 RtlAnsiStringToUnicodeString(PipeName
, &AnsiPipe
, FALSE
);
875 /* Call the Unicode function */
876 return CallNamedPipeW(PipeName
->Buffer
,
891 CallNamedPipeW(LPCWSTR lpNamedPipeName
,
895 DWORD nOutBufferSize
,
906 /* Try creating it */
907 hPipe
= CreateFileW(lpNamedPipeName
,
908 GENERIC_READ
| GENERIC_WRITE
,
909 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
912 FILE_ATTRIBUTE_NORMAL
,
915 /* Success, break out */
916 if (hPipe
!= INVALID_HANDLE_VALUE
)
919 /* Already tried twice, give up */
924 WaitNamedPipeW(lpNamedPipeName
, nTimeOut
);
926 /* Get ready to try again */
930 /* Set the pipe mode */
931 dwPipeMode
= PIPE_READMODE_MESSAGE
| PIPE_WAIT
;
932 bError
= SetNamedPipeHandleState(hPipe
, &dwPipeMode
, NULL
, NULL
);
935 /* Couldn't change state, fail */
940 /* Do the transact */
941 bError
= TransactNamedPipe(hPipe
,
949 /* Close the handle */
961 DisconnectNamedPipe(HANDLE hNamedPipe
)
963 IO_STATUS_BLOCK Iosb
;
966 /* Send the FSCTL to the driver */
967 Status
= NtFsControlFile(hNamedPipe
,
972 FSCTL_PIPE_DISCONNECT
,
977 if (Status
== STATUS_PENDING
)
979 /* Wait on NPFS to finish and get updated status */
980 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
981 if (NT_SUCCESS(Status
))
982 Status
= Iosb
.Status
;
985 /* Check for error */
986 if (!NT_SUCCESS(Status
))
989 BaseSetLastNTError(Status
);
1002 GetNamedPipeHandleStateW(HANDLE hNamedPipe
,
1004 LPDWORD lpCurInstances
,
1005 LPDWORD lpMaxCollectionCount
,
1006 LPDWORD lpCollectDataTimeout
,
1008 DWORD nMaxUserNameSize
)
1010 IO_STATUS_BLOCK StatusBlock
;
1013 if (lpState
!= NULL
)
1015 FILE_PIPE_INFORMATION PipeInfo
;
1017 Status
= NtQueryInformationFile(hNamedPipe
,
1020 sizeof(FILE_PIPE_INFORMATION
),
1021 FilePipeInformation
);
1022 if (!NT_SUCCESS(Status
))
1024 BaseSetLastNTError(Status
);
1028 *lpState
= ((PipeInfo
.CompletionMode
!= FILE_PIPE_QUEUE_OPERATION
) ? PIPE_NOWAIT
: PIPE_WAIT
);
1029 *lpState
|= ((PipeInfo
.ReadMode
!= FILE_PIPE_BYTE_STREAM_MODE
) ? PIPE_READMODE_MESSAGE
: PIPE_READMODE_BYTE
);
1032 if(lpCurInstances
!= NULL
)
1034 FILE_PIPE_LOCAL_INFORMATION LocalInfo
;
1036 Status
= NtQueryInformationFile(hNamedPipe
,
1039 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
1040 FilePipeLocalInformation
);
1041 if (!NT_SUCCESS(Status
))
1043 BaseSetLastNTError(Status
);
1047 *lpCurInstances
= min(LocalInfo
.CurrentInstances
, PIPE_UNLIMITED_INSTANCES
);
1050 if (lpMaxCollectionCount
!= NULL
|| lpCollectDataTimeout
!= NULL
)
1052 FILE_PIPE_REMOTE_INFORMATION RemoteInfo
;
1054 Status
= NtQueryInformationFile(hNamedPipe
,
1057 sizeof(FILE_PIPE_REMOTE_INFORMATION
),
1058 FilePipeRemoteInformation
);
1059 if (!NT_SUCCESS(Status
))
1061 BaseSetLastNTError(Status
);
1065 if (lpMaxCollectionCount
!= NULL
)
1067 *lpMaxCollectionCount
= RemoteInfo
.MaximumCollectionCount
;
1070 if (lpCollectDataTimeout
!= NULL
)
1072 LARGE_INTEGER CollectDataTime
;
1074 /* Convert time and return it */
1075 RemoteInfo
.CollectDataTime
.QuadPart
*= -1;
1076 CollectDataTime
= RtlExtendedLargeIntegerDivide(RemoteInfo
.CollectDataTime
, 10000, NULL
);
1077 /* In case of overflow, just return MAX - 1 */
1078 if (CollectDataTime
.HighPart
!= 0)
1080 *lpCollectDataTimeout
= -2;
1084 *lpCollectDataTimeout
= CollectDataTime
.LowPart
;
1089 if (lpUserName
!= NULL
)
1091 return NpGetUserNamep(hNamedPipe
, lpUserName
, nMaxUserNameSize
);
1103 GetNamedPipeHandleStateA(HANDLE hNamedPipe
,
1105 LPDWORD lpCurInstances
,
1106 LPDWORD lpMaxCollectionCount
,
1107 LPDWORD lpCollectDataTimeout
,
1109 DWORD nMaxUserNameSize
)
1111 UNICODE_STRING UserNameW
= { 0, 0, NULL
};
1112 ANSI_STRING UserNameA
;
1115 if(lpUserName
!= NULL
)
1117 UserNameW
.MaximumLength
= (USHORT
)nMaxUserNameSize
* sizeof(WCHAR
);
1118 UserNameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW
.MaximumLength
);
1119 if (UserNameW
.Buffer
== NULL
)
1121 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1125 UserNameA
.Buffer
= lpUserName
;
1126 UserNameA
.Length
= 0;
1127 UserNameA
.MaximumLength
= (USHORT
)nMaxUserNameSize
;
1130 Ret
= GetNamedPipeHandleStateW(hNamedPipe
,
1133 lpMaxCollectionCount
,
1134 lpCollectDataTimeout
,
1137 if (Ret
&& lpUserName
!= NULL
)
1141 RtlInitUnicodeString(&UserNameW
, UserNameW
.Buffer
);
1142 Status
= RtlUnicodeStringToAnsiString(&UserNameA
, &UserNameW
, FALSE
);
1143 if (!NT_SUCCESS(Status
))
1145 BaseSetLastNTError(Status
);
1150 if (UserNameW
.Buffer
!= NULL
)
1152 RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW
.Buffer
);
1164 GetNamedPipeInfo(HANDLE hNamedPipe
,
1166 LPDWORD lpOutBufferSize
,
1167 LPDWORD lpInBufferSize
,
1168 LPDWORD lpMaxInstances
)
1170 FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation
;
1171 IO_STATUS_BLOCK StatusBlock
;
1174 Status
= NtQueryInformationFile(hNamedPipe
,
1176 &PipeLocalInformation
,
1177 sizeof(FILE_PIPE_LOCAL_INFORMATION
),
1178 FilePipeLocalInformation
);
1179 if (!NT_SUCCESS(Status
))
1181 BaseSetLastNTError(Status
);
1185 if (lpFlags
!= NULL
)
1187 *lpFlags
= (PipeLocalInformation
.NamedPipeEnd
== FILE_PIPE_SERVER_END
) ? PIPE_SERVER_END
: PIPE_CLIENT_END
;
1188 *lpFlags
|= (PipeLocalInformation
.NamedPipeType
== 1) ? PIPE_TYPE_MESSAGE
: PIPE_TYPE_BYTE
;
1191 if (lpOutBufferSize
!= NULL
)
1192 *lpOutBufferSize
= PipeLocalInformation
.OutboundQuota
;
1194 if (lpInBufferSize
!= NULL
)
1195 *lpInBufferSize
= PipeLocalInformation
.InboundQuota
;
1197 if (lpMaxInstances
!= NULL
)
1199 if (PipeLocalInformation
.MaximumInstances
>= 255)
1200 *lpMaxInstances
= PIPE_UNLIMITED_INSTANCES
;
1202 *lpMaxInstances
= PipeLocalInformation
.MaximumInstances
;
1214 PeekNamedPipe(HANDLE hNamedPipe
,
1217 LPDWORD lpBytesRead
,
1218 LPDWORD lpTotalBytesAvail
,
1219 LPDWORD lpBytesLeftThisMessage
)
1221 PFILE_PIPE_PEEK_BUFFER Buffer
;
1222 IO_STATUS_BLOCK Iosb
;
1227 /* Calculate the buffer space that we'll need and allocate it */
1228 BufferSize
= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[nBufferSize
]);
1229 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
1232 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1236 /* Tell the driver to seek */
1237 Status
= NtFsControlFile(hNamedPipe
,
1247 if (Status
== STATUS_PENDING
)
1249 /* Wait for npfs to be done, and update the status */
1250 Status
= NtWaitForSingleObject(hNamedPipe
, FALSE
, NULL
);
1251 if (NT_SUCCESS(Status
))
1252 Status
= Iosb
.Status
;
1255 /* Overflow is success for us */
1256 if (Status
== STATUS_BUFFER_OVERFLOW
)
1257 Status
= STATUS_SUCCESS
;
1260 if (!NT_SUCCESS(Status
))
1262 /* Free the buffer and return failure */
1263 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1264 BaseSetLastNTError(Status
);
1268 /* Check if caller requested bytes available */
1269 if (lpTotalBytesAvail
)
1271 /* Return bytes available */
1272 *lpTotalBytesAvail
= Buffer
->ReadDataAvailable
;
1275 /* Calculate the bytes returned, minus our structure overhead */
1276 BytesRead
= (ULONG
)(Iosb
.Information
-
1277 FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER
, Data
[0]));
1278 ASSERT(BytesRead
<= nBufferSize
);
1280 /* Check if caller requested bytes read */
1283 /* Return the bytes read */
1284 *lpBytesRead
= BytesRead
;
1287 /* Check if caller requested bytes left */
1288 if (lpBytesLeftThisMessage
)
1290 /* Calculate total minus what we returned and our structure overhead */
1291 *lpBytesLeftThisMessage
= Buffer
->MessageLength
- BytesRead
;
1294 /* Check if the caller wanted to see the actual data */
1297 /* Give him what he wants */
1298 RtlCopyMemory(lpBuffer
,
1303 /* Free the buffer */
1304 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
1315 TransactNamedPipe(IN HANDLE hNamedPipe
,
1316 IN LPVOID lpInBuffer
,
1317 IN DWORD nInBufferSize
,
1318 OUT LPVOID lpOutBuffer
,
1319 IN DWORD nOutBufferSize
,
1320 OUT LPDWORD lpBytesRead OPTIONAL
,
1321 IN LPOVERLAPPED lpOverlapped OPTIONAL
)
1325 if (lpBytesRead
!= NULL
)
1330 if (lpOverlapped
!= NULL
)
1334 ApcContext
= (((ULONG_PTR
)lpOverlapped
->hEvent
& 0x1) ? NULL
: lpOverlapped
);
1335 lpOverlapped
->Internal
= STATUS_PENDING
;
1337 Status
= NtFsControlFile(hNamedPipe
,
1338 lpOverlapped
->hEvent
,
1341 (PIO_STATUS_BLOCK
)lpOverlapped
,
1342 FSCTL_PIPE_TRANSCEIVE
,
1347 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1349 BaseSetLastNTError(Status
);
1353 if (lpBytesRead
!= NULL
)
1355 *lpBytesRead
= lpOverlapped
->InternalHigh
;
1360 IO_STATUS_BLOCK Iosb
;
1362 Status
= NtFsControlFile(hNamedPipe
,
1367 FSCTL_PIPE_TRANSCEIVE
,
1372 if (Status
== STATUS_PENDING
)
1374 Status
= NtWaitForSingleObject(hNamedPipe
,
1377 if (NT_SUCCESS(Status
))
1378 Status
= Iosb
.Status
;
1381 if (NT_SUCCESS(Status
))
1383 /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1384 check that case either and crashes (only after the operation
1386 *lpBytesRead
= Iosb
.Information
;
1390 BaseSetLastNTError(Status
);