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