Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

pnprlist.c File Reference

#include "iop.h"

Go to the source code of this file.

Defines

#define RELATION_FLAGS   0x00000003
#define RELATION_FLAG_TAGGED   0x00000001
#define RELATION_FLAG_DESCENDANT   0x00000002

Functions

NTSTATUS IopAddRelationToList (IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DirectDescendant, IN BOOLEAN Tagged)
PRELATION_LIST IopAllocateRelationList (VOID)
NTSTATUS IopCompressRelationList (IN OUT PRELATION_LIST *List)
BOOLEAN IopEnumerateRelations (IN PRELATION_LIST List, IN OUT PULONG Marker, OUT PDEVICE_OBJECT *DeviceObject, OUT BOOLEAN *DirectDescendant, OPTIONAL OUT BOOLEAN *Tagged, OPTIONAL IN BOOLEAN Reverse)
VOID IopFreeRelationList (IN PRELATION_LIST List)
ULONG IopGetRelationsCount (PRELATION_LIST List)
ULONG IopGetRelationsTaggedCount (PRELATION_LIST List)
BOOLEAN IopIsRelationInList (PRELATION_LIST List, PDEVICE_OBJECT DeviceObject)
NTSTATUS IopMergeRelationLists (IN OUT PRELATION_LIST TargetList, IN PRELATION_LIST SourceList, IN BOOLEAN Tagged)
NTSTATUS IopRemoveIndirectRelationsFromList (IN PRELATION_LIST List)
NTSTATUS IopRemoveRelationFromList (PRELATION_LIST List, PDEVICE_OBJECT DeviceObject)
VOID IopSetAllRelationsTags (PRELATION_LIST List, BOOLEAN Tagged)
NTSTATUS IopSetRelationsTag (IN PRELATION_LIST List, IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Tagged)


Define Documentation

#define RELATION_FLAG_DESCENDANT   0x00000002
 

Definition at line 52 of file pnprlist.c.

Referenced by IopAddRelationToList(), IopEnumerateRelations(), and IopRemoveIndirectRelationsFromList().

#define RELATION_FLAG_TAGGED   0x00000001
 

Definition at line 51 of file pnprlist.c.

Referenced by IopAddRelationToList(), IopEnumerateRelations(), IopRemoveIndirectRelationsFromList(), IopRemoveRelationFromList(), IopSetAllRelationsTags(), and IopSetRelationsTag().

#define RELATION_FLAGS   0x00000003
 

Definition at line 49 of file pnprlist.c.

Referenced by IopAddRelationToList(), IopEnumerateRelations(), IopFreeRelationList(), IopIsRelationInList(), IopMergeRelationLists(), IopRemoveIndirectRelationsFromList(), IopRemoveRelationFromList(), and IopSetRelationsTag().


Function Documentation

NTSTATUS IopAddRelationToList IN PRELATION_LIST  List,
IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  DirectDescendant,
IN BOOLEAN  Tagged
 

Definition at line 55 of file pnprlist.c.

References ASSERT, _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, ExAllocatePool, IopNumberDeviceNodes, _DEVICE_NODE::Level, List, _RELATION_LIST_ENTRY::MaxCount, NULL, ObReferenceObject, PAGED_CODE, PagedPool, PRELATION_LIST_ENTRY, RELATION_FLAG_DESCENDANT, RELATION_FLAG_TAGGED, RELATION_FLAGS, and RELATION_LIST_ENTRY.

Referenced by IopInvalidateRelationsInList(), IopMergeRelationLists(), and IopProcessRelation().

00064 : 00065 00066 Adds an element to a relation list. 00067 00068 If this is the first DeviceObject of a particular level then a new 00069 RELATION_LIST_ENTRY will be allocated. 00070 00071 This routine should only be called on an uncompressed relation list, 00072 otherwise it is likely that STATUS_INVALID_PARAMETER will be returned. 00073 00074 Arguments: 00075 00076 List Relation list to which the DeviceObject is added. 00077 00078 DeviceObject DeviceObject to be added to List. It must be a 00079 PhysicalDeviceObject (PDO). 00080 00081 DirectDescendant Indicates whether DeviceObject is a direct descendant of 00082 the original target device of this remove. 00083 00084 Tagged Indicates whether DeviceObject should be tagged in List. 00085 00086 Return Value: 00087 00088 STATUS_SUCCESS 00089 00090 The DeviceObject was added successfully. 00091 00092 STATUS_OBJECT_NAME_COLLISION 00093 00094 The DeviceObject already exists in the relation list. 00095 00096 STATUS_INSUFFICIENT_RESOURCES 00097 00098 There isn't enough PagedPool available to allocate a new 00099 RELATION_LIST_ENTRY. 00100 00101 STATUS_INVALID_PARAMETER 00102 00103 The level of the DEVICE_NODE associated with DeviceObject is less than 00104 FirstLevel or greater than the MaxLevel. 00105 00106 STATUS_NO_SUCH_DEVICE 00107 00108 DeviceObject is not a PhysicalDeviceObject (PDO), it doesn't have a 00109 DEVICE_NODE associated with it. 00110 00111 --*/ 00112 00113 { 00114 PDEVICE_NODE deviceNode; 00115 PRELATION_LIST_ENTRY entry; 00116 ULONG level; 00117 ULONG index; 00118 ULONG flags; 00119 00120 PAGED_CODE(); 00121 00122 flags = 0; 00123 00124 if (Tagged) { 00125 Tagged = 1; 00126 flags |= RELATION_FLAG_TAGGED; 00127 } 00128 00129 if (DirectDescendant) { 00130 flags |= RELATION_FLAG_DESCENDANT; 00131 } 00132 00133 if ((deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode) != NULL) { 00134 level = deviceNode->Level; 00135 00136 // 00137 // Since this routine is called with the DeviceNode Tree locked and 00138 // List is initially allocated with enough entries to hold the deepest 00139 // DEVICE_NODE this ASSERT should never fire. If it does then either 00140 // the tree is changing or we were given a compressed list. 00141 // 00142 ASSERT(List->FirstLevel <= level && level <= List->MaxLevel); 00143 00144 if (List->FirstLevel <= level && level <= List->MaxLevel) { 00145 00146 if ((entry = List->Entries[ level - List->FirstLevel ]) == NULL) { 00147 00148 // 00149 // This is the first DeviceObject of its level, allocate a new 00150 // RELATION_LIST_ENTRY. 00151 // 00152 entry = ExAllocatePool( PagedPool, 00153 sizeof(RELATION_LIST_ENTRY) + 00154 IopNumberDeviceNodes * sizeof(PDEVICE_OBJECT)); 00155 00156 if (entry == NULL) { 00157 return STATUS_INSUFFICIENT_RESOURCES; 00158 } 00159 00160 // 00161 // We always allocate enough Devices to hold the whole tree as 00162 // a simplification. Since each entry is a PDEVICE_OBJECT and 00163 // there is generally under 50 devices on a machine this means 00164 // under 1K for each entry. The excess space will be freed when 00165 // the list is compressed. 00166 // 00167 entry->Count = 0; 00168 entry->MaxCount = IopNumberDeviceNodes; 00169 00170 List->Entries[ level - List->FirstLevel ] = entry; 00171 } 00172 00173 // 00174 // There should always be room for a DeviceObject since the Entry is 00175 // initially dimensioned large enough to hold all the DEVICE_NODES 00176 // in the system. 00177 // 00178 ASSERT(entry->Count < entry->MaxCount); 00179 00180 if (entry->Count < entry->MaxCount) { 00181 // 00182 // Search the list to see if DeviceObject has already been 00183 // added. 00184 // 00185 for (index = 0; index < entry->Count; index++) { 00186 if (((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAGS) == (ULONG_PTR)DeviceObject) { 00187 00188 // 00189 // DeviceObject already exists in the list. However 00190 // the Direct Descendant flag may differ. We will 00191 // override it if DirectDescendant is TRUE. This could 00192 // happen if we merged two relation lists. 00193 00194 if (DirectDescendant) { 00195 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] | RELATION_FLAG_DESCENDANT); 00196 } 00197 00198 return STATUS_OBJECT_NAME_COLLISION; 00199 } 00200 } 00201 } else { 00202 // 00203 // There isn't room in the Entry for another DEVICE_OBJECT, the 00204 // list has probably already been compressed. 00205 // 00206 return STATUS_INVALID_PARAMETER; 00207 } 00208 00209 // 00210 // Take out a reference on DeviceObject, we will release it when we 00211 // free the list or remove the DeviceObject from the list. 00212 // 00213 ObReferenceObject( DeviceObject ); 00214 00215 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)DeviceObject | flags); 00216 entry->Count++; 00217 00218 List->Count++; 00219 List->TagCount += Tagged; 00220 00221 return STATUS_SUCCESS; 00222 } else { 00223 // 00224 // There isn't an Entry available for the level of this 00225 // DEVICE_OBJECT, the list has probably already been compressed. 00226 // 00227 00228 return STATUS_INVALID_PARAMETER; 00229 } 00230 } else { 00231 // 00232 // DeviceObject is not a PhysicalDeviceObject (PDO). 00233 // 00234 return STATUS_NO_SUCH_DEVICE; 00235 } 00236 }

PRELATION_LIST IopAllocateRelationList VOID   ) 
 

Definition at line 239 of file pnprlist.c.

References ExAllocatePool, IopMaxDeviceNodeLevel, _RELATION_LIST::MaxLevel, NULL, PAGED_CODE, PagedPool, and RELATION_LIST.

Referenced by IopInvalidateRelationsInList(), and IopLockDeviceRemovalRelations().

00245 : 00246 00247 Allocate a new Relations List. The list is initially sized large enough to 00248 hold the deepest DEVICE_NODE encountered since the system started. 00249 00250 Arguments: 00251 00252 NONE 00253 00254 Return Value: 00255 00256 Newly allocated list if enough PagedPool is available, otherwise NULL. 00257 00258 --*/ 00259 00260 { 00261 PRELATION_LIST list; 00262 ULONG maxLevel; 00263 ULONG listSize; 00264 00265 PAGED_CODE(); 00266 00267 // 00268 // Level number of the deepest DEVICE_NODE allocated since the system 00269 // started. 00270 // 00271 maxLevel = IopMaxDeviceNodeLevel; 00272 listSize = sizeof(RELATION_LIST) + maxLevel * sizeof(PRELATION_LIST_ENTRY); 00273 00274 if ((list = ExAllocatePool( PagedPool, listSize )) != NULL) { 00275 RtlZeroMemory(list, listSize); 00276 // list->FirstLevel = 0; 00277 // list->Count = 0; 00278 // list->Tagged = 0; 00279 list->MaxLevel = maxLevel; 00280 } 00281 00282 return list; 00283 }

NTSTATUS IopCompressRelationList IN OUT PRELATION_LIST List  ) 
 

Definition at line 286 of file pnprlist.c.

References ASSERT, _RELATION_LIST_ENTRY::Count, _RELATION_LIST::Count, _RELATION_LIST_ENTRY::Devices, _RELATION_LIST::Entries, ExAllocatePool, ExFreePool(), _RELATION_LIST::FirstLevel, List, _RELATION_LIST_ENTRY::MaxCount, _RELATION_LIST::MaxLevel, NULL, PAGED_CODE, PagedPool, PDEVICE_OBJECT, PRELATION_LIST_ENTRY, and _RELATION_LIST::TagCount.

Referenced by IopLockDeviceRemovalRelations().

00292 : 00293 00294 Compresses the relation list by reallocating the list and all the entries so 00295 that they a just large enough to hold their current contents. 00296 00297 Once a list has been compressed IopAddRelationToList and 00298 IopMergeRelationLists targetting this list are both likely to fail. 00299 00300 Arguments: 00301 00302 List Relation List to compress. 00303 00304 Return Value: 00305 00306 STATUS_SUCCESS 00307 00308 The list was compressed. Although this routine does allocate memory and 00309 the allocation can fail, the routine itself will never fail. Since the 00310 memory we are allocating is always smaller then the memory it is 00311 replacing we just keep the old memory if the allocation fails. 00312 00313 --*/ 00314 00315 { 00316 PRELATION_LIST oldList, newList; 00317 PRELATION_LIST_ENTRY oldEntry, newEntry; 00318 ULONG lowestLevel; 00319 ULONG highestLevel; 00320 ULONG index; 00321 00322 PAGED_CODE(); 00323 00324 oldList = *List; 00325 00326 // 00327 // Initialize lowestLevel and highestLevel with illegal values chosen so 00328 // that the first real entry will override them. 00329 // 00330 lowestLevel = oldList->MaxLevel; 00331 highestLevel = oldList->FirstLevel; 00332 00333 // 00334 // Loop through the list looking for allocated entries. 00335 // 00336 for (index = 0; index <= (oldList->MaxLevel - oldList->FirstLevel); index++) { 00337 00338 if ((oldEntry = oldList->Entries[ index ]) != NULL) { 00339 // 00340 // This entry is allocated, update lowestLevel and highestLevel if 00341 // necessary. 00342 // 00343 if (lowestLevel > index) { 00344 lowestLevel = index; 00345 } 00346 00347 if (highestLevel < index) { 00348 highestLevel = index; 00349 } 00350 00351 if (oldEntry->Count < oldEntry->MaxCount) { 00352 00353 // 00354 // This entry is only partially full. Allocate a new entry 00355 // which is just the right size to hold the current number of 00356 // PDEVICE_OBJECTs. 00357 // 00358 newEntry = ExAllocatePool( PagedPool, 00359 sizeof(RELATION_LIST_ENTRY) + 00360 (oldEntry->Count - 1) * sizeof(PDEVICE_OBJECT)); 00361 00362 if (newEntry != NULL) { 00363 00364 // 00365 // Initialize Count and MaxCount to the number of 00366 // PDEVICE_OBJECTs in the old entry. 00367 // 00368 newEntry->Count = oldEntry->Count; 00369 newEntry->MaxCount = oldEntry->Count; 00370 00371 // 00372 // Copy the PDEVICE_OBJECTs from the old entry to the new 00373 // one. 00374 // 00375 RtlCopyMemory( newEntry->Devices, 00376 oldEntry->Devices, 00377 oldEntry->Count * sizeof(PDEVICE_OBJECT)); 00378 00379 // 00380 // Free the old entry and store the new entry in the list. 00381 // 00382 ExFreePool( oldEntry ); 00383 00384 oldList->Entries[ index ] = newEntry; 00385 } 00386 } 00387 } 00388 } 00389 00390 // 00391 // Assert that the old list isn't empty. 00392 // 00393 ASSERT(lowestLevel <= highestLevel); 00394 00395 if (lowestLevel > highestLevel) { 00396 // 00397 // The list is empty - we shouldn't get asked to compress an empty list 00398 // but lets do it anyways. 00399 // 00400 lowestLevel = 0; 00401 highestLevel = 0; 00402 } 00403 00404 // 00405 // Check if the old list had unused entries at the beginning or the end of 00406 // the Entries array. 00407 // 00408 if (lowestLevel != oldList->FirstLevel || highestLevel != oldList->MaxLevel) { 00409 00410 // 00411 // Allocate a new List with just enough Entries to hold those between 00412 // FirstLevel and MaxLevel inclusive. 00413 // 00414 newList = ExAllocatePool( PagedPool, 00415 sizeof(RELATION_LIST) + 00416 (highestLevel - lowestLevel) * sizeof(PRELATION_LIST_ENTRY)); 00417 00418 if (newList != NULL) { 00419 // 00420 // Copy the old list to the new list and return it to the caller. 00421 // 00422 newList->Count = oldList->Count; 00423 newList->TagCount = oldList->TagCount; 00424 newList->FirstLevel = lowestLevel; 00425 newList->MaxLevel = highestLevel; 00426 00427 RtlCopyMemory( newList->Entries, 00428 &oldList->Entries[ lowestLevel ], 00429 (highestLevel - lowestLevel + 1) * sizeof(PRELATION_LIST_ENTRY)); 00430 00431 ExFreePool( oldList ); 00432 00433 *List = newList; 00434 } 00435 } 00436 00437 return STATUS_SUCCESS; 00438 }

BOOLEAN IopEnumerateRelations IN PRELATION_LIST  List,
IN OUT PULONG  Marker,
OUT PDEVICE_OBJECT DeviceObject,
OUT BOOLEAN *  DirectDescendant,
OPTIONAL OUT BOOLEAN *  Tagged,
OPTIONAL IN BOOLEAN  Reverse
 

Definition at line 441 of file pnprlist.c.

References ASSERT, _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, FALSE, List, NULL, PAGED_CODE, RELATION_FLAG_DESCENDANT, RELATION_FLAG_TAGGED, RELATION_FLAGS, and TRUE.

00452 : 00453 00454 Enumerates the relations in a list. 00455 00456 Arguments: 00457 00458 List Relation list to be enumerated. 00459 00460 Marker Cookie used to maintain current place in the list. It 00461 must be initialized to 0 the first time 00462 IopEnumerateRelations is called. 00463 00464 DeviceObject Returned Relation. 00465 00466 DirectDescendant If specified then it is set if the relation is a direct 00467 descendant of the original target device of this remove. 00468 00469 Tagged If specified then it is set if the relation is tagged 00470 otherwise it is cleared. 00471 00472 Reverse Direction of traversal, TRUE means from deepest to 00473 closest to the root, FALSE means from the root down. 00474 00475 If Reverse changes on a subsequent call then the 00476 previously enumerated relation is skipped. For example, 00477 given the sequence A, B, C, D, E. If 00478 IopEnumerateRelations is called thrice with Reverse set 00479 to FALSE and then called repeatedly with Reverse set to 00480 TRUE until it returns FALSE, the sequence would be: A, 00481 B, C, B, A. 00482 00483 Once the end has been reached it is not possible to 00484 change directions. 00485 00486 00487 Return Value: 00488 00489 TRUE 00490 00491 DeviceObject and optionally Tagged have been set to the next relation. 00492 00493 FALSE 00494 00495 There are no more relations. 00496 00497 --*/ 00498 00499 { 00500 PRELATION_LIST_ENTRY entry; 00501 LONG levelIndex; 00502 ULONG entryIndex; 00503 00504 PAGED_CODE(); 00505 00506 // 00507 // The basic assumptions of our use of Marker is that there will never be 00508 // more than 16M DeviceNodes at any one level and that the tree will never 00509 // be more than 127 deep. 00510 // 00511 // The format of Marker is 00512 // Bit 31 = Valid (used to distinguish the initial call 00513 // Bit 30-24 = Current index into entries 00514 // Bit 23-0 = Current index into devices, 0xFFFFFF means last 00515 // 00516 if (*Marker == ~0U) { 00517 // 00518 // We've reached the end. 00519 // 00520 return FALSE; 00521 } 00522 00523 if (*Marker == 0) { 00524 // 00525 // This is the initial call to IopEnumerateRelations 00526 // 00527 if (Reverse) { 00528 // 00529 // Initialize levelIndex to the last element of Entries 00530 // 00531 levelIndex = List->MaxLevel - List->FirstLevel; 00532 } else { 00533 // 00534 // Initialize levelIndex to the first element of Entries 00535 // 00536 levelIndex = 0; 00537 } 00538 // 00539 // Initialize entryIndex to unknown element of Devices. If we are going 00540 // in reverse then this will appear to be beyond the last element and 00541 // we'll adjust it the last one. If we are going forward then this will 00542 // appear to be just prior to the first element so when we increment it, 00543 // it will become zero. 00544 // 00545 entryIndex = ~0U; 00546 } else { 00547 // 00548 // Bit 31 is our valid bit, used to distinguish level 0, device 0 from 00549 // the first time call. 00550 // 00551 ASSERT(*Marker & ((ULONG)1 << 31)); 00552 // 00553 // Current level stored in bits 30-24. 00554 // 00555 levelIndex = (*Marker >> 24) & 0x7F; 00556 // 00557 // Current device stored in bits 23-0. 00558 // 00559 entryIndex = *Marker & 0x00FFFFFF; 00560 } 00561 00562 if (Reverse) { 00563 // 00564 // We are traversing the list bottom up, from the deepest device towards 00565 // the root. 00566 // 00567 for ( ; levelIndex >= 0; levelIndex--) { 00568 00569 // 00570 // Since the Entries array can be sparse find the next allocated 00571 // Entry. 00572 // 00573 if ((entry = List->Entries[ levelIndex ]) != NULL) { 00574 00575 if (entryIndex > entry->Count) { 00576 // 00577 // entryIndex (the current one) is greater than Count, this 00578 // will be the case where it is 0xFFFFFF, in other words 00579 // unspecified. Adjust it so that it is one past the last 00580 // one in this Entry. 00581 // 00582 entryIndex = entry->Count; 00583 } 00584 00585 if (entryIndex > 0) { 00586 00587 // 00588 // The current entry is beyond the first entry so the next 00589 // entry (which is the one we are looking for is immediately 00590 // prior, adjust entryIndex. 00591 // 00592 entryIndex--; 00593 00594 // 00595 // Get the device object and remove the tag. 00596 // 00597 *DeviceObject = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ entryIndex ] & ~RELATION_FLAGS); 00598 00599 if (Tagged != NULL) { 00600 // 00601 // The caller is interested in the tag value. 00602 // 00603 *Tagged = (BOOLEAN)((ULONG_PTR)entry->Devices[ entryIndex ] & RELATION_FLAG_TAGGED); 00604 } 00605 00606 if (DirectDescendant != NULL) { 00607 // 00608 // The caller is interested in the DirectDescendant value. 00609 // 00610 *DirectDescendant = (BOOLEAN)((ULONG_PTR)entry->Devices[ entryIndex ] & RELATION_FLAG_DESCENDANT); 00611 } 00612 00613 // 00614 // Update the marker (info for current device) 00615 // 00616 *Marker = ((ULONG)1 << 31) | (levelIndex << 24) | (entryIndex & 0x00FFFFFF); 00617 00618 return TRUE; 00619 } 00620 } 00621 00622 // 00623 // The current device object has been deleted or the current 00624 // device object is the first one in this Entry. 00625 // We need to continue to search backwards through the other 00626 // Entries. 00627 // 00628 entryIndex = ~0U; 00629 } 00630 } else { 00631 for ( ; levelIndex <= (LONG)(List->MaxLevel - List->FirstLevel); levelIndex++) { 00632 00633 // 00634 // Since the Entries array can be sparse find the next allocated 00635 // Entry. 00636 // 00637 if ((entry = List->Entries[ levelIndex ]) != NULL) { 00638 00639 // 00640 // entryIndex is the index of the current device or 0xFFFFFFFF 00641 // if this is the first time we have been called or the current 00642 // current device is the last one in its Entry. Increment the 00643 // index to point to the next device. 00644 // 00645 entryIndex++; 00646 00647 if (entryIndex < entry->Count) { 00648 00649 // 00650 // The next device is within this entry. 00651 // 00652 // 00653 // Get the device object and remove the tag. 00654 // 00655 *DeviceObject = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ entryIndex ] & ~RELATION_FLAGS); 00656 00657 if (Tagged != NULL) { 00658 // 00659 // The caller is interested in the tag value. 00660 // 00661 *Tagged = (BOOLEAN)((ULONG_PTR)entry->Devices[ entryIndex ] & RELATION_FLAG_TAGGED); 00662 } 00663 00664 if (DirectDescendant != NULL) { 00665 // 00666 // The caller is interested in the DirectDescendant value. 00667 // 00668 *DirectDescendant = (BOOLEAN)((ULONG_PTR)entry->Devices[ entryIndex ] & RELATION_FLAG_DESCENDANT); 00669 } 00670 00671 // 00672 // Update the marker (info for current device) 00673 // 00674 *Marker = ((ULONG)1 << 31) | (levelIndex << 24) | (entryIndex & 0x00FFFFFF); 00675 00676 return TRUE; 00677 } 00678 } 00679 00680 // 00681 // The current device has been removed or we have processed the 00682 // last device in the current entry. 00683 // Set entryIndex so that it is just before the first device in 00684 // the next entry. Continue the search looking for the next 00685 // allocated Entry. 00686 // 00687 entryIndex = ~0U; 00688 } 00689 } 00690 00691 // 00692 // We are at the end of the list 00693 // 00694 *Marker = ~0U; 00695 *DeviceObject = NULL; 00696 00697 if (Tagged != NULL) { 00698 *Tagged = FALSE; 00699 } 00700 00701 if (DirectDescendant != NULL) { 00702 *DirectDescendant = FALSE; 00703 } 00704 00705 return FALSE; 00706 }

VOID IopFreeRelationList IN PRELATION_LIST  List  ) 
 

Definition at line 709 of file pnprlist.c.

References _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, ExFreePool(), List, NULL, ObDereferenceObject, PAGED_CODE, and RELATION_FLAGS.

Referenced by IopDelayedRemoveWorker(), IopInvalidateRelationsInList(), IopLockDeviceRemovalRelations(), IopProcessCompletedEject(), and IopProcessRelation().

00715 : 00716 00717 Free a relation list allocated by IopAllocateRelationList. 00718 00719 Arguments: 00720 00721 List The list to be freed. 00722 00723 Return Value: 00724 00725 NONE. 00726 00727 --*/ 00728 00729 { 00730 PRELATION_LIST_ENTRY entry; 00731 ULONG levelIndex; 00732 ULONG entryIndex; 00733 00734 PAGED_CODE(); 00735 00736 // 00737 // Search the list looking for allocated Entries. 00738 // 00739 for (levelIndex = 0; levelIndex <= (List->MaxLevel - List->FirstLevel); levelIndex++) { 00740 00741 if ((entry = List->Entries[ levelIndex ]) != NULL) { 00742 // 00743 // This entry has been allocated. 00744 // 00745 for (entryIndex = 0; entryIndex < entry->Count; entryIndex++) { 00746 // 00747 // Dereference all the Devices in the entry. 00748 // 00749 ObDereferenceObject((PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ entryIndex ] & ~RELATION_FLAGS)); 00750 } 00751 // 00752 // Free the Entry. 00753 // 00754 ExFreePool( entry ); 00755 } 00756 } 00757 00758 // 00759 // Free the list. It isn't necessary to dereference the DeviceObject that 00760 // was the original target that caused the list to be created. This 00761 // DeviceObject is also in one of the Entries and its reference is taken 00762 // and released there. 00763 // 00764 ExFreePool( List ); 00765 }

ULONG IopGetRelationsCount PRELATION_LIST  List  ) 
 

Definition at line 768 of file pnprlist.c.

References List, and PAGED_CODE.

00774 : 00775 00776 Returns the total number of relations (Device Objects) in all the entries. 00777 00778 Arguments: 00779 00780 List Relation List. 00781 00782 Return Value: 00783 00784 Count of relations (Device Objects). 00785 00786 --*/ 00787 00788 { 00789 PAGED_CODE(); 00790 00791 return List->Count; 00792 }

ULONG IopGetRelationsTaggedCount PRELATION_LIST  List  ) 
 

Definition at line 795 of file pnprlist.c.

References List, and PAGED_CODE.

00801 : 00802 00803 Returns the total number of relations (Device Objects) in all the entries 00804 which are tagged. 00805 00806 Arguments: 00807 00808 List Relation List. 00809 00810 Return Value: 00811 00812 Count of tagged relations (Device Objects). 00813 00814 --*/ 00815 00816 { 00817 PAGED_CODE(); 00818 00819 return List->TagCount; 00820 }

BOOLEAN IopIsRelationInList PRELATION_LIST  List,
PDEVICE_OBJECT  DeviceObject
 

Definition at line 823 of file pnprlist.c.

References _RELATION_LIST_ENTRY::Count, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, _RELATION_LIST_ENTRY::Devices, FALSE, _DEVICE_NODE::Level, List, NULL, PAGED_CODE, RELATION_FLAGS, and TRUE.

00830 : 00831 00832 Checks if a relation (Device Object) exists in the specified relation list. 00833 00834 Arguments: 00835 00836 List Relation list to check. 00837 00838 DeviceObject Relation to be checked. 00839 00840 00841 Return Value: 00842 00843 TRUE 00844 00845 Relation exists. 00846 00847 FALSE 00848 00849 Relation is not in the list. 00850 00851 --*/ 00852 00853 { 00854 PDEVICE_NODE deviceNode; 00855 PRELATION_LIST_ENTRY entry; 00856 ULONG level; 00857 ULONG index; 00858 00859 PAGED_CODE(); 00860 00861 if ((deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode) != NULL) { 00862 // 00863 // The device object is a PDO. 00864 // 00865 level = deviceNode->Level; 00866 00867 if (List->FirstLevel <= level && level <= List->MaxLevel) { 00868 // 00869 // The level is within the range of levels stored in this list. 00870 // 00871 if ((entry = List->Entries[ level - List->FirstLevel ]) != NULL) { 00872 // 00873 // There is an Entry for this level. 00874 // 00875 for (index = 0; index < entry->Count; index++) { 00876 // 00877 // For each Device in the entry, compare it to the given 00878 // DeviceObject 00879 if (((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAGS) == (ULONG_PTR)DeviceObject) { 00880 // 00881 // It matches 00882 // 00883 return TRUE; 00884 } 00885 } 00886 } 00887 } 00888 } 00889 00890 // 00891 // It wasn't a PDO 00892 // or the level wasn't in the range of levels in this list 00893 // or there are no DeviceObjects at the same level in this list 00894 // or the DeviceObject isn't in the Entry for its level in this list 00895 // 00896 return FALSE; 00897 }

NTSTATUS IopMergeRelationLists IN OUT PRELATION_LIST  TargetList,
IN PRELATION_LIST  SourceList,
IN BOOLEAN  Tagged
 

Definition at line 900 of file pnprlist.c.

References ASSERT, _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, FALSE, IopAddRelationToList(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and RELATION_FLAGS.

Referenced by IopProcessRelation().

00908 : 00909 00910 Merges two relation lists by copying all the relations from the source list 00911 to the target list. Source list remains unchanged. 00912 00913 Arguments: 00914 00915 TargetList List to which the relations from Sourcelist are added. 00916 00917 SourceList List of relations to be added to TargetList. 00918 00919 Tagged TRUE if relations from SourceList should be tagged when added to 00920 TargetList. If FALSE then relations added from SourceList are 00921 untagged. 00922 00923 Return Value: 00924 00925 STATUS_SUCCESS 00926 00927 All the relations in SourceList were added to TargetList successfully. 00928 00929 STATUS_OBJECT_NAME_COLLISION 00930 00931 One of the relations in SourceList already exists in TargetList. This 00932 is a fatal error and TargetList may already have some of the relations 00933 from SourceList added. This could be dealt with more gracefully if 00934 necessary but the current callers of IopMergeRelationLists avoid this 00935 situation. 00936 00937 STATUS_INSUFFICIENT_RESOURCES 00938 00939 There isn't enough PagedPool available to allocate a new 00940 RELATION_LIST_ENTRY. 00941 00942 STATUS_INVALID_PARAMETER 00943 00944 The level of one of the relations in SourceList is less than FirstLevel 00945 or greater than the MaxLevel. This is a fatal error and TargetList may 00946 already have some of the relations from SourceList added. The only way 00947 this could happen is if the tree lock isn't held or if TargetList has 00948 been compressed by IopCompressRelationList. Both situations would be 00949 bugs in the caller. 00950 00951 STATUS_NO_SUCH_DEVICE 00952 00953 One of the relations in SourceList is not a PhysicalDeviceObject (PDO), 00954 it doesn't have a DEVICE_NODE associated with it. This is a fatal error 00955 and TargetList may already have some of the relations from SourceList 00956 added. This should never happen since it was a PDO when it was added to 00957 SourceList. 00958 00959 00960 --*/ 00961 00962 { 00963 PRELATION_LIST_ENTRY entry; 00964 ULONG levelIndex; 00965 ULONG entryIndex; 00966 NTSTATUS status = STATUS_SUCCESS; 00967 00968 PAGED_CODE(); 00969 00970 // 00971 // For each level entry in SourceList 00972 // 00973 for (levelIndex = 0; 00974 levelIndex <= (SourceList->MaxLevel - SourceList->FirstLevel); 00975 levelIndex++) { 00976 00977 if ((entry = SourceList->Entries[ levelIndex ]) != NULL) { 00978 // 00979 // The Entry has Devices 00980 // 00981 for (entryIndex = 0; entryIndex < entry->Count; entryIndex++) { 00982 // 00983 // For each Device in the Entry, add it to the target List. 00984 // 00985 status = IopAddRelationToList( TargetList, 00986 (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ entryIndex ] & ~RELATION_FLAGS), 00987 FALSE, 00988 Tagged); 00989 00990 // 00991 // BUGBUG - Need to handle STATUS_INSUFFICIENT_RESOURCES more 00992 // gracefully. Currently the only way this can happen is 00993 // during Eject and that code isn't enabled yet. 00994 // 00995 ASSERT(NT_SUCCESS(status)); 00996 00997 if (!NT_SUCCESS(status)) { 00998 // 00999 // BUGBUG - We should undo the damage we've done to 01000 // TargetList by removing those relations we've added from 01001 // SourceList. 01002 // 01003 break; 01004 } 01005 } 01006 } 01007 } 01008 01009 return status; 01010 }

NTSTATUS IopRemoveIndirectRelationsFromList IN PRELATION_LIST  List  ) 
 

Definition at line 1013 of file pnprlist.c.

References _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, ExFreePool(), List, NULL, ObDereferenceObject, PAGED_CODE, RELATION_FLAG_DESCENDANT, RELATION_FLAG_TAGGED, and RELATION_FLAGS.

01019 : 01020 01021 Removes all the relations without the DirectDescendant flag from a relation 01022 list. 01023 01024 Arguments: 01025 01026 List List from which to remove the relations. 01027 01028 01029 Return Value: 01030 01031 STATUS_SUCCESS 01032 01033 The relations were removed successfully. 01034 01035 --*/ 01036 01037 { 01038 PDEVICE_OBJECT deviceObject; 01039 PRELATION_LIST_ENTRY entry; 01040 ULONG level; 01041 LONG index; 01042 01043 PAGED_CODE(); 01044 01045 // 01046 // For each Entry in the list. 01047 // 01048 for (level = List->FirstLevel; level <= List->MaxLevel; level++) { 01049 01050 // 01051 // If the entry is allocated. 01052 // 01053 if ((entry = List->Entries[ level - List->FirstLevel ]) != NULL) { 01054 01055 // 01056 // For each Device in the list. 01057 // 01058 for (index = entry->Count - 1; index >= 0; index--) { 01059 if (!((ULONG_PTR)entry->Devices[ index ] & RELATION_FLAG_DESCENDANT)) { 01060 01061 deviceObject = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAGS); 01062 01063 ObDereferenceObject( deviceObject ); 01064 01065 if ((ULONG_PTR)entry->Devices[ index ] & RELATION_FLAG_TAGGED) { 01066 List->TagCount--; 01067 } 01068 01069 if (index < ((LONG)entry->Count - 1)) { 01070 01071 RtlMoveMemory( &entry->Devices[ index ], 01072 &entry->Devices[ index + 1 ], 01073 (entry->Count - index - 1) * sizeof(PDEVICE_OBJECT)); 01074 } 01075 01076 if (--entry->Count == 0) { 01077 List->Entries[ level - List->FirstLevel ] = NULL; 01078 ExFreePool(entry); 01079 } 01080 01081 List->Count--; 01082 } 01083 } 01084 } 01085 } 01086 return STATUS_SUCCESS; 01087 }

NTSTATUS IopRemoveRelationFromList PRELATION_LIST  List,
PDEVICE_OBJECT  DeviceObject
 

Definition at line 1090 of file pnprlist.c.

References ASSERT, _RELATION_LIST_ENTRY::Count, _DEVOBJ_EXTENSION::DeviceNode, _DEVICE_OBJECT::DeviceObjectExtension, _RELATION_LIST_ENTRY::Devices, ExFreePool(), _DEVICE_NODE::Level, List, NULL, ObDereferenceObject, PAGED_CODE, RELATION_FLAG_TAGGED, and RELATION_FLAGS.

01097 : 01098 01099 Removes a relation from a relation list. 01100 01101 Arguments: 01102 01103 List List from which to remove the relation. 01104 01105 DeviceObject Relation to remove. 01106 01107 Return Value: 01108 01109 STATUS_SUCCESS 01110 01111 The relation was removed successfully. 01112 01113 STATUS_NO_SUCH_DEVICE 01114 01115 The relation doesn't exist in the list. 01116 01117 --*/ 01118 01119 { 01120 PDEVICE_NODE deviceNode; 01121 PRELATION_LIST_ENTRY entry; 01122 ULONG level; 01123 LONG index; 01124 01125 PAGED_CODE(); 01126 01127 if ((deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode) != NULL) { 01128 level = deviceNode->Level; 01129 01130 ASSERT(List->FirstLevel <= level && level <= List->MaxLevel); 01131 01132 if (List->FirstLevel <= level && level <= List->MaxLevel) { 01133 if ((entry = List->Entries[ level - List->FirstLevel ]) != NULL) { 01134 for (index = entry->Count - 1; index >= 0; index--) { 01135 if (((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAGS) == (ULONG_PTR)DeviceObject) { 01136 01137 ObDereferenceObject( DeviceObject ); 01138 01139 if (((ULONG_PTR)entry->Devices[ index ] & RELATION_FLAG_TAGGED) != 0) { 01140 List->TagCount--; 01141 } 01142 if (index < ((LONG)entry->Count - 1)) { 01143 01144 RtlMoveMemory( &entry->Devices[ index ], 01145 &entry->Devices[ index + 1 ], 01146 (entry->Count - index - 1) * sizeof(PDEVICE_OBJECT)); 01147 } 01148 01149 if (--entry->Count == 0) { 01150 List->Entries[ level - List->FirstLevel ] = NULL; 01151 ExFreePool(entry); 01152 } 01153 01154 List->Count--; 01155 01156 return STATUS_SUCCESS; 01157 } 01158 } 01159 } 01160 } 01161 } 01162 return STATUS_NO_SUCH_DEVICE; 01163 }

VOID IopSetAllRelationsTags PRELATION_LIST  List,
BOOLEAN  Tagged
 

Definition at line 1166 of file pnprlist.c.

References _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, List, NULL, PAGED_CODE, and RELATION_FLAG_TAGGED.

01173 : 01174 01175 Tags or untags all the relations in a relations list. 01176 01177 Arguments: 01178 01179 List Relation list containing relations to be tagged or untagged. 01180 01181 Tagged TRUE if the relations should be tagged, FALSE if they are to be 01182 untagged. 01183 01184 Return Value: 01185 01186 NONE 01187 01188 --*/ 01189 01190 { 01191 PRELATION_LIST_ENTRY entry; 01192 ULONG level; 01193 ULONG index; 01194 01195 PAGED_CODE(); 01196 01197 // 01198 // For each Entry in the list. 01199 // 01200 for (level = List->FirstLevel; level <= List->MaxLevel; level++) { 01201 01202 // 01203 // If the entry is allocated. 01204 // 01205 if ((entry = List->Entries[ level - List->FirstLevel ]) != NULL) { 01206 01207 // 01208 // For each Device in the list. 01209 // 01210 for (index = 0; index < entry->Count; index++) { 01211 01212 // 01213 // Set or clear the tag based on the argument Tagged. 01214 // 01215 if (Tagged) { 01216 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] | RELATION_FLAG_TAGGED); 01217 } else { 01218 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAG_TAGGED); 01219 } 01220 } 01221 } 01222 } 01223 01224 // 01225 // If we are setting the tags then update the TagCount to the number of 01226 // relations in the list. Otherwise reset it to zero. 01227 // 01228 List->TagCount = Tagged ? List->Count : 0; 01229 }

NTSTATUS IopSetRelationsTag IN PRELATION_LIST  List,
IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  Tagged
 

Definition at line 1232 of file pnprlist.c.

References _RELATION_LIST_ENTRY::Count, _RELATION_LIST_ENTRY::Devices, _DEVICE_NODE::Level, List, NULL, PAGED_CODE, RELATION_FLAG_TAGGED, and RELATION_FLAGS.

Referenced by IopChainDereferenceComplete(), and IopInvalidateRelationsInList().

01240 : 01241 01242 Sets or clears a tag on a specified relation in a relations list. This 01243 routine is also used by some callers to determine if a relation exists in 01244 a list and if so to set the tag. 01245 01246 Arguments: 01247 01248 List List containing relation to be tagged or untagged. 01249 01250 DeviceObject Relation to be tagged or untagged. 01251 01252 Tagged TRUE if relation is to be tagged, FALSE if it is to be 01253 untagged. 01254 01255 Return Value: 01256 01257 STATUS_SUCCESS 01258 01259 The relation was tagged successfully. 01260 01261 STATUS_NO_SUCH_DEVICE 01262 01263 The relation doesn't exist in the list. 01264 01265 --*/ 01266 01267 { 01268 PDEVICE_NODE deviceNode; 01269 PRELATION_LIST_ENTRY entry; 01270 ULONG level; 01271 LONG index; 01272 01273 PAGED_CODE(); 01274 01275 if ((deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode) != NULL) { 01276 // 01277 // DeviceObject is a PhysicalDeviceObject (PDO), get its level. 01278 // 01279 level = deviceNode->Level; 01280 01281 if (List->FirstLevel <= level && level <= List->MaxLevel) { 01282 // 01283 // The level is within the range of levels in this List. 01284 // 01285 if ((entry = List->Entries[ level - List->FirstLevel ]) != NULL) { 01286 // 01287 // The Entry for this level is allocated. Search each device 01288 // in the Entry looking for a match. 01289 // 01290 for (index = entry->Count - 1; index >= 0; index--) { 01291 01292 if (((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAGS) == (ULONG_PTR)DeviceObject) { 01293 01294 // 01295 // We found a match 01296 // 01297 if ((ULONG_PTR)entry->Devices[ index ] & RELATION_FLAG_TAGGED) { 01298 // 01299 // The relation is already tagged so to simplify the 01300 // logic below decrement the TagCount. We'll 01301 // increment it later if the caller still wants it 01302 // to be tagged. 01303 // 01304 List->TagCount--; 01305 } 01306 01307 if (Tagged) { 01308 // 01309 // Set the tag and increment the number of tagged 01310 // relations. 01311 // 01312 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] | RELATION_FLAG_TAGGED); 01313 List->TagCount++; 01314 } else { 01315 // 01316 // Clear the tag. 01317 // 01318 entry->Devices[ index ] = (PDEVICE_OBJECT)((ULONG_PTR)entry->Devices[ index ] & ~RELATION_FLAG_TAGGED); 01319 } 01320 01321 return STATUS_SUCCESS; 01322 } 01323 } 01324 } 01325 } 01326 } 01327 01328 // 01329 // It wasn't a PDO 01330 // or the level wasn't in the range of levels in this list 01331 // or there are no DeviceObjects at the same level in this list 01332 // or the DeviceObject isn't in the Entry for its level in this list 01333 // 01334 return STATUS_NO_SUCH_DEVICE; 01335 }


Generated on Sat May 15 19:45:15 2004 for test by doxygen 1.3.7