kernel32: Move named pipe functions to kernelbase.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1834d9e9fe
commit
bc28ed4c6c
|
@ -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
|
||||
|
|
|
@ -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.@)
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue