Coverage Report

Created: 2026-08-31 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/handle/handle.c
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Handle Management
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <winpr/config.h>
22
23
#include <winpr/handle.h>
24
25
#ifndef _WIN32
26
27
#include <errno.h>
28
#include <fcntl.h>
29
#include <pthread.h>
30
#include <string.h>
31
32
#include "../synch/synch.h"
33
#include "../thread/thread.h"
34
#include "../pipe/pipe.h"
35
#include "../comm/comm.h"
36
#include "../security/security.h"
37
38
#ifdef WINPR_HAVE_UNISTD_H
39
#include <unistd.h>
40
#endif
41
42
#include <winpr/assert.h>
43
44
#include "../handle/handle.h"
45
#include "../log.h"
46
#define TAG WINPR_TAG("handle")
47
48
BOOL CloseHandle(HANDLE hObject)
49
0
{
50
0
  ULONG type = 0;
51
0
  WINPR_HANDLE* hdl = nullptr;
52
53
0
  if (!winpr_Handle_GetInfo(hObject, &type, &hdl) || !hdl || !hdl->ops)
54
0
    return FALSE;
55
56
0
  BOOL ok = TRUE;
57
0
  if (hdl->ops->CloseHandle)
58
0
    ok = hdl->ops->CloseHandle(hObject);
59
60
  /* a type's CloseHandle op can legitimately refuse (e.g. file.c won't close the pStdHandleFile
61
   * singleton unless forced) - if it did, this handle wasn't actually closed, so leave its
62
   * refcount/memory alone entirely. */
63
0
  if (!ok)
64
0
    return FALSE;
65
66
  /* WINPR_THREAD manages its own close/free lifecycle: closing the handle of a still-running
67
   * thread detaches it instead of freeing it, and the free only happens later, from the
68
   * thread's own pthread routine once it actually returns (see ThreadCloseHandle() /
69
   * cleanup_handle() in thread.c). Applying the generic release-then-maybe-free sequence below
70
   * on top of that would free the struct while the thread may still be running against it. */
71
0
  if (type == HANDLE_TYPE_THREAD)
72
0
    return TRUE;
73
74
0
  if (!winpr_Handle_Release(hObject))
75
0
    winpr_Handle_ConvertToNone(hObject);
76
77
0
  return TRUE;
78
0
}
79
80
BOOL DuplicateHandle(WINPR_ATTR_UNUSED HANDLE hSourceProcessHandle,
81
                     WINPR_ATTR_UNUSED HANDLE hSourceHandle,
82
                     WINPR_ATTR_UNUSED HANDLE hTargetProcessHandle,
83
                     WINPR_ATTR_UNUSED LPHANDLE lpTargetHandle,
84
                     WINPR_ATTR_UNUSED DWORD dwDesiredAccess, WINPR_ATTR_UNUSED BOOL bInheritHandle,
85
                     WINPR_ATTR_UNUSED DWORD dwOptions)
86
0
{
87
0
  WLog_ERR(TAG, "DuplicateHandle not implemented");
88
0
  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
89
0
  return FALSE;
90
0
}
91
92
BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags)
93
0
{
94
0
  if (!lpdwFlags)
95
0
    return FALSE;
96
97
0
  const int fd = winpr_Handle_getFd(hObject);
98
0
  if (fd < 0)
99
0
  {
100
0
    WLog_ERR(TAG, "unable to resolve a file descriptor for this handle type");
101
0
    return FALSE;
102
0
  }
103
104
0
  const int flags = fcntl(fd, F_GETFD);
105
0
  if (flags < 0)
106
0
  {
107
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
108
0
    WLog_ERR(TAG, "fcntl(F_GETFD) failed: %s", winpr_strerror(errno, buffer, sizeof(buffer)));
109
0
    return FALSE;
110
0
  }
111
112
0
  *lpdwFlags = (flags & FD_CLOEXEC) ? 0 : HANDLE_FLAG_INHERIT;
113
0
  return TRUE;
114
0
}
115
116
BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags)
117
0
{
118
0
  const int fd = winpr_Handle_getFd(hObject);
119
0
  if (fd < 0)
120
0
  {
121
0
    WLog_ERR(TAG, "unable to resolve a file descriptor for this handle type");
122
0
    return FALSE;
123
0
  }
124
125
  /* only HANDLE_FLAG_INHERIT is meaningful on POSIX; ignore any other bit in the mask rather
126
   * than failing, matching how Windows treats masks it doesn't recognize on other handle
127
   * types */
128
0
  if (!(dwMask & HANDLE_FLAG_INHERIT))
129
0
    return TRUE;
130
131
0
  int flags = fcntl(fd, F_GETFD);
132
0
  if (flags < 0)
133
0
  {
134
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
135
0
    WLog_ERR(TAG, "fcntl(F_GETFD) failed: %s", winpr_strerror(errno, buffer, sizeof(buffer)));
136
0
    return FALSE;
137
0
  }
138
139
0
  flags = (dwFlags & HANDLE_FLAG_INHERIT) ? (flags & ~FD_CLOEXEC) : (flags | FD_CLOEXEC);
140
0
  if (fcntl(fd, F_SETFD, flags) < 0)
141
0
  {
142
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
143
0
    WLog_ERR(TAG, "fcntl(F_SETFD) failed: %s", winpr_strerror(errno, buffer, sizeof(buffer)));
144
0
    return FALSE;
145
0
  }
146
147
0
  return TRUE;
148
0
}
149
150
BOOL winpr_set_cloexec(int fd, BOOL cloexec)
151
0
{
152
0
  const int flags = fcntl(fd, F_GETFD);
153
0
  if (flags < 0)
154
0
    return FALSE;
155
156
0
  const int newFlags = cloexec ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
157
  return fcntl(fd, F_SETFD, newFlags) >= 0;
158
0
}
159
160
#endif