FreeRDP
Loading...
Searching...
No Matches
namedPipeClient.c
1
22#include <winpr/config.h>
23
24#include <winpr/crt.h>
25#include <winpr/path.h>
26#include <winpr/file.h>
27
28#ifdef WINPR_HAVE_UNISTD_H
29#include <unistd.h>
30#endif
31
32#include "../log.h"
33#define TAG WINPR_TAG("file")
34
35#ifndef _WIN32
36
37#ifdef ANDROID
38#include <sys/vfs.h>
39#else
40#include <sys/statvfs.h>
41#endif
42
43#include "../handle/handle.h"
44
45#include "../pipe/pipe.h"
46#include "namedPipeClient.h"
47
48static BOOL NamedPipeClientIsHandled(HANDLE handle)
49{
50 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_NAMED_PIPE, TRUE);
51}
52
53static BOOL NamedPipeClientCloseHandle(HANDLE handle)
54{
55 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
56
57 if (!NamedPipeClientIsHandled(handle))
58 return FALSE;
59
60 if (pNamedPipe->clientfd != -1)
61 {
62 // WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
63 close(pNamedPipe->clientfd);
64 }
65
66 if (pNamedPipe->serverfd != -1)
67 {
68 // WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
69 close(pNamedPipe->serverfd);
70 }
71
72 if (pNamedPipe->pfnUnrefNamedPipe)
73 pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
74
75 free(pNamedPipe->lpFileName);
76 free(pNamedPipe->lpFilePath);
77 free(pNamedPipe->name);
78 free(pNamedPipe);
79 return TRUE;
80}
81
82static int NamedPipeClientGetFd(HANDLE handle)
83{
84 WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
85
86 if (!NamedPipeClientIsHandled(handle))
87 return -1;
88
89 if (file->ServerMode)
90 return file->serverfd;
91 else
92 return file->clientfd;
93}
94
95static HANDLE_OPS ops = {
96 NamedPipeClientIsHandled,
97 NamedPipeClientCloseHandle,
98 NamedPipeClientGetFd,
99 NULL, /* CleanupHandle */
100 NamedPipeRead,
101 NULL, /* FileReadEx */
102 NULL, /* FileReadScatter */
103 NamedPipeWrite,
104 NULL, /* FileWriteEx */
105 NULL, /* FileWriteGather */
106 NULL, /* FileGetFileSize */
107 NULL, /* FlushFileBuffers */
108 NULL, /* FileSetEndOfFile */
109 NULL, /* FileSetFilePointer */
110 NULL, /* SetFilePointerEx */
111 NULL, /* FileLockFile */
112 NULL, /* FileLockFileEx */
113 NULL, /* FileUnlockFile */
114 NULL, /* FileUnlockFileEx */
115 NULL, /* SetFileTime */
116 NULL, /* FileGetFileInformationByHandle */
117};
118
119static HANDLE
120NamedPipeClientCreateFileA(LPCSTR lpFileName, WINPR_ATTR_UNUSED DWORD dwDesiredAccess,
121 WINPR_ATTR_UNUSED DWORD dwShareMode,
122 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
123 WINPR_ATTR_UNUSED DWORD dwCreationDisposition,
124 DWORD dwFlagsAndAttributes, WINPR_ATTR_UNUSED HANDLE hTemplateFile)
125{
126 int status = 0;
127 struct sockaddr_un s = { 0 };
128
129 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
130 {
131 WLog_ERR(TAG, "WinPR does not support the FILE_FLAG_OVERLAPPED flag");
132 SetLastError(ERROR_NOT_SUPPORTED);
133 return INVALID_HANDLE_VALUE;
134 }
135
136 if (!lpFileName)
137 return INVALID_HANDLE_VALUE;
138
139 if (!IsNamedPipeFileNameA(lpFileName))
140 return INVALID_HANDLE_VALUE;
141
142 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
143
144 if (!pNamedPipe)
145 {
146 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
147 return INVALID_HANDLE_VALUE;
148 }
149
150 HANDLE hNamedPipe = (HANDLE)pNamedPipe;
151 WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
152 pNamedPipe->name = _strdup(lpFileName);
153
154 if (!pNamedPipe->name)
155 {
156 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
157 goto fail;
158 }
159
160 pNamedPipe->dwOpenMode = 0;
161 pNamedPipe->dwPipeMode = 0;
162 pNamedPipe->nMaxInstances = 0;
163 pNamedPipe->nOutBufferSize = 0;
164 pNamedPipe->nInBufferSize = 0;
165 pNamedPipe->nDefaultTimeOut = 0;
166 pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
167 pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
168
169 if (!pNamedPipe->lpFileName)
170 goto fail;
171
172 pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
173
174 if (!pNamedPipe->lpFilePath)
175 goto fail;
176
177 pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
178 if (pNamedPipe->clientfd < 0)
179 goto fail;
180
181 pNamedPipe->serverfd = -1;
182 pNamedPipe->ServerMode = FALSE;
183 s.sun_family = AF_UNIX;
184 (void)sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
185 status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
186 pNamedPipe->common.ops = &ops;
187
188 if (status != 0)
189 goto fail;
190
191 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
192 {
193 // TODO: Implement
194 WLog_ERR(TAG, "TODO: implement this");
195 }
196
197 return hNamedPipe;
198
199fail:
200 if (pNamedPipe)
201 {
202 if (pNamedPipe->clientfd >= 0)
203 close(pNamedPipe->clientfd);
204 free(pNamedPipe->name);
205 free(pNamedPipe->lpFileName);
206 free(pNamedPipe->lpFilePath);
207 free(pNamedPipe);
208 }
209 return INVALID_HANDLE_VALUE;
210}
211
212const HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
213{
214 static const HANDLE_CREATOR NamedPipeClientHandleCreator = { .IsHandled = IsNamedPipeFileNameA,
215 .CreateFileA =
216 NamedPipeClientCreateFileA };
217 return &NamedPipeClientHandleCreator;
218}
219
220#endif
221
222/* Extended API */
223
224#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
225
226BOOL IsNamedPipeFileNameA(LPCSTR lpName)
227{
228 if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
229 return FALSE;
230
231 return TRUE;
232}
233
234char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
235{
236 char* lpFileName = NULL;
237
238 if (!lpName)
239 return NULL;
240
241 if (!IsNamedPipeFileNameA(lpName))
242 return NULL;
243
244 lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
245 return lpFileName;
246}
247
248char* GetNamedPipeUnixDomainSocketBaseFilePathA(void)
249{
250 char* lpTempPath = NULL;
251 char* lpPipePath = NULL;
252 lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
253
254 if (!lpTempPath)
255 return NULL;
256
257 lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
258 free(lpTempPath);
259 return lpPipePath;
260}
261
262char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
263{
264 char* lpPipePath = NULL;
265 char* lpFileName = NULL;
266 char* lpFilePath = NULL;
267 lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
268 lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
269 lpFilePath = GetCombinedPath(lpPipePath, lpFileName);
270 free(lpPipePath);
271 free(lpFileName);
272 return lpFilePath;
273}
274
275int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
276{
277#ifndef _WIN32
278 int fd = 0;
279 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
280
281 if (!NamedPipeClientIsHandled(hNamedPipe))
282 return -1;
283
284 fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
285 return fd;
286#else
287 return -1;
288#endif
289}