FreeRDP
Loading...
Searching...
No Matches
data_transfer.c
1
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <winpr/sysinfo.h>
26#include <winpr/cast.h>
27
28#include <urbdrc_helpers.h>
29
30#include "urbdrc_types.h"
31#include "data_transfer.h"
32#include "msusb.h"
33
34static void usb_process_get_port_status(IUDEVICE* pdev, wStream* out)
35{
36 int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
37
38 switch (bcdUSB)
39 {
40 case USB_v1_0:
41 Stream_Write_UINT32(out, 0x303);
42 break;
43
44 case USB_v1_1:
45 Stream_Write_UINT32(out, 0x103);
46 break;
47
48 case USB_v2_0:
49 default:
50 Stream_Write_UINT32(out, 0x503);
51 break;
52 }
53}
54
55/* [MS-RDPEUSB] 2.2.10.1.1TS_URB_RESULT_HEADER */
56static BOOL write_urb_result_header(wStream* s, UINT16 Size, UINT32 status)
57{
58 if (!Stream_EnsureRemainingCapacity(s, 8ULL + Size))
59 return FALSE;
60 Stream_Write_UINT16(s, Size);
61 Stream_Seek_UINT16(s);
62 Stream_Write_UINT32(s, status);
63 return TRUE;
64}
65
66/* [MS-RDPEUSB] 2.2.7.2 URB Completion (URB_COMPLETION)
67 * 2.2.7.3 URB Completion No Data (URB_COMPLETION_NO_DATA)
68 */
69static wStream* create_urb_completion_message(UINT32 InterfaceId, UINT32 MessageId,
70 UINT32 RequestId, UINT32 FunctionId)
71{
72 wStream* out =
73 create_shared_message_header_with_functionid(InterfaceId, MessageId, FunctionId, 4);
74 if (!out)
75 return nullptr;
76
77 Stream_Write_UINT32(out, RequestId);
78 return out;
79}
80
81static UINT send_urb_completion_message(GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
82 HRESULT hResult, UINT32 OutputSize, const void* data)
83{
84 WINPR_ASSERT(callback);
85 UINT status = ERROR_OUTOFMEMORY;
86
87 if (!Stream_EnsureRemainingCapacity(out, 8ULL + OutputSize))
88 goto fail;
89
90 Stream_Write_INT32(out, hResult);
91 Stream_Write_UINT32(out, OutputSize);
92 Stream_Write(out, data, OutputSize);
93 return stream_write_and_free(callback->plugin, callback->channel, out);
94
95fail:
96 Stream_Free(out, TRUE);
97 return status;
98}
99
100/* [MS-RDPEUSB] 2.2.7.2 and 2.2.7.3:
101 * Only a TRANSFER_IN_REQUEST that returns data carries an OutputBuffer.
102 * TRANSFER_OUT_REQUEST reports the transferred byte count in OutputBufferSize,
103 * but always uses URB_COMPLETION_NO_DATA. */
104static UINT32 urb_completion_payload_size(int transferDir, UINT32 outputBufferSize)
105{
106 return (transferDir == USBD_TRANSFER_DIRECTION_IN) ? outputBufferSize : 0;
107}
108
109static UINT urb_write_completion(WINPR_ATTR_UNUSED IUDEVICE* pdev,
110 GENERIC_CHANNEL_CALLBACK* callback, BOOL noAck, wStream* out,
111 UINT32 InterfaceId, UINT32 MessageId, UINT32 RequestId,
112 UINT32 usbd_status, UINT32 OutputBufferSize, int transferDir)
113{
114 if (!out)
115 return ERROR_INVALID_PARAMETER;
116
117 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
118 if (Stream_Capacity(out) < payloadSize + 36ULL)
119 {
120 Stream_Free(out, TRUE);
121 return ERROR_INVALID_PARAMETER;
122 }
123
124 Stream_ResetPosition(out);
125
126 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
127 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
128 {
129 Stream_Free(out, TRUE);
130 return ERROR_OUTOFMEMORY;
131 }
132
133 Stream_Write_UINT32(out, RequestId);
134 Stream_Write_UINT32(out, 8);
136 if (!write_urb_result_header(out, 8, usbd_status))
137 {
138 Stream_Free(out, TRUE);
139 return ERROR_OUTOFMEMORY;
140 }
141
142 /* [MS-RDPEUSB] URB_COMPLETION: a failed URB must also fail the IRP, otherwise the server side
143 * (e.g. usbstor) never runs its stall recovery (SYNC_RESET_PIPE_AND_CLEAR_STALL) */
144 HRESULT hr = S_OK;
145 const UINT32 mask = 0x80000000ul;
146 const UINT32 masked = usbd_status & mask;
147 if (masked == mask)
148 hr = HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
149 Stream_Write_INT32(out, hr);
150 Stream_Write_UINT32(out, OutputBufferSize);
151 Stream_Seek(out, payloadSize);
152
153 if (!noAck)
154 return stream_write_and_free(callback->plugin, callback->channel, out);
155 else
156 Stream_Free(out, TRUE);
157
158 return ERROR_SUCCESS;
159}
160
161static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
162 UINT32 OutputBufferSize)
163{
164 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
165
166#if UINT32_MAX >= SIZE_MAX
167 if (OutputBufferSize > UINT32_MAX - 28ull)
168 return nullptr;
169#endif
170
171 wStream* out = create_shared_message_header_with_functionid(
172 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
173 if (!out)
174 return nullptr;
175
176 Stream_Write_UINT32(out, RequestId);
177 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
178 Stream_Write_UINT32(out, OutputBufferSize);
179 Stream_Write_UINT32(out, OutputBufferSize);
180 return out;
181}
182
183/* [MS-RDPEUSB] 2.2.7.1 IO Control Completion (IOCONTROL_COMPLETION)
184 *
185 * The Information and OutputBufferSize fields describe the OutputBuffer that
186 * follows them, but urb_create_iocompletion() has to write both before the IO
187 * control handler has produced any output. Rewrite them once the payload is
188 * complete so that a handler which returns nothing does not announce a buffer
189 * it never sends.
190 */
191static BOOL urb_finalize_iocompletion(wStream* out)
192{
193 WINPR_ASSERT(out);
194
195 const size_t header = 12ULL /* SHARED_MSG_HEADER */ + 4ULL /* RequestId */;
196 const size_t offset = header + 4ULL /* HResult */;
197 const size_t fixed = offset + 4ULL /* Information */ + 4ULL /* OutputBufferSize */;
198 const size_t end = Stream_GetPosition(out);
199
200 if (end < fixed)
201 return FALSE;
202
203 const size_t OutputBufferSize = end - fixed;
204
205 if (OutputBufferSize > UINT32_MAX)
206 return FALSE;
207
208 const UINT32 size = WINPR_ASSERTING_INT_CAST(UINT32, OutputBufferSize);
209
210 if (!Stream_SetPosition(out, offset))
211 return FALSE;
212
213 Stream_Write_UINT32(out, size);
214 Stream_Write_UINT32(out, size);
215 return Stream_SetPosition(out, end);
216}
217
218static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
219 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
220 IUDEVMAN* udevman)
221{
222 UINT32 NumRequestCompletion = 0;
223 UINT32 RequestCompletion = 0;
224
225 if (!callback || !s || !udevman || !pdev)
226 return ERROR_INVALID_PARAMETER;
227
228 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
229
230 if (!urbdrc)
231 return ERROR_INVALID_PARAMETER;
232
233 WLog_Print(urbdrc->log, WLOG_DEBUG, "urbdrc_process_register_request_callback");
234
235 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
236 return ERROR_INVALID_DATA;
237
238 Stream_Read_UINT32(s, NumRequestCompletion);
240 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL * NumRequestCompletion))
241 return ERROR_INVALID_DATA;
242 for (uint32_t x = 0; x < NumRequestCompletion; x++)
243 {
246 Stream_Read_UINT32(s, RequestCompletion);
247 pdev->set_ReqCompletion(pdev, RequestCompletion);
248 }
249
250 return ERROR_SUCCESS;
251}
252
253static UINT urbdrc_process_cancel_request(IUDEVICE* pdev, wStream* s, IUDEVMAN* udevman)
254{
255 UINT32 CancelId = 0;
256 URBDRC_PLUGIN* urbdrc = nullptr;
257
258 if (!s || !udevman || !pdev)
259 return ERROR_INVALID_PARAMETER;
260
261 urbdrc = (URBDRC_PLUGIN*)udevman->plugin;
262
263 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
264 return ERROR_INVALID_DATA;
265
266 Stream_Read_UINT32(s, CancelId);
267 WLog_Print(urbdrc->log, WLOG_DEBUG, "CANCEL_REQUEST: CancelId=%08" PRIx32 "", CancelId);
268
269 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
270 return ERROR_INTERNAL_ERROR;
271
272 return ERROR_SUCCESS;
273}
274
275static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev, wStream* s,
276 IUDEVMAN* udevman)
277{
278 UINT32 Reason = 0;
279 URBDRC_PLUGIN* urbdrc = nullptr;
280
281 if (!s || !udevman)
282 return ERROR_INVALID_PARAMETER;
283
284 urbdrc = (URBDRC_PLUGIN*)udevman->plugin;
285
286 if (!urbdrc)
287 return ERROR_INVALID_PARAMETER;
288
289 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
290 return ERROR_INVALID_DATA;
291
292 Stream_Read_UINT32(s, Reason);
294 switch (Reason)
295 {
296 case UsbRetractReason_BlockedByPolicy:
297 WLog_Print(urbdrc->log, WLOG_DEBUG,
298 "UsbRetractReason_BlockedByPolicy: now it is not support");
299 return ERROR_ACCESS_DENIED;
300
301 default:
302 WLog_Print(urbdrc->log, WLOG_DEBUG,
303 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32 "", Reason);
304 return ERROR_ACCESS_DENIED;
305 }
306
307 return ERROR_SUCCESS;
308}
309
310static UINT urbdrc_process_io_control(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
311 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
312{
313 UINT32 InterfaceId = 0;
314 UINT32 IoControlCode = 0;
315 UINT32 InputBufferSize = 0;
316 UINT32 OutputBufferSize = 0;
317 UINT32 RequestId = 0;
318 UINT32 usbd_status = USBD_STATUS_SUCCESS;
319 wStream* out = nullptr;
320 int success = 0;
321 URBDRC_PLUGIN* urbdrc = nullptr;
322
323 if (!callback || !s || !udevman || !pdev)
324 return ERROR_INVALID_PARAMETER;
325
326 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
327
328 if (!urbdrc)
329 return ERROR_INVALID_PARAMETER;
330
331 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
332 return ERROR_INVALID_DATA;
333
334 Stream_Read_UINT32(s, IoControlCode);
335 Stream_Read_UINT32(s, InputBufferSize);
336
337 if (!Stream_SafeSeek(s, InputBufferSize))
338 return ERROR_INVALID_DATA;
339 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
340 return ERROR_INVALID_DATA;
341
342 Stream_Read_UINT32(s, OutputBufferSize);
343 Stream_Read_UINT32(s, RequestId);
344
345 if (OutputBufferSize > UINT32_MAX - 4)
346 return ERROR_INVALID_DATA;
347
348 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
349 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
350
351 if (!out)
352 return ERROR_OUTOFMEMORY;
353
354 switch (IoControlCode)
355 {
356 case IOCTL_INTERNAL_USB_SUBMIT_URB:
357 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
358 WLog_Print(urbdrc->log, WLOG_ERROR,
359 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
360 break;
361
362 case IOCTL_INTERNAL_USB_RESET_PORT:
363 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
364 success = pdev->reset_device(pdev);
365 break;
366
367 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
368 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
369 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
370 Stream_Pointer(out));
371
372 if (success)
373 {
374 if (!Stream_SafeSeek(out, OutputBufferSize))
375 {
376 Stream_Free(out, TRUE);
377 return ERROR_INVALID_DATA;
378 }
379
380 if (pdev->isExist(pdev) == 0)
381 Stream_Write_UINT32(out, 0);
382 else
383 usb_process_get_port_status(pdev, out);
384 }
385
386 break;
387
388 case IOCTL_INTERNAL_USB_CYCLE_PORT:
389 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
390 WLog_Print(urbdrc->log, WLOG_ERROR,
391 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
392 break;
393
394 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
395 WLog_Print(urbdrc->log, WLOG_DEBUG,
396 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
397 WLog_Print(urbdrc->log, WLOG_ERROR,
398 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
399 break;
400
401 default:
402 WLog_Print(urbdrc->log, WLOG_DEBUG,
403 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32 "",
404 IoControlCode);
405 Stream_Free(out, TRUE);
406 return ERROR_INVALID_OPERATION;
407 }
408
409 if (!urb_finalize_iocompletion(out))
410 {
411 Stream_Free(out, TRUE);
412 return ERROR_INTERNAL_ERROR;
413 }
414
415 return stream_write_and_free(callback->plugin, callback->channel, out);
416}
417
418static UINT urbdrc_process_internal_io_control(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
419 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
420{
421 if (!pdev || !callback || !s || !udevman)
422 return ERROR_INVALID_PARAMETER;
423
424 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
425 WINPR_ASSERT(urbdrc);
426
427 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
428 return ERROR_INVALID_DATA;
429
430 const UINT32 IoControlCode = Stream_Get_UINT32(s);
431 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
432 {
433 WLog_ERR(
434 TAG,
435 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
436 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
437 IoControlCode);
438 return ERROR_INVALID_DATA;
439 }
440 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
441
442 if (!Stream_SafeSeek(s, InputBufferSize))
443 return ERROR_INVALID_DATA;
444 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
445 return ERROR_INVALID_DATA;
446 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
447 const UINT32 RequestId = Stream_Get_UINT32(s);
448 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
449 // TODO: Implement control code.
451 const UINT32 frames = GetTickCount();
452
453 if (4 > OutputBufferSize)
454 {
455 WLog_Print(urbdrc->log, WLOG_DEBUG, "out_size %" PRIu32 " > OutputBufferSize %" PRIu32, 4u,
456 OutputBufferSize);
457 return ERROR_BAD_CONFIGURATION;
458 }
459 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
460
461 if (!out)
462 return ERROR_OUTOFMEMORY;
463
464 Stream_Write_UINT32(out, frames);
465 return stream_write_and_free(callback->plugin, callback->channel, out);
466}
467
468/* [MS-RDPEUSB] 2.2.6.6 Query Device Text Response Message (QUERY_DEVICE_TEXT_RSP) */
469static UINT urbdrc_send_query_device_text_response(GENERIC_CHANNEL_CALLBACK* callback,
470 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
471 const BYTE* text, uint8_t bytelen)
472{
473 WINPR_ASSERT(callback);
474
475 const uint8_t charlen = bytelen / sizeof(WCHAR);
476 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
477 8ULL + bytelen);
478
479 if (!out)
480 return ERROR_OUTOFMEMORY;
481
482 Stream_Write(out, text, bytelen); /* '\0' terminated unicode */
483 Stream_Write_INT32(out, hr);
484 return stream_write_and_free(callback->plugin, callback->channel, out);
485}
486
487static UINT urbdrc_process_query_device_text(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
488 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
489{
490 UINT32 TextType = 0;
491 UINT32 LocaleId = 0;
492 UINT8 bufferSize = 0xFF;
493 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
494
495 if (!pdev || !callback || !s || !udevman)
496 return ERROR_INVALID_PARAMETER;
497 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
498 return ERROR_INVALID_DATA;
499
500 Stream_Read_UINT32(s, TextType);
501 Stream_Read_UINT32(s, LocaleId);
502 if (LocaleId > UINT16_MAX)
503 return ERROR_INVALID_DATA;
504
505 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
506 &bufferSize, DeviceDescription);
507 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
508 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
509 DeviceDescription, bufferSize);
510}
511
512static void func_select_all_interface_for_msconfig(URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
513 MSUSB_CONFIG_DESCRIPTOR* MsConfig)
514{
515 WINPR_ASSERT(urbdrc);
516 WINPR_ASSERT(pdev);
517 WINPR_ASSERT(MsConfig);
518
519 MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces;
520 UINT32 NumInterfaces = MsConfig->NumInterfaces;
521
522 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
523 {
524 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
525 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
526 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
527 if (rc < 0)
528 {
529 WLog_Print(urbdrc->log, WLOG_WARN,
530 "select_interface %" PRIu8 " [%" PRIu8 "] failed [%d]", InterfaceNumber,
531 AlternateSetting, rc);
532 }
533 }
534}
535
536/* [MS-RDPEUSB] 2.2.10.2 TS_URB_SELECT_CONFIGURATION_RESULT */
537static UINT send_urb_select_configuration_result(GENERIC_CHANNEL_CALLBACK* callback,
538 UINT32 InterfaceId, UINT32 MessageId,
539 UINT32 RequestId, UINT32 UrbStatus,
540 const MSUSB_CONFIG_DESCRIPTOR* MsConfig)
541{
542 wStream* out =
543 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
544 if (!out)
545 return ERROR_OUTOFMEMORY;
546
547 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
548 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
549
550 if (!Stream_EnsureRemainingCapacity(out, 4))
551 goto fail;
552 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
553
554 if (!write_urb_result_header(out, usize, UrbStatus))
555 goto fail;
556
558 if (MsConfig)
559 {
560 if (!msusb_msconfig_write(MsConfig, out))
561 goto fail;
562 }
563 else
564 {
565 Stream_Write_UINT32(out, 0);
566 Stream_Write_UINT32(out, 0);
567 }
568
569 return send_urb_completion_message(callback, out, 0, 0, nullptr);
570
571fail:
572 Stream_Free(out, TRUE);
573 return ERROR_OUTOFMEMORY;
574}
575
576static UINT urb_select_configuration(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
577 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
578 int transferDir)
579{
580 MSUSB_CONFIG_DESCRIPTOR* MsConfig = nullptr;
581 UINT32 NumInterfaces = 0;
582 UINT32 usbd_status = 0;
583 BYTE ConfigurationDescriptorIsValid = 0;
584 URBDRC_PLUGIN* urbdrc = nullptr;
585 const BOOL noAck = (RequestField & 0x80000000U) != 0;
586 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
587
588 if (!callback || !s || !udevman || !pdev)
589 return ERROR_INVALID_PARAMETER;
590
591 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
592
593 if (!urbdrc)
594 return ERROR_INVALID_PARAMETER;
595
596 if (transferDir == 0)
597 {
598 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_configuration: unsupported transfer out");
599 return ERROR_INVALID_PARAMETER;
600 }
601
602 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
603 return ERROR_INVALID_DATA;
604
605 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
606 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
607 Stream_Seek(s, 3); /* Padding */
608 Stream_Read_UINT32(s, NumInterfaces);
609
611 if (ConfigurationDescriptorIsValid)
612 {
613 /* parser data for struct config */
614 MsConfig = msusb_msconfig_read(s, NumInterfaces);
615
616 if (!MsConfig)
617 return ERROR_INVALID_DATA;
618
619 /* select config */
620 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
621 if (lrc != 0)
622 {
623 msusb_msconfig_free(MsConfig);
624 MsConfig = nullptr;
625 return ERROR_INTERNAL_ERROR;
626 }
627
628 /* select all interface */
629 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
630 /* complete configuration setup */
631 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
632 {
633 msusb_msconfig_free(MsConfig);
634 MsConfig = nullptr;
635 }
636 }
637
638 if (noAck)
639 return CHANNEL_RC_OK;
640 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
641 usbd_status, MsConfig);
642}
643
644/* [MS-RDPEUSB[ 2.2.10.3 TS_URB_SELECT_INTERFACE_RESULT */
645static UINT urb_select_interface_result(GENERIC_CHANNEL_CALLBACK* callback, UINT32 RequestId,
646 UINT32 InterfaceId, UINT32 MessageId,
647 MSUSB_INTERFACE_DESCRIPTOR* MsInterface)
648{
649 WINPR_ASSERT(callback);
650 WINPR_ASSERT(MsInterface);
651
652 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
653 wStream* out =
654 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
655
656 if (!out)
657 return ERROR_OUTOFMEMORY;
658
659 const uint32_t size = 8U + interface_size;
660 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
661
662 if (!Stream_EnsureRemainingCapacity(out, 4))
663 goto fail;
664 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
665
666 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
667 goto fail;
668
669 if (!msusb_msinterface_write(MsInterface, out))
670 goto fail;
671
672 return send_urb_completion_message(callback, out, 0, 0, nullptr);
673
674fail:
675 Stream_Free(out, TRUE);
676
677 return ERROR_INTERNAL_ERROR;
678}
679
680static UINT urb_select_interface(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
681 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
682 int transferDir)
683{
684 const BOOL noAck = (RequestField & 0x80000000U) != 0;
685 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
686
687 if (!callback || !s || !udevman || !pdev)
688 return ERROR_INVALID_PARAMETER;
689
690 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
691
692 if (!urbdrc)
693 return ERROR_INVALID_PARAMETER;
694
695 if (transferDir == 0)
696 {
697 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_interface: not support transfer out");
698 return ERROR_INVALID_PARAMETER;
699 }
700
701 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
702 return ERROR_INVALID_DATA;
703
704 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
705 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
706 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = msusb_msinterface_read(s);
707
708 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
709 {
710 msusb_msinterface_free(MsInterface);
711 return ERROR_INVALID_DATA;
712 }
713
714 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
715 if (OutputBufferSize != 0)
716 {
717 WLog_Print(urbdrc->log, WLOG_ERROR,
718 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
719 "%" PRIu32,
720 OutputBufferSize);
721 msusb_msinterface_free(MsInterface);
722 return ERROR_INVALID_DATA;
723 }
724
725 const int lerr =
726 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
727 if (lerr != 0)
728 {
729 msusb_msinterface_free(MsInterface);
730 return ERROR_INTERNAL_ERROR;
731 }
732
733 /* replace device's MsInterface */
734 MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->get_MsConfig(pdev);
735 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
736 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
737 return ERROR_BAD_CONFIGURATION;
738
739 /* complete configuration setup */
740 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
741 return ERROR_BAD_CONFIGURATION;
742
743 if (noAck)
744 return CHANNEL_RC_OK;
745
746 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
747}
748
749static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
750 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
751 int transferDir, int External)
752{
753 UINT32 out_size = 0;
754 UINT32 InterfaceId = 0;
755 UINT32 EndpointAddress = 0;
756 UINT32 PipeHandle = 0;
757 UINT32 TransferFlags = 0;
758 UINT32 OutputBufferSize = 0;
759 UINT32 usbd_status = 0;
760 UINT32 Timeout = 0;
761 BYTE bmRequestType = 0;
762 BYTE Request = 0;
763 UINT16 Value = 0;
764 UINT16 Index = 0;
765 UINT16 length = 0;
766 BYTE* buffer = nullptr;
767 wStream* out = nullptr;
768 URBDRC_PLUGIN* urbdrc = nullptr;
769 const BOOL noAck = (RequestField & 0x80000000U) != 0;
770 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
771
772 if (!callback || !s || !udevman || !pdev)
773 return ERROR_INVALID_PARAMETER;
774
775 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
776
777 if (!urbdrc)
778 return ERROR_INVALID_PARAMETER;
779
780 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
781 return ERROR_INVALID_DATA;
782
783 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
784 Stream_Read_UINT32(s, PipeHandle);
785 Stream_Read_UINT32(s, TransferFlags);
786 EndpointAddress = (PipeHandle & 0x000000ff);
787 Timeout = 2000;
788
789 switch (External)
790 {
791 case URB_CONTROL_TRANSFER_EXTERNAL:
792 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
793 return ERROR_INVALID_DATA;
794
795 Stream_Read_UINT32(s, Timeout);
796 break;
797
798 case URB_CONTROL_TRANSFER_NONEXTERNAL:
799 break;
800 default:
801 break;
802 }
803
805 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
806 return ERROR_INVALID_DATA;
807
808 Stream_Read_UINT8(s, bmRequestType);
809 Stream_Read_UINT8(s, Request);
810 Stream_Read_UINT16(s, Value);
811 Stream_Read_UINT16(s, Index);
812 Stream_Read_UINT16(s, length);
813 Stream_Read_UINT32(s, OutputBufferSize);
814
815 if (length != OutputBufferSize)
816 {
817 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_control_transfer ERROR: buf != length");
818 return ERROR_INVALID_DATA;
819 }
820
821 out_size = 36 + OutputBufferSize;
822 out = Stream_New(nullptr, out_size);
823
824 if (!out)
825 return ERROR_OUTOFMEMORY;
826
827 Stream_Seek(out, 36);
829 buffer = Stream_Pointer(out);
830
831 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
832 {
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
834 {
835 Stream_Free(out, TRUE);
836 return ERROR_INVALID_DATA;
837 }
838 Stream_Copy(s, out, OutputBufferSize);
839 }
840
842 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
843 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
844 Timeout))
845 {
846 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
847 Stream_Free(out, TRUE);
848 return ERROR_INTERNAL_ERROR;
849 }
850
851 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
852 usbd_status, OutputBufferSize, transferDir);
853}
854
855static void urb_bulk_transfer_cb(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
856 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
857 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
858 WINPR_ATTR_UNUSED UINT32 StartFrame,
859 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
860 int transferDir)
861{
862 if (!pdev->isChannelClosed(pdev))
863 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
864 OutputBufferSize, transferDir);
865 else
866 Stream_Free(out, TRUE);
867}
868
869static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
870 wStream* s, UINT32 RequestField, UINT32 MessageId,
871 IUDEVMAN* udevman, int transferDir)
872{
873 UINT32 EndpointAddress = 0;
874 UINT32 PipeHandle = 0;
875 UINT32 TransferFlags = 0;
876 UINT32 OutputBufferSize = 0;
877 const BOOL noAck = (RequestField & 0x80000000U) != 0;
878 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
879
880 if (!pdev || !callback || !s || !udevman)
881 return ERROR_INVALID_PARAMETER;
882
883 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
884 return ERROR_INVALID_DATA;
885
886 Stream_Read_UINT32(s, PipeHandle);
887 Stream_Read_UINT32(s, TransferFlags);
888 Stream_Read_UINT32(s, OutputBufferSize);
889 EndpointAddress = (PipeHandle & 0x000000ff);
890
891 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
892 {
893 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
894 {
895 return ERROR_INVALID_DATA;
896 }
897 }
898
900 const int rc = pdev->bulk_or_interrupt_transfer(
901 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
902 OutputBufferSize,
903 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
904 urb_bulk_transfer_cb, 10000);
905
906 return (uint32_t)rc;
907}
908
909static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
910 GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
911 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
912 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
913 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
914 int transferDir)
915{
916 if (!noAck)
917 {
918 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
919 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
920 Stream_ResetPosition(out);
921
922 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
923 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
924 {
925 Stream_Free(out, TRUE);
926 return;
927 }
928
929 Stream_Write_UINT32(out, RequestId);
930 Stream_Write_UINT32(out, 20 + packetSize);
931 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
932 status))
933 {
934 Stream_Free(out, TRUE);
935 return;
936 }
937
938 Stream_Write_UINT32(out, StartFrame);
940 if (status == 0)
941 {
943 Stream_Write_UINT32(out, NumberOfPackets);
944 Stream_Write_UINT32(out, ErrorCount);
945 Stream_Seek(out, packetSize);
946 }
947 else
948 {
949 Stream_Write_UINT32(out, 0);
950 Stream_Write_UINT32(out, ErrorCount);
951 }
952
953 Stream_Write_UINT32(out, 0);
954 Stream_Write_UINT32(out, OutputBufferSize);
955 Stream_Seek(out, payloadSize);
956
957 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
958 if (rc != CHANNEL_RC_OK)
959 WLog_WARN(TAG, "stream_write_and_free failed with %" PRIu32, rc);
960 }
961}
962
963static UINT urb_isoch_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
964 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
965 int transferDir)
966{
967 int rc = 0;
968 UINT32 EndpointAddress = 0;
969 UINT32 PipeHandle = 0;
970 UINT32 TransferFlags = 0;
971 UINT32 StartFrame = 0;
972 UINT32 NumberOfPackets = 0;
973 UINT32 ErrorCount = 0;
974 UINT32 OutputBufferSize = 0;
975 BYTE* packetDescriptorData = nullptr;
976 const BOOL noAck = (RequestField & 0x80000000U) != 0;
977 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
978
979 if (!pdev || !callback || !udevman)
980 return ERROR_INVALID_PARAMETER;
981
982 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
983 return ERROR_INVALID_DATA;
984
985 Stream_Read_UINT32(s, PipeHandle);
986 EndpointAddress = (PipeHandle & 0x000000ff);
987 Stream_Read_UINT32(s, TransferFlags);
988 Stream_Read_UINT32(s, StartFrame);
989 Stream_Read_UINT32(s, NumberOfPackets);
990 Stream_Read_UINT32(s, ErrorCount);
992 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
993 return ERROR_INVALID_DATA;
994
995 packetDescriptorData = Stream_Pointer(s);
996 Stream_Seek(s, 12ULL * NumberOfPackets);
997
998 if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UINT32)))
999 return ERROR_INVALID_DATA;
1000 Stream_Read_UINT32(s, OutputBufferSize);
1001
1002 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1003 {
1004 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1005 return ERROR_INVALID_DATA;
1006 }
1007
1008 rc = pdev->isoch_transfer(
1009 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1010 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1011 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1012 urb_isoch_transfer_cb, 2000);
1013
1014 if (rc < 0)
1015 return ERROR_INTERNAL_ERROR;
1016 return (UINT)rc;
1017}
1018
1019static UINT urb_control_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1020 wStream* s, UINT32 RequestField, UINT32 MessageId,
1021 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1022{
1023 size_t out_size = 0;
1024 UINT32 InterfaceId = 0;
1025 UINT32 OutputBufferSize = 0;
1026 UINT32 usbd_status = 0;
1027 BYTE bmRequestType = 0;
1028 BYTE desc_index = 0;
1029 BYTE desc_type = 0;
1030 UINT16 langId = 0;
1031 wStream* out = nullptr;
1032 URBDRC_PLUGIN* urbdrc = nullptr;
1033 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1034 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1035
1036 if (!callback || !s || !udevman || !pdev)
1037 return ERROR_INVALID_PARAMETER;
1038
1039 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1040
1041 if (!urbdrc)
1042 return ERROR_INVALID_PARAMETER;
1043
1044 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1045 return ERROR_INVALID_DATA;
1046
1047 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1048 Stream_Read_UINT8(s, desc_index);
1049 Stream_Read_UINT8(s, desc_type);
1050 Stream_Read_UINT16(s, langId);
1051 Stream_Read_UINT32(s, OutputBufferSize);
1052 if (OutputBufferSize > UINT32_MAX - 36)
1053 return ERROR_INVALID_DATA;
1054 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1055 {
1056 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1057 return ERROR_INVALID_DATA;
1058 }
1059
1060 out_size = 36ULL + OutputBufferSize;
1061 out = Stream_New(nullptr, out_size);
1062
1063 if (!out)
1064 return ERROR_OUTOFMEMORY;
1065
1066 Stream_Seek(out, 36);
1067 bmRequestType = func_recipient;
1068
1069 switch (transferDir)
1070 {
1071 case USBD_TRANSFER_DIRECTION_IN:
1072 bmRequestType |= 0x80;
1073 break;
1074
1075 case USBD_TRANSFER_DIRECTION_OUT:
1076 bmRequestType |= 0x00;
1077 Stream_Copy(s, out, OutputBufferSize);
1078 Stream_Rewind(out, OutputBufferSize);
1079 break;
1080
1081 default:
1082 WLog_Print(urbdrc->log, WLOG_DEBUG, "get error transferDir");
1083 OutputBufferSize = 0;
1084 usbd_status = USBD_STATUS_STALL_PID;
1085 break;
1086 }
1087
1089 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1090 0x06, /* REQUEST_GET_DESCRIPTOR */
1091 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1092 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1093 {
1094 WLog_Print(urbdrc->log, WLOG_ERROR, "get_descriptor failed");
1095 Stream_Free(out, TRUE);
1096 return ERROR_INTERNAL_ERROR;
1097 }
1098
1099 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1100 usbd_status, OutputBufferSize, transferDir);
1101}
1102
1103static UINT urb_control_get_status_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1104 wStream* s, UINT32 RequestField, UINT32 MessageId,
1105 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1106{
1107 size_t out_size = 0;
1108 UINT32 InterfaceId = 0;
1109 UINT32 OutputBufferSize = 0;
1110 UINT32 usbd_status = 0;
1111 UINT16 Index = 0;
1112 BYTE bmRequestType = 0;
1113 wStream* out = nullptr;
1114 URBDRC_PLUGIN* urbdrc = nullptr;
1115 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1116 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1117
1118 if (!callback || !s || !udevman || !pdev)
1119 return ERROR_INVALID_PARAMETER;
1120
1121 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1122
1123 if (!urbdrc)
1124 return ERROR_INVALID_PARAMETER;
1125
1126 if (transferDir == 0)
1127 {
1128 WLog_Print(urbdrc->log, WLOG_DEBUG,
1129 "urb_control_get_status_request: transfer out not supported");
1130 return ERROR_INVALID_PARAMETER;
1131 }
1132
1133 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1134 return ERROR_INVALID_DATA;
1135
1136 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1137 Stream_Read_UINT16(s, Index);
1138 Stream_Seek(s, 2);
1139 Stream_Read_UINT32(s, OutputBufferSize);
1140 if (OutputBufferSize > UINT32_MAX - 36)
1141 return ERROR_INVALID_DATA;
1142 out_size = 36ULL + OutputBufferSize;
1143 out = Stream_New(nullptr, out_size);
1144
1145 if (!out)
1146 return ERROR_OUTOFMEMORY;
1147
1148 Stream_Seek(out, 36);
1149 bmRequestType = func_recipient | 0x80;
1150
1151 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00, /* REQUEST_GET_STATUS */
1152 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1153 1000))
1154 {
1155 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1156 Stream_Free(out, TRUE);
1157 return ERROR_INTERNAL_ERROR;
1158 }
1159
1160 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1161 usbd_status, OutputBufferSize, transferDir);
1162}
1163
1164static UINT urb_control_vendor_or_class_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1165 wStream* s, UINT32 RequestField, UINT32 MessageId,
1166 IUDEVMAN* udevman, BYTE func_type,
1167 BYTE func_recipient, int transferDir)
1168{
1169 UINT32 out_size = 0;
1170 UINT32 InterfaceId = 0;
1171 UINT32 TransferFlags = 0;
1172 UINT32 usbd_status = 0;
1173 UINT32 OutputBufferSize = 0;
1174 BYTE ReqTypeReservedBits = 0;
1175 BYTE Request = 0;
1176 BYTE bmRequestType = 0;
1177 UINT16 Value = 0;
1178 UINT16 Index = 0;
1179 wStream* out = nullptr;
1180 URBDRC_PLUGIN* urbdrc = nullptr;
1181 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1182 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1183
1184 if (!callback || !s || !udevman || !pdev)
1185 return ERROR_INVALID_PARAMETER;
1186
1187 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1188
1189 if (!urbdrc)
1190 return ERROR_INVALID_PARAMETER;
1191
1192 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1193 return ERROR_INVALID_DATA;
1194
1195 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1196 Stream_Read_UINT32(s, TransferFlags);
1197 Stream_Read_UINT8(s, ReqTypeReservedBits);
1198 Stream_Read_UINT8(s, Request);
1199 Stream_Read_UINT16(s, Value);
1200 Stream_Read_UINT16(s, Index);
1201 Stream_Seek_UINT16(s);
1202 Stream_Read_UINT32(s, OutputBufferSize);
1203 if (OutputBufferSize > UINT32_MAX - 36)
1204 return ERROR_INVALID_DATA;
1205
1206 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1207 {
1208 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1209 return ERROR_INVALID_DATA;
1210 }
1211
1212 out_size = 36ULL + OutputBufferSize;
1213 out = Stream_New(nullptr, out_size);
1214
1215 if (!out)
1216 return ERROR_OUTOFMEMORY;
1217
1218 Stream_Seek(out, 36);
1219
1221 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1222 {
1223 Stream_Copy(s, out, OutputBufferSize);
1224 Stream_Rewind(out, OutputBufferSize);
1225 }
1226
1228 bmRequestType = func_type | func_recipient;
1229
1230 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1231 bmRequestType |= 0x80;
1232
1233 WLog_Print(urbdrc->log, WLOG_DEBUG,
1234 "RequestId 0x%" PRIx32 " TransferFlags: 0x%" PRIx32 " ReqTypeReservedBits: 0x%" PRIx8
1235 " "
1236 "Request:0x%" PRIx8 " Value: 0x%" PRIx16 " Index: 0x%" PRIx16
1237 " OutputBufferSize: 0x%" PRIx32 " bmRequestType: 0x%" PRIx8,
1238 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1239 OutputBufferSize, bmRequestType);
1240
1241 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1242 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1243 {
1244 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1245 Stream_Free(out, TRUE);
1246 return ERROR_INTERNAL_ERROR;
1247 }
1248
1249 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1250 usbd_status, OutputBufferSize, transferDir);
1251}
1252
1253static UINT urb_os_feature_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1254 wStream* s, UINT32 RequestField, UINT32 MessageId,
1255 IUDEVMAN* udevman, int transferDir)
1256{
1257 size_t out_size = 0;
1258 UINT32 InterfaceId = 0;
1259 UINT32 OutputBufferSize = 0;
1260 UINT32 usbd_status = 0;
1261 BYTE Recipient = 0;
1262 BYTE InterfaceNumber = 0;
1263 BYTE Ms_PageIndex = 0;
1264 UINT16 Ms_featureDescIndex = 0;
1265 wStream* out = nullptr;
1266 int ret = 0;
1267 URBDRC_PLUGIN* urbdrc = nullptr;
1268 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1269 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1270
1271 if (!callback || !s || !udevman || !pdev)
1272 return ERROR_INVALID_PARAMETER;
1273
1274 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1275
1276 if (!urbdrc)
1277 return ERROR_INVALID_PARAMETER;
1278
1279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1280 return ERROR_INVALID_DATA;
1281
1282 /* 2.2.9.15 TS_URB_OS_FEATURE_DESCRIPTOR_REQUEST */
1283 Stream_Read_UINT8(s, Recipient);
1284 Recipient = (Recipient & 0x1f); /* Mask out Padding1 */
1285 Stream_Read_UINT8(s, InterfaceNumber);
1286 Stream_Read_UINT8(s, Ms_PageIndex);
1287 Stream_Read_UINT16(s, Ms_featureDescIndex);
1288 Stream_Seek(s, 3); /* Padding 2 */
1289 Stream_Read_UINT32(s, OutputBufferSize);
1290 if (OutputBufferSize > UINT32_MAX - 36)
1291 return ERROR_INVALID_DATA;
1292
1293 switch (transferDir)
1294 {
1295 case USBD_TRANSFER_DIRECTION_OUT:
1296 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1297 return ERROR_INVALID_DATA;
1298
1299 break;
1300
1301 default:
1302 break;
1303 }
1304
1305 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1306 out_size = 36ULL + OutputBufferSize;
1307 out = Stream_New(nullptr, out_size);
1308
1309 if (!out)
1310 return ERROR_OUTOFMEMORY;
1311
1312 Stream_Seek(out, 36);
1313
1314 switch (transferDir)
1315 {
1316 case USBD_TRANSFER_DIRECTION_OUT:
1317 Stream_Copy(s, out, OutputBufferSize);
1318 Stream_Rewind(out, OutputBufferSize);
1319 break;
1320
1321 case USBD_TRANSFER_DIRECTION_IN:
1322 break;
1323 default:
1324 break;
1325 }
1326
1327 WLog_Print(urbdrc->log, WLOG_DEBUG,
1328 "Ms descriptor arg: Recipient:0x%" PRIx8 ", "
1329 "InterfaceNumber:0x%" PRIx8 ", Ms_PageIndex:0x%" PRIx8 ", "
1330 "Ms_featureDescIndex:0x%" PRIx16 ", OutputBufferSize:0x%" PRIx32 "",
1331 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1333 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1334 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1335 &OutputBufferSize, Stream_Pointer(out), 1000);
1336
1337 if (ret < 0)
1338 WLog_Print(urbdrc->log, WLOG_DEBUG, "os_feature_descriptor_request: error num %d", ret);
1339
1340 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1341 usbd_status, OutputBufferSize, transferDir);
1342}
1343
1344static UINT urb_pipe_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1345 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1346 int transferDir, int action)
1347{
1348 UINT32 usbd_status = 0;
1349 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1350 int rc = 0;
1351 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1352 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1353
1354 if (!callback || !s || !udevman || !pdev)
1355 return ERROR_INVALID_PARAMETER;
1356
1357 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1358
1359 if (!urbdrc)
1360 return ERROR_INVALID_PARAMETER;
1361
1362 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1363 return ERROR_INVALID_DATA;
1364
1365 if (transferDir == 0)
1366 {
1367 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: not support transfer out");
1368 return ERROR_INVALID_PARAMETER;
1369 }
1370
1371 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1372 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1373 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1374 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1375
1376 if (OutputBufferSize != 0)
1377 {
1378 WLog_Print(urbdrc->log, WLOG_DEBUG,
1379 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32 " != 0",
1380 OutputBufferSize);
1381 return ERROR_BAD_CONFIGURATION;
1382 }
1383
1384 switch (action)
1385 {
1386 case PIPE_CANCEL:
1387 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1388 PIPE_CANCEL);
1389
1390 if (rc < 0)
1391 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE SET HALT: error %u", ret);
1392 else
1393 ret = USBD_STATUS_SUCCESS;
1394
1395 break;
1396
1397 case PIPE_RESET:
1398 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: PIPE_RESET ep 0x%" PRIx32 "",
1399 EndpointAddress);
1400 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1401 PIPE_RESET);
1402
1403 if (rc < 0)
1404 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE RESET: error %u", ret);
1405 else
1406 ret = USBD_STATUS_SUCCESS;
1407
1408 break;
1409
1410 default:
1411 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request action: %d not supported",
1412 action);
1413 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1414 break;
1415 }
1416
1419 wStream* out = Stream_New(nullptr, 36);
1420
1421 if (!out)
1422 return ERROR_OUTOFMEMORY;
1423
1424 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1425 0, transferDir);
1426}
1427/* [MS-RDPEUSB] 2.2.10.4 TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT */
1428static UINT urb_send_current_frame_number_result(GENERIC_CHANNEL_CALLBACK* callback,
1429 UINT32 RequestId, UINT32 MessageId,
1430 UINT32 CompletionId, UINT32 FrameNumber)
1431{
1432 WINPR_ASSERT(callback);
1433
1434 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1435 wStream* out =
1436 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1437
1438 if (!out)
1439 return ERROR_OUTOFMEMORY;
1440
1441 if (!Stream_EnsureRemainingCapacity(out, 4))
1442 goto fail;
1443 Stream_Write_UINT32(out, 12);
1444 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1445 goto fail;
1446 Stream_Write_UINT32(out, FrameNumber);
1447 return send_urb_completion_message(callback, out, 0, 0, nullptr);
1448
1449fail:
1450 Stream_Free(out, TRUE);
1451 return ERROR_OUTOFMEMORY;
1452}
1453
1454static UINT urb_get_current_frame_number(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1455 wStream* s, UINT32 RequestField, UINT32 MessageId,
1456 IUDEVMAN* udevman, int transferDir)
1457{
1458 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1459 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1460
1461 if (!callback || !s || !udevman || !pdev)
1462 return ERROR_INVALID_PARAMETER;
1463
1464 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1465
1466 if (!urbdrc)
1467 return ERROR_INVALID_PARAMETER;
1468
1469 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1470 return ERROR_INVALID_DATA;
1471
1472 if (transferDir == 0)
1473 {
1474 WLog_Print(urbdrc->log, WLOG_DEBUG,
1475 "urb_get_current_frame_number: not support transfer out");
1476 return ERROR_INVALID_PARAMETER;
1477 }
1478
1479 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1480 if (OutputBufferSize != 0)
1481 {
1482 WLog_Print(urbdrc->log, WLOG_WARN, "OutputBufferSize=%" PRIu32 ", expected 0",
1483 OutputBufferSize);
1484 }
1486 const UINT32 dummy_frames = GetTickCount();
1487 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1488
1489 if (noAck)
1490 return CHANNEL_RC_OK;
1491
1492 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1493 dummy_frames);
1494}
1495
1496/* Unused function for current server */
1497static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1498 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1499 UINT32 RequestField, UINT32 MessageId,
1500 IUDEVMAN* udevman, int transferDir)
1501{
1502 size_t out_size = 0;
1503 UINT32 InterfaceId = 0;
1504 UINT32 OutputBufferSize = 0;
1505 UINT32 usbd_status = 0;
1506 wStream* out = nullptr;
1507 URBDRC_PLUGIN* urbdrc = nullptr;
1508 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1509 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1510
1511 if (!callback || !s || !udevman || !pdev)
1512 return ERROR_INVALID_PARAMETER;
1513
1514 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1515
1516 if (!urbdrc)
1517 return ERROR_INVALID_PARAMETER;
1518
1519 if (transferDir == 0)
1520 {
1521 WLog_Print(urbdrc->log, WLOG_DEBUG,
1522 "urb_control_get_configuration_request:"
1523 " not support transfer out");
1524 return ERROR_INVALID_PARAMETER;
1525 }
1526
1527 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1528 return ERROR_INVALID_DATA;
1529
1530 Stream_Read_UINT32(s, OutputBufferSize);
1531 if (OutputBufferSize > UINT32_MAX - 36)
1532 return ERROR_INVALID_DATA;
1533 out_size = 36ULL + OutputBufferSize;
1534 out = Stream_New(nullptr, out_size);
1535
1536 if (!out)
1537 return ERROR_OUTOFMEMORY;
1538
1539 Stream_Seek(out, 36);
1540 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1541
1542 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1543 0x08, /* REQUEST_GET_CONFIGURATION */
1544 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1545 {
1546 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1547 Stream_Free(out, TRUE);
1548 return ERROR_INTERNAL_ERROR;
1549 }
1550
1551 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1552 usbd_status, OutputBufferSize, transferDir);
1553}
1554
1555/* Unused function for current server */
1556static UINT urb_control_get_interface_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1557 wStream* s, UINT32 RequestField, UINT32 MessageId,
1558 IUDEVMAN* udevman, int transferDir)
1559{
1560 size_t out_size = 0;
1561 UINT32 InterfaceId = 0;
1562 UINT32 OutputBufferSize = 0;
1563 UINT32 usbd_status = 0;
1564 UINT16 InterfaceNr = 0;
1565 wStream* out = nullptr;
1566 URBDRC_PLUGIN* urbdrc = nullptr;
1567 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1568 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1569
1570 if (!callback || !s || !udevman || !pdev)
1571 return ERROR_INVALID_PARAMETER;
1572
1573 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1574
1575 if (!urbdrc)
1576 return ERROR_INVALID_PARAMETER;
1577
1578 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1579 return ERROR_INVALID_DATA;
1580
1581 if (transferDir == 0)
1582 {
1583 WLog_Print(urbdrc->log, WLOG_DEBUG,
1584 "urb_control_get_interface_request: not support transfer out");
1585 return ERROR_INVALID_PARAMETER;
1586 }
1587
1588 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1589 Stream_Read_UINT16(s, InterfaceNr);
1590 Stream_Seek(s, 2);
1591 Stream_Read_UINT32(s, OutputBufferSize);
1592 if (OutputBufferSize > UINT32_MAX - 36)
1593 return ERROR_INVALID_DATA;
1594 out_size = 36ULL + OutputBufferSize;
1595 out = Stream_New(nullptr, out_size);
1596
1597 if (!out)
1598 return ERROR_OUTOFMEMORY;
1599
1600 Stream_Seek(out, 36);
1601
1602 if (!pdev->control_transfer(
1603 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */
1604 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1605 {
1606 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1607 Stream_Free(out, TRUE);
1608 return ERROR_INTERNAL_ERROR;
1609 }
1610
1611 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1612 usbd_status, OutputBufferSize, transferDir);
1613}
1614
1615static UINT urb_control_feature_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1616 wStream* s, UINT32 RequestField, UINT32 MessageId,
1617 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1618 int transferDir)
1619{
1620 UINT32 InterfaceId = 0;
1621 UINT32 OutputBufferSize = 0;
1622 UINT32 usbd_status = 0;
1623 UINT16 FeatureSelector = 0;
1624 UINT16 Index = 0;
1625 BYTE bmRequestType = 0;
1626 BYTE bmRequest = 0;
1627 wStream* out = nullptr;
1628 URBDRC_PLUGIN* urbdrc = nullptr;
1629 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1630 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1631
1632 if (!callback || !s || !udevman || !pdev)
1633 return ERROR_INVALID_PARAMETER;
1634
1635 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1636
1637 if (!urbdrc)
1638 return ERROR_INVALID_PARAMETER;
1639
1640 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1641 return ERROR_INVALID_DATA;
1642
1643 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1644 Stream_Read_UINT16(s, FeatureSelector);
1645 Stream_Read_UINT16(s, Index);
1646 Stream_Read_UINT32(s, OutputBufferSize);
1647 if (OutputBufferSize > UINT32_MAX - 36)
1648 return ERROR_INVALID_DATA;
1649 switch (transferDir)
1650 {
1651 case USBD_TRANSFER_DIRECTION_OUT:
1652 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1653 return ERROR_INVALID_DATA;
1654
1655 break;
1656
1657 default:
1658 break;
1659 }
1660
1661 out = Stream_New(nullptr, 36ULL + OutputBufferSize);
1662
1663 if (!out)
1664 return ERROR_OUTOFMEMORY;
1665
1666 Stream_Seek(out, 36);
1667 bmRequestType = func_recipient;
1668
1669 switch (transferDir)
1670 {
1671 case USBD_TRANSFER_DIRECTION_OUT:
1672 WLog_Print(urbdrc->log, WLOG_ERROR,
1673 "Function urb_control_feature_request: OUT Unchecked");
1674 Stream_Copy(s, out, OutputBufferSize);
1675 Stream_Rewind(out, OutputBufferSize);
1676 bmRequestType |= 0x00;
1677 break;
1678
1679 case USBD_TRANSFER_DIRECTION_IN:
1680 bmRequestType |= 0x80;
1681 break;
1682 default:
1683 break;
1684 }
1685
1686 switch (command)
1687 {
1688 case URB_SET_FEATURE:
1689 bmRequest = 0x03; /* REQUEST_SET_FEATURE */
1690 break;
1691
1692 case URB_CLEAR_FEATURE:
1693 bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */
1694 break;
1695
1696 default:
1697 WLog_Print(urbdrc->log, WLOG_ERROR,
1698 "urb_control_feature_request: Error Command 0x%02" PRIx8 "", command);
1699 Stream_Free(out, TRUE);
1700 return ERROR_INTERNAL_ERROR;
1701 }
1702
1703 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1704 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1705 {
1706 WLog_Print(urbdrc->log, WLOG_DEBUG, "feature control transfer failed");
1707 Stream_Free(out, TRUE);
1708 return ERROR_INTERNAL_ERROR;
1709 }
1710
1711 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1712 usbd_status, OutputBufferSize, transferDir);
1713}
1714
1715static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1716 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1717 int transferDir)
1718{
1719 UINT32 CbTsUrb = 0;
1720 UINT16 Size = 0;
1721 UINT16 URB_Function = 0;
1722 UINT32 RequestId = 0;
1723 UINT error = ERROR_INTERNAL_ERROR;
1724 URBDRC_PLUGIN* urbdrc = nullptr;
1725
1726 if (!callback || !s || !udevman || !pdev)
1727 return ERROR_INVALID_PARAMETER;
1728
1729 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1730
1731 if (!urbdrc)
1732 return ERROR_INVALID_PARAMETER;
1733
1734 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1735 return ERROR_INVALID_DATA;
1736
1737 Stream_Read_UINT32(s, CbTsUrb);
1738 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1739 return ERROR_INVALID_DATA;
1740 Stream_Read_UINT16(s, Size);
1741 if (Size != CbTsUrb)
1742 {
1743 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1744 ? "2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1745 : "2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1746 WLog_ERR(TAG,
1747 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1748 " != %s::CbTsUrb 0x%08" PRIx32,
1749 Size, section, CbTsUrb);
1750 return ERROR_INVALID_DATA;
1751 }
1752 Stream_Read_UINT16(s, URB_Function);
1753 Stream_Read_UINT32(s, RequestId);
1754 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB %s[%" PRIu16 "]", urb_function_string(URB_Function),
1755 URB_Function);
1756
1757 switch (URB_Function)
1758 {
1759 case TS_URB_SELECT_CONFIGURATION:
1760 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1761 transferDir);
1762 break;
1763
1764 case TS_URB_SELECT_INTERFACE:
1765 error =
1766 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1767 break;
1768
1769 case TS_URB_PIPE_REQUEST:
1770 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1771 PIPE_CANCEL);
1772 break;
1773
1774 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1778 break;
1779
1780 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1784 break;
1785
1786 case TS_URB_GET_FRAME_LENGTH:
1790 break;
1791
1792 case TS_URB_SET_FRAME_LENGTH:
1796 break;
1797
1798 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1799 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1800 transferDir);
1801 break;
1802
1803 case TS_URB_CONTROL_TRANSFER:
1804 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1805 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1806 break;
1807
1808 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1809 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1810 transferDir);
1811 break;
1812
1813 case TS_URB_ISOCH_TRANSFER:
1814 error =
1815 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1816 break;
1817
1818 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1819 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1820 0x00, transferDir);
1821 break;
1822
1823 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1824 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1825 0x00, transferDir);
1826 break;
1827
1828 case TS_URB_SET_FEATURE_TO_DEVICE:
1829 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1830 0x00, URB_SET_FEATURE, transferDir);
1831 break;
1832
1833 case TS_URB_SET_FEATURE_TO_INTERFACE:
1834 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1835 0x01, URB_SET_FEATURE, transferDir);
1836 break;
1837
1838 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x02, URB_SET_FEATURE, transferDir);
1841 break;
1842
1843 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x00, URB_CLEAR_FEATURE, transferDir);
1846 break;
1847
1848 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1849 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1850 0x01, URB_CLEAR_FEATURE, transferDir);
1851 break;
1852
1853 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1854 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 0x02, URB_CLEAR_FEATURE, transferDir);
1856 break;
1857
1858 case TS_URB_GET_STATUS_FROM_DEVICE:
1859 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1860 0x00, transferDir);
1861 break;
1862
1863 case TS_URB_GET_STATUS_FROM_INTERFACE:
1864 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1865 0x01, transferDir);
1866 break;
1867
1868 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1870 0x02, transferDir);
1871 break;
1872
1873 case TS_URB_RESERVED_0X0016:
1874 break;
1875
1876 case TS_URB_VENDOR_DEVICE:
1877 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1878 udevman, (0x02u << 5), /* vendor type */
1879 0x00, transferDir);
1880 break;
1881
1882 case TS_URB_VENDOR_INTERFACE:
1883 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1884 udevman, (0x02u << 5), /* vendor type */
1885 0x01, transferDir);
1886 break;
1887
1888 case TS_URB_VENDOR_ENDPOINT:
1889 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1890 udevman, (0x02u << 5), /* vendor type */
1891 0x02, transferDir);
1892 break;
1893
1894 case TS_URB_CLASS_DEVICE:
1895 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1896 udevman, (0x01u << 5), /* class type */
1897 0x00, transferDir);
1898 break;
1899
1900 case TS_URB_CLASS_INTERFACE:
1901 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1902 udevman, (0x01u << 5), /* class type */
1903 0x01, transferDir);
1904 break;
1905
1906 case TS_URB_CLASS_ENDPOINT:
1907 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1908 udevman, (0x01u << 5), /* class type */
1909 0x02, transferDir);
1910 break;
1911
1912 case TS_URB_RESERVE_0X001D:
1913 break;
1914
1915 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1916 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1917 PIPE_RESET);
1918 break;
1919
1920 case TS_URB_CLASS_OTHER:
1921 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1922 udevman, (0x01u << 5), /* class type */
1923 0x03, transferDir);
1924 break;
1925
1926 case TS_URB_VENDOR_OTHER:
1927 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1928 udevman, (0x02u << 5), /* vendor type */
1929 0x03, transferDir);
1930 break;
1931
1932 case TS_URB_GET_STATUS_FROM_OTHER:
1933 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1934 0x03, transferDir);
1935 break;
1936
1937 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1938 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1939 0x03, URB_CLEAR_FEATURE, transferDir);
1940 break;
1941
1942 case TS_URB_SET_FEATURE_TO_OTHER:
1943 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1944 0x03, URB_SET_FEATURE, transferDir);
1945 break;
1946
1947 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1948 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1949 0x02, transferDir);
1950 break;
1951
1952 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1953 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1954 0x02, transferDir);
1955 break;
1956
1957 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1958 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1959 udevman, transferDir);
1960 break;
1961
1962 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1963 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1964 udevman, transferDir);
1965 break;
1966
1967 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1968 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1969 0x01, transferDir);
1970 break;
1971
1972 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1973 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1974 0x01, transferDir);
1975 break;
1976
1977 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1978 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1979 udevman, transferDir);
1980 break;
1981
1982 case TS_URB_RESERVE_0X002B:
1983 case TS_URB_RESERVE_0X002C:
1984 case TS_URB_RESERVE_0X002D:
1985 case TS_URB_RESERVE_0X002E:
1986 case TS_URB_RESERVE_0X002F:
1987 break;
1988
1990 case TS_URB_SYNC_RESET_PIPE:
1991 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1992 PIPE_RESET);
1993 break;
1994
1995 case TS_URB_SYNC_CLEAR_STALL:
1996 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1997 PIPE_RESET);
1998 break;
1999
2000 case TS_URB_CONTROL_TRANSFER_EX:
2001 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
2002 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
2003 break;
2004
2005 default:
2006 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB_Func: %" PRIx16 " is not found!",
2007 URB_Function);
2008 break;
2009 }
2010
2011 if (error)
2012 {
2013 WLog_Print(urbdrc->log, WLOG_WARN,
2014 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2015 urb_function_string(URB_Function), URB_Function, error);
2016 }
2017
2018 return error;
2019}
2020
2021UINT urbdrc_process_udev_data_transfer(GENERIC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
2022 IUDEVMAN* udevman, wStream* data)
2023{
2024 UINT32 InterfaceId = 0;
2025 UINT32 MessageId = 0;
2026 UINT32 FunctionId = 0;
2027 IUDEVICE* pdev = nullptr;
2028 UINT error = ERROR_INTERNAL_ERROR;
2029
2030 if (!urbdrc || !data || !callback || !udevman)
2031 goto fail;
2032
2033 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2034 goto fail;
2035
2036 Stream_Rewind_UINT32(data);
2037
2038 Stream_Read_UINT32(data, InterfaceId);
2039 Stream_Read_UINT32(data, MessageId);
2040 Stream_Read_UINT32(data, FunctionId);
2041
2042 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2043
2044 /* Device does not exist, ignore this request. */
2045 if (pdev == nullptr)
2046 {
2047 error = ERROR_SUCCESS;
2048 goto fail;
2049 }
2050
2051 /* Device has been removed, ignore this request. */
2052 if (pdev->isChannelClosed(pdev))
2053 {
2054 error = ERROR_SUCCESS;
2055 goto fail;
2056 }
2057
2058 /* USB kernel driver detach!! */
2059 if (!pdev->detach_kernel_driver(pdev))
2060 {
2061 error = ERROR_SUCCESS;
2062 goto fail;
2063 }
2064
2065 switch (FunctionId)
2066 {
2067 case CANCEL_REQUEST:
2068 error = urbdrc_process_cancel_request(pdev, data, udevman);
2069 break;
2070
2071 case REGISTER_REQUEST_CALLBACK:
2072 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2073 break;
2074
2075 case IO_CONTROL:
2076 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2077 break;
2078
2079 case INTERNAL_IO_CONTROL:
2080 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2081 break;
2082
2083 case QUERY_DEVICE_TEXT:
2084 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2085 break;
2086
2087 case TRANSFER_IN_REQUEST:
2088 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2089 USBD_TRANSFER_DIRECTION_IN);
2090 break;
2091
2092 case TRANSFER_OUT_REQUEST:
2093 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2094 USBD_TRANSFER_DIRECTION_OUT);
2095 break;
2096
2097 case RETRACT_DEVICE:
2098 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2099 break;
2100
2101 default:
2102 WLog_Print(urbdrc->log, WLOG_WARN,
2103 "urbdrc_process_udev_data_transfer:"
2104 " unknown FunctionId 0x%" PRIX32 "",
2105 FunctionId);
2106 break;
2107 }
2108
2109fail:
2110 if (error)
2111 {
2112 WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
2113 }
2114
2115 return error;
2116}