Blame winpr/libwinpr/pipe/pipe.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * Pipe Functions
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2017 Armin Novak <armin.novak@thincast.com>
Packit 1fb8d4
 * Copyright 2017 Thincast Technologies GmbH
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/path.h>
Packit 1fb8d4
#include <winpr/synch.h>
Packit 1fb8d4
#include <winpr/handle.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/pipe.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_UNISTD_H
Packit 1fb8d4
#include <unistd.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#include "../handle/handle.h"
Packit 1fb8d4
Packit 1fb8d4
#include <fcntl.h>
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
#include <sys/un.h>
Packit 1fb8d4
#include <sys/socket.h>
Packit 1fb8d4
#include <assert.h>
Packit 1fb8d4
#include <unistd.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_SYS_AIO_H
Packit 1fb8d4
#undef HAVE_SYS_AIO_H /* disable for now, incomplete */
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_SYS_AIO_H
Packit 1fb8d4
#include <aio.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "pipe.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("pipe")
Packit 1fb8d4
Packit 1fb8d4
/*
Packit 1fb8d4
 * Since the WinPR implementation of named pipes makes use of UNIX domain
Packit 1fb8d4
 * sockets, it is not possible to bind the same name more than once (i.e.,
Packit 1fb8d4
 * SO_REUSEADDR does not work with UNIX domain sockets).  As a result, the
Packit 1fb8d4
 * first call to CreateNamedPipe with name n creates a "shared" UNIX domain
Packit 1fb8d4
 * socket descriptor that gets duplicated via dup() for the first and all
Packit 1fb8d4
 * subsequent calls to CreateNamedPipe with name n.
Packit 1fb8d4
 *
Packit 1fb8d4
 * The following array keeps track of the references to the shared socked
Packit 1fb8d4
 * descriptors. If an entry's reference count is zero the base socket
Packit 1fb8d4
 * descriptor gets closed and the entry is removed from the list.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static wArrayList* g_NamedPipeServerSockets = NULL;
Packit 1fb8d4
Packit 1fb8d4
typedef struct _NamedPipeServerSocketEntry
Packit 1fb8d4
{
Packit 1fb8d4
	char* name;
Packit 1fb8d4
	int serverfd;
Packit 1fb8d4
	int references;
Packit 1fb8d4
} NamedPipeServerSocketEntry;
Packit 1fb8d4
Packit 1fb8d4
static BOOL PipeIsHandled(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_PIPE* pPipe = (WINPR_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!pPipe || (pPipe->Type != HANDLE_TYPE_ANONYMOUS_PIPE))
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_INVALID_HANDLE);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int PipeGetFd(HANDLE handle)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_PIPE* pipe = (WINPR_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!PipeIsHandled(handle))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return pipe->fd;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PipeCloseHandle(HANDLE handle)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_PIPE* pipe = (WINPR_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!PipeIsHandled(handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (pipe->fd != -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		close(pipe->fd);
Packit 1fb8d4
		pipe->fd = -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(handle);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
Packit 1fb8d4
                     LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	int io_status;
Packit 1fb8d4
	WINPR_PIPE* pipe;
Packit 1fb8d4
	BOOL status = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pipe = (WINPR_PIPE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	do
Packit 1fb8d4
	{
Packit 1fb8d4
		io_status = read(pipe->fd, lpBuffer, nNumberOfBytesToRead);
Packit Service 5a9772
	} while ((io_status < 0) && (errno == EINTR));
Packit 1fb8d4
Packit 1fb8d4
	if (io_status < 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = FALSE;
Packit 1fb8d4
Packit 1fb8d4
		switch (errno)
Packit 1fb8d4
		{
Packit 1fb8d4
			case EWOULDBLOCK:
Packit 1fb8d4
				SetLastError(ERROR_NO_DATA);
Packit 1fb8d4
				break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpNumberOfBytesRead)
Packit 1fb8d4
		*lpNumberOfBytesRead = io_status;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL PipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
Packit 1fb8d4
                      LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	int io_status;
Packit 1fb8d4
	WINPR_PIPE* pipe;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pipe = (WINPR_PIPE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	do
Packit 1fb8d4
	{
Packit 1fb8d4
		io_status = write(pipe->fd, lpBuffer, nNumberOfBytesToWrite);
Packit Service 5a9772
	} while ((io_status < 0) && (errno == EINTR));
Packit 1fb8d4
Packit 1fb8d4
	if ((io_status < 0) && (errno == EWOULDBLOCK))
Packit 1fb8d4
		io_status = 0;
Packit 1fb8d4
Packit 1fb8d4
	*lpNumberOfBytesWritten = io_status;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static HANDLE_OPS ops = {
Packit Service 5a9772
	PipeIsHandled, PipeCloseHandle,
Packit Service 5a9772
	PipeGetFd,     NULL, /* CleanupHandle */
Packit Service 5a9772
	PipeRead,      NULL, /* FileReadEx */
Packit Service 5a9772
	NULL,                /* FileReadScatter */
Packit Service 5a9772
	PipeWrite,     NULL, /* FileWriteEx */
Packit Service 5a9772
	NULL,                /* FileWriteGather */
Packit Service 5a9772
	NULL,                /* FileGetFileSize */
Packit Service 5a9772
	NULL,                /*  FlushFileBuffers */
Packit Service 5a9772
	NULL,                /* FileSetEndOfFile */
Packit Service 5a9772
	NULL,                /* FileSetFilePointer */
Packit Service 5a9772
	NULL,                /* SetFilePointerEx */
Packit Service 5a9772
	NULL,                /* FileLockFile */
Packit Service 5a9772
	NULL,                /* FileLockFileEx */
Packit Service 5a9772
	NULL,                /* FileUnlockFile */
Packit Service 5a9772
	NULL,                /* FileUnlockFileEx */
Packit Service 5a9772
	NULL                 /* SetFileTime */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static BOOL NamedPipeIsHandled(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_NAMED_PIPE* pPipe = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!pPipe || (pPipe->Type != HANDLE_TYPE_NAMED_PIPE) || (pPipe == INVALID_HANDLE_VALUE))
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_INVALID_HANDLE);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int NamedPipeGetFd(HANDLE handle)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!NamedPipeIsHandled(handle))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (pipe->ServerMode)
Packit 1fb8d4
		return pipe->serverfd;
Packit 1fb8d4
Packit 1fb8d4
	return pipe->clientfd;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL NamedPipeCloseHandle(HANDLE handle)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit Service 5a9772
	/* This check confuses the analyzer. Since not all handle
Packit Service 5a9772
	 * types are handled here, it guesses that the memory of a
Packit Service 5a9772
	 * NamedPipeHandle may leak. */
Packit Service 5a9772
#ifndef __clang_analyzer__
Packit 1fb8d4
	if (!NamedPipeIsHandled(handle))
Packit 1fb8d4
		return FALSE;
Packit Service 5a9772
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->pfnUnrefNamedPipe)
Packit 1fb8d4
		pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
Packit 1fb8d4
Packit 1fb8d4
	free(pNamedPipe->name);
Packit 1fb8d4
	free(pNamedPipe->lpFileName);
Packit 1fb8d4
	free(pNamedPipe->lpFilePath);
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->serverfd != -1)
Packit 1fb8d4
		close(pNamedPipe->serverfd);
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->clientfd != -1)
Packit 1fb8d4
		close(pNamedPipe->clientfd);
Packit 1fb8d4
Packit 1fb8d4
	free(pNamedPipe);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL NamedPipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
Packit 1fb8d4
                   LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	int io_status;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pipe;
Packit 1fb8d4
	BOOL status = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pipe = (WINPR_NAMED_PIPE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (pipe->clientfd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		do
Packit 1fb8d4
		{
Packit 1fb8d4
			io_status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
Packit Service 5a9772
		} while ((io_status < 0) && (errno == EINTR));
Packit 1fb8d4
Packit 1fb8d4
		if (io_status == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_BROKEN_PIPE);
Packit 1fb8d4
			status = FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (io_status < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = FALSE;
Packit 1fb8d4
Packit 1fb8d4
			switch (errno)
Packit 1fb8d4
			{
Packit 1fb8d4
				case EWOULDBLOCK:
Packit 1fb8d4
					SetLastError(ERROR_NO_DATA);
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				default:
Packit 1fb8d4
					SetLastError(ERROR_BROKEN_PIPE);
Packit 1fb8d4
					break;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (lpNumberOfBytesRead)
Packit 1fb8d4
			*lpNumberOfBytesRead = io_status;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Overlapped I/O */
Packit 1fb8d4
		if (!lpOverlapped)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (pipe->clientfd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		pipe->lpOverlapped = lpOverlapped;
Packit 1fb8d4
#ifdef HAVE_SYS_AIO_H
Packit 1fb8d4
		{
Packit 1fb8d4
			int aio_status;
Packit 1fb8d4
			struct aiocb cb;
Packit 1fb8d4
			ZeroMemory(&cb, sizeof(struct aiocb));
Packit 1fb8d4
			cb.aio_fildes = pipe->clientfd;
Packit 1fb8d4
			cb.aio_buf = lpBuffer;
Packit 1fb8d4
			cb.aio_nbytes = nNumberOfBytesToRead;
Packit 1fb8d4
			cb.aio_offset = lpOverlapped->Offset;
Packit 1fb8d4
			cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
Packit 1fb8d4
			cb.aio_sigevent.sigev_signo = SIGIO;
Packit Service 5a9772
			cb.aio_sigevent.sigev_value.sival_ptr = (void*)lpOverlapped;
Packit 1fb8d4
			InstallAioSignalHandler();
Packit 1fb8d4
			aio_status = aio_read(&cb;;
Packit 1fb8d4
			WLog_DBG(TAG, "aio_read status: %d", aio_status);
Packit 1fb8d4
Packit 1fb8d4
			if (aio_status < 0)
Packit 1fb8d4
				status = FALSE;
Packit 1fb8d4
Packit 1fb8d4
			return status;
Packit 1fb8d4
		}
Packit 1fb8d4
#else
Packit 1fb8d4
		/* synchronous behavior */
Packit 1fb8d4
		lpOverlapped->Internal = 0;
Packit Service 5a9772
		lpOverlapped->InternalHigh = (ULONG_PTR)nNumberOfBytesToRead;
Packit Service 5a9772
		lpOverlapped->Pointer = (PVOID)lpBuffer;
Packit 1fb8d4
		SetEvent(lpOverlapped->hEvent);
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL NamedPipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
Packit 1fb8d4
                    LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	int io_status;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pipe;
Packit 1fb8d4
	BOOL status = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	pipe = (WINPR_NAMED_PIPE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (pipe->clientfd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		do
Packit 1fb8d4
		{
Packit 1fb8d4
			io_status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
Packit Service 5a9772
		} while ((io_status < 0) && (errno == EINTR));
Packit 1fb8d4
Packit 1fb8d4
		if (io_status < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			*lpNumberOfBytesWritten = 0;
Packit 1fb8d4
Packit 1fb8d4
			switch (errno)
Packit 1fb8d4
			{
Packit 1fb8d4
				case EWOULDBLOCK:
Packit 1fb8d4
					io_status = 0;
Packit 1fb8d4
					status = TRUE;
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				default:
Packit 1fb8d4
					status = FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		*lpNumberOfBytesWritten = io_status;
Packit 1fb8d4
		return status;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Overlapped I/O */
Packit 1fb8d4
		if (!lpOverlapped)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (pipe->clientfd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		pipe->lpOverlapped = lpOverlapped;
Packit 1fb8d4
#ifdef HAVE_SYS_AIO_H
Packit 1fb8d4
		{
Packit 1fb8d4
			struct aiocb cb;
Packit 1fb8d4
			ZeroMemory(&cb, sizeof(struct aiocb));
Packit 1fb8d4
			cb.aio_fildes = pipe->clientfd;
Packit Service 5a9772
			cb.aio_buf = (void*)lpBuffer;
Packit 1fb8d4
			cb.aio_nbytes = nNumberOfBytesToWrite;
Packit 1fb8d4
			cb.aio_offset = lpOverlapped->Offset;
Packit 1fb8d4
			cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
Packit 1fb8d4
			cb.aio_sigevent.sigev_signo = SIGIO;
Packit Service 5a9772
			cb.aio_sigevent.sigev_value.sival_ptr = (void*)lpOverlapped;
Packit 1fb8d4
			InstallAioSignalHandler();
Packit 1fb8d4
			io_status = aio_write(&cb;;
Packit 1fb8d4
			WLog_DBG("aio_write status: %d", io_status);
Packit 1fb8d4
Packit 1fb8d4
			if (io_status < 0)
Packit 1fb8d4
				status = FALSE;
Packit 1fb8d4
Packit 1fb8d4
			return status;
Packit 1fb8d4
		}
Packit 1fb8d4
#else
Packit 1fb8d4
		/* synchronous behavior */
Packit 1fb8d4
		lpOverlapped->Internal = 1;
Packit Service 5a9772
		lpOverlapped->InternalHigh = (ULONG_PTR)nNumberOfBytesToWrite;
Packit Service 5a9772
		lpOverlapped->Pointer = (PVOID)lpBuffer;
Packit 1fb8d4
		SetEvent(lpOverlapped->hEvent);
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static HANDLE_OPS namedOps = { NamedPipeIsHandled,
Packit Service 5a9772
	                           NamedPipeCloseHandle,
Packit Service 5a9772
	                           NamedPipeGetFd,
Packit Service 5a9772
	                           NULL, /* CleanupHandle */
Packit Service 5a9772
	                           NamedPipeRead,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NamedPipeWrite,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL,
Packit Service 5a9772
	                           NULL };
Packit 1fb8d4
Packit 1fb8d4
static BOOL InitWinPRPipeModule()
Packit 1fb8d4
{
Packit 1fb8d4
	if (g_NamedPipeServerSockets)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	g_NamedPipeServerSockets = ArrayList_New(FALSE);
Packit 1fb8d4
	return g_NamedPipeServerSockets != NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/*
Packit 1fb8d4
 * Unnamed pipe
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes,
Packit 1fb8d4
                DWORD nSize)
Packit 1fb8d4
{
Packit 1fb8d4
	int pipe_fd[2];
Packit 1fb8d4
	WINPR_PIPE* pReadPipe;
Packit 1fb8d4
	WINPR_PIPE* pWritePipe;
Packit 1fb8d4
	pipe_fd[0] = -1;
Packit 1fb8d4
	pipe_fd[1] = -1;
Packit 1fb8d4
Packit 1fb8d4
	if (pipe(pipe_fd) < 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "failed to create pipe");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	pReadPipe = (WINPR_PIPE*)calloc(1, sizeof(WINPR_PIPE));
Packit Service 5a9772
	pWritePipe = (WINPR_PIPE*)calloc(1, sizeof(WINPR_PIPE));
Packit 1fb8d4
Packit 1fb8d4
	if (!pReadPipe || !pWritePipe)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(pReadPipe);
Packit 1fb8d4
		free(pWritePipe);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pReadPipe->fd = pipe_fd[0];
Packit 1fb8d4
	pWritePipe->fd = pipe_fd[1];
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pReadPipe, HANDLE_TYPE_ANONYMOUS_PIPE, WINPR_FD_READ);
Packit 1fb8d4
	pReadPipe->ops = &ops;
Packit Service 5a9772
	*((ULONG_PTR*)hReadPipe) = (ULONG_PTR)pReadPipe;
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pWritePipe, HANDLE_TYPE_ANONYMOUS_PIPE, WINPR_FD_READ);
Packit 1fb8d4
	pWritePipe->ops = &ops;
Packit Service 5a9772
	*((ULONG_PTR*)hWritePipe) = (ULONG_PTR)pWritePipe;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Named pipe
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static void winpr_unref_named_pipe(WINPR_NAMED_PIPE* pNamedPipe)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	NamedPipeServerSocketEntry* baseSocket;
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	assert(pNamedPipe->name);
Packit 1fb8d4
	assert(g_NamedPipeServerSockets);
Packit Service 5a9772
	// WLog_VRB(TAG, "%p (%s)", (void*) pNamedPipe, pNamedPipe->name);
Packit 1fb8d4
	ArrayList_Lock(g_NamedPipeServerSockets);
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
Packit 1fb8d4
	{
Packit Service 5a9772
		baseSocket =
Packit Service 5a9772
		    (NamedPipeServerSocketEntry*)ArrayList_GetItem(g_NamedPipeServerSockets, index);
Packit 1fb8d4
		assert(baseSocket->name);
Packit 1fb8d4
Packit 1fb8d4
		if (!strcmp(baseSocket->name, pNamedPipe->name))
Packit 1fb8d4
		{
Packit 1fb8d4
			assert(baseSocket->references > 0);
Packit 1fb8d4
			assert(baseSocket->serverfd != -1);
Packit 1fb8d4
Packit 1fb8d4
			if (--baseSocket->references == 0)
Packit 1fb8d4
			{
Packit Service 5a9772
				// WLog_DBG(TAG, "removing shared server socked resource");
Packit Service 5a9772
				// WLog_DBG(TAG, "closing shared serverfd %d", baseSocket->serverfd);
Packit 1fb8d4
				ArrayList_Remove(g_NamedPipeServerSockets, baseSocket);
Packit 1fb8d4
				close(baseSocket->serverfd);
Packit 1fb8d4
				free(baseSocket->name);
Packit 1fb8d4
				free(baseSocket);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Unlock(g_NamedPipeServerSockets);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
Packit 1fb8d4
                        DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut,
Packit 1fb8d4
                        LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	char* lpPipePath;
Packit 1fb8d4
	struct sockaddr_un s;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe = NULL;
Packit 1fb8d4
	int serverfd = -1;
Packit 1fb8d4
	NamedPipeServerSocketEntry* baseSocket = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (dwOpenMode & FILE_FLAG_OVERLAPPED)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!lpName)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	if (!InitWinPRPipeModule())
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Lock(g_NamedPipeServerSockets);
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
Packit 1fb8d4
	pNamedPipe->serverfd = -1;
Packit 1fb8d4
	pNamedPipe->clientfd = -1;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pNamedPipe->name = _strdup(lpName)))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName)))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName)))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	pNamedPipe->dwOpenMode = dwOpenMode;
Packit 1fb8d4
	pNamedPipe->dwPipeMode = dwPipeMode;
Packit 1fb8d4
	pNamedPipe->nMaxInstances = nMaxInstances;
Packit 1fb8d4
	pNamedPipe->nOutBufferSize = nOutBufferSize;
Packit 1fb8d4
	pNamedPipe->nInBufferSize = nInBufferSize;
Packit 1fb8d4
	pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
Packit 1fb8d4
	pNamedPipe->dwFlagsAndAttributes = dwOpenMode;
Packit 1fb8d4
	pNamedPipe->clientfd = -1;
Packit 1fb8d4
	pNamedPipe->ServerMode = TRUE;
Packit 1fb8d4
	pNamedPipe->ops = &namedOps;
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
Packit 1fb8d4
	{
Packit Service 5a9772
		baseSocket =
Packit Service 5a9772
		    (NamedPipeServerSocketEntry*)ArrayList_GetItem(g_NamedPipeServerSockets, index);
Packit 1fb8d4
Packit 1fb8d4
		if (!strcmp(baseSocket->name, lpName))
Packit 1fb8d4
		{
Packit 1fb8d4
			serverfd = baseSocket->serverfd;
Packit Service 5a9772
			// WLog_DBG(TAG, "using shared socked resource for pipe %p (%s)", (void*) pNamedPipe,
Packit Service 5a9772
			// lpName);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* If this is the first instance of the named pipe... */
Packit 1fb8d4
	if (serverfd == -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Create the UNIX domain socket and start listening. */
Packit 1fb8d4
		if (!(lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA()))
Packit 1fb8d4
			goto out;
Packit 1fb8d4
Packit 1fb8d4
		if (!PathFileExistsA(lpPipePath))
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!CreateDirectoryA(lpPipePath, 0))
Packit 1fb8d4
			{
Packit 1fb8d4
				free(lpPipePath);
Packit 1fb8d4
				goto out;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			UnixChangeFileMode(lpPipePath, 0xFFFF);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		free(lpPipePath);
Packit 1fb8d4
Packit 1fb8d4
		if (PathFileExistsA(pNamedPipe->lpFilePath))
Packit 1fb8d4
			DeleteFileA(pNamedPipe->lpFilePath);
Packit 1fb8d4
Packit 1fb8d4
		if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "CreateNamedPipeA: socket error, %s", strerror(errno));
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		ZeroMemory(&s, sizeof(struct sockaddr_un));
Packit 1fb8d4
		s.sun_family = AF_UNIX;
Packit 1fb8d4
		sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
Packit 1fb8d4
Packit Service 5a9772
		if (bind(serverfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un)) == -1)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "CreateNamedPipeA: bind error, %s", strerror(errno));
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (listen(serverfd, 2) == -1)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "CreateNamedPipeA: listen error, %s", strerror(errno));
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF);
Packit 1fb8d4
Packit Service 5a9772
		if (!(baseSocket = (NamedPipeServerSocketEntry*)malloc(sizeof(NamedPipeServerSocketEntry))))
Packit 1fb8d4
			goto out;
Packit 1fb8d4
Packit 1fb8d4
		if (!(baseSocket->name = _strdup(lpName)))
Packit 1fb8d4
		{
Packit 1fb8d4
			free(baseSocket);
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		baseSocket->serverfd = serverfd;
Packit 1fb8d4
		baseSocket->references = 0;
Packit 1fb8d4
Packit 1fb8d4
		if (ArrayList_Add(g_NamedPipeServerSockets, baseSocket) < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(baseSocket->name);
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		// WLog_DBG(TAG, "created shared socked resource for pipe %p (%s). base serverfd = %d",
Packit Service 5a9772
		// (void*) pNamedPipe, lpName, serverfd);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pNamedPipe->serverfd = dup(baseSocket->serverfd);
Packit Service 5a9772
	// WLog_DBG(TAG, "using serverfd %d (duplicated from %d)", pNamedPipe->serverfd,
Packit Service 5a9772
	// baseSocket->serverfd);
Packit 1fb8d4
	pNamedPipe->pfnUnrefNamedPipe = winpr_unref_named_pipe;
Packit 1fb8d4
	baseSocket->references++;
Packit 1fb8d4
Packit 1fb8d4
	if (dwOpenMode & FILE_FLAG_OVERLAPPED)
Packit 1fb8d4
	{
Packit 1fb8d4
#if 0
Packit 1fb8d4
		int flags = fcntl(pNamedPipe->serverfd, F_GETFL);
Packit 1fb8d4
Packit 1fb8d4
		if (flags != -1)
Packit 1fb8d4
			fcntl(pNamedPipe->serverfd, F_SETFL, flags | O_NONBLOCK);
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Unlock(g_NamedPipeServerSockets);
Packit 1fb8d4
	return pNamedPipe;
Packit 1fb8d4
out:
Packit 1fb8d4
	NamedPipeCloseHandle(pNamedPipe);
Packit 1fb8d4
Packit 1fb8d4
	if (serverfd != -1)
Packit 1fb8d4
		close(serverfd);
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Unlock(g_NamedPipeServerSockets);
Packit 1fb8d4
	return INVALID_HANDLE_VALUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
Packit 1fb8d4
                        DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut,
Packit 1fb8d4
                        LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s is not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	socklen_t length;
Packit 1fb8d4
	struct sockaddr_un s;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!hNamedPipe)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (!(pNamedPipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
Packit 1fb8d4
	{
Packit 1fb8d4
		length = sizeof(struct sockaddr_un);
Packit 1fb8d4
		ZeroMemory(&s, sizeof(struct sockaddr_un));
Packit Service 5a9772
		status = accept(pNamedPipe->serverfd, (struct sockaddr*)&s, &length);
Packit 1fb8d4
Packit 1fb8d4
		if (status < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "ConnectNamedPipe: accept error");
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pNamedPipe->clientfd = status;
Packit 1fb8d4
		pNamedPipe->ServerMode = FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!lpOverlapped)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (pNamedPipe->serverfd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		pNamedPipe->lpOverlapped = lpOverlapped;
Packit 1fb8d4
		/* synchronous behavior */
Packit 1fb8d4
		lpOverlapped->Internal = 2;
Packit Service 5a9772
		lpOverlapped->InternalHigh = (ULONG_PTR)0;
Packit Service 5a9772
		lpOverlapped->Pointer = (PVOID)NULL;
Packit 1fb8d4
		SetEvent(lpOverlapped->hEvent);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL DisconnectNamedPipe(HANDLE hNamedPipe)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe;
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->clientfd != -1)
Packit 1fb8d4
	{
Packit 1fb8d4
		close(pNamedPipe->clientfd);
Packit 1fb8d4
		pNamedPipe->clientfd = -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead,
Packit Service 5a9772
                   LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize,
Packit Service 5a9772
                       LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead,
Packit Service 5a9772
                       LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	DWORD nWaitTime;
Packit 1fb8d4
	char* lpFilePath;
Packit 1fb8d4
	DWORD dwSleepInterval;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpNamedPipeName)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpNamedPipeName);
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFilePath)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
Packit 1fb8d4
		nTimeOut = 50;
Packit 1fb8d4
Packit 1fb8d4
	nWaitTime = 0;
Packit 1fb8d4
	status = TRUE;
Packit 1fb8d4
	dwSleepInterval = 10;
Packit 1fb8d4
Packit 1fb8d4
	while (!PathFileExistsA(lpFilePath))
Packit 1fb8d4
	{
Packit 1fb8d4
		Sleep(dwSleepInterval);
Packit 1fb8d4
		nWaitTime += dwSleepInterval;
Packit 1fb8d4
Packit 1fb8d4
		if (nWaitTime >= nTimeOut)
Packit 1fb8d4
		{
Packit 1fb8d4
			status = FALSE;
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(lpFilePath);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
Packit 1fb8d4
                             LPDWORD lpCollectDataTimeout)
Packit 1fb8d4
{
Packit 1fb8d4
	int fd;
Packit 1fb8d4
	int flags;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe;
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (lpMode)
Packit 1fb8d4
	{
Packit 1fb8d4
		pNamedPipe->dwPipeMode = *lpMode;
Packit 1fb8d4
		fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
Packit 1fb8d4
Packit 1fb8d4
		if (fd == -1)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		flags = fcntl(fd, F_GETFL);
Packit 1fb8d4
Packit 1fb8d4
		if (flags < 0)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		if (pNamedPipe->dwPipeMode & PIPE_NOWAIT)
Packit 1fb8d4
			flags = (flags | O_NONBLOCK);
Packit 1fb8d4
		else
Packit 1fb8d4
			flags = (flags & ~(O_NONBLOCK));
Packit 1fb8d4
Packit 1fb8d4
		if (fcntl(fd, F_SETFL, flags) < 0)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpMaxCollectionCount)
Packit 1fb8d4
	{
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpCollectDataTimeout)
Packit 1fb8d4
	{
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL GetNamedPipeClientComputerNameA(HANDLE Pipe, LPCSTR ClientComputerName,
Packit 1fb8d4
                                     ULONG ClientComputerNameLength)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL GetNamedPipeClientComputerNameW(HANDLE Pipe, LPCWSTR ClientComputerName,
Packit 1fb8d4
                                     ULONG ClientComputerNameLength)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif