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 nullptr, /* CleanupHandle */
100 NamedPipeRead,
101 nullptr, /* FileReadEx */
102 nullptr, /* FileReadScatter */
103 NamedPipeWrite,
104 nullptr, /* FileWriteEx */
105 nullptr, /* FileWriteGather */
106 nullptr, /* FileGetFileSize */
107 nullptr, /* FlushFileBuffers */
108 nullptr, /* FileSetEndOfFile */
109 nullptr, /* FileSetFilePointer */
110 nullptr, /* SetFilePointerEx */
111 nullptr, /* FileLockFile */
112 nullptr, /* FileLockFileEx */
113 nullptr, /* FileUnlockFile */
114 nullptr, /* FileUnlockFileEx */
115 nullptr, /* SetFileTime */
116 nullptr, /* 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 = WINPR_C_ARRAY_INIT;
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 return (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) == 0);
229}
230
231char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
232{
233 char* lpFileName = nullptr;
234
235 if (!lpName)
236 return nullptr;
237
238 if (!IsNamedPipeFileNameA(lpName))
239 return nullptr;
240
241 lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
242 return lpFileName;
243}
244
245char* GetNamedPipeUnixDomainSocketBaseFilePathA(void)
246{
247 char* lpTempPath = nullptr;
248 char* lpPipePath = nullptr;
249 lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
250
251 if (!lpTempPath)
252 return nullptr;
253
254 lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
255 free(lpTempPath);
256 return lpPipePath;
257}
258
259char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
260{
261 char* lpPipePath = nullptr;
262 char* lpFileName = nullptr;
263 char* lpFilePath = nullptr;
264 lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
265 lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
266 lpFilePath = GetCombinedPath(lpPipePath, lpFileName);
267 free(lpPipePath);
268 free(lpFileName);
269 return lpFilePath;
270}
271
272int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
273{
274#ifndef _WIN32
275 int fd = 0;
276 WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
277
278 if (!NamedPipeClientIsHandled(hNamedPipe))
279 return -1;
280
281 fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
282 return fd;
283#else
284 return -1;
285#endif
286}