libwinpr-pipe: implement of more named pipes
This commit is contained in:
parent
afe1f22bcf
commit
65bc944def
@ -106,6 +106,14 @@ WINPR_API BOOL GetNamedPipeClientComputerNameW(HANDLE Pipe, LPCWSTR ClientComput
|
||||
#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
|
||||
|
@ -125,13 +125,21 @@
|
||||
|
||||
#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>
|
||||
@ -146,15 +154,28 @@
|
||||
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;
|
||||
@ -163,9 +184,32 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
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,
|
||||
@ -215,6 +259,17 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
|
||||
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;
|
||||
@ -240,7 +295,6 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
{
|
||||
ULONG Type;
|
||||
PVOID Object;
|
||||
WINPR_PIPE* pipe;
|
||||
|
||||
if (!winpr_Handle_GetInfo(hFile, &Type, &Object))
|
||||
return FALSE;
|
||||
@ -267,6 +321,17 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
|
||||
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;
|
||||
|
@ -35,6 +35,11 @@
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "pipe.h"
|
||||
|
||||
/*
|
||||
@ -80,20 +85,84 @@ BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpP
|
||||
|
||||
#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;
|
||||
|
||||
@ -107,16 +176,42 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
|
||||
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;
|
||||
}
|
||||
@ -129,10 +224,29 @@ HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWOR
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,9 @@ struct winpr_named_pipe
|
||||
{
|
||||
WINPR_HANDLE_DEF();
|
||||
|
||||
int fd;
|
||||
int clientfd;
|
||||
int serverfd;
|
||||
|
||||
const char* name;
|
||||
const char* lpFileName;
|
||||
const char* lpFilePath;
|
||||
|
@ -5,19 +5,78 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
@ -49,6 +108,8 @@ static void* named_pipe_server_thread(void* arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SetEvent(ReadyEvent);
|
||||
|
||||
fConnected = ConnectNamedPipe(hNamedPipe, NULL);
|
||||
|
||||
if (!fConnected)
|
||||
@ -66,22 +127,29 @@ static void* named_pipe_server_thread(void* arg)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -96,6 +164,8 @@ int TestPipeCreateNamedPipe(int argc, char* argv[])
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user