ReactOS 0.4.17-dev-684-ga6524ef
range.c File Reference
#include <ntifs.h>
#include <ndk/rtlfuncs.h>
#include "arbiter.h"
#include <debug.h>
Include dependency graph for range.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static VOID ArbpWritePriority (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALTERNATIVE Alternative)
 Writes an alternative's priority to the next ordering-list range it can be satisfied from.
 
static BOOLEAN ArbpIsRootEnumerated (_In_ PDEVICE_OBJECT DeviceObject)
 Determines whether a device is enumerated by the root enumerator.
 
static BOOLEAN ArbpSharesDriverStack (_In_ PDEVICE_OBJECT DeviceA, _In_ PDEVICE_OBJECT DeviceB)
 Determines whether a common driver is loaded on both device stacks, above the physical device objects.
 
static BOOLEAN ArbpShareDriverExclusive (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Attempts last-chance sharing for a CmResourceShareDriverExclusive requirement whose window RtlFindRange found occupied.
 
static BOOLEAN ArbpReuseOwnedInterrupt (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Hands a device back its own already routed IRQ instead of searching for a fresh one, on legacy-PIC / no-ACPI interrupt routing setups.
 
BOOLEAN NTAPI ArbiterLibGetNextAllocationRange (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Moves the working window to the next candidate range, walking the entry's alternatives in priority order across the arbiter's ordering list.
 
BOOLEAN NTAPI ArbiterLibFindSuitableRange (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Finds a free range of the current candidate window in the arbiter's tentative allocation list.
 
VOID NTAPI ArbiterLibAddAllocation (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Records the chosen placement in the arbiter's tentative allocation list, owned by the requesting device.
 
VOID NTAPI ArbiterLibBacktrackAllocation (_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
 Undoes the last AddAllocation performed for this entry.
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file range.c.

Function Documentation

◆ ArbiterLibAddAllocation()

VOID NTAPI ArbiterLibAddAllocation ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)

Records the chosen placement in the arbiter's tentative allocation list, owned by the requesting device.

Parameters
[in]ArbiterThe arbiter instance whose PossibleAllocation list receives the range.
[in,out]ArbStateThe allocation state whose Start, End and RangeAttributes describe the placement. The range is owned by the entry's physical device object.
Remarks
ADD_IF_CONFLICT is required because override solutions intentionally overlap existing ranges.

Definition at line 618 of file range.c.

621{
623
624 PAGED_CODE();
625
626 if (ArbState->CurrentAlternative != NULL &&
627 (ArbState->CurrentAlternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED))
628 {
630 }
631
632 RtlAddRange(Arbiter->PossibleAllocation,
633 ArbState->Start,
634 ArbState->End,
635 ArbState->RangeAttributes,
636 Flags,
637 NULL,
638 ArbState->Entry ? ArbState->Entry->PhysicalDeviceObject : NULL);
639}
#define PAGED_CODE()
#define ARBITER_ALTERNATIVE_FLAG_SHARED
Definition: arbiter.h:29
#define NULL
Definition: types.h:112
NTSYSAPI NTSTATUS NTAPI RtlAddRange(_Inout_ PRTL_RANGE_LIST RangeList, _In_ ULONGLONG Start, _In_ ULONGLONG End, _In_ UCHAR Attributes, _In_ ULONG Flags, _In_opt_ PVOID UserData, _In_opt_ PVOID Owner)
#define RTL_RANGE_LIST_ADD_IF_CONFLICT
Definition: rtltypes.h:81
#define RTL_RANGE_LIST_ADD_SHARED
Definition: rtltypes.h:82
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibBacktrackAllocation()

VOID NTAPI ArbiterLibBacktrackAllocation ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)

Undoes the last AddAllocation performed for this entry.

Parameters
[in]ArbiterThe arbiter instance whose PossibleAllocation list the tentative range is deleted from.
[in,out]ArbStateThe allocation state whose Start and End describe the placement being removed sanity checked by the entry's physical device object.

Definition at line 656 of file range.c.

659{
660 PAGED_CODE();
661
662 RtlDeleteRange(Arbiter->PossibleAllocation,
663 ArbState->Start,
664 ArbState->End,
665 ArbState->Entry ? ArbState->Entry->PhysicalDeviceObject : NULL);
666}
NTSYSAPI NTSTATUS NTAPI RtlDeleteRange(_Inout_ PRTL_RANGE_LIST RangeList, _In_ ULONGLONG Start, _In_ ULONGLONG End, _In_ PVOID Owner)

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibFindSuitableRange()

BOOLEAN NTAPI ArbiterLibFindSuitableRange ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)

Finds a free range of the current candidate window in the arbiter's tentative allocation list.

Parameters
[in]ArbiterThe arbiter instance whose PossibleAllocation list is searched.
[in,out]ArbStateThe allocation state of the entry being placed. On success, Start and End receive the chosen window.
Returns
Returns TRUE if a placement was found,FALSE if the window cannot satisfy the requirement.
Remarks
Legacy requests treat boot-allocated ranges as available. When RtlFindRange reports a conflict, a driver-exclusive requirement may still share the range (ArbpShareDriverExclusive), and failing that the arbiter's OverrideConflict callback gets a last-chance override. this is how a device is re-assigned its own boot configuration.

Definition at line 520 of file range.c.

523{
524 PARBITER_ALTERNATIVE Alternative = ArbState->CurrentAlternative;
525 ULONG Flags = 0;
527
528 PAGED_CODE();
529
530 if (Alternative == NULL)
531 return FALSE;
532
533 if (ArbState->CurrentMinimum > ArbState->CurrentMaximum)
534 return FALSE;
535
536 if (Alternative->Length == 0)
537 {
538 ArbState->Start = ArbState->CurrentMinimum;
539 ArbState->End = ArbState->CurrentMinimum;
540 return TRUE;
541 }
542
543 /*
544 * Interrupt retention: give the device back its firmware-routed vector rather
545 * than letting the top-down search pick an untranslatable one
546 */
547 if (ArbpReuseOwnedInterrupt(Arbiter, ArbState))
548 return TRUE;
549
550 /* Legacy requests consider preallocated (boot) ranges available. */
551 if (ArbState->Entry != NULL &&
552 (ArbState->Entry->RequestSource == ArbiterRequestLegacyReported ||
553 ArbState->Entry->RequestSource == ArbiterRequestLegacyAssigned))
554 {
555 ArbState->RangeAvailableAttributes |= ARBITER_RANGE_BOOT_ALLOCATED;
556 }
557
558 if (ArbState->Flags & ARBITER_STATE_FLAG_NULL_CONFLICT_OK)
560 if (Alternative->Flags & ARBITER_ALTERNATIVE_FLAG_SHARED)
562
563 Status = RtlFindRange(Arbiter->PossibleAllocation,
564 ArbState->CurrentMinimum,
565 ArbState->CurrentMaximum,
566 (ULONG)Alternative->Length,
567 (ULONG)(Alternative->Alignment ? Alternative->Alignment : 1),
568 Flags,
569 ArbState->RangeAvailableAttributes,
570 Arbiter->ConflictCallbackContext,
571 Arbiter->ConflictCallback,
572 &ArbState->Start);
573 if (!NT_SUCCESS(Status))
574 {
575 /*
576 * The window is occupied. A CmResourceShareDriverExclusive requirement
577 * can still succeed by sharing the conflicting range with the same driver
578 * or another root-enumerated device
579 *
580 * This matters a lot because HAL reverses quite a bit and marks it this.
581 * This mechanism is how Windows "internally allows this".
582 */
583 if (ArbpShareDriverExclusive(Arbiter, ArbState))
584 return TRUE;
585 if (Arbiter->OverrideConflict != NULL &&
586 Arbiter->OverrideConflict(Arbiter, ArbState))
587 {
588 return TRUE;
589 }
590 return FALSE;
591 }
592
593 ArbState->End = ArbState->Start + Alternative->Length - 1;
594 return TRUE;
595}
#define ARBITER_STATE_FLAG_NULL_CONFLICT_OK
Definition: arbiter.h:44
#define ARBITER_RANGE_BOOT_ALLOCATED
Definition: arbiter.h:41
LONG NTSTATUS
Definition: precomp.h:26
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI RtlFindRange(_In_ PRTL_RANGE_LIST RangeList, _In_ ULONGLONG Minimum, _In_ ULONGLONG Maximum, _In_ ULONG Length, _In_ ULONG Alignment, _In_ ULONG Flags, _In_ UCHAR AttributeAvailableMask, _In_opt_ PVOID Context, _In_opt_ PRTL_CONFLICT_RANGE_CALLBACK Callback, _Out_ PULONGLONG Start)
#define RTL_RANGE_LIST_NULL_CONFLICT_OK
Definition: rtltypes.h:90
#define RTL_RANGE_LIST_SHARED_OK
Definition: rtltypes.h:89
static BOOLEAN ArbpShareDriverExclusive(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Attempts last-chance sharing for a CmResourceShareDriverExclusive requirement whose window RtlFindRan...
Definition: range.c:215
static BOOLEAN ArbpReuseOwnedInterrupt(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Hands a device back its own already routed IRQ instead of searching for a fresh one,...
Definition: range.c:316
@ ArbiterRequestLegacyAssigned
Definition: iotypes.h:4619
@ ArbiterRequestLegacyReported
Definition: iotypes.h:4617

Referenced by ArbiterLibInitializeInstance().

◆ ArbiterLibGetNextAllocationRange()

BOOLEAN NTAPI ArbiterLibGetNextAllocationRange ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)

Moves the working window to the next candidate range, walking the entry's alternatives in priority order across the arbiter's ordering list.

Parameters
[in]ArbiterThe arbiter instance whose ordering list supplies the candidate windows.
[in,out]ArbStateThe allocation state of the entry being placed. On success, CurrentMinimum, CurrentMaximum and CurrentAlternative describe the next window to search; the window is pre-trimmed so an aligned allocation of the required length fits inside it.
Returns
Returns TRUE if a new candidate window was produced, FALSE once every alternative is exhausted.

Definition at line 379 of file range.c.

382{
383 PARBITER_ALTERNATIVE Alternative;
385 UINT64 Minimum, Maximum;
386
387 PAGED_CODE();
388
389 if (ArbState->AlternativeCount == 0)
390 return FALSE;
391
392 for (;;)
393 {
394 /* Advance the alternative we last worked on, or seed all on first entry. */
395 if (ArbState->CurrentAlternative != NULL)
396 {
397 ArbpWritePriority(Arbiter, ArbState->CurrentAlternative);
398 }
399 else
400 {
401 for (Alternative = ArbState->Alternatives;
402 Alternative < &ArbState->Alternatives[ArbState->AlternativeCount];
403 ++Alternative)
404 {
405 Alternative->Priority = ARBITER_PRIORITY_NULL;
406 ArbpWritePriority(Arbiter, Alternative);
407 }
408 }
409
410 /* Pick the best (lowest-priority) alternative. */
411 Lowest = ArbState->Alternatives;
412 for (Alternative = ArbState->Alternatives + 1;
413 Alternative < &ArbState->Alternatives[ArbState->AlternativeCount];
414 ++Alternative)
415 {
416 if (Alternative->Priority < Lowest->Priority)
417 Lowest = Alternative;
418 }
419
421 return FALSE;
422
423 if (Lowest->Priority == ARBITER_PRIORITY_RESERVED ||
425 {
426 /* Final pass: the whole requirement window. */
427 Minimum = Lowest->Minimum;
428 Maximum = Lowest->Maximum;
429 }
430 else
431 {
432 PARBITER_ORDERING Ordering;
433 ULONG Index = (Lowest->Priority < 0) ? (ULONG)(-(Lowest->Priority + 1))
434 : (ULONG)(Lowest->Priority - 1);
435 if (Index >= Arbiter->OrderingList.Count)
436 {
438 continue;
439 }
440 Ordering = &Arbiter->OrderingList.Orderings[Index];
441 Minimum = max(Lowest->Minimum, Ordering->Start);
442 Maximum = min(Lowest->Maximum, Ordering->End);
443 }
444
445 /*
446 * Trim the window so an aligned allocation of the required length is
447 * possible; skip the window entirely if it cannot hold one.
448 */
449 if (Lowest->Length != 0)
450 {
451 UINT64 Alignment = Lowest->Alignment ? Lowest->Alignment : 1;
452 UINT64 LengthMinusOne = Lowest->Length - 1;
453 UINT64 AlignedMax;
454
455 Minimum += Alignment - 1;
456 Minimum -= Minimum % Alignment;
457
458 if (Minimum > Maximum || LengthMinusOne > Maximum - Minimum)
459 {
460 ArbState->CurrentAlternative = Lowest; /* consume this priority */
461 continue;
462 }
463
464 AlignedMax = Maximum - LengthMinusOne;
465 AlignedMax -= AlignedMax % Alignment;
466 if (AlignedMax < Minimum)
467 {
468 ArbState->CurrentAlternative = Lowest; /* no aligned start fits */
469 continue;
470 }
471 Maximum = AlignedMax + LengthMinusOne;
472 }
473 else
474 {
475 Minimum = Lowest->Minimum;
476 Maximum = Lowest->Maximum;
477 }
478
479 if (Minimum != ArbState->CurrentMinimum ||
480 Maximum != ArbState->CurrentMaximum ||
481 ArbState->CurrentAlternative != Lowest)
482 {
483 ArbState->CurrentMinimum = Minimum;
484 ArbState->CurrentMaximum = Maximum;
485 ArbState->CurrentAlternative = Lowest;
486 return TRUE;
487 }
488
489 ArbState->CurrentAlternative = Lowest;
490 }
491}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define ARBITER_PRIORITY_NULL
Definition: arbiter.h:22
#define ARBITER_PRIORITY_RESERVED
Definition: arbiter.h:24
#define ARBITER_PRIORITY_EXHAUSTED
Definition: arbiter.h:25
#define ARBITER_PRIORITY_PREFERRED_RESERVED
Definition: arbiter.h:23
union Alignment_ Alignment
#define min(a, b)
Definition: monoChain.cc:55
static VOID ArbpWritePriority(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALTERNATIVE Alternative)
Writes an alternative's priority to the next ordering-list range it can be satisfied from.
Definition: range.c:38
UINT64 Start
Definition: arbiter.h:81
#define max(a, b)
Definition: svc.c:63
_In_ WDFCOLLECTION _In_ ULONG Index

Referenced by ArbiterLibInitializeInstance().

◆ ArbpIsRootEnumerated()

static BOOLEAN ArbpIsRootEnumerated ( _In_ PDEVICE_OBJECT  DeviceObject)
static

Determines whether a device is enumerated by the root enumerator.

Parameters
[in]DeviceObjectThe physical device object to examine. May be NULL, in which case the device is not considered root-enumerated.
Returns
Returns TRUE if the device's enumerator name is "ROOT", FALSE otherwise or if the property cannot be read.

Definition at line 123 of file range.c.

125{
126 WCHAR Buffer[16];
129 ULONG Length = 0;
130
131 PAGED_CODE();
132
133 if (DeviceObject == NULL)
134 return FALSE;
135
137 sizeof(Buffer), Buffer, &Length)))
138 {
139 return FALSE;
140 }
141
144}
Definition: bufpool.h:45
LPWSTR Name
Definition: desk.c:124
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define L(x)
Definition: resources.c:13
@ Root
Definition: cmtypes.h:261
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
short WCHAR
Definition: pedump.c:58
NTSTATUS NTAPI IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength)
Definition: pnpmgr.c:1382
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
@ DevicePropertyEnumeratorName
Definition: iotypes.h:1210

Referenced by ArbpShareDriverExclusive().

◆ ArbpReuseOwnedInterrupt()

static BOOLEAN ArbpReuseOwnedInterrupt ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)
static

Hands a device back its own already routed IRQ instead of searching for a fresh one, on legacy-PIC / no-ACPI interrupt routing setups.

Parameters
[in]ArbiterThe arbiter instance. The routine is a no-op for every resource type other than CmResourceTypeInterrupt.
[in,out]ArbStateThe allocation state of the requirement. On success, Start and End receive the vector this device already owns in the committed allocation list.
Returns
Returns TRUE if an owned vector inside the requested window was found and reused, FALSE otherwise.
Remarks
pci.sys emits line-based interrupt requirement of (MinimumVector 0, MaximumVector 0xFFFFFFFF) which expects an upstream ACPI _PRT arbiter to clamp it to the routed GSIV. With no ACPI the root IRQ arbiter is the only one in the tree, and RtlFindRange searches top-down so a loose window resolves to 0xFFFFFFFF. But the BIOS already handled each device's IRQ which pci.sys reports as the device's boot config; the boot reservation recorded it as a [Vector, Vector] range owned by this PDO in the committed list, and every later commit re-records the assigned vector the same way. Reusing that vector keeps the device on the interrupt the firmware wired it to.

Definition at line 316 of file range.c.

319{
320 PARBITER_LIST_ENTRY Entry = ArbState->Entry;
321 PARBITER_ALTERNATIVE Alternative = ArbState->CurrentAlternative;
323 PRTL_RANGE Range;
324
325 PAGED_CODE();
326
327 if (Arbiter->ResourceType != CmResourceTypeInterrupt)
328 return FALSE;
329
330 if (Entry == NULL || Entry->PhysicalDeviceObject == NULL || Alternative == NULL)
331 return FALSE;
332
333 if (!NT_SUCCESS(RtlGetFirstRange(Arbiter->Allocation, &Iterator, &Range)))
334 return FALSE;
335
336 while (Range != NULL)
337 {
338 if ((PDEVICE_OBJECT)Range->Owner == Entry->PhysicalDeviceObject &&
339 Range->Start >= ArbState->CurrentMinimum &&
340 Range->Start <= ArbState->CurrentMaximum &&
341 Range->End <= ArbState->CurrentMaximum &&
342 (Range->End - Range->Start + 1) >= Alternative->Length)
343 {
344 ArbState->Start = Range->Start;
345 ArbState->End = Range->Start + Alternative->Length - 1;
346 return TRUE;
347 }
348
349 if (!NT_SUCCESS(RtlGetNextRange(&Iterator, &Range, TRUE)))
350 break;
351 }
352
353 return FALSE;
354}
NTSYSAPI NTSTATUS NTAPI RtlGetNextRange(_Inout_ PRTL_RANGE_LIST_ITERATOR Iterator, _Outptr_ PRTL_RANGE *Range, _In_ BOOLEAN MoveForwards)
NTSYSAPI NTSTATUS NTAPI RtlGetFirstRange(_In_ PRTL_RANGE_LIST RangeList, _Out_ PRTL_RANGE_LIST_ITERATOR Iterator, _Outptr_ PRTL_RANGE *Range)
#define CmResourceTypeInterrupt
Definition: restypes.h:105
Entry
Definition: section.c:5216
Definition: iotypes.h:4633
ULONGLONG End
Definition: rtltypes.h:1497
ULONGLONG Start
Definition: rtltypes.h:1496
PVOID Owner
Definition: rtltypes.h:1499
_In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR Iterator
Definition: wdfchildlist.h:656

Referenced by ArbiterLibFindSuitableRange().

◆ ArbpShareDriverExclusive()

static BOOLEAN ArbpShareDriverExclusive ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALLOCATION_STATE  ArbState 
)
static

Attempts last-chance sharing for a CmResourceShareDriverExclusive requirement whose window RtlFindRange found occupied.

Parameters
[in]ArbiterThe arbiter instance whose tentative allocation list is walked for an overlapping, owned, not-already-available range that the request is allowed to share.
[in,out]ArbStateThe allocation state of the requirement. On success, Start and End receive the requested window and the range attributes are tagged ARBITER_RANGE_SHARED_DRIVER for a driver-exclusive requirement.
Returns
Returns TRUE if the conflicting range may be shared with the requester, FALSE if the conflict is real.
Remarks
"DriverExclusive" excludes only OTHER drivers: the SAME driver may share the resource across its devices, and two root-enumerated ("ROOT") devices may share it. This is how a device claims a resource the HAL/firmware reports for the same hardware Example: the ports the kernel debugger reserves, which the HAL marks DriverExclusive.

Definition at line 215 of file range.c.

218{
219 PARBITER_LIST_ENTRY Entry = ArbState->Entry;
220 PDEVICE_OBJECT Requester;
222 PRTL_RANGE Range;
223 BOOLEAN RequesterIsRoot;
224
225 PAGED_CODE();
226
227 if (Entry == NULL || Entry->PhysicalDeviceObject == NULL ||
228 ArbState->CurrentAlternative == NULL)
229 {
230 return FALSE;
231 }
232
233 Requester = Entry->PhysicalDeviceObject;
234 RequesterIsRoot = ArbpIsRootEnumerated(Requester);
235
236 if (!NT_SUCCESS(RtlGetFirstRange(Arbiter->PossibleAllocation, &Iterator, &Range)))
237 return FALSE;
238
239 while (Range != NULL)
240 {
241 /*
242 * Candidate: overlaps the requested window, is not already made available
243 * by attribute, and either the request or the range is driver-exclusive.
244 */
245 if (Range->Start <= ArbState->CurrentMaximum &&
246 Range->End >= ArbState->CurrentMinimum &&
247 !(Range->Attributes & ArbState->RangeAvailableAttributes) &&
248 (ArbState->CurrentAlternative->Descriptor->ShareDisposition == CmResourceShareDriverExclusive ||
250 Range->Owner != NULL)
251 {
253 BOOLEAN Share = FALSE;
254
255 /* Two root-enumerated devices may share; else only a shared driver. */
256 if (RequesterIsRoot && ArbpIsRootEnumerated(Owner))
257 Share = TRUE;
258 else if (ArbpSharesDriverStack(Requester, Owner))
259 Share = TRUE;
260
261 if (Share)
262 {
263 ArbState->Start = ArbState->CurrentMinimum;
264 ArbState->End = ArbState->CurrentMaximum;
265 if (ArbState->CurrentAlternative->Descriptor->ShareDisposition ==
267 {
268 ArbState->RangeAttributes |= ARBITER_RANGE_SHARED_DRIVER;
269 }
270 return TRUE;
271 }
272 }
273
274 if (!NT_SUCCESS(RtlGetNextRange(&Iterator, &Range, TRUE)))
275 break;
276 }
277
278 return FALSE;
279}
unsigned char BOOLEAN
Definition: actypes.h:127
#define ARBITER_RANGE_SHARED_DRIVER
Definition: arbiter.h:40
struct _DEVICE_OBJECT * PDEVICE_OBJECT
if(dx< 0)
Definition: linetemp.h:194
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID Owner
Definition: rtlfuncs.h:1629
static BOOLEAN ArbpSharesDriverStack(_In_ PDEVICE_OBJECT DeviceA, _In_ PDEVICE_OBJECT DeviceB)
Determines whether a common driver is loaded on both device stacks, above the physical device objects...
Definition: range.c:164
static BOOLEAN ArbpIsRootEnumerated(_In_ PDEVICE_OBJECT DeviceObject)
Determines whether a device is enumerated by the root enumerator.
Definition: range.c:123
UCHAR Attributes
Definition: rtltypes.h:1500
@ CmResourceShareDriverExclusive
Definition: cmtypes.h:242

Referenced by ArbiterLibFindSuitableRange().

◆ ArbpSharesDriverStack()

static BOOLEAN ArbpSharesDriverStack ( _In_ PDEVICE_OBJECT  DeviceA,
_In_ PDEVICE_OBJECT  DeviceB 
)
static

Determines whether a common driver is loaded on both device stacks, above the physical device objects.

Parameters
[in]DeviceAThe first physical device object whose attached stack is walked.
[in]DeviceBThe second physical device object whose attached stack is walked.
Returns
Returns TRUE if any driver attached above DeviceA also appears above DeviceB, FALSE otherwise.

Definition at line 164 of file range.c.

167{
169
170 PAGED_CODE();
171
172 for (A = DeviceA->AttachedDevice; A != NULL; A = A->AttachedDevice)
173 {
174 for (B = DeviceB->AttachedDevice; B != NULL; B = B->AttachedDevice)
175 {
176 if (A->DriverObject == B->DriverObject)
177 return TRUE;
178 }
179 }
180
181 return FALSE;
182}
Definition: ehthrow.cxx:93
Definition: ehthrow.cxx:54
#define A(row, col)
#define B(row, col)

Referenced by ArbpShareDriverExclusive().

◆ ArbpWritePriority()

static VOID ArbpWritePriority ( _In_ PARBITER_INSTANCE  Arbiter,
_Inout_ PARBITER_ALTERNATIVE  Alternative 
)
static

Writes an alternative's priority to the next ordering-list range it can be satisfied from.

Parameters
[in]ArbiterThe arbiter instance whose ordering list is walked.
[in,out]AlternativeThe alternative whose priority is written. Ordinary priorities are ordering-list indices biased by one, negated for IO_RESOURCE_PREFERRED alternatives so they sort first. Once the orderings are exhausted the alternative is given one final full-range pass at (PREFERRED_)RESERVED priority, after which it goes EXHAUSTED.

Definition at line 38 of file range.c.

41{
42 PARBITER_ORDERING Ordering;
44 INT32 Priority = Alternative->Priority;
45 BOOLEAN Preferred;
47
48 PAGED_CODE();
49
52 {
53 Alternative->Priority = ARBITER_PRIORITY_EXHAUSTED;
54 return;
55 }
56
57 Preferred = (Alternative->Descriptor->Option & IO_RESOURCE_PREFERRED) != 0;
58
60 {
61 Ordering = Arbiter->OrderingList.Orderings;
62 }
63 else
64 {
65 /* A fixed alternative fits in exactly one place; it gets a single shot. */
66 if (Alternative->Flags & ARBITER_ALTERNATIVE_FLAG_FIXED)
67 {
68 Alternative->Priority = ARBITER_PRIORITY_EXHAUSTED;
69 return;
70 }
71
72 Index = (Priority < 0) ? (ULONG)(-(Priority + 1)) : (ULONG)(Priority - 1);
73 if (Index >= Arbiter->OrderingList.Count)
74 {
75 Alternative->Priority = Preferred ? ARBITER_PRIORITY_PREFERRED_RESERVED
77 return;
78 }
79 Ordering = &Arbiter->OrderingList.Orderings[Index + 1];
80 }
81
82 End = &Arbiter->OrderingList.Orderings[Arbiter->OrderingList.Count];
83 for (; Ordering < End; ++Ordering)
84 {
85 UINT64 Start, RangeEnd;
86
87 if (Ordering->Start > Alternative->Maximum ||
88 Alternative->Minimum > Ordering->End)
89 {
90 continue; /* No intersection with this alternative's window */
91 }
92
93 Start = max(Alternative->Minimum, Ordering->Start);
94 RangeEnd = min(Alternative->Maximum, Ordering->End);
95
96 if ((RangeEnd - Start + 1) >= Alternative->Length)
97 {
98 INT32 NewPriority = (INT32)(Ordering - Arbiter->OrderingList.Orderings) + 1;
99 Alternative->Priority = Preferred ? -NewPriority : NewPriority;
100 return;
101 }
102 }
103
104 Alternative->Priority = Preferred ? ARBITER_PRIORITY_PREFERRED_RESERVED
106}
static _Out_opt_ PULONGLONG Start
#define ARBITER_ALTERNATIVE_FLAG_FIXED
Definition: arbiter.h:28
int32_t INT32
Definition: typedefs.h:58
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:655
#define IO_RESOURCE_PREFERRED

Referenced by ArbiterLibGetNextAllocationRange().