#define GetNamedPipeClientComputerName GetNamedPipeClientComputerNameA
#endif
+/**
+ * Extended API
+ */
+
+WINPR_API char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName);
+WINPR_API char* GetNamedPipeUnixDomainSocketBaseFilePathA();
+WINPR_API char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName);
+
#ifdef __cplusplus
}
#endif
#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 <fcntl.h>
+#include <sys/un.h>
#include <sys/stat.h>
+#include <sys/socket.h>
#ifdef ANDROID
#include <sys/vfs.h>
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
+ char* name;
+ int status;
HANDLE hNamedPipe;
+ unsigned long flags;
+ struct sockaddr_un s;
WINPR_NAMED_PIPE* pNamedPipe;
if (!lpFileName)
return INVALID_HANDLE_VALUE;
+ name = GetNamedPipeNameWithoutPrefixA(lpFileName);
+
+ if (!name)
+ return INVALID_HANDLE_VALUE;
+
+ free(name);
+
pNamedPipe = (WINPR_NAMED_PIPE*) malloc(sizeof(WINPR_NAMED_PIPE));
hNamedPipe = (HANDLE) pNamedPipe;
+ WINPR_HANDLE_SET_TYPE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE);
+
pNamedPipe->name = _strdup(lpFileName);
pNamedPipe->dwOpenMode = 0;
pNamedPipe->dwPipeMode = 0;
pNamedPipe->nInBufferSize = 0;
pNamedPipe->nDefaultTimeOut = 0;
- WINPR_HANDLE_SET_TYPE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE);
+ pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
+ pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
- return INVALID_HANDLE_VALUE;
+ pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ pNamedPipe->serverfd = -1;
+
+ if (0)
+ {
+ flags = fcntl(pNamedPipe->clientfd, F_GETFL);
+ flags = flags | O_NONBLOCK;
+ fcntl(pNamedPipe->clientfd, F_SETFL, flags);
+ }
+
+ ZeroMemory(&s, sizeof(struct sockaddr_un));
+ s.sun_family = AF_UNIX;
+ strcpy(s.sun_path, pNamedPipe->lpFilePath);
+
+ status = connect(pNamedPipe->clientfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
+
+ if (status != 0)
+ {
+ printf("connect: %d\n", status);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ return hNamedPipe;
}
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
status = nNumberOfBytesToRead;
+ if (pipe->clientfd != -1)
+ status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
+ else
+ return FALSE;
+
+ if (status < 0)
+ {
+ *lpNumberOfBytesRead = 0;
+ return FALSE;
+ }
+
*lpNumberOfBytesRead = status;
return TRUE;
{
ULONG Type;
PVOID Object;
- WINPR_PIPE* pipe;
if (!winpr_Handle_GetInfo(hFile, &Type, &Object))
return FALSE;
status = nNumberOfBytesToWrite;
+ if (pipe->clientfd != -1)
+ status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
+ else
+ return FALSE;
+
+ if (status < 0)
+ {
+ *lpNumberOfBytesWritten = 0;
+ return FALSE;
+ }
+
*lpNumberOfBytesWritten = status;
return TRUE;
#include "../handle/handle.h"
+#include <fcntl.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
#include "pipe.h"
/*
#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
+char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
+{
+ char* lpFileName;
+
+ if (!lpName)
+ return NULL;
+
+ if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
+ return NULL;
+
+ lpFileName = _strdup(&lpName[strlen(NAMED_PIPE_PREFIX_PATH)]);
+
+ return lpFileName;
+}
+
+char* GetNamedPipeUnixDomainSocketBaseFilePathA()
+{
+ char* lpTempPath;
+ char* lpPipePath;
+
+ lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
+ lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
+
+ free(lpTempPath);
+
+ return lpPipePath;
+}
+
+char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
+{
+ char* lpPipePath;
+ char* lpFileName;
+ char* lpFilePath;
+
+ lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
+
+ lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
+ lpFilePath = GetCombinedPath(lpPipePath, (char*) lpFileName);
+
+ free(lpPipePath);
+ free(lpFileName);
+
+ return lpFilePath;
+}
+
+int UnixChangeMode(const char* filename, int flags)
+{
+ mode_t fl = 0;
+
+ fl |= (flags & 0x4000) ? S_ISUID : 0;
+ fl |= (flags & 0x2000) ? S_ISGID : 0;
+ fl |= (flags & 0x1000) ? S_ISVTX : 0;
+ fl |= (flags & 0x0400) ? S_IRUSR : 0;
+ fl |= (flags & 0x0200) ? S_IWUSR : 0;
+ fl |= (flags & 0x0100) ? S_IXUSR : 0;
+ fl |= (flags & 0x0040) ? S_IRGRP : 0;
+ fl |= (flags & 0x0020) ? S_IWGRP : 0;
+ fl |= (flags & 0x0010) ? S_IXGRP : 0;
+ fl |= (flags & 0x0004) ? S_IROTH : 0;
+ fl |= (flags & 0x0002) ? S_IWOTH : 0;
+ fl |= (flags & 0x0001) ? S_IXOTH : 0;
+
+ return chmod(filename, fl);
+}
+
HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
+ int status;
HANDLE hNamedPipe;
- char* lpTempPath;
char* lpPipePath;
+ unsigned long flags;
+ struct sockaddr_un s;
WINPR_NAMED_PIPE* pNamedPipe;
if (!lpName)
return INVALID_HANDLE_VALUE;
- if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
- return INVALID_HANDLE_VALUE;
-
pNamedPipe = (WINPR_NAMED_PIPE*) malloc(sizeof(WINPR_NAMED_PIPE));
hNamedPipe = (HANDLE) pNamedPipe;
pNamedPipe->nInBufferSize = nInBufferSize;
pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
- lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
- lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
+ pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
+ pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName);
- pNamedPipe->lpFileName = _strdup(&lpName[strlen(NAMED_PIPE_PREFIX_PATH)]);
- pNamedPipe->lpFilePath = GetCombinedPath(lpPipePath, (char*) pNamedPipe->lpFileName);
+ lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
+
+ if (!PathFileExistsA(lpPipePath))
+ CreateDirectoryA(lpPipePath, 0);
- free(lpTempPath);
free(lpPipePath);
- printf("CreateNamedPipe: %s\n", pNamedPipe->lpFilePath);
+ pNamedPipe->clientfd = -1;
+ pNamedPipe->serverfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+
+ if (0)
+ {
+ flags = fcntl(pNamedPipe->serverfd, F_GETFL);
+ flags = flags | O_NONBLOCK;
+ fcntl(pNamedPipe->serverfd, F_SETFL, flags);
+ }
+
+ ZeroMemory(&s, sizeof(struct sockaddr_un));
+ s.sun_family = AF_UNIX;
+ strcpy(s.sun_path, pNamedPipe->lpFilePath);
+ unlink(s.sun_path);
+
+ status = bind(pNamedPipe->serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
+
+ if (status == 0)
+ {
+ status = listen(pNamedPipe->serverfd, 2);
+
+ if (status == 0)
+ {
+ UnixChangeMode(pNamedPipe->lpFilePath, 0xFFFF);
+ }
+ }
return hNamedPipe;
}
BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
{
+ int status;
+ socklen_t length;
+ struct sockaddr_un s;
WINPR_NAMED_PIPE* pNamedPipe;
+ if (!hNamedPipe)
+ return FALSE;
+
pNamedPipe = (WINPR_NAMED_PIPE*) hNamedPipe;
+ length = sizeof(struct sockaddr_un);
+ ZeroMemory(&s, sizeof(struct sockaddr_un));
+
+ status = accept(pNamedPipe->serverfd, (struct sockaddr*) &s, &length);
+
+ if (status < 0)
+ {
+ printf("accept: %d\n", status);
+ return FALSE;
+ }
+
+ pNamedPipe->clientfd = status;
+
return TRUE;
}
{
WINPR_HANDLE_DEF();
- int fd;
+ int clientfd;
+ int serverfd;
+
const char* name;
const char* lpFileName;
const char* lpFilePath;
#include <winpr/file.h>
#include <winpr/tchar.h>
#include <winpr/winpr.h>
+#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#define PIPE_BUFFER_SIZE 32
+static HANDLE ReadyEvent;
+
static LPTSTR lpszPipeName = _T("\\\\.\\pipe\\winpr_test_pipe");
static void* named_pipe_client_thread(void* arg)
{
HANDLE hNamedPipe;
+ BYTE* lpReadBuffer;
+ BYTE* lpWriteBuffer;
+ BOOL fSuccess = FALSE;
+ DWORD nNumberOfBytesToRead;
+ DWORD nNumberOfBytesToWrite;
+ DWORD lpNumberOfBytesRead;
+ DWORD lpNumberOfBytesWritten;
+
+ WaitForSingleObject(ReadyEvent, INFINITE);
hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (!hNamedPipe)
+ {
+ printf("Named Pipe CreateFile failure: NULL handle\n");
+ return NULL;
+ }
+
+ if (hNamedPipe == INVALID_HANDLE_VALUE)
+ {
+ printf("Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n");
+ return NULL;
+ }
+
+ lpReadBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
+ lpWriteBuffer = (BYTE*) malloc(PIPE_BUFFER_SIZE);
+
+ lpNumberOfBytesWritten = 0;
+ nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
+
+ FillMemory(lpWriteBuffer, 0xAB, PIPE_BUFFER_SIZE);
+
+ fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
+
+ if (!fSuccess || (lpNumberOfBytesWritten == 0))
+ {
+ printf("Client NamedPipe WriteFile failure\n");
+ return NULL;
+ }
+
+ lpNumberOfBytesRead = 0;
+ nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
+
+ ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
+
+ fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL);
+
+ if (!fSuccess || (lpNumberOfBytesRead == 0))
+ {
+ printf("Client NamedPipe ReadFile failure\n");
+ return NULL;
+ }
+
+ printf("Client ReadFile (%d):\n", lpNumberOfBytesRead);
+ winpr_HexDump(lpReadBuffer, lpNumberOfBytesRead);
+
+ free(lpReadBuffer);
+ free(lpWriteBuffer);
+
return NULL;
}
return NULL;
}
+ SetEvent(ReadyEvent);
+
fConnected = ConnectNamedPipe(hNamedPipe, NULL);
if (!fConnected)
lpNumberOfBytesRead = 0;
nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
+ ZeroMemory(lpReadBuffer, PIPE_BUFFER_SIZE);
+
fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL);
if (!fSuccess || (lpNumberOfBytesRead == 0))
{
- printf("NamedPipe ReadFile failure\n");
+ printf("Server NamedPipe ReadFile failure\n");
return NULL;
}
+ printf("Server ReadFile (%d):\n", lpNumberOfBytesRead);
+ winpr_HexDump(lpReadBuffer, lpNumberOfBytesRead);
+
lpNumberOfBytesWritten = 0;
nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
+ FillMemory(lpWriteBuffer, 0xCD, PIPE_BUFFER_SIZE);
+
fSuccess = WriteFile(hNamedPipe, lpWriteBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
- if (!fSuccess || (lpNumberOfBytesRead == 0))
+ if (!fSuccess || (lpNumberOfBytesWritten == 0))
{
- printf("NamedPipe WriteFile failure\n");
+ printf("Server NamedPipe WriteFile failure\n");
return NULL;
}
HANDLE ClientThread;
HANDLE ServerThread;
+ ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL);
ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL);