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 // Currently unused, so just skip the data
705 // const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
706 Stream_Seek_UINT32(s);
707 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = msusb_msinterface_read(s);
708
709 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
710 {
711 msusb_msinterface_free(MsInterface);
712 return ERROR_INVALID_DATA;
713 }
714
715 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
716 if (OutputBufferSize != 0)
717 {
718 WLog_Print(urbdrc->log, WLOG_ERROR,
719 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
720 "%" PRIu32,
721 OutputBufferSize);
722 msusb_msinterface_free(MsInterface);
723 return ERROR_INVALID_DATA;
724 }
725
726 const int lerr =
727 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
728 if (lerr != 0)
729 {
730 msusb_msinterface_free(MsInterface);
731 return ERROR_INTERNAL_ERROR;
732 }
733
734 /* replace device's MsInterface */
735 MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->get_MsConfig(pdev);
736 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
737 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
738 {
739 msusb_msinterface_free(MsInterface);
740 return ERROR_BAD_CONFIGURATION;
741 }
742
743 /* complete configuration setup */
744 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
745 return ERROR_BAD_CONFIGURATION;
746
747 if (noAck)
748 return CHANNEL_RC_OK;
749
750 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
751}
752
753static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
754 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
755 int transferDir, int External)
756{
757 UINT32 out_size = 0;
758 UINT32 InterfaceId = 0;
759 UINT32 EndpointAddress = 0;
760 UINT32 PipeHandle = 0;
761 UINT32 TransferFlags = 0;
762 UINT32 OutputBufferSize = 0;
763 UINT32 usbd_status = 0;
764 UINT32 Timeout = 0;
765 BYTE bmRequestType = 0;
766 BYTE Request = 0;
767 UINT16 Value = 0;
768 UINT16 Index = 0;
769 UINT16 length = 0;
770 BYTE* buffer = nullptr;
771 wStream* out = nullptr;
772 URBDRC_PLUGIN* urbdrc = nullptr;
773 const BOOL noAck = (RequestField & 0x80000000U) != 0;
774 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
775
776 if (!callback || !s || !udevman || !pdev)
777 return ERROR_INVALID_PARAMETER;
778
779 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
780
781 if (!urbdrc)
782 return ERROR_INVALID_PARAMETER;
783
784 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
785 return ERROR_INVALID_DATA;
786
787 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
788 Stream_Read_UINT32(s, PipeHandle);
789 Stream_Read_UINT32(s, TransferFlags);
790 EndpointAddress = (PipeHandle & 0x000000ff);
791 Timeout = 2000;
792
793 switch (External)
794 {
795 case URB_CONTROL_TRANSFER_EXTERNAL:
796 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
797 return ERROR_INVALID_DATA;
798
799 Stream_Read_UINT32(s, Timeout);
800 break;
801
802 case URB_CONTROL_TRANSFER_NONEXTERNAL:
803 break;
804 default:
805 break;
806 }
807
809 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
810 return ERROR_INVALID_DATA;
811
812 Stream_Read_UINT8(s, bmRequestType);
813 Stream_Read_UINT8(s, Request);
814 Stream_Read_UINT16(s, Value);
815 Stream_Read_UINT16(s, Index);
816 Stream_Read_UINT16(s, length);
817 Stream_Read_UINT32(s, OutputBufferSize);
818
819 if (length != OutputBufferSize)
820 {
821 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_control_transfer ERROR: buf != length");
822 return ERROR_INVALID_DATA;
823 }
824
825 out_size = 36 + OutputBufferSize;
826 out = Stream_New(nullptr, out_size);
827
828 if (!out)
829 return ERROR_OUTOFMEMORY;
830
831 Stream_Seek(out, 36);
833 buffer = Stream_Pointer(out);
834
835 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
836 {
837 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
838 {
839 Stream_Free(out, TRUE);
840 return ERROR_INVALID_DATA;
841 }
842 Stream_Copy(s, out, OutputBufferSize);
843 }
844
846 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
847 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
848 Timeout))
849 {
850 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
851 Stream_Free(out, TRUE);
852 return ERROR_INTERNAL_ERROR;
853 }
854
855 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
856 usbd_status, OutputBufferSize, transferDir);
857}
858
859static void urb_bulk_transfer_cb(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
860 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
861 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
862 WINPR_ATTR_UNUSED UINT32 StartFrame,
863 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
864 int transferDir)
865{
866 if (!pdev->isChannelClosed(pdev))
867 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
868 OutputBufferSize, transferDir);
869 else
870 Stream_Free(out, TRUE);
871}
872
873static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
874 wStream* s, UINT32 RequestField, UINT32 MessageId,
875 IUDEVMAN* udevman, int transferDir)
876{
877 UINT32 EndpointAddress = 0;
878 UINT32 PipeHandle = 0;
879 UINT32 TransferFlags = 0;
880 UINT32 OutputBufferSize = 0;
881 const BOOL noAck = (RequestField & 0x80000000U) != 0;
882 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
883
884 if (!pdev || !callback || !s || !udevman)
885 return ERROR_INVALID_PARAMETER;
886
887 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
888 return ERROR_INVALID_DATA;
889
890 Stream_Read_UINT32(s, PipeHandle);
891 Stream_Read_UINT32(s, TransferFlags);
892 Stream_Read_UINT32(s, OutputBufferSize);
893 EndpointAddress = (PipeHandle & 0x000000ff);
894
895 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
896 {
897 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
898 {
899 return ERROR_INVALID_DATA;
900 }
901 }
902
904 const int rc = pdev->bulk_or_interrupt_transfer(
905 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
906 OutputBufferSize,
907 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
908 urb_bulk_transfer_cb, 10000);
909
910 return (uint32_t)rc;
911}
912
913static void urb_isoch_transfer_cb(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
914 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
915 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
916 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
917 int transferDir)
918{
919 /* The channel (and with it the callback) is gone, nobody to report to. */
920 if (pdev->isChannelClosed(pdev))
921 {
922 Stream_Free(out, TRUE);
923 return;
924 }
925
926 if (!noAck)
927 {
928 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
929 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
930 Stream_ResetPosition(out);
931
932 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
933 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
934 {
935 Stream_Free(out, TRUE);
936 return;
937 }
938
939 Stream_Write_UINT32(out, RequestId);
940 Stream_Write_UINT32(out, 20 + packetSize);
941 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
942 status))
943 {
944 Stream_Free(out, TRUE);
945 return;
946 }
947
948 Stream_Write_UINT32(out, StartFrame);
950 if (status == 0)
951 {
953 Stream_Write_UINT32(out, NumberOfPackets);
954 Stream_Write_UINT32(out, ErrorCount);
955 Stream_Seek(out, packetSize);
956 }
957 else
958 {
959 Stream_Write_UINT32(out, 0);
960 Stream_Write_UINT32(out, ErrorCount);
961 }
962
963 Stream_Write_UINT32(out, 0);
964 Stream_Write_UINT32(out, OutputBufferSize);
965 Stream_Seek(out, payloadSize);
966
967 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
968 if (rc != CHANNEL_RC_OK)
969 WLog_WARN(TAG, "stream_write_and_free failed with %" PRIu32, rc);
970 }
971}
972
973static UINT urb_isoch_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
974 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
975 int transferDir)
976{
977 int rc = 0;
978 UINT32 EndpointAddress = 0;
979 UINT32 PipeHandle = 0;
980 UINT32 TransferFlags = 0;
981 UINT32 StartFrame = 0;
982 UINT32 NumberOfPackets = 0;
983 UINT32 ErrorCount = 0;
984 UINT32 OutputBufferSize = 0;
985 BYTE* packetDescriptorData = nullptr;
986 const BOOL noAck = (RequestField & 0x80000000U) != 0;
987 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
988
989 if (!pdev || !callback || !udevman)
990 return ERROR_INVALID_PARAMETER;
991
992 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
993 return ERROR_INVALID_DATA;
994
995 Stream_Read_UINT32(s, PipeHandle);
996 EndpointAddress = (PipeHandle & 0x000000ff);
997 Stream_Read_UINT32(s, TransferFlags);
998 Stream_Read_UINT32(s, StartFrame);
999 Stream_Read_UINT32(s, NumberOfPackets);
1000 Stream_Read_UINT32(s, ErrorCount);
1002 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
1003 return ERROR_INVALID_DATA;
1004
1005 packetDescriptorData = Stream_Pointer(s);
1006 Stream_Seek(s, 12ULL * NumberOfPackets);
1007
1008 if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UINT32)))
1009 return ERROR_INVALID_DATA;
1010 Stream_Read_UINT32(s, OutputBufferSize);
1011
1012 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1013 {
1014 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1015 return ERROR_INVALID_DATA;
1016 }
1017
1018 rc = pdev->isoch_transfer(
1019 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1020 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1021 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1022 urb_isoch_transfer_cb, 2000);
1023
1024 if (rc < 0)
1025 return ERROR_INTERNAL_ERROR;
1026 return (UINT)rc;
1027}
1028
1029static UINT urb_control_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1030 wStream* s, UINT32 RequestField, UINT32 MessageId,
1031 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1032{
1033 size_t out_size = 0;
1034 UINT32 InterfaceId = 0;
1035 UINT32 OutputBufferSize = 0;
1036 UINT32 usbd_status = 0;
1037 BYTE bmRequestType = 0;
1038 BYTE desc_index = 0;
1039 BYTE desc_type = 0;
1040 UINT16 langId = 0;
1041 wStream* out = nullptr;
1042 URBDRC_PLUGIN* urbdrc = nullptr;
1043 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1044 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1045
1046 if (!callback || !s || !udevman || !pdev)
1047 return ERROR_INVALID_PARAMETER;
1048
1049 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1050
1051 if (!urbdrc)
1052 return ERROR_INVALID_PARAMETER;
1053
1054 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1055 return ERROR_INVALID_DATA;
1056
1057 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1058 Stream_Read_UINT8(s, desc_index);
1059 Stream_Read_UINT8(s, desc_type);
1060 Stream_Read_UINT16(s, langId);
1061 Stream_Read_UINT32(s, OutputBufferSize);
1062 if (OutputBufferSize > UINT32_MAX - 36)
1063 return ERROR_INVALID_DATA;
1064 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1065 {
1066 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1067 return ERROR_INVALID_DATA;
1068 }
1069
1070 out_size = 36ULL + OutputBufferSize;
1071 out = Stream_New(nullptr, out_size);
1072
1073 if (!out)
1074 return ERROR_OUTOFMEMORY;
1075
1076 Stream_Seek(out, 36);
1077 bmRequestType = func_recipient;
1078
1079 switch (transferDir)
1080 {
1081 case USBD_TRANSFER_DIRECTION_IN:
1082 bmRequestType |= 0x80;
1083 break;
1084
1085 case USBD_TRANSFER_DIRECTION_OUT:
1086 bmRequestType |= 0x00;
1087 Stream_Copy(s, out, OutputBufferSize);
1088 Stream_Rewind(out, OutputBufferSize);
1089 break;
1090
1091 default:
1092 WLog_Print(urbdrc->log, WLOG_DEBUG, "get error transferDir");
1093 OutputBufferSize = 0;
1094 usbd_status = USBD_STATUS_STALL_PID;
1095 break;
1096 }
1097
1099 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1100 0x06, /* REQUEST_GET_DESCRIPTOR */
1101 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1102 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1103 {
1104 WLog_Print(urbdrc->log, WLOG_ERROR, "get_descriptor failed");
1105 Stream_Free(out, TRUE);
1106 return ERROR_INTERNAL_ERROR;
1107 }
1108
1109 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1110 usbd_status, OutputBufferSize, transferDir);
1111}
1112
1113static UINT urb_control_get_status_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1114 wStream* s, UINT32 RequestField, UINT32 MessageId,
1115 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1116{
1117 size_t out_size = 0;
1118 UINT32 InterfaceId = 0;
1119 UINT32 OutputBufferSize = 0;
1120 UINT32 usbd_status = 0;
1121 UINT16 Index = 0;
1122 BYTE bmRequestType = 0;
1123 wStream* out = nullptr;
1124 URBDRC_PLUGIN* urbdrc = nullptr;
1125 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1126 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1127
1128 if (!callback || !s || !udevman || !pdev)
1129 return ERROR_INVALID_PARAMETER;
1130
1131 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1132
1133 if (!urbdrc)
1134 return ERROR_INVALID_PARAMETER;
1135
1136 if (transferDir == 0)
1137 {
1138 WLog_Print(urbdrc->log, WLOG_DEBUG,
1139 "urb_control_get_status_request: transfer out not supported");
1140 return ERROR_INVALID_PARAMETER;
1141 }
1142
1143 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1144 return ERROR_INVALID_DATA;
1145
1146 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1147 Stream_Read_UINT16(s, Index);
1148 Stream_Seek(s, 2);
1149 Stream_Read_UINT32(s, OutputBufferSize);
1150 if (OutputBufferSize > UINT32_MAX - 36)
1151 return ERROR_INVALID_DATA;
1152 out_size = 36ULL + OutputBufferSize;
1153 out = Stream_New(nullptr, out_size);
1154
1155 if (!out)
1156 return ERROR_OUTOFMEMORY;
1157
1158 Stream_Seek(out, 36);
1159 bmRequestType = func_recipient | 0x80;
1160
1161 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00, /* REQUEST_GET_STATUS */
1162 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1163 1000))
1164 {
1165 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1166 Stream_Free(out, TRUE);
1167 return ERROR_INTERNAL_ERROR;
1168 }
1169
1170 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1171 usbd_status, OutputBufferSize, transferDir);
1172}
1173
1174static UINT urb_control_vendor_or_class_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1175 wStream* s, UINT32 RequestField, UINT32 MessageId,
1176 IUDEVMAN* udevman, BYTE func_type,
1177 BYTE func_recipient, int transferDir)
1178{
1179 UINT32 out_size = 0;
1180 UINT32 InterfaceId = 0;
1181 UINT32 TransferFlags = 0;
1182 UINT32 usbd_status = 0;
1183 UINT32 OutputBufferSize = 0;
1184 BYTE ReqTypeReservedBits = 0;
1185 BYTE Request = 0;
1186 BYTE bmRequestType = 0;
1187 UINT16 Value = 0;
1188 UINT16 Index = 0;
1189 wStream* out = nullptr;
1190 URBDRC_PLUGIN* urbdrc = nullptr;
1191 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1192 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1193
1194 if (!callback || !s || !udevman || !pdev)
1195 return ERROR_INVALID_PARAMETER;
1196
1197 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1198
1199 if (!urbdrc)
1200 return ERROR_INVALID_PARAMETER;
1201
1202 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1203 return ERROR_INVALID_DATA;
1204
1205 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1206 Stream_Read_UINT32(s, TransferFlags);
1207 Stream_Read_UINT8(s, ReqTypeReservedBits);
1208 Stream_Read_UINT8(s, Request);
1209 Stream_Read_UINT16(s, Value);
1210 Stream_Read_UINT16(s, Index);
1211 Stream_Seek_UINT16(s);
1212 Stream_Read_UINT32(s, OutputBufferSize);
1213 if (OutputBufferSize > UINT32_MAX - 36)
1214 return ERROR_INVALID_DATA;
1215
1216 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1217 {
1218 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1219 return ERROR_INVALID_DATA;
1220 }
1221
1222 out_size = 36ULL + OutputBufferSize;
1223 out = Stream_New(nullptr, out_size);
1224
1225 if (!out)
1226 return ERROR_OUTOFMEMORY;
1227
1228 Stream_Seek(out, 36);
1229
1231 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1232 {
1233 Stream_Copy(s, out, OutputBufferSize);
1234 Stream_Rewind(out, OutputBufferSize);
1235 }
1236
1238 bmRequestType = func_type | func_recipient;
1239
1240 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1241 bmRequestType |= 0x80;
1242
1243 WLog_Print(urbdrc->log, WLOG_DEBUG,
1244 "RequestId 0x%" PRIx32 " TransferFlags: 0x%" PRIx32 " ReqTypeReservedBits: 0x%" PRIx8
1245 " "
1246 "Request:0x%" PRIx8 " Value: 0x%" PRIx16 " Index: 0x%" PRIx16
1247 " OutputBufferSize: 0x%" PRIx32 " bmRequestType: 0x%" PRIx8,
1248 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1249 OutputBufferSize, bmRequestType);
1250
1251 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1252 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1253 {
1254 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1255 Stream_Free(out, TRUE);
1256 return ERROR_INTERNAL_ERROR;
1257 }
1258
1259 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1260 usbd_status, OutputBufferSize, transferDir);
1261}
1262
1263static UINT urb_os_feature_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1264 wStream* s, UINT32 RequestField, UINT32 MessageId,
1265 IUDEVMAN* udevman, int transferDir)
1266{
1267 size_t out_size = 0;
1268 UINT32 InterfaceId = 0;
1269 UINT32 OutputBufferSize = 0;
1270 UINT32 usbd_status = 0;
1271 BYTE Recipient = 0;
1272 BYTE InterfaceNumber = 0;
1273 BYTE Ms_PageIndex = 0;
1274 UINT16 Ms_featureDescIndex = 0;
1275 wStream* out = nullptr;
1276 int ret = 0;
1277 URBDRC_PLUGIN* urbdrc = nullptr;
1278 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1279 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1280
1281 if (!callback || !s || !udevman || !pdev)
1282 return ERROR_INVALID_PARAMETER;
1283
1284 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1285
1286 if (!urbdrc)
1287 return ERROR_INVALID_PARAMETER;
1288
1289 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1290 return ERROR_INVALID_DATA;
1291
1292 /* 2.2.9.15 TS_URB_OS_FEATURE_DESCRIPTOR_REQUEST */
1293 Stream_Read_UINT8(s, Recipient);
1294 Recipient = (Recipient & 0x1f); /* Mask out Padding1 */
1295 Stream_Read_UINT8(s, InterfaceNumber);
1296 Stream_Read_UINT8(s, Ms_PageIndex);
1297 Stream_Read_UINT16(s, Ms_featureDescIndex);
1298 Stream_Seek(s, 3); /* Padding 2 */
1299 Stream_Read_UINT32(s, OutputBufferSize);
1300 if (OutputBufferSize > UINT32_MAX - 36)
1301 return ERROR_INVALID_DATA;
1302
1303 switch (transferDir)
1304 {
1305 case USBD_TRANSFER_DIRECTION_OUT:
1306 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1307 return ERROR_INVALID_DATA;
1308
1309 break;
1310
1311 default:
1312 break;
1313 }
1314
1315 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1316 out_size = 36ULL + OutputBufferSize;
1317 out = Stream_New(nullptr, out_size);
1318
1319 if (!out)
1320 return ERROR_OUTOFMEMORY;
1321
1322 Stream_Seek(out, 36);
1323
1324 switch (transferDir)
1325 {
1326 case USBD_TRANSFER_DIRECTION_OUT:
1327 Stream_Copy(s, out, OutputBufferSize);
1328 Stream_Rewind(out, OutputBufferSize);
1329 break;
1330
1331 case USBD_TRANSFER_DIRECTION_IN:
1332 break;
1333 default:
1334 break;
1335 }
1336
1337 WLog_Print(urbdrc->log, WLOG_DEBUG,
1338 "Ms descriptor arg: Recipient:0x%" PRIx8 ", "
1339 "InterfaceNumber:0x%" PRIx8 ", Ms_PageIndex:0x%" PRIx8 ", "
1340 "Ms_featureDescIndex:0x%" PRIx16 ", OutputBufferSize:0x%" PRIx32 "",
1341 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1343 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1344 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1345 &OutputBufferSize, Stream_Pointer(out), 1000);
1346
1347 if (ret < 0)
1348 WLog_Print(urbdrc->log, WLOG_DEBUG, "os_feature_descriptor_request: error num %d", ret);
1349
1350 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1351 usbd_status, OutputBufferSize, transferDir);
1352}
1353
1354static UINT urb_pipe_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1355 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1356 int transferDir, int action)
1357{
1358 UINT32 usbd_status = 0;
1359 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1360 int rc = 0;
1361 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1362 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1363
1364 if (!callback || !s || !udevman || !pdev)
1365 return ERROR_INVALID_PARAMETER;
1366
1367 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1368
1369 if (!urbdrc)
1370 return ERROR_INVALID_PARAMETER;
1371
1372 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1373 return ERROR_INVALID_DATA;
1374
1375 if (transferDir == 0)
1376 {
1377 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: not support transfer out");
1378 return ERROR_INVALID_PARAMETER;
1379 }
1380
1381 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1382 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1383 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1384 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1385
1386 if (OutputBufferSize != 0)
1387 {
1388 WLog_Print(urbdrc->log, WLOG_DEBUG,
1389 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32 " != 0",
1390 OutputBufferSize);
1391 return ERROR_BAD_CONFIGURATION;
1392 }
1393
1394 switch (action)
1395 {
1396 case PIPE_CANCEL:
1397 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1398 PIPE_CANCEL);
1399
1400 if (rc < 0)
1401 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE SET HALT: error %u", ret);
1402 else
1403 ret = USBD_STATUS_SUCCESS;
1404
1405 break;
1406
1407 case PIPE_RESET:
1408 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: PIPE_RESET ep 0x%" PRIx32 "",
1409 EndpointAddress);
1410 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1411 PIPE_RESET);
1412
1413 if (rc < 0)
1414 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE RESET: error %u", ret);
1415 else
1416 ret = USBD_STATUS_SUCCESS;
1417
1418 break;
1419
1420 default:
1421 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request action: %d not supported",
1422 action);
1423 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1424 break;
1425 }
1426
1429 wStream* out = Stream_New(nullptr, 36);
1430
1431 if (!out)
1432 return ERROR_OUTOFMEMORY;
1433
1434 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1435 0, transferDir);
1436}
1437/* [MS-RDPEUSB] 2.2.10.4 TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT */
1438static UINT urb_send_current_frame_number_result(GENERIC_CHANNEL_CALLBACK* callback,
1439 UINT32 RequestId, UINT32 MessageId,
1440 UINT32 CompletionId, UINT32 FrameNumber)
1441{
1442 WINPR_ASSERT(callback);
1443
1444 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1445 wStream* out =
1446 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1447
1448 if (!out)
1449 return ERROR_OUTOFMEMORY;
1450
1451 if (!Stream_EnsureRemainingCapacity(out, 4))
1452 goto fail;
1453 Stream_Write_UINT32(out, 12);
1454 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1455 goto fail;
1456 Stream_Write_UINT32(out, FrameNumber);
1457 return send_urb_completion_message(callback, out, 0, 0, nullptr);
1458
1459fail:
1460 Stream_Free(out, TRUE);
1461 return ERROR_OUTOFMEMORY;
1462}
1463
1464static UINT urb_get_current_frame_number(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1465 wStream* s, UINT32 RequestField, UINT32 MessageId,
1466 IUDEVMAN* udevman, int transferDir)
1467{
1468 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1469 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1470
1471 if (!callback || !s || !udevman || !pdev)
1472 return ERROR_INVALID_PARAMETER;
1473
1474 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1475
1476 if (!urbdrc)
1477 return ERROR_INVALID_PARAMETER;
1478
1479 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1480 return ERROR_INVALID_DATA;
1481
1482 if (transferDir == 0)
1483 {
1484 WLog_Print(urbdrc->log, WLOG_DEBUG,
1485 "urb_get_current_frame_number: not support transfer out");
1486 return ERROR_INVALID_PARAMETER;
1487 }
1488
1489 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1490 if (OutputBufferSize != 0)
1491 {
1492 WLog_Print(urbdrc->log, WLOG_WARN, "OutputBufferSize=%" PRIu32 ", expected 0",
1493 OutputBufferSize);
1494 }
1496 const UINT32 dummy_frames = GetTickCount();
1497 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1498
1499 if (noAck)
1500 return CHANNEL_RC_OK;
1501
1502 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1503 dummy_frames);
1504}
1505
1506/* Unused function for current server */
1507static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1508 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1509 UINT32 RequestField, UINT32 MessageId,
1510 IUDEVMAN* udevman, int transferDir)
1511{
1512 size_t out_size = 0;
1513 UINT32 InterfaceId = 0;
1514 UINT32 OutputBufferSize = 0;
1515 UINT32 usbd_status = 0;
1516 wStream* out = nullptr;
1517 URBDRC_PLUGIN* urbdrc = nullptr;
1518 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1519 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1520
1521 if (!callback || !s || !udevman || !pdev)
1522 return ERROR_INVALID_PARAMETER;
1523
1524 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1525
1526 if (!urbdrc)
1527 return ERROR_INVALID_PARAMETER;
1528
1529 if (transferDir == 0)
1530 {
1531 WLog_Print(urbdrc->log, WLOG_DEBUG,
1532 "urb_control_get_configuration_request:"
1533 " not support transfer out");
1534 return ERROR_INVALID_PARAMETER;
1535 }
1536
1537 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1538 return ERROR_INVALID_DATA;
1539
1540 Stream_Read_UINT32(s, OutputBufferSize);
1541 if (OutputBufferSize > UINT32_MAX - 36)
1542 return ERROR_INVALID_DATA;
1543 out_size = 36ULL + OutputBufferSize;
1544 out = Stream_New(nullptr, out_size);
1545
1546 if (!out)
1547 return ERROR_OUTOFMEMORY;
1548
1549 Stream_Seek(out, 36);
1550 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1551
1552 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1553 0x08, /* REQUEST_GET_CONFIGURATION */
1554 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1555 {
1556 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1557 Stream_Free(out, TRUE);
1558 return ERROR_INTERNAL_ERROR;
1559 }
1560
1561 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1562 usbd_status, OutputBufferSize, transferDir);
1563}
1564
1565/* Unused function for current server */
1566static UINT urb_control_get_interface_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1567 wStream* s, UINT32 RequestField, UINT32 MessageId,
1568 IUDEVMAN* udevman, int transferDir)
1569{
1570 size_t out_size = 0;
1571 UINT32 InterfaceId = 0;
1572 UINT32 OutputBufferSize = 0;
1573 UINT32 usbd_status = 0;
1574 UINT16 InterfaceNr = 0;
1575 wStream* out = nullptr;
1576 URBDRC_PLUGIN* urbdrc = nullptr;
1577 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1578 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1579
1580 if (!callback || !s || !udevman || !pdev)
1581 return ERROR_INVALID_PARAMETER;
1582
1583 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1584
1585 if (!urbdrc)
1586 return ERROR_INVALID_PARAMETER;
1587
1588 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1589 return ERROR_INVALID_DATA;
1590
1591 if (transferDir == 0)
1592 {
1593 WLog_Print(urbdrc->log, WLOG_DEBUG,
1594 "urb_control_get_interface_request: not support transfer out");
1595 return ERROR_INVALID_PARAMETER;
1596 }
1597
1598 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1599 Stream_Read_UINT16(s, InterfaceNr);
1600 Stream_Seek(s, 2);
1601 Stream_Read_UINT32(s, OutputBufferSize);
1602 if (OutputBufferSize > UINT32_MAX - 36)
1603 return ERROR_INVALID_DATA;
1604 out_size = 36ULL + OutputBufferSize;
1605 out = Stream_New(nullptr, out_size);
1606
1607 if (!out)
1608 return ERROR_OUTOFMEMORY;
1609
1610 Stream_Seek(out, 36);
1611
1612 if (!pdev->control_transfer(
1613 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */
1614 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1615 {
1616 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1617 Stream_Free(out, TRUE);
1618 return ERROR_INTERNAL_ERROR;
1619 }
1620
1621 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1622 usbd_status, OutputBufferSize, transferDir);
1623}
1624
1625static UINT urb_control_feature_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1626 wStream* s, UINT32 RequestField, UINT32 MessageId,
1627 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1628 int transferDir)
1629{
1630 UINT32 InterfaceId = 0;
1631 UINT32 OutputBufferSize = 0;
1632 UINT32 usbd_status = 0;
1633 UINT16 FeatureSelector = 0;
1634 UINT16 Index = 0;
1635 BYTE bmRequestType = 0;
1636 BYTE bmRequest = 0;
1637 wStream* out = nullptr;
1638 URBDRC_PLUGIN* urbdrc = nullptr;
1639 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1640 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1641
1642 if (!callback || !s || !udevman || !pdev)
1643 return ERROR_INVALID_PARAMETER;
1644
1645 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1646
1647 if (!urbdrc)
1648 return ERROR_INVALID_PARAMETER;
1649
1650 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1651 return ERROR_INVALID_DATA;
1652
1653 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1654 Stream_Read_UINT16(s, FeatureSelector);
1655 Stream_Read_UINT16(s, Index);
1656 Stream_Read_UINT32(s, OutputBufferSize);
1657 if (OutputBufferSize > UINT32_MAX - 36)
1658 return ERROR_INVALID_DATA;
1659 switch (transferDir)
1660 {
1661 case USBD_TRANSFER_DIRECTION_OUT:
1662 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1663 return ERROR_INVALID_DATA;
1664
1665 break;
1666
1667 default:
1668 break;
1669 }
1670
1671 out = Stream_New(nullptr, 36ULL + OutputBufferSize);
1672
1673 if (!out)
1674 return ERROR_OUTOFMEMORY;
1675
1676 Stream_Seek(out, 36);
1677 bmRequestType = func_recipient;
1678
1679 switch (transferDir)
1680 {
1681 case USBD_TRANSFER_DIRECTION_OUT:
1682 WLog_Print(urbdrc->log, WLOG_ERROR,
1683 "Function urb_control_feature_request: OUT Unchecked");
1684 Stream_Copy(s, out, OutputBufferSize);
1685 Stream_Rewind(out, OutputBufferSize);
1686 bmRequestType |= 0x00;
1687 break;
1688
1689 case USBD_TRANSFER_DIRECTION_IN:
1690 bmRequestType |= 0x80;
1691 break;
1692 default:
1693 break;
1694 }
1695
1696 switch (command)
1697 {
1698 case URB_SET_FEATURE:
1699 bmRequest = 0x03; /* REQUEST_SET_FEATURE */
1700 break;
1701
1702 case URB_CLEAR_FEATURE:
1703 bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */
1704 break;
1705
1706 default:
1707 WLog_Print(urbdrc->log, WLOG_ERROR,
1708 "urb_control_feature_request: Error Command 0x%02" PRIx8 "", command);
1709 Stream_Free(out, TRUE);
1710 return ERROR_INTERNAL_ERROR;
1711 }
1712
1713 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1714 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1715 {
1716 WLog_Print(urbdrc->log, WLOG_DEBUG, "feature control transfer failed");
1717 Stream_Free(out, TRUE);
1718 return ERROR_INTERNAL_ERROR;
1719 }
1720
1721 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1722 usbd_status, OutputBufferSize, transferDir);
1723}
1724
1725static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1726 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1727 int transferDir)
1728{
1729 UINT32 CbTsUrb = 0;
1730 UINT16 Size = 0;
1731 UINT16 URB_Function = 0;
1732 UINT32 RequestId = 0;
1733 UINT error = ERROR_INTERNAL_ERROR;
1734 URBDRC_PLUGIN* urbdrc = nullptr;
1735
1736 if (!callback || !s || !udevman || !pdev)
1737 return ERROR_INVALID_PARAMETER;
1738
1739 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1740
1741 if (!urbdrc)
1742 return ERROR_INVALID_PARAMETER;
1743
1744 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1745 return ERROR_INVALID_DATA;
1746
1747 Stream_Read_UINT32(s, CbTsUrb);
1748 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1749 return ERROR_INVALID_DATA;
1750 Stream_Read_UINT16(s, Size);
1751 if (Size != CbTsUrb)
1752 {
1753 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1754 ? "2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1755 : "2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1756 WLog_ERR(TAG,
1757 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1758 " != %s::CbTsUrb 0x%08" PRIx32,
1759 Size, section, CbTsUrb);
1760 return ERROR_INVALID_DATA;
1761 }
1762 Stream_Read_UINT16(s, URB_Function);
1763 Stream_Read_UINT32(s, RequestId);
1764 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB %s[%" PRIu16 "]", urb_function_string(URB_Function),
1765 URB_Function);
1766
1767 switch (URB_Function)
1768 {
1769 case TS_URB_SELECT_CONFIGURATION:
1770 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1771 transferDir);
1772 break;
1773
1774 case TS_URB_SELECT_INTERFACE:
1775 error =
1776 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1777 break;
1778
1779 case TS_URB_PIPE_REQUEST:
1780 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1781 PIPE_CANCEL);
1782 break;
1783
1784 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1788 break;
1789
1790 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1794 break;
1795
1796 case TS_URB_GET_FRAME_LENGTH:
1800 break;
1801
1802 case TS_URB_SET_FRAME_LENGTH:
1806 break;
1807
1808 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1809 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1810 transferDir);
1811 break;
1812
1813 case TS_URB_CONTROL_TRANSFER:
1814 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1815 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1816 break;
1817
1818 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1819 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1820 transferDir);
1821 break;
1822
1823 case TS_URB_ISOCH_TRANSFER:
1824 error =
1825 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1826 break;
1827
1828 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1829 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1830 0x00, transferDir);
1831 break;
1832
1833 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1834 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1835 0x00, transferDir);
1836 break;
1837
1838 case TS_URB_SET_FEATURE_TO_DEVICE:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x00, URB_SET_FEATURE, transferDir);
1841 break;
1842
1843 case TS_URB_SET_FEATURE_TO_INTERFACE:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x01, URB_SET_FEATURE, transferDir);
1846 break;
1847
1848 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1849 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1850 0x02, URB_SET_FEATURE, transferDir);
1851 break;
1852
1853 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1854 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 0x00, URB_CLEAR_FEATURE, transferDir);
1856 break;
1857
1858 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1859 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1860 0x01, URB_CLEAR_FEATURE, transferDir);
1861 break;
1862
1863 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1864 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1865 0x02, URB_CLEAR_FEATURE, transferDir);
1866 break;
1867
1868 case TS_URB_GET_STATUS_FROM_DEVICE:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1870 0x00, transferDir);
1871 break;
1872
1873 case TS_URB_GET_STATUS_FROM_INTERFACE:
1874 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1875 0x01, transferDir);
1876 break;
1877
1878 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1879 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1880 0x02, transferDir);
1881 break;
1882
1883 case TS_URB_RESERVED_0X0016:
1884 break;
1885
1886 case TS_URB_VENDOR_DEVICE:
1887 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1888 udevman, (0x02u << 5), /* vendor type */
1889 0x00, transferDir);
1890 break;
1891
1892 case TS_URB_VENDOR_INTERFACE:
1893 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1894 udevman, (0x02u << 5), /* vendor type */
1895 0x01, transferDir);
1896 break;
1897
1898 case TS_URB_VENDOR_ENDPOINT:
1899 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1900 udevman, (0x02u << 5), /* vendor type */
1901 0x02, transferDir);
1902 break;
1903
1904 case TS_URB_CLASS_DEVICE:
1905 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1906 udevman, (0x01u << 5), /* class type */
1907 0x00, transferDir);
1908 break;
1909
1910 case TS_URB_CLASS_INTERFACE:
1911 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1912 udevman, (0x01u << 5), /* class type */
1913 0x01, transferDir);
1914 break;
1915
1916 case TS_URB_CLASS_ENDPOINT:
1917 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1918 udevman, (0x01u << 5), /* class type */
1919 0x02, transferDir);
1920 break;
1921
1922 case TS_URB_RESERVE_0X001D:
1923 break;
1924
1925 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1926 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1927 PIPE_RESET);
1928 break;
1929
1930 case TS_URB_CLASS_OTHER:
1931 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1932 udevman, (0x01u << 5), /* class type */
1933 0x03, transferDir);
1934 break;
1935
1936 case TS_URB_VENDOR_OTHER:
1937 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1938 udevman, (0x02u << 5), /* vendor type */
1939 0x03, transferDir);
1940 break;
1941
1942 case TS_URB_GET_STATUS_FROM_OTHER:
1943 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1944 0x03, transferDir);
1945 break;
1946
1947 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1948 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1949 0x03, URB_CLEAR_FEATURE, transferDir);
1950 break;
1951
1952 case TS_URB_SET_FEATURE_TO_OTHER:
1953 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1954 0x03, URB_SET_FEATURE, transferDir);
1955 break;
1956
1957 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1958 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1959 0x02, transferDir);
1960 break;
1961
1962 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1963 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1964 0x02, transferDir);
1965 break;
1966
1967 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1968 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1969 udevman, transferDir);
1970 break;
1971
1972 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1973 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1974 udevman, transferDir);
1975 break;
1976
1977 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1978 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1979 0x01, transferDir);
1980 break;
1981
1982 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1983 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1984 0x01, transferDir);
1985 break;
1986
1987 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1988 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1989 udevman, transferDir);
1990 break;
1991
1992 case TS_URB_RESERVE_0X002B:
1993 case TS_URB_RESERVE_0X002C:
1994 case TS_URB_RESERVE_0X002D:
1995 case TS_URB_RESERVE_0X002E:
1996 case TS_URB_RESERVE_0X002F:
1997 break;
1998
2000 case TS_URB_SYNC_RESET_PIPE:
2001 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
2002 PIPE_RESET);
2003 break;
2004
2005 case TS_URB_SYNC_CLEAR_STALL:
2006 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
2007 PIPE_RESET);
2008 break;
2009
2010 case TS_URB_CONTROL_TRANSFER_EX:
2011 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
2012 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
2013 break;
2014
2015 default:
2016 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB_Func: %" PRIx16 " is not found!",
2017 URB_Function);
2018 break;
2019 }
2020
2021 if (error)
2022 {
2023 WLog_Print(urbdrc->log, WLOG_WARN,
2024 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2025 urb_function_string(URB_Function), URB_Function, error);
2026 }
2027
2028 return error;
2029}
2030
2031UINT urbdrc_process_udev_data_transfer(GENERIC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
2032 IUDEVMAN* udevman, wStream* data)
2033{
2034 UINT32 InterfaceId = 0;
2035 UINT32 MessageId = 0;
2036 UINT32 FunctionId = 0;
2037 IUDEVICE* pdev = nullptr;
2038 UINT error = ERROR_INTERNAL_ERROR;
2039
2040 if (!urbdrc || !data || !callback || !udevman)
2041 goto fail;
2042
2043 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2044 goto fail;
2045
2046 Stream_Rewind_UINT32(data);
2047
2048 Stream_Read_UINT32(data, InterfaceId);
2049 Stream_Read_UINT32(data, MessageId);
2050 Stream_Read_UINT32(data, FunctionId);
2051
2052 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2053
2054 /* Device does not exist, ignore this request. */
2055 if (pdev == nullptr)
2056 {
2057 error = ERROR_SUCCESS;
2058 goto fail;
2059 }
2060
2061 /* Device has been removed, ignore this request. */
2062 if (pdev->isChannelClosed(pdev))
2063 {
2064 error = ERROR_SUCCESS;
2065 goto fail;
2066 }
2067
2068 /* Whatever channel the request arrived on, answer on the channel the device is bound to: a
2069 * pending transfer keeps the callback of that channel and closing it drains the device before
2070 * the callback is freed. Any other channel may go away while the transfer is still pending. */
2071 callback = pdev->get_channelCallback(pdev);
2072
2073 /* Device has not been announced yet, ignore this request. */
2074 if (callback == nullptr)
2075 {
2076 error = ERROR_SUCCESS;
2077 goto fail;
2078 }
2079
2080 /* USB kernel driver detach!! */
2081 if (!pdev->detach_kernel_driver(pdev))
2082 {
2083 error = ERROR_SUCCESS;
2084 goto fail;
2085 }
2086
2087 switch (FunctionId)
2088 {
2089 case CANCEL_REQUEST:
2090 error = urbdrc_process_cancel_request(pdev, data, udevman);
2091 break;
2092
2093 case REGISTER_REQUEST_CALLBACK:
2094 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2095 break;
2096
2097 case IO_CONTROL:
2098 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2099 break;
2100
2101 case INTERNAL_IO_CONTROL:
2102 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2103 break;
2104
2105 case QUERY_DEVICE_TEXT:
2106 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2107 break;
2108
2109 case TRANSFER_IN_REQUEST:
2110 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2111 USBD_TRANSFER_DIRECTION_IN);
2112 break;
2113
2114 case TRANSFER_OUT_REQUEST:
2115 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2116 USBD_TRANSFER_DIRECTION_OUT);
2117 break;
2118
2119 case RETRACT_DEVICE:
2120 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2121 break;
2122
2123 default:
2124 WLog_Print(urbdrc->log, WLOG_WARN,
2125 "urbdrc_process_udev_data_transfer:"
2126 " unknown FunctionId 0x%" PRIX32 "",
2127 FunctionId);
2128 break;
2129 }
2130
2131fail:
2132 if (error)
2133 {
2134 WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
2135 }
2136
2137 return error;
2138}