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