2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpres.c
5 * PURPOSE: Resource handling code
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 * ReactOS Portable Systems Group
17 IopGetNextResourceList(
18 _In_
const IO_RESOURCE_LIST
*ResourceList
)
20 ASSERT((ResourceList
->Count
> 0) && (ResourceList
->Count
< 1000));
21 return (PIO_RESOURCE_LIST
)(
22 &ResourceList
->Descriptors
[ResourceList
->Count
]);
27 IopCheckDescriptorForConflict(
28 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
,
29 OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
31 CM_RESOURCE_LIST CmList
;
35 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
36 CmList
.List
[0].BusNumber
= 0;
37 CmList
.List
[0].PartialResourceList
.Version
= 1;
38 CmList
.List
[0].PartialResourceList
.Revision
= 1;
39 CmList
.List
[0].PartialResourceList
.Count
= 1;
40 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
42 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
43 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
51 IopFindBusNumberResource(
52 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
53 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
56 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
58 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
59 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
61 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
62 Start
<= IoDesc
->u
.BusNumber
.MaxBusNumber
- IoDesc
->u
.BusNumber
.Length
+ 1;
65 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
66 CmDesc
->u
.BusNumber
.Start
= Start
;
68 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
70 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
74 DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start
, CmDesc
->u
.BusNumber
.Length
);
84 IopFindMemoryResource(
85 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
86 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
89 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
91 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
92 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
95 if (IoDesc
->u
.Memory
.Alignment
== 0)
96 IoDesc
->u
.Memory
.Alignment
= 1;
98 for (Start
= (ULONGLONG
)IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
99 Start
<= (ULONGLONG
)IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
- IoDesc
->u
.Memory
.Length
+ 1;
100 Start
+= IoDesc
->u
.Memory
.Alignment
)
102 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
103 CmDesc
->u
.Memory
.Start
.QuadPart
= (LONGLONG
)Start
;
105 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
107 Start
+= (ULONGLONG
)ConflictingDesc
.u
.Memory
.Start
.QuadPart
+
108 ConflictingDesc
.u
.Memory
.Length
;
112 DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start
, CmDesc
->u
.Memory
.Length
);
123 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
124 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
127 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
129 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
130 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
133 if (IoDesc
->u
.Port
.Alignment
== 0)
134 IoDesc
->u
.Port
.Alignment
= 1;
136 for (Start
= (ULONGLONG
)IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
137 Start
<= (ULONGLONG
)IoDesc
->u
.Port
.MaximumAddress
.QuadPart
- IoDesc
->u
.Port
.Length
+ 1;
138 Start
+= IoDesc
->u
.Port
.Alignment
)
140 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
141 CmDesc
->u
.Port
.Start
.QuadPart
= (LONGLONG
)Start
;
143 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
145 Start
+= (ULONGLONG
)ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
149 DPRINT("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start
, CmDesc
->u
.Port
.Length
);
154 DPRINT1("IopFindPortResource failed!\n");
161 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
162 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
166 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
167 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
169 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
170 Channel
<= IoDesc
->u
.Dma
.MaximumChannel
;
173 CmDesc
->u
.Dma
.Channel
= Channel
;
174 CmDesc
->u
.Dma
.Port
= 0;
176 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
178 DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel
);
188 IopFindInterruptResource(
189 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
190 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
194 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
195 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
197 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
198 Vector
<= IoDesc
->u
.Interrupt
.MaximumVector
;
201 CmDesc
->u
.Interrupt
.Vector
= Vector
;
202 CmDesc
->u
.Interrupt
.Level
= Vector
;
203 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
205 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
207 DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector
);
212 DPRINT1("Failed to satisfy interrupt requirement with IRQ 0x%x-0x%x\n",
213 IoDesc
->u
.Interrupt
.MinimumVector
,
214 IoDesc
->u
.Interrupt
.MaximumVector
);
219 IopFixupResourceListWithRequirements(
220 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
221 OUT PCM_RESOURCE_LIST
*ResourceList
)
224 BOOLEAN AlternateRequired
= FALSE
;
225 PIO_RESOURCE_LIST ResList
;
227 /* Save the initial resource count when we got here so we can restore if an alternate fails */
228 if (*ResourceList
!= NULL
)
229 OldCount
= (*ResourceList
)->List
[0].PartialResourceList
.Count
;
233 ResList
= &RequirementsList
->List
[0];
234 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++, ResList
= IopGetNextResourceList(ResList
))
238 /* We need to get back to where we were before processing the last alternative list */
239 if (OldCount
== 0 && *ResourceList
!= NULL
)
241 /* Just free it and kill the pointer */
242 ExFreePool(*ResourceList
);
243 *ResourceList
= NULL
;
245 else if (OldCount
!= 0)
247 PCM_RESOURCE_LIST NewList
;
249 /* Let's resize it */
250 (*ResourceList
)->List
[0].PartialResourceList
.Count
= OldCount
;
252 /* Allocate the new smaller list */
253 NewList
= ExAllocatePool(PagedPool
, PnpDetermineResourceListSize(*ResourceList
));
255 return STATUS_NO_MEMORY
;
257 /* Copy the old stuff back */
258 RtlCopyMemory(NewList
, *ResourceList
, PnpDetermineResourceListSize(*ResourceList
));
260 /* Free the old one */
261 ExFreePool(*ResourceList
);
263 /* Store the pointer to the new one */
264 *ResourceList
= NewList
;
267 for (ii
= 0; ii
< ResList
->Count
; ii
++)
270 PCM_PARTIAL_RESOURCE_LIST PartialList
= (*ResourceList
) ? &(*ResourceList
)->List
[0].PartialResourceList
: NULL
;
271 PIO_RESOURCE_DESCRIPTOR IoDesc
= &ResList
->Descriptors
[ii
];
272 BOOLEAN Matched
= FALSE
;
274 /* Skip alternates if we don't need one */
275 if (!AlternateRequired
&& (IoDesc
->Option
& IO_RESOURCE_ALTERNATIVE
))
277 DPRINT("Skipping unneeded alternate\n");
281 /* Check if we couldn't satsify a requirement or its alternates */
282 if (AlternateRequired
&& !(IoDesc
->Option
& IO_RESOURCE_ALTERNATIVE
))
284 DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i
);
286 /* Break out of this loop and try the next list */
290 for (iii
= 0; PartialList
&& iii
< PartialList
->Count
&& !Matched
; iii
++)
292 /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
293 but only one is allowed and it must be the last one in the list! */
294 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
= &PartialList
->PartialDescriptors
[iii
];
296 /* First check types */
297 if (IoDesc
->Type
!= CmDesc
->Type
)
300 switch (IoDesc
->Type
)
302 case CmResourceTypeInterrupt
:
303 /* Make sure it satisfies our vector range */
304 if (CmDesc
->u
.Interrupt
.Vector
>= IoDesc
->u
.Interrupt
.MinimumVector
&&
305 CmDesc
->u
.Interrupt
.Vector
<= IoDesc
->u
.Interrupt
.MaximumVector
)
312 DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n",
313 CmDesc
->u
.Interrupt
.Vector
,
314 IoDesc
->u
.Interrupt
.MinimumVector
,
315 IoDesc
->u
.Interrupt
.MaximumVector
);
319 case CmResourceTypeMemory
:
320 case CmResourceTypePort
:
321 /* Make sure the length matches and it satisfies our address range */
322 if (CmDesc
->u
.Memory
.Length
== IoDesc
->u
.Memory
.Length
&&
323 (ULONGLONG
)CmDesc
->u
.Memory
.Start
.QuadPart
>= (ULONGLONG
)IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
&&
324 (ULONGLONG
)CmDesc
->u
.Memory
.Start
.QuadPart
+ CmDesc
->u
.Memory
.Length
- 1 <= (ULONGLONG
)IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
)
331 DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n",
332 CmDesc
->u
.Memory
.Start
.QuadPart
,
333 CmDesc
->u
.Memory
.Length
,
334 IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
,
335 IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
336 IoDesc
->u
.Memory
.Length
);
340 case CmResourceTypeBusNumber
:
341 /* Make sure the length matches and it satisfies our bus number range */
342 if (CmDesc
->u
.BusNumber
.Length
== IoDesc
->u
.BusNumber
.Length
&&
343 CmDesc
->u
.BusNumber
.Start
>= IoDesc
->u
.BusNumber
.MinBusNumber
&&
344 CmDesc
->u
.BusNumber
.Start
+ CmDesc
->u
.BusNumber
.Length
- 1 <= IoDesc
->u
.BusNumber
.MaxBusNumber
)
351 DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n",
352 CmDesc
->u
.BusNumber
.Start
,
353 CmDesc
->u
.BusNumber
.Length
,
354 IoDesc
->u
.BusNumber
.MinBusNumber
,
355 IoDesc
->u
.BusNumber
.MaxBusNumber
,
356 IoDesc
->u
.BusNumber
.Length
);
360 case CmResourceTypeDma
:
361 /* Make sure it fits in our channel range */
362 if (CmDesc
->u
.Dma
.Channel
>= IoDesc
->u
.Dma
.MinimumChannel
&&
363 CmDesc
->u
.Dma
.Channel
<= IoDesc
->u
.Dma
.MaximumChannel
)
370 DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n",
371 CmDesc
->u
.Dma
.Channel
,
372 IoDesc
->u
.Dma
.MinimumChannel
,
373 IoDesc
->u
.Dma
.MaximumChannel
);
378 /* Other stuff is fine */
384 /* Check if we found a matching descriptor */
387 PCM_RESOURCE_LIST NewList
;
388 CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc
;
389 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr
;
390 BOOLEAN FoundResource
= TRUE
;
392 /* Setup the new CM descriptor */
393 NewDesc
.Type
= IoDesc
->Type
;
394 NewDesc
.Flags
= IoDesc
->Flags
;
395 NewDesc
.ShareDisposition
= IoDesc
->ShareDisposition
;
397 /* Let'se see if we can find a resource to satisfy this */
398 switch (IoDesc
->Type
)
400 case CmResourceTypeInterrupt
:
401 /* Find an available interrupt */
402 if (!IopFindInterruptResource(IoDesc
, &NewDesc
))
404 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
405 IoDesc
->u
.Interrupt
.MinimumVector
, IoDesc
->u
.Interrupt
.MaximumVector
);
407 FoundResource
= FALSE
;
411 case CmResourceTypePort
:
412 /* Find an available port range */
413 if (!IopFindPortResource(IoDesc
, &NewDesc
))
415 DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
416 IoDesc
->u
.Port
.MinimumAddress
.QuadPart
, IoDesc
->u
.Port
.MaximumAddress
.QuadPart
,
417 IoDesc
->u
.Port
.Length
);
419 FoundResource
= FALSE
;
423 case CmResourceTypeMemory
:
424 /* Find an available memory range */
425 if (!IopFindMemoryResource(IoDesc
, &NewDesc
))
427 DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
428 IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
, IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
429 IoDesc
->u
.Memory
.Length
);
431 FoundResource
= FALSE
;
435 case CmResourceTypeBusNumber
:
436 /* Find an available bus address range */
437 if (!IopFindBusNumberResource(IoDesc
, &NewDesc
))
439 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
440 IoDesc
->u
.BusNumber
.MinBusNumber
, IoDesc
->u
.BusNumber
.MaxBusNumber
,
441 IoDesc
->u
.BusNumber
.Length
);
443 FoundResource
= FALSE
;
447 case CmResourceTypeDma
:
448 /* Find an available DMA channel */
449 if (!IopFindDmaResource(IoDesc
, &NewDesc
))
451 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
452 IoDesc
->u
.Dma
.MinimumChannel
, IoDesc
->u
.Dma
.MaximumChannel
);
454 FoundResource
= FALSE
;
459 DPRINT1("Unsupported resource type: %x\n", IoDesc
->Type
);
460 FoundResource
= FALSE
;
464 /* Check if it's missing and required */
465 if (!FoundResource
&& IoDesc
->Option
== 0)
467 /* Break out of this loop and try the next list */
468 DPRINT1("Unable to satisfy required resource in list %lu\n", i
);
471 else if (!FoundResource
)
473 /* Try an alternate for this preferred descriptor */
474 AlternateRequired
= TRUE
;
479 /* Move on to the next preferred or required descriptor after this one */
480 AlternateRequired
= FALSE
;
483 /* Figure out what we need */
484 if (PartialList
== NULL
)
486 /* We need a new list */
487 NewList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
489 return STATUS_NO_MEMORY
;
493 NewList
->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
494 NewList
->List
[0].BusNumber
= RequirementsList
->BusNumber
;
495 NewList
->List
[0].PartialResourceList
.Version
= 1;
496 NewList
->List
[0].PartialResourceList
.Revision
= 1;
497 NewList
->List
[0].PartialResourceList
.Count
= 1;
499 /* Set our pointer */
500 DescPtr
= &NewList
->List
[0].PartialResourceList
.PartialDescriptors
[0];
504 /* Allocate the new larger list */
505 NewList
= ExAllocatePool(PagedPool
, PnpDetermineResourceListSize(*ResourceList
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
507 return STATUS_NO_MEMORY
;
509 /* Copy the old stuff back */
510 RtlCopyMemory(NewList
, *ResourceList
, PnpDetermineResourceListSize(*ResourceList
));
512 /* Set our pointer */
513 DescPtr
= &NewList
->List
[0].PartialResourceList
.PartialDescriptors
[NewList
->List
[0].PartialResourceList
.Count
];
515 /* Increment the descriptor count */
516 NewList
->List
[0].PartialResourceList
.Count
++;
518 /* Free the old list */
519 ExFreePool(*ResourceList
);
522 /* Copy the descriptor in */
525 /* Store the new list */
526 *ResourceList
= NewList
;
530 /* Check if we need an alternate with no resources left */
531 if (AlternateRequired
)
533 DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i
);
535 /* Try the next alternate list */
539 /* We're done because we satisfied one of the alternate lists */
540 return STATUS_SUCCESS
;
543 /* We ran out of alternates */
544 DPRINT1("Out of alternate lists!\n");
549 ExFreePool(*ResourceList
);
550 *ResourceList
= NULL
;
554 return STATUS_CONFLICTING_ADDRESSES
;
559 IopCheckResourceDescriptor(
560 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
561 IN PCM_RESOURCE_LIST ResourceList
,
563 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
566 BOOLEAN Result
= FALSE
;
567 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
569 FullDescriptor
= &ResourceList
->List
[0];
570 for (i
= 0; i
< ResourceList
->Count
; i
++)
572 PCM_PARTIAL_RESOURCE_LIST ResList
= &FullDescriptor
->PartialResourceList
;
573 FullDescriptor
= CmiGetNextResourceDescriptor(FullDescriptor
);
575 for (ii
= 0; ii
< ResList
->Count
; ii
++)
577 /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
578 but only one is allowed and it must be the last one in the list! */
579 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
581 /* We don't care about shared resources */
582 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
583 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
586 /* Make sure we're comparing the same types */
587 if (ResDesc
->Type
!= ResDesc2
->Type
)
590 switch (ResDesc
->Type
)
592 case CmResourceTypeMemory
:
593 if (((ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
< (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
&&
594 (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
595 (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
) || ((ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
<
596 (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
&& (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
+
597 ResDesc2
->u
.Memory
.Length
> (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
))
601 DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
602 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
603 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
604 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
613 case CmResourceTypePort
:
614 if (((ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
< (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
&&
615 (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
616 (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
) || ((ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
<
617 (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
&& (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
+
618 ResDesc2
->u
.Port
.Length
> (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
))
622 DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
623 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
624 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
625 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
634 case CmResourceTypeInterrupt
:
635 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
639 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
640 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
641 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
650 case CmResourceTypeBusNumber
:
651 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
652 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
653 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
654 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
655 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
659 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
660 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
661 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
662 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
671 case CmResourceTypeDma
:
672 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
676 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
677 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
678 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
692 if (Result
&& ConflictingDescriptor
)
694 RtlCopyMemory(ConflictingDescriptor
,
696 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
699 // Hacked, because after fixing resource list parsing
700 // we actually detect resource conflicts
701 return Silent
? Result
: FALSE
; // Result;
706 IopUpdateControlKeyWithResources(
707 IN PDEVICE_NODE DeviceNode
)
709 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
710 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
711 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
712 HANDLE EnumKey
, InstanceKey
, ControlKey
;
714 OBJECT_ATTRIBUTES ObjectAttributes
;
716 /* Open the Enum key */
717 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
718 if (!NT_SUCCESS(Status
))
721 /* Open the instance key (eg. Root\PNP0A03) */
722 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
725 if (!NT_SUCCESS(Status
))
728 /* Create/Open the Control key */
729 InitializeObjectAttributes(&ObjectAttributes
,
731 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
734 Status
= ZwCreateKey(&ControlKey
,
741 ZwClose(InstanceKey
);
743 if (!NT_SUCCESS(Status
))
746 /* Write the resource list */
747 Status
= ZwSetValueKey(ControlKey
,
751 DeviceNode
->ResourceList
,
752 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
755 if (!NT_SUCCESS(Status
))
758 return STATUS_SUCCESS
;
763 IopFilterResourceRequirements(
764 IN PDEVICE_NODE DeviceNode
)
766 IO_STACK_LOCATION Stack
;
767 IO_STATUS_BLOCK IoStatusBlock
;
770 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
772 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
773 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
775 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
777 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
779 DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
782 else if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
784 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
787 return STATUS_SUCCESS
;
792 IopUpdateResourceMap(
793 IN PDEVICE_NODE DeviceNode
,
799 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
800 UNICODE_STRING KeyName
;
801 OBJECT_ATTRIBUTES ObjectAttributes
;
803 RtlInitUnicodeString(&KeyName
,
804 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
805 InitializeObjectAttributes(&ObjectAttributes
,
807 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
810 Status
= ZwCreateKey(&ResourceMapKey
,
817 if (!NT_SUCCESS(Status
))
820 RtlInitUnicodeString(&KeyName
, Level1Key
);
821 InitializeObjectAttributes(&ObjectAttributes
,
823 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
826 Status
= ZwCreateKey(&PnpMgrLevel1
,
833 ZwClose(ResourceMapKey
);
834 if (!NT_SUCCESS(Status
))
837 RtlInitUnicodeString(&KeyName
, Level2Key
);
838 InitializeObjectAttributes(&ObjectAttributes
,
840 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
843 Status
= ZwCreateKey(&PnpMgrLevel2
,
850 ZwClose(PnpMgrLevel1
);
851 if (!NT_SUCCESS(Status
))
854 if (DeviceNode
->ResourceList
)
856 UNICODE_STRING NameU
;
857 UNICODE_STRING RawSuffix
, TranslatedSuffix
;
860 ASSERT(DeviceNode
->ResourceListTranslated
);
862 RtlInitUnicodeString(&TranslatedSuffix
, L
".Translated");
863 RtlInitUnicodeString(&RawSuffix
, L
".Raw");
865 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
866 DevicePropertyPhysicalDeviceObjectName
,
870 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
874 NameU
.Buffer
= ExAllocatePool(PagedPool
, OldLength
+ TranslatedSuffix
.Length
);
877 ZwClose(PnpMgrLevel2
);
878 return STATUS_INSUFFICIENT_RESOURCES
;
882 NameU
.MaximumLength
= (USHORT
)OldLength
+ TranslatedSuffix
.Length
;
884 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
885 DevicePropertyPhysicalDeviceObjectName
,
889 if (!NT_SUCCESS(Status
))
891 ZwClose(PnpMgrLevel2
);
892 ExFreePool(NameU
.Buffer
);
896 else if (!NT_SUCCESS(Status
))
899 ZwClose(PnpMgrLevel2
);
904 /* This should never happen */
908 NameU
.Length
= (USHORT
)OldLength
;
910 RtlAppendUnicodeStringToString(&NameU
, &RawSuffix
);
912 Status
= ZwSetValueKey(PnpMgrLevel2
,
916 DeviceNode
->ResourceList
,
917 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
918 if (!NT_SUCCESS(Status
))
920 ZwClose(PnpMgrLevel2
);
921 ExFreePool(NameU
.Buffer
);
925 /* "Remove" the suffix by setting the length back to what it used to be */
926 NameU
.Length
= (USHORT
)OldLength
;
928 RtlAppendUnicodeStringToString(&NameU
, &TranslatedSuffix
);
930 Status
= ZwSetValueKey(PnpMgrLevel2
,
934 DeviceNode
->ResourceListTranslated
,
935 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
936 ZwClose(PnpMgrLevel2
);
937 ExFreePool(NameU
.Buffer
);
939 if (!NT_SUCCESS(Status
))
944 ZwClose(PnpMgrLevel2
);
947 return STATUS_SUCCESS
;
951 IopUpdateResourceMapForPnPDevice(
952 IN PDEVICE_NODE DeviceNode
)
954 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
959 IopTranslateDeviceResources(
960 IN PDEVICE_NODE DeviceNode
)
962 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
963 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
964 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
965 ULONG i
, j
, ListSize
;
968 if (!DeviceNode
->ResourceList
)
970 DeviceNode
->ResourceListTranslated
= NULL
;
971 return STATUS_SUCCESS
;
974 /* That's easy to translate a resource list. Just copy the
975 * untranslated one and change few fields in the copy
977 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
979 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
980 if (!DeviceNode
->ResourceListTranslated
)
982 Status
= STATUS_NO_MEMORY
;
985 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
987 FullDescriptor
= &DeviceNode
->ResourceList
->List
[0];
988 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
990 pPartialResourceList
= &FullDescriptor
->PartialResourceList
;
991 FullDescriptor
= CmiGetNextResourceDescriptor(FullDescriptor
);
993 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
995 /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
996 but only one is allowed and it must be the last one in the list! */
997 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
999 /* Calculate the location of the translated resource descriptor */
1000 DescriptorTranslated
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)(
1001 (PUCHAR
)DeviceNode
->ResourceListTranslated
+
1002 ((PUCHAR
)DescriptorRaw
- (PUCHAR
)DeviceNode
->ResourceList
));
1004 switch (DescriptorRaw
->Type
)
1006 case CmResourceTypePort
:
1008 ULONG AddressSpace
= 1; /* IO space */
1009 if (!HalTranslateBusAddress(
1010 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1011 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1012 DescriptorRaw
->u
.Port
.Start
,
1014 &DescriptorTranslated
->u
.Port
.Start
))
1016 Status
= STATUS_UNSUCCESSFUL
;
1017 DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Port
.Start
.QuadPart
);
1021 if (AddressSpace
== 0)
1023 DPRINT1("Guessed incorrect address space: 1 -> 0\n");
1025 /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
1026 * invalid for this state but I'm not 100% sure */
1027 DescriptorRaw
->Flags
=
1028 DescriptorTranslated
->Flags
= CM_RESOURCE_PORT_MEMORY
;
1032 case CmResourceTypeInterrupt
:
1035 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1036 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1037 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1038 DescriptorRaw
->u
.Interrupt
.Level
,
1039 DescriptorRaw
->u
.Interrupt
.Vector
,
1041 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
1042 DescriptorTranslated
->u
.Interrupt
.Level
= Irql
;
1043 if (!DescriptorTranslated
->u
.Interrupt
.Vector
)
1045 Status
= STATUS_UNSUCCESSFUL
;
1046 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw
->u
.Interrupt
.Vector
,
1047 DescriptorRaw
->u
.Interrupt
.Level
);
1052 case CmResourceTypeMemory
:
1054 ULONG AddressSpace
= 0; /* Memory space */
1055 if (!HalTranslateBusAddress(
1056 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1057 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1058 DescriptorRaw
->u
.Memory
.Start
,
1060 &DescriptorTranslated
->u
.Memory
.Start
))
1062 Status
= STATUS_UNSUCCESSFUL
;
1063 DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Memory
.Start
.QuadPart
);
1067 if (AddressSpace
!= 0)
1069 DPRINT1("Guessed incorrect address space: 0 -> 1\n");
1071 /* This should never happen for memory space */
1076 case CmResourceTypeDma
:
1077 case CmResourceTypeBusNumber
:
1078 case CmResourceTypeDevicePrivate
:
1079 case CmResourceTypeDeviceSpecific
:
1083 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1084 Status
= STATUS_NOT_IMPLEMENTED
;
1089 return STATUS_SUCCESS
;
1092 /* Yes! Also delete ResourceList because ResourceList and
1093 * ResourceListTranslated should be a pair! */
1094 ExFreePool(DeviceNode
->ResourceList
);
1095 DeviceNode
->ResourceList
= NULL
;
1096 if (DeviceNode
->ResourceListTranslated
)
1098 ExFreePool(DeviceNode
->ResourceListTranslated
);
1099 DeviceNode
->ResourceList
= NULL
;
1106 IopAssignDeviceResources(
1107 IN PDEVICE_NODE DeviceNode
)
1112 Status
= IopFilterResourceRequirements(DeviceNode
);
1113 if (!NT_SUCCESS(Status
))
1116 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1118 /* No resource needed for this device */
1119 DeviceNode
->ResourceList
= NULL
;
1120 DeviceNode
->ResourceListTranslated
= NULL
;
1121 PiSetDevNodeState(DeviceNode
, DeviceNodeResourcesAssigned
);
1122 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
1124 return STATUS_SUCCESS
;
1127 if (DeviceNode
->BootResources
)
1129 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
1131 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
1132 if (!DeviceNode
->ResourceList
)
1134 Status
= STATUS_NO_MEMORY
;
1138 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
1140 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1141 if (!NT_SUCCESS(Status
))
1143 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1144 ExFreePool(DeviceNode
->ResourceList
);
1145 DeviceNode
->ResourceList
= NULL
;
1150 /* We'll make this from the requirements */
1151 DeviceNode
->ResourceList
= NULL
;
1154 /* No resources requirements */
1155 if (!DeviceNode
->ResourceRequirements
)
1158 /* Call HAL to fixup our resource requirements list */
1159 HalAdjustResourceList(&DeviceNode
->ResourceRequirements
);
1161 /* Add resource requirements that aren't in the list we already got */
1162 Status
= IopFixupResourceListWithRequirements(DeviceNode
->ResourceRequirements
,
1163 &DeviceNode
->ResourceList
);
1164 if (!NT_SUCCESS(Status
))
1166 DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode
->InstancePath
);
1167 DeviceNode
->Problem
= CM_PROB_NORMAL_CONFLICT
;
1171 /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */
1172 ASSERT(IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
) != STATUS_CONFLICTING_ADDRESSES
);
1175 Status
= IopTranslateDeviceResources(DeviceNode
);
1176 if (!NT_SUCCESS(Status
))
1178 DeviceNode
->Problem
= CM_PROB_TRANSLATION_FAILED
;
1179 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode
->InstancePath
);
1183 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
1184 if (!NT_SUCCESS(Status
))
1187 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
1188 if (!NT_SUCCESS(Status
))
1191 PiSetDevNodeState(DeviceNode
, DeviceNodeResourcesAssigned
);
1193 return STATUS_SUCCESS
;
1196 if (DeviceNode
->ResourceList
)
1198 ExFreePool(DeviceNode
->ResourceList
);
1199 DeviceNode
->ResourceList
= NULL
;
1202 DeviceNode
->ResourceListTranslated
= NULL
;
1209 IopCheckForResourceConflict(
1210 IN PCM_RESOURCE_LIST ResourceList1
,
1211 IN PCM_RESOURCE_LIST ResourceList2
,
1213 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1216 BOOLEAN Result
= FALSE
;
1217 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
1219 FullDescriptor
= &ResourceList1
->List
[0];
1220 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1222 PCM_PARTIAL_RESOURCE_LIST ResList
= &FullDescriptor
->PartialResourceList
;
1223 FullDescriptor
= CmiGetNextResourceDescriptor(FullDescriptor
);
1225 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1227 /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1228 but only one is allowed and it must be the last one in the list! */
1229 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1231 Result
= IopCheckResourceDescriptor(ResDesc
,
1234 ConflictingDescriptor
);
1235 if (Result
) goto ByeBye
;
1245 IopDetectResourceConflict(
1246 IN PCM_RESOURCE_LIST ResourceList
,
1248 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1250 OBJECT_ATTRIBUTES ObjectAttributes
;
1251 UNICODE_STRING KeyName
;
1252 HANDLE ResourceMapKey
= NULL
, ChildKey2
= NULL
, ChildKey3
= NULL
;
1253 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1254 PKEY_BASIC_INFORMATION KeyInformation
;
1255 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1256 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1257 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1260 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1261 InitializeObjectAttributes(&ObjectAttributes
,
1263 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1266 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1267 if (!NT_SUCCESS(Status
))
1269 /* The key is missing which means we are the first device */
1270 return STATUS_SUCCESS
;
1275 Status
= ZwEnumerateKey(ResourceMapKey
,
1277 KeyBasicInformation
,
1281 if (Status
== STATUS_NO_MORE_ENTRIES
)
1283 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1285 KeyInformationLength
= RequiredLength
;
1286 KeyInformation
= ExAllocatePoolWithTag(PagedPool
,
1287 KeyInformationLength
,
1289 if (!KeyInformation
)
1291 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1295 Status
= ZwEnumerateKey(ResourceMapKey
,
1297 KeyBasicInformation
,
1299 KeyInformationLength
,
1305 if (!NT_SUCCESS(Status
))
1307 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1311 KeyName
.Buffer
= KeyInformation
->Name
;
1312 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1313 InitializeObjectAttributes(&ObjectAttributes
,
1315 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1318 Status
= ZwOpenKey(&ChildKey2
,
1319 KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
1321 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1322 if (!NT_SUCCESS(Status
))
1327 Status
= ZwEnumerateKey(ChildKey2
,
1329 KeyBasicInformation
,
1333 if (Status
== STATUS_NO_MORE_ENTRIES
)
1335 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1337 KeyInformationLength
= RequiredLength
;
1338 KeyInformation
= ExAllocatePoolWithTag(PagedPool
,
1339 KeyInformationLength
,
1341 if (!KeyInformation
)
1343 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1347 Status
= ZwEnumerateKey(ChildKey2
,
1349 KeyBasicInformation
,
1351 KeyInformationLength
,
1357 if (!NT_SUCCESS(Status
))
1359 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1363 KeyName
.Buffer
= KeyInformation
->Name
;
1364 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1365 InitializeObjectAttributes(&ObjectAttributes
,
1367 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1370 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1371 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1372 if (!NT_SUCCESS(Status
))
1377 Status
= ZwEnumerateValueKey(ChildKey3
,
1379 KeyValuePartialInformation
,
1383 if (Status
== STATUS_NO_MORE_ENTRIES
)
1385 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1387 KeyValueInformationLength
= RequiredLength
;
1388 KeyValueInformation
= ExAllocatePoolWithTag(PagedPool
,
1389 KeyValueInformationLength
,
1391 if (!KeyValueInformation
)
1393 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1397 Status
= ZwEnumerateValueKey(ChildKey3
,
1399 KeyValuePartialInformation
,
1400 KeyValueInformation
,
1401 KeyValueInformationLength
,
1406 if (!NT_SUCCESS(Status
))
1408 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1412 Status
= ZwEnumerateValueKey(ChildKey3
,
1414 KeyValueBasicInformation
,
1418 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1420 KeyNameInformationLength
= RequiredLength
;
1421 KeyNameInformation
= ExAllocatePoolWithTag(PagedPool
,
1422 KeyNameInformationLength
+ sizeof(WCHAR
),
1424 if (!KeyNameInformation
)
1426 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1430 Status
= ZwEnumerateValueKey(ChildKey3
,
1432 KeyValueBasicInformation
,
1434 KeyNameInformationLength
,
1440 if (!NT_SUCCESS(Status
))
1442 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1446 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1448 /* Skip translated entries */
1449 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1451 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1452 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1456 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1458 if (IopCheckForResourceConflict(ResourceList
,
1459 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1461 ConflictingDescriptor
))
1463 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1464 Status
= STATUS_CONFLICTING_ADDRESSES
;
1468 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1474 if (ResourceMapKey
!= NULL
)
1475 ObCloseHandle(ResourceMapKey
, KernelMode
);
1476 if (ChildKey2
!= NULL
)
1477 ObCloseHandle(ChildKey2
, KernelMode
);
1478 if (ChildKey3
!= NULL
)
1479 ObCloseHandle(ChildKey3
, KernelMode
);
1481 if (Status
== STATUS_NO_MORE_ENTRIES
)
1482 Status
= STATUS_SUCCESS
;