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 IopCheckDescriptorForConflict(
18 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
,
19 OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
21 CM_RESOURCE_LIST CmList
;
25 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
26 CmList
.List
[0].BusNumber
= 0;
27 CmList
.List
[0].PartialResourceList
.Version
= 1;
28 CmList
.List
[0].PartialResourceList
.Revision
= 1;
29 CmList
.List
[0].PartialResourceList
.Count
= 1;
30 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
32 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
33 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
41 IopFindBusNumberResource(
42 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
43 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
46 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
48 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
49 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
51 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
52 Start
<= IoDesc
->u
.BusNumber
.MaxBusNumber
- IoDesc
->u
.BusNumber
.Length
+ 1;
55 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
56 CmDesc
->u
.BusNumber
.Start
= Start
;
58 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
60 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
64 DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start
, CmDesc
->u
.BusNumber
.Length
);
74 IopFindMemoryResource(
75 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
76 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
79 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
81 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
82 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
85 if (IoDesc
->u
.Memory
.Alignment
== 0)
86 IoDesc
->u
.Memory
.Alignment
= 1;
88 for (Start
= (ULONGLONG
)IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
89 Start
<= (ULONGLONG
)IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
- IoDesc
->u
.Memory
.Length
+ 1;
90 Start
+= IoDesc
->u
.Memory
.Alignment
)
92 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
93 CmDesc
->u
.Memory
.Start
.QuadPart
= (LONGLONG
)Start
;
95 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
97 Start
+= (ULONGLONG
)ConflictingDesc
.u
.Memory
.Start
.QuadPart
+
98 ConflictingDesc
.u
.Memory
.Length
;
102 DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start
, CmDesc
->u
.Memory
.Length
);
113 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
114 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
117 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
119 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
120 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
123 if (IoDesc
->u
.Port
.Alignment
== 0)
124 IoDesc
->u
.Port
.Alignment
= 1;
126 for (Start
= (ULONGLONG
)IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
127 Start
<= (ULONGLONG
)IoDesc
->u
.Port
.MaximumAddress
.QuadPart
- IoDesc
->u
.Port
.Length
+ 1;
128 Start
+= IoDesc
->u
.Port
.Alignment
)
130 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
131 CmDesc
->u
.Port
.Start
.QuadPart
= (LONGLONG
)Start
;
133 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
135 Start
+= (ULONGLONG
)ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
139 DPRINT("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start
, CmDesc
->u
.Port
.Length
);
144 DPRINT1("IopFindPortResource failed!\n");
151 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
152 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
156 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
157 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
159 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
160 Channel
<= IoDesc
->u
.Dma
.MaximumChannel
;
163 CmDesc
->u
.Dma
.Channel
= Channel
;
164 CmDesc
->u
.Dma
.Port
= 0;
166 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
168 DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel
);
178 IopFindInterruptResource(
179 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
180 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
184 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
185 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
187 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
188 Vector
<= IoDesc
->u
.Interrupt
.MaximumVector
;
191 CmDesc
->u
.Interrupt
.Vector
= Vector
;
192 CmDesc
->u
.Interrupt
.Level
= Vector
;
193 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
195 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
197 DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector
);
206 IopFixupResourceListWithRequirements(
207 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
208 OUT PCM_RESOURCE_LIST
*ResourceList
)
211 BOOLEAN AlternateRequired
= FALSE
;
213 /* Save the initial resource count when we got here so we can restore if an alternate fails */
214 if (*ResourceList
!= NULL
)
215 OldCount
= (*ResourceList
)->List
[0].PartialResourceList
.Count
;
219 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
222 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
224 /* We need to get back to where we were before processing the last alternative list */
225 if (OldCount
== 0 && *ResourceList
!= NULL
)
227 /* Just free it and kill the pointer */
228 ExFreePool(*ResourceList
);
229 *ResourceList
= NULL
;
231 else if (OldCount
!= 0)
233 PCM_RESOURCE_LIST NewList
;
235 /* Let's resize it */
236 (*ResourceList
)->List
[0].PartialResourceList
.Count
= OldCount
;
238 /* Allocate the new smaller list */
239 NewList
= ExAllocatePool(PagedPool
, PnpDetermineResourceListSize(*ResourceList
));
241 return STATUS_NO_MEMORY
;
243 /* Copy the old stuff back */
244 RtlCopyMemory(NewList
, *ResourceList
, PnpDetermineResourceListSize(*ResourceList
));
246 /* Free the old one */
247 ExFreePool(*ResourceList
);
249 /* Store the pointer to the new one */
250 *ResourceList
= NewList
;
253 for (ii
= 0; ii
< ResList
->Count
; ii
++)
256 PCM_PARTIAL_RESOURCE_LIST PartialList
= (*ResourceList
) ? &(*ResourceList
)->List
[0].PartialResourceList
: NULL
;
257 PIO_RESOURCE_DESCRIPTOR IoDesc
= &ResList
->Descriptors
[ii
];
258 BOOLEAN Matched
= FALSE
;
260 /* Skip alternates if we don't need one */
261 if (!AlternateRequired
&& (IoDesc
->Option
& IO_RESOURCE_ALTERNATIVE
))
263 DPRINT("Skipping unneeded alternate\n");
267 /* Check if we couldn't satsify a requirement or its alternates */
268 if (AlternateRequired
&& !(IoDesc
->Option
& IO_RESOURCE_ALTERNATIVE
))
270 DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i
);
272 /* Break out of this loop and try the next list */
276 for (iii
= 0; PartialList
&& iii
< PartialList
->Count
&& !Matched
; iii
++)
278 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
= &PartialList
->PartialDescriptors
[iii
];
280 /* First check types */
281 if (IoDesc
->Type
!= CmDesc
->Type
)
284 switch (IoDesc
->Type
)
286 case CmResourceTypeInterrupt
:
287 /* Make sure it satisfies our vector range */
288 if (CmDesc
->u
.Interrupt
.Vector
>= IoDesc
->u
.Interrupt
.MinimumVector
&&
289 CmDesc
->u
.Interrupt
.Vector
<= IoDesc
->u
.Interrupt
.MaximumVector
)
296 DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n",
297 CmDesc
->u
.Interrupt
.Vector
,
298 IoDesc
->u
.Interrupt
.MinimumVector
,
299 IoDesc
->u
.Interrupt
.MaximumVector
);
303 case CmResourceTypeMemory
:
304 case CmResourceTypePort
:
305 /* Make sure the length matches and it satisfies our address range */
306 if (CmDesc
->u
.Memory
.Length
== IoDesc
->u
.Memory
.Length
&&
307 (ULONGLONG
)CmDesc
->u
.Memory
.Start
.QuadPart
>= (ULONGLONG
)IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
&&
308 (ULONGLONG
)CmDesc
->u
.Memory
.Start
.QuadPart
+ CmDesc
->u
.Memory
.Length
- 1 <= (ULONGLONG
)IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
)
315 DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n",
316 CmDesc
->u
.Memory
.Start
.QuadPart
,
317 CmDesc
->u
.Memory
.Length
,
318 IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
,
319 IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
320 IoDesc
->u
.Memory
.Length
);
324 case CmResourceTypeBusNumber
:
325 /* Make sure the length matches and it satisfies our bus number range */
326 if (CmDesc
->u
.BusNumber
.Length
== IoDesc
->u
.BusNumber
.Length
&&
327 CmDesc
->u
.BusNumber
.Start
>= IoDesc
->u
.BusNumber
.MinBusNumber
&&
328 CmDesc
->u
.BusNumber
.Start
+ CmDesc
->u
.BusNumber
.Length
- 1 <= IoDesc
->u
.BusNumber
.MaxBusNumber
)
335 DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n",
336 CmDesc
->u
.BusNumber
.Start
,
337 CmDesc
->u
.BusNumber
.Length
,
338 IoDesc
->u
.BusNumber
.MinBusNumber
,
339 IoDesc
->u
.BusNumber
.MaxBusNumber
,
340 IoDesc
->u
.BusNumber
.Length
);
344 case CmResourceTypeDma
:
345 /* Make sure it fits in our channel range */
346 if (CmDesc
->u
.Dma
.Channel
>= IoDesc
->u
.Dma
.MinimumChannel
&&
347 CmDesc
->u
.Dma
.Channel
<= IoDesc
->u
.Dma
.MaximumChannel
)
354 DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n",
355 CmDesc
->u
.Dma
.Channel
,
356 IoDesc
->u
.Dma
.MinimumChannel
,
357 IoDesc
->u
.Dma
.MaximumChannel
);
362 /* Other stuff is fine */
368 /* Check if we found a matching descriptor */
371 PCM_RESOURCE_LIST NewList
;
372 CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc
;
373 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr
;
374 BOOLEAN FoundResource
= TRUE
;
376 /* Setup the new CM descriptor */
377 NewDesc
.Type
= IoDesc
->Type
;
378 NewDesc
.Flags
= IoDesc
->Flags
;
379 NewDesc
.ShareDisposition
= IoDesc
->ShareDisposition
;
381 /* Let'se see if we can find a resource to satisfy this */
382 switch (IoDesc
->Type
)
384 case CmResourceTypeInterrupt
:
385 /* Find an available interrupt */
386 if (!IopFindInterruptResource(IoDesc
, &NewDesc
))
388 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
389 IoDesc
->u
.Interrupt
.MinimumVector
, IoDesc
->u
.Interrupt
.MaximumVector
);
391 FoundResource
= FALSE
;
395 case CmResourceTypePort
:
396 /* Find an available port range */
397 if (!IopFindPortResource(IoDesc
, &NewDesc
))
399 DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
400 IoDesc
->u
.Port
.MinimumAddress
.QuadPart
, IoDesc
->u
.Port
.MaximumAddress
.QuadPart
,
401 IoDesc
->u
.Port
.Length
);
403 FoundResource
= FALSE
;
407 case CmResourceTypeMemory
:
408 /* Find an available memory range */
409 if (!IopFindMemoryResource(IoDesc
, &NewDesc
))
411 DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
412 IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
, IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
413 IoDesc
->u
.Memory
.Length
);
415 FoundResource
= FALSE
;
419 case CmResourceTypeBusNumber
:
420 /* Find an available bus address range */
421 if (!IopFindBusNumberResource(IoDesc
, &NewDesc
))
423 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
424 IoDesc
->u
.BusNumber
.MinBusNumber
, IoDesc
->u
.BusNumber
.MaxBusNumber
,
425 IoDesc
->u
.BusNumber
.Length
);
427 FoundResource
= FALSE
;
431 case CmResourceTypeDma
:
432 /* Find an available DMA channel */
433 if (!IopFindDmaResource(IoDesc
, &NewDesc
))
435 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
436 IoDesc
->u
.Dma
.MinimumChannel
, IoDesc
->u
.Dma
.MaximumChannel
);
438 FoundResource
= FALSE
;
443 DPRINT1("Unsupported resource type: %x\n", IoDesc
->Type
);
444 FoundResource
= FALSE
;
448 /* Check if it's missing and required */
449 if (!FoundResource
&& IoDesc
->Option
== 0)
451 /* Break out of this loop and try the next list */
452 DPRINT1("Unable to satisfy required resource in list %lu\n", i
);
455 else if (!FoundResource
)
457 /* Try an alternate for this preferred descriptor */
458 AlternateRequired
= TRUE
;
463 /* Move on to the next preferred or required descriptor after this one */
464 AlternateRequired
= FALSE
;
467 /* Figure out what we need */
468 if (PartialList
== NULL
)
470 /* We need a new list */
471 NewList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
473 return STATUS_NO_MEMORY
;
477 NewList
->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
478 NewList
->List
[0].BusNumber
= RequirementsList
->BusNumber
;
479 NewList
->List
[0].PartialResourceList
.Version
= 1;
480 NewList
->List
[0].PartialResourceList
.Revision
= 1;
481 NewList
->List
[0].PartialResourceList
.Count
= 1;
483 /* Set our pointer */
484 DescPtr
= &NewList
->List
[0].PartialResourceList
.PartialDescriptors
[0];
488 /* Allocate the new larger list */
489 NewList
= ExAllocatePool(PagedPool
, PnpDetermineResourceListSize(*ResourceList
) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
491 return STATUS_NO_MEMORY
;
493 /* Copy the old stuff back */
494 RtlCopyMemory(NewList
, *ResourceList
, PnpDetermineResourceListSize(*ResourceList
));
496 /* Set our pointer */
497 DescPtr
= &NewList
->List
[0].PartialResourceList
.PartialDescriptors
[NewList
->List
[0].PartialResourceList
.Count
];
499 /* Increment the descriptor count */
500 NewList
->List
[0].PartialResourceList
.Count
++;
502 /* Free the old list */
503 ExFreePool(*ResourceList
);
506 /* Copy the descriptor in */
509 /* Store the new list */
510 *ResourceList
= NewList
;
514 /* Check if we need an alternate with no resources left */
515 if (AlternateRequired
)
517 DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i
);
519 /* Try the next alternate list */
523 /* We're done because we satisfied one of the alternate lists */
524 return STATUS_SUCCESS
;
527 /* We ran out of alternates */
528 DPRINT1("Out of alternate lists!\n");
533 ExFreePool(*ResourceList
);
534 *ResourceList
= NULL
;
538 return STATUS_CONFLICTING_ADDRESSES
;
543 IopCheckResourceDescriptor(
544 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
545 IN PCM_RESOURCE_LIST ResourceList
,
547 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
550 BOOLEAN Result
= FALSE
;
552 for (i
= 0; i
< ResourceList
->Count
; i
++)
554 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
555 for (ii
= 0; ii
< ResList
->Count
; ii
++)
557 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
559 /* We don't care about shared resources */
560 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
561 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
564 /* Make sure we're comparing the same types */
565 if (ResDesc
->Type
!= ResDesc2
->Type
)
568 switch (ResDesc
->Type
)
570 case CmResourceTypeMemory
:
571 if (((ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
< (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
&&
572 (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
573 (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
) || ((ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
<
574 (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
&& (ULONGLONG
)ResDesc2
->u
.Memory
.Start
.QuadPart
+
575 ResDesc2
->u
.Memory
.Length
> (ULONGLONG
)ResDesc
->u
.Memory
.Start
.QuadPart
))
579 DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
580 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
581 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
582 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
591 case CmResourceTypePort
:
592 if (((ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
< (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
&&
593 (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
594 (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
) || ((ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
<
595 (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
&& (ULONGLONG
)ResDesc2
->u
.Port
.Start
.QuadPart
+
596 ResDesc2
->u
.Port
.Length
> (ULONGLONG
)ResDesc
->u
.Port
.Start
.QuadPart
))
600 DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
601 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
602 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
603 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
612 case CmResourceTypeInterrupt
:
613 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
617 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
618 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
619 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
628 case CmResourceTypeBusNumber
:
629 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
630 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
631 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
632 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
633 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
637 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
638 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
639 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
640 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
649 case CmResourceTypeDma
:
650 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
654 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
655 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
656 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
670 if (Result
&& ConflictingDescriptor
)
672 RtlCopyMemory(ConflictingDescriptor
,
674 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
682 IopUpdateControlKeyWithResources(
683 IN PDEVICE_NODE DeviceNode
)
685 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
686 UNICODE_STRING Control
= RTL_CONSTANT_STRING(L
"Control");
687 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"AllocConfig");
688 HANDLE EnumKey
, InstanceKey
, ControlKey
;
690 OBJECT_ATTRIBUTES ObjectAttributes
;
692 /* Open the Enum key */
693 Status
= IopOpenRegistryKeyEx(&EnumKey
, NULL
, &EnumRoot
, KEY_ENUMERATE_SUB_KEYS
);
694 if (!NT_SUCCESS(Status
))
697 /* Open the instance key (eg. Root\PNP0A03) */
698 Status
= IopOpenRegistryKeyEx(&InstanceKey
, EnumKey
, &DeviceNode
->InstancePath
, KEY_ENUMERATE_SUB_KEYS
);
701 if (!NT_SUCCESS(Status
))
704 /* Create/Open the Control key */
705 InitializeObjectAttributes(&ObjectAttributes
,
707 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
710 Status
= ZwCreateKey(&ControlKey
,
717 ZwClose(InstanceKey
);
719 if (!NT_SUCCESS(Status
))
722 /* Write the resource list */
723 Status
= ZwSetValueKey(ControlKey
,
727 DeviceNode
->ResourceList
,
728 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
731 if (!NT_SUCCESS(Status
))
734 return STATUS_SUCCESS
;
739 IopFilterResourceRequirements(
740 IN PDEVICE_NODE DeviceNode
)
742 IO_STACK_LOCATION Stack
;
743 IO_STATUS_BLOCK IoStatusBlock
;
746 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
748 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
749 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
751 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
753 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
755 DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
758 else if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
760 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
763 return STATUS_SUCCESS
;
768 IopUpdateResourceMap(
769 IN PDEVICE_NODE DeviceNode
,
775 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
776 UNICODE_STRING KeyName
;
777 OBJECT_ATTRIBUTES ObjectAttributes
;
779 RtlInitUnicodeString(&KeyName
,
780 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
781 InitializeObjectAttributes(&ObjectAttributes
,
783 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
786 Status
= ZwCreateKey(&ResourceMapKey
,
793 if (!NT_SUCCESS(Status
))
796 RtlInitUnicodeString(&KeyName
, Level1Key
);
797 InitializeObjectAttributes(&ObjectAttributes
,
799 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
802 Status
= ZwCreateKey(&PnpMgrLevel1
,
809 ZwClose(ResourceMapKey
);
810 if (!NT_SUCCESS(Status
))
813 RtlInitUnicodeString(&KeyName
, Level2Key
);
814 InitializeObjectAttributes(&ObjectAttributes
,
816 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_KERNEL_HANDLE
,
819 Status
= ZwCreateKey(&PnpMgrLevel2
,
826 ZwClose(PnpMgrLevel1
);
827 if (!NT_SUCCESS(Status
))
830 if (DeviceNode
->ResourceList
)
832 UNICODE_STRING NameU
;
833 UNICODE_STRING RawSuffix
, TranslatedSuffix
;
836 ASSERT(DeviceNode
->ResourceListTranslated
);
838 RtlInitUnicodeString(&TranslatedSuffix
, L
".Translated");
839 RtlInitUnicodeString(&RawSuffix
, L
".Raw");
841 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
842 DevicePropertyPhysicalDeviceObjectName
,
846 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
850 NameU
.Buffer
= ExAllocatePool(PagedPool
, OldLength
+ TranslatedSuffix
.Length
);
853 ZwClose(PnpMgrLevel2
);
854 return STATUS_INSUFFICIENT_RESOURCES
;
858 NameU
.MaximumLength
= (USHORT
)OldLength
+ TranslatedSuffix
.Length
;
860 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
861 DevicePropertyPhysicalDeviceObjectName
,
865 if (!NT_SUCCESS(Status
))
867 ZwClose(PnpMgrLevel2
);
868 ExFreePool(NameU
.Buffer
);
872 else if (!NT_SUCCESS(Status
))
875 ZwClose(PnpMgrLevel2
);
880 /* This should never happen */
884 NameU
.Length
= (USHORT
)OldLength
;
886 RtlAppendUnicodeStringToString(&NameU
, &RawSuffix
);
888 Status
= ZwSetValueKey(PnpMgrLevel2
,
892 DeviceNode
->ResourceList
,
893 PnpDetermineResourceListSize(DeviceNode
->ResourceList
));
894 if (!NT_SUCCESS(Status
))
896 ZwClose(PnpMgrLevel2
);
897 ExFreePool(NameU
.Buffer
);
901 /* "Remove" the suffix by setting the length back to what it used to be */
902 NameU
.Length
= (USHORT
)OldLength
;
904 RtlAppendUnicodeStringToString(&NameU
, &TranslatedSuffix
);
906 Status
= ZwSetValueKey(PnpMgrLevel2
,
910 DeviceNode
->ResourceListTranslated
,
911 PnpDetermineResourceListSize(DeviceNode
->ResourceListTranslated
));
912 ZwClose(PnpMgrLevel2
);
913 ExFreePool(NameU
.Buffer
);
915 if (!NT_SUCCESS(Status
))
920 ZwClose(PnpMgrLevel2
);
923 return STATUS_SUCCESS
;
927 IopUpdateResourceMapForPnPDevice(
928 IN PDEVICE_NODE DeviceNode
)
930 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
935 IopTranslateDeviceResources(
936 IN PDEVICE_NODE DeviceNode
)
938 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
939 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
940 ULONG i
, j
, ListSize
;
943 if (!DeviceNode
->ResourceList
)
945 DeviceNode
->ResourceListTranslated
= NULL
;
946 return STATUS_SUCCESS
;
949 /* That's easy to translate a resource list. Just copy the
950 * untranslated one and change few fields in the copy
952 ListSize
= PnpDetermineResourceListSize(DeviceNode
->ResourceList
);
954 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, ListSize
);
955 if (!DeviceNode
->ResourceListTranslated
)
957 Status
= STATUS_NO_MEMORY
;
960 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, ListSize
);
962 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
964 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
965 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
967 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
968 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
969 switch (DescriptorRaw
->Type
)
971 case CmResourceTypePort
:
973 ULONG AddressSpace
= 1; /* IO space */
974 if (!HalTranslateBusAddress(
975 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
976 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
977 DescriptorRaw
->u
.Port
.Start
,
979 &DescriptorTranslated
->u
.Port
.Start
))
981 Status
= STATUS_UNSUCCESSFUL
;
982 DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Port
.Start
.QuadPart
);
986 if (AddressSpace
== 0)
988 DPRINT1("Guessed incorrect address space: 1 -> 0\n");
990 /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
991 * invalid for this state but I'm not 100% sure */
992 DescriptorRaw
->Flags
=
993 DescriptorTranslated
->Flags
= CM_RESOURCE_PORT_MEMORY
;
997 case CmResourceTypeInterrupt
:
999 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1000 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1001 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1002 DescriptorRaw
->u
.Interrupt
.Level
,
1003 DescriptorRaw
->u
.Interrupt
.Vector
,
1004 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1005 &DescriptorTranslated
->u
.Interrupt
.Affinity
);
1007 if (!DescriptorTranslated
->u
.Interrupt
.Vector
)
1009 Status
= STATUS_UNSUCCESSFUL
;
1010 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw
->u
.Interrupt
.Vector
,
1011 DescriptorRaw
->u
.Interrupt
.Level
);
1016 case CmResourceTypeMemory
:
1018 ULONG AddressSpace
= 0; /* Memory space */
1019 if (!HalTranslateBusAddress(
1020 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1021 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1022 DescriptorRaw
->u
.Memory
.Start
,
1024 &DescriptorTranslated
->u
.Memory
.Start
))
1026 Status
= STATUS_UNSUCCESSFUL
;
1027 DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw
->u
.Memory
.Start
.QuadPart
);
1031 if (AddressSpace
!= 0)
1033 DPRINT1("Guessed incorrect address space: 0 -> 1\n");
1035 /* This should never happen for memory space */
1040 case CmResourceTypeDma
:
1041 case CmResourceTypeBusNumber
:
1042 case CmResourceTypeDeviceSpecific
:
1046 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1047 Status
= STATUS_NOT_IMPLEMENTED
;
1052 return STATUS_SUCCESS
;
1055 /* Yes! Also delete ResourceList because ResourceList and
1056 * ResourceListTranslated should be a pair! */
1057 ExFreePool(DeviceNode
->ResourceList
);
1058 DeviceNode
->ResourceList
= NULL
;
1059 if (DeviceNode
->ResourceListTranslated
)
1061 ExFreePool(DeviceNode
->ResourceListTranslated
);
1062 DeviceNode
->ResourceList
= NULL
;
1069 IopAssignDeviceResources(
1070 IN PDEVICE_NODE DeviceNode
)
1075 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1077 Status
= IopFilterResourceRequirements(DeviceNode
);
1078 if (!NT_SUCCESS(Status
))
1081 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1083 DeviceNode
->Flags
|= DNF_NO_RESOURCE_REQUIRED
;
1084 DeviceNode
->Flags
&= ~DNF_ASSIGNING_RESOURCES
;
1086 /* No resource needed for this device */
1087 DeviceNode
->ResourceList
= NULL
;
1088 DeviceNode
->ResourceListTranslated
= NULL
;
1090 return STATUS_SUCCESS
;
1093 if (DeviceNode
->BootResources
)
1095 ListSize
= PnpDetermineResourceListSize(DeviceNode
->BootResources
);
1097 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
1098 if (!DeviceNode
->ResourceList
)
1100 Status
= STATUS_NO_MEMORY
;
1104 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, ListSize
);
1106 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1107 if (!NT_SUCCESS(Status
))
1109 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1110 ExFreePool(DeviceNode
->ResourceList
);
1111 DeviceNode
->ResourceList
= NULL
;
1116 /* We'll make this from the requirements */
1117 DeviceNode
->ResourceList
= NULL
;
1120 /* No resources requirements */
1121 if (!DeviceNode
->ResourceRequirements
)
1124 /* Call HAL to fixup our resource requirements list */
1125 HalAdjustResourceList(&DeviceNode
->ResourceRequirements
);
1127 /* Add resource requirements that aren't in the list we already got */
1128 Status
= IopFixupResourceListWithRequirements(DeviceNode
->ResourceRequirements
,
1129 &DeviceNode
->ResourceList
);
1130 if (!NT_SUCCESS(Status
))
1132 DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode
->InstancePath
);
1133 DeviceNode
->Problem
= CM_PROB_NORMAL_CONFLICT
;
1137 /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */
1138 ASSERT(IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
) != STATUS_CONFLICTING_ADDRESSES
);
1141 Status
= IopTranslateDeviceResources(DeviceNode
);
1142 if (!NT_SUCCESS(Status
))
1144 DeviceNode
->Problem
= CM_PROB_TRANSLATION_FAILED
;
1145 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode
->InstancePath
);
1149 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
1150 if (!NT_SUCCESS(Status
))
1153 Status
= IopUpdateControlKeyWithResources(DeviceNode
);
1154 if (!NT_SUCCESS(Status
))
1157 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
1159 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1161 return STATUS_SUCCESS
;
1164 if (DeviceNode
->ResourceList
)
1166 ExFreePool(DeviceNode
->ResourceList
);
1167 DeviceNode
->ResourceList
= NULL
;
1170 DeviceNode
->ResourceListTranslated
= NULL
;
1172 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1179 IopCheckForResourceConflict(
1180 IN PCM_RESOURCE_LIST ResourceList1
,
1181 IN PCM_RESOURCE_LIST ResourceList2
,
1183 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1186 BOOLEAN Result
= FALSE
;
1188 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1190 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
1191 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1193 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1195 Result
= IopCheckResourceDescriptor(ResDesc
,
1198 ConflictingDescriptor
);
1199 if (Result
) goto ByeBye
;
1209 IopDetectResourceConflict(
1210 IN PCM_RESOURCE_LIST ResourceList
,
1212 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1214 OBJECT_ATTRIBUTES ObjectAttributes
;
1215 UNICODE_STRING KeyName
;
1216 HANDLE ResourceMapKey
= NULL
, ChildKey2
= NULL
, ChildKey3
= NULL
;
1217 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1218 PKEY_BASIC_INFORMATION KeyInformation
;
1219 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1220 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1221 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1224 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1225 InitializeObjectAttributes(&ObjectAttributes
,
1227 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1230 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1231 if (!NT_SUCCESS(Status
))
1233 /* The key is missing which means we are the first device */
1234 return STATUS_SUCCESS
;
1239 Status
= ZwEnumerateKey(ResourceMapKey
,
1241 KeyBasicInformation
,
1245 if (Status
== STATUS_NO_MORE_ENTRIES
)
1247 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1249 KeyInformationLength
= RequiredLength
;
1250 KeyInformation
= ExAllocatePoolWithTag(PagedPool
,
1251 KeyInformationLength
,
1253 if (!KeyInformation
)
1255 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1259 Status
= ZwEnumerateKey(ResourceMapKey
,
1261 KeyBasicInformation
,
1263 KeyInformationLength
,
1269 if (!NT_SUCCESS(Status
))
1271 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1275 KeyName
.Buffer
= KeyInformation
->Name
;
1276 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1277 InitializeObjectAttributes(&ObjectAttributes
,
1279 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1282 Status
= ZwOpenKey(&ChildKey2
,
1283 KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
1285 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1286 if (!NT_SUCCESS(Status
))
1291 Status
= ZwEnumerateKey(ChildKey2
,
1293 KeyBasicInformation
,
1297 if (Status
== STATUS_NO_MORE_ENTRIES
)
1299 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1301 KeyInformationLength
= RequiredLength
;
1302 KeyInformation
= ExAllocatePoolWithTag(PagedPool
,
1303 KeyInformationLength
,
1305 if (!KeyInformation
)
1307 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1311 Status
= ZwEnumerateKey(ChildKey2
,
1313 KeyBasicInformation
,
1315 KeyInformationLength
,
1321 if (!NT_SUCCESS(Status
))
1323 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1327 KeyName
.Buffer
= KeyInformation
->Name
;
1328 KeyName
.MaximumLength
= KeyName
.Length
= (USHORT
)KeyInformation
->NameLength
;
1329 InitializeObjectAttributes(&ObjectAttributes
,
1331 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1334 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1335 ExFreePoolWithTag(KeyInformation
, TAG_IO
);
1336 if (!NT_SUCCESS(Status
))
1341 Status
= ZwEnumerateValueKey(ChildKey3
,
1343 KeyValuePartialInformation
,
1347 if (Status
== STATUS_NO_MORE_ENTRIES
)
1349 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1351 KeyValueInformationLength
= RequiredLength
;
1352 KeyValueInformation
= ExAllocatePoolWithTag(PagedPool
,
1353 KeyValueInformationLength
,
1355 if (!KeyValueInformation
)
1357 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1361 Status
= ZwEnumerateValueKey(ChildKey3
,
1363 KeyValuePartialInformation
,
1364 KeyValueInformation
,
1365 KeyValueInformationLength
,
1370 if (!NT_SUCCESS(Status
))
1372 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1376 Status
= ZwEnumerateValueKey(ChildKey3
,
1378 KeyValueBasicInformation
,
1382 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1384 KeyNameInformationLength
= RequiredLength
;
1385 KeyNameInformation
= ExAllocatePoolWithTag(PagedPool
,
1386 KeyNameInformationLength
+ sizeof(WCHAR
),
1388 if (!KeyNameInformation
)
1390 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1394 Status
= ZwEnumerateValueKey(ChildKey3
,
1396 KeyValueBasicInformation
,
1398 KeyNameInformationLength
,
1404 if (!NT_SUCCESS(Status
))
1406 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1410 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1412 /* Skip translated entries */
1413 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1415 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1416 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1420 ExFreePoolWithTag(KeyNameInformation
, TAG_IO
);
1422 if (IopCheckForResourceConflict(ResourceList
,
1423 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1425 ConflictingDescriptor
))
1427 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1428 Status
= STATUS_CONFLICTING_ADDRESSES
;
1432 ExFreePoolWithTag(KeyValueInformation
, TAG_IO
);
1438 if (ResourceMapKey
!= NULL
)
1439 ObCloseHandle(ResourceMapKey
, KernelMode
);
1440 if (ChildKey2
!= NULL
)
1441 ObCloseHandle(ChildKey2
, KernelMode
);
1442 if (ChildKey3
!= NULL
)
1443 ObCloseHandle(ChildKey3
, KernelMode
);
1445 if (Status
== STATUS_NO_MORE_ENTRIES
)
1446 Status
= STATUS_SUCCESS
;