kernel32: Move named pipe functions to kernelbase.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-06-27 19:28:32 +02:00
parent 1834d9e9fe
commit bc28ed4c6c
4 changed files with 378 additions and 457 deletions

View File

@ -205,7 +205,7 @@
@ stdcall BuildCommDCBW(wstr ptr)
@ stdcall CallbackMayRunLong(ptr)
@ stdcall CallNamedPipeA(str ptr long ptr long ptr long)
@ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long)
@ stdcall -import CallNamedPipeW(wstr ptr long ptr long ptr long)
@ stub CancelDeviceWakeupRequest
@ stdcall CancelIo(long)
@ stdcall CancelIoEx(long ptr)
@ -243,7 +243,7 @@
@ stdcall CompareStringW(long long wstr long wstr long)
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long)
@ stdcall CompareStringOrdinal(wstr long wstr long long)
@ stdcall ConnectNamedPipe(long ptr)
@ stdcall -import ConnectNamedPipe(long ptr)
@ stub ConsoleMenuControl
@ stub ConsoleSubst
@ stdcall ContinueDebugEvent(long long long)
@ -304,7 +304,7 @@
@ stdcall -import CreateMutexExW(ptr wstr long long)
@ stdcall -import CreateMutexW(ptr long wstr)
@ stdcall CreateNamedPipeA(str long long long long long long ptr)
@ stdcall CreateNamedPipeW(wstr long long long long long long ptr)
@ stdcall -import CreateNamedPipeW(wstr long long long long long long ptr)
# @ stub CreateNlsSecurityDescriptor
@ stdcall CreatePipe(ptr ptr ptr long)
# @ stub CreatePrivateNamespaceA
@ -378,7 +378,7 @@
@ stdcall -arch=x86_64 DequeueUmsCompletionListItems(ptr long ptr)
@ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr)
@ stdcall DisableThreadLibraryCalls(long)
@ stdcall DisconnectNamedPipe(long)
@ stdcall -import DisconnectNamedPipe(long)
@ stdcall DnsHostnameToComputerNameA (str ptr ptr)
@ stdcall DnsHostnameToComputerNameW (wstr ptr ptr)
@ stdcall DosDateTimeToFileTime(long long ptr)
@ -731,7 +731,7 @@
@ stdcall GetNamedPipeClientSessionId(long ptr)
@ stdcall GetNamedPipeHandleStateA(long ptr ptr ptr ptr str long)
@ stdcall GetNamedPipeHandleStateW(long ptr ptr ptr ptr wstr long)
@ stdcall GetNamedPipeInfo(long ptr ptr ptr ptr)
@ stdcall -import GetNamedPipeInfo(long ptr ptr ptr ptr)
@ stdcall GetNamedPipeServerProcessId(long ptr)
@ stdcall GetNamedPipeServerSessionId(long ptr)
@ stdcall GetNativeSystemInfo(ptr)
@ -1138,7 +1138,7 @@
@ stdcall OutputDebugStringW(wstr)
@ stdcall PeekConsoleInputA(ptr ptr long ptr)
@ stdcall PeekConsoleInputW(ptr ptr long ptr)
@ stdcall PeekNamedPipe(long ptr long ptr ptr ptr)
@ stdcall -import PeekNamedPipe(long ptr long ptr ptr ptr)
@ stdcall -import PostQueuedCompletionStatus(long long ptr ptr)
@ stdcall PowerClearRequest(long long)
@ stdcall PowerCreateRequest(ptr)
@ -1423,7 +1423,7 @@
@ stdcall SetMailslotInfo(long long)
@ stub SetMessageWaitingIndicator
# @ stub SetNamedPipeAttribute
@ stdcall SetNamedPipeHandleState(long ptr ptr ptr)
@ stdcall -import SetNamedPipeHandleState(long ptr ptr ptr)
@ stdcall SetPriorityClass(long long)
@ stdcall SetProcessAffinityMask(long long)
@ stdcall SetProcessAffinityUpdateMode(long long)
@ -1509,7 +1509,7 @@
@ stdcall TlsGetValue(long)
@ stdcall TlsSetValue(long ptr)
@ stdcall Toolhelp32ReadProcessMemory(long ptr ptr long ptr)
@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr)
@ stdcall -import TransactNamedPipe(long ptr long ptr long ptr ptr)
@ stdcall TransmitCommChar(long long)
@ stub TrimVirtualBuffer
@ stdcall TryAcquireSRWLockExclusive(ptr) ntdll.RtlTryAcquireSRWLockExclusive
@ -1581,7 +1581,7 @@
@ stdcall WaitForThreadpoolWaitCallbacks(ptr long) ntdll.TpWaitForWait
@ stdcall WaitForThreadpoolWorkCallbacks(ptr long) ntdll.TpWaitForWork
@ stdcall WaitNamedPipeA (str long)
@ stdcall WaitNamedPipeW (wstr long)
@ stdcall -import WaitNamedPipeW (wstr long)
@ stdcall WakeAllConditionVariable(ptr) ntdll.RtlWakeAllConditionVariable
@ stdcall WakeConditionVariable(ptr) ntdll.RtlWakeConditionVariable
# @ stub WerGetFlags

View File

@ -708,131 +708,6 @@ HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
}
/***********************************************************************
* CreateNamedPipeW (KERNEL32.@)
*/
HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
DWORD dwPipeMode, DWORD nMaxInstances,
DWORD nOutBufferSize, DWORD nInBufferSize,
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
{
HANDLE handle;
UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
DWORD access, options, sharing;
BOOLEAN pipe_type, read_mode, non_block;
NTSTATUS status;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER timeout;
TRACE("(%s, %#08x, %#08x, %d, %d, %d, %d, %p)\n",
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
{
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE;
}
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
RtlFreeUnicodeString( &nt_name );
return INVALID_HANDLE_VALUE;
}
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &nt_name;
attr.Attributes = OBJ_CASE_INSENSITIVE |
((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
attr.SecurityQualityOfService = NULL;
switch(dwOpenMode & 3)
{
case PIPE_ACCESS_INBOUND:
sharing = FILE_SHARE_WRITE;
access = GENERIC_READ;
break;
case PIPE_ACCESS_OUTBOUND:
sharing = FILE_SHARE_READ;
access = GENERIC_WRITE;
break;
case PIPE_ACCESS_DUPLEX:
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
access = GENERIC_READ | GENERIC_WRITE;
break;
default:
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE;
}
access |= SYNCHRONIZE;
options = 0;
if (dwOpenMode & WRITE_DAC) access |= WRITE_DAC;
if (dwOpenMode & WRITE_OWNER) access |= WRITE_OWNER;
if (dwOpenMode & ACCESS_SYSTEM_SECURITY) access |= ACCESS_SYSTEM_SECURITY;
if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_NONALERT;
pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) != 0;
read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) != 0;
non_block = (dwPipeMode & PIPE_NOWAIT) != 0;
if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ~0U;
timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
SetLastError(0);
status = NtCreateNamedPipeFile(&handle, access, &attr, &iosb, sharing,
FILE_OVERWRITE_IF, options, pipe_type,
read_mode, non_block, nMaxInstances,
nInBufferSize, nOutBufferSize, &timeout);
RtlFreeUnicodeString( &nt_name );
if (status)
{
handle = INVALID_HANDLE_VALUE;
SetLastError( RtlNtStatusToDosError(status) );
}
return handle;
}
/***********************************************************************
* PeekNamedPipe (KERNEL32.@)
*/
BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
{
FILE_PIPE_PEEK_BUFFER local_buffer;
FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
IO_STATUS_BLOCK io;
NTSTATUS status;
if (cbBuffer && !(buffer = HeapAlloc( GetProcessHeap(), 0,
FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ))))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
status = NtFsControlFile( hPipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ) );
if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS;
if (!status)
{
ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
if (lpcbRead) *lpcbRead = read_size;
if (lpcbMessage) *lpcbMessage = buffer->MessageLength - read_size;
if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
}
else SetLastError( RtlNtStatusToDosError(status) );
if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
return !status;
}
/***********************************************************************
* WaitNamedPipeA (KERNEL32.@)
*/
@ -851,238 +726,6 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
}
/***********************************************************************
* WaitNamedPipeW (KERNEL32.@)
*
* Waits for a named pipe instance to become available
*
* PARAMS
* name [I] Pointer to a named pipe name to wait for
* nTimeOut [I] How long to wait in ms
*
* RETURNS
* TRUE: Success, named pipe can be opened with CreateFile
* FALSE: Failure, GetLastError can be called for further details
*/
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
{
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
NTSTATUS status;
UNICODE_STRING nt_name, pipe_dev_name;
FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES attr;
ULONG sz_pipe_wait;
HANDLE pipe_dev;
TRACE("%s 0x%08x\n",debugstr_w(name),nTimeOut);
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
return FALSE;
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ||
nt_name.Length < sizeof(leadin) ||
strncmpiW( nt_name.Buffer, leadin, ARRAY_SIZE( leadin )) != 0)
{
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE;
}
sz_pipe_wait = sizeof(*pipe_wait) + nt_name.Length - sizeof(leadin) - sizeof(WCHAR);
if (!(pipe_wait = HeapAlloc( GetProcessHeap(), 0, sz_pipe_wait)))
{
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
}
pipe_dev_name.Buffer = nt_name.Buffer;
pipe_dev_name.Length = sizeof(leadin);
pipe_dev_name.MaximumLength = sizeof(leadin);
InitializeObjectAttributes(&attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr,
&iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (status != STATUS_SUCCESS)
{
HeapFree( GetProcessHeap(), 0, pipe_wait);
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE;
}
pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT);
if (nTimeOut == NMPWAIT_WAIT_FOREVER)
pipe_wait->Timeout.QuadPart = ((ULONGLONG)0x7fffffff << 32) | 0xffffffff;
else
pipe_wait->Timeout.QuadPart = (ULONGLONG)nTimeOut * -10000;
pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
memcpy( pipe_wait->Name, nt_name.Buffer + ARRAY_SIZE( leadin ), pipe_wait->NameLength );
RtlFreeUnicodeString( &nt_name );
status = NtFsControlFile( pipe_dev, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
pipe_wait, sz_pipe_wait, NULL, 0 );
HeapFree( GetProcessHeap(), 0, pipe_wait );
NtClose( pipe_dev );
if(status != STATUS_SUCCESS)
{
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
else
return TRUE;
}
/***********************************************************************
* ConnectNamedPipe (KERNEL32.@)
*
* Connects to a named pipe
*
* Parameters
* hPipe: A handle to a named pipe returned by CreateNamedPipe
* overlapped: Optional OVERLAPPED struct
*
* Return values
* TRUE: Success
* FALSE: Failure, GetLastError can be called for further details
*/
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
{
NTSTATUS status;
IO_STATUS_BLOCK status_block;
LPVOID cvalue = NULL;
TRACE("(%p,%p)\n", hPipe, overlapped);
if(overlapped)
{
overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
}
status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, cvalue,
overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
if (status == STATUS_PENDING && !overlapped)
{
WaitForSingleObject(hPipe, INFINITE);
status = status_block.u.Status;
}
if (status == STATUS_SUCCESS) return TRUE;
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
/***********************************************************************
* DisconnectNamedPipe (KERNEL32.@)
*
* Disconnects from a named pipe
*
* Parameters
* hPipe: A handle to a named pipe returned by CreateNamedPipe
*
* Return values
* TRUE: Success
* FALSE: Failure, GetLastError can be called for further details
*/
BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
{
NTSTATUS status;
IO_STATUS_BLOCK io_block;
TRACE("(%p)\n",hPipe);
status = NtFsControlFile(hPipe, 0, NULL, NULL, &io_block, FSCTL_PIPE_DISCONNECT,
NULL, 0, NULL, 0);
if (status == STATUS_SUCCESS) return TRUE;
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
/***********************************************************************
* TransactNamedPipe (KERNEL32.@)
*/
BOOL WINAPI TransactNamedPipe(
HANDLE handle, LPVOID write_buf, DWORD write_size, LPVOID read_buf,
DWORD read_size, LPDWORD bytes_read, LPOVERLAPPED overlapped)
{
IO_STATUS_BLOCK default_iosb, *iosb = &default_iosb;
HANDLE event = NULL;
void *cvalue = NULL;
NTSTATUS status;
TRACE("%p %p %u %p %u %p %p\n", handle, write_buf, write_size, read_buf,
read_size, bytes_read, overlapped);
if (overlapped)
{
event = overlapped->hEvent;
iosb = (IO_STATUS_BLOCK *)overlapped;
if (((ULONG_PTR)event & 1) == 0) cvalue = overlapped;
}
else
{
iosb->Information = 0;
}
status = NtFsControlFile(handle, event, NULL, cvalue, iosb, FSCTL_PIPE_TRANSCEIVE,
write_buf, write_size, read_buf, read_size);
if (status == STATUS_PENDING && !overlapped)
{
WaitForSingleObject(handle, INFINITE);
status = iosb->u.Status;
}
if (bytes_read) *bytes_read = overlapped && status ? 0 : iosb->Information;
if (status)
{
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}
return TRUE;
}
/***********************************************************************
* GetNamedPipeInfo (KERNEL32.@)
*/
BOOL WINAPI GetNamedPipeInfo(
HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
{
FILE_PIPE_LOCAL_INFORMATION fpli;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
FilePipeLocalInformation);
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (lpFlags)
{
*lpFlags = (fpli.NamedPipeEnd & FILE_PIPE_SERVER_END) ?
PIPE_SERVER_END : PIPE_CLIENT_END;
*lpFlags |= (fpli.NamedPipeType & FILE_PIPE_TYPE_MESSAGE) ?
PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
}
if (lpOutputBufferSize) *lpOutputBufferSize = fpli.OutboundQuota;
if (lpInputBufferSize) *lpInputBufferSize = fpli.InboundQuota;
if (lpMaxInstances) *lpMaxInstances = fpli.MaximumInstances;
return TRUE;
}
/***********************************************************************
* GetNamedPipeClientProcessId (KERNEL32.@)
*/
@ -1232,45 +875,6 @@ BOOL WINAPI GetNamedPipeHandleStateW(
return TRUE;
}
/***********************************************************************
* SetNamedPipeHandleState (KERNEL32.@)
*/
BOOL WINAPI SetNamedPipeHandleState(
HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
LPDWORD lpCollectDataTimeout)
{
/* should be a fixme, but this function is called a lot by the RPC
* runtime, and it slows down InstallShield a fair bit. */
WARN("semi-stub: %p %p/%d %p %p\n",
hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
if (lpMode)
{
FILE_PIPE_INFORMATION fpi;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
if (*lpMode & ~(PIPE_READMODE_MESSAGE | PIPE_NOWAIT))
status = STATUS_INVALID_PARAMETER;
else
{
fpi.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
fpi.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
status = NtSetInformationFile(hNamedPipe, &iosb, &fpi, sizeof(fpi), FilePipeInformation);
}
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
}
return TRUE;
}
/***********************************************************************
* CallNamedPipeA (KERNEL32.@)
*/
@ -1301,49 +905,6 @@ BOOL WINAPI CallNamedPipeA(
return ret;
}
/***********************************************************************
* CallNamedPipeW (KERNEL32.@)
*/
BOOL WINAPI CallNamedPipeW(
LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
LPVOID lpOutput, DWORD lpOutputSize,
LPDWORD lpBytesRead, DWORD nTimeout)
{
HANDLE pipe;
BOOL ret;
DWORD mode;
TRACE("%s %p %d %p %d %p %d\n",
debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
lpOutput, lpOutputSize, lpBytesRead, nTimeout);
pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
ret = WaitNamedPipeW(lpNamedPipeName, nTimeout);
if (!ret)
return FALSE;
pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
return FALSE;
}
mode = PIPE_READMODE_MESSAGE;
ret = SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
if (!ret)
{
CloseHandle(pipe);
return FALSE;
}
ret = TransactNamedPipe(pipe, lpInput, lpInputSize, lpOutput, lpOutputSize, lpBytesRead, NULL);
CloseHandle(pipe);
if (!ret)
return FALSE;
return TRUE;
}
/******************************************************************
* CreatePipe (KERNEL32.@)
*

View File

@ -100,7 +100,7 @@
@ stub BemFreeContract
@ stub BemFreeReference
# @ stub CLOSE_LOCAL_HANDLE_INTERNAL
@ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long) kernel32.CallNamedPipeW
@ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long)
@ stdcall CallbackMayRunLong(ptr) kernel32.CallbackMayRunLong
@ stdcall CancelIo(long) kernel32.CancelIo
@ stdcall CancelIoEx(long ptr) kernel32.CancelIoEx
@ -157,7 +157,7 @@
@ stdcall CompareStringEx(wstr long wstr long wstr long ptr ptr long) kernel32.CompareStringEx
@ stdcall CompareStringOrdinal(wstr long wstr long long) kernel32.CompareStringOrdinal
@ stdcall CompareStringW(long long wstr long wstr long) kernel32.CompareStringW
@ stdcall ConnectNamedPipe(long ptr) kernel32.ConnectNamedPipe
@ stdcall ConnectNamedPipe(long ptr)
@ stdcall ContinueDebugEvent(long long long) kernel32.ContinueDebugEvent
@ stdcall ConvertDefaultLocale(long) kernel32.ConvertDefaultLocale
@ stdcall ConvertFiberToThread() kernel32.ConvertFiberToThread
@ -199,7 +199,7 @@
@ stdcall CreateMutexExA(ptr str long long)
@ stdcall CreateMutexExW(ptr wstr long long)
@ stdcall CreateMutexW(ptr long wstr)
@ stdcall CreateNamedPipeW(wstr long long long long long long ptr) kernel32.CreateNamedPipeW
@ stdcall CreateNamedPipeW(wstr long long long long long long ptr)
@ stdcall CreatePipe(ptr ptr ptr long) kernel32.CreatePipe
# @ stub CreatePrivateNamespaceW
@ stdcall CreatePrivateObjectSecurity(ptr ptr ptr long long ptr)
@ -266,7 +266,7 @@
@ stdcall DisableThreadLibraryCalls(long) kernel32.DisableThreadLibraryCalls
@ stdcall DisassociateCurrentThreadFromCallback(ptr) kernel32.DisassociateCurrentThreadFromCallback
# @ stub DiscardVirtualMemory
@ stdcall DisconnectNamedPipe(long) kernel32.DisconnectNamedPipe
@ stdcall DisconnectNamedPipe(long)
# @ stub DnsHostnameToComputerNameExW
# @ stub DsBindWithSpnExW
# @ stub DsCrackNamesW
@ -571,7 +571,7 @@
@ stub GetNamedPipeAttribute
@ stub GetNamedPipeClientComputerNameW
@ stdcall GetNamedPipeHandleStateW(long ptr ptr ptr ptr wstr long) kernel32.GetNamedPipeHandleStateW
@ stdcall GetNamedPipeInfo(long ptr ptr ptr ptr) kernel32.GetNamedPipeInfo
@ stdcall GetNamedPipeInfo(long ptr ptr ptr ptr)
@ stdcall GetNativeSystemInfo(ptr) kernel32.GetNativeSystemInfo
# @ stub GetNextFgPolicyRefreshInfoInternal
@ stdcall GetNumaHighestNodeNumber(ptr) kernel32.GetNumaHighestNodeNumber
@ -1144,7 +1144,7 @@
# @ stub PcwSetQueryItemUserData
@ stdcall PeekConsoleInputA(ptr ptr long ptr) kernel32.PeekConsoleInputA
@ stdcall PeekConsoleInputW(ptr ptr long ptr) kernel32.PeekConsoleInputW
@ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) kernel32.PeekNamedPipe
@ stdcall PeekNamedPipe(long ptr long ptr ptr ptr)
@ stdcall PerfCreateInstance(long ptr wstr long)
# @ stub PerfDecrementULongCounterValue
# @ stub PerfDecrementULongLongCounterValue
@ -1449,7 +1449,7 @@
@ stdcall SetLastError(long) kernel32.SetLastError
@ stdcall SetLocalTime(ptr) kernel32.SetLocalTime
@ stdcall SetLocaleInfoW(long long wstr) kernel32.SetLocaleInfoW
@ stdcall SetNamedPipeHandleState(long ptr ptr ptr) kernel32.SetNamedPipeHandleState
@ stdcall SetNamedPipeHandleState(long ptr ptr ptr)
@ stdcall SetPriorityClass(long long) kernel32.SetPriorityClass
@ stdcall SetPrivateObjectSecurity(long ptr ptr ptr long)
@ stub SetPrivateObjectSecurityEx
@ -1604,7 +1604,7 @@
@ stdcall TraceEvent(int64 ptr) ntdll.EtwLogTraceEvent
@ varargs TraceMessage(int64 long ptr long) ntdll.EtwTraceMessage
@ stdcall TraceMessageVa(int64 long ptr long ptr) ntdll.EtwTraceMessageVa
@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr) kernel32.TransactNamedPipe
@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr)
@ stdcall TransmitCommChar(long long) kernel32.TransmitCommChar
@ stdcall TryAcquireSRWLockExclusive(ptr) kernel32.TryAcquireSRWLockExclusive
@ stdcall TryAcquireSRWLockShared(ptr) kernel32.TryAcquireSRWLockShared
@ -1696,7 +1696,7 @@
@ stdcall WaitForThreadpoolWaitCallbacks(ptr long) kernel32.WaitForThreadpoolWaitCallbacks
@ stdcall WaitForThreadpoolWorkCallbacks(ptr long) kernel32.WaitForThreadpoolWorkCallbacks
# @ stub WaitForUserPolicyForegroundProcessingInternal
@ stdcall WaitNamedPipeW(wstr long) kernel32.WaitNamedPipeW
@ stdcall WaitNamedPipeW(wstr long)
@ stdcall WaitOnAddress(ptr ptr long long)
@ stdcall WakeAllConditionVariable(ptr) kernel32.WakeAllConditionVariable
@ stdcall WakeByAddressAll(ptr) ntdll.RtlWakeAddressAll

View File

@ -866,3 +866,363 @@ BOOL WINAPI DECLSPEC_HOTPATCH PostQueuedCompletionStatus( HANDLE port, DWORD cou
return set_ntstatus( NtSetIoCompletion( port, key, (ULONG_PTR)overlapped, STATUS_SUCCESS, count ));
}
/***********************************************************************
* Named pipes
***********************************************************************/
/***********************************************************************
* CallNamedPipeW (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH CallNamedPipeW( LPCWSTR name, LPVOID input, DWORD in_size,
LPVOID output, DWORD out_size,
LPDWORD read_size, DWORD timeout )
{
HANDLE pipe;
BOOL ret;
DWORD mode;
TRACE( "%s %p %d %p %d %p %d\n", debugstr_w(name),
input, in_size, output, out_size, read_size, timeout );
pipe = CreateFileW( name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
if (pipe == INVALID_HANDLE_VALUE)
{
if (!WaitNamedPipeW( name, timeout )) return FALSE;
pipe = CreateFileW( name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
if (pipe == INVALID_HANDLE_VALUE) return FALSE;
}
mode = PIPE_READMODE_MESSAGE;
ret = SetNamedPipeHandleState( pipe, &mode, NULL, NULL );
if (ret) ret = TransactNamedPipe( pipe, input, in_size, output, out_size, read_size, NULL );
CloseHandle( pipe );
return ret;
}
/***********************************************************************
* ConnectNamedPipe (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH ConnectNamedPipe( HANDLE pipe, LPOVERLAPPED overlapped )
{
NTSTATUS status;
IO_STATUS_BLOCK status_block;
LPVOID cvalue = NULL;
TRACE( "(%p,%p)\n", pipe, overlapped );
if (overlapped)
{
overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
}
status = NtFsControlFile( pipe, overlapped ? overlapped->hEvent : NULL, NULL, cvalue,
overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0 );
if (status == STATUS_PENDING && !overlapped)
{
WaitForSingleObject( pipe, INFINITE );
status = status_block.u.Status;
}
return set_ntstatus( status );
}
/***********************************************************************
* CreateNamedPipeW (kernelbase.@)
*/
HANDLE WINAPI DECLSPEC_HOTPATCH CreateNamedPipeW( LPCWSTR name, DWORD open_mode, DWORD pipe_mode,
DWORD instances, DWORD out_buff, DWORD in_buff,
DWORD timeout, LPSECURITY_ATTRIBUTES sa )
{
HANDLE handle;
UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
DWORD access, options, sharing;
BOOLEAN pipe_type, read_mode, non_block;
NTSTATUS status;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER time;
TRACE( "(%s, %#08x, %#08x, %d, %d, %d, %d, %p)\n", debugstr_w(name),
open_mode, pipe_mode, instances, out_buff, in_buff, timeout, sa );
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
{
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE;
}
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
RtlFreeUnicodeString( &nt_name );
return INVALID_HANDLE_VALUE;
}
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &nt_name;
attr.Attributes = OBJ_CASE_INSENSITIVE | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
attr.SecurityQualityOfService = NULL;
switch (open_mode & 3)
{
case PIPE_ACCESS_INBOUND:
sharing = FILE_SHARE_WRITE;
access = GENERIC_READ;
break;
case PIPE_ACCESS_OUTBOUND:
sharing = FILE_SHARE_READ;
access = GENERIC_WRITE;
break;
case PIPE_ACCESS_DUPLEX:
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
access = GENERIC_READ | GENERIC_WRITE;
break;
default:
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_HANDLE_VALUE;
}
access |= SYNCHRONIZE;
options = 0;
if (open_mode & WRITE_DAC) access |= WRITE_DAC;
if (open_mode & WRITE_OWNER) access |= WRITE_OWNER;
if (open_mode & ACCESS_SYSTEM_SECURITY) access |= ACCESS_SYSTEM_SECURITY;
if (open_mode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
if (!(open_mode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_NONALERT;
pipe_type = (pipe_mode & PIPE_TYPE_MESSAGE) != 0;
read_mode = (pipe_mode & PIPE_READMODE_MESSAGE) != 0;
non_block = (pipe_mode & PIPE_NOWAIT) != 0;
if (instances >= PIPE_UNLIMITED_INSTANCES) instances = ~0U;
time.QuadPart = (ULONGLONG)timeout * -10000;
SetLastError( 0 );
status = NtCreateNamedPipeFile( &handle, access, &attr, &iosb, sharing,
FILE_OVERWRITE_IF, options, pipe_type,
read_mode, non_block, instances, in_buff, out_buff, &time );
RtlFreeUnicodeString( &nt_name );
if (status)
{
handle = INVALID_HANDLE_VALUE;
SetLastError( RtlNtStatusToDosError(status) );
}
return handle;
}
/***********************************************************************
* DisconnectNamedPipe (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH DisconnectNamedPipe( HANDLE pipe )
{
IO_STATUS_BLOCK io_block;
TRACE( "(%p)\n", pipe );
return set_ntstatus( NtFsControlFile( pipe, 0, NULL, NULL, &io_block,
FSCTL_PIPE_DISCONNECT, NULL, 0, NULL, 0 ));
}
/***********************************************************************
* GetNamedPipeInfo (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH GetNamedPipeInfo( HANDLE pipe, LPDWORD flags, LPDWORD out_size,
LPDWORD in_size, LPDWORD instances )
{
FILE_PIPE_LOCAL_INFORMATION info;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
status = NtQueryInformationFile( pipe, &iosb, &info, sizeof(info), FilePipeLocalInformation );
if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
}
if (flags)
{
*flags = (info.NamedPipeEnd & FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
*flags |= (info.NamedPipeType & FILE_PIPE_TYPE_MESSAGE) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
}
if (out_size) *out_size = info.OutboundQuota;
if (in_size) *in_size = info.InboundQuota;
if (instances) *instances = info.MaximumInstances;
return TRUE;
}
/***********************************************************************
* PeekNamedPipe (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH PeekNamedPipe( HANDLE pipe, LPVOID out_buffer, DWORD size,
LPDWORD read_size, LPDWORD avail, LPDWORD message )
{
FILE_PIPE_PEEK_BUFFER local_buffer;
FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
IO_STATUS_BLOCK io;
NTSTATUS status;
if (size && !(buffer = HeapAlloc( GetProcessHeap(), 0,
FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[size] ))))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
status = NtFsControlFile( pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[size] ) );
if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS;
if (!status)
{
ULONG count = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
if (avail) *avail = buffer->ReadDataAvailable;
if (read_size) *read_size = count;
if (message) *message = buffer->MessageLength - count;
if (out_buffer) memcpy( out_buffer, buffer->Data, count );
}
else SetLastError( RtlNtStatusToDosError(status) );
if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
return !status;
}
/***********************************************************************
* SetNamedPipeHandleState (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH SetNamedPipeHandleState( HANDLE pipe, LPDWORD mode,
LPDWORD count, LPDWORD timeout )
{
FILE_PIPE_INFORMATION info;
IO_STATUS_BLOCK iosb;
NTSTATUS status = STATUS_SUCCESS;
/* should be a fixme, but this function is called a lot by the RPC
* runtime, and it slows down InstallShield a fair bit. */
WARN( "semi-stub: %p %p/%d %p %p\n", pipe, mode, mode ? *mode : 0, count, timeout );
if (mode)
{
if (*mode & ~(PIPE_READMODE_MESSAGE | PIPE_NOWAIT)) status = STATUS_INVALID_PARAMETER;
else
{
info.CompletionMode = (*mode & PIPE_NOWAIT) ?
FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
info.ReadMode = (*mode & PIPE_READMODE_MESSAGE) ?
FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
status = NtSetInformationFile( pipe, &iosb, &info, sizeof(info), FilePipeInformation );
}
}
return set_ntstatus( status );
}
/***********************************************************************
* TransactNamedPipe (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH TransactNamedPipe( HANDLE handle, LPVOID write_buf, DWORD write_size,
LPVOID read_buf, DWORD read_size, LPDWORD bytes_read,
LPOVERLAPPED overlapped)
{
IO_STATUS_BLOCK default_iosb, *iosb = &default_iosb;
HANDLE event = NULL;
void *cvalue = NULL;
NTSTATUS status;
TRACE( "%p %p %u %p %u %p %p\n", handle,
write_buf, write_size, read_buf, read_size, bytes_read, overlapped );
if (overlapped)
{
event = overlapped->hEvent;
iosb = (IO_STATUS_BLOCK *)overlapped;
if (((ULONG_PTR)event & 1) == 0) cvalue = overlapped;
}
else
{
iosb->Information = 0;
}
status = NtFsControlFile( handle, event, NULL, cvalue, iosb, FSCTL_PIPE_TRANSCEIVE,
write_buf, write_size, read_buf, read_size );
if (status == STATUS_PENDING && !overlapped)
{
WaitForSingleObject(handle, INFINITE);
status = iosb->u.Status;
}
if (bytes_read) *bytes_read = overlapped && status ? 0 : iosb->Information;
return set_ntstatus( status );
}
/***********************************************************************
* WaitNamedPipeW (kernelbase.@)
*/
BOOL WINAPI DECLSPEC_HOTPATCH WaitNamedPipeW( LPCWSTR name, DWORD timeout )
{
static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
NTSTATUS status;
UNICODE_STRING nt_name, pipe_dev_name;
FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES attr;
ULONG wait_size;
HANDLE pipe_dev;
TRACE( "%s 0x%08x\n", debugstr_w(name), timeout );
if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL )) return FALSE;
if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ||
nt_name.Length < sizeof(leadin) ||
wcsnicmp( nt_name.Buffer, leadin, ARRAY_SIZE( leadin )) != 0)
{
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE;
}
wait_size = sizeof(*pipe_wait) + nt_name.Length - sizeof(leadin) - sizeof(WCHAR);
if (!(pipe_wait = HeapAlloc( GetProcessHeap(), 0, wait_size)))
{
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
}
pipe_dev_name.Buffer = nt_name.Buffer;
pipe_dev_name.Length = sizeof(leadin);
pipe_dev_name.MaximumLength = sizeof(leadin);
InitializeObjectAttributes( &attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL );
status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr,
&iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (status != STATUS_SUCCESS)
{
HeapFree( GetProcessHeap(), 0, pipe_wait );
RtlFreeUnicodeString( &nt_name );
SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE;
}
pipe_wait->TimeoutSpecified = !(timeout == NMPWAIT_USE_DEFAULT_WAIT);
if (timeout == NMPWAIT_WAIT_FOREVER)
pipe_wait->Timeout.QuadPart = ((ULONGLONG)0x7fffffff << 32) | 0xffffffff;
else
pipe_wait->Timeout.QuadPart = (ULONGLONG)timeout * -10000;
pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
memcpy( pipe_wait->Name, nt_name.Buffer + ARRAY_SIZE( leadin ), pipe_wait->NameLength );
RtlFreeUnicodeString( &nt_name );
status = NtFsControlFile( pipe_dev, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
pipe_wait, wait_size, NULL, 0 );
HeapFree( GetProcessHeap(), 0, pipe_wait );
NtClose( pipe_dev );
return set_ntstatus( status );
}