libwinpr-pipe: add support for overlapped i/o with named pipes (synchronous, compatib...
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 23 Aug 2013 02:36:37 +0000 (22:36 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 23 Aug 2013 02:36:37 +0000 (22:36 -0400)
CMakeLists.txt
config.h.in
winpr/libwinpr/file/file.c
winpr/libwinpr/io/io.c
winpr/libwinpr/pipe/pipe.c
winpr/libwinpr/pipe/pipe.h
winpr/libwinpr/wtsapi/wtsapi.c

index a38dd3a..4ca2f34 100755 (executable)
@@ -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")
index 83b0abe..bbbe361 100755 (executable)
@@ -32,6 +32,7 @@
 #cmakedefine HAVE_EVENTFD_H
 #cmakedefine HAVE_TIMERFD_H
 #cmakedefine HAVE_TM_GMTOFF
+#cmakedefine HAVE_AIO_H
 
 
 /* Options */
index feaf66d..48bfaeb 100644 (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>
 
  * 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
 #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->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
+               {
+                       status = nNumberOfBytesToRead;
+
+                       if (pipe->clientfd == -1)
+                               return FALSE;
 
-               if (pipe->clientfd != -1)
                        status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
-               else
-                       return FALSE;
 
-               if (status < 0)
-               {
-                       *lpNumberOfBytesRead = 0;
-                       return FALSE;
+                       if (status < 0)
+                       {
+                               *lpNumberOfBytesRead = 0;
+                               return FALSE;
+                       }
+
+                       *lpNumberOfBytesRead = status;
                }
+               else
+               {
+                       /* Overlapped I/O */
 
-               *lpNumberOfBytesRead = status;
+                       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->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
+               {
+                       status = nNumberOfBytesToWrite;
+
+                       if (pipe->clientfd == -1)
+                               return FALSE;
 
-               if (pipe->clientfd != -1)
                        status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
-               else
-                       return FALSE;
 
-               if (status < 0)
-               {
-                       *lpNumberOfBytesWritten = 0;
-                       return FALSE;
+                       if (status < 0)
+                       {
+                               *lpNumberOfBytesWritten = 0;
+                               return FALSE;
+                       }
+
+                       *lpNumberOfBytesWritten = status;
                }
+               else
+               {
+                       /* Overlapped I/O */
 
-               *lpNumberOfBytesWritten = status;
+                       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;
        }
index b319e6c..bf6adaa 100644 (file)
 
 #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;
 }
 
index 241f131..2345da3 100644 (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;
 }
 
index 2c326a7..efc7998 100644 (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;
 
index 600abe5..8e8201f 100644 (file)
 
 #ifndef _WIN32
 
-BOOL WTSStopRemoteControlSession(ULONG LogonId)
+BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
 {
        return TRUE;
 }
 
-BOOL WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
+BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
 {
        return TRUE;
 }
 
-BOOL WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers)
+BOOL WTSStopRemoteControlSession(ULONG LogonId)
 {
        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)