21#include <winpr/config.h>
23#include <winpr/handle.h>
24#include <winpr/assert.h>
27#define TAG WINPR_TAG("handle")
36#include "../synch/synch.h"
37#include "../thread/thread.h"
38#include "../pipe/pipe.h"
39#include "../comm/comm.h"
40#include "../security/security.h"
42#ifdef WINPR_HAVE_UNISTD_H
46#include "../handle/handle.h"
53static BOOL winpr_handle_format_split(
const char* format,
size_t* prefixLen,
const char** suffix)
55 const char* placeholder = strstr(format,
"{}");
58 WLog_ERR(TAG,
"format string '%s' has no {} placeholder for the handle value", format);
62 *prefixLen = (size_t)(placeholder - format);
63 *suffix = placeholder + 2;
74static char winpr_handle_export_type_tag(ULONG type)
78 case HANDLE_TYPE_ANONYMOUS_PIPE:
86BOOL winpr_exportHandleToString(HANDLE h,
const char* format,
char* outStr,
size_t outSz)
88 if (!format || !outStr || (outSz == 0))
92 const char* suffix =
nullptr;
93 if (!winpr_handle_format_split(format, &prefixLen, &suffix))
96 if (!h || (h == INVALID_HANDLE_VALUE))
98 WLog_ERR(TAG,
"refusing to export an invalid handle");
101 size_t remaining = outSz - 1;
102 if (remaining <= prefixLen)
104 remaining -= prefixLen;
106 size_t suffixLen = strlen(suffix);
107 if (remaining <= suffixLen)
109 remaining -= suffixLen;
111 char value[32] = WINPR_C_ARRAY_INIT;
113 const int valueLenInt = snprintf(value,
sizeof(value),
"%llx", (
unsigned long long)(UINT_PTR)h);
117 if (!winpr_Handle_GetInfo(h, &type, &hdl))
119 WLog_ERR(TAG,
"unable to resolve handle info");
123 const char typeTag = winpr_handle_export_type_tag(type);
127 "exporting handle type %" PRIu32
" is not supported, only pipe handles can be "
133 const int fd = winpr_Handle_getFd(h);
136 WLog_ERR(TAG,
"unable to resolve a file descriptor for this handle");
139 const int valueLenInt = snprintf(value,
sizeof(value),
"%c%x", typeTag, (
unsigned)fd);
141 if (valueLenInt <= 0)
143 const size_t valueLen = (size_t)valueLenInt;
145 if (valueLen > remaining)
148 memcpy(outStr, format, prefixLen);
149 memcpy(outStr + prefixLen, value, valueLen);
150 memcpy(outStr + prefixLen + valueLen, suffix, suffixLen + 1);
154HANDLE winpr_importHandleFromString(
const char* str,
const char* format)
157 return INVALID_HANDLE_VALUE;
159 size_t prefixLen = 0;
160 const char* suffix =
nullptr;
161 if (!winpr_handle_format_split(format, &prefixLen, &suffix))
162 return INVALID_HANDLE_VALUE;
164 const size_t suffixLen = strlen(suffix);
165 const size_t strLen = strlen(str);
166 if ((strLen < prefixLen + suffixLen) || (strncmp(str, format, prefixLen) != 0) ||
167 (strcmp(str + strLen - suffixLen, suffix) != 0))
169 WLog_ERR(TAG,
"input string '%s' does not match format '%s'", str, format);
170 return INVALID_HANDLE_VALUE;
173 char value[32] = WINPR_C_ARRAY_INIT;
174 size_t valueLen = strLen - prefixLen - suffixLen;
175 const char* valueStart = str + prefixLen;
176 if ((valueLen == 0) || (valueLen >=
sizeof(value)))
178 WLog_ERR(TAG,
"input string '%s' has no usable handle value", str);
179 return INVALID_HANDLE_VALUE;
185 const char typeTag = valueStart[0];
189 "unsupported handle type tag '%c' in '%s', only pipe handles ('P') can be "
192 return INVALID_HANDLE_VALUE;
198 WLog_ERR(TAG,
"input string '%s' has no usable handle value after the type tag", str);
199 return INVALID_HANDLE_VALUE;
203 memcpy(value, valueStart, valueLen);
204 value[valueLen] =
'\0';
207 const unsigned long long numeric = strtoull(value, &end, 16);
208 if (!end || (*end !=
'\0'))
210 WLog_ERR(TAG,
"invalid handle value '%s'", value);
211 return INVALID_HANDLE_VALUE;
215 return (HANDLE)(UINT_PTR)numeric;
217 if (numeric > INT32_MAX)
219 WLog_ERR(TAG,
"handle value '%s' out of range for a file descriptor", value);
220 return INVALID_HANDLE_VALUE;
222 return winpr_Pipe_FromFd((
int)numeric);
228BOOL CloseHandle(HANDLE hObject)
233 if (!winpr_Handle_GetInfo(hObject, &type, &hdl) || !hdl || !hdl->ops)
237 if (hdl->ops->CloseHandle)
238 ok = hdl->ops->CloseHandle(hObject);
251 if (type == HANDLE_TYPE_THREAD)
254 if (!winpr_Handle_Release(hObject))
255 winpr_Handle_ConvertToNone(hObject);
260BOOL DuplicateHandle(WINPR_ATTR_UNUSED HANDLE hSourceProcessHandle,
261 WINPR_ATTR_UNUSED HANDLE hSourceHandle,
262 WINPR_ATTR_UNUSED HANDLE hTargetProcessHandle,
263 WINPR_ATTR_UNUSED LPHANDLE lpTargetHandle,
264 WINPR_ATTR_UNUSED DWORD dwDesiredAccess, WINPR_ATTR_UNUSED BOOL bInheritHandle,
265 WINPR_ATTR_UNUSED DWORD dwOptions)
267 WLog_ERR(TAG,
"DuplicateHandle not implemented");
268 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
272BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags)
277 const int fd = winpr_Handle_getFd(hObject);
280 WLog_ERR(TAG,
"unable to resolve a file descriptor for this handle type");
284 const int flags = fcntl(fd, F_GETFD);
287 char buffer[64] = WINPR_C_ARRAY_INIT;
288 WLog_ERR(TAG,
"fcntl(F_GETFD) failed: %s", winpr_strerror(errno, buffer,
sizeof(buffer)));
292 *lpdwFlags = (flags & FD_CLOEXEC) ? 0 : HANDLE_FLAG_INHERIT;
296BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags)
298 const int fd = winpr_Handle_getFd(hObject);
301 WLog_ERR(TAG,
"unable to resolve a file descriptor for this handle type");
308 if (!(dwMask & HANDLE_FLAG_INHERIT))
311 int flags = fcntl(fd, F_GETFD);
314 char buffer[64] = WINPR_C_ARRAY_INIT;
315 WLog_ERR(TAG,
"fcntl(F_GETFD) failed: %s", winpr_strerror(errno, buffer,
sizeof(buffer)));
319 flags = (dwFlags & HANDLE_FLAG_INHERIT) ? (flags & ~FD_CLOEXEC) : (flags | FD_CLOEXEC);
320 if (fcntl(fd, F_SETFD, flags) < 0)
322 char buffer[64] = WINPR_C_ARRAY_INIT;
323 WLog_ERR(TAG,
"fcntl(F_SETFD) failed: %s", winpr_strerror(errno, buffer,
sizeof(buffer)));
330BOOL winpr_set_cloexec(
int fd, BOOL cloexec)
332 const int flags = fcntl(fd, F_GETFD);
336 const int newFlags = cloexec ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
337 return fcntl(fd, F_SETFD, newFlags) >= 0;