xref: /reactos/ntoskrnl/io/pnpmgr/pnpres.c (revision 49358f34)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS Kernel
3c2c66affSColin Finck  * COPYRIGHT:       GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            ntoskrnl/io/pnpmgr/pnpres.c
5c2c66affSColin Finck  * PURPOSE:         Resource handling code
6c2c66affSColin Finck  * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
7c2c66affSColin Finck  *                  ReactOS Portable Systems Group
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include <ntoskrnl.h>
11c2c66affSColin Finck 
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck 
15b82bf8ceSTimo Kreuzer FORCEINLINE
16b82bf8ceSTimo Kreuzer PIO_RESOURCE_LIST
IopGetNextResourceList(_In_ const IO_RESOURCE_LIST * ResourceList)17b82bf8ceSTimo Kreuzer IopGetNextResourceList(
18b82bf8ceSTimo Kreuzer     _In_ const IO_RESOURCE_LIST *ResourceList)
19b82bf8ceSTimo Kreuzer {
20b82bf8ceSTimo Kreuzer     ASSERT((ResourceList->Count > 0) && (ResourceList->Count < 1000));
21b82bf8ceSTimo Kreuzer     return (PIO_RESOURCE_LIST)(
22b82bf8ceSTimo Kreuzer         &ResourceList->Descriptors[ResourceList->Count]);
23b82bf8ceSTimo Kreuzer }
24b82bf8ceSTimo Kreuzer 
25c2c66affSColin Finck static
26c2c66affSColin Finck BOOLEAN
IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc,OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)279538c3ccSEric Kohl IopCheckDescriptorForConflict(
289538c3ccSEric Kohl     PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc,
299538c3ccSEric Kohl     OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
30c2c66affSColin Finck {
31c2c66affSColin Finck     CM_RESOURCE_LIST CmList;
32c2c66affSColin Finck     NTSTATUS Status;
33c2c66affSColin Finck 
34c2c66affSColin Finck     CmList.Count = 1;
35c2c66affSColin Finck     CmList.List[0].InterfaceType = InterfaceTypeUndefined;
36c2c66affSColin Finck     CmList.List[0].BusNumber = 0;
37c2c66affSColin Finck     CmList.List[0].PartialResourceList.Version = 1;
38c2c66affSColin Finck     CmList.List[0].PartialResourceList.Revision = 1;
39c2c66affSColin Finck     CmList.List[0].PartialResourceList.Count = 1;
40c2c66affSColin Finck     CmList.List[0].PartialResourceList.PartialDescriptors[0] = *CmDesc;
41c2c66affSColin Finck 
42c2c66affSColin Finck     Status = IopDetectResourceConflict(&CmList, TRUE, ConflictingDescriptor);
43c2c66affSColin Finck     if (Status == STATUS_CONFLICTING_ADDRESSES)
44c2c66affSColin Finck         return TRUE;
45c2c66affSColin Finck 
46c2c66affSColin Finck     return FALSE;
47c2c66affSColin Finck }
48c2c66affSColin Finck 
49c2c66affSColin Finck static
50c2c66affSColin Finck BOOLEAN
IopFindBusNumberResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)51c2c66affSColin Finck IopFindBusNumberResource(
52c2c66affSColin Finck     IN PIO_RESOURCE_DESCRIPTOR IoDesc,
53c2c66affSColin Finck     OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
54c2c66affSColin Finck {
55c2c66affSColin Finck     ULONG Start;
56c2c66affSColin Finck     CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
57c2c66affSColin Finck 
58c2c66affSColin Finck     ASSERT(IoDesc->Type == CmDesc->Type);
59c2c66affSColin Finck     ASSERT(IoDesc->Type == CmResourceTypeBusNumber);
60c2c66affSColin Finck 
61c2c66affSColin Finck     for (Start = IoDesc->u.BusNumber.MinBusNumber;
62c2c66affSColin Finck          Start <= IoDesc->u.BusNumber.MaxBusNumber - IoDesc->u.BusNumber.Length + 1;
63c2c66affSColin Finck          Start++)
64c2c66affSColin Finck     {
65c2c66affSColin Finck         CmDesc->u.BusNumber.Length = IoDesc->u.BusNumber.Length;
66c2c66affSColin Finck         CmDesc->u.BusNumber.Start = Start;
67c2c66affSColin Finck 
68c2c66affSColin Finck         if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
69c2c66affSColin Finck         {
70c2c66affSColin Finck             Start += ConflictingDesc.u.BusNumber.Start + ConflictingDesc.u.BusNumber.Length;
71c2c66affSColin Finck         }
72c2c66affSColin Finck         else
73c2c66affSColin Finck         {
74c2c66affSColin Finck             DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start, CmDesc->u.BusNumber.Length);
75c2c66affSColin Finck             return TRUE;
76c2c66affSColin Finck         }
77c2c66affSColin Finck     }
78c2c66affSColin Finck 
79c2c66affSColin Finck     return FALSE;
80c2c66affSColin Finck }
81c2c66affSColin Finck 
82c2c66affSColin Finck static
83c2c66affSColin Finck BOOLEAN
IopFindMemoryResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)84c2c66affSColin Finck IopFindMemoryResource(
85c2c66affSColin Finck     IN PIO_RESOURCE_DESCRIPTOR IoDesc,
86c2c66affSColin Finck     OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
87c2c66affSColin Finck {
88c2c66affSColin Finck     ULONGLONG Start;
89c2c66affSColin Finck     CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
90c2c66affSColin Finck 
91c2c66affSColin Finck     ASSERT(IoDesc->Type == CmDesc->Type);
92c2c66affSColin Finck     ASSERT(IoDesc->Type == CmResourceTypeMemory);
93c2c66affSColin Finck 
94c2c66affSColin Finck     /* HACK */
959538c3ccSEric Kohl     if (IoDesc->u.Memory.Alignment == 0)
969538c3ccSEric Kohl         IoDesc->u.Memory.Alignment = 1;
97c2c66affSColin Finck 
98c2c66affSColin Finck     for (Start = (ULONGLONG)IoDesc->u.Memory.MinimumAddress.QuadPart;
99c2c66affSColin Finck          Start <= (ULONGLONG)IoDesc->u.Memory.MaximumAddress.QuadPart - IoDesc->u.Memory.Length + 1;
100c2c66affSColin Finck          Start += IoDesc->u.Memory.Alignment)
101c2c66affSColin Finck     {
102c2c66affSColin Finck         CmDesc->u.Memory.Length = IoDesc->u.Memory.Length;
103c2c66affSColin Finck         CmDesc->u.Memory.Start.QuadPart = (LONGLONG)Start;
104c2c66affSColin Finck 
105c2c66affSColin Finck         if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
106c2c66affSColin Finck         {
107c2c66affSColin Finck             Start += (ULONGLONG)ConflictingDesc.u.Memory.Start.QuadPart +
108c2c66affSColin Finck                      ConflictingDesc.u.Memory.Length;
109c2c66affSColin Finck         }
110c2c66affSColin Finck         else
111c2c66affSColin Finck         {
112c2c66affSColin Finck             DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Memory.Length);
113c2c66affSColin Finck             return TRUE;
114c2c66affSColin Finck         }
115c2c66affSColin Finck     }
116c2c66affSColin Finck 
117c2c66affSColin Finck     return FALSE;
118c2c66affSColin Finck }
119c2c66affSColin Finck 
120c2c66affSColin Finck static
121c2c66affSColin Finck BOOLEAN
IopFindPortResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)122c2c66affSColin Finck IopFindPortResource(
123c2c66affSColin Finck     IN PIO_RESOURCE_DESCRIPTOR IoDesc,
124c2c66affSColin Finck     OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
125c2c66affSColin Finck {
126c2c66affSColin Finck     ULONGLONG Start;
127c2c66affSColin Finck     CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc;
128c2c66affSColin Finck 
129c2c66affSColin Finck     ASSERT(IoDesc->Type == CmDesc->Type);
130c2c66affSColin Finck     ASSERT(IoDesc->Type == CmResourceTypePort);
131c2c66affSColin Finck 
132c2c66affSColin Finck     /* HACK */
1339538c3ccSEric Kohl     if (IoDesc->u.Port.Alignment == 0)
1349538c3ccSEric Kohl         IoDesc->u.Port.Alignment = 1;
135c2c66affSColin Finck 
136c2c66affSColin Finck     for (Start = (ULONGLONG)IoDesc->u.Port.MinimumAddress.QuadPart;
137c2c66affSColin Finck          Start <= (ULONGLONG)IoDesc->u.Port.MaximumAddress.QuadPart - IoDesc->u.Port.Length + 1;
138c2c66affSColin Finck          Start += IoDesc->u.Port.Alignment)
139c2c66affSColin Finck     {
140c2c66affSColin Finck         CmDesc->u.Port.Length = IoDesc->u.Port.Length;
141c2c66affSColin Finck         CmDesc->u.Port.Start.QuadPart = (LONGLONG)Start;
142c2c66affSColin Finck 
143c2c66affSColin Finck         if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc))
144c2c66affSColin Finck         {
145c2c66affSColin Finck             Start += (ULONGLONG)ConflictingDesc.u.Port.Start.QuadPart + ConflictingDesc.u.Port.Length;
146c2c66affSColin Finck         }
147c2c66affSColin Finck         else
148c2c66affSColin Finck         {
149c2c66affSColin Finck             DPRINT("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Port.Length);
150c2c66affSColin Finck             return TRUE;
151c2c66affSColin Finck         }
152c2c66affSColin Finck     }
153c2c66affSColin Finck 
154c2c66affSColin Finck     DPRINT1("IopFindPortResource failed!\n");
155c2c66affSColin Finck     return FALSE;
156c2c66affSColin Finck }
157c2c66affSColin Finck 
158c2c66affSColin Finck static
159c2c66affSColin Finck BOOLEAN
IopFindDmaResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)160c2c66affSColin Finck IopFindDmaResource(
161c2c66affSColin Finck     IN PIO_RESOURCE_DESCRIPTOR IoDesc,
162c2c66affSColin Finck     OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
163c2c66affSColin Finck {
164c2c66affSColin Finck     ULONG Channel;
165c2c66affSColin Finck 
166c2c66affSColin Finck     ASSERT(IoDesc->Type == CmDesc->Type);
167c2c66affSColin Finck     ASSERT(IoDesc->Type == CmResourceTypeDma);
168c2c66affSColin Finck 
169c2c66affSColin Finck     for (Channel = IoDesc->u.Dma.MinimumChannel;
170c2c66affSColin Finck          Channel <= IoDesc->u.Dma.MaximumChannel;
171c2c66affSColin Finck          Channel++)
172c2c66affSColin Finck     {
173c2c66affSColin Finck         CmDesc->u.Dma.Channel = Channel;
174c2c66affSColin Finck         CmDesc->u.Dma.Port = 0;
175c2c66affSColin Finck 
176c2c66affSColin Finck         if (!IopCheckDescriptorForConflict(CmDesc, NULL))
177c2c66affSColin Finck         {
178c2c66affSColin Finck             DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel);
179c2c66affSColin Finck             return TRUE;
180c2c66affSColin Finck         }
181c2c66affSColin Finck     }
182c2c66affSColin Finck 
183c2c66affSColin Finck     return FALSE;
184c2c66affSColin Finck }
185c2c66affSColin Finck 
186c2c66affSColin Finck static
187c2c66affSColin Finck BOOLEAN
IopFindInterruptResource(IN PIO_RESOURCE_DESCRIPTOR IoDesc,OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)188c2c66affSColin Finck IopFindInterruptResource(
189c2c66affSColin Finck     IN PIO_RESOURCE_DESCRIPTOR IoDesc,
190c2c66affSColin Finck     OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc)
191c2c66affSColin Finck {
192c2c66affSColin Finck     ULONG Vector;
193c2c66affSColin Finck 
194c2c66affSColin Finck     ASSERT(IoDesc->Type == CmDesc->Type);
195c2c66affSColin Finck     ASSERT(IoDesc->Type == CmResourceTypeInterrupt);
196c2c66affSColin Finck 
197c2c66affSColin Finck     for (Vector = IoDesc->u.Interrupt.MinimumVector;
198c2c66affSColin Finck          Vector <= IoDesc->u.Interrupt.MaximumVector;
199c2c66affSColin Finck          Vector++)
200c2c66affSColin Finck     {
201c2c66affSColin Finck         CmDesc->u.Interrupt.Vector = Vector;
202c2c66affSColin Finck         CmDesc->u.Interrupt.Level = Vector;
203c2c66affSColin Finck         CmDesc->u.Interrupt.Affinity = (KAFFINITY)-1;
204c2c66affSColin Finck 
205c2c66affSColin Finck         if (!IopCheckDescriptorForConflict(CmDesc, NULL))
206c2c66affSColin Finck         {
207c2c66affSColin Finck             DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector);
208c2c66affSColin Finck             return TRUE;
209c2c66affSColin Finck         }
210c2c66affSColin Finck     }
211c2c66affSColin Finck 
212b82bf8ceSTimo Kreuzer     DPRINT1("Failed to satisfy interrupt requirement with IRQ 0x%x-0x%x\n",
213b82bf8ceSTimo Kreuzer             IoDesc->u.Interrupt.MinimumVector,
214b82bf8ceSTimo Kreuzer             IoDesc->u.Interrupt.MaximumVector);
215c2c66affSColin Finck     return FALSE;
216c2c66affSColin Finck }
217c2c66affSColin Finck 
218c2c66affSColin Finck NTSTATUS NTAPI
IopFixupResourceListWithRequirements(IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,OUT PCM_RESOURCE_LIST * ResourceList)219c2c66affSColin Finck IopFixupResourceListWithRequirements(
220c2c66affSColin Finck     IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
221c2c66affSColin Finck     OUT PCM_RESOURCE_LIST *ResourceList)
222c2c66affSColin Finck {
223c2c66affSColin Finck     ULONG i, OldCount;
224c2c66affSColin Finck     BOOLEAN AlternateRequired = FALSE;
225b82bf8ceSTimo Kreuzer     PIO_RESOURCE_LIST ResList;
226c2c66affSColin Finck 
227c2c66affSColin Finck     /* Save the initial resource count when we got here so we can restore if an alternate fails */
228c2c66affSColin Finck     if (*ResourceList != NULL)
229c2c66affSColin Finck         OldCount = (*ResourceList)->List[0].PartialResourceList.Count;
230c2c66affSColin Finck     else
231c2c66affSColin Finck         OldCount = 0;
232c2c66affSColin Finck 
233b82bf8ceSTimo Kreuzer     ResList = &RequirementsList->List[0];
234b82bf8ceSTimo Kreuzer     for (i = 0; i < RequirementsList->AlternativeLists; i++, ResList = IopGetNextResourceList(ResList))
235c2c66affSColin Finck     {
236c2c66affSColin Finck         ULONG ii;
237c2c66affSColin Finck 
238c2c66affSColin Finck         /* We need to get back to where we were before processing the last alternative list */
239c2c66affSColin Finck         if (OldCount == 0 && *ResourceList != NULL)
240c2c66affSColin Finck         {
241c2c66affSColin Finck             /* Just free it and kill the pointer */
242c2c66affSColin Finck             ExFreePool(*ResourceList);
243c2c66affSColin Finck             *ResourceList = NULL;
244c2c66affSColin Finck         }
245c2c66affSColin Finck         else if (OldCount != 0)
246c2c66affSColin Finck         {
247c2c66affSColin Finck             PCM_RESOURCE_LIST NewList;
248c2c66affSColin Finck 
249c2c66affSColin Finck             /* Let's resize it */
250c2c66affSColin Finck             (*ResourceList)->List[0].PartialResourceList.Count = OldCount;
251c2c66affSColin Finck 
252c2c66affSColin Finck             /* Allocate the new smaller list */
253c2c66affSColin Finck             NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList));
254c2c66affSColin Finck             if (!NewList)
255c2c66affSColin Finck                 return STATUS_NO_MEMORY;
256c2c66affSColin Finck 
257c2c66affSColin Finck             /* Copy the old stuff back */
258c2c66affSColin Finck             RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
259c2c66affSColin Finck 
260c2c66affSColin Finck             /* Free the old one */
261c2c66affSColin Finck             ExFreePool(*ResourceList);
262c2c66affSColin Finck 
263c2c66affSColin Finck             /* Store the pointer to the new one */
264c2c66affSColin Finck             *ResourceList = NewList;
265c2c66affSColin Finck         }
266c2c66affSColin Finck 
267c2c66affSColin Finck         for (ii = 0; ii < ResList->Count; ii++)
268c2c66affSColin Finck         {
269c2c66affSColin Finck             ULONG iii;
270c2c66affSColin Finck             PCM_PARTIAL_RESOURCE_LIST PartialList = (*ResourceList) ? &(*ResourceList)->List[0].PartialResourceList : NULL;
271c2c66affSColin Finck             PIO_RESOURCE_DESCRIPTOR IoDesc = &ResList->Descriptors[ii];
272c2c66affSColin Finck             BOOLEAN Matched = FALSE;
273c2c66affSColin Finck 
274c2c66affSColin Finck             /* Skip alternates if we don't need one */
275c2c66affSColin Finck             if (!AlternateRequired && (IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
276c2c66affSColin Finck             {
277c2c66affSColin Finck                 DPRINT("Skipping unneeded alternate\n");
278c2c66affSColin Finck                 continue;
279c2c66affSColin Finck             }
280c2c66affSColin Finck 
281c2c66affSColin Finck             /* Check if we couldn't satsify a requirement or its alternates */
282c2c66affSColin Finck             if (AlternateRequired && !(IoDesc->Option & IO_RESOURCE_ALTERNATIVE))
283c2c66affSColin Finck             {
284c2c66affSColin Finck                 DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
285c2c66affSColin Finck 
286c2c66affSColin Finck                 /* Break out of this loop and try the next list */
287c2c66affSColin Finck                 break;
288c2c66affSColin Finck             }
289c2c66affSColin Finck 
290c2c66affSColin Finck             for (iii = 0; PartialList && iii < PartialList->Count && !Matched; iii++)
291c2c66affSColin Finck             {
292b82bf8ceSTimo Kreuzer                 /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
293b82bf8ceSTimo Kreuzer                    but only one is allowed and it must be the last one in the list! */
294c2c66affSColin Finck                 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = &PartialList->PartialDescriptors[iii];
295c2c66affSColin Finck 
296c2c66affSColin Finck                 /* First check types */
297c2c66affSColin Finck                 if (IoDesc->Type != CmDesc->Type)
298c2c66affSColin Finck                     continue;
299c2c66affSColin Finck 
300c2c66affSColin Finck                 switch (IoDesc->Type)
301c2c66affSColin Finck                 {
302c2c66affSColin Finck                     case CmResourceTypeInterrupt:
303c2c66affSColin Finck                         /* Make sure it satisfies our vector range */
304c2c66affSColin Finck                         if (CmDesc->u.Interrupt.Vector >= IoDesc->u.Interrupt.MinimumVector &&
305c2c66affSColin Finck                             CmDesc->u.Interrupt.Vector <= IoDesc->u.Interrupt.MaximumVector)
306c2c66affSColin Finck                         {
307c2c66affSColin Finck                             /* Found it */
308c2c66affSColin Finck                             Matched = TRUE;
309c2c66affSColin Finck                         }
310c2c66affSColin Finck                         else
311c2c66affSColin Finck                         {
312c2c66affSColin Finck                             DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n",
313c2c66affSColin Finck                                    CmDesc->u.Interrupt.Vector,
314c2c66affSColin Finck                                    IoDesc->u.Interrupt.MinimumVector,
315c2c66affSColin Finck                                    IoDesc->u.Interrupt.MaximumVector);
316c2c66affSColin Finck                         }
317c2c66affSColin Finck                         break;
318c2c66affSColin Finck 
319c2c66affSColin Finck                     case CmResourceTypeMemory:
320c2c66affSColin Finck                     case CmResourceTypePort:
321c2c66affSColin Finck                         /* Make sure the length matches and it satisfies our address range */
322c2c66affSColin Finck                         if (CmDesc->u.Memory.Length == IoDesc->u.Memory.Length &&
323c2c66affSColin Finck                             (ULONGLONG)CmDesc->u.Memory.Start.QuadPart >= (ULONGLONG)IoDesc->u.Memory.MinimumAddress.QuadPart &&
324c2c66affSColin Finck                             (ULONGLONG)CmDesc->u.Memory.Start.QuadPart + CmDesc->u.Memory.Length - 1 <= (ULONGLONG)IoDesc->u.Memory.MaximumAddress.QuadPart)
325c2c66affSColin Finck                         {
326c2c66affSColin Finck                             /* Found it */
327c2c66affSColin Finck                             Matched = TRUE;
328c2c66affSColin Finck                         }
329c2c66affSColin Finck                         else
330c2c66affSColin Finck                         {
331c2c66affSColin Finck                             DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n",
332c2c66affSColin Finck                                    CmDesc->u.Memory.Start.QuadPart,
333c2c66affSColin Finck                                    CmDesc->u.Memory.Length,
334c2c66affSColin Finck                                    IoDesc->u.Memory.MinimumAddress.QuadPart,
335c2c66affSColin Finck                                    IoDesc->u.Memory.MaximumAddress.QuadPart,
336c2c66affSColin Finck                                    IoDesc->u.Memory.Length);
337c2c66affSColin Finck                         }
338c2c66affSColin Finck                         break;
339c2c66affSColin Finck 
340c2c66affSColin Finck                     case CmResourceTypeBusNumber:
341c2c66affSColin Finck                         /* Make sure the length matches and it satisfies our bus number range */
342c2c66affSColin Finck                         if (CmDesc->u.BusNumber.Length == IoDesc->u.BusNumber.Length &&
343c2c66affSColin Finck                             CmDesc->u.BusNumber.Start >= IoDesc->u.BusNumber.MinBusNumber &&
344c2c66affSColin Finck                             CmDesc->u.BusNumber.Start + CmDesc->u.BusNumber.Length - 1 <= IoDesc->u.BusNumber.MaxBusNumber)
345c2c66affSColin Finck                         {
346c2c66affSColin Finck                             /* Found it */
347c2c66affSColin Finck                             Matched = TRUE;
348c2c66affSColin Finck                         }
349c2c66affSColin Finck                         else
350c2c66affSColin Finck                         {
351c2c66affSColin Finck                             DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n",
352c2c66affSColin Finck                                    CmDesc->u.BusNumber.Start,
353c2c66affSColin Finck                                    CmDesc->u.BusNumber.Length,
354c2c66affSColin Finck                                    IoDesc->u.BusNumber.MinBusNumber,
355c2c66affSColin Finck                                    IoDesc->u.BusNumber.MaxBusNumber,
356c2c66affSColin Finck                                    IoDesc->u.BusNumber.Length);
357c2c66affSColin Finck                         }
358c2c66affSColin Finck                         break;
359c2c66affSColin Finck 
360c2c66affSColin Finck                     case CmResourceTypeDma:
361c2c66affSColin Finck                         /* Make sure it fits in our channel range */
362c2c66affSColin Finck                         if (CmDesc->u.Dma.Channel >= IoDesc->u.Dma.MinimumChannel &&
363c2c66affSColin Finck                             CmDesc->u.Dma.Channel <= IoDesc->u.Dma.MaximumChannel)
364c2c66affSColin Finck                         {
365c2c66affSColin Finck                             /* Found it */
366c2c66affSColin Finck                             Matched = TRUE;
367c2c66affSColin Finck                         }
368c2c66affSColin Finck                         else
369c2c66affSColin Finck                         {
370c2c66affSColin Finck                             DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n",
371c2c66affSColin Finck                                    CmDesc->u.Dma.Channel,
372c2c66affSColin Finck                                    IoDesc->u.Dma.MinimumChannel,
373c2c66affSColin Finck                                    IoDesc->u.Dma.MaximumChannel);
374c2c66affSColin Finck                         }
375c2c66affSColin Finck                         break;
376c2c66affSColin Finck 
377c2c66affSColin Finck                     default:
378c2c66affSColin Finck                         /* Other stuff is fine */
379c2c66affSColin Finck                         Matched = TRUE;
380c2c66affSColin Finck                         break;
381c2c66affSColin Finck                 }
382c2c66affSColin Finck             }
383c2c66affSColin Finck 
384c2c66affSColin Finck             /* Check if we found a matching descriptor */
385c2c66affSColin Finck             if (!Matched)
386c2c66affSColin Finck             {
387c2c66affSColin Finck                 PCM_RESOURCE_LIST NewList;
388c2c66affSColin Finck                 CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc;
389c2c66affSColin Finck                 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr;
390c2c66affSColin Finck                 BOOLEAN FoundResource = TRUE;
391c2c66affSColin Finck 
392c2c66affSColin Finck                 /* Setup the new CM descriptor */
393c2c66affSColin Finck                 NewDesc.Type = IoDesc->Type;
394c2c66affSColin Finck                 NewDesc.Flags = IoDesc->Flags;
395c2c66affSColin Finck                 NewDesc.ShareDisposition = IoDesc->ShareDisposition;
396c2c66affSColin Finck 
397c2c66affSColin Finck                 /* Let'se see if we can find a resource to satisfy this */
398c2c66affSColin Finck                 switch (IoDesc->Type)
399c2c66affSColin Finck                 {
400c2c66affSColin Finck                     case CmResourceTypeInterrupt:
401c2c66affSColin Finck                         /* Find an available interrupt */
402c2c66affSColin Finck                         if (!IopFindInterruptResource(IoDesc, &NewDesc))
403c2c66affSColin Finck                         {
404c2c66affSColin Finck                             DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
405c2c66affSColin Finck                                     IoDesc->u.Interrupt.MinimumVector, IoDesc->u.Interrupt.MaximumVector);
406c2c66affSColin Finck 
407c2c66affSColin Finck                             FoundResource = FALSE;
408c2c66affSColin Finck                         }
409c2c66affSColin Finck                         break;
410c2c66affSColin Finck 
411c2c66affSColin Finck                     case CmResourceTypePort:
412c2c66affSColin Finck                         /* Find an available port range */
413c2c66affSColin Finck                         if (!IopFindPortResource(IoDesc, &NewDesc))
414c2c66affSColin Finck                         {
415c2c66affSColin Finck                             DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n",
416c2c66affSColin Finck                                     IoDesc->u.Port.MinimumAddress.QuadPart, IoDesc->u.Port.MaximumAddress.QuadPart,
417c2c66affSColin Finck                                     IoDesc->u.Port.Length);
418c2c66affSColin Finck 
419c2c66affSColin Finck                             FoundResource = FALSE;
420c2c66affSColin Finck                         }
421c2c66affSColin Finck                         break;
422c2c66affSColin Finck 
423c2c66affSColin Finck                     case CmResourceTypeMemory:
424c2c66affSColin Finck                         /* Find an available memory range */
425c2c66affSColin Finck                         if (!IopFindMemoryResource(IoDesc, &NewDesc))
426c2c66affSColin Finck                         {
427c2c66affSColin Finck                             DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n",
428c2c66affSColin Finck                                     IoDesc->u.Memory.MinimumAddress.QuadPart, IoDesc->u.Memory.MaximumAddress.QuadPart,
429c2c66affSColin Finck                                     IoDesc->u.Memory.Length);
430c2c66affSColin Finck 
431c2c66affSColin Finck                             FoundResource = FALSE;
432c2c66affSColin Finck                         }
433c2c66affSColin Finck                         break;
434c2c66affSColin Finck 
435c2c66affSColin Finck                     case CmResourceTypeBusNumber:
436c2c66affSColin Finck                         /* Find an available bus address range */
437c2c66affSColin Finck                         if (!IopFindBusNumberResource(IoDesc, &NewDesc))
438c2c66affSColin Finck                         {
439c2c66affSColin Finck                             DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
440c2c66affSColin Finck                                     IoDesc->u.BusNumber.MinBusNumber, IoDesc->u.BusNumber.MaxBusNumber,
441c2c66affSColin Finck                                     IoDesc->u.BusNumber.Length);
442c2c66affSColin Finck 
443c2c66affSColin Finck                             FoundResource = FALSE;
444c2c66affSColin Finck                         }
445c2c66affSColin Finck                         break;
446c2c66affSColin Finck 
447c2c66affSColin Finck                     case CmResourceTypeDma:
448c2c66affSColin Finck                         /* Find an available DMA channel */
449c2c66affSColin Finck                         if (!IopFindDmaResource(IoDesc, &NewDesc))
450c2c66affSColin Finck                         {
451c2c66affSColin Finck                             DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
452c2c66affSColin Finck                                     IoDesc->u.Dma.MinimumChannel, IoDesc->u.Dma.MaximumChannel);
453c2c66affSColin Finck 
454c2c66affSColin Finck                             FoundResource = FALSE;
455c2c66affSColin Finck                         }
456c2c66affSColin Finck                         break;
457c2c66affSColin Finck 
458c2c66affSColin Finck                     default:
459c2c66affSColin Finck                         DPRINT1("Unsupported resource type: %x\n", IoDesc->Type);
460c2c66affSColin Finck                         FoundResource = FALSE;
461c2c66affSColin Finck                         break;
462c2c66affSColin Finck                 }
463c2c66affSColin Finck 
464c2c66affSColin Finck                 /* Check if it's missing and required */
465c2c66affSColin Finck                 if (!FoundResource && IoDesc->Option == 0)
466c2c66affSColin Finck                 {
467c2c66affSColin Finck                     /* Break out of this loop and try the next list */
468c2c66affSColin Finck                     DPRINT1("Unable to satisfy required resource in list %lu\n", i);
469c2c66affSColin Finck                     break;
470c2c66affSColin Finck                 }
471c2c66affSColin Finck                 else if (!FoundResource)
472c2c66affSColin Finck                 {
473c2c66affSColin Finck                     /* Try an alternate for this preferred descriptor */
474c2c66affSColin Finck                     AlternateRequired = TRUE;
475c2c66affSColin Finck                     continue;
476c2c66affSColin Finck                 }
477c2c66affSColin Finck                 else
478c2c66affSColin Finck                 {
479c2c66affSColin Finck                     /* Move on to the next preferred or required descriptor after this one */
480c2c66affSColin Finck                     AlternateRequired = FALSE;
481c2c66affSColin Finck                 }
482c2c66affSColin Finck 
483c2c66affSColin Finck                 /* Figure out what we need */
484c2c66affSColin Finck                 if (PartialList == NULL)
485c2c66affSColin Finck                 {
486c2c66affSColin Finck                     /* We need a new list */
487c2c66affSColin Finck                     NewList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
488c2c66affSColin Finck                     if (!NewList)
489c2c66affSColin Finck                         return STATUS_NO_MEMORY;
490c2c66affSColin Finck 
491c2c66affSColin Finck                     /* Set it up */
492c2c66affSColin Finck                     NewList->Count = 1;
493c2c66affSColin Finck                     NewList->List[0].InterfaceType = RequirementsList->InterfaceType;
494c2c66affSColin Finck                     NewList->List[0].BusNumber = RequirementsList->BusNumber;
495c2c66affSColin Finck                     NewList->List[0].PartialResourceList.Version = 1;
496c2c66affSColin Finck                     NewList->List[0].PartialResourceList.Revision = 1;
497c2c66affSColin Finck                     NewList->List[0].PartialResourceList.Count = 1;
498c2c66affSColin Finck 
499c2c66affSColin Finck                     /* Set our pointer */
500c2c66affSColin Finck                     DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[0];
501c2c66affSColin Finck                 }
502c2c66affSColin Finck                 else
503c2c66affSColin Finck                 {
504c2c66affSColin Finck                     /* Allocate the new larger list */
505c2c66affSColin Finck                     NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
506c2c66affSColin Finck                     if (!NewList)
507c2c66affSColin Finck                         return STATUS_NO_MEMORY;
508c2c66affSColin Finck 
509c2c66affSColin Finck                     /* Copy the old stuff back */
510c2c66affSColin Finck                     RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList));
511c2c66affSColin Finck 
512c2c66affSColin Finck                     /* Set our pointer */
513c2c66affSColin Finck                     DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[NewList->List[0].PartialResourceList.Count];
514c2c66affSColin Finck 
515c2c66affSColin Finck                     /* Increment the descriptor count */
516c2c66affSColin Finck                     NewList->List[0].PartialResourceList.Count++;
517c2c66affSColin Finck 
518c2c66affSColin Finck                     /* Free the old list */
519c2c66affSColin Finck                     ExFreePool(*ResourceList);
520c2c66affSColin Finck                 }
521c2c66affSColin Finck 
522c2c66affSColin Finck                 /* Copy the descriptor in */
523c2c66affSColin Finck                 *DescPtr = NewDesc;
524c2c66affSColin Finck 
525c2c66affSColin Finck                 /* Store the new list */
526c2c66affSColin Finck                 *ResourceList = NewList;
527c2c66affSColin Finck             }
528c2c66affSColin Finck         }
529c2c66affSColin Finck 
530c2c66affSColin Finck         /* Check if we need an alternate with no resources left */
531c2c66affSColin Finck         if (AlternateRequired)
532c2c66affSColin Finck         {
533c2c66affSColin Finck             DPRINT1("Unable to satisfy preferred resource or alternates in list %lu\n", i);
534c2c66affSColin Finck 
535c2c66affSColin Finck             /* Try the next alternate list */
536c2c66affSColin Finck             continue;
537c2c66affSColin Finck         }
538c2c66affSColin Finck 
539c2c66affSColin Finck         /* We're done because we satisfied one of the alternate lists */
540c2c66affSColin Finck         return STATUS_SUCCESS;
541c2c66affSColin Finck     }
542c2c66affSColin Finck 
543c2c66affSColin Finck     /* We ran out of alternates */
544c2c66affSColin Finck     DPRINT1("Out of alternate lists!\n");
545c2c66affSColin Finck 
546c2c66affSColin Finck     /* Free the list */
547c2c66affSColin Finck     if (*ResourceList)
548c2c66affSColin Finck     {
549c2c66affSColin Finck         ExFreePool(*ResourceList);
550c2c66affSColin Finck         *ResourceList = NULL;
551c2c66affSColin Finck     }
552c2c66affSColin Finck 
553c2c66affSColin Finck     /* Fail */
554c2c66affSColin Finck     return STATUS_CONFLICTING_ADDRESSES;
555c2c66affSColin Finck }
556c2c66affSColin Finck 
557c2c66affSColin Finck static
558c2c66affSColin Finck BOOLEAN
IopCheckResourceDescriptor(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc,IN PCM_RESOURCE_LIST ResourceList,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)559c2c66affSColin Finck IopCheckResourceDescriptor(
560c2c66affSColin Finck     IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc,
561c2c66affSColin Finck     IN PCM_RESOURCE_LIST ResourceList,
562c2c66affSColin Finck     IN BOOLEAN Silent,
563c2c66affSColin Finck     OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
564c2c66affSColin Finck {
565c2c66affSColin Finck     ULONG i, ii;
566c2c66affSColin Finck     BOOLEAN Result = FALSE;
567b82bf8ceSTimo Kreuzer     PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
568c2c66affSColin Finck 
569b82bf8ceSTimo Kreuzer     FullDescriptor = &ResourceList->List[0];
570c2c66affSColin Finck     for (i = 0; i < ResourceList->Count; i++)
571c2c66affSColin Finck     {
572b82bf8ceSTimo Kreuzer         PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList;
573b82bf8ceSTimo Kreuzer         FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
574b82bf8ceSTimo Kreuzer 
575c2c66affSColin Finck         for (ii = 0; ii < ResList->Count; ii++)
576c2c66affSColin Finck         {
577b82bf8ceSTimo Kreuzer             /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
578b82bf8ceSTimo Kreuzer                but only one is allowed and it must be the last one in the list! */
579c2c66affSColin Finck             PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii];
580c2c66affSColin Finck 
581c2c66affSColin Finck             /* We don't care about shared resources */
582c2c66affSColin Finck             if (ResDesc->ShareDisposition == CmResourceShareShared &&
583c2c66affSColin Finck                 ResDesc2->ShareDisposition == CmResourceShareShared)
584c2c66affSColin Finck                 continue;
585c2c66affSColin Finck 
586c2c66affSColin Finck             /* Make sure we're comparing the same types */
587c2c66affSColin Finck             if (ResDesc->Type != ResDesc2->Type)
588c2c66affSColin Finck                 continue;
589c2c66affSColin Finck 
590c2c66affSColin Finck             switch (ResDesc->Type)
591c2c66affSColin Finck             {
592c2c66affSColin Finck                 case CmResourceTypeMemory:
59343f1d916SVictor Perevertkin                 {
59443f1d916SVictor Perevertkin                     /* NOTE: ranges are in a form [x1;x2) */
59543f1d916SVictor Perevertkin                     UINT64 rStart = (UINT64)ResDesc->u.Memory.Start.QuadPart;
59643f1d916SVictor Perevertkin                     UINT64 rEnd = (UINT64)ResDesc->u.Memory.Start.QuadPart
59743f1d916SVictor Perevertkin                                   + ResDesc->u.Memory.Length;
59843f1d916SVictor Perevertkin                     UINT64 r2Start = (UINT64)ResDesc2->u.Memory.Start.QuadPart;
59943f1d916SVictor Perevertkin                     UINT64 r2End = (UINT64)ResDesc2->u.Memory.Start.QuadPart
60043f1d916SVictor Perevertkin                                    + ResDesc2->u.Memory.Length;
60143f1d916SVictor Perevertkin 
60243f1d916SVictor Perevertkin                     if (rStart < r2End && r2Start < rEnd)
603c2c66affSColin Finck                     {
604c2c66affSColin Finck                         if (!Silent)
605c2c66affSColin Finck                         {
606c2c66affSColin Finck                             DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
60743f1d916SVictor Perevertkin                                     rStart, rEnd, r2Start, r2End);
608c2c66affSColin Finck                         }
609c2c66affSColin Finck 
610c2c66affSColin Finck                         Result = TRUE;
611c2c66affSColin Finck 
612c2c66affSColin Finck                         goto ByeBye;
613c2c66affSColin Finck                     }
614c2c66affSColin Finck                     break;
61543f1d916SVictor Perevertkin                 }
616c2c66affSColin Finck                 case CmResourceTypePort:
61743f1d916SVictor Perevertkin                 {
61843f1d916SVictor Perevertkin                     /* NOTE: ranges are in a form [x1;x2) */
61943f1d916SVictor Perevertkin                     UINT64 rStart = (UINT64)ResDesc->u.Port.Start.QuadPart;
62043f1d916SVictor Perevertkin                     UINT64 rEnd = (UINT64)ResDesc->u.Port.Start.QuadPart
62143f1d916SVictor Perevertkin                                   + ResDesc->u.Port.Length;
62243f1d916SVictor Perevertkin                     UINT64 r2Start = (UINT64)ResDesc2->u.Port.Start.QuadPart;
62343f1d916SVictor Perevertkin                     UINT64 r2End = (UINT64)ResDesc2->u.Port.Start.QuadPart
62443f1d916SVictor Perevertkin                                    + ResDesc2->u.Port.Length;
62543f1d916SVictor Perevertkin 
62643f1d916SVictor Perevertkin                     if (rStart < r2End && r2Start < rEnd)
627c2c66affSColin Finck                     {
628c2c66affSColin Finck                         if (!Silent)
629c2c66affSColin Finck                         {
630c2c66affSColin Finck                             DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n",
63143f1d916SVictor Perevertkin                                     rStart, rEnd, r2Start, r2End);
632c2c66affSColin Finck                         }
633c2c66affSColin Finck 
634c2c66affSColin Finck                         Result = TRUE;
635c2c66affSColin Finck 
636c2c66affSColin Finck                         goto ByeBye;
637c2c66affSColin Finck                     }
638c2c66affSColin Finck                     break;
63943f1d916SVictor Perevertkin                 }
640c2c66affSColin Finck                 case CmResourceTypeInterrupt:
64143f1d916SVictor Perevertkin                 {
642c2c66affSColin Finck                     if (ResDesc->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector)
643c2c66affSColin Finck                     {
644c2c66affSColin Finck                         if (!Silent)
645c2c66affSColin Finck                         {
646c2c66affSColin Finck                             DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
647c2c66affSColin Finck                                     ResDesc->u.Interrupt.Vector, ResDesc->u.Interrupt.Level,
648c2c66affSColin Finck                                     ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level);
649c2c66affSColin Finck                         }
650c2c66affSColin Finck 
651c2c66affSColin Finck                         Result = TRUE;
652c2c66affSColin Finck 
653c2c66affSColin Finck                         goto ByeBye;
654c2c66affSColin Finck                     }
655c2c66affSColin Finck                     break;
65643f1d916SVictor Perevertkin                 }
657c2c66affSColin Finck                 case CmResourceTypeBusNumber:
65843f1d916SVictor Perevertkin                 {
65943f1d916SVictor Perevertkin                     /* NOTE: ranges are in a form [x1;x2) */
66043f1d916SVictor Perevertkin                     UINT32 rStart = ResDesc->u.BusNumber.Start;
66143f1d916SVictor Perevertkin                     UINT32 rEnd = ResDesc->u.BusNumber.Start + ResDesc->u.BusNumber.Length;
66243f1d916SVictor Perevertkin                     UINT32 r2Start = ResDesc2->u.BusNumber.Start;
66343f1d916SVictor Perevertkin                     UINT32 r2End = ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length;
66443f1d916SVictor Perevertkin 
66543f1d916SVictor Perevertkin                     if (rStart < r2End && r2Start < rEnd)
666c2c66affSColin Finck                     {
667c2c66affSColin Finck                         if (!Silent)
668c2c66affSColin Finck                         {
669c2c66affSColin Finck                             DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
67043f1d916SVictor Perevertkin                                     rStart, rEnd, r2Start, r2End);
671c2c66affSColin Finck                         }
672c2c66affSColin Finck 
673c2c66affSColin Finck                         Result = TRUE;
674c2c66affSColin Finck 
675c2c66affSColin Finck                         goto ByeBye;
676c2c66affSColin Finck                     }
677c2c66affSColin Finck                     break;
67843f1d916SVictor Perevertkin                 }
679c2c66affSColin Finck                 case CmResourceTypeDma:
68043f1d916SVictor Perevertkin                 {
681c2c66affSColin Finck                     if (ResDesc->u.Dma.Channel == ResDesc2->u.Dma.Channel)
682c2c66affSColin Finck                     {
683c2c66affSColin Finck                         if (!Silent)
684c2c66affSColin Finck                         {
685c2c66affSColin Finck                             DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
686c2c66affSColin Finck                                     ResDesc->u.Dma.Channel, ResDesc->u.Dma.Port,
687c2c66affSColin Finck                                     ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port);
688c2c66affSColin Finck                         }
689c2c66affSColin Finck 
690c2c66affSColin Finck                         Result = TRUE;
691c2c66affSColin Finck 
692c2c66affSColin Finck                         goto ByeBye;
693c2c66affSColin Finck                     }
694c2c66affSColin Finck                     break;
695c2c66affSColin Finck                 }
696c2c66affSColin Finck             }
697c2c66affSColin Finck         }
69843f1d916SVictor Perevertkin     }
699c2c66affSColin Finck 
700c2c66affSColin Finck ByeBye:
701c2c66affSColin Finck 
702c2c66affSColin Finck     if (Result && ConflictingDescriptor)
703c2c66affSColin Finck     {
704c2c66affSColin Finck         RtlCopyMemory(ConflictingDescriptor,
705c2c66affSColin Finck                       ResDesc,
706c2c66affSColin Finck                       sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
707c2c66affSColin Finck     }
708c2c66affSColin Finck 
709b82bf8ceSTimo Kreuzer     // Hacked, because after fixing resource list parsing
710b82bf8ceSTimo Kreuzer     // we actually detect resource conflicts
711b82bf8ceSTimo Kreuzer     return Silent ? Result : FALSE; // Result;
712c2c66affSColin Finck }
713c2c66affSColin Finck 
714c2c66affSColin Finck static
715c2c66affSColin Finck NTSTATUS
IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode)7169538c3ccSEric Kohl IopUpdateControlKeyWithResources(
7179538c3ccSEric Kohl     IN PDEVICE_NODE DeviceNode)
718c2c66affSColin Finck {
719c2c66affSColin Finck     UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
720c2c66affSColin Finck     UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control");
721c2c66affSColin Finck     UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"AllocConfig");
722c2c66affSColin Finck     HANDLE EnumKey, InstanceKey, ControlKey;
723c2c66affSColin Finck     NTSTATUS Status;
724c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
725c2c66affSColin Finck 
726c2c66affSColin Finck     /* Open the Enum key */
727c2c66affSColin Finck     Status = IopOpenRegistryKeyEx(&EnumKey, NULL, &EnumRoot, KEY_ENUMERATE_SUB_KEYS);
728c2c66affSColin Finck     if (!NT_SUCCESS(Status))
729c2c66affSColin Finck         return Status;
730c2c66affSColin Finck 
731c2c66affSColin Finck     /* Open the instance key (eg. Root\PNP0A03) */
732c2c66affSColin Finck     Status = IopOpenRegistryKeyEx(&InstanceKey, EnumKey, &DeviceNode->InstancePath, KEY_ENUMERATE_SUB_KEYS);
733c2c66affSColin Finck     ZwClose(EnumKey);
734c2c66affSColin Finck 
735c2c66affSColin Finck     if (!NT_SUCCESS(Status))
736c2c66affSColin Finck         return Status;
737c2c66affSColin Finck 
738c2c66affSColin Finck     /* Create/Open the Control key */
739c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
740c2c66affSColin Finck                                &Control,
741c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
742c2c66affSColin Finck                                InstanceKey,
743c2c66affSColin Finck                                NULL);
744c2c66affSColin Finck     Status = ZwCreateKey(&ControlKey,
745c2c66affSColin Finck                          KEY_SET_VALUE,
746c2c66affSColin Finck                          &ObjectAttributes,
747c2c66affSColin Finck                          0,
748c2c66affSColin Finck                          NULL,
749c2c66affSColin Finck                          REG_OPTION_VOLATILE,
750c2c66affSColin Finck                          NULL);
751c2c66affSColin Finck     ZwClose(InstanceKey);
752c2c66affSColin Finck 
753c2c66affSColin Finck     if (!NT_SUCCESS(Status))
754c2c66affSColin Finck         return Status;
755c2c66affSColin Finck 
756c2c66affSColin Finck     /* Write the resource list */
757c2c66affSColin Finck     Status = ZwSetValueKey(ControlKey,
758c2c66affSColin Finck                            &ValueName,
759c2c66affSColin Finck                            0,
760c2c66affSColin Finck                            REG_RESOURCE_LIST,
761c2c66affSColin Finck                            DeviceNode->ResourceList,
762c2c66affSColin Finck                            PnpDetermineResourceListSize(DeviceNode->ResourceList));
763c2c66affSColin Finck     ZwClose(ControlKey);
764c2c66affSColin Finck 
765c2c66affSColin Finck     if (!NT_SUCCESS(Status))
766c2c66affSColin Finck         return Status;
767c2c66affSColin Finck 
768c2c66affSColin Finck     return STATUS_SUCCESS;
769c2c66affSColin Finck }
770c2c66affSColin Finck 
771c2c66affSColin Finck static
772c2c66affSColin Finck NTSTATUS
IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode)7739538c3ccSEric Kohl IopFilterResourceRequirements(
7749538c3ccSEric Kohl     IN PDEVICE_NODE DeviceNode)
775c2c66affSColin Finck {
776c2c66affSColin Finck     IO_STACK_LOCATION Stack;
777c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
778c2c66affSColin Finck     NTSTATUS Status;
779c2c66affSColin Finck 
780c2c66affSColin Finck     DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
781c2c66affSColin Finck 
782c2c66affSColin Finck     Stack.Parameters.FilterResourceRequirements.IoResourceRequirementList = DeviceNode->ResourceRequirements;
7839538c3ccSEric Kohl     Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
784c2c66affSColin Finck                                &IoStatusBlock,
785c2c66affSColin Finck                                IRP_MN_FILTER_RESOURCE_REQUIREMENTS,
786c2c66affSColin Finck                                &Stack);
787c2c66affSColin Finck     if (!NT_SUCCESS(Status) && Status != STATUS_NOT_SUPPORTED)
788c2c66affSColin Finck     {
789c2c66affSColin Finck         DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
790c2c66affSColin Finck         return Status;
791c2c66affSColin Finck     }
792c2c66affSColin Finck     else if (NT_SUCCESS(Status) && IoStatusBlock.Information)
793c2c66affSColin Finck     {
794c2c66affSColin Finck         DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
795c2c66affSColin Finck     }
796c2c66affSColin Finck 
797c2c66affSColin Finck     return STATUS_SUCCESS;
798c2c66affSColin Finck }
799c2c66affSColin Finck 
800c2c66affSColin Finck 
801c2c66affSColin Finck NTSTATUS
IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode,PWCHAR Level1Key,PWCHAR Level2Key)8029538c3ccSEric Kohl IopUpdateResourceMap(
8039538c3ccSEric Kohl     IN PDEVICE_NODE DeviceNode,
8049538c3ccSEric Kohl     PWCHAR Level1Key,
8059538c3ccSEric Kohl     PWCHAR Level2Key)
806c2c66affSColin Finck {
807c2c66affSColin Finck     NTSTATUS Status;
808c2c66affSColin Finck     ULONG Disposition;
809c2c66affSColin Finck     HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey;
810c2c66affSColin Finck     UNICODE_STRING KeyName;
811c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
812c2c66affSColin Finck 
813c2c66affSColin Finck     RtlInitUnicodeString(&KeyName,
814c2c66affSColin Finck                          L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
815c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
816c2c66affSColin Finck                                &KeyName,
817c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
818c2c66affSColin Finck                                NULL,
819c2c66affSColin Finck                                NULL);
820c2c66affSColin Finck     Status = ZwCreateKey(&ResourceMapKey,
821c2c66affSColin Finck                          KEY_ALL_ACCESS,
822c2c66affSColin Finck                          &ObjectAttributes,
823c2c66affSColin Finck                          0,
824c2c66affSColin Finck                          NULL,
825c2c66affSColin Finck                          REG_OPTION_VOLATILE,
826c2c66affSColin Finck                          &Disposition);
827c2c66affSColin Finck     if (!NT_SUCCESS(Status))
828c2c66affSColin Finck         return Status;
829c2c66affSColin Finck 
830c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, Level1Key);
831c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
832c2c66affSColin Finck                                &KeyName,
833c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
834c2c66affSColin Finck                                ResourceMapKey,
835c2c66affSColin Finck                                NULL);
836c2c66affSColin Finck     Status = ZwCreateKey(&PnpMgrLevel1,
837c2c66affSColin Finck                          KEY_ALL_ACCESS,
838c2c66affSColin Finck                          &ObjectAttributes,
839c2c66affSColin Finck                          0,
840c2c66affSColin Finck                          NULL,
841c2c66affSColin Finck                          REG_OPTION_VOLATILE,
842c2c66affSColin Finck                          &Disposition);
843c2c66affSColin Finck     ZwClose(ResourceMapKey);
844c2c66affSColin Finck     if (!NT_SUCCESS(Status))
845c2c66affSColin Finck         return Status;
846c2c66affSColin Finck 
847c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, Level2Key);
848c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
849c2c66affSColin Finck                                &KeyName,
850c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
851c2c66affSColin Finck                                PnpMgrLevel1,
852c2c66affSColin Finck                                NULL);
853c2c66affSColin Finck     Status = ZwCreateKey(&PnpMgrLevel2,
854c2c66affSColin Finck                          KEY_ALL_ACCESS,
855c2c66affSColin Finck                          &ObjectAttributes,
856c2c66affSColin Finck                          0,
857c2c66affSColin Finck                          NULL,
858c2c66affSColin Finck                          REG_OPTION_VOLATILE,
859c2c66affSColin Finck                          &Disposition);
860c2c66affSColin Finck     ZwClose(PnpMgrLevel1);
861c2c66affSColin Finck     if (!NT_SUCCESS(Status))
862c2c66affSColin Finck         return Status;
863c2c66affSColin Finck 
864c2c66affSColin Finck     if (DeviceNode->ResourceList)
865c2c66affSColin Finck     {
866c2c66affSColin Finck         UNICODE_STRING NameU;
867c2c66affSColin Finck         UNICODE_STRING RawSuffix, TranslatedSuffix;
868c2c66affSColin Finck         ULONG OldLength = 0;
869c2c66affSColin Finck 
870c2c66affSColin Finck         ASSERT(DeviceNode->ResourceListTranslated);
871c2c66affSColin Finck 
872c2c66affSColin Finck         RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
873c2c66affSColin Finck         RtlInitUnicodeString(&RawSuffix, L".Raw");
874c2c66affSColin Finck 
875c2c66affSColin Finck         Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
876c2c66affSColin Finck                                      DevicePropertyPhysicalDeviceObjectName,
877c2c66affSColin Finck                                      0,
878c2c66affSColin Finck                                      NULL,
879c2c66affSColin Finck                                      &OldLength);
880c2c66affSColin Finck         if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
881c2c66affSColin Finck         {
882c2c66affSColin Finck             ASSERT(OldLength);
883c2c66affSColin Finck 
884c2c66affSColin Finck             NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length);
885c2c66affSColin Finck             if (!NameU.Buffer)
886c2c66affSColin Finck             {
887c2c66affSColin Finck                 ZwClose(PnpMgrLevel2);
888c2c66affSColin Finck                 return STATUS_INSUFFICIENT_RESOURCES;
889c2c66affSColin Finck             }
890c2c66affSColin Finck 
891c2c66affSColin Finck             NameU.Length = 0;
892c2c66affSColin Finck             NameU.MaximumLength = (USHORT)OldLength + TranslatedSuffix.Length;
893c2c66affSColin Finck 
894c2c66affSColin Finck             Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
895c2c66affSColin Finck                                          DevicePropertyPhysicalDeviceObjectName,
896c2c66affSColin Finck                                          NameU.MaximumLength,
897c2c66affSColin Finck                                          NameU.Buffer,
898c2c66affSColin Finck                                          &OldLength);
899c2c66affSColin Finck             if (!NT_SUCCESS(Status))
900c2c66affSColin Finck             {
901c2c66affSColin Finck                 ZwClose(PnpMgrLevel2);
902c2c66affSColin Finck                 ExFreePool(NameU.Buffer);
903c2c66affSColin Finck                 return Status;
904c2c66affSColin Finck             }
905c2c66affSColin Finck         }
906c2c66affSColin Finck         else if (!NT_SUCCESS(Status))
907c2c66affSColin Finck         {
908c2c66affSColin Finck             /* Some failure */
909c2c66affSColin Finck             ZwClose(PnpMgrLevel2);
910c2c66affSColin Finck             return Status;
911c2c66affSColin Finck         }
912c2c66affSColin Finck         else
913c2c66affSColin Finck         {
914c2c66affSColin Finck             /* This should never happen */
915c2c66affSColin Finck             ASSERT(FALSE);
916c2c66affSColin Finck         }
917c2c66affSColin Finck 
918a86c3794SHervé Poussineau         NameU.Length = (USHORT)OldLength - sizeof(UNICODE_NULL); /* Remove final NULL */
919c2c66affSColin Finck 
920c2c66affSColin Finck         RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
921c2c66affSColin Finck 
922c2c66affSColin Finck         Status = ZwSetValueKey(PnpMgrLevel2,
923c2c66affSColin Finck                                &NameU,
924c2c66affSColin Finck                                0,
925c2c66affSColin Finck                                REG_RESOURCE_LIST,
926c2c66affSColin Finck                                DeviceNode->ResourceList,
927c2c66affSColin Finck                                PnpDetermineResourceListSize(DeviceNode->ResourceList));
928c2c66affSColin Finck         if (!NT_SUCCESS(Status))
929c2c66affSColin Finck         {
930c2c66affSColin Finck             ZwClose(PnpMgrLevel2);
931c2c66affSColin Finck             ExFreePool(NameU.Buffer);
932c2c66affSColin Finck             return Status;
933c2c66affSColin Finck         }
934c2c66affSColin Finck 
935c2c66affSColin Finck         /* "Remove" the suffix by setting the length back to what it used to be */
936a86c3794SHervé Poussineau         NameU.Length = (USHORT)OldLength - sizeof(UNICODE_NULL); /* Remove final NULL */
937c2c66affSColin Finck 
938c2c66affSColin Finck         RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
939c2c66affSColin Finck 
940c2c66affSColin Finck         Status = ZwSetValueKey(PnpMgrLevel2,
941c2c66affSColin Finck                                &NameU,
942c2c66affSColin Finck                                0,
943c2c66affSColin Finck                                REG_RESOURCE_LIST,
944c2c66affSColin Finck                                DeviceNode->ResourceListTranslated,
945c2c66affSColin Finck                                PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated));
946c2c66affSColin Finck         ZwClose(PnpMgrLevel2);
947c2c66affSColin Finck         ExFreePool(NameU.Buffer);
948c2c66affSColin Finck 
949c2c66affSColin Finck         if (!NT_SUCCESS(Status))
950c2c66affSColin Finck             return Status;
951c2c66affSColin Finck     }
952c2c66affSColin Finck     else
953c2c66affSColin Finck     {
954c2c66affSColin Finck         ZwClose(PnpMgrLevel2);
955c2c66affSColin Finck     }
956c2c66affSColin Finck 
957c2c66affSColin Finck     return STATUS_SUCCESS;
958c2c66affSColin Finck }
959c2c66affSColin Finck 
960c2c66affSColin Finck NTSTATUS
IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)9619538c3ccSEric Kohl IopUpdateResourceMapForPnPDevice(
9629538c3ccSEric Kohl     IN PDEVICE_NODE DeviceNode)
963c2c66affSColin Finck {
964c2c66affSColin Finck     return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager");
965c2c66affSColin Finck }
966c2c66affSColin Finck 
967c2c66affSColin Finck static
968c2c66affSColin Finck NTSTATUS
IopTranslateDeviceResources(IN PDEVICE_NODE DeviceNode)969c2c66affSColin Finck IopTranslateDeviceResources(
970c2c66affSColin Finck    IN PDEVICE_NODE DeviceNode)
971c2c66affSColin Finck {
972c2c66affSColin Finck    PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
973c2c66affSColin Finck    PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
974b82bf8ceSTimo Kreuzer    PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
975c2c66affSColin Finck    ULONG i, j, ListSize;
976c2c66affSColin Finck    NTSTATUS Status;
977c2c66affSColin Finck 
978c2c66affSColin Finck    if (!DeviceNode->ResourceList)
979c2c66affSColin Finck    {
980c2c66affSColin Finck       DeviceNode->ResourceListTranslated = NULL;
981c2c66affSColin Finck       return STATUS_SUCCESS;
982c2c66affSColin Finck    }
983c2c66affSColin Finck 
984c2c66affSColin Finck    /* That's easy to translate a resource list. Just copy the
985c2c66affSColin Finck     * untranslated one and change few fields in the copy
986c2c66affSColin Finck     */
987c2c66affSColin Finck    ListSize = PnpDetermineResourceListSize(DeviceNode->ResourceList);
988c2c66affSColin Finck 
989c2c66affSColin Finck    DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize);
990c2c66affSColin Finck    if (!DeviceNode->ResourceListTranslated)
991c2c66affSColin Finck    {
992c2c66affSColin Finck       Status = STATUS_NO_MEMORY;
993c2c66affSColin Finck       goto cleanup;
994c2c66affSColin Finck    }
995c2c66affSColin Finck    RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize);
996c2c66affSColin Finck 
997b82bf8ceSTimo Kreuzer    FullDescriptor = &DeviceNode->ResourceList->List[0];
998c2c66affSColin Finck    for (i = 0; i < DeviceNode->ResourceList->Count; i++)
999c2c66affSColin Finck    {
1000b82bf8ceSTimo Kreuzer       pPartialResourceList = &FullDescriptor->PartialResourceList;
1001b82bf8ceSTimo Kreuzer       FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
1002b82bf8ceSTimo Kreuzer 
1003c2c66affSColin Finck       for (j = 0; j < pPartialResourceList->Count; j++)
1004c2c66affSColin Finck       {
1005b82bf8ceSTimo Kreuzer         /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1006b82bf8ceSTimo Kreuzer            but only one is allowed and it must be the last one in the list! */
1007c2c66affSColin Finck          DescriptorRaw = &pPartialResourceList->PartialDescriptors[j];
1008b82bf8ceSTimo Kreuzer 
1009b82bf8ceSTimo Kreuzer          /* Calculate the location of the translated resource descriptor */
1010b82bf8ceSTimo Kreuzer          DescriptorTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)(
1011b82bf8ceSTimo Kreuzer              (PUCHAR)DeviceNode->ResourceListTranslated +
1012b82bf8ceSTimo Kreuzer              ((PUCHAR)DescriptorRaw - (PUCHAR)DeviceNode->ResourceList));
1013b82bf8ceSTimo Kreuzer 
1014c2c66affSColin Finck          switch (DescriptorRaw->Type)
1015c2c66affSColin Finck          {
1016c2c66affSColin Finck             case CmResourceTypePort:
1017c2c66affSColin Finck             {
1018c2c66affSColin Finck                ULONG AddressSpace = 1; /* IO space */
1019c2c66affSColin Finck                if (!HalTranslateBusAddress(
1020c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].InterfaceType,
1021c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].BusNumber,
1022c2c66affSColin Finck                   DescriptorRaw->u.Port.Start,
1023c2c66affSColin Finck                   &AddressSpace,
1024c2c66affSColin Finck                   &DescriptorTranslated->u.Port.Start))
1025c2c66affSColin Finck                {
1026c2c66affSColin Finck                   Status = STATUS_UNSUCCESSFUL;
1027c2c66affSColin Finck                   DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
1028c2c66affSColin Finck                   goto cleanup;
1029c2c66affSColin Finck                }
1030c2c66affSColin Finck 
1031c2c66affSColin Finck                if (AddressSpace == 0)
1032c2c66affSColin Finck                {
1033c2c66affSColin Finck                    DPRINT1("Guessed incorrect address space: 1 -> 0\n");
1034c2c66affSColin Finck 
1035c2c66affSColin Finck                    /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are
1036c2c66affSColin Finck                     * invalid for this state but I'm not 100% sure */
1037c2c66affSColin Finck                    DescriptorRaw->Flags =
1038c2c66affSColin Finck                    DescriptorTranslated->Flags = CM_RESOURCE_PORT_MEMORY;
1039c2c66affSColin Finck                }
1040c2c66affSColin Finck                break;
1041c2c66affSColin Finck             }
1042c2c66affSColin Finck             case CmResourceTypeInterrupt:
1043c2c66affSColin Finck             {
1044b82bf8ceSTimo Kreuzer                KIRQL Irql;
1045c2c66affSColin Finck                DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
1046c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].InterfaceType,
1047c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].BusNumber,
1048c2c66affSColin Finck                   DescriptorRaw->u.Interrupt.Level,
1049c2c66affSColin Finck                   DescriptorRaw->u.Interrupt.Vector,
1050b82bf8ceSTimo Kreuzer                   &Irql,
1051c2c66affSColin Finck                   &DescriptorTranslated->u.Interrupt.Affinity);
1052b82bf8ceSTimo Kreuzer                DescriptorTranslated->u.Interrupt.Level = Irql;
1053c2c66affSColin Finck                if (!DescriptorTranslated->u.Interrupt.Vector)
1054c2c66affSColin Finck                {
1055c2c66affSColin Finck                    Status = STATUS_UNSUCCESSFUL;
1056c2c66affSColin Finck                    DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector,
1057c2c66affSColin Finck                                                                                                    DescriptorRaw->u.Interrupt.Level);
1058c2c66affSColin Finck                    goto cleanup;
1059c2c66affSColin Finck                }
1060c2c66affSColin Finck                break;
1061c2c66affSColin Finck             }
1062c2c66affSColin Finck             case CmResourceTypeMemory:
1063c2c66affSColin Finck             {
1064c2c66affSColin Finck                ULONG AddressSpace = 0; /* Memory space */
1065c2c66affSColin Finck                if (!HalTranslateBusAddress(
1066c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].InterfaceType,
1067c2c66affSColin Finck                   DeviceNode->ResourceList->List[i].BusNumber,
1068c2c66affSColin Finck                   DescriptorRaw->u.Memory.Start,
1069c2c66affSColin Finck                   &AddressSpace,
1070c2c66affSColin Finck                   &DescriptorTranslated->u.Memory.Start))
1071c2c66affSColin Finck                {
1072c2c66affSColin Finck                   Status = STATUS_UNSUCCESSFUL;
1073c2c66affSColin Finck                   DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
1074c2c66affSColin Finck                   goto cleanup;
1075c2c66affSColin Finck                }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck                if (AddressSpace != 0)
1078c2c66affSColin Finck                {
1079c2c66affSColin Finck                    DPRINT1("Guessed incorrect address space: 0 -> 1\n");
1080c2c66affSColin Finck 
1081c2c66affSColin Finck                    /* This should never happen for memory space */
1082c2c66affSColin Finck                    ASSERT(FALSE);
1083c2c66affSColin Finck                }
1084c2c66affSColin Finck             }
1085c2c66affSColin Finck 
1086c2c66affSColin Finck             case CmResourceTypeDma:
1087c2c66affSColin Finck             case CmResourceTypeBusNumber:
1088129e009aSHervé Poussineau             case CmResourceTypeDevicePrivate:
1089c2c66affSColin Finck             case CmResourceTypeDeviceSpecific:
1090c2c66affSColin Finck                /* Nothing to do */
1091c2c66affSColin Finck                break;
1092c2c66affSColin Finck             default:
1093c2c66affSColin Finck                DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type);
1094c2c66affSColin Finck                Status = STATUS_NOT_IMPLEMENTED;
1095c2c66affSColin Finck                goto cleanup;
1096c2c66affSColin Finck          }
1097c2c66affSColin Finck       }
1098c2c66affSColin Finck    }
1099c2c66affSColin Finck    return STATUS_SUCCESS;
1100c2c66affSColin Finck 
1101c2c66affSColin Finck cleanup:
1102c2c66affSColin Finck    /* Yes! Also delete ResourceList because ResourceList and
1103c2c66affSColin Finck     * ResourceListTranslated should be a pair! */
1104c2c66affSColin Finck    ExFreePool(DeviceNode->ResourceList);
1105c2c66affSColin Finck    DeviceNode->ResourceList = NULL;
1106c2c66affSColin Finck    if (DeviceNode->ResourceListTranslated)
1107c2c66affSColin Finck    {
1108c2c66affSColin Finck       ExFreePool(DeviceNode->ResourceListTranslated);
1109c2c66affSColin Finck       DeviceNode->ResourceList = NULL;
1110c2c66affSColin Finck    }
1111c2c66affSColin Finck    return Status;
1112c2c66affSColin Finck }
1113c2c66affSColin Finck 
1114c2c66affSColin Finck NTSTATUS
1115c2c66affSColin Finck NTAPI
IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)1116c2c66affSColin Finck IopAssignDeviceResources(
1117c2c66affSColin Finck    IN PDEVICE_NODE DeviceNode)
1118c2c66affSColin Finck {
1119c2c66affSColin Finck    NTSTATUS Status;
1120c2c66affSColin Finck    ULONG ListSize;
1121c2c66affSColin Finck 
1122c2c66affSColin Finck    Status = IopFilterResourceRequirements(DeviceNode);
1123c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1124c2c66affSColin Finck        goto ByeBye;
1125c2c66affSColin Finck 
1126c2c66affSColin Finck    if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements)
1127c2c66affSColin Finck    {
1128c2c66affSColin Finck       /* No resource needed for this device */
1129c2c66affSColin Finck       DeviceNode->ResourceList = NULL;
1130c2c66affSColin Finck       DeviceNode->ResourceListTranslated = NULL;
1131798fc13bSVictor Perevertkin       PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
1132798fc13bSVictor Perevertkin       DeviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED;
1133c2c66affSColin Finck 
1134c2c66affSColin Finck       return STATUS_SUCCESS;
1135c2c66affSColin Finck    }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck    if (DeviceNode->BootResources)
1138c2c66affSColin Finck    {
1139c2c66affSColin Finck        ListSize = PnpDetermineResourceListSize(DeviceNode->BootResources);
1140c2c66affSColin Finck 
1141c2c66affSColin Finck        DeviceNode->ResourceList = ExAllocatePool(PagedPool, ListSize);
1142c2c66affSColin Finck        if (!DeviceNode->ResourceList)
1143c2c66affSColin Finck        {
1144c2c66affSColin Finck            Status = STATUS_NO_MEMORY;
1145c2c66affSColin Finck            goto ByeBye;
1146c2c66affSColin Finck        }
1147c2c66affSColin Finck 
1148c2c66affSColin Finck        RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, ListSize);
1149c2c66affSColin Finck 
1150c2c66affSColin Finck        Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
1151c2c66affSColin Finck        if (!NT_SUCCESS(Status))
1152c2c66affSColin Finck        {
1153c2c66affSColin Finck            DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath);
1154c2c66affSColin Finck            ExFreePool(DeviceNode->ResourceList);
1155c2c66affSColin Finck            DeviceNode->ResourceList = NULL;
1156c2c66affSColin Finck        }
1157c2c66affSColin Finck    }
1158c2c66affSColin Finck    else
1159c2c66affSColin Finck    {
1160c2c66affSColin Finck        /* We'll make this from the requirements */
1161c2c66affSColin Finck        DeviceNode->ResourceList = NULL;
1162c2c66affSColin Finck    }
1163c2c66affSColin Finck 
1164c2c66affSColin Finck    /* No resources requirements */
1165c2c66affSColin Finck    if (!DeviceNode->ResourceRequirements)
1166c2c66affSColin Finck        goto Finish;
1167c2c66affSColin Finck 
1168c2c66affSColin Finck    /* Call HAL to fixup our resource requirements list */
1169c2c66affSColin Finck    HalAdjustResourceList(&DeviceNode->ResourceRequirements);
1170c2c66affSColin Finck 
1171c2c66affSColin Finck    /* Add resource requirements that aren't in the list we already got */
1172c2c66affSColin Finck    Status = IopFixupResourceListWithRequirements(DeviceNode->ResourceRequirements,
1173c2c66affSColin Finck                                                  &DeviceNode->ResourceList);
1174c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1175c2c66affSColin Finck    {
1176c2c66affSColin Finck        DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
1177c2c66affSColin Finck        DeviceNode->Problem = CM_PROB_NORMAL_CONFLICT;
1178c2c66affSColin Finck        goto ByeBye;
1179c2c66affSColin Finck    }
1180c2c66affSColin Finck 
1181c2c66affSColin Finck    /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */
1182c2c66affSColin Finck    ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES);
1183c2c66affSColin Finck 
1184c2c66affSColin Finck Finish:
1185c2c66affSColin Finck    Status = IopTranslateDeviceResources(DeviceNode);
1186c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1187c2c66affSColin Finck    {
1188c2c66affSColin Finck        DeviceNode->Problem = CM_PROB_TRANSLATION_FAILED;
1189c2c66affSColin Finck        DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
1190c2c66affSColin Finck        goto ByeBye;
1191c2c66affSColin Finck    }
1192c2c66affSColin Finck 
1193c2c66affSColin Finck    Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
1194c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1195c2c66affSColin Finck        goto ByeBye;
1196c2c66affSColin Finck 
1197c2c66affSColin Finck    Status = IopUpdateControlKeyWithResources(DeviceNode);
1198c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1199c2c66affSColin Finck        goto ByeBye;
1200c2c66affSColin Finck 
1201798fc13bSVictor Perevertkin    PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
1202c2c66affSColin Finck 
1203c2c66affSColin Finck    return STATUS_SUCCESS;
1204c2c66affSColin Finck 
1205c2c66affSColin Finck ByeBye:
1206c2c66affSColin Finck    if (DeviceNode->ResourceList)
1207c2c66affSColin Finck    {
1208c2c66affSColin Finck       ExFreePool(DeviceNode->ResourceList);
1209c2c66affSColin Finck       DeviceNode->ResourceList = NULL;
1210c2c66affSColin Finck    }
1211c2c66affSColin Finck 
1212c2c66affSColin Finck    DeviceNode->ResourceListTranslated = NULL;
1213c2c66affSColin Finck 
1214c2c66affSColin Finck    return Status;
1215c2c66affSColin Finck }
1216c2c66affSColin Finck 
1217c2c66affSColin Finck static
1218c2c66affSColin Finck BOOLEAN
IopCheckForResourceConflict(IN PCM_RESOURCE_LIST ResourceList1,IN PCM_RESOURCE_LIST ResourceList2,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)1219c2c66affSColin Finck IopCheckForResourceConflict(
1220c2c66affSColin Finck    IN PCM_RESOURCE_LIST ResourceList1,
1221c2c66affSColin Finck    IN PCM_RESOURCE_LIST ResourceList2,
1222c2c66affSColin Finck    IN BOOLEAN Silent,
1223c2c66affSColin Finck    OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
1224c2c66affSColin Finck {
1225c2c66affSColin Finck    ULONG i, ii;
1226c2c66affSColin Finck    BOOLEAN Result = FALSE;
1227b82bf8ceSTimo Kreuzer    PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
1228c2c66affSColin Finck 
1229b82bf8ceSTimo Kreuzer    FullDescriptor = &ResourceList1->List[0];
1230c2c66affSColin Finck    for (i = 0; i < ResourceList1->Count; i++)
1231c2c66affSColin Finck    {
1232b82bf8ceSTimo Kreuzer       PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList;
1233b82bf8ceSTimo Kreuzer       FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
1234b82bf8ceSTimo Kreuzer 
1235c2c66affSColin Finck       for (ii = 0; ii < ResList->Count; ii++)
1236c2c66affSColin Finck       {
1237b82bf8ceSTimo Kreuzer         /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1238b82bf8ceSTimo Kreuzer            but only one is allowed and it must be the last one in the list! */
1239c2c66affSColin Finck          PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = &ResList->PartialDescriptors[ii];
1240c2c66affSColin Finck 
1241c2c66affSColin Finck          Result = IopCheckResourceDescriptor(ResDesc,
1242c2c66affSColin Finck                                              ResourceList2,
1243c2c66affSColin Finck                                              Silent,
1244c2c66affSColin Finck                                              ConflictingDescriptor);
1245c2c66affSColin Finck          if (Result) goto ByeBye;
1246c2c66affSColin Finck       }
1247c2c66affSColin Finck    }
1248c2c66affSColin Finck 
1249c2c66affSColin Finck ByeBye:
1250c2c66affSColin Finck 
1251c2c66affSColin Finck    return Result;
1252c2c66affSColin Finck }
1253c2c66affSColin Finck 
1254c2c66affSColin Finck NTSTATUS NTAPI
IopDetectResourceConflict(IN PCM_RESOURCE_LIST ResourceList,IN BOOLEAN Silent,OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)1255c2c66affSColin Finck IopDetectResourceConflict(
1256c2c66affSColin Finck    IN PCM_RESOURCE_LIST ResourceList,
1257c2c66affSColin Finck    IN BOOLEAN Silent,
1258c2c66affSColin Finck    OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
1259c2c66affSColin Finck {
1260c2c66affSColin Finck    OBJECT_ATTRIBUTES ObjectAttributes;
1261c2c66affSColin Finck    UNICODE_STRING KeyName;
1262c2c66affSColin Finck    HANDLE ResourceMapKey = NULL, ChildKey2 = NULL, ChildKey3 = NULL;
1263c2c66affSColin Finck    ULONG KeyInformationLength, RequiredLength, KeyValueInformationLength, KeyNameInformationLength;
1264c2c66affSColin Finck    PKEY_BASIC_INFORMATION KeyInformation;
1265c2c66affSColin Finck    PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
1266c2c66affSColin Finck    PKEY_VALUE_BASIC_INFORMATION KeyNameInformation;
1267*49358f34SHervé Poussineau    ULONG ChildKeyIndex1 = 0, ChildKeyIndex2, ChildKeyIndex3;
1268c2c66affSColin Finck    NTSTATUS Status;
1269c2c66affSColin Finck 
1270c2c66affSColin Finck    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1271c2c66affSColin Finck    InitializeObjectAttributes(&ObjectAttributes,
1272c2c66affSColin Finck                               &KeyName,
1273c2c66affSColin Finck                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1274c2c66affSColin Finck                               NULL,
1275c2c66affSColin Finck                               NULL);
1276c2c66affSColin Finck    Status = ZwOpenKey(&ResourceMapKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
1277c2c66affSColin Finck    if (!NT_SUCCESS(Status))
1278c2c66affSColin Finck    {
1279c2c66affSColin Finck       /* The key is missing which means we are the first device */
1280c2c66affSColin Finck       return STATUS_SUCCESS;
1281c2c66affSColin Finck    }
1282c2c66affSColin Finck 
1283c2c66affSColin Finck    while (TRUE)
1284c2c66affSColin Finck    {
1285c2c66affSColin Finck       Status = ZwEnumerateKey(ResourceMapKey,
1286c2c66affSColin Finck                               ChildKeyIndex1,
1287c2c66affSColin Finck                               KeyBasicInformation,
1288c2c66affSColin Finck                               NULL,
1289c2c66affSColin Finck                               0,
1290c2c66affSColin Finck                               &RequiredLength);
1291c2c66affSColin Finck       if (Status == STATUS_NO_MORE_ENTRIES)
1292c2c66affSColin Finck           break;
1293c2c66affSColin Finck       else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
1294c2c66affSColin Finck       {
1295c2c66affSColin Finck           KeyInformationLength = RequiredLength;
1296c2c66affSColin Finck           KeyInformation = ExAllocatePoolWithTag(PagedPool,
1297c2c66affSColin Finck                                                  KeyInformationLength,
1298c2c66affSColin Finck                                                  TAG_IO);
1299c2c66affSColin Finck           if (!KeyInformation)
1300c2c66affSColin Finck           {
1301c2c66affSColin Finck               Status = STATUS_INSUFFICIENT_RESOURCES;
1302c2c66affSColin Finck               goto cleanup;
1303c2c66affSColin Finck           }
1304c2c66affSColin Finck 
1305c2c66affSColin Finck           Status = ZwEnumerateKey(ResourceMapKey,
1306c2c66affSColin Finck                                   ChildKeyIndex1,
1307c2c66affSColin Finck                                   KeyBasicInformation,
1308c2c66affSColin Finck                                   KeyInformation,
1309c2c66affSColin Finck                                   KeyInformationLength,
1310c2c66affSColin Finck                                   &RequiredLength);
1311c2c66affSColin Finck       }
1312c2c66affSColin Finck       else
1313c2c66affSColin Finck          goto cleanup;
1314c2c66affSColin Finck       ChildKeyIndex1++;
1315c2c66affSColin Finck       if (!NT_SUCCESS(Status))
1316c2c66affSColin Finck       {
1317c2c66affSColin Finck           ExFreePoolWithTag(KeyInformation, TAG_IO);
1318c2c66affSColin Finck           goto cleanup;
1319c2c66affSColin Finck       }
1320c2c66affSColin Finck 
1321c2c66affSColin Finck       KeyName.Buffer = KeyInformation->Name;
1322c2c66affSColin Finck       KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
1323c2c66affSColin Finck       InitializeObjectAttributes(&ObjectAttributes,
1324c2c66affSColin Finck                                  &KeyName,
1325c2c66affSColin Finck                                  OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1326c2c66affSColin Finck                                  ResourceMapKey,
1327c2c66affSColin Finck                                  NULL);
1328c2c66affSColin Finck       Status = ZwOpenKey(&ChildKey2,
1329c2c66affSColin Finck                          KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
1330c2c66affSColin Finck                          &ObjectAttributes);
1331c2c66affSColin Finck       ExFreePoolWithTag(KeyInformation, TAG_IO);
1332c2c66affSColin Finck       if (!NT_SUCCESS(Status))
1333c2c66affSColin Finck           goto cleanup;
1334c2c66affSColin Finck 
1335*49358f34SHervé Poussineau       ChildKeyIndex2 = 0;
1336c2c66affSColin Finck       while (TRUE)
1337c2c66affSColin Finck       {
1338c2c66affSColin Finck           Status = ZwEnumerateKey(ChildKey2,
1339c2c66affSColin Finck                                   ChildKeyIndex2,
1340c2c66affSColin Finck                                   KeyBasicInformation,
1341c2c66affSColin Finck                                   NULL,
1342c2c66affSColin Finck                                   0,
1343c2c66affSColin Finck                                   &RequiredLength);
1344c2c66affSColin Finck           if (Status == STATUS_NO_MORE_ENTRIES)
1345c2c66affSColin Finck               break;
1346c2c66affSColin Finck           else if (Status == STATUS_BUFFER_TOO_SMALL)
1347c2c66affSColin Finck           {
1348c2c66affSColin Finck               KeyInformationLength = RequiredLength;
1349c2c66affSColin Finck               KeyInformation = ExAllocatePoolWithTag(PagedPool,
1350c2c66affSColin Finck                                                      KeyInformationLength,
1351c2c66affSColin Finck                                                      TAG_IO);
1352c2c66affSColin Finck               if (!KeyInformation)
1353c2c66affSColin Finck               {
1354c2c66affSColin Finck                   Status = STATUS_INSUFFICIENT_RESOURCES;
1355c2c66affSColin Finck                   goto cleanup;
1356c2c66affSColin Finck               }
1357c2c66affSColin Finck 
1358c2c66affSColin Finck               Status = ZwEnumerateKey(ChildKey2,
1359c2c66affSColin Finck                                       ChildKeyIndex2,
1360c2c66affSColin Finck                                       KeyBasicInformation,
1361c2c66affSColin Finck                                       KeyInformation,
1362c2c66affSColin Finck                                       KeyInformationLength,
1363c2c66affSColin Finck                                       &RequiredLength);
1364c2c66affSColin Finck           }
1365c2c66affSColin Finck           else
1366c2c66affSColin Finck               goto cleanup;
1367c2c66affSColin Finck           ChildKeyIndex2++;
1368c2c66affSColin Finck           if (!NT_SUCCESS(Status))
1369c2c66affSColin Finck           {
1370c2c66affSColin Finck               ExFreePoolWithTag(KeyInformation, TAG_IO);
1371c2c66affSColin Finck               goto cleanup;
1372c2c66affSColin Finck           }
1373c2c66affSColin Finck 
1374c2c66affSColin Finck           KeyName.Buffer = KeyInformation->Name;
1375c2c66affSColin Finck           KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength;
1376c2c66affSColin Finck           InitializeObjectAttributes(&ObjectAttributes,
1377c2c66affSColin Finck                                      &KeyName,
1378c2c66affSColin Finck                                      OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1379c2c66affSColin Finck                                      ChildKey2,
1380c2c66affSColin Finck                                      NULL);
1381c2c66affSColin Finck           Status = ZwOpenKey(&ChildKey3, KEY_QUERY_VALUE, &ObjectAttributes);
1382c2c66affSColin Finck           ExFreePoolWithTag(KeyInformation, TAG_IO);
1383c2c66affSColin Finck           if (!NT_SUCCESS(Status))
1384c2c66affSColin Finck               goto cleanup;
1385c2c66affSColin Finck 
1386*49358f34SHervé Poussineau           ChildKeyIndex3 = 0;
1387c2c66affSColin Finck           while (TRUE)
1388c2c66affSColin Finck           {
1389c2c66affSColin Finck               Status = ZwEnumerateValueKey(ChildKey3,
1390c2c66affSColin Finck                                            ChildKeyIndex3,
1391c2c66affSColin Finck                                            KeyValuePartialInformation,
1392c2c66affSColin Finck                                            NULL,
1393c2c66affSColin Finck                                            0,
1394c2c66affSColin Finck                                            &RequiredLength);
1395c2c66affSColin Finck               if (Status == STATUS_NO_MORE_ENTRIES)
1396c2c66affSColin Finck                   break;
1397c2c66affSColin Finck               else if (Status == STATUS_BUFFER_TOO_SMALL)
1398c2c66affSColin Finck               {
1399c2c66affSColin Finck                   KeyValueInformationLength = RequiredLength;
1400c2c66affSColin Finck                   KeyValueInformation = ExAllocatePoolWithTag(PagedPool,
1401c2c66affSColin Finck                                                               KeyValueInformationLength,
1402c2c66affSColin Finck                                                               TAG_IO);
1403c2c66affSColin Finck                   if (!KeyValueInformation)
1404c2c66affSColin Finck                   {
1405c2c66affSColin Finck                       Status = STATUS_INSUFFICIENT_RESOURCES;
1406c2c66affSColin Finck                       goto cleanup;
1407c2c66affSColin Finck                   }
1408c2c66affSColin Finck 
1409c2c66affSColin Finck                   Status = ZwEnumerateValueKey(ChildKey3,
1410c2c66affSColin Finck                                                ChildKeyIndex3,
1411c2c66affSColin Finck                                                KeyValuePartialInformation,
1412c2c66affSColin Finck                                                KeyValueInformation,
1413c2c66affSColin Finck                                                KeyValueInformationLength,
1414c2c66affSColin Finck                                                &RequiredLength);
1415c2c66affSColin Finck               }
1416c2c66affSColin Finck               else
1417c2c66affSColin Finck                   goto cleanup;
1418c2c66affSColin Finck               if (!NT_SUCCESS(Status))
1419c2c66affSColin Finck               {
1420c2c66affSColin Finck                   ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1421c2c66affSColin Finck                   goto cleanup;
1422c2c66affSColin Finck               }
1423c2c66affSColin Finck 
1424c2c66affSColin Finck               Status = ZwEnumerateValueKey(ChildKey3,
1425c2c66affSColin Finck                                            ChildKeyIndex3,
1426c2c66affSColin Finck                                            KeyValueBasicInformation,
1427c2c66affSColin Finck                                            NULL,
1428c2c66affSColin Finck                                            0,
1429c2c66affSColin Finck                                            &RequiredLength);
1430c2c66affSColin Finck               if (Status == STATUS_BUFFER_TOO_SMALL)
1431c2c66affSColin Finck               {
1432c2c66affSColin Finck                   KeyNameInformationLength = RequiredLength;
1433c2c66affSColin Finck                   KeyNameInformation = ExAllocatePoolWithTag(PagedPool,
1434c2c66affSColin Finck                                                              KeyNameInformationLength + sizeof(WCHAR),
1435c2c66affSColin Finck                                                              TAG_IO);
1436c2c66affSColin Finck                   if (!KeyNameInformation)
1437c2c66affSColin Finck                   {
1438c2c66affSColin Finck                       Status = STATUS_INSUFFICIENT_RESOURCES;
1439c2c66affSColin Finck                       goto cleanup;
1440c2c66affSColin Finck                   }
1441c2c66affSColin Finck 
1442c2c66affSColin Finck                   Status = ZwEnumerateValueKey(ChildKey3,
1443c2c66affSColin Finck                                                ChildKeyIndex3,
1444c2c66affSColin Finck                                                KeyValueBasicInformation,
1445c2c66affSColin Finck                                                KeyNameInformation,
1446c2c66affSColin Finck                                                KeyNameInformationLength,
1447c2c66affSColin Finck                                                &RequiredLength);
1448c2c66affSColin Finck               }
1449c2c66affSColin Finck               else
1450c2c66affSColin Finck                   goto cleanup;
1451c2c66affSColin Finck               ChildKeyIndex3++;
1452c2c66affSColin Finck               if (!NT_SUCCESS(Status))
1453c2c66affSColin Finck               {
1454c2c66affSColin Finck                   ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1455c2c66affSColin Finck                   goto cleanup;
1456c2c66affSColin Finck               }
1457c2c66affSColin Finck 
1458c2c66affSColin Finck               KeyNameInformation->Name[KeyNameInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
1459c2c66affSColin Finck 
1460c2c66affSColin Finck               /* Skip translated entries */
1461c2c66affSColin Finck               if (wcsstr(KeyNameInformation->Name, L".Translated"))
1462c2c66affSColin Finck               {
1463c2c66affSColin Finck                   ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1464c2c66affSColin Finck                   ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1465c2c66affSColin Finck                   continue;
1466c2c66affSColin Finck               }
1467c2c66affSColin Finck 
1468c2c66affSColin Finck               ExFreePoolWithTag(KeyNameInformation, TAG_IO);
1469c2c66affSColin Finck 
1470c2c66affSColin Finck               if (IopCheckForResourceConflict(ResourceList,
1471c2c66affSColin Finck                                               (PCM_RESOURCE_LIST)KeyValueInformation->Data,
1472c2c66affSColin Finck                                               Silent,
1473c2c66affSColin Finck                                               ConflictingDescriptor))
1474c2c66affSColin Finck               {
1475c2c66affSColin Finck                   ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1476c2c66affSColin Finck                   Status = STATUS_CONFLICTING_ADDRESSES;
1477c2c66affSColin Finck                   goto cleanup;
1478c2c66affSColin Finck               }
1479c2c66affSColin Finck 
1480c2c66affSColin Finck               ExFreePoolWithTag(KeyValueInformation, TAG_IO);
1481c2c66affSColin Finck           }
1482c2c66affSColin Finck       }
1483c2c66affSColin Finck    }
1484c2c66affSColin Finck 
1485c2c66affSColin Finck cleanup:
1486c2c66affSColin Finck    if (ResourceMapKey != NULL)
1487c2c66affSColin Finck        ObCloseHandle(ResourceMapKey, KernelMode);
1488c2c66affSColin Finck    if (ChildKey2 != NULL)
1489c2c66affSColin Finck        ObCloseHandle(ChildKey2, KernelMode);
1490c2c66affSColin Finck    if (ChildKey3 != NULL)
1491c2c66affSColin Finck        ObCloseHandle(ChildKey3, KernelMode);
1492c2c66affSColin Finck 
1493c2c66affSColin Finck    if (Status == STATUS_NO_MORE_ENTRIES)
1494c2c66affSColin Finck        Status = STATUS_SUCCESS;
1495c2c66affSColin Finck 
1496c2c66affSColin Finck    return Status;
1497c2c66affSColin Finck }
1498c2c66affSColin Finck 
1499