libwinpr-pipe: add support for overlapped i/o with named pipes (synchronous, compatible implementation)

This commit is contained in:
Marc-André Moreau 2013-08-22 22:36:37 -04:00
parent c1625c1ead
commit 8423fccbc2
7 changed files with 270 additions and 47 deletions

View File

@ -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")

View File

@ -32,6 +32,7 @@
#cmakedefine HAVE_EVENTFD_H
#cmakedefine HAVE_TIMERFD_H
#cmakedefine HAVE_TM_GMTOFF
#cmakedefine HAVE_AIO_H
/* Options */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)