FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
urbdrc_helpers.c
1
20#include <freerdp/config.h>
21
22#include "urbdrc_helpers.h"
23#include "urbdrc_types.h"
24#include <winpr/print.h>
25
26const char* mask_to_string(UINT32 mask)
27{
28 switch (mask)
29 {
30 case STREAM_ID_NONE:
31 return "STREAM_ID_NONE";
32
33 case STREAM_ID_PROXY:
34 return "STREAM_ID_PROXY";
35
36 case STREAM_ID_STUB:
37 return "STREAM_ID_STUB";
38
39 default:
40 return "UNKNOWN";
41 }
42}
43const char* interface_to_string(UINT32 id)
44{
45 switch (id)
46 {
47 case CAPABILITIES_NEGOTIATOR:
48 return "CAPABILITIES_NEGOTIATOR";
49
50 case SERVER_CHANNEL_NOTIFICATION:
51 return "SERVER_CHANNEL_NOTIFICATION";
52
53 case CLIENT_CHANNEL_NOTIFICATION:
54 return "CLIENT_CHANNEL_NOTIFICATION";
55
56 default:
57 return "DEVICE_MESSAGE";
58 }
59}
60
61static const char* call_to_string_none(BOOL client, UINT32 interfaceId, UINT32 functionId)
62{
63 WINPR_UNUSED(interfaceId);
64
65 if (client)
66 return "RIM_EXCHANGE_CAPABILITY_RESPONSE [none |client]";
67 else
68 {
69 switch (functionId)
70 {
71 case RIM_EXCHANGE_CAPABILITY_REQUEST:
72 return "RIM_EXCHANGE_CAPABILITY_REQUEST [none |server]";
73
74 case RIMCALL_RELEASE:
75 return "RIMCALL_RELEASE [none |server]";
76
77 case RIMCALL_QUERYINTERFACE:
78 return "RIMCALL_QUERYINTERFACE [none |server]";
79
80 default:
81 return "UNKNOWN [none |server]";
82 }
83 }
84}
85
86static const char* call_to_string_proxy_server(UINT32 functionId)
87{
88 switch (functionId)
89 {
90 case QUERY_DEVICE_TEXT:
91 return "QUERY_DEVICE_TEXT [proxy|server]";
92
93 case INTERNAL_IO_CONTROL:
94 return "INTERNAL_IO_CONTROL [proxy|server]";
95
96 case IO_CONTROL:
97 return "IO_CONTROL [proxy|server]";
98
99 case REGISTER_REQUEST_CALLBACK:
100 return "REGISTER_REQUEST_CALLBACK [proxy|server]";
101
102 case CANCEL_REQUEST:
103 return "CANCEL_REQUEST [proxy|server]";
104
105 case RETRACT_DEVICE:
106 return "RETRACT_DEVICE [proxy|server]";
107
108 case TRANSFER_IN_REQUEST:
109 return "TRANSFER_IN_REQUEST [proxy|server]";
110
111 case TRANSFER_OUT_REQUEST:
112 return "TRANSFER_OUT_REQUEST [proxy|server]";
113
114 default:
115 return "UNKNOWN [proxy|server]";
116 }
117}
118
119static const char* call_to_string_proxy_client(UINT32 functionId)
120{
121 switch (functionId)
122 {
123 case URB_COMPLETION_NO_DATA:
124 return "URB_COMPLETION_NO_DATA [proxy|client]";
125
126 case URB_COMPLETION:
127 return "URB_COMPLETION [proxy|client]";
128
129 case IOCONTROL_COMPLETION:
130 return "IOCONTROL_COMPLETION [proxy|client]";
131
132 case TRANSFER_OUT_REQUEST:
133 return "TRANSFER_OUT_REQUEST [proxy|client]";
134
135 default:
136 return "UNKNOWN [proxy|client]";
137 }
138}
139
140static const char* call_to_string_proxy(BOOL client, UINT32 interfaceId, UINT32 functionId)
141{
142 switch (interfaceId & INTERFACE_ID_MASK)
143 {
144 case CLIENT_DEVICE_SINK:
145 switch (functionId)
146 {
147 case ADD_VIRTUAL_CHANNEL:
148 return "ADD_VIRTUAL_CHANNEL [proxy|sink ]";
149
150 case ADD_DEVICE:
151 return "ADD_DEVICE [proxy|sink ]";
152 case RIMCALL_RELEASE:
153 return "RIMCALL_RELEASE [proxy|sink ]";
154
155 case RIMCALL_QUERYINTERFACE:
156 return "RIMCALL_QUERYINTERFACE [proxy|sink ]";
157 default:
158 return "UNKNOWN [proxy|sink ]";
159 }
160
161 case SERVER_CHANNEL_NOTIFICATION:
162 switch (functionId)
163 {
164 case CHANNEL_CREATED:
165 return "CHANNEL_CREATED [proxy|server]";
166
167 case RIMCALL_RELEASE:
168 return "RIMCALL_RELEASE [proxy|server]";
169
170 case RIMCALL_QUERYINTERFACE:
171 return "RIMCALL_QUERYINTERFACE [proxy|server]";
172
173 default:
174 return "UNKNOWN [proxy|server]";
175 }
176
177 case CLIENT_CHANNEL_NOTIFICATION:
178 switch (functionId)
179 {
180 case CHANNEL_CREATED:
181 return "CHANNEL_CREATED [proxy|client]";
182 case RIMCALL_RELEASE:
183 return "RIMCALL_RELEASE [proxy|client]";
184 case RIMCALL_QUERYINTERFACE:
185 return "RIMCALL_QUERYINTERFACE [proxy|client]";
186 default:
187 return "UNKNOWN [proxy|client]";
188 }
189
190 default:
191 if (client)
192 return call_to_string_proxy_client(functionId);
193 else
194 return call_to_string_proxy_server(functionId);
195 }
196}
197
198static const char* call_to_string_stub(WINPR_ATTR_UNUSED BOOL client,
199 WINPR_ATTR_UNUSED UINT32 interfaceNr,
200 WINPR_ATTR_UNUSED UINT32 functionId)
201{
202 return "QUERY_DEVICE_TEXT_RSP [stub |client]";
203}
204
205const char* call_to_string(BOOL client, UINT32 interfaceNr, UINT32 functionId)
206{
207 const UINT32 mask = (interfaceNr & STREAM_ID_MASK) >> 30;
208 const UINT32 interfaceId = interfaceNr & INTERFACE_ID_MASK;
209
210 switch (mask)
211 {
212 case STREAM_ID_NONE:
213 return call_to_string_none(client, interfaceId, functionId);
214
215 case STREAM_ID_PROXY:
216 return call_to_string_proxy(client, interfaceId, functionId);
217
218 case STREAM_ID_STUB:
219 return call_to_string_stub(client, interfaceId, functionId);
220
221 default:
222 return "UNKNOWN[mask]";
223 }
224}
225
226const char* urb_function_string(UINT16 urb)
227{
228 switch (urb)
229 {
230 case TS_URB_SELECT_CONFIGURATION:
231 return "TS_URB_SELECT_CONFIGURATION";
232
233 case TS_URB_SELECT_INTERFACE:
234 return "TS_URB_SELECT_INTERFACE";
235
236 case TS_URB_PIPE_REQUEST:
237 return "TS_URB_PIPE_REQUEST";
238
239 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
240 return "TS_URB_TAKE_FRAME_LENGTH_CONTROL";
241
242 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
243 return "TS_URB_RELEASE_FRAME_LENGTH_CONTROL";
244
245 case TS_URB_GET_FRAME_LENGTH:
246 return "TS_URB_GET_FRAME_LENGTH";
247
248 case TS_URB_SET_FRAME_LENGTH:
249 return "TS_URB_SET_FRAME_LENGTH";
250
251 case TS_URB_GET_CURRENT_FRAME_NUMBER:
252 return "TS_URB_GET_CURRENT_FRAME_NUMBER";
253
254 case TS_URB_CONTROL_TRANSFER:
255 return "TS_URB_CONTROL_TRANSFER";
256
257 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
258 return "TS_URB_BULK_OR_INTERRUPT_TRANSFER";
259
260 case TS_URB_ISOCH_TRANSFER:
261 return "TS_URB_ISOCH_TRANSFER";
262
263 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
264 return "TS_URB_GET_DESCRIPTOR_FROM_DEVICE";
265
266 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
267 return "TS_URB_SET_DESCRIPTOR_TO_DEVICE";
268
269 case TS_URB_SET_FEATURE_TO_DEVICE:
270 return "TS_URB_SET_FEATURE_TO_DEVICE";
271
272 case TS_URB_SET_FEATURE_TO_INTERFACE:
273 return "TS_URB_SET_FEATURE_TO_INTERFACE";
274
275 case TS_URB_SET_FEATURE_TO_ENDPOINT:
276 return "TS_URB_SET_FEATURE_TO_ENDPOINT";
277
278 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
279 return "TS_URB_CLEAR_FEATURE_TO_DEVICE";
280
281 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
282 return "TS_URB_CLEAR_FEATURE_TO_INTERFACE";
283
284 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
285 return "TS_URB_CLEAR_FEATURE_TO_ENDPOINT";
286
287 case TS_URB_GET_STATUS_FROM_DEVICE:
288 return "TS_URB_GET_STATUS_FROM_DEVICE";
289
290 case TS_URB_GET_STATUS_FROM_INTERFACE:
291 return "TS_URB_GET_STATUS_FROM_INTERFACE";
292
293 case TS_URB_GET_STATUS_FROM_ENDPOINT:
294 return "TS_URB_GET_STATUS_FROM_ENDPOINT";
295
296 case TS_URB_RESERVED_0X0016:
297 return "TS_URB_RESERVED_0X0016";
298
299 case TS_URB_VENDOR_DEVICE:
300 return "TS_URB_VENDOR_DEVICE";
301
302 case TS_URB_VENDOR_INTERFACE:
303 return "TS_URB_VENDOR_INTERFACE";
304
305 case TS_URB_VENDOR_ENDPOINT:
306 return "TS_URB_VENDOR_ENDPOINT";
307
308 case TS_URB_CLASS_DEVICE:
309 return "TS_URB_CLASS_DEVICE";
310
311 case TS_URB_CLASS_INTERFACE:
312 return "TS_URB_CLASS_INTERFACE";
313
314 case TS_URB_CLASS_ENDPOINT:
315 return "TS_URB_CLASS_ENDPOINT";
316
317 case TS_URB_RESERVE_0X001D:
318 return "TS_URB_RESERVE_0X001D";
319
320 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
321 return "TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL";
322
323 case TS_URB_CLASS_OTHER:
324 return "TS_URB_CLASS_OTHER";
325
326 case TS_URB_VENDOR_OTHER:
327 return "TS_URB_VENDOR_OTHER";
328
329 case TS_URB_GET_STATUS_FROM_OTHER:
330 return "TS_URB_GET_STATUS_FROM_OTHER";
331
332 case TS_URB_CLEAR_FEATURE_TO_OTHER:
333 return "TS_URB_CLEAR_FEATURE_TO_OTHER";
334
335 case TS_URB_SET_FEATURE_TO_OTHER:
336 return "TS_URB_SET_FEATURE_TO_OTHER";
337
338 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
339 return "TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT";
340
341 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
342 return "TS_URB_SET_DESCRIPTOR_TO_ENDPOINT";
343
344 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
345 return "TS_URB_CONTROL_GET_CONFIGURATION_REQUEST";
346
347 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
348 return "TS_URB_CONTROL_GET_INTERFACE_REQUEST";
349
350 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
351 return "TS_URB_GET_DESCRIPTOR_FROM_INTERFACE";
352
353 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
354 return "TS_URB_SET_DESCRIPTOR_TO_INTERFACE";
355
356 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
357 return "TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST";
358
359 case TS_URB_RESERVE_0X002B:
360 return "TS_URB_RESERVE_0X002B";
361
362 case TS_URB_RESERVE_0X002C:
363 return "TS_URB_RESERVE_0X002C";
364
365 case TS_URB_RESERVE_0X002D:
366 return "TS_URB_RESERVE_0X002D";
367
368 case TS_URB_RESERVE_0X002E:
369 return "TS_URB_RESERVE_0X002E";
370
371 case TS_URB_RESERVE_0X002F:
372 return "TS_URB_RESERVE_0X002F";
373
374 case TS_URB_SYNC_RESET_PIPE:
375 return "TS_URB_SYNC_RESET_PIPE";
376
377 case TS_URB_SYNC_CLEAR_STALL:
378 return "TS_URB_SYNC_CLEAR_STALL";
379
380 case TS_URB_CONTROL_TRANSFER_EX:
381 return "TS_URB_CONTROL_TRANSFER_EX";
382
383 default:
384 return "UNKNOWN";
385 }
386}
387
388void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s)
389{
390 const char* type = write ? "WRITE" : "READ";
391 UINT32 InterfaceId = 0;
392 UINT32 MessageId = 0;
393 UINT32 FunctionId = 0;
394 size_t length = 0;
395 size_t pos = 0;
396
397 pos = Stream_GetPosition(s);
398 if (write)
399 {
400 length = pos;
401 Stream_SetPosition(s, 0);
402 }
403 else
404 length = Stream_GetRemainingLength(s);
405
406 if (length < 12)
407 return;
408
409 Stream_Read_UINT32(s, InterfaceId);
410 Stream_Read_UINT32(s, MessageId);
411 Stream_Read_UINT32(s, FunctionId);
412 Stream_SetPosition(s, pos);
413
414 WLog_Print(log, WLOG_DEBUG,
415 "[%-5s] %s [%08" PRIx32 "] InterfaceId=%08" PRIx32 ", MessageId=%08" PRIx32
416 ", FunctionId=%08" PRIx32 ", length=%" PRIuz,
417 type, call_to_string(client, InterfaceId, FunctionId), FunctionId, InterfaceId,
418 MessageId, FunctionId, length);
419#if defined(WITH_DEBUG_URBDRC)
420 if (write)
421 WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC sent: ---");
422 else
423 WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC received:");
424 winpr_HexLogDump(log, WLOG_TRACE, Stream_Buffer(s), length);
425 WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC end -----");
426#endif
427}
428
429/* [MS-RDPEUSB] 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
430BOOL write_shared_message_header_with_functionid(wStream* s, UINT32 InterfaceId, UINT32 MessageId,
431 UINT32 FunctionId)
432{
433 if (!Stream_EnsureRemainingCapacity(s, 12))
434 return FALSE;
435
436 Stream_Write_UINT32(s, InterfaceId);
437 Stream_Write_UINT32(s, MessageId);
438 Stream_Write_UINT32(s, FunctionId);
439 return TRUE;
440}
441
442wStream* create_shared_message_header_with_functionid(UINT32 InterfaceId, UINT32 MessageId,
443 UINT32 FunctionId, size_t OutputSize)
444{
445 wStream* out = Stream_New(NULL, 12ULL + OutputSize);
446 if (!out)
447 return NULL;
448 (void)write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId);
449 return out;
450}