mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 03:44:06 +08:00
libwinpr-pipe: add support for overlapped i/o with named pipes (synchronous, compatible implementation)
This commit is contained in:
parent
c1625c1ead
commit
8423fccbc2
@ -270,6 +270,7 @@ if(NOT IOS AND NOT ANDROID)
|
||||
endif()
|
||||
|
||||
if(UNIX OR CYGWIN)
|
||||
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
||||
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
|
||||
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
|
||||
set(X11_FEATURE_TYPE "RECOMMENDED")
|
||||
|
@ -32,6 +32,7 @@
|
||||
#cmakedefine HAVE_EVENTFD_H
|
||||
#cmakedefine HAVE_TIMERFD_H
|
||||
#cmakedefine HAVE_TM_GMTOFF
|
||||
#cmakedefine HAVE_AIO_H
|
||||
|
||||
|
||||
/* Options */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/platform.h>
|
||||
|
||||
#include <winpr/file.h>
|
||||
|
||||
@ -124,6 +125,21 @@
|
||||
* http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf
|
||||
*/
|
||||
|
||||
/**
|
||||
* Asynchronous I/O - The GNU C Library:
|
||||
* http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* aio.h - asynchronous input and output:
|
||||
* http://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Asynchronous I/O User Guide:
|
||||
* http://code.google.com/p/kernel/wiki/AIOUserGuide
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
@ -142,6 +158,14 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#undef HAVE_AIO_H /* disable for now, incomplete */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#include <aio.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <sys/vfs.h>
|
||||
#else
|
||||
@ -184,6 +208,7 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
pNamedPipe->nOutBufferSize = 0;
|
||||
pNamedPipe->nInBufferSize = 0;
|
||||
pNamedPipe->nDefaultTimeOut = 0;
|
||||
pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
|
||||
|
||||
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
|
||||
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
|
||||
@ -255,20 +280,66 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
|
||||
pipe = (WINPR_NAMED_PIPE*) Object;
|
||||
|
||||
status = nNumberOfBytesToRead;
|
||||
|
||||
if (pipe->clientfd != -1)
|
||||
status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (status < 0)
|
||||
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
|
||||
{
|
||||
*lpNumberOfBytesRead = 0;
|
||||
return FALSE;
|
||||
}
|
||||
status = nNumberOfBytesToRead;
|
||||
|
||||
*lpNumberOfBytesRead = status;
|
||||
if (pipe->clientfd == -1)
|
||||
return FALSE;
|
||||
|
||||
status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
*lpNumberOfBytesRead = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesRead = status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overlapped I/O */
|
||||
|
||||
if (!lpOverlapped)
|
||||
return FALSE;
|
||||
|
||||
if (pipe->clientfd == -1)
|
||||
return FALSE;
|
||||
|
||||
pipe->lpOverlapped = lpOverlapped;
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
{
|
||||
struct aiocb cb;
|
||||
|
||||
ZeroMemory(&cb, sizeof(struct aiocb));
|
||||
cb.aio_nbytes = nNumberOfBytesToRead;
|
||||
cb.aio_fildes = pipe->clientfd;
|
||||
cb.aio_offset = lpOverlapped->Offset;
|
||||
cb.aio_buf = lpBuffer;
|
||||
|
||||
status = aio_read(&cb);
|
||||
|
||||
printf("aio_read status: %d\n", status);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/* synchronous behavior */
|
||||
|
||||
lpOverlapped->Internal = 0;
|
||||
lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToRead;
|
||||
lpOverlapped->Pointer = (PVOID) lpBuffer;
|
||||
|
||||
SetEvent(lpOverlapped->hEvent);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -317,20 +388,66 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
|
||||
pipe = (WINPR_NAMED_PIPE*) Object;
|
||||
|
||||
status = nNumberOfBytesToWrite;
|
||||
|
||||
if (pipe->clientfd != -1)
|
||||
status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (status < 0)
|
||||
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
|
||||
{
|
||||
*lpNumberOfBytesWritten = 0;
|
||||
return FALSE;
|
||||
}
|
||||
status = nNumberOfBytesToWrite;
|
||||
|
||||
*lpNumberOfBytesWritten = status;
|
||||
if (pipe->clientfd == -1)
|
||||
return FALSE;
|
||||
|
||||
status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
*lpNumberOfBytesWritten = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesWritten = status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Overlapped I/O */
|
||||
|
||||
if (!lpOverlapped)
|
||||
return FALSE;
|
||||
|
||||
if (pipe->clientfd == -1)
|
||||
return FALSE;
|
||||
|
||||
pipe->lpOverlapped = lpOverlapped;
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
{
|
||||
struct aiocb cb;
|
||||
|
||||
ZeroMemory(&cb, sizeof(struct aiocb));
|
||||
cb.aio_nbytes = nNumberOfBytesToWrite;
|
||||
cb.aio_fildes = pipe->clientfd;
|
||||
cb.aio_offset = lpOverlapped->Offset;
|
||||
cb.aio_buf = lpBuffer;
|
||||
|
||||
status = aio_write(&cb);
|
||||
|
||||
printf("aio_write status: %d\n", status);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/* synchronous behavior */
|
||||
|
||||
lpOverlapped->Internal = 1;
|
||||
lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToWrite;
|
||||
lpOverlapped->Pointer = (PVOID) lpBuffer;
|
||||
|
||||
SetEvent(lpOverlapped->hEvent);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -23,25 +23,69 @@
|
||||
|
||||
#include <winpr/io.h>
|
||||
|
||||
/**
|
||||
* api-ms-win-core-io-l1-1-1.dll:
|
||||
*
|
||||
* GetOverlappedResult
|
||||
* GetOverlappedResultEx
|
||||
* DeviceIoControl
|
||||
* CreateIoCompletionPort
|
||||
* GetQueuedCompletionStatus
|
||||
* GetQueuedCompletionStatusEx
|
||||
* PostQueuedCompletionStatus
|
||||
* CancelIo
|
||||
* CancelIoEx
|
||||
* CancelSynchronousIo
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#include "../pipe/pipe.h"
|
||||
|
||||
BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait)
|
||||
{
|
||||
ULONG Type;
|
||||
PVOID Object;
|
||||
|
||||
if (!winpr_Handle_GetInfo(hFile, &Type, &Object))
|
||||
return FALSE;
|
||||
|
||||
else if (Type == HANDLE_TYPE_NAMED_PIPE)
|
||||
{
|
||||
int status;
|
||||
DWORD request;
|
||||
PVOID lpBuffer;
|
||||
DWORD nNumberOfBytes;
|
||||
WINPR_NAMED_PIPE* pipe;
|
||||
|
||||
pipe = (WINPR_NAMED_PIPE*) Object;
|
||||
|
||||
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
|
||||
return FALSE;
|
||||
|
||||
if (pipe->clientfd == -1)
|
||||
return FALSE;
|
||||
|
||||
lpBuffer = lpOverlapped->Pointer;
|
||||
request = (DWORD) lpOverlapped->Internal;
|
||||
nNumberOfBytes = (DWORD) lpOverlapped->InternalHigh;
|
||||
|
||||
if (request == 0)
|
||||
{
|
||||
status = read(pipe->clientfd, lpBuffer, nNumberOfBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = write(pipe->clientfd, lpBuffer, nNumberOfBytes);
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
*lpNumberOfBytesTransferred = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesTransferred = status;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,7 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
|
||||
pNamedPipe->nOutBufferSize = nOutBufferSize;
|
||||
pNamedPipe->nInBufferSize = nInBufferSize;
|
||||
pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
|
||||
pNamedPipe->dwFlagsAndAttributes = dwOpenMode;
|
||||
|
||||
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
|
||||
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName);
|
||||
@ -177,6 +178,14 @@ BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
|
||||
|
||||
pNamedPipe->clientfd = status;
|
||||
|
||||
if (pNamedPipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
|
||||
{
|
||||
if (!lpOverlapped)
|
||||
return FALSE;
|
||||
|
||||
SetEvent(lpOverlapped->hEvent);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ struct winpr_named_pipe
|
||||
DWORD nOutBufferSize;
|
||||
DWORD nInBufferSize;
|
||||
DWORD nDefaultTimeOut;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
LPOVERLAPPED lpOverlapped;
|
||||
};
|
||||
typedef struct winpr_named_pipe WINPR_NAMED_PIPE;
|
||||
|
||||
|
@ -32,11 +32,6 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
BOOL WTSStopRemoteControlSession(ULONG LogonId)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
|
||||
{
|
||||
return TRUE;
|
||||
@ -47,6 +42,11 @@ BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WTSStopRemoteControlSession(ULONG LogonId)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait)
|
||||
{
|
||||
return TRUE;
|
||||
@ -191,11 +191,24 @@ BOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
|
||||
|
||||
HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
|
||||
{
|
||||
return NULL;
|
||||
HANDLE handle = NULL;
|
||||
|
||||
if (hServer != WTS_CURRENT_SERVER_HANDLE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
|
||||
{
|
||||
HANDLE handle = NULL;
|
||||
|
||||
if (!flags)
|
||||
return WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, SessionId, pVirtualName);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -375,12 +388,48 @@ BOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
|
||||
|
||||
BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
|
||||
{
|
||||
return TRUE;
|
||||
BOOL status = TRUE;
|
||||
|
||||
switch (WTSTypeClass)
|
||||
{
|
||||
case WTSTypeProcessInfoLevel0:
|
||||
break;
|
||||
|
||||
case WTSTypeProcessInfoLevel1:
|
||||
break;
|
||||
|
||||
case WTSTypeSessionInfoLevel1:
|
||||
break;
|
||||
|
||||
default:
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)
|
||||
{
|
||||
return TRUE;
|
||||
BOOL status = TRUE;
|
||||
|
||||
switch (WTSTypeClass)
|
||||
{
|
||||
case WTSTypeProcessInfoLevel0:
|
||||
break;
|
||||
|
||||
case WTSTypeProcessInfoLevel1:
|
||||
break;
|
||||
|
||||
case WTSTypeSessionInfoLevel1:
|
||||
break;
|
||||
|
||||
default:
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId, LPWSTR* ppProcessInfo, DWORD* pCount)
|
||||
|
Loading…
Reference in New Issue
Block a user