ReactOS 0.4.17-dev-1281-g065abb3
hubioctl.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS SuperSpeed USB Hub Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: User mode and internal IOCTLs on the hub FDO queue
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9#include "devreq.h"
10
11#define NDEBUG
12#include <debug.h>
13
14/* ntifs.h only */
15extern "C"
21
22/* Fixed parts of the user mode structures; our usbioctl.h leaves the USB 3 ones unpacked */
23#define HUB_IO_NODE_INFO_SIZE sizeof(USB_NODE_INFORMATION)
24#define HUB_IO_CONNECTION_SIZE FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION, PipeList)
25#define HUB_IO_NAME_HEADER FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName)
26#define HUB_IO_NAME_SIZE sizeof(USB_NODE_CONNECTION_NAME)
27#define HUB_IO_DESCRIPTOR_HEADER FIELD_OFFSET(USB_DESCRIPTOR_REQUEST, Data)
28#define HUB_IO_ATTRIBUTES_SIZE sizeof(USB_NODE_CONNECTION_ATTRIBUTES)
29#define HUB_IO_HUB_INFO_EX_SIZE (FIELD_OFFSET(USB_HUB_INFORMATION_EX, u) + sizeof(USB_HUB_DESCRIPTOR))
30#define HUB_IO_CONNECTOR_SIZE (FIELD_OFFSET(USB_PORT_CONNECTOR_PROPERTIES, CompanionHubSymbolicLinkName) + sizeof(WCHAR))
31#define HUB_IO_CONNECTION_V2_SIZE sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2)
32#define HUB_IO_CYCLE_SIZE sizeof(USB_CYCLE_PORT_PARAMS)
33
36C_ASSERT(sizeof(USB_PIPE_INFO) == 11);
45
46/* MaxPortPower of a bus powered hub, in mA */
47#define HUB_BUS_POWERED_PORT_POWER 100
48
49/* _UPC connector types of a Type-C connector */
50#define HUB_UPC_TYPE_C_USB2 0x08
51#define HUB_UPC_TYPE_C_SWITCH 0x09
52#define HUB_UPC_TYPE_C_NO_SWITCH 0x0A
53
54/* String descriptors are answered from the cache only in US English */
55#define HUB_LANGID_US_ENGLISH 0x0409
56
57/* IOCTL_USB_GET_PORT_STATUS, private to usbhub3 */
59{
63};
64
66
67static const char HubTagUserRequest[] = "User Mode FDO Request";
68
69/* Shared helpers */
70
73static
76HubIoCallerIsAdmin(VOID)
77{
80 BOOLEAN Admin;
81
82 PAGED_CODE();
83
85 SeLockSubjectContext(&Subject);
86
87 Token = (Subject.ClientToken != NULL) ? Subject.ClientToken : Subject.PrimaryToken;
88 Admin = (Token != NULL) && SeTokenIsAdmin(Token);
89
90 SeUnlockSubjectContext(&Subject);
92
93 return Admin ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
94}
95
97static
103{
104 PWCHAR Cursor = Link->Buffer;
105 PWCHAR End;
106
107 *Bytes = 0;
108 if (Cursor == NULL)
109 return NULL;
110
111 End = Cursor + Link->Length / sizeof(WCHAR);
112
113 if (Cursor < End && *Cursor == L'\\')
114 {
115 for (Cursor++; Cursor < End; Cursor++)
116 {
117 if (*Cursor == L'\\' || *Cursor == UNICODE_NULL)
118 break;
119 }
120
121 if (Cursor < End && *Cursor == L'\\')
122 Cursor++;
123 }
124
125 *Bytes = (ULONG)((End - Cursor) * sizeof(WCHAR));
126 return Cursor;
127}
128
130static
132NTAPI
134 _In_ HubFdo* Hub,
135 _In_ size_t MinInput,
136 _In_ size_t InputLength,
138 _In_ size_t MinOutput,
139 _In_ size_t OutputLength)
140{
142
144 {
145 DPRINT1("Hub %p is not configured, user request refused\n", Hub);
146 return STATUS_UNSUCCESSFUL;
147 }
148
149 if (InputLength < MinInput)
150 {
151 DPRINT1("Hub %p user request input %lu bytes, needs %lu\n", Hub, (ULONG)InputLength, (ULONG)MinInput);
153 }
154
155 if (OutputLength < MinOutput)
156 {
157 DPRINT1("Hub %p user request output %lu bytes, needs %lu\n", Hub, (ULONG)OutputLength, (ULONG)MinOutput);
159 }
160
161 if (MinInput >= sizeof(ULONG))
162 {
164 if (PortNumber == 0 || PortNumber > Hub->m_PortCount)
165 {
166 DPRINT1("Hub %p user request for invalid port %lu\n", Hub, PortNumber);
168 }
169 }
170
171 return STATUS_SUCCESS;
172}
173
175static
177NTAPI
179 _In_ HubFdo* Hub,
180 _In_ WDFREQUEST Request,
181 _In_ size_t MinInput,
182 _In_ size_t InputLength,
183 _In_ size_t MinOutput,
184 _In_ size_t OutputLength,
186{
188
189 Status = WdfRequestRetrieveOutputBuffer(Request, OutputLength, Buffer, NULL);
190 if (!NT_SUCCESS(Status))
191 {
192 DPRINT1("Hub %p request %p has no output buffer 0x%lx\n", Hub, Request, Status);
193 *Buffer = NULL;
194 return Status;
195 }
196
197 return HubIoValidate(Hub, MinInput, InputLength, *Buffer, MinOutput, OutputLength);
198}
199
201static
202HubPdo*
203NTAPI
205 _In_ HubFdo* Hub,
207{
208 WDFDEVICE Device = NULL;
209 HubPdo* Pdo;
210
212
213 while ((Device = WdfFdoRetrieveNextStaticChild(Hub->m_Device, Device, WdfRetrievePresentChildren)) != NULL)
214 {
215 Pdo = HubGetPdoContext(Device);
216 if (Pdo->m_PortNumber == PortNumber)
217 return Pdo;
218 }
219
220 return NULL;
221}
222
223static
224VOID
225NTAPI
227 _In_ HubFdo* Hub)
228{
230}
231
232static
233VOID
234NTAPI
236 _In_ HubFdo* Hub,
237 _In_ WDFREQUEST Request)
238{
240
241 WdfRequestFormatRequestUsingCurrentType(Request);
243
244 if (!WdfRequestSend(Request, WdfDeviceGetIoTarget(Hub->m_Device), &Options))
245 {
246 DPRINT1("Hub %p forwarding request %p failed 0x%lx\n", Hub, Request, WdfRequestGetStatus(Request));
247 WdfRequestComplete(Request, WdfRequestGetStatus(Request));
248 }
249}
250
252static
253VOID
254NTAPI
256 _In_ HubFdo* Hub,
258{
259 ULONG MaskBytes;
260
262
263 if (!Hub->IsRootHub())
264 {
266 {
268 return;
269 }
270
272 return;
273
274 Descriptor->wHubCharacteristics = Hub->m_HubDescriptor.Usb30.wHubCharacteristics & 0x1F;
277 }
278 else
279 {
280 Descriptor->bPowerOnToPowerGood = 2;
281 }
282
283 /* QUIRK: the length stays 9 even when the port masks need more room */
284 Descriptor->bDescriptorLength = 9;
285 Descriptor->bDescriptorType = USB_20_HUB_DESCRIPTOR_TYPE;
286 Descriptor->bNumberOfPorts = (UCHAR)Hub->m_PortCount;
287
288 /* Every port removable, then the legacy power control mask all ones */
289 MaskBytes = Hub->m_PortCount / 8 + 1;
290 RtlFillMemory(&Descriptor->bRemoveAndPowerMask[MaskBytes], MaskBytes, 0xFF);
291}
292
294static
296NTAPI
299 _In_ ULONG SpeedId,
301{
303 ULONG Index;
304
305 for (Index = 0; Index < Port->m_Info.SublinkSpeedAttrCount; Index++)
306 {
307 Attribute = &Port->m_Info.SublinkSpeedAttr[Index];
308 if (Attribute->SublinkSpeedAttrID == SpeedId && Attribute->SublinkTypeDir == Direction)
310 }
311
312 return FALSE;
313}
314
315/* The device has a SuperSpeedPlus capability exactly when its sublink speeds were cached */
316static
318NTAPI
321{
322 ULONG Index;
323
324 if (Child->m_SublinkSpeedAttr == NULL)
325 return FALSE;
326
327 for (Index = 0; Index < Child->m_SublinkSpeedAttrCount; Index++)
328 {
329 if (Child->m_SublinkSpeedAttr[Index].LinkProtocol != USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED_PROTOCOL_SS)
330 return TRUE;
331 }
332
333 return FALSE;
334}
335
336static
338NTAPI
341{
342 HubPort* Port = Child->m_Port;
343 USB_PORT_EXT_STATUS Extended;
344
345 if (Child->m_SublinkSpeedAttr == NULL || !Port->HasProperty(PortProperty::EnhancedSuperSpeed))
346 return FALSE;
347
348 Extended.AsUlong32 = Port->m_Current.ExtendedStatus;
349
350 /* QUIRK: the Tx lookup also uses the Rx sublink speed id */
353}
354
355/* Section 6.8a without the device reference */
356static
357VOID
358NTAPI
360 _In_ WDFREQUEST Request,
363{
364 if (NT_SUCCESS(Status))
366 else
367 WdfRequestComplete(Request, Status);
368}
369
370VOID
371NTAPI
374 _In_ WDFREQUEST Request,
377{
380}
381
382VOID
384{
386 WDFREQUEST Request = Child->m_FdoRequest;
387
388 Child->m_FdoRequest = NULL;
389 DPRINT1("Device %p descriptor request %p failed by the device machine\n", Child, Request);
391}
392
393/* Handlers */
394
395static
396VOID
397NTAPI
399 _In_ HubFdo* Hub,
400 _In_ WDFREQUEST Request,
401 _In_ size_t OutputLength,
402 _In_ size_t InputLength)
403{
405 ULONG Index;
406 HubPort* Port;
408
409 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, sizeof(*Info), OutputLength, (PVOID*)&Info);
410 if (!NT_SUCCESS(Status))
411 {
412 WdfRequestComplete(Request, Status);
413 return;
414 }
415
416 Index = Info->ConnectionIndex;
417 RtlZeroMemory(Info, OutputLength);
418 Info->ConnectionIndex = Index;
419
421 if (Port == NULL)
422 {
423 DPRINT1("Hub %p port status: no port %lu\n", Hub, Index);
425 return;
426 }
427
428 /* The hub machine completes it through ReplyPortStatus or FailPortStatus */
432}
433
434static
435VOID
436NTAPI
438 _In_ HubFdo* Hub,
439 _In_ WDFREQUEST Request,
440 _In_ size_t OutputLength,
441 _In_ size_t InputLength)
442{
445
446 Status = HubIoValidate(Hub, 0, InputLength, NULL, HUB_IO_NODE_INFO_SIZE, OutputLength);
447 if (NT_SUCCESS(Status))
448 {
449 Status = WdfRequestRetrieveOutputBuffer(Request, OutputLength, (PVOID*)&Info, NULL);
450 if (!NT_SUCCESS(Status))
451 DPRINT1("Hub %p node information has no output buffer 0x%lx\n", Hub, Status);
452 }
453
454 if (NT_SUCCESS(Status))
455 {
456 RtlZeroMemory(Info, OutputLength);
457 Info->NodeType = UsbHub;
458 Info->u.HubInformation.HubIsBusPowered = (Hub->m_MaxPortPower == HUB_BUS_POWERED_PORT_POWER);
459 HubIoBuild20Descriptor(Hub, &Info->u.HubInformation.HubDescriptor);
460 }
461
462 /* QUIRK: the size is reported on failure too */
464}
465
466static
467VOID
468NTAPI
470 _In_ HubFdo* Hub,
471 _In_ WDFREQUEST Request,
472 _In_ size_t OutputLength,
473 _In_ size_t InputLength)
474{
476 ULONG Index;
477 ULONG Returned = 0;
478 HubPdo* Pdo;
480
481 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_NAME_SIZE, OutputLength, (PVOID*)&Name);
482 if (!NT_SUCCESS(Status))
483 goto Fail;
484
485 Index = Name->ConnectionIndex;
486
488 if (Pdo == NULL)
489 {
491 DPRINT1("Hub %p driver key name: no device on port %lu\n", Hub, Index);
493 goto Fail;
494 }
495
496 RtlZeroMemory(Name, OutputLength);
497 Name->ConnectionIndex = Index;
498
499 Status = WdfDeviceQueryProperty(Pdo->m_Device,
501 (ULONG)(OutputLength - HUB_IO_NAME_HEADER),
502 Name->DriverKeyName,
503 &Returned);
505
506 /* A name that does not fit still reports its size */
509
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT1("Hub %p driver key name of port %lu failed 0x%lx\n", Hub, Index, Status);
513 goto Fail;
514 }
515
516 Name->ActualLength = Returned + HUB_IO_NAME_SIZE;
517 if (OutputLength >= Name->ActualLength)
518 {
520 return;
521 }
522
523 /* A name that does not fit is returned empty */
524 Name->DriverKeyName[0] = UNICODE_NULL;
526 return;
527
528Fail:
529 /* Some callers read ActualLength without looking at the status */
530 if (Name != NULL && OutputLength >= HUB_IO_NAME_SIZE)
531 {
532 Name->DriverKeyName[0] = UNICODE_NULL;
533 Name->ActualLength = HUB_IO_NAME_SIZE;
534 }
535
536 WdfRequestComplete(Request, Status);
537}
538
539static
540VOID
541NTAPI
543 _In_ HubFdo* Hub,
544 _In_ WDFREQUEST Request,
545 _In_ size_t OutputLength,
546 _In_ size_t InputLength,
547 _In_ BOOLEAN Extended)
548{
549 PUSB_NODE_CONNECTION_INFORMATION_EX Info;
554 USB_DEVICE_SPEED Speed;
556 HubPort* Port;
557 HubPdo* Pdo;
559 size_t Remaining;
560 size_t Information;
561 ULONG Index;
562 KIRQL Irql;
564
565 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_CONNECTION_SIZE, OutputLength, (PVOID*)&Info);
566 if (!NT_SUCCESS(Status))
567 {
568 WdfRequestComplete(Request, Status);
569 return;
570 }
571
572 PortNumber = (USHORT)Info->ConnectionIndex;
573 RtlZeroMemory(Info, OutputLength);
574
576 Info->ConnectionStatus = (Port != NULL) ? Port->m_ConnectionStatus : DeviceGeneralFailure;
577
579 Child = (Pdo != NULL) ? Pdo->m_Child : NULL;
580 if (Child == NULL)
581 {
582 /* QUIRK: ConnectionIndex stays 0 for an empty port */
585 return;
586 }
587
588 Info->ConnectionIndex = PortNumber;
589 RtlCopyMemory(&Info->DeviceDescriptor, &Child->m_DeviceDescriptor, sizeof(Info->DeviceDescriptor));
590
591 Speed = Child->Speed();
592 if (Extended)
593 {
594 /* Callers of this form predate SuperSpeed */
595 Info->Speed = (UCHAR)((Speed == UsbSuperSpeed) ? UsbHighSpeed : Speed);
596 }
597 else
598 {
599 ((PUSB_NODE_CONNECTION_INFORMATION)Info)->LowSpeed = (Speed == UsbLowSpeed);
600 }
601
602 Info->DeviceAddress = Child->m_Address;
603 Info->DeviceIsHub = Child->HasProperty(ChildProperty::IsHub);
604
606
607 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
608
609 Config = Child->m_CurrentConfig;
610 if (Child->HasState(ChildState::ConfigurationValid) && Config != NULL)
611 {
612 Info->CurrentConfigurationValue = Config->Descriptor.bConfigurationValue;
613
614 /* QUIRK: the full count even when fewer pipes fit */
615 Info->NumberOfOpenPipes = Config->EndpointCount;
616
617 Remaining = OutputLength - HUB_IO_CONNECTION_SIZE;
618 Pipe = &Info->PipeList[0];
619
620 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
621 {
623
624 for (Index = 0; Index < Interface->PipeCount && Remaining >= sizeof(*Pipe); Index++)
625 {
626 RtlCopyMemory(&Pipe->EndpointDescriptor,
627 Interface->Pipes[Index].Descriptor,
628 sizeof(Pipe->EndpointDescriptor));
629 Pipe->ScheduleOffset = 0;
630 Pipe++;
631 Remaining -= sizeof(*Pipe);
632 }
633 }
634
635 Information = OutputLength - Remaining;
636 }
637
638 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
640
642}
643
644static
645VOID
646NTAPI
648 _In_ HubFdo* Hub,
649 _In_ WDFREQUEST Request,
650 _In_ size_t OutputLength,
651 _In_ size_t InputLength)
652{
656 WDFSTRING String;
657 PWCHAR Text;
658 ULONG TextBytes;
659 ULONG Index;
660 HubPdo* Pdo;
663
664 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_NAME_SIZE, OutputLength, (PVOID*)&Name);
665 if (!NT_SUCCESS(Status))
666 {
667 WdfRequestComplete(Request, Status);
668 return;
669 }
670
671 Index = Name->ConnectionIndex;
672
674 Child = (Pdo != NULL) ? Pdo->m_Child : NULL;
675 if (Child == NULL || !Child->HasProperty(ChildProperty::IsHub))
676 {
677 /* QUIRK: the rest of the buffer is left as the caller sent it */
679 Name->ActualLength = HUB_IO_NAME_SIZE;
680 Name->NodeName[0] = UNICODE_NULL;
682 return;
683 }
684
685 RtlZeroMemory(Name, OutputLength);
686 Name->ConnectionIndex = Index;
687
689 Attributes.ParentObject = Pdo->m_Device;
690
691 Status = WdfStringCreate(NULL, &Attributes, &String);
692 if (NT_SUCCESS(Status))
693 {
694 Status = WdfDeviceRetrieveDeviceInterfaceString(Pdo->m_Device, &GUID_DEVINTERFACE_USB_HUB, NULL, String);
695 if (!NT_SUCCESS(Status))
697 }
698
700
701 if (!NT_SUCCESS(Status))
702 {
703 DPRINT1("Hub %p connection name of port %lu failed 0x%lx\n", Hub, Index, Status);
704 WdfRequestComplete(Request, Status);
705 return;
706 }
707
709 Text = HubIoStripLinkPrefix(&Path, &TextBytes);
710 Name->ActualLength = TextBytes + HUB_IO_NAME_SIZE;
711
712 if (TextBytes <= OutputLength - HUB_IO_NAME_HEADER)
713 {
714 RtlCopyMemory(Name->NodeName, Text, TextBytes);
715
716 /* ActualLength can exceed the caller's buffer by two bytes */
717 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, min((size_t)Name->ActualLength, OutputLength));
718 }
719 else
720 {
721 Name->NodeName[0] = UNICODE_NULL;
723 }
724
726}
727
728static
729VOID
730NTAPI
732 _In_ HubFdo* Hub,
733 _In_ WDFQUEUE Queue,
734 _In_ WDFREQUEST Request,
735 _In_ size_t OutputLength,
736 _In_ size_t InputLength)
737{
739 struct _URB_CONTROL_TRANSFER_EX* Urb;
742 ULONG SerialBytes;
744 ULONG Size = 0;
745 UCHAR Type;
746 UCHAR Index;
747 HubPdo* Pdo;
750
751 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_DESCRIPTOR_HEADER + 1, OutputLength, (PVOID*)&Descriptor);
752 if (!NT_SUCCESS(Status))
753 {
755 return;
756 }
757
758 DataLength = (ULONG)(OutputLength - HUB_IO_DESCRIPTOR_HEADER);
760
761 Pdo = HubIoLockChild(Hub, (USHORT)Descriptor->ConnectionIndex);
762 Child = (Pdo != NULL) ? Pdo->m_Child : NULL;
763 if (Child == NULL || !Child->HasState(ChildState::WorkingDevice))
764 {
766 DPRINT1("Hub %p descriptor request: no known device on port %lu\n", Hub, Descriptor->ConnectionIndex);
768 return;
769 }
770
771 /* Only a standard GET_DESCRIPTOR goes through, whatever the caller asked */
772 Descriptor->SetupPacket.bmRequest = (BMREQUEST_DEVICE_TO_HOST << 7) | (BMREQUEST_STANDARD << 5) | BMREQUEST_TO_DEVICE;
773 Descriptor->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
774
775 Type = HIBYTE(Descriptor->SetupPacket.wValue);
776 Index = LOBYTE(Descriptor->SetupPacket.wValue);
777
778 DPRINT("Hub %p descriptor request port %lu type %u index %u\n", Hub, Descriptor->ConnectionIndex, Type, Index);
779
780 switch (Type)
781 {
783 Size = min((ULONG)sizeof(Child->m_DeviceDescriptor), DataLength);
784 RtlCopyMemory(Descriptor->Data, &Child->m_DeviceDescriptor, Size);
785 goto Cached;
786
788 if (Child->m_ConfigDescriptor == NULL || Index != 0)
789 break;
790
791 Size = min((ULONG)Child->m_ConfigDescriptor->wTotalLength, DataLength);
792 RtlCopyMemory(Descriptor->Data, Child->m_ConfigDescriptor, Size);
793 goto Cached;
794
796 if (Child->m_Bos == NULL)
797 break;
798
799 Size = min((ULONG)Child->m_Bos->wTotalLength, DataLength);
800 RtlCopyMemory(Descriptor->Data, Child->m_Bos, Size);
801 goto Cached;
802
804 if (Index == 0 ||
805 Index != Child->m_DeviceDescriptor.iSerialNumber ||
806 Descriptor->SetupPacket.wIndex != HUB_LANGID_US_ENGLISH)
807 {
808 break;
809 }
810
811 if (!HubIdGetSerialNumberText(Child, &Serial, &SerialBytes))
812 {
814 DPRINT1("Hub %p device %p has no stored serial number\n", Hub, Child);
816 return;
817 }
818
819 /* QUIRK: answered from the cache, without the MSFT decoration */
820 Size = min(SerialBytes + (ULONG)sizeof(WCHAR), DataLength);
821 if (Size > Descriptor->SetupPacket.wLength)
822 break;
823
824 Descriptor->Data[0] = (UCHAR)Size;
825 if (Size >= sizeof(WCHAR))
826 {
828 RtlCopyMemory(&Descriptor->Data[2], Serial, Size - sizeof(WCHAR));
829 }
830 goto Cached;
831
832 default:
833 break;
834 }
835
836 /* Never ask the device for more than the caller's buffer holds */
837 if (Descriptor->SetupPacket.wLength > DataLength)
838 Descriptor->SetupPacket.wLength = (USHORT)DataLength;
839
840 Urb = &HubGetQueueContext(Queue)->Urb;
841 RtlZeroMemory(Urb, sizeof(*Urb));
842 RtlCopyMemory(Urb->SetupPacket, &Descriptor->SetupPacket, sizeof(Urb->SetupPacket));
843 Urb->Hdr.Length = sizeof(*Urb);
844 Urb->Hdr.Function = URB_FUNCTION_CONTROL_TRANSFER_EX;
845 Urb->Hdr.UsbdDeviceHandle = Child->m_UsbDevice;
847 Urb->TransferBufferLength = DataLength;
848 Urb->TransferBuffer = Descriptor->Data;
850
851 /* Dropped by HubCompleteFdoDescriptorRequest */
854
855 RtlZeroMemory(&Stack, sizeof(Stack));
857 Stack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
858 Stack.Parameters.Others.Argument1 = Urb;
859 WdfRequestWdmFormatUsingStackLocation(Request, &Stack);
860
861 Child->m_FdoRequest = Request;
863 return;
864
865Cached:
868}
869
870static
871VOID
872NTAPI
874 _In_ HubFdo* Hub,
875 _In_ WDFREQUEST Request,
876 _In_ size_t OutputLength,
877 _In_ size_t InputLength,
878 _In_ BOOLEAN Extended)
879{
880 PUSB_HUB_CAP_FLAGS Caps;
883
884 Status = HubIoPrepare(Hub, Request, 0, InputLength, sizeof(*Caps), OutputLength, (PVOID*)&Caps);
885 if (NT_SUCCESS(Status))
886 {
887 RtlZeroMemory(Caps, OutputLength);
889
890 if (!Extended)
891 {
892 ((PUSB_HUB_CAPABILITIES)Caps)->HubIs2xCapable = HighSpeedCapable;
893 }
894 else
895 {
896 Caps->HubIsBusPowered = (Hub->m_MaxPortPower == HUB_BUS_POWERED_PORT_POWER);
897 Caps->HubIsHighSpeedCapable = HighSpeedCapable;
898 Caps->HubIsHighSpeed = Hub->IsRootHub() || Hub->m_Parent.HubSpeed == UsbHighSpeed;
899 Caps->HubIsMultiTtCapable = Hub->HasFlag(HubFlag::MultiTtHub);
900 Caps->HubIsMultiTt = Hub->HasFlag(HubFlag::MultiTtHub);
901 Caps->HubIsRoot = Hub->IsRootHub();
902 Caps->HubIsArmedWakeOnConnect = Hub->HasFlag(HubFlag::WakeOnConnect);
903 }
904 }
905
906 /* QUIRK: the size is reported on failure too */
908}
909
910static
911VOID
912NTAPI
914 _In_ HubFdo* Hub,
915 _In_ WDFREQUEST Request,
916 _In_ size_t OutputLength,
917 _In_ size_t InputLength)
918{
919 PUSB_NODE_CONNECTION_ATTRIBUTES Attributes;
921 HubPort* Port;
923
924 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_ATTRIBUTES_SIZE, OutputLength, (PVOID*)&Attributes);
925 if (NT_SUCCESS(Status))
926 {
927 PortNumber = (USHORT)Attributes->ConnectionIndex;
928 RtlZeroMemory(Attributes, OutputLength);
929
931 Attributes->ConnectionIndex = PortNumber;
932 Attributes->PortAttributes = 0;
933 Attributes->ConnectionStatus = (Port != NULL) ? Port->m_ConnectionStatus : DeviceGeneralFailure;
934 }
935
937}
938
939static
940VOID
941NTAPI
943 _In_ HubFdo* Hub,
944 _In_ WDFREQUEST Request,
945 _In_ size_t OutputLength,
946 _In_ size_t InputLength)
947{
950
951 Status = HubIoPrepare(Hub, Request, 0, InputLength, HUB_IO_HUB_INFO_EX_SIZE, OutputLength, (PVOID*)&Info);
952 if (NT_SUCCESS(Status))
953 {
954 RtlZeroMemory(Info, OutputLength);
955 Info->HighestPortNumber = (USHORT)Hub->m_PortCount;
956
957 if (Hub->IsRootHub())
958 {
959 Info->HubType = UsbRootHub;
960 }
961 else if (Hub->m_Parent.HubSpeed == UsbSuperSpeed)
962 {
963 Info->HubType = Usb30Hub;
964 RtlCopyMemory(&Info->u.Usb30HubDescriptor, &Hub->m_HubDescriptor.Usb30, sizeof(USB_30_HUB_DESCRIPTOR));
965 }
966 else
967 {
968 Info->HubType = Usb20Hub;
969 RtlCopyMemory(&Info->u.UsbHubDescriptor, &Hub->m_HubDescriptor.Usb20, sizeof(USB_HUB_DESCRIPTOR));
970 }
971 }
972
974}
975
976static
977VOID
978NTAPI
980 _In_ HubFdo* Hub,
981 _In_ WDFREQUEST Request,
982 _In_ size_t OutputLength,
983 _In_ size_t InputLength)
984{
987 USHORT CompanionIndex;
988 HubPort* Port;
990 PWCHAR Text;
991 ULONG TextBytes;
995
996 /* The minimum input covers the companion index, so the port number is checked too */
997 Status = HubIoPrepare(Hub, Request, HUB_IO_CONNECTOR_SIZE, InputLength, HUB_IO_CONNECTOR_SIZE, OutputLength, (PVOID*)&Props);
998 if (!NT_SUCCESS(Status))
999 {
1000 WdfRequestComplete(Request, Status);
1001 return;
1002 }
1003
1005 CompanionIndex = Props->CompanionIndex;
1006
1007 RtlZeroMemory(Props, OutputLength);
1008 Props->ConnectionIndex = PortNumber;
1009 Props->CompanionIndex = CompanionIndex;
1011
1013 if (Port == NULL)
1014 {
1015 DPRINT1("Hub %p connector properties: no port %u\n", Hub, PortNumber);
1017 return;
1018 }
1019
1020 Connector = Port->m_AcpiUpc.ConnectorType;
1027
1028 if (CompanionIndex > 1)
1029 {
1031 return;
1032 }
1033
1034 HubConnectorLock();
1035
1036 Companion = HubConnectorFindCompanion(Port, CompanionIndex);
1037 if (Companion != NULL)
1038 {
1039 Props->CompanionPortNumber = Companion->Number();
1040
1041 Text = HubIoStripLinkPrefix(&Companion->m_Hub->m_SymbolicLinkName, &TextBytes);
1042 if (Text != NULL)
1043 {
1044 Props->ActualLength = TextBytes + HUB_IO_CONNECTOR_SIZE;
1045 if (OutputLength - HUB_IO_CONNECTOR_SIZE >= TextBytes)
1046 {
1048
1049 /* QUIRK: the whole output length, not ActualLength */
1050 Information = OutputLength;
1051 }
1052 }
1053 }
1054
1055 HubConnectorUnlock();
1056
1058}
1059
1060static
1061VOID
1062NTAPI
1064 _In_ HubFdo* Hub,
1065 _In_ WDFREQUEST Request,
1066 _In_ size_t OutputLength,
1067 _In_ size_t InputLength)
1068{
1072 HubPort* Port;
1073 HubPdo* Pdo;
1074 HubChild* Child;
1076
1079 {
1080 DPRINT1("Hub %p connection information V2 length %lu too small\n", Hub, Info->Length);
1082 }
1083
1084 if (!NT_SUCCESS(Status))
1085 {
1086 WdfRequestComplete(Request, Status);
1087 return;
1088 }
1089
1090 PortNumber = (USHORT)Info->ConnectionIndex;
1091 Wanted = Info->SupportedUsbProtocols;
1092
1093 RtlZeroMemory(Info, OutputLength);
1094 Info->ConnectionIndex = PortNumber;
1095
1096 if (!Wanted.Usb300)
1097 {
1098 DPRINT1("Hub %p connection information V2 caller does not claim USB 3\n", Hub);
1099 WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
1100 return;
1101 }
1102
1104
1106 if (Port == NULL)
1107 {
1108 DPRINT1("Hub %p connection information V2: no port %u\n", Hub, PortNumber);
1110 return;
1111 }
1112
1113 if (Port->IsUsb30())
1114 {
1115 Info->SupportedUsbProtocols.Usb300 = 1;
1116 }
1117 else
1118 {
1119 Info->SupportedUsbProtocols.Usb110 = 1;
1121 Info->SupportedUsbProtocols.Usb200 = 1;
1122 }
1123
1125 Child = (Pdo != NULL) ? Pdo->m_Child : NULL;
1126 if (Child != NULL)
1127 {
1128 Info->Flags.DeviceIsSuperSpeedCapableOrHigher = (Child->m_SqmFlags & (LONG)ChildSqm::SuperSpeedCapable) != 0;
1129 Info->Flags.DeviceIsSuperSpeedPlusCapableOrHigher = HubIoDeviceSspCapable(Child);
1130
1131 if (Port->IsUsb30())
1132 {
1133 Info->Flags.DeviceIsOperatingAtSuperSpeedOrHigher = 1;
1134 Info->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher = HubIoDeviceRunsSsp(Child);
1135 }
1136 }
1137
1139
1141}
1142
1143static
1144VOID
1145NTAPI
1147 _In_ HubFdo* Hub,
1148 _In_ WDFREQUEST Request,
1149 _In_ size_t OutputLength,
1150 _In_ size_t InputLength)
1151{
1152 PUSB_CYCLE_PORT_PARAMS Params;
1153 BOOLEAN UxdUpdate = FALSE;
1154 HubPdo* Pdo;
1155 HubChild* Child;
1156 NTSTATUS IdleStatus;
1158
1159 Status = HubIoPrepare(Hub, Request, sizeof(ULONG), InputLength, HUB_IO_CYCLE_SIZE, OutputLength, (PVOID*)&Params);
1160 if (!NT_SUCCESS(Status))
1161 goto Exit;
1162
1163 Params->StatusReturned = USBD_STATUS_SUCCESS;
1164
1165 Pdo = HubIoLockChild(Hub, (USHORT)Params->ConnectionIndex);
1166 Child = (Pdo != NULL) ? Pdo->m_Child : NULL;
1167 if (Child == NULL)
1168 {
1170 DPRINT1("Hub %p cycle: no device on port %lu\n", Hub, Params->ConnectionIndex);
1171 Params->StatusReturned = USBD_STATUS_DEVICE_GONE;
1173 goto Exit;
1174 }
1175
1176 HubSaveUxdState(Hub, Child, &UxdUpdate);
1177
1180
1181 /* QUIRK: a non admin caller with a UXD update cycles the port but still fails */
1182 Status = HubIoCallerIsAdmin();
1183 if (!NT_SUCCESS(Status))
1184 DPRINT1("Hub %p cycle of port %lu: caller is not an administrator\n", Hub, Params->ConnectionIndex);
1185
1186 if (NT_SUCCESS(Status) || UxdUpdate)
1187 {
1188 IdleStatus = WdfDeviceStopIdle(Hub->m_Device, TRUE);
1189 if (!NT_SUCCESS(IdleStatus))
1190 {
1191 DPRINT1("Hub %p cycle of port %lu: stop idle failed 0x%lx\n", Hub, Params->ConnectionIndex, IdleStatus);
1192 Status = IdleStatus;
1193 }
1194 else
1195 {
1196 DPRINT("Hub %p cycling port %lu\n", Hub, Params->ConnectionIndex);
1197
1198 /* One queued cycle is enough */
1199 if (InterlockedCompareExchange(&Pdo->m_CycleQueued, 1, 0) == 0)
1200 Child->m_Port->Post(PortEvent::CycleRequest);
1201
1203 }
1204 }
1205
1207
1208Exit:
1210}
1211
1212static
1213VOID
1214NTAPI
1216 _In_ HubFdo* Hub,
1217 _In_ WDFREQUEST Request)
1218{
1220
1221 Status = HubIoCallerIsAdmin();
1224
1225 if (NT_SUCCESS(Status))
1226 DPRINT("Hub %p reset request queued\n", Hub);
1227 else
1228 DPRINT1("Hub %p reset request not done 0x%lx\n", Hub, Status);
1229
1230 /* QUIRK: success whatever happened */
1231 WdfRequestComplete(Request, STATUS_SUCCESS);
1232}
1233
1234/* Queue callbacks */
1235
1236VOID
1237NTAPI
1239 _In_ WDFQUEUE Queue,
1240 _In_ WDFREQUEST Request,
1241 _In_ size_t OutputBufferLength,
1242 _In_ size_t InputBufferLength,
1244{
1245 HubFdo* Hub = HubFdo::FromDevice(WdfIoQueueGetDevice(Queue));
1246
1247 PAGED_CODE();
1248
1249 switch (IoControlCode)
1250 {
1253 break;
1254
1257 break;
1258
1261 break;
1262
1263 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
1265 break;
1266
1269 break;
1270
1273 break;
1274
1277 break;
1278
1279 case IOCTL_USB_GET_HUB_CAPABILITIES:
1281 break;
1282
1283 case IOCTL_USB_GET_HUB_CAPABILITIES_EX:
1285 break;
1286
1287 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
1289 break;
1290
1291 case IOCTL_USB_HUB_CYCLE_PORT:
1293 break;
1294
1295 case IOCTL_USB_RESET_HUB:
1297 break;
1298
1301 break;
1302
1305 break;
1306
1309 break;
1310
1311 default:
1313 break;
1314 }
1315}
1316
1317/* A child PDO forwards its client's port status request here and waits for it */
1318VOID
1319NTAPI
1321 _In_ WDFQUEUE Queue,
1322 _In_ WDFREQUEST Request,
1323 _In_ size_t OutputBufferLength,
1324 _In_ size_t InputBufferLength,
1326{
1327 HubFdo* Hub = HubFdo::FromDevice(WdfIoQueueGetDevice(Queue));
1329 HubPdo* Pdo;
1330 HubPort* Port;
1331
1334
1336 {
1337 /* QUIRK: not passed down */
1338 DPRINT1("Hub %p unexpected internal IOCTL 0x%lx\n", Hub, IoControlCode);
1339 WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
1340 return;
1341 }
1342
1344 WdfRequestGetParameters(Request, &Params);
1345
1346 Pdo = (HubPdo*)Params.Parameters.Others.Arg2;
1347 Port = (Pdo->m_Child != NULL) ? Pdo->m_Child->m_Port : NULL;
1348 if (Port == NULL)
1349 {
1350 DPRINT1("Hub %p port status for PDO %p without a device\n", Hub, Pdo);
1351 *(PULONG)Params.Parameters.Others.Arg1 = 0;
1352 WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
1353 return;
1354 }
1355
1359}
1360
1361/* Diagnostics */
1362
1364VOID
1365NTAPI
1366HubReportPnpProblem(
1367 _In_ WDFDEVICE Device,
1369{
1370 PAGED_CODE();
1371
1372 /* The problem is only logged; DEVPKEY_Device_DriverProblemDesc is not set */
1373 if (MessageId != 0)
1374 DPRINT1("Hub device %p problem 0x%lx\n", Device, MessageId);
1375}
#define PAGED_CODE()
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
HubFdo * Hub
Definition: bootdev.cpp:261
Definition: bufpool.h:45
VOID FailHubDescriptorRequest()
Definition: hubioctl.cpp:383
HubChild * m_Device
Definition: devsm.h:1832
WDFREQUEST m_FdoRequest
Definition: hubchild.h:366
Definition: fdo.h:132
WDFDEVICE m_Device
Definition: fdo.h:349
USB_HUB_DESCRIPTOR Usb20
Definition: fdo.h:419
WDFREQUEST m_PortStatusRequest
Definition: fdo.h:392
ULONG m_PortCount
Definition: fdo.h:379
VOID Post(_In_ HubEvent Event)
Definition: fdo.h:194
BOOLEAN HasFlag(_In_ HubFlag Flag) const
Definition: fdo.h:153
BOOLEAN RequestHubReset()
Definition: fanout.cpp:452
static HubFdo * FromDevice(_In_ WDFDEVICE Device)
Definition: fdo.cpp:37
HubPort * m_PortStatusTarget
Definition: fdo.h:393
HubParentInfo m_ParentInfo
Definition: fdo.h:360
USB_30_HUB_DESCRIPTOR Usb30
Definition: fdo.h:420
ULONG m_MaxPortPower
Definition: fdo.h:384
UCXHUB_PARENT_INTERFACE m_Parent
Definition: fdo.h:355
BOOLEAN IsRootHub() const
Definition: fdo.h:174
union HubFdo::@1628 m_HubDescriptor
HubPort * FindPort(_In_ ULONG PortNumber)
Definition: fanout.cpp:42
HubChild * m_Child
Definition: childpdo.h:57
_Out_ PKIRQL Irql
Definition: csq.h:179
PUCHAR End
Definition: desccheck.cpp:2229
PUCHAR Cursor
Definition: desccheck.cpp:2228
LPWSTR Name
Definition: desk.c:124
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
@ Connector
VOID NTAPI HubCompleteFdoDescriptorRequest(_In_ HubChild *Child, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG Size)
Definition: hubioctl.cpp:372
@ HubGetDescriptor
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG DataLength
Definition: dispmprt.h:233
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define L(x)
Definition: resources.c:13
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
int Fail
Definition: ehthrow.cxx:24
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
Status
Definition: gdiplustypes.h:24
CPPORT Port[4]
Definition: headless.c:38
@ SuperSpeedCapable
@ ConfigurationValid
HubSaveUxdState(Child->m_Hub, Child, NULL)
BOOLEAN NTAPI HubIdGetSerialNumberText(_In_ HubChild *Child, _Outptr_result_bytebuffer_(*Length) PCWSTR *Text, _Out_ PULONG Length)
Definition: hubid.cpp:1111
static VOID NTAPI HubIoGetConnectionAttributes(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:913
#define HUB_IO_NAME_SIZE
Definition: hubioctl.cpp:26
#define HUB_IO_CONNECTION_SIZE
Definition: hubioctl.cpp:24
#define HUB_LANGID_US_ENGLISH
Definition: hubioctl.cpp:55
#define HUB_IO_DESCRIPTOR_HEADER
Definition: hubioctl.cpp:27
static VOID NTAPI HubIoGetConnectorProperties(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:979
static VOID NTAPI HubIoForward(_In_ HubFdo *Hub, _In_ WDFREQUEST Request)
Definition: hubioctl.cpp:235
static VOID NTAPI HubIoGetConnectionName(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:647
#define HUB_UPC_TYPE_C_USB2
Definition: hubioctl.cpp:50
static VOID NTAPI HubIoGetHubInformationEx(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:942
static VOID NTAPI HubIoGetPortStatus(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:398
static HubPdo *NTAPI HubIoLockChild(_In_ HubFdo *Hub, _In_ USHORT PortNumber)
Definition: hubioctl.cpp:204
VOID NTAPI HubCompleteFdoDescriptorRequest(_In_ HubChild *Child, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG Size)
Definition: hubioctl.cpp:372
#define HUB_IO_CONNECTION_V2_SIZE
Definition: hubioctl.cpp:31
_In_ ULONG MessageId
Definition: hubioctl.cpp:1369
static PWCHAR NTAPI HubIoStripLinkPrefix(_In_ PCUNICODE_STRING Link, _Out_ PULONG Bytes)
Definition: hubioctl.cpp:100
#define HUB_IO_NAME_HEADER
Definition: hubioctl.cpp:25
#define HUB_UPC_TYPE_C_SWITCH
Definition: hubioctl.cpp:51
static VOID NTAPI HubIoResetHub(_In_ HubFdo *Hub, _In_ WDFREQUEST Request)
Definition: hubioctl.cpp:1215
static NTSTATUS NTAPI HubIoValidate(_In_ HubFdo *Hub, _In_ size_t MinInput, _In_ size_t InputLength, _In_opt_ PVOID Buffer, _In_ size_t MinOutput, _In_ size_t OutputLength)
Definition: hubioctl.cpp:133
#define HUB_BUS_POWERED_PORT_POWER
Definition: hubioctl.cpp:47
static BOOLEAN NTAPI HubIoDeviceRunsSsp(_In_ HubChild *Child)
Definition: hubioctl.cpp:339
#define HUB_IO_NODE_INFO_SIZE
Definition: hubioctl.cpp:23
static VOID NTAPI HubIoCompleteDescriptor(_In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG Size)
Definition: hubioctl.cpp:359
static VOID NTAPI HubIoGetConnectionInformation(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength, _In_ BOOLEAN Extended)
Definition: hubioctl.cpp:542
static VOID NTAPI HubIoGetNodeInformation(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:437
#define HUB_UPC_TYPE_C_NO_SWITCH
Definition: hubioctl.cpp:52
static const char HubTagUserRequest[]
Definition: hubioctl.cpp:67
#define HUB_IO_CYCLE_SIZE
Definition: hubioctl.cpp:32
static BOOLEAN NTAPI HubIoDeviceSspCapable(_In_ HubChild *Child)
Definition: hubioctl.cpp:319
static VOID NTAPI HubIoGetConnectionInformationV2(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:1063
static VOID NTAPI HubIoGetDriverKeyName(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:469
static VOID NTAPI HubIoCyclePort(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:1146
static VOID NTAPI HubIoGetHubCapabilities(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength, _In_ BOOLEAN Extended)
Definition: hubioctl.cpp:873
NTKERNELAPI BOOLEAN NTAPI SeTokenIsAdmin(_In_ PACCESS_TOKEN Token)
Determines if a token is either an admin token or not. Such condition is checked based upon TOKEN_HAS...
Definition: token.c:2104
static VOID NTAPI HubIoGetDescriptor(_In_ HubFdo *Hub, _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputLength, _In_ size_t InputLength)
Definition: hubioctl.cpp:731
static VOID NTAPI HubIoUnlockChildren(_In_ HubFdo *Hub)
Definition: hubioctl.cpp:226
#define HUB_IO_ATTRIBUTES_SIZE
Definition: hubioctl.cpp:28
#define HUB_IO_HUB_INFO_EX_SIZE
Definition: hubioctl.cpp:29
#define HUB_IO_CONNECTOR_SIZE
Definition: hubioctl.cpp:30
static NTSTATUS NTAPI HubIoPrepare(_In_ HubFdo *Hub, _In_ WDFREQUEST Request, _In_ size_t MinInput, _In_ size_t InputLength, _In_ size_t MinOutput, _In_ size_t OutputLength, _Outptr_result_maybenull_ PVOID *Buffer)
Definition: hubioctl.cpp:178
static VOID NTAPI HubIoBuild20Descriptor(_In_ HubFdo *Hub, _Out_ PUSB_HUB_DESCRIPTOR Descriptor)
Definition: hubioctl.cpp:255
static BOOLEAN NTAPI HubIoPortSpeedIsPlus(_In_ HubPort *Port, _In_ ULONG SpeedId, _In_ ULONG Direction)
Definition: hubioctl.cpp:297
ULONG Returned
UNICODE_STRING Path
#define HUB_SETUP_REQUEST_TIMEOUT_MS
Definition: hubreq.h:11
@ PortStatusRequest
HubPort *NTAPI HubConnectorFindCompanion(_In_ HubPort *Port, _In_ ULONG Index)
Definition: portconn.cpp:287
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
_Must_inspect_result_ _In_ UCXUSBDEVICE _In_ ULONG _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR Companion
Definition: hubucx.h:308
_In_ ULONG PortNumber
Definition: hubucx.h:272
_In_ UCXUSBDEVICE _In_ PDEVICE_OBJECT Pdo
Definition: hubucx.h:280
WdfFdoLockStaticChildListForIteration(Hub->m_Device)
WdfFdoUnlockStaticChildListFromIteration(Hub->m_Device)
#define InterlockedCompareExchange
Definition: interlocked.h:119
_In_ ULONG Wanted
Definition: intr.cpp:782
#define C_ASSERT(e)
Definition: intsafe.h:73
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
if(dx< 0)
Definition: linetemp.h:194
_In_ UINT Bytes
Definition: mmcopy.h:9
#define min(a, b)
Definition: monoChain.cc:55
_In_ ULONG _In_ BOOLEAN Cached
Definition: ndis.h:3789
#define _Outptr_result_maybenull_
Definition: no_sal2.h:266
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:603
ULONG64 Serial
Definition: rhubpdo.cpp:335
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
static void Exit(void)
Definition: sock.c:1330
ULONG Flags
Definition: fdo.h:100
ULONG ConnectionIndex
Definition: hubioctl.cpp:60
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PACCESS_TOKEN ClientToken
Definition: setypes.h:218
PACCESS_TOKEN PrimaryToken
Definition: setypes.h:220
USB_DEVICE_SPEED HubSpeed
Definition: hubucx.h:504
UCHAR bPowerOnToPowerGood
Definition: usb300.h:289
USHORT wHubCharacteristics
Definition: usb300.h:288
UCHAR bHubControlCurrent
Definition: usb300.h:290
USB_PORT_PROPERTIES UsbPortProperties
Definition: usbioctl.h:719
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:107
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: subject.c:171
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:138
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
_In_ PGUID _In_ ULONG OutputBufferLength
Definition: ucxcontroller.h:81
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
_In_ UCXUSBDEVICE _In_ ULONG Interface
Definition: ucxusbdevice.h:428
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
ULONG RxSublinkSpeedID
Definition: usb300.h:299
ULONG PortIsUserConnectable
Definition: usbioctl.h:703
ULONG PortConnectorIsTypeC
Definition: usbioctl.h:706
ULONG PortIsDebugCapable
Definition: usbioctl.h:704
ULONG PortHasMultipleCompanions
Definition: usbioctl.h:705
#define BMREQUEST_TO_DEVICE
Definition: usb100.h:38
#define USB_REQUEST_GET_DESCRIPTOR
Definition: usb100.h:82
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usb100.h:50
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usb100.h:49
#define USB_STRING_DESCRIPTOR_TYPE
Definition: usb100.h:51
#define BMREQUEST_STANDARD
Definition: usb100.h:34
#define BMREQUEST_DEVICE_TO_HOST
Definition: usb100.h:32
@ UsbSuperSpeed
Definition: usb200.h:45
@ UsbHighSpeed
Definition: usb200.h:44
@ UsbLowSpeed
Definition: usb200.h:42
@ UsbFullSpeed
Definition: usb200.h:43
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
#define USB_20_HUB_DESCRIPTOR_TYPE
Definition: usb200.h:280
#define USB_BOS_DESCRIPTOR_TYPE
Definition: usb300.h:17
#define USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED_DIR_RX
Definition: usb300.h:59
#define USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED_PROTOCOL_SS
Definition: usb300.h:61
#define USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED_DIR_TX
Definition: usb300.h:60
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL HubEvtIoInternalDeviceControl
Definition: fdo.h:550
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL HubEvtIoDeviceControl
Definition: fdo.h:549
@ WakeOnConnect
#define HUB_PARENT_HIGH_SPEED_CAPABLE
Definition: fdo.h:107
#define USBD_STATUS_DEVICE_GONE
Definition: usb.h:222
#define USBD_STATUS_SUCCESS
Definition: usb.h:177
#define USBD_TRANSFER_DIRECTION_IN
Definition: usb.h:167
#define USBD_SHORT_TRANSFER_OK
Definition: usb.h:161
#define USBD_DEFAULT_PIPE_TRANSFER
Definition: usb.h:163
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
Definition: usbdlib.h:333
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
#define IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES
Definition: usbioctl.h:678
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2
Definition: usbioctl.h:681
#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
Definition: usbioctl.h:175
#define IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
Definition: usbioctl.h:187
struct _USB_NODE_CONNECTION_INFORMATION * PUSB_NODE_CONNECTION_INFORMATION
#define IOCTL_USB_GET_HUB_INFORMATION_EX
Definition: usbioctl.h:675
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
Definition: usbioctl.h:172
#define IOCTL_USB_GET_NODE_INFORMATION
Definition: usbioctl.h:169
#define IOCTL_USB_GET_NODE_CONNECTION_NAME
Definition: usbioctl.h:178
#define IOCTL_USB_GET_PORT_STATUS
Definition: usbioctl.h:672
@ DeviceGeneralFailure
Definition: usbioctl.h:281
@ UsbRootHub
Definition: usbioctl.h:685
@ Usb20Hub
Definition: usbioctl.h:686
@ Usb30Hub
Definition: usbioctl.h:687
@ UsbHub
Definition: usbioctl.h:219
#define IOCTL_INTERNAL_USB_GET_PORT_STATUS
Definition: usbioctl.h:44
UNICODE_STRING Text
Definition: userreq.cpp:261
WdfObjectDelete(String)
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, ActualLength)
WdfStringGetUnicodeString(Original, &Name)
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
@ WdfRetrievePresentChildren
Definition: wdfchildlist.h:61
_In_ WDFCOLLECTION _In_ ULONG Index
#define WdfDeviceStopIdle(Device, WaitForD0)
Definition: wdfdevice.h:1977
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2231
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3540
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
#define WdfDeviceResumeIdle(Device)
Definition: wdfdevice.h:1983
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION Direction
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
#define WdfObjectDereferenceWithTag(Handle, Tag)
Definition: wdfobject.h:829
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define WdfObjectReferenceWithTag(Handle, Tag)
Definition: wdfobject.h:806
_Must_inspect_result_ FORCEINLINE BOOLEAN WdfRequestSend(_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_opt_ PWDF_REQUEST_SEND_OPTIONS Options)
Definition: wdfrequest.h:677
FORCEINLINE VOID WDF_REQUEST_SEND_OPTIONS_INIT(_Out_ PWDF_REQUEST_SEND_OPTIONS Options, _In_ ULONG Flags)
Definition: wdfrequest.h:409
@ WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET
Definition: wdfrequest.h:111
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_In_ WDFUSBPIPE Pipe
Definition: wdfusb.h:1741
#define NTKERNELAPI
@ DevicePropertyDriverKeyName
Definition: iotypes.h:1202
#define IRP_MJ_INTERNAL_DEVICE_CONTROL