Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/channels/rdpdr/client/devman.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Device Redirection Virtual Channel
4
 *
5
 * Copyright 2010-2011 Vic Lee
6
 * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
 * Copyright 2015 Thincast Technologies GmbH
8
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9
 * Copyright 2016 Armin Novak <armin.novak@gmail.com>
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 *     http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23
24
#include <freerdp/config.h>
25
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
30
#include <winpr/crt.h>
31
#include <winpr/stream.h>
32
33
#include <freerdp/types.h>
34
#include <freerdp/addin.h>
35
#include <freerdp/client/channels.h>
36
#include <freerdp/channels/log.h>
37
38
#include "rdpdr_main.h"
39
40
#include "devman.h"
41
42
#define TAG CHANNELS_TAG("rdpdr.client")
43
44
static void devman_device_free(void* obj)
45
0
{
46
0
  DEVICE* device = (DEVICE*)obj;
47
48
0
  if (!device)
49
0
    return;
50
51
0
  IFCALL(device->Free, device);
52
0
}
53
54
DEVMAN* devman_new(rdpdrPlugin* rdpdr)
55
0
{
56
0
  DEVMAN* devman = NULL;
57
58
0
  if (!rdpdr)
59
0
    return NULL;
60
61
0
  devman = (DEVMAN*)calloc(1, sizeof(DEVMAN));
62
63
0
  if (!devman)
64
0
  {
65
0
    WLog_Print(rdpdr->log, WLOG_INFO, "calloc failed!");
66
0
    return NULL;
67
0
  }
68
69
0
  devman->plugin = (void*)rdpdr;
70
0
  devman->id_sequence = 1;
71
0
  devman->devices = ListDictionary_New(TRUE);
72
73
0
  if (!devman->devices)
74
0
  {
75
0
    WLog_Print(rdpdr->log, WLOG_INFO, "ListDictionary_New failed!");
76
0
    free(devman);
77
0
    return NULL;
78
0
  }
79
80
0
  ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free;
81
0
  return devman;
82
0
}
83
84
void devman_free(DEVMAN* devman)
85
0
{
86
0
  ListDictionary_Free(devman->devices);
87
0
  free(devman);
88
0
}
89
90
void devman_unregister_device(DEVMAN* devman, void* key)
91
0
{
92
0
  DEVICE* device = NULL;
93
94
0
  if (!devman || !key)
95
0
    return;
96
97
0
  device = (DEVICE*)ListDictionary_Take(devman->devices, key);
98
99
0
  if (device)
100
0
    devman_device_free(device);
101
0
}
102
103
/**
104
 * Function description
105
 *
106
 * @return 0 on success, otherwise a Win32 error code
107
 */
108
static UINT devman_register_device(DEVMAN* devman, DEVICE* device)
109
0
{
110
0
  void* key = NULL;
111
112
0
  if (!devman || !device)
113
0
    return ERROR_INVALID_PARAMETER;
114
115
0
  device->id = devman->id_sequence++;
116
0
  key = (void*)(size_t)device->id;
117
118
0
  if (!ListDictionary_Add(devman->devices, key, device))
119
0
  {
120
0
    WLog_INFO(TAG, "ListDictionary_Add failed!");
121
0
    return ERROR_INTERNAL_ERROR;
122
0
  }
123
124
0
  return CHANNEL_RC_OK;
125
0
}
126
127
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id)
128
0
{
129
0
  DEVICE* device = NULL;
130
0
  void* key = (void*)(size_t)id;
131
132
0
  if (!devman)
133
0
  {
134
0
    WLog_ERR(TAG, "device manager=%p", devman);
135
0
    return NULL;
136
0
  }
137
138
0
  device = (DEVICE*)ListDictionary_GetItemValue(devman->devices, key);
139
0
  if (!device)
140
0
    WLog_WARN(TAG, "could not find device ID 0x%08" PRIx32, id);
141
0
  return device;
142
0
}
143
144
DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
145
0
{
146
0
  DEVICE* device = NULL;
147
0
  ULONG_PTR* keys = NULL;
148
149
0
  if (!devman)
150
0
    return NULL;
151
152
0
  ListDictionary_Lock(devman->devices);
153
0
  const size_t count = ListDictionary_GetKeys(devman->devices, &keys);
154
155
0
  for (size_t x = 0; x < count; x++)
156
0
  {
157
0
    DEVICE* cur = (DEVICE*)ListDictionary_GetItemValue(devman->devices, (void*)keys[x]);
158
159
0
    if (!cur)
160
0
      continue;
161
162
0
    if (cur->type != type)
163
0
      continue;
164
165
0
    device = cur;
166
0
    break;
167
0
  }
168
169
0
  free(keys);
170
0
  ListDictionary_Unlock(devman->devices);
171
0
  return device;
172
0
}
173
174
static const char DRIVE_SERVICE_NAME[] = "drive";
175
static const char PRINTER_SERVICE_NAME[] = "printer";
176
static const char SMARTCARD_SERVICE_NAME[] = "smartcard";
177
static const char SERIAL_SERVICE_NAME[] = "serial";
178
static const char PARALLEL_SERVICE_NAME[] = "parallel";
179
180
/**
181
 * Function description
182
 *
183
 * @return 0 on success, otherwise a Win32 error code
184
 */
185
UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpContext* rdpcontext)
186
0
{
187
0
  const char* ServiceName = NULL;
188
0
  DEVICE_SERVICE_ENTRY_POINTS ep;
189
0
  PDEVICE_SERVICE_ENTRY entry = NULL;
190
0
  union
191
0
  {
192
0
    const RDPDR_DEVICE* cdp;
193
0
    RDPDR_DEVICE* dp;
194
0
  } devconv;
195
196
0
  devconv.cdp = device;
197
0
  if (!devman || !device || !rdpcontext)
198
0
    return ERROR_INVALID_PARAMETER;
199
200
0
  if (device->Type == RDPDR_DTYP_FILESYSTEM)
201
0
    ServiceName = DRIVE_SERVICE_NAME;
202
0
  else if (device->Type == RDPDR_DTYP_PRINT)
203
0
    ServiceName = PRINTER_SERVICE_NAME;
204
0
  else if (device->Type == RDPDR_DTYP_SMARTCARD)
205
0
    ServiceName = SMARTCARD_SERVICE_NAME;
206
0
  else if (device->Type == RDPDR_DTYP_SERIAL)
207
0
    ServiceName = SERIAL_SERVICE_NAME;
208
0
  else if (device->Type == RDPDR_DTYP_PARALLEL)
209
0
    ServiceName = PARALLEL_SERVICE_NAME;
210
211
0
  if (!ServiceName)
212
0
  {
213
0
    WLog_INFO(TAG, "ServiceName %s did not match!", ServiceName);
214
0
    return ERROR_INVALID_NAME;
215
0
  }
216
217
0
  if (device->Name)
218
0
    WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name);
219
0
  else
220
0
    WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
221
222
0
  entry = (PDEVICE_SERVICE_ENTRY)freerdp_load_channel_addin_entry(ServiceName, NULL,
223
0
                                                                  "DeviceServiceEntry", 0);
224
225
0
  if (!entry)
226
0
  {
227
0
    WLog_INFO(TAG, "freerdp_load_channel_addin_entry failed!");
228
0
    return ERROR_INTERNAL_ERROR;
229
0
  }
230
231
0
  ep.devman = devman;
232
0
  ep.RegisterDevice = devman_register_device;
233
0
  ep.device = devconv.dp;
234
0
  ep.rdpcontext = rdpcontext;
235
0
  return entry(&ep);
236
0
}