ReactOS 0.4.17-dev-1281-g065abb3
hubmsos.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: MS OS 1.0 and 2.0 descriptor decisions and their registry installs
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9#include "hubregistry.h"
10
11#define NDEBUG
12#include <debug.h>
13
14/* MS OS string descriptor bFlags: the container ID feature descriptor exists */
15#define MSOS_FLAG_CONTAINER_ID 0x02
16
17/* Extended properties feature descriptor */
18#define MSOS_EXT_PROPERTIES_INDEX 5
19#define MSOS_EXT_PROPERTIES_VERSION 0x0100
20#define MSOS_EXT_PROPERTIES_MAX 4096
21
22/* MS OS 2.0 registry property descriptor type */
23#define MSOS20_TYPE_REGISTRY_PROPERTY 4
24
25#include <pshpack1.h>
26
27/* Extended properties header, followed by Count custom properties */
29{
34};
35
36/* One custom property; the name, a ULONG data length and the data follow */
38{
42};
43
44#include <poppack.h>
45
48
49/* Size, type, name length and data length */
50#define MSOS_CUSTOM_PROPERTY_FIXED (sizeof(HubMsOsCustomProperty) + sizeof(ULONG))
51
52/* Version gate shared by the MS OS 1.0 queries: USB 2.0 and later, or no version at all */
53static
58{
59 USHORT BcdUsb = Child->m_DeviceDescriptor.bcdUSB;
60
61 return BcdUsb >= 0x0200 || BcdUsb < 0x0100;
62}
63
64static
69{
70 return (Child->m_MsOs20.Flags & HUB_MSOS20_SET_INFO) != 0;
71}
72
73static
78{
79 return (const HubMsOsExtPropHeader*)Child->m_ScratchBuffer;
80}
81
82/* MS OS 2.0 */
83
84/* Every errata, property and state bit except the alternate enumeration ones is dropped; the registry query runs again afterwards */
87{
88 const LONG Keep = (LONG)ChildState::AltEnumCompleted | (LONG)ChildState::AltEnumCommandSent;
89
90 if (!m_Device->m_AltEnumCached || m_Device->HasState(ChildState::AltEnumCommandSent))
91 return FALSE;
92
93 m_Device->SetState(ChildState::AltEnumCompleted);
95
96 m_Device->m_Hacks = 0;
99
100 return TRUE;
101}
102
105{
107 !m_Device->HasState(ChildState::AltEnumCommandSent);
108}
109
112{
114 return FALSE;
115
116 m_Device->SetState(ChildState::AltEnumCompleted);
117 return TRUE;
118}
119
122{
124}
125
128{
130 return FALSE;
131
132 return !m_Device->HasProperty(ChildProperty::ExtPropertiesInstalled);
133}
134
135/* One registry property descriptor of the set into the hardware key */
137static
139NTAPI
140HubInstallMsOs20Property(
143{
144 const UCHAR* Name = (const UCHAR*)(Property + 1);
145 const UCHAR* Tail = Name + Property->wPropertyNameLength;
148
150
151 /* The descriptor counts the NUL; the value name must not */
153 ValueName.Length = 0;
154 while (ValueName.Length < Property->wPropertyNameLength &&
155 ValueName.Buffer[ValueName.Length / sizeof(WCHAR)] != UNICODE_NULL)
156 {
157 ValueName.Length += sizeof(WCHAR);
158 }
159 ValueName.MaximumLength = ValueName.Length;
160
162 &ValueName,
163 Property->wPropertyDataType,
165 (PVOID)(Tail + sizeof(DataLength)));
166}
167
168/* Only top level properties are installed; a failed write stops the walk but still answers TRUE */
171{
173 const HubMsOs20SetHeader* Header = (const HubMsOs20SetHeader*)Child->m_MsOs20Set;
176 PUCHAR End;
178
179 PAGED_CODE();
180
181 if (Header == NULL)
182 {
183 DPRINT1("Device %p has no MS OS 2.0 descriptor set to install\n", Child);
184 return FALSE;
185 }
186
187 End = (PUCHAR)Header + Header->wTotalLength;
189
190 while (Current != NULL)
191 {
192 if (Current->wDescriptorType == MSOS20_TYPE_REGISTRY_PROPERTY)
193 {
194 /* The registry write reports its own failure */
195 Status = HubInstallMsOs20Property(Child, (const HubMsOs20Registry*)Current);
196 if (!NT_SUCCESS(Status))
197 break;
198 }
199
201 {
202 DPRINT1("Device %p MS OS 2.0 descriptor set walk failed\n", Child);
203 Result = FALSE;
204 break;
205 }
206 }
207
208 /* The model id goes out whatever the property walk did */
209 if ((Child->m_MsOs20.Flags & HUB_MSOS20_MODEL_ID) && Child->m_MsOs20.ModelId != NULL && Child->m_Pdo != NULL)
210 {
211 Status = IoSetDevicePropertyData(WdfDeviceWdmGetDeviceObject(Child->m_Pdo->m_Device),
212 &DEVPKEY_Device_ModelId,
214 0,
216 sizeof(Child->m_MsOs20.ModelId->ModelId),
217 Child->m_MsOs20.ModelId->ModelId);
218 if (!NT_SUCCESS(Status))
219 DPRINT1("Setting the model id failed 0x%lx\n", Status);
220 }
221
222 return Result;
223}
224
225/* MS OS 1.0 query gates */
226
229{
231
233 return FALSE;
234
235 switch (HubDriver.MsOsMode)
236 {
237 case HubMsOsMode::ForceQuery:
238 Child->ClearProperty(ChildProperty::MsOsNotSupported);
239 return TRUE;
240
241 case HubMsOsMode::NeverQuery:
242 Child->SetProperty(ChildProperty::MsOsNotSupported);
243 return FALSE;
244
245 default:
246 break;
247 }
248
250 !Child->HasProperty(ChildProperty::MsOsNotSupported) &&
251 Child->m_MsOsVendorCode == 0)
252 {
253 return TRUE;
254 }
255
256 return Child->HasHack(ChildHack::AlwaysQueryMsOs);
257}
258
261{
263
265 return FALSE;
266
268 !Child->HasProperty(ChildProperty::MsOsNotSupported) &&
269 !Child->HasProperty(ChildProperty::IsComposite))
270 {
271 return TRUE;
272 }
273
274 return Child->HasHack(ChildHack::AlwaysQueryMsOs);
275}
276
279{
281
283 return FALSE;
284
286 !Child->HasProperty(ChildProperty::MsOsNotSupported) &&
287 !Child->HasHack(ChildHack::SkipContainerIdQuery))
288 {
289 return TRUE;
290 }
291
292 return Child->HasHack(ChildHack::AlwaysQueryMsOs);
293}
294
297{
299}
300
301/* Reads the semaphore first, so the answer reflects the hardware key now */
304{
307 BOOLEAN Installed;
308
309 PAGED_CODE();
310
311 HubRefreshExtPropertiesInstalled(Child);
312 Installed = Child->HasProperty(ChildProperty::ExtPropertiesInstalled);
313
314 if (Child->HasProperty(ChildProperty::IsComposite) || HubHasMsOs20SetInfo(Child))
315 return FALSE;
316
317 if (Child->HasHack(ChildHack::AlwaysQueryMsOs) && !Installed)
318 return TRUE;
319
320 if ((BcdUsb >= 0x0100 && BcdUsb <= 0x01FF) ||
321 Installed ||
322 Child->HasProperty(ChildProperty::MsOsNotSupported))
323 {
324 return FALSE;
325 }
326
327 return TRUE;
328}
329
330/* MS OS 1.0 usbflags records; write failures are ignored */
331
332VOID
334{
335 UCHAR Record[2] = { 0, 0 };
336
337 PAGED_CODE();
338
339 HubWriteUsbflagsValue(m_Device, L"osvc", Record, sizeof(Record));
340 m_Device->SetProperty(ChildProperty::MsOsNotSupported);
341}
342
343VOID
345{
346 UCHAR Record[2];
347
348 PAGED_CODE();
349
350 Record[0] = 1;
352 HubWriteUsbflagsValue(m_Device, L"osvc", Record, sizeof(Record));
353}
354
355/* Read back as the 2 byte value 1 by the next errata query */
356VOID
358{
359 USHORT Record = 1;
360
361 HubWriteUsbflagsValue(m_Device, L"SkipContainerIdQuery", &Record, sizeof(Record));
362 m_Device->m_Hacks |= (ULONG)ChildHack::SkipContainerIdQuery;
363}
364
365/* MS OS 1.0 extended properties */
366
367VOID
369{
370 m_Device->SetState(ChildState::MsOsInstallHandled);
371}
372
375{
376 DECLARE_CONST_UNICODE_STRING(Name, L"ExtPropDescSemaphore");
377 ULONG Value = 1;
378
379 PAGED_CODE();
380
382}
383
384/* The header stays in the scratch buffer for the full read and its check */
387{
389
390 if (m_Device->m_Control.Urb.TransferBufferLength != sizeof(*Header))
391 {
392 DPRINT1("Device %p extended properties header is %lu bytes\n",
393 m_Device, m_Device->m_Control.Urb.TransferBufferLength);
394 return FALSE;
395 }
396
397 if (Header->dwLength >= sizeof(*Header) &&
398 Header->bcdVersion == MSOS_EXT_PROPERTIES_VERSION &&
400 Header->wCount != 0)
401 {
402 return TRUE;
403 }
404
405 DPRINT1("Device %p extended properties header is invalid\n", m_Device);
406 return FALSE;
407}
408
409/* Sized from the header before the 4 KB cap is checked */
412{
414
415 if (Child->m_ExtProperties != NULL)
416 ExFreePoolWithTag(Child->m_ExtProperties, HUB_TAG_DEVICE);
417
419 if (Child->m_ExtProperties == NULL)
420 {
421 DPRINT1("Device %p extended properties of %lu bytes could not be allocated\n",
423 return FALSE;
424 }
425
426 return TRUE;
427}
428
429/* Custom property at Offset fits and is well formed; Size gets its dwSize */
430static
432NTAPI
438{
440 ULONG Remaining = Total - Offset;
443 const WCHAR* Name;
444
445 if (Remaining < MSOS_CUSTOM_PROPERTY_FIXED)
446 return FALSE;
447
448 *Size = Property->dwSize;
449 if (*Size > Remaining || *Size < MSOS_CUSTOM_PROPERTY_FIXED)
450 return FALSE;
451
452 if (Property->dwPropertyDataType < REG_SZ || Property->dwPropertyDataType > REG_MULTI_SZ)
453 return FALSE;
454
455 NameLength = Property->wPropertyNameLength;
457 return FALSE;
458
459 Name = (const WCHAR*)(Property + 1);
460 if (Name[0] == UNICODE_NULL || Name[NameLength / sizeof(WCHAR) - 1] != UNICODE_NULL)
461 return FALSE;
462
464
466}
467
468/* Bytes after the last counted property are allowed */
471{
474 const UCHAR* Buffer = (const UCHAR*)Child->m_ExtProperties;
475 ULONG Total = Header->dwLength;
477 ULONG Size;
478 ULONG Found = 0;
479
480 if (Buffer == NULL || Child->m_Control.Urb.TransferBufferLength != Total)
481 {
482 DPRINT1("Device %p extended properties: %lu of %lu bytes read\n",
483 Child, Child->m_Control.Urb.TransferBufferLength, Total);
484 return FALSE;
485 }
486
487 if (!RtlEqualMemory(Buffer, Header, sizeof(*Header)))
488 {
489 DPRINT1("Device %p extended properties header changed between reads\n", Child);
490 return FALSE;
491 }
492
494 {
495 DPRINT1("Device %p extended properties too large (%lu bytes)\n", Child, Total);
496 return FALSE;
497 }
498
499 for (Offset = sizeof(*Header); Offset < Total; Offset += Size)
500 {
502 {
503 DPRINT1("Device %p custom property at offset %lu is invalid\n", Child, Offset);
504 return FALSE;
505 }
506
507 if (++Found == Header->wCount)
508 break;
509 }
510
511 if (Found != Header->wCount)
512 {
513 DPRINT1("Device %p has %lu custom properties, header says %u\n", Child, Found, Header->wCount);
514 return FALSE;
515 }
516
517 return TRUE;
518}
519
520/* The first failed write ends the install */
523{
525 const UCHAR* Cursor = (const UCHAR*)Child->m_ExtProperties + sizeof(HubMsOsExtPropHeader);
526 USHORT Count = ((const HubMsOsExtPropHeader*)Child->m_ExtProperties)->wCount;
529 const UCHAR* Tail;
532
533 PAGED_CODE();
534
535 for (Index = 0; Index < Count; Index++)
536 {
538
540 Tail = (const UCHAR*)(Property + 1) + Property->wPropertyNameLength;
542
544 &Name,
545 Property->dwPropertyDataType,
547 (PVOID)(Tail + sizeof(DataLength)))))
548 {
549 return FALSE;
550 }
551
552 Cursor += Property->dwSize;
553 }
554
555 return TRUE;
556}
557
558VOID
560{
562
566}
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
#define REG_SZ
Definition: layer.c:22
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
return Found
Definition: dirsup.c:1270
Definition: bufpool.h:45
BOOLEAN AltEnumNeededOnReenum()
Definition: hubmsos.cpp:111
HubChild * m_Device
Definition: devsm.h:1832
BOOLEAN MsOsQueryWanted()
Definition: hubmsos.cpp:228
VOID StoreMsOsVendorCode()
Definition: hubmsos.cpp:344
BOOLEAN ExtPropertiesWanted()
Definition: hubmsos.cpp:303
BOOLEAN AltEnumNeededAfterBos()
Definition: hubmsos.cpp:104
BOOLEAN ExtPropertiesValid()
Definition: hubmsos.cpp:470
VOID MarkMsOsInstallHandled()
Definition: hubmsos.cpp:368
BOOLEAN MsOs20ValuesWanted()
Definition: hubmsos.cpp:127
BOOLEAN SetExtPropertiesSemaphore()
Definition: hubmsos.cpp:374
BOOLEAN MsOsExtendedConfigSupported()
Definition: hubmsos.cpp:260
BOOLEAN WriteCustomProperties()
Definition: hubmsos.cpp:522
BOOLEAN InstallMsOs20Values()
Definition: hubmsos.cpp:170
VOID MarkContainerIdUnsupported()
Definition: hubmsos.cpp:357
BOOLEAN AltEnumNeededInEnum()
Definition: hubmsos.cpp:86
BOOLEAN ExtPropertiesHeaderValid()
Definition: hubmsos.cpp:386
BOOLEAN MsOsContainerIdSupported()
Definition: hubmsos.cpp:296
VOID MarkMsOsUnsupported()
Definition: hubmsos.cpp:333
BOOLEAN MsOs20Supported()
Definition: hubmsos.cpp:121
BOOLEAN ContainerIdWanted()
Definition: hubmsos.cpp:278
VOID FreeExtPropertiesBuffer()
Definition: hubmsos.cpp:559
BOOLEAN AllocateExtPropertiesBuffer()
Definition: hubmsos.cpp:411
Definition: Header.h:9
USB_DEVICE_DESCRIPTOR m_OriginalDeviceDescriptor
Definition: hubchild.h:502
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
Definition: hubchild.h:386
PVOID m_ExtProperties
Definition: hubchild.h:505
BOOLEAN m_AltEnumCached
Definition: hubchild.h:499
HubMsOs20Info m_MsOs20
Definition: hubchild.h:494
ULONG m_Hacks
Definition: hubchild.h:329
UCHAR m_MsOsVendorCode
Definition: hubchild.h:490
VOID SetProperty(_In_ ChildProperty Flag)
Definition: hubchild.h:295
BOOLEAN HasProperty(_In_ ChildProperty Flag) const
Definition: hubchild.h:288
volatile LONG m_StateFlags
Definition: hubchild.h:331
HubMsOs20SetInfo m_MsOs20SetInfo
Definition: hubchild.h:493
HubControlRequest m_Control
Definition: hubchild.h:359
HubMsOsString m_MsOsString
Definition: hubchild.h:489
volatile LONG m_Properties
Definition: hubchild.h:330
VOID SetState(_In_ ChildState Flag)
Definition: hubchild.h:267
BOOLEAN HasState(_In_ ChildState Flag) const
Definition: hubchild.h:260
BOOLEAN NTAPI HubDescNextMsOs20(_In_ PUCHAR End, _Inout_ HubMsOs20Common **Current)
Definition: desccheck.cpp:2647
PUCHAR End
Definition: desccheck.cpp:2229
PUCHAR Cursor
Definition: desccheck.cpp:2228
#define HUB_MSOS20_ALT_ENUM
Definition: desccheck.h:490
#define HUB_MSOS20_REGISTRY
Definition: desccheck.h:494
#define HUB_MSOS20_MODEL_ID
Definition: desccheck.h:496
#define HUB_MSOS20_SET_INFO
Definition: desccheck.h:488
LPWSTR Name
Definition: desk.c:124
#define DEVPROP_TYPE_GUID
Definition: devpropdef.h:42
_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
static DWORD DWORD * dwLength
Definition: fusion.c:86
#define L(x)
Definition: resources.c:13
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
HubDriverState HubDriver
Definition: entry.cpp:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:24
static BOOLEAN NTAPI HubMsOsVersionAllowed(_In_ HubChild *Child)
Definition: hubmsos.cpp:56
#define MSOS_FLAG_CONTAINER_ID
Definition: hubmsos.cpp:15
static BOOLEAN NTAPI HubHasMsOs20SetInfo(_In_ HubChild *Child)
Definition: hubmsos.cpp:67
return HubWriteDeviceValue(Child, &ValueName, Property->wPropertyDataType, DataLength,(PVOID)(Tail+sizeof(DataLength)))
#define MSOS20_TYPE_REGISTRY_PROPERTY
Definition: hubmsos.cpp:23
#define MSOS_EXT_PROPERTIES_INDEX
Definition: hubmsos.cpp:18
#define MSOS_EXT_PROPERTIES_MAX
Definition: hubmsos.cpp:20
#define MSOS_EXT_PROPERTIES_VERSION
Definition: hubmsos.cpp:19
static const HubMsOsExtPropHeader *NTAPI HubExtPropHeader(_In_ HubChild *Child)
Definition: hubmsos.cpp:76
USHORT DataLength
Definition: hubmsos.cpp:147
UNICODE_STRING ValueName
Definition: hubmsos.cpp:146
#define MSOS_CUSTOM_PROPERTY_FIXED
Definition: hubmsos.cpp:50
static BOOLEAN NTAPI HubCustomPropertyValid(_In_reads_bytes_(Total) const UCHAR *Buffer, _In_ ULONG Total, _In_ ULONG Offset, _Out_ PULONG Size)
Definition: hubmsos.cpp:433
const UCHAR * Tail
Definition: hubmsos.cpp:145
HubUxdSettings Current
_In_ PCUNICODE_STRING _Out_ HubUxdSettings * Record
#define HUB_TAG_DEVICE
Definition: hubutil.h:13
ULONG Total
Definition: hubwmi.cpp:548
#define InterlockedAnd
Definition: interlocked.h:77
#define C_ASSERT(e)
Definition: intsafe.h:73
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
if(dx< 0)
Definition: linetemp.h:194
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define REG_MULTI_SZ
Definition: nt_native.h:1504
#define LOCALE_NEUTRAL
#define UNICODE_NULL
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
Input NameLength
Definition: portacpi.cpp:298
#define REG_DWORD
Definition: sdbapi.c:615
struct _URB_CONTROL_TRANSFER_EX Urb
Definition: hubreq.h:21
HubMsOsMode MsOsMode
Definition: hubdriver.h:92
USHORT wPropertyNameLength
Definition: hubmsos.cpp:41
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
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
_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_ WDFDEVICE Child
Definition: wdffdo.h:536
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define NT_ASSERT
Definition: rtlfuncs.h:3334