From bc28ed4c6c626f918f1b6f92e7e44f9694b12c10 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 27 Jun 2019 19:28:32 +0200 Subject: [PATCH] kernel32: Move named pipe functions to kernelbase. Signed-off-by: Alexandre Julliard --- dlls/kernel32/kernel32.spec | 18 +- dlls/kernel32/sync.c | 439 -------------------------------- dlls/kernelbase/kernelbase.spec | 18 +- dlls/kernelbase/sync.c | 360 ++++++++++++++++++++++++++ 4 files changed, 378 insertions(+), 457 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 529402825e1..6163f1a0828 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -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 diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index e4c54c52685..962fdb4e070 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -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.@) * diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 2d4b6c057fc..96c20497f4a 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -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 diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index bb5ae935e00..4dac6d9fcc4 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -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 ); +}