Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpnpres.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * COPYRIGHT: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/pnpmgr/pnpres.c 00005 * PURPOSE: Resource handling code 00006 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) 00007 * ReactOS Portable Systems Group 00008 */ 00009 00010 #include <ntoskrnl.h> 00011 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 static 00016 BOOLEAN 00017 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) 00018 { 00019 CM_RESOURCE_LIST CmList; 00020 NTSTATUS Status; 00021 00022 CmList.Count = 1; 00023 CmList.List[0].InterfaceType = InterfaceTypeUndefined; 00024 CmList.List[0].BusNumber = 0; 00025 CmList.List[0].PartialResourceList.Version = 1; 00026 CmList.List[0].PartialResourceList.Revision = 1; 00027 CmList.List[0].PartialResourceList.Count = 1; 00028 CmList.List[0].PartialResourceList.PartialDescriptors[0] = *CmDesc; 00029 00030 Status = IopDetectResourceConflict(&CmList, TRUE, ConflictingDescriptor); 00031 if (Status == STATUS_CONFLICTING_ADDRESSES) 00032 return TRUE; 00033 00034 return FALSE; 00035 } 00036 00037 static 00038 BOOLEAN 00039 IopFindBusNumberResource( 00040 IN PIO_RESOURCE_DESCRIPTOR IoDesc, 00041 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) 00042 { 00043 ULONG Start; 00044 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; 00045 00046 ASSERT(IoDesc->Type == CmDesc->Type); 00047 ASSERT(IoDesc->Type == CmResourceTypeBusNumber); 00048 00049 for (Start = IoDesc->u.BusNumber.MinBusNumber; 00050 Start <= IoDesc->u.BusNumber.MaxBusNumber - IoDesc->u.BusNumber.Length + 1; 00051 Start++) 00052 { 00053 CmDesc->u.BusNumber.Length = IoDesc->u.BusNumber.Length; 00054 CmDesc->u.BusNumber.Start = Start; 00055 00056 if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) 00057 { 00058 Start += ConflictingDesc.u.BusNumber.Start + ConflictingDesc.u.BusNumber.Length; 00059 } 00060 else 00061 { 00062 DPRINT1("Satisfying bus number requirement with 0x%x (length: 0x%x)\n", Start, CmDesc->u.BusNumber.Length); 00063 return TRUE; 00064 } 00065 } 00066 00067 return FALSE; 00068 } 00069 00070 static 00071 BOOLEAN 00072 IopFindMemoryResource( 00073 IN PIO_RESOURCE_DESCRIPTOR IoDesc, 00074 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) 00075 { 00076 LONGLONG Start; 00077 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; 00078 00079 ASSERT(IoDesc->Type == CmDesc->Type); 00080 ASSERT(IoDesc->Type == CmResourceTypeMemory); 00081 00082 /* HACK */ 00083 if (IoDesc->u.Memory.Alignment == 0) IoDesc->u.Memory.Alignment = 1; 00084 00085 for (Start = IoDesc->u.Memory.MinimumAddress.QuadPart; 00086 Start <= IoDesc->u.Memory.MaximumAddress.QuadPart - IoDesc->u.Memory.Length + 1; 00087 Start += IoDesc->u.Memory.Alignment) 00088 { 00089 CmDesc->u.Memory.Length = IoDesc->u.Memory.Length; 00090 CmDesc->u.Memory.Start.QuadPart = Start; 00091 00092 if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) 00093 { 00094 Start += ConflictingDesc.u.Memory.Start.QuadPart + 00095 ConflictingDesc.u.Memory.Length; 00096 } 00097 else 00098 { 00099 DPRINT1("Satisfying memory requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Memory.Length); 00100 return TRUE; 00101 } 00102 } 00103 00104 return FALSE; 00105 } 00106 00107 static 00108 BOOLEAN 00109 IopFindPortResource( 00110 IN PIO_RESOURCE_DESCRIPTOR IoDesc, 00111 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) 00112 { 00113 LONGLONG Start; 00114 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; 00115 00116 ASSERT(IoDesc->Type == CmDesc->Type); 00117 ASSERT(IoDesc->Type == CmResourceTypePort); 00118 00119 /* HACK */ 00120 if (IoDesc->u.Port.Alignment == 0) IoDesc->u.Port.Alignment = 1; 00121 00122 for (Start = IoDesc->u.Port.MinimumAddress.QuadPart; 00123 Start <= IoDesc->u.Port.MaximumAddress.QuadPart - IoDesc->u.Port.Length + 1; 00124 Start += IoDesc->u.Port.Alignment) 00125 { 00126 CmDesc->u.Port.Length = IoDesc->u.Port.Length; 00127 CmDesc->u.Port.Start.QuadPart = Start; 00128 00129 if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) 00130 { 00131 Start += ConflictingDesc.u.Port.Start.QuadPart + ConflictingDesc.u.Port.Length; 00132 } 00133 else 00134 { 00135 DPRINT1("Satisfying port requirement with 0x%I64x (length: 0x%x)\n", Start, CmDesc->u.Port.Length); 00136 return TRUE; 00137 } 00138 } 00139 00140 return FALSE; 00141 } 00142 00143 static 00144 BOOLEAN 00145 IopFindDmaResource( 00146 IN PIO_RESOURCE_DESCRIPTOR IoDesc, 00147 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) 00148 { 00149 ULONG Channel; 00150 00151 ASSERT(IoDesc->Type == CmDesc->Type); 00152 ASSERT(IoDesc->Type == CmResourceTypeDma); 00153 00154 for (Channel = IoDesc->u.Dma.MinimumChannel; 00155 Channel <= IoDesc->u.Dma.MaximumChannel; 00156 Channel++) 00157 { 00158 CmDesc->u.Dma.Channel = Channel; 00159 CmDesc->u.Dma.Port = 0; 00160 00161 if (!IopCheckDescriptorForConflict(CmDesc, NULL)) 00162 { 00163 DPRINT1("Satisfying DMA requirement with channel 0x%x\n", Channel); 00164 return TRUE; 00165 } 00166 } 00167 00168 return FALSE; 00169 } 00170 00171 static 00172 BOOLEAN 00173 IopFindInterruptResource( 00174 IN PIO_RESOURCE_DESCRIPTOR IoDesc, 00175 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) 00176 { 00177 ULONG Vector; 00178 00179 ASSERT(IoDesc->Type == CmDesc->Type); 00180 ASSERT(IoDesc->Type == CmResourceTypeInterrupt); 00181 00182 for (Vector = IoDesc->u.Interrupt.MinimumVector; 00183 Vector <= IoDesc->u.Interrupt.MaximumVector; 00184 Vector++) 00185 { 00186 CmDesc->u.Interrupt.Vector = Vector; 00187 CmDesc->u.Interrupt.Level = Vector; 00188 CmDesc->u.Interrupt.Affinity = (KAFFINITY)-1; 00189 00190 if (!IopCheckDescriptorForConflict(CmDesc, NULL)) 00191 { 00192 DPRINT1("Satisfying interrupt requirement with IRQ 0x%x\n", Vector); 00193 return TRUE; 00194 } 00195 } 00196 00197 return FALSE; 00198 } 00199 00200 NTSTATUS NTAPI 00201 IopFixupResourceListWithRequirements( 00202 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList, 00203 OUT PCM_RESOURCE_LIST *ResourceList) 00204 { 00205 ULONG i, OldCount; 00206 BOOLEAN AlternateRequired = FALSE; 00207 00208 /* Save the initial resource count when we got here so we can restore if an alternate fails */ 00209 if (*ResourceList != NULL) 00210 OldCount = (*ResourceList)->List[0].PartialResourceList.Count; 00211 else 00212 OldCount = 0; 00213 00214 for (i = 0; i < RequirementsList->AlternativeLists; i++) 00215 { 00216 ULONG ii; 00217 PIO_RESOURCE_LIST ResList = &RequirementsList->List[i]; 00218 00219 /* We need to get back to where we were before processing the last alternative list */ 00220 if (OldCount == 0 && *ResourceList != NULL) 00221 { 00222 /* Just free it and kill the pointer */ 00223 ExFreePool(*ResourceList); 00224 *ResourceList = NULL; 00225 } 00226 else if (OldCount != 0) 00227 { 00228 PCM_RESOURCE_LIST NewList; 00229 00230 /* Let's resize it */ 00231 (*ResourceList)->List[0].PartialResourceList.Count = OldCount; 00232 00233 /* Allocate the new smaller list */ 00234 NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList)); 00235 if (!NewList) 00236 return STATUS_NO_MEMORY; 00237 00238 /* Copy the old stuff back */ 00239 RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList)); 00240 00241 /* Free the old one */ 00242 ExFreePool(*ResourceList); 00243 00244 /* Store the pointer to the new one */ 00245 *ResourceList = NewList; 00246 } 00247 00248 for (ii = 0; ii < ResList->Count; ii++) 00249 { 00250 ULONG iii; 00251 PCM_PARTIAL_RESOURCE_LIST PartialList = (*ResourceList) ? &(*ResourceList)->List[0].PartialResourceList : NULL; 00252 PIO_RESOURCE_DESCRIPTOR IoDesc = &ResList->Descriptors[ii]; 00253 BOOLEAN Matched = FALSE; 00254 00255 /* Skip alternates if we don't need one */ 00256 if (!AlternateRequired && (IoDesc->Option & IO_RESOURCE_ALTERNATIVE)) 00257 { 00258 DPRINT("Skipping unneeded alternate\n"); 00259 continue; 00260 } 00261 00262 /* Check if we couldn't satsify a requirement or its alternates */ 00263 if (AlternateRequired && !(IoDesc->Option & IO_RESOURCE_ALTERNATIVE)) 00264 { 00265 DPRINT1("Unable to satisfy preferred resource or alternates in list %d\n", i); 00266 00267 /* Break out of this loop and try the next list */ 00268 break; 00269 } 00270 00271 for (iii = 0; PartialList && iii < PartialList->Count && !Matched; iii++) 00272 { 00273 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = &PartialList->PartialDescriptors[iii]; 00274 00275 /* First check types */ 00276 if (IoDesc->Type != CmDesc->Type) 00277 continue; 00278 00279 switch (IoDesc->Type) 00280 { 00281 case CmResourceTypeInterrupt: 00282 /* Make sure it satisfies our vector range */ 00283 if (CmDesc->u.Interrupt.Vector >= IoDesc->u.Interrupt.MinimumVector && 00284 CmDesc->u.Interrupt.Vector <= IoDesc->u.Interrupt.MaximumVector) 00285 { 00286 /* Found it */ 00287 Matched = TRUE; 00288 } 00289 else 00290 { 00291 DPRINT("Interrupt - Not a match! 0x%x not inside 0x%x to 0x%x\n", 00292 CmDesc->u.Interrupt.Vector, 00293 IoDesc->u.Interrupt.MinimumVector, 00294 IoDesc->u.Interrupt.MaximumVector); 00295 } 00296 break; 00297 00298 case CmResourceTypeMemory: 00299 case CmResourceTypePort: 00300 /* Make sure the length matches and it satisfies our address range */ 00301 if (CmDesc->u.Memory.Length == IoDesc->u.Memory.Length && 00302 CmDesc->u.Memory.Start.QuadPart >= IoDesc->u.Memory.MinimumAddress.QuadPart && 00303 CmDesc->u.Memory.Start.QuadPart + CmDesc->u.Memory.Length - 1 <= IoDesc->u.Memory.MaximumAddress.QuadPart) 00304 { 00305 /* Found it */ 00306 Matched = TRUE; 00307 } 00308 else 00309 { 00310 DPRINT("Memory/Port - Not a match! 0x%I64x with length 0x%x not inside 0x%I64x to 0x%I64x with length 0x%x\n", 00311 CmDesc->u.Memory.Start.QuadPart, 00312 CmDesc->u.Memory.Length, 00313 IoDesc->u.Memory.MinimumAddress.QuadPart, 00314 IoDesc->u.Memory.MaximumAddress.QuadPart, 00315 IoDesc->u.Memory.Length); 00316 } 00317 break; 00318 00319 case CmResourceTypeBusNumber: 00320 /* Make sure the length matches and it satisfies our bus number range */ 00321 if (CmDesc->u.BusNumber.Length == IoDesc->u.BusNumber.Length && 00322 CmDesc->u.BusNumber.Start >= IoDesc->u.BusNumber.MinBusNumber && 00323 CmDesc->u.BusNumber.Start + CmDesc->u.BusNumber.Length - 1 <= IoDesc->u.BusNumber.MaxBusNumber) 00324 { 00325 /* Found it */ 00326 Matched = TRUE; 00327 } 00328 else 00329 { 00330 DPRINT("Bus Number - Not a match! 0x%x with length 0x%x not inside 0x%x to 0x%x with length 0x%x\n", 00331 CmDesc->u.BusNumber.Start, 00332 CmDesc->u.BusNumber.Length, 00333 IoDesc->u.BusNumber.MinBusNumber, 00334 IoDesc->u.BusNumber.MaxBusNumber, 00335 IoDesc->u.BusNumber.Length); 00336 } 00337 break; 00338 00339 case CmResourceTypeDma: 00340 /* Make sure it fits in our channel range */ 00341 if (CmDesc->u.Dma.Channel >= IoDesc->u.Dma.MinimumChannel && 00342 CmDesc->u.Dma.Channel <= IoDesc->u.Dma.MaximumChannel) 00343 { 00344 /* Found it */ 00345 Matched = TRUE; 00346 } 00347 else 00348 { 00349 DPRINT("DMA - Not a match! 0x%x not inside 0x%x to 0x%x\n", 00350 CmDesc->u.Dma.Channel, 00351 IoDesc->u.Dma.MinimumChannel, 00352 IoDesc->u.Dma.MaximumChannel); 00353 } 00354 break; 00355 00356 default: 00357 /* Other stuff is fine */ 00358 Matched = TRUE; 00359 break; 00360 } 00361 } 00362 00363 /* Check if we found a matching descriptor */ 00364 if (!Matched) 00365 { 00366 PCM_RESOURCE_LIST NewList; 00367 CM_PARTIAL_RESOURCE_DESCRIPTOR NewDesc; 00368 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescPtr; 00369 BOOLEAN FoundResource = TRUE; 00370 00371 /* Setup the new CM descriptor */ 00372 NewDesc.Type = IoDesc->Type; 00373 NewDesc.Flags = IoDesc->Flags; 00374 NewDesc.ShareDisposition = IoDesc->ShareDisposition; 00375 00376 /* Let'se see if we can find a resource to satisfy this */ 00377 switch (IoDesc->Type) 00378 { 00379 case CmResourceTypeInterrupt: 00380 /* Find an available interrupt */ 00381 if (!IopFindInterruptResource(IoDesc, &NewDesc)) 00382 { 00383 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n", 00384 IoDesc->u.Interrupt.MinimumVector, IoDesc->u.Interrupt.MaximumVector); 00385 00386 FoundResource = FALSE; 00387 } 00388 break; 00389 00390 case CmResourceTypePort: 00391 /* Find an available port range */ 00392 if (!IopFindPortResource(IoDesc, &NewDesc)) 00393 { 00394 DPRINT1("Failed to find an available port resource (0x%I64x to 0x%I64x length: 0x%x)\n", 00395 IoDesc->u.Port.MinimumAddress.QuadPart, IoDesc->u.Port.MaximumAddress.QuadPart, 00396 IoDesc->u.Port.Length); 00397 00398 FoundResource = FALSE; 00399 } 00400 break; 00401 00402 case CmResourceTypeMemory: 00403 /* Find an available memory range */ 00404 if (!IopFindMemoryResource(IoDesc, &NewDesc)) 00405 { 00406 DPRINT1("Failed to find an available memory resource (0x%I64x to 0x%I64x length: 0x%x)\n", 00407 IoDesc->u.Memory.MinimumAddress.QuadPart, IoDesc->u.Memory.MaximumAddress.QuadPart, 00408 IoDesc->u.Memory.Length); 00409 00410 FoundResource = FALSE; 00411 } 00412 break; 00413 00414 case CmResourceTypeBusNumber: 00415 /* Find an available bus address range */ 00416 if (!IopFindBusNumberResource(IoDesc, &NewDesc)) 00417 { 00418 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n", 00419 IoDesc->u.BusNumber.MinBusNumber, IoDesc->u.BusNumber.MaxBusNumber, 00420 IoDesc->u.BusNumber.Length); 00421 00422 FoundResource = FALSE; 00423 } 00424 break; 00425 00426 case CmResourceTypeDma: 00427 /* Find an available DMA channel */ 00428 if (!IopFindDmaResource(IoDesc, &NewDesc)) 00429 { 00430 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n", 00431 IoDesc->u.Dma.MinimumChannel, IoDesc->u.Dma.MaximumChannel); 00432 00433 FoundResource = FALSE; 00434 } 00435 break; 00436 00437 default: 00438 DPRINT1("Unsupported resource type: %x\n", IoDesc->Type); 00439 FoundResource = FALSE; 00440 break; 00441 } 00442 00443 /* Check if it's missing and required */ 00444 if (!FoundResource && IoDesc->Option == 0) 00445 { 00446 /* Break out of this loop and try the next list */ 00447 DPRINT1("Unable to satisfy required resource in list %d\n", i); 00448 break; 00449 } 00450 else if (!FoundResource) 00451 { 00452 /* Try an alternate for this preferred descriptor */ 00453 AlternateRequired = TRUE; 00454 continue; 00455 } 00456 else 00457 { 00458 /* Move on to the next preferred or required descriptor after this one */ 00459 AlternateRequired = FALSE; 00460 } 00461 00462 /* Figure out what we need */ 00463 if (PartialList == NULL) 00464 { 00465 /* We need a new list */ 00466 NewList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST)); 00467 if (!NewList) 00468 return STATUS_NO_MEMORY; 00469 00470 /* Set it up */ 00471 NewList->Count = 1; 00472 NewList->List[0].InterfaceType = RequirementsList->InterfaceType; 00473 NewList->List[0].BusNumber = RequirementsList->BusNumber; 00474 NewList->List[0].PartialResourceList.Version = 1; 00475 NewList->List[0].PartialResourceList.Revision = 1; 00476 NewList->List[0].PartialResourceList.Count = 1; 00477 00478 /* Set our pointer */ 00479 DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[0]; 00480 } 00481 else 00482 { 00483 /* Allocate the new larger list */ 00484 NewList = ExAllocatePool(PagedPool, PnpDetermineResourceListSize(*ResourceList) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 00485 if (!NewList) 00486 return STATUS_NO_MEMORY; 00487 00488 /* Copy the old stuff back */ 00489 RtlCopyMemory(NewList, *ResourceList, PnpDetermineResourceListSize(*ResourceList)); 00490 00491 /* Set our pointer */ 00492 DescPtr = &NewList->List[0].PartialResourceList.PartialDescriptors[NewList->List[0].PartialResourceList.Count]; 00493 00494 /* Increment the descriptor count */ 00495 NewList->List[0].PartialResourceList.Count++; 00496 00497 /* Free the old list */ 00498 ExFreePool(*ResourceList); 00499 } 00500 00501 /* Copy the descriptor in */ 00502 *DescPtr = NewDesc; 00503 00504 /* Store the new list */ 00505 *ResourceList = NewList; 00506 } 00507 } 00508 00509 /* Check if we need an alternate with no resources left */ 00510 if (AlternateRequired) 00511 { 00512 DPRINT1("Unable to satisfy preferred resource or alternates in list %d\n", i); 00513 00514 /* Try the next alternate list */ 00515 continue; 00516 } 00517 00518 /* We're done because we satisfied one of the alternate lists */ 00519 return STATUS_SUCCESS; 00520 } 00521 00522 /* We ran out of alternates */ 00523 DPRINT1("Out of alternate lists!\n"); 00524 00525 /* Free the list */ 00526 if (*ResourceList) 00527 { 00528 ExFreePool(*ResourceList); 00529 *ResourceList = NULL; 00530 } 00531 00532 /* Fail */ 00533 return STATUS_CONFLICTING_ADDRESSES; 00534 } 00535 00536 static 00537 BOOLEAN 00538 IopCheckResourceDescriptor( 00539 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc, 00540 IN PCM_RESOURCE_LIST ResourceList, 00541 IN BOOLEAN Silent, 00542 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) 00543 { 00544 ULONG i, ii; 00545 BOOLEAN Result = FALSE; 00546 00547 for (i = 0; i < ResourceList->Count; i++) 00548 { 00549 PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList; 00550 for (ii = 0; ii < ResList->Count; ii++) 00551 { 00552 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii]; 00553 00554 /* We don't care about shared resources */ 00555 if (ResDesc->ShareDisposition == CmResourceShareShared && 00556 ResDesc2->ShareDisposition == CmResourceShareShared) 00557 continue; 00558 00559 /* Make sure we're comparing the same types */ 00560 if (ResDesc->Type != ResDesc2->Type) 00561 continue; 00562 00563 switch (ResDesc->Type) 00564 { 00565 case CmResourceTypeMemory: 00566 if ((ResDesc->u.Memory.Start.QuadPart < ResDesc2->u.Memory.Start.QuadPart && 00567 ResDesc->u.Memory.Start.QuadPart + ResDesc->u.Memory.Length > 00568 ResDesc2->u.Memory.Start.QuadPart) || (ResDesc2->u.Memory.Start.QuadPart < 00569 ResDesc->u.Memory.Start.QuadPart && ResDesc2->u.Memory.Start.QuadPart + 00570 ResDesc2->u.Memory.Length > ResDesc->u.Memory.Start.QuadPart)) 00571 { 00572 if (!Silent) 00573 { 00574 DPRINT1("Resource conflict: Memory (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n", 00575 ResDesc->u.Memory.Start.QuadPart, ResDesc->u.Memory.Start.QuadPart + 00576 ResDesc->u.Memory.Length, ResDesc2->u.Memory.Start.QuadPart, 00577 ResDesc2->u.Memory.Start.QuadPart + ResDesc2->u.Memory.Length); 00578 } 00579 00580 Result = TRUE; 00581 00582 goto ByeBye; 00583 } 00584 break; 00585 00586 case CmResourceTypePort: 00587 if ((ResDesc->u.Port.Start.QuadPart < ResDesc2->u.Port.Start.QuadPart && 00588 ResDesc->u.Port.Start.QuadPart + ResDesc->u.Port.Length > 00589 ResDesc2->u.Port.Start.QuadPart) || (ResDesc2->u.Port.Start.QuadPart < 00590 ResDesc->u.Port.Start.QuadPart && ResDesc2->u.Port.Start.QuadPart + 00591 ResDesc2->u.Port.Length > ResDesc->u.Port.Start.QuadPart)) 00592 { 00593 if (!Silent) 00594 { 00595 DPRINT1("Resource conflict: Port (0x%I64x to 0x%I64x vs. 0x%I64x to 0x%I64x)\n", 00596 ResDesc->u.Port.Start.QuadPart, ResDesc->u.Port.Start.QuadPart + 00597 ResDesc->u.Port.Length, ResDesc2->u.Port.Start.QuadPart, 00598 ResDesc2->u.Port.Start.QuadPart + ResDesc2->u.Port.Length); 00599 } 00600 00601 Result = TRUE; 00602 00603 goto ByeBye; 00604 } 00605 break; 00606 00607 case CmResourceTypeInterrupt: 00608 if (ResDesc->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector) 00609 { 00610 if (!Silent) 00611 { 00612 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n", 00613 ResDesc->u.Interrupt.Vector, ResDesc->u.Interrupt.Level, 00614 ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level); 00615 } 00616 00617 Result = TRUE; 00618 00619 goto ByeBye; 00620 } 00621 break; 00622 00623 case CmResourceTypeBusNumber: 00624 if ((ResDesc->u.BusNumber.Start < ResDesc2->u.BusNumber.Start && 00625 ResDesc->u.BusNumber.Start + ResDesc->u.BusNumber.Length > 00626 ResDesc2->u.BusNumber.Start) || (ResDesc2->u.BusNumber.Start < 00627 ResDesc->u.BusNumber.Start && ResDesc2->u.BusNumber.Start + 00628 ResDesc2->u.BusNumber.Length > ResDesc->u.BusNumber.Start)) 00629 { 00630 if (!Silent) 00631 { 00632 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n", 00633 ResDesc->u.BusNumber.Start, ResDesc->u.BusNumber.Start + 00634 ResDesc->u.BusNumber.Length, ResDesc2->u.BusNumber.Start, 00635 ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length); 00636 } 00637 00638 Result = TRUE; 00639 00640 goto ByeBye; 00641 } 00642 break; 00643 00644 case CmResourceTypeDma: 00645 if (ResDesc->u.Dma.Channel == ResDesc2->u.Dma.Channel) 00646 { 00647 if (!Silent) 00648 { 00649 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n", 00650 ResDesc->u.Dma.Channel, ResDesc->u.Dma.Port, 00651 ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port); 00652 } 00653 00654 Result = TRUE; 00655 00656 goto ByeBye; 00657 } 00658 break; 00659 } 00660 } 00661 } 00662 00663 ByeBye: 00664 00665 if (Result && ConflictingDescriptor) 00666 { 00667 RtlCopyMemory(ConflictingDescriptor, 00668 ResDesc, 00669 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 00670 } 00671 00672 return Result; 00673 } 00674 00675 static 00676 NTSTATUS 00677 IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode) 00678 { 00679 UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); 00680 UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); 00681 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"AllocConfig"); 00682 HANDLE EnumKey, InstanceKey, ControlKey; 00683 NTSTATUS Status; 00684 OBJECT_ATTRIBUTES ObjectAttributes; 00685 00686 /* Open the Enum key */ 00687 Status = IopOpenRegistryKeyEx(&EnumKey, NULL, &EnumRoot, KEY_ENUMERATE_SUB_KEYS); 00688 if (!NT_SUCCESS(Status)) 00689 return Status; 00690 00691 /* Open the instance key (eg. Root\PNP0A03) */ 00692 Status = IopOpenRegistryKeyEx(&InstanceKey, EnumKey, &DeviceNode->InstancePath, KEY_ENUMERATE_SUB_KEYS); 00693 ZwClose(EnumKey); 00694 00695 if (!NT_SUCCESS(Status)) 00696 return Status; 00697 00698 /* Create/Open the Control key */ 00699 InitializeObjectAttributes(&ObjectAttributes, 00700 &Control, 00701 OBJ_CASE_INSENSITIVE, 00702 InstanceKey, 00703 NULL); 00704 Status = ZwCreateKey(&ControlKey, 00705 KEY_SET_VALUE, 00706 &ObjectAttributes, 00707 0, 00708 NULL, 00709 REG_OPTION_VOLATILE, 00710 NULL); 00711 ZwClose(InstanceKey); 00712 00713 if (!NT_SUCCESS(Status)) 00714 return Status; 00715 00716 /* Write the resource list */ 00717 Status = ZwSetValueKey(ControlKey, 00718 &ValueName, 00719 0, 00720 REG_RESOURCE_LIST, 00721 DeviceNode->ResourceList, 00722 PnpDetermineResourceListSize(DeviceNode->ResourceList)); 00723 ZwClose(ControlKey); 00724 00725 if (!NT_SUCCESS(Status)) 00726 return Status; 00727 00728 return STATUS_SUCCESS; 00729 } 00730 00731 static 00732 NTSTATUS 00733 IopFilterResourceRequirements(IN PDEVICE_NODE DeviceNode) 00734 { 00735 IO_STACK_LOCATION Stack; 00736 IO_STATUS_BLOCK IoStatusBlock; 00737 NTSTATUS Status; 00738 00739 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n"); 00740 00741 Stack.Parameters.FilterResourceRequirements.IoResourceRequirementList = DeviceNode->ResourceRequirements; 00742 Status = IopInitiatePnpIrp( 00743 DeviceNode->PhysicalDeviceObject, 00744 &IoStatusBlock, 00745 IRP_MN_FILTER_RESOURCE_REQUIREMENTS, 00746 &Stack); 00747 if (!NT_SUCCESS(Status) && Status != STATUS_NOT_SUPPORTED) 00748 { 00749 DPRINT1("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n"); 00750 return Status; 00751 } 00752 else if (NT_SUCCESS(Status) && IoStatusBlock.Information) 00753 { 00754 DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information; 00755 } 00756 00757 return STATUS_SUCCESS; 00758 } 00759 00760 00761 NTSTATUS 00762 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key) 00763 { 00764 NTSTATUS Status; 00765 ULONG Disposition; 00766 HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey; 00767 UNICODE_STRING KeyName; 00768 OBJECT_ATTRIBUTES ObjectAttributes; 00769 00770 RtlInitUnicodeString(&KeyName, 00771 L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); 00772 InitializeObjectAttributes(&ObjectAttributes, 00773 &KeyName, 00774 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 00775 0, 00776 NULL); 00777 Status = ZwCreateKey(&ResourceMapKey, 00778 KEY_ALL_ACCESS, 00779 &ObjectAttributes, 00780 0, 00781 NULL, 00782 REG_OPTION_VOLATILE, 00783 &Disposition); 00784 if (!NT_SUCCESS(Status)) 00785 return Status; 00786 00787 RtlInitUnicodeString(&KeyName, Level1Key); 00788 InitializeObjectAttributes(&ObjectAttributes, 00789 &KeyName, 00790 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 00791 ResourceMapKey, 00792 NULL); 00793 Status = ZwCreateKey(&PnpMgrLevel1, 00794 KEY_ALL_ACCESS, 00795 &ObjectAttributes, 00796 0, 00797 NULL, 00798 REG_OPTION_VOLATILE, 00799 &Disposition); 00800 ZwClose(ResourceMapKey); 00801 if (!NT_SUCCESS(Status)) 00802 return Status; 00803 00804 RtlInitUnicodeString(&KeyName, Level2Key); 00805 InitializeObjectAttributes(&ObjectAttributes, 00806 &KeyName, 00807 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 00808 PnpMgrLevel1, 00809 NULL); 00810 Status = ZwCreateKey(&PnpMgrLevel2, 00811 KEY_ALL_ACCESS, 00812 &ObjectAttributes, 00813 0, 00814 NULL, 00815 REG_OPTION_VOLATILE, 00816 &Disposition); 00817 ZwClose(PnpMgrLevel1); 00818 if (!NT_SUCCESS(Status)) 00819 return Status; 00820 00821 if (DeviceNode->ResourceList) 00822 { 00823 UNICODE_STRING NameU; 00824 UNICODE_STRING RawSuffix, TranslatedSuffix; 00825 ULONG OldLength = 0; 00826 00827 ASSERT(DeviceNode->ResourceListTranslated); 00828 00829 RtlInitUnicodeString(&TranslatedSuffix, L".Translated"); 00830 RtlInitUnicodeString(&RawSuffix, L".Raw"); 00831 00832 Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject, 00833 DevicePropertyPhysicalDeviceObjectName, 00834 0, 00835 NULL, 00836 &OldLength); 00837 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 00838 { 00839 ASSERT(OldLength); 00840 00841 NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length); 00842 if (!NameU.Buffer) 00843 { 00844 ZwClose(PnpMgrLevel2); 00845 return STATUS_INSUFFICIENT_RESOURCES; 00846 } 00847 00848 NameU.Length = 0; 00849 NameU.MaximumLength = (USHORT)OldLength + TranslatedSuffix.Length; 00850 00851 Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject, 00852 DevicePropertyPhysicalDeviceObjectName, 00853 NameU.MaximumLength, 00854 NameU.Buffer, 00855 &OldLength); 00856 if (!NT_SUCCESS(Status)) 00857 { 00858 ZwClose(PnpMgrLevel2); 00859 ExFreePool(NameU.Buffer); 00860 return Status; 00861 } 00862 } 00863 else if (!NT_SUCCESS(Status)) 00864 { 00865 /* Some failure */ 00866 ZwClose(PnpMgrLevel2); 00867 return Status; 00868 } 00869 else 00870 { 00871 /* This should never happen */ 00872 ASSERT(FALSE); 00873 } 00874 00875 NameU.Length = (USHORT)OldLength; 00876 00877 RtlAppendUnicodeStringToString(&NameU, &RawSuffix); 00878 00879 Status = ZwSetValueKey(PnpMgrLevel2, 00880 &NameU, 00881 0, 00882 REG_RESOURCE_LIST, 00883 DeviceNode->ResourceList, 00884 PnpDetermineResourceListSize(DeviceNode->ResourceList)); 00885 if (!NT_SUCCESS(Status)) 00886 { 00887 ZwClose(PnpMgrLevel2); 00888 ExFreePool(NameU.Buffer); 00889 return Status; 00890 } 00891 00892 /* "Remove" the suffix by setting the length back to what it used to be */ 00893 NameU.Length = (USHORT)OldLength; 00894 00895 RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix); 00896 00897 Status = ZwSetValueKey(PnpMgrLevel2, 00898 &NameU, 00899 0, 00900 REG_RESOURCE_LIST, 00901 DeviceNode->ResourceListTranslated, 00902 PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated)); 00903 ZwClose(PnpMgrLevel2); 00904 ExFreePool(NameU.Buffer); 00905 00906 if (!NT_SUCCESS(Status)) 00907 return Status; 00908 } 00909 else 00910 { 00911 ZwClose(PnpMgrLevel2); 00912 } 00913 00914 return STATUS_SUCCESS; 00915 } 00916 00917 NTSTATUS 00918 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode) 00919 { 00920 return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager"); 00921 } 00922 00923 static 00924 NTSTATUS 00925 IopTranslateDeviceResources( 00926 IN PDEVICE_NODE DeviceNode) 00927 { 00928 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; 00929 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; 00930 ULONG i, j, ListSize; 00931 NTSTATUS Status; 00932 00933 if (!DeviceNode->ResourceList) 00934 { 00935 DeviceNode->ResourceListTranslated = NULL; 00936 return STATUS_SUCCESS; 00937 } 00938 00939 /* That's easy to translate a resource list. Just copy the 00940 * untranslated one and change few fields in the copy 00941 */ 00942 ListSize = PnpDetermineResourceListSize(DeviceNode->ResourceList); 00943 00944 DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize); 00945 if (!DeviceNode->ResourceListTranslated) 00946 { 00947 Status = STATUS_NO_MEMORY; 00948 goto cleanup; 00949 } 00950 RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize); 00951 00952 for (i = 0; i < DeviceNode->ResourceList->Count; i++) 00953 { 00954 pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList; 00955 for (j = 0; j < pPartialResourceList->Count; j++) 00956 { 00957 DescriptorRaw = &pPartialResourceList->PartialDescriptors[j]; 00958 DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j]; 00959 switch (DescriptorRaw->Type) 00960 { 00961 case CmResourceTypePort: 00962 { 00963 ULONG AddressSpace = 1; /* IO space */ 00964 if (!HalTranslateBusAddress( 00965 DeviceNode->ResourceList->List[i].InterfaceType, 00966 DeviceNode->ResourceList->List[i].BusNumber, 00967 DescriptorRaw->u.Port.Start, 00968 &AddressSpace, 00969 &DescriptorTranslated->u.Port.Start)) 00970 { 00971 Status = STATUS_UNSUCCESSFUL; 00972 DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart); 00973 goto cleanup; 00974 } 00975 00976 if (AddressSpace == 0) 00977 { 00978 DPRINT1("Guessed incorrect address space: 1 -> 0\n"); 00979 00980 /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are 00981 * invalid for this state but I'm not 100% sure */ 00982 DescriptorRaw->Flags = 00983 DescriptorTranslated->Flags = CM_RESOURCE_PORT_MEMORY; 00984 } 00985 break; 00986 } 00987 case CmResourceTypeInterrupt: 00988 { 00989 DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( 00990 DeviceNode->ResourceList->List[i].InterfaceType, 00991 DeviceNode->ResourceList->List[i].BusNumber, 00992 DescriptorRaw->u.Interrupt.Level, 00993 DescriptorRaw->u.Interrupt.Vector, 00994 (PKIRQL)&DescriptorTranslated->u.Interrupt.Level, 00995 &DescriptorTranslated->u.Interrupt.Affinity); 00996 00997 if (!DescriptorTranslated->u.Interrupt.Vector) 00998 { 00999 Status = STATUS_UNSUCCESSFUL; 01000 DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector, 01001 DescriptorRaw->u.Interrupt.Level); 01002 goto cleanup; 01003 } 01004 break; 01005 } 01006 case CmResourceTypeMemory: 01007 { 01008 ULONG AddressSpace = 0; /* Memory space */ 01009 if (!HalTranslateBusAddress( 01010 DeviceNode->ResourceList->List[i].InterfaceType, 01011 DeviceNode->ResourceList->List[i].BusNumber, 01012 DescriptorRaw->u.Memory.Start, 01013 &AddressSpace, 01014 &DescriptorTranslated->u.Memory.Start)) 01015 { 01016 Status = STATUS_UNSUCCESSFUL; 01017 DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart); 01018 goto cleanup; 01019 } 01020 01021 if (AddressSpace != 0) 01022 { 01023 DPRINT1("Guessed incorrect address space: 0 -> 1\n"); 01024 01025 /* This should never happen for memory space */ 01026 ASSERT(FALSE); 01027 } 01028 } 01029 01030 case CmResourceTypeDma: 01031 case CmResourceTypeBusNumber: 01032 case CmResourceTypeDeviceSpecific: 01033 /* Nothing to do */ 01034 break; 01035 default: 01036 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type); 01037 Status = STATUS_NOT_IMPLEMENTED; 01038 goto cleanup; 01039 } 01040 } 01041 } 01042 return STATUS_SUCCESS; 01043 01044 cleanup: 01045 /* Yes! Also delete ResourceList because ResourceList and 01046 * ResourceListTranslated should be a pair! */ 01047 ExFreePool(DeviceNode->ResourceList); 01048 DeviceNode->ResourceList = NULL; 01049 if (DeviceNode->ResourceListTranslated) 01050 { 01051 ExFreePool(DeviceNode->ResourceListTranslated); 01052 DeviceNode->ResourceList = NULL; 01053 } 01054 return Status; 01055 } 01056 01057 NTSTATUS 01058 NTAPI 01059 IopAssignDeviceResources( 01060 IN PDEVICE_NODE DeviceNode) 01061 { 01062 NTSTATUS Status; 01063 ULONG ListSize; 01064 01065 IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); 01066 01067 Status = IopFilterResourceRequirements(DeviceNode); 01068 if (!NT_SUCCESS(Status)) 01069 goto ByeBye; 01070 01071 if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements) 01072 { 01073 DeviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED; 01074 DeviceNode->Flags &= ~DNF_ASSIGNING_RESOURCES; 01075 01076 /* No resource needed for this device */ 01077 DeviceNode->ResourceList = NULL; 01078 DeviceNode->ResourceListTranslated = NULL; 01079 01080 return STATUS_SUCCESS; 01081 } 01082 01083 if (DeviceNode->BootResources) 01084 { 01085 ListSize = PnpDetermineResourceListSize(DeviceNode->BootResources); 01086 01087 DeviceNode->ResourceList = ExAllocatePool(PagedPool, ListSize); 01088 if (!DeviceNode->ResourceList) 01089 { 01090 Status = STATUS_NO_MEMORY; 01091 goto ByeBye; 01092 } 01093 01094 RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, ListSize); 01095 01096 Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL); 01097 if (!NT_SUCCESS(Status)) 01098 { 01099 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath); 01100 ExFreePool(DeviceNode->ResourceList); 01101 DeviceNode->ResourceList = NULL; 01102 } 01103 } 01104 else 01105 { 01106 /* We'll make this from the requirements */ 01107 DeviceNode->ResourceList = NULL; 01108 } 01109 01110 /* No resources requirements */ 01111 if (!DeviceNode->ResourceRequirements) 01112 goto Finish; 01113 01114 /* Call HAL to fixup our resource requirements list */ 01115 HalAdjustResourceList(&DeviceNode->ResourceRequirements); 01116 01117 /* Add resource requirements that aren't in the list we already got */ 01118 Status = IopFixupResourceListWithRequirements(DeviceNode->ResourceRequirements, 01119 &DeviceNode->ResourceList); 01120 if (!NT_SUCCESS(Status)) 01121 { 01122 DPRINT1("Failed to fixup a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath); 01123 DeviceNode->Problem = CM_PROB_NORMAL_CONFLICT; 01124 goto ByeBye; 01125 } 01126 01127 /* IopFixupResourceListWithRequirements should NEVER give us a conflicting list */ 01128 ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES); 01129 01130 Finish: 01131 Status = IopTranslateDeviceResources(DeviceNode); 01132 if (!NT_SUCCESS(Status)) 01133 { 01134 DeviceNode->Problem = CM_PROB_TRANSLATION_FAILED; 01135 DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath); 01136 goto ByeBye; 01137 } 01138 01139 Status = IopUpdateResourceMapForPnPDevice(DeviceNode); 01140 if (!NT_SUCCESS(Status)) 01141 goto ByeBye; 01142 01143 Status = IopUpdateControlKeyWithResources(DeviceNode); 01144 if (!NT_SUCCESS(Status)) 01145 goto ByeBye; 01146 01147 IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED); 01148 01149 IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); 01150 01151 return STATUS_SUCCESS; 01152 01153 ByeBye: 01154 if (DeviceNode->ResourceList) 01155 { 01156 ExFreePool(DeviceNode->ResourceList); 01157 DeviceNode->ResourceList = NULL; 01158 } 01159 01160 DeviceNode->ResourceListTranslated = NULL; 01161 01162 IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); 01163 01164 return Status; 01165 } 01166 01167 static 01168 BOOLEAN 01169 IopCheckForResourceConflict( 01170 IN PCM_RESOURCE_LIST ResourceList1, 01171 IN PCM_RESOURCE_LIST ResourceList2, 01172 IN BOOLEAN Silent, 01173 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) 01174 { 01175 ULONG i, ii; 01176 BOOLEAN Result = FALSE; 01177 01178 for (i = 0; i < ResourceList1->Count; i++) 01179 { 01180 PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList1->List[i].PartialResourceList; 01181 for (ii = 0; ii < ResList->Count; ii++) 01182 { 01183 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = &ResList->PartialDescriptors[ii]; 01184 01185 Result = IopCheckResourceDescriptor(ResDesc, 01186 ResourceList2, 01187 Silent, 01188 ConflictingDescriptor); 01189 if (Result) goto ByeBye; 01190 } 01191 } 01192 01193 ByeBye: 01194 01195 return Result; 01196 } 01197 01198 NTSTATUS NTAPI 01199 IopDetectResourceConflict( 01200 IN PCM_RESOURCE_LIST ResourceList, 01201 IN BOOLEAN Silent, 01202 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) 01203 { 01204 OBJECT_ATTRIBUTES ObjectAttributes; 01205 UNICODE_STRING KeyName; 01206 HANDLE ResourceMapKey = INVALID_HANDLE_VALUE, ChildKey2 = INVALID_HANDLE_VALUE, ChildKey3 = INVALID_HANDLE_VALUE; 01207 ULONG KeyInformationLength, RequiredLength, KeyValueInformationLength, KeyNameInformationLength; 01208 PKEY_BASIC_INFORMATION KeyInformation; 01209 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; 01210 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation; 01211 ULONG ChildKeyIndex1 = 0, ChildKeyIndex2 = 0, ChildKeyIndex3 = 0; 01212 NTSTATUS Status; 01213 01214 RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); 01215 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, 0, NULL); 01216 Status = ZwOpenKey(&ResourceMapKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes); 01217 if (!NT_SUCCESS(Status)) 01218 { 01219 /* The key is missing which means we are the first device */ 01220 return STATUS_SUCCESS; 01221 } 01222 01223 while (TRUE) 01224 { 01225 Status = ZwEnumerateKey(ResourceMapKey, 01226 ChildKeyIndex1, 01227 KeyBasicInformation, 01228 NULL, 01229 0, 01230 &RequiredLength); 01231 if (Status == STATUS_NO_MORE_ENTRIES) 01232 break; 01233 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 01234 { 01235 KeyInformationLength = RequiredLength; 01236 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength); 01237 if (!KeyInformation) 01238 { 01239 Status = STATUS_INSUFFICIENT_RESOURCES; 01240 goto cleanup; 01241 } 01242 01243 Status = ZwEnumerateKey(ResourceMapKey, 01244 ChildKeyIndex1, 01245 KeyBasicInformation, 01246 KeyInformation, 01247 KeyInformationLength, 01248 &RequiredLength); 01249 } 01250 else 01251 goto cleanup; 01252 ChildKeyIndex1++; 01253 if (!NT_SUCCESS(Status)) 01254 goto cleanup; 01255 01256 KeyName.Buffer = KeyInformation->Name; 01257 KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength; 01258 InitializeObjectAttributes(&ObjectAttributes, 01259 &KeyName, 01260 OBJ_CASE_INSENSITIVE, 01261 ResourceMapKey, 01262 NULL); 01263 Status = ZwOpenKey(&ChildKey2, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes); 01264 ExFreePool(KeyInformation); 01265 if (!NT_SUCCESS(Status)) 01266 goto cleanup; 01267 01268 while (TRUE) 01269 { 01270 Status = ZwEnumerateKey(ChildKey2, 01271 ChildKeyIndex2, 01272 KeyBasicInformation, 01273 NULL, 01274 0, 01275 &RequiredLength); 01276 if (Status == STATUS_NO_MORE_ENTRIES) 01277 break; 01278 else if (Status == STATUS_BUFFER_TOO_SMALL) 01279 { 01280 KeyInformationLength = RequiredLength; 01281 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength); 01282 if (!KeyInformation) 01283 { 01284 Status = STATUS_INSUFFICIENT_RESOURCES; 01285 goto cleanup; 01286 } 01287 01288 Status = ZwEnumerateKey(ChildKey2, 01289 ChildKeyIndex2, 01290 KeyBasicInformation, 01291 KeyInformation, 01292 KeyInformationLength, 01293 &RequiredLength); 01294 } 01295 else 01296 goto cleanup; 01297 ChildKeyIndex2++; 01298 if (!NT_SUCCESS(Status)) 01299 goto cleanup; 01300 01301 KeyName.Buffer = KeyInformation->Name; 01302 KeyName.MaximumLength = KeyName.Length = (USHORT)KeyInformation->NameLength; 01303 InitializeObjectAttributes(&ObjectAttributes, 01304 &KeyName, 01305 OBJ_CASE_INSENSITIVE, 01306 ChildKey2, 01307 NULL); 01308 Status = ZwOpenKey(&ChildKey3, KEY_QUERY_VALUE, &ObjectAttributes); 01309 ExFreePool(KeyInformation); 01310 if (!NT_SUCCESS(Status)) 01311 goto cleanup; 01312 01313 while (TRUE) 01314 { 01315 Status = ZwEnumerateValueKey(ChildKey3, 01316 ChildKeyIndex3, 01317 KeyValuePartialInformation, 01318 NULL, 01319 0, 01320 &RequiredLength); 01321 if (Status == STATUS_NO_MORE_ENTRIES) 01322 break; 01323 else if (Status == STATUS_BUFFER_TOO_SMALL) 01324 { 01325 KeyValueInformationLength = RequiredLength; 01326 KeyValueInformation = ExAllocatePool(PagedPool, KeyValueInformationLength); 01327 if (!KeyValueInformation) 01328 { 01329 Status = STATUS_INSUFFICIENT_RESOURCES; 01330 goto cleanup; 01331 } 01332 01333 Status = ZwEnumerateValueKey(ChildKey3, 01334 ChildKeyIndex3, 01335 KeyValuePartialInformation, 01336 KeyValueInformation, 01337 KeyValueInformationLength, 01338 &RequiredLength); 01339 } 01340 else 01341 goto cleanup; 01342 if (!NT_SUCCESS(Status)) 01343 goto cleanup; 01344 01345 Status = ZwEnumerateValueKey(ChildKey3, 01346 ChildKeyIndex3, 01347 KeyValueBasicInformation, 01348 NULL, 01349 0, 01350 &RequiredLength); 01351 if (Status == STATUS_BUFFER_TOO_SMALL) 01352 { 01353 KeyNameInformationLength = RequiredLength; 01354 KeyNameInformation = ExAllocatePool(PagedPool, KeyNameInformationLength + sizeof(WCHAR)); 01355 if (!KeyNameInformation) 01356 { 01357 Status = STATUS_INSUFFICIENT_RESOURCES; 01358 goto cleanup; 01359 } 01360 01361 Status = ZwEnumerateValueKey(ChildKey3, 01362 ChildKeyIndex3, 01363 KeyValueBasicInformation, 01364 KeyNameInformation, 01365 KeyNameInformationLength, 01366 &RequiredLength); 01367 } 01368 else 01369 goto cleanup; 01370 01371 ChildKeyIndex3++; 01372 01373 if (!NT_SUCCESS(Status)) 01374 goto cleanup; 01375 01376 KeyNameInformation->Name[KeyNameInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL; 01377 01378 /* Skip translated entries */ 01379 if (wcsstr(KeyNameInformation->Name, L".Translated")) 01380 { 01381 ExFreePool(KeyNameInformation); 01382 continue; 01383 } 01384 01385 ExFreePool(KeyNameInformation); 01386 01387 if (IopCheckForResourceConflict(ResourceList, 01388 (PCM_RESOURCE_LIST)KeyValueInformation->Data, 01389 Silent, 01390 ConflictingDescriptor)) 01391 { 01392 ExFreePool(KeyValueInformation); 01393 Status = STATUS_CONFLICTING_ADDRESSES; 01394 goto cleanup; 01395 } 01396 01397 ExFreePool(KeyValueInformation); 01398 } 01399 } 01400 } 01401 01402 cleanup: 01403 if (ResourceMapKey != INVALID_HANDLE_VALUE) 01404 ZwClose(ResourceMapKey); 01405 if (ChildKey2 != INVALID_HANDLE_VALUE) 01406 ZwClose(ChildKey2); 01407 if (ChildKey3 != INVALID_HANDLE_VALUE) 01408 ZwClose(ChildKey3); 01409 01410 if (Status == STATUS_NO_MORE_ENTRIES) 01411 Status = STATUS_SUCCESS; 01412 01413 return Status; 01414 } 01415 Generated on Sun May 27 2012 04:37:18 for ReactOS by
1.7.6.1
|