ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pnpres.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.