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

heapdbg.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 heapdbg.c 00008 00009 Abstract: 00010 00011 This module implements a debugging layer on top of heap allocator. 00012 00013 Author: 00014 00015 Steve Wood (stevewo) 20-Sep-1994 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "ntrtlp.h" 00022 #include "heap.h" 00023 #include "heappriv.h" 00024 00025 BOOLEAN RtlpValidateHeapHdrsEnable = FALSE; // Set to TRUE if headers are being corrupted 00026 BOOLEAN RtlpValidateHeapTagsEnable; // Set to TRUE if tag counts are off and you want to know why 00027 00028 HEAP_STOP_ON_VALUES RtlpHeapStopOn; 00029 00030 00031 const struct { 00032 00033 ULONG Offset; 00034 LPSTR Description; 00035 00036 } RtlpHeapHeaderFieldOffsets[] = { 00037 00038 FIELD_OFFSET( HEAP, Entry ), "Entry", 00039 FIELD_OFFSET( HEAP, Signature ), "Signature", 00040 FIELD_OFFSET( HEAP, Flags ), "Flags", 00041 FIELD_OFFSET( HEAP, ForceFlags ), "ForceFlags", 00042 FIELD_OFFSET( HEAP, VirtualMemoryThreshold ), "VirtualMemoryThreshold", 00043 FIELD_OFFSET( HEAP, SegmentReserve ), "SegmentReserve", 00044 FIELD_OFFSET( HEAP, SegmentCommit ), "SegmentCommit", 00045 FIELD_OFFSET( HEAP, DeCommitFreeBlockThreshold ), "DeCommitFreeBlockThreshold", 00046 FIELD_OFFSET( HEAP, DeCommitTotalFreeThreshold ), "DeCommitTotalFreeThreshold", 00047 FIELD_OFFSET( HEAP, TotalFreeSize ), "TotalFreeSize", 00048 FIELD_OFFSET( HEAP, MaximumAllocationSize ), "MaximumAllocationSize", 00049 FIELD_OFFSET( HEAP, ProcessHeapsListIndex ), "ProcessHeapsListIndex", 00050 FIELD_OFFSET( HEAP, HeaderValidateLength ), "HeaderValidateLength", 00051 FIELD_OFFSET( HEAP, HeaderValidateCopy ), "HeaderValidateCopy", 00052 FIELD_OFFSET( HEAP, NextAvailableTagIndex ), "NextAvailableTagIndex", 00053 FIELD_OFFSET( HEAP, MaximumTagIndex ), "MaximumTagIndex", 00054 FIELD_OFFSET( HEAP, TagEntries ), "TagEntries", 00055 FIELD_OFFSET( HEAP, UCRSegments ), "UCRSegments", 00056 FIELD_OFFSET( HEAP, UnusedUnCommittedRanges ), "UnusedUnCommittedRanges", 00057 FIELD_OFFSET( HEAP, AlignRound ), "AlignRound", 00058 FIELD_OFFSET( HEAP, AlignMask ), "AlignMask", 00059 FIELD_OFFSET( HEAP, VirtualAllocdBlocks ), "VirtualAllocdBlocks", 00060 FIELD_OFFSET( HEAP, Segments ), "Segments", 00061 FIELD_OFFSET( HEAP, u ), "FreeListsInUse", 00062 FIELD_OFFSET( HEAP, FreeListsInUseTerminate ), "FreeListsInUseTerminate", 00063 FIELD_OFFSET( HEAP, AllocatorBackTraceIndex ), "AllocatorBackTraceIndex", 00064 FIELD_OFFSET( HEAP, Reserved1 ), "Reserved1", 00065 FIELD_OFFSET( HEAP, PseudoTagEntries ), "PseudoTagEntries", 00066 FIELD_OFFSET( HEAP, FreeLists ), "FreeLists", 00067 FIELD_OFFSET( HEAP, LockVariable ), "LockVariable", 00068 FIELD_OFFSET( HEAP, Lookaside ), "Lookaside", 00069 FIELD_OFFSET( HEAP, LookasideLockCount ), "LookasideLockCount", 00070 sizeof( HEAP ), "Uncommitted Ranges", 00071 0xFFFF, NULL 00072 }; 00073 00074 00075 VOID 00076 RtlpUpdateHeapListIndex ( 00077 USHORT OldIndex, 00078 USHORT NewIndex 00079 ) 00080 00081 /*++ 00082 00083 Routine Description: 00084 00085 Arguments: 00086 00087 Return Value: 00088 00089 --*/ 00090 00091 { 00092 if (RtlpHeapStopOn.AllocTag.HeapIndex == OldIndex) { 00093 00094 RtlpHeapStopOn.AllocTag.HeapIndex = NewIndex; 00095 } 00096 00097 if (RtlpHeapStopOn.ReAllocTag.HeapIndex == OldIndex) { 00098 00099 RtlpHeapStopOn.ReAllocTag.HeapIndex = NewIndex; 00100 } 00101 00102 if (RtlpHeapStopOn.FreeTag.HeapIndex == OldIndex) { 00103 00104 RtlpHeapStopOn.FreeTag.HeapIndex = NewIndex; 00105 } 00106 00107 return; 00108 } 00109 00110 00111 BOOLEAN 00112 RtlpValidateHeapHeaders ( 00113 IN PHEAP Heap, 00114 IN BOOLEAN Recompute 00115 ) 00116 00117 /*++ 00118 00119 Routine Description: 00120 00121 Arguments: 00122 00123 Return Value: 00124 00125 --*/ 00126 00127 { 00128 ULONG i; 00129 SIZE_T n; 00130 SIZE_T nEqual; 00131 NTSTATUS Status; 00132 00133 if (!RtlpValidateHeapHdrsEnable) { 00134 00135 return TRUE; 00136 } 00137 00138 if (Heap->HeaderValidateCopy == NULL) { 00139 00140 n = Heap->HeaderValidateLength; 00141 00142 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 00143 &Heap->HeaderValidateCopy, 00144 0, 00145 &n, 00146 MEM_COMMIT, 00147 PAGE_READWRITE ); 00148 00149 if (!NT_SUCCESS( Status )) { 00150 00151 return TRUE; 00152 } 00153 00154 Recompute = TRUE; 00155 } 00156 00157 n = Heap->HeaderValidateLength; 00158 00159 if (!Recompute) { 00160 00161 nEqual = RtlCompareMemory( Heap, 00162 Heap->HeaderValidateCopy, 00163 n ); 00164 00165 } else { 00166 00167 RtlMoveMemory( Heap->HeaderValidateCopy, 00168 Heap, 00169 n ); 00170 00171 nEqual = n; 00172 } 00173 00174 if (n != nEqual) { 00175 00176 HeapDebugPrint(( "Heap %x - headers modified (%x is %x instead of %x)\n", 00177 Heap, 00178 (PCHAR)Heap + nEqual, 00179 *(PULONG)((PCHAR)Heap + nEqual), 00180 *(PULONG)((PCHAR)Heap->HeaderValidateCopy + nEqual))); 00181 00182 for (i=0; RtlpHeapHeaderFieldOffsets[ i ].Description != NULL; i++) { 00183 00184 if ((nEqual >= RtlpHeapHeaderFieldOffsets[ i ].Offset) && 00185 (nEqual < RtlpHeapHeaderFieldOffsets[ i+1 ].Offset)) { 00186 00187 DbgPrint( " This is located in the %s field of the heap header.\n", 00188 RtlpHeapHeaderFieldOffsets[ i ].Description ); 00189 00190 break; 00191 } 00192 } 00193 00194 return FALSE; 00195 00196 } else { 00197 00198 return TRUE; 00199 } 00200 } 00201 00202 00203 PVOID 00204 RtlDebugCreateHeap ( 00205 IN ULONG Flags, 00206 IN PVOID HeapBase OPTIONAL, 00207 IN SIZE_T ReserveSize OPTIONAL, 00208 IN SIZE_T CommitSize OPTIONAL, 00209 IN PVOID Lock OPTIONAL, 00210 IN PRTL_HEAP_PARAMETERS Parameters 00211 ) 00212 00213 /*++ 00214 00215 Routine Description: 00216 00217 Arguments: 00218 00219 Return Value: 00220 00221 --*/ 00222 00223 { 00224 PHEAP Heap; 00225 NTSTATUS Status; 00226 MEMORY_BASIC_INFORMATION MemoryInformation; 00227 00228 if (ReserveSize <= sizeof( HEAP_ENTRY )) { 00229 00230 HeapDebugPrint(( "Invalid ReserveSize parameter - %lx\n", ReserveSize )); 00231 HeapDebugBreak( NULL ); 00232 00233 return NULL; 00234 } 00235 00236 if (ReserveSize < CommitSize) { 00237 00238 HeapDebugPrint(( "Invalid CommitSize parameter - %lx\n", CommitSize )); 00239 HeapDebugBreak( NULL ); 00240 00241 return NULL; 00242 } 00243 00244 if ((Flags & HEAP_NO_SERIALIZE) && ARGUMENT_PRESENT( Lock )) { 00245 00246 HeapDebugPrint(( "May not specify Lock parameter with HEAP_NO_SERIALIZE\n" )); 00247 HeapDebugBreak( NULL ); 00248 00249 return NULL; 00250 } 00251 00252 if (ARGUMENT_PRESENT( HeapBase )) { 00253 00254 Status = NtQueryVirtualMemory( NtCurrentProcess(), 00255 HeapBase, 00256 MemoryBasicInformation, 00257 &MemoryInformation, 00258 sizeof( MemoryInformation ), 00259 NULL ); 00260 00261 if (!NT_SUCCESS( Status )) { 00262 00263 HeapDebugPrint(( "Specified HeapBase (%lx) invalid, Status = %lx\n", 00264 HeapBase, 00265 Status )); 00266 00267 HeapDebugBreak( NULL ); 00268 00269 return NULL; 00270 } 00271 00272 if (MemoryInformation.BaseAddress != HeapBase) { 00273 00274 HeapDebugPrint(( "Specified HeapBase (%lx) != to BaseAddress (%lx)\n", 00275 HeapBase, 00276 MemoryInformation.BaseAddress )); 00277 00278 HeapDebugBreak( NULL ); 00279 00280 return NULL; 00281 } 00282 00283 if (MemoryInformation.State == MEM_FREE) { 00284 00285 HeapDebugPrint(( "Specified HeapBase (%lx) is free or not writable\n", 00286 MemoryInformation.BaseAddress )); 00287 00288 HeapDebugBreak( NULL ); 00289 00290 return NULL; 00291 } 00292 } 00293 00294 Heap = RtlCreateHeap( Flags | 00295 HEAP_SKIP_VALIDATION_CHECKS | 00296 HEAP_TAIL_CHECKING_ENABLED | 00297 HEAP_FREE_CHECKING_ENABLED, 00298 HeapBase, 00299 ReserveSize, 00300 CommitSize, 00301 Lock, 00302 Parameters ); 00303 00304 if (Heap != NULL) { 00305 00306 #if i386 00307 00308 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 00309 00310 Heap->AllocatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 00311 } 00312 00313 #endif // i386 00314 00315 RtlpValidateHeapHeaders( Heap, TRUE ); 00316 } 00317 00318 return Heap; 00319 } 00320 00321 00322 BOOLEAN 00323 RtlpSerializeHeap ( 00324 IN PVOID HeapHandle 00325 ) 00326 00327 /*++ 00328 00329 Routine Description: 00330 00331 Arguments: 00332 00333 Return Value: 00334 00335 --*/ 00336 00337 { 00338 NTSTATUS Status; 00339 PHEAP Heap = (PHEAP)HeapHandle; 00340 PHEAP_LOCK Lock; 00341 00342 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00343 RtlpDebugPageHeapSerialize( HeapHandle )); 00344 00345 // 00346 // Validate that HeapAddress points to a HEAP structure. 00347 // 00348 00349 if (!RtlpCheckHeapSignature( Heap, "RtlpSerializeHeap" )) { 00350 00351 return FALSE; 00352 } 00353 00354 // 00355 // Lock the heap. 00356 // 00357 00358 if (Heap->Flags & HEAP_NO_SERIALIZE) { 00359 00360 Lock = RtlAllocateHeap( HeapHandle, HEAP_NO_SERIALIZE, sizeof( *Lock ) ); 00361 00362 if ( Lock == NULL ) { 00363 00364 return FALSE; 00365 } 00366 00367 Status = RtlInitializeLockRoutine( Lock ); 00368 00369 if (!NT_SUCCESS( Status )) { 00370 00371 RtlFreeHeap( HeapHandle, HEAP_NO_SERIALIZE, Lock ); 00372 00373 return FALSE; 00374 } 00375 00376 Heap->LockVariable = Lock; 00377 Heap->Flags &= ~HEAP_NO_SERIALIZE; 00378 Heap->ForceFlags &= ~HEAP_NO_SERIALIZE; 00379 00380 RtlpValidateHeapHeaders( Heap, TRUE ); 00381 } 00382 00383 return TRUE; 00384 } 00385 00386 00387 BOOLEAN 00388 RtlDebugDestroyHeap ( 00389 IN PVOID HeapHandle 00390 ) 00391 00392 /*++ 00393 00394 Routine Description: 00395 00396 Arguments: 00397 00398 Return Value: 00399 00400 --*/ 00401 00402 { 00403 PHEAP Heap = (PHEAP)HeapHandle; 00404 LIST_ENTRY ListEntry; 00405 SIZE_T n; 00406 00407 if (HeapHandle == NtCurrentPeb()->ProcessHeap) { 00408 00409 HeapDebugPrint(( "May not destroy the process heap at %x\n", HeapHandle )); 00410 00411 return FALSE; 00412 } 00413 00414 if (!RtlpCheckHeapSignature( Heap, "RtlDestroyHeap" )) { 00415 00416 return FALSE; 00417 } 00418 00419 if (!RtlpValidateHeap( Heap, FALSE )) { 00420 00421 return FALSE; 00422 } 00423 00424 // 00425 // Now mark the heap as invalid by zeroing the signature field. 00426 // 00427 00428 Heap->Signature = 0; 00429 00430 if (Heap->HeaderValidateCopy != NULL) { 00431 00432 n = 0; 00433 NtFreeVirtualMemory( NtCurrentProcess(), 00434 &Heap->HeaderValidateCopy, 00435 &n, 00436 MEM_RELEASE ); 00437 } 00438 00439 return TRUE; 00440 } 00441 00442 00443 PVOID 00444 RtlDebugAllocateHeap ( 00445 IN PVOID HeapHandle, 00446 IN ULONG Flags, 00447 IN SIZE_T Size 00448 ) 00449 00450 /*++ 00451 00452 Routine Description: 00453 00454 Arguments: 00455 00456 Return Value: 00457 00458 --*/ 00459 00460 { 00461 PHEAP Heap = (PHEAP)HeapHandle; 00462 BOOLEAN LockAcquired = FALSE; 00463 PVOID ReturnValue = NULL; 00464 SIZE_T AllocationSize; 00465 USHORT TagIndex; 00466 PHEAP_ENTRY BusyBlock; 00467 PHEAP_ENTRY_EXTRA ExtraStuff; 00468 00469 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00470 RtlpDebugPageHeapAllocate( HeapHandle, Flags, Size )); 00471 00472 try { 00473 00474 try { 00475 00476 // 00477 // Validate that HeapAddress points to a HEAP structure. 00478 // 00479 00480 if (!RtlpCheckHeapSignature( Heap, "RtlAllocateHeap" )) { 00481 00482 ReturnValue = NULL; 00483 leave; 00484 } 00485 00486 Flags |= Heap->ForceFlags | HEAP_SETTABLE_USER_VALUE | HEAP_SKIP_VALIDATION_CHECKS; 00487 00488 // 00489 // Verify that the size did not wrap or exceed the limit for this heap. 00490 // 00491 00492 AllocationSize = (((Size ? Size : 1) + Heap->AlignRound) & Heap->AlignMask) + 00493 sizeof( HEAP_ENTRY_EXTRA ); 00494 00495 if ((AllocationSize < Size) || (AllocationSize > Heap->MaximumAllocationSize)) { 00496 00497 HeapDebugPrint(( "Invalid allocation size - %lx (exceeded %x)\n", 00498 Size, 00499 Heap->MaximumAllocationSize )); 00500 00501 ReturnValue = NULL; 00502 leave; 00503 } 00504 00505 // 00506 // Lock the heap 00507 // 00508 00509 if (!(Flags & HEAP_NO_SERIALIZE)) { 00510 00511 RtlAcquireLockRoutine( Heap->LockVariable ); 00512 00513 LockAcquired = TRUE; 00514 00515 Flags |= HEAP_NO_SERIALIZE; 00516 } 00517 00518 RtlpValidateHeap( Heap, FALSE ); 00519 00520 ReturnValue = RtlAllocateHeapSlowly( HeapHandle, Flags, Size ); 00521 00522 RtlpValidateHeapHeaders( Heap, TRUE ); 00523 00524 if (ReturnValue != NULL) { 00525 00526 BusyBlock = (PHEAP_ENTRY)ReturnValue - 1; 00527 00528 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00529 00530 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00531 00532 #if i386 00533 00534 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 00535 00536 ExtraStuff->AllocatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 00537 00538 } else { 00539 00540 ExtraStuff->AllocatorBackTraceIndex = 0; 00541 } 00542 00543 #endif // i386 00544 00545 TagIndex = ExtraStuff->TagIndex; 00546 00547 } else { 00548 00549 TagIndex = BusyBlock->SmallTagIndex; 00550 } 00551 00552 if (Heap->Flags & HEAP_VALIDATE_ALL_ENABLED) { 00553 00554 RtlpValidateHeap( Heap, FALSE ); 00555 } 00556 } 00557 00558 if (ReturnValue != NULL) { 00559 00560 if ((ULONG_PTR)ReturnValue == RtlpHeapStopOn.AllocAddress) { 00561 00562 HeapDebugPrint(( "Just allocated block at %lx for 0x%x bytes\n", 00563 RtlpHeapStopOn.AllocAddress, 00564 Size )); 00565 00566 HeapDebugBreak( NULL ); 00567 00568 } else if ((IS_HEAP_TAGGING_ENABLED()) && 00569 (TagIndex != 0) && 00570 (TagIndex == RtlpHeapStopOn.AllocTag.TagIndex) && 00571 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.AllocTag.HeapIndex)) { 00572 00573 HeapDebugPrint(( "Just allocated block at %lx for 0x%x bytes with tag %ws\n", 00574 ReturnValue, 00575 Size, 00576 RtlpGetTagName( Heap, TagIndex ))); 00577 00578 HeapDebugBreak( NULL ); 00579 } 00580 } 00581 00582 } except( GetExceptionCode() == STATUS_NO_MEMORY ? EXCEPTION_CONTINUE_SEARCH : 00583 EXCEPTION_EXECUTE_HANDLER ) { 00584 00585 SET_LAST_STATUS( GetExceptionCode() ); 00586 00587 ReturnValue = NULL; 00588 } 00589 00590 } finally { 00591 00592 if (LockAcquired) { 00593 00594 RtlReleaseLockRoutine( Heap->LockVariable ); 00595 } 00596 } 00597 00598 return ReturnValue; 00599 } 00600 00601 00602 PVOID 00603 RtlDebugReAllocateHeap ( 00604 IN PVOID HeapHandle, 00605 IN ULONG Flags, 00606 IN PVOID BaseAddress, 00607 IN SIZE_T Size 00608 ) 00609 00610 /*++ 00611 00612 Routine Description: 00613 00614 Arguments: 00615 00616 Return Value: 00617 00618 --*/ 00619 00620 { 00621 PHEAP Heap = (PHEAP)HeapHandle; 00622 SIZE_T AllocationSize; 00623 PHEAP_ENTRY BusyBlock; 00624 PHEAP_ENTRY_EXTRA ExtraStuff; 00625 BOOLEAN LockAcquired = FALSE; 00626 PVOID ReturnValue = NULL; 00627 USHORT TagIndex; 00628 00629 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00630 RtlpDebugPageHeapReAllocate( HeapHandle, Flags, BaseAddress, Size )); 00631 00632 try { 00633 00634 try { 00635 00636 // 00637 // Validate that HeapAddress points to a HEAP structure. 00638 // 00639 00640 if (!RtlpCheckHeapSignature( Heap, "RtlReAllocateHeap" )) { 00641 00642 ReturnValue = NULL; 00643 leave; 00644 } 00645 00646 Flags |= Heap->ForceFlags | HEAP_SETTABLE_USER_VALUE | HEAP_SKIP_VALIDATION_CHECKS; 00647 00648 // 00649 // Verify that the size did not wrap or exceed the limit for this heap. 00650 // 00651 00652 AllocationSize = (((Size ? Size : 1) + Heap->AlignRound) & Heap->AlignMask) + 00653 sizeof( HEAP_ENTRY_EXTRA ); 00654 00655 if (AllocationSize < Size || AllocationSize > Heap->MaximumAllocationSize) { 00656 00657 HeapDebugPrint(( "Invalid allocation size - %lx (exceeded %x)\n", 00658 Size, 00659 Heap->MaximumAllocationSize )); 00660 00661 HeapDebugBreak( NULL ); 00662 00663 ReturnValue = NULL; 00664 leave; 00665 } 00666 00667 // 00668 // Lock the heap 00669 // 00670 00671 if (!(Flags & HEAP_NO_SERIALIZE)) { 00672 00673 RtlAcquireLockRoutine( Heap->LockVariable ); 00674 00675 LockAcquired = TRUE; 00676 00677 Flags |= HEAP_NO_SERIALIZE; 00678 } 00679 00680 RtlpValidateHeap( Heap, FALSE ); 00681 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00682 00683 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlReAllocateHeap" )) { 00684 00685 if ((ULONG_PTR)BaseAddress == RtlpHeapStopOn.ReAllocAddress) { 00686 00687 HeapDebugPrint(( "About to reallocate block at %lx to 0x%x bytes\n", 00688 RtlpHeapStopOn.ReAllocAddress, 00689 Size )); 00690 00691 HeapDebugBreak( NULL ); 00692 00693 } else if (IS_HEAP_TAGGING_ENABLED() && RtlpHeapStopOn.ReAllocTag.HeapAndTagIndex != 0) { 00694 00695 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00696 00697 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00698 TagIndex = ExtraStuff->TagIndex; 00699 00700 } else { 00701 00702 TagIndex = BusyBlock->SmallTagIndex; 00703 } 00704 00705 if ((TagIndex != 0) && 00706 (TagIndex == RtlpHeapStopOn.ReAllocTag.TagIndex) && 00707 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.ReAllocTag.HeapIndex)) { 00708 00709 HeapDebugPrint(( "About to rellocate block at %lx to 0x%x bytes with tag %ws\n", 00710 BaseAddress, 00711 Size, 00712 RtlpGetTagName( Heap, TagIndex ))); 00713 00714 HeapDebugBreak( NULL ); 00715 } 00716 } 00717 00718 ReturnValue = RtlReAllocateHeap( HeapHandle, Flags, BaseAddress, Size ); 00719 00720 if (ReturnValue != NULL) { 00721 00722 BusyBlock = (PHEAP_ENTRY)ReturnValue - 1; 00723 00724 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00725 00726 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00727 00728 #if i386 00729 00730 if (Heap->Flags & HEAP_CAPTURE_STACK_BACKTRACES) { 00731 00732 ExtraStuff->AllocatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 00733 00734 } else { 00735 00736 ExtraStuff->AllocatorBackTraceIndex = 0; 00737 } 00738 00739 #endif // i386 00740 00741 TagIndex = ExtraStuff->TagIndex; 00742 00743 } else { 00744 00745 TagIndex = BusyBlock->SmallTagIndex; 00746 } 00747 } 00748 00749 RtlpValidateHeapHeaders( Heap, TRUE ); 00750 RtlpValidateHeap( Heap, FALSE ); 00751 } 00752 00753 if (ReturnValue != NULL) { 00754 00755 if ((ULONG_PTR)ReturnValue == RtlpHeapStopOn.ReAllocAddress) { 00756 00757 HeapDebugPrint(( "Just reallocated block at %lx to 0x%x bytes\n", 00758 RtlpHeapStopOn.ReAllocAddress, 00759 Size )); 00760 00761 HeapDebugBreak( NULL ); 00762 00763 } else if ((IS_HEAP_TAGGING_ENABLED()) && 00764 (TagIndex == RtlpHeapStopOn.ReAllocTag.TagIndex) && 00765 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.ReAllocTag.HeapIndex)) { 00766 00767 HeapDebugPrint(( "Just reallocated block at %lx to 0x%x bytes with tag %ws\n", 00768 ReturnValue, 00769 Size, 00770 RtlpGetTagName( Heap, TagIndex ))); 00771 00772 HeapDebugBreak( NULL ); 00773 } 00774 } 00775 00776 } except( GetExceptionCode() == STATUS_NO_MEMORY ? EXCEPTION_CONTINUE_SEARCH : 00777 EXCEPTION_EXECUTE_HANDLER ) { 00778 00779 SET_LAST_STATUS( GetExceptionCode() ); 00780 00781 ReturnValue = NULL; 00782 } 00783 00784 } finally { 00785 00786 if (LockAcquired) { 00787 00788 RtlReleaseLockRoutine( Heap->LockVariable ); 00789 } 00790 } 00791 00792 return ReturnValue; 00793 } 00794 00795 00796 BOOLEAN 00797 RtlDebugFreeHeap ( 00798 IN PVOID HeapHandle, 00799 IN ULONG Flags, 00800 IN PVOID BaseAddress 00801 ) 00802 00803 /*++ 00804 00805 Routine Description: 00806 00807 Arguments: 00808 00809 Return Value: 00810 00811 --*/ 00812 00813 { 00814 PHEAP Heap = (PHEAP)HeapHandle; 00815 PHEAP_ENTRY BusyBlock; 00816 PHEAP_ENTRY_EXTRA ExtraStuff; 00817 SIZE_T Size; 00818 BOOLEAN Result = FALSE; 00819 BOOLEAN LockAcquired = FALSE; 00820 USHORT TagIndex; 00821 00822 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00823 RtlpDebugPageHeapFree( HeapHandle, Flags, BaseAddress )); 00824 00825 try { 00826 00827 try { 00828 00829 // 00830 // Validate that HeapAddress points to a HEAP structure. 00831 // 00832 00833 if (!RtlpCheckHeapSignature( Heap, "RtlFreeHeap" )) { 00834 00835 Result = FALSE; 00836 leave; 00837 } 00838 00839 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 00840 00841 // 00842 // Lock the heap 00843 // 00844 00845 if (!(Flags & HEAP_NO_SERIALIZE)) { 00846 00847 RtlAcquireLockRoutine( Heap->LockVariable ); 00848 00849 LockAcquired = TRUE; 00850 00851 Flags |= HEAP_NO_SERIALIZE; 00852 } 00853 00854 RtlpValidateHeap( Heap, FALSE ); 00855 00856 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00857 Size = BusyBlock->Size << HEAP_GRANULARITY_SHIFT; 00858 00859 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlFreeHeap" )) { 00860 00861 if ((ULONG_PTR)BaseAddress == RtlpHeapStopOn.FreeAddress) { 00862 00863 HeapDebugPrint(( "About to free block at %lx\n", 00864 RtlpHeapStopOn.FreeAddress )); 00865 00866 HeapDebugBreak( NULL ); 00867 00868 } else if ((IS_HEAP_TAGGING_ENABLED()) && (RtlpHeapStopOn.FreeTag.HeapAndTagIndex != 0)) { 00869 00870 if (BusyBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 00871 00872 ExtraStuff = RtlpGetExtraStuffPointer( BusyBlock ); 00873 00874 TagIndex = ExtraStuff->TagIndex; 00875 00876 } else { 00877 00878 TagIndex = BusyBlock->SmallTagIndex; 00879 } 00880 00881 if ((TagIndex != 0) && 00882 (TagIndex == RtlpHeapStopOn.FreeTag.TagIndex) && 00883 (Heap->ProcessHeapsListIndex == RtlpHeapStopOn.FreeTag.HeapIndex)) { 00884 00885 HeapDebugPrint(( "About to free block at %lx with tag %ws\n", 00886 BaseAddress, 00887 RtlpGetTagName( Heap, TagIndex ))); 00888 00889 HeapDebugBreak( NULL ); 00890 } 00891 } 00892 00893 Result = RtlFreeHeapSlowly( HeapHandle, Flags, BaseAddress ); 00894 00895 RtlpValidateHeapHeaders( Heap, TRUE ); 00896 RtlpValidateHeap( Heap, FALSE ); 00897 } 00898 00899 } except( EXCEPTION_EXECUTE_HANDLER ) { 00900 00901 SET_LAST_STATUS( GetExceptionCode() ); 00902 00903 Result = FALSE; 00904 } 00905 00906 } finally { 00907 00908 if (LockAcquired) { 00909 00910 RtlReleaseLockRoutine( Heap->LockVariable ); 00911 } 00912 } 00913 00914 return Result; 00915 } 00916 00917 00918 BOOLEAN 00919 RtlDebugGetUserInfoHeap ( 00920 IN PVOID HeapHandle, 00921 IN ULONG Flags, 00922 IN PVOID BaseAddress, 00923 OUT PVOID *UserValue OPTIONAL, 00924 OUT PULONG UserFlags OPTIONAL 00925 ) 00926 00927 /*++ 00928 00929 Routine Description: 00930 00931 Arguments: 00932 00933 Return Value: 00934 00935 --*/ 00936 00937 { 00938 PHEAP Heap = (PHEAP)HeapHandle; 00939 PHEAP_ENTRY BusyBlock; 00940 BOOLEAN Result = FALSE; 00941 BOOLEAN LockAcquired = FALSE; 00942 00943 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 00944 RtlpDebugPageHeapGetUserInfo( HeapHandle, Flags, BaseAddress, UserValue, UserFlags )); 00945 00946 try { 00947 00948 try { 00949 00950 // 00951 // Validate that HeapAddress points to a HEAP structure. 00952 // 00953 00954 if (!RtlpCheckHeapSignature( Heap, "RtlGetUserInfoHeap" )) { 00955 00956 Result = FALSE; 00957 leave; 00958 } 00959 00960 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 00961 00962 // 00963 // Lock the heap 00964 // 00965 00966 if (!(Flags & HEAP_NO_SERIALIZE)) { 00967 00968 RtlAcquireLockRoutine( Heap->LockVariable ); 00969 00970 LockAcquired = TRUE; 00971 00972 Flags |= HEAP_NO_SERIALIZE; 00973 } 00974 00975 RtlpValidateHeap( Heap, FALSE ); 00976 00977 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 00978 00979 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlGetUserInfoHeap" )) { 00980 00981 Result = RtlGetUserInfoHeap( HeapHandle, Flags, BaseAddress, UserValue, UserFlags ); 00982 } 00983 00984 } except( EXCEPTION_EXECUTE_HANDLER ) { 00985 00986 SET_LAST_STATUS( GetExceptionCode() ); 00987 } 00988 00989 } finally { 00990 00991 if (LockAcquired) { 00992 00993 RtlReleaseLockRoutine( Heap->LockVariable ); 00994 } 00995 } 00996 00997 return Result; 00998 } 00999 01000 01001 BOOLEAN 01002 RtlDebugSetUserValueHeap ( 01003 IN PVOID HeapHandle, 01004 IN ULONG Flags, 01005 IN PVOID BaseAddress, 01006 IN PVOID UserValue 01007 ) 01008 01009 /*++ 01010 01011 Routine Description: 01012 01013 Arguments: 01014 01015 Return Value: 01016 01017 --*/ 01018 01019 { 01020 PHEAP Heap = (PHEAP)HeapHandle; 01021 PHEAP_ENTRY BusyBlock; 01022 BOOLEAN Result = FALSE; 01023 BOOLEAN LockAcquired = FALSE; 01024 01025 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01026 RtlpDebugPageHeapSetUserValue( HeapHandle, Flags, BaseAddress, UserValue )); 01027 01028 try { 01029 01030 try { 01031 01032 // 01033 // Validate that HeapAddress points to a HEAP structure. 01034 // 01035 01036 if (!RtlpCheckHeapSignature( Heap, "RtlSetUserValueHeap" )) { 01037 01038 Result = FALSE; 01039 leave; 01040 } 01041 01042 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01043 01044 // 01045 // Lock the heap 01046 // 01047 01048 if (!(Flags & HEAP_NO_SERIALIZE)) { 01049 01050 RtlAcquireLockRoutine( Heap->LockVariable ); 01051 01052 LockAcquired = TRUE; 01053 01054 Flags |= HEAP_NO_SERIALIZE; 01055 } 01056 01057 RtlpValidateHeap( Heap, FALSE ); 01058 01059 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01060 01061 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlSetUserValueHeap" )) { 01062 01063 Result = RtlSetUserValueHeap( HeapHandle, Flags, BaseAddress, UserValue ); 01064 01065 RtlpValidateHeap( Heap, FALSE ); 01066 } 01067 01068 } except( EXCEPTION_EXECUTE_HANDLER ) { 01069 01070 SET_LAST_STATUS( GetExceptionCode() ); 01071 } 01072 01073 } finally { 01074 01075 if (LockAcquired) { 01076 01077 RtlReleaseLockRoutine( Heap->LockVariable ); 01078 } 01079 } 01080 01081 return Result; 01082 } 01083 01084 01085 BOOLEAN 01086 RtlDebugSetUserFlagsHeap ( 01087 IN PVOID HeapHandle, 01088 IN ULONG Flags, 01089 IN PVOID BaseAddress, 01090 IN ULONG UserFlagsReset, 01091 IN ULONG UserFlagsSet 01092 ) 01093 01094 /*++ 01095 01096 Routine Description: 01097 01098 Arguments: 01099 01100 Return Value: 01101 01102 --*/ 01103 01104 { 01105 PHEAP Heap = (PHEAP)HeapHandle; 01106 PHEAP_ENTRY BusyBlock; 01107 BOOLEAN Result = FALSE; 01108 BOOLEAN LockAcquired = FALSE; 01109 01110 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01111 RtlpDebugPageHeapSetUserFlags( HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet )); 01112 01113 if ((UserFlagsReset & ~HEAP_SETTABLE_USER_FLAGS) || 01114 (UserFlagsSet & ~HEAP_SETTABLE_USER_FLAGS)) { 01115 01116 return FALSE; 01117 } 01118 01119 try { 01120 01121 try { 01122 01123 // 01124 // Validate that HeapAddress points to a HEAP structure. 01125 // 01126 01127 if (!RtlpCheckHeapSignature( Heap, "RtlSetUserFlagsHeap" )) { 01128 01129 Result = FALSE; 01130 leave; 01131 } 01132 01133 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01134 01135 // 01136 // Lock the heap 01137 // 01138 01139 if (!(Flags & HEAP_NO_SERIALIZE)) { 01140 01141 RtlAcquireLockRoutine( Heap->LockVariable ); 01142 01143 LockAcquired = TRUE; 01144 01145 Flags |= HEAP_NO_SERIALIZE; 01146 } 01147 01148 RtlpValidateHeap( Heap, FALSE ); 01149 01150 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01151 01152 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlSetUserFlagsHeap" )) { 01153 01154 Result = RtlSetUserFlagsHeap( HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet ); 01155 01156 RtlpValidateHeap( Heap, FALSE ); 01157 } 01158 01159 } except( EXCEPTION_EXECUTE_HANDLER ) { 01160 01161 SET_LAST_STATUS( GetExceptionCode() ); 01162 } 01163 01164 } finally { 01165 01166 if (LockAcquired) { 01167 01168 RtlReleaseLockRoutine( Heap->LockVariable ); 01169 } 01170 } 01171 01172 return Result; 01173 } 01174 01175 01176 SIZE_T 01177 RtlDebugSizeHeap ( 01178 IN PVOID HeapHandle, 01179 IN ULONG Flags, 01180 IN PVOID BaseAddress 01181 ) 01182 01183 /*++ 01184 01185 Routine Description: 01186 01187 Arguments: 01188 01189 Return Value: 01190 01191 --*/ 01192 01193 { 01194 PHEAP Heap = (PHEAP)HeapHandle; 01195 PHEAP_ENTRY BusyBlock; 01196 BOOLEAN LockAcquired = FALSE; 01197 SIZE_T BusySize; 01198 01199 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01200 RtlpDebugPageHeapSize( HeapHandle, Flags, BaseAddress )); 01201 01202 BusySize = 0xFFFFFFFF; 01203 01204 try { 01205 01206 try { 01207 01208 // 01209 // Validate that HeapAddress points to a HEAP structure. 01210 // 01211 01212 if (!RtlpCheckHeapSignature( Heap, "RtlSizeHeap" )) { 01213 01214 BusySize = FALSE; 01215 leave; 01216 } 01217 01218 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01219 01220 // 01221 // Lock the heap 01222 // 01223 01224 if (!(Flags & HEAP_NO_SERIALIZE)) { 01225 01226 RtlAcquireLockRoutine( Heap->LockVariable ); 01227 01228 Flags |= HEAP_NO_SERIALIZE; 01229 01230 LockAcquired = TRUE; 01231 } 01232 01233 RtlpValidateHeap( Heap, FALSE ); 01234 01235 BusyBlock = (PHEAP_ENTRY)BaseAddress - 1; 01236 01237 if (RtlpValidateHeapEntry( Heap, BusyBlock, "RtlSizeHeap" )) { 01238 01239 BusySize = RtlSizeHeap( HeapHandle, Flags, BaseAddress ); 01240 } 01241 01242 } except( EXCEPTION_EXECUTE_HANDLER ) { 01243 01244 SET_LAST_STATUS( GetExceptionCode() ); 01245 } 01246 01247 } finally { 01248 01249 if (LockAcquired) { 01250 01251 RtlReleaseLockRoutine( Heap->LockVariable ); 01252 } 01253 } 01254 01255 return BusySize; 01256 } 01257 01258 01259 SIZE_T 01260 RtlDebugCompactHeap ( 01261 IN PVOID HeapHandle, 01262 IN ULONG Flags 01263 ) 01264 01265 /*++ 01266 01267 Routine Description: 01268 01269 Arguments: 01270 01271 Return Value: 01272 01273 --*/ 01274 01275 { 01276 PHEAP Heap = (PHEAP)HeapHandle; 01277 BOOLEAN LockAcquired = FALSE; 01278 SIZE_T LargestFreeSize; 01279 01280 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01281 RtlpDebugPageHeapCompact( HeapHandle, Flags )); 01282 01283 LargestFreeSize = 0; 01284 01285 try { 01286 01287 try { 01288 01289 // 01290 // Validate that HeapAddress points to a HEAP structure. 01291 // 01292 01293 if (!RtlpCheckHeapSignature( Heap, "RtlCompactHeap" )) { 01294 01295 LargestFreeSize = 0; 01296 leave; 01297 } 01298 01299 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01300 01301 // 01302 // Lock the heap 01303 // 01304 01305 if (!(Flags & HEAP_NO_SERIALIZE)) { 01306 01307 RtlAcquireLockRoutine( Heap->LockVariable ); 01308 01309 LockAcquired = TRUE; 01310 01311 Flags |= HEAP_NO_SERIALIZE; 01312 } 01313 01314 RtlpValidateHeap( Heap, FALSE ); 01315 01316 LargestFreeSize = RtlCompactHeap( HeapHandle, Flags ); 01317 01318 RtlpValidateHeapHeaders( Heap, TRUE ); 01319 01320 } except( EXCEPTION_EXECUTE_HANDLER ) { 01321 01322 SET_LAST_STATUS( GetExceptionCode() ); 01323 } 01324 01325 } finally { 01326 01327 if (LockAcquired) { 01328 01329 RtlReleaseLockRoutine( Heap->LockVariable ); 01330 } 01331 } 01332 01333 return LargestFreeSize; 01334 } 01335 01336 01337 NTSTATUS 01338 RtlDebugZeroHeap ( 01339 IN PVOID HeapHandle, 01340 IN ULONG Flags 01341 ) 01342 01343 /*++ 01344 01345 Routine Description: 01346 01347 Arguments: 01348 01349 Return Value: 01350 01351 --*/ 01352 01353 { 01354 NTSTATUS Status; 01355 PHEAP Heap = (PHEAP)HeapHandle; 01356 BOOLEAN LockAcquired = FALSE; 01357 SIZE_T LargestFreeSize; 01358 01359 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01360 RtlpDebugPageHeapZero( HeapHandle, Flags )); 01361 01362 Status = STATUS_SUCCESS; 01363 LargestFreeSize = 0; 01364 01365 try { 01366 01367 try { 01368 01369 // 01370 // Validate that HeapAddress points to a HEAP structure. 01371 // 01372 01373 if (!RtlpCheckHeapSignature( Heap, "RtlZeroHeap" )) { 01374 01375 Status = STATUS_INVALID_PARAMETER; 01376 leave; 01377 } 01378 01379 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01380 01381 // 01382 // Lock the heap 01383 // 01384 01385 if (!(Flags & HEAP_NO_SERIALIZE)) { 01386 01387 RtlAcquireLockRoutine( Heap->LockVariable ); 01388 01389 LockAcquired = TRUE; 01390 01391 Flags |= HEAP_NO_SERIALIZE; 01392 } 01393 01394 if (!RtlpValidateHeap( Heap, FALSE )) { 01395 01396 Status = STATUS_INVALID_PARAMETER; 01397 01398 } else { 01399 01400 Status = RtlZeroHeap( HeapHandle, Flags ); 01401 } 01402 01403 } except( EXCEPTION_EXECUTE_HANDLER ) { 01404 01405 Status = GetExceptionCode(); 01406 } 01407 01408 } finally { 01409 01410 if (LockAcquired) { 01411 01412 RtlReleaseLockRoutine( Heap->LockVariable ); 01413 } 01414 } 01415 01416 return Status; 01417 } 01418 01419 01420 NTSTATUS 01421 RtlDebugCreateTagHeap ( 01422 IN PVOID HeapHandle, 01423 IN ULONG Flags, 01424 IN PWSTR TagPrefix OPTIONAL, 01425 IN PWSTR TagNames 01426 ) 01427 01428 /*++ 01429 01430 Routine Description: 01431 01432 Arguments: 01433 01434 Return Value: 01435 01436 --*/ 01437 01438 { 01439 PHEAP Heap = (PHEAP)HeapHandle; 01440 BOOLEAN LockAcquired = FALSE; 01441 ULONG TagIndex; 01442 01443 TagIndex = 0; 01444 01445 try { 01446 01447 try { 01448 01449 // 01450 // Validate that HeapAddress points to a HEAP structure. 01451 // 01452 01453 if (RtlpCheckHeapSignature( Heap, "RtlCreateTagHeap" )) { 01454 01455 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01456 01457 // 01458 // Lock the heap 01459 // 01460 01461 if (!(Flags & HEAP_NO_SERIALIZE)) { 01462 01463 RtlAcquireLockRoutine( Heap->LockVariable ); 01464 01465 LockAcquired = TRUE; 01466 01467 Flags |= HEAP_NO_SERIALIZE; 01468 } 01469 01470 if (RtlpValidateHeap( Heap, FALSE )) { 01471 01472 TagIndex = RtlCreateTagHeap( HeapHandle, Flags, TagPrefix, TagNames ); 01473 } 01474 01475 RtlpValidateHeapHeaders( Heap, TRUE ); 01476 } 01477 01478 } except( EXCEPTION_EXECUTE_HANDLER ) { 01479 01480 SET_LAST_STATUS( GetExceptionCode() ); 01481 } 01482 01483 } finally { 01484 01485 if (LockAcquired) { 01486 01487 RtlReleaseLockRoutine( Heap->LockVariable ); 01488 } 01489 } 01490 01491 return TagIndex; 01492 } 01493 01494 01495 NTSYSAPI 01496 PWSTR 01497 NTAPI 01498 RtlDebugQueryTagHeap ( 01499 IN PVOID HeapHandle, 01500 IN ULONG Flags, 01501 IN USHORT TagIndex, 01502 IN BOOLEAN ResetCounters, 01503 OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL 01504 ) 01505 01506 /*++ 01507 01508 Routine Description: 01509 01510 Arguments: 01511 01512 Return Value: 01513 01514 --*/ 01515 01516 { 01517 PHEAP Heap = (PHEAP)HeapHandle; 01518 BOOLEAN LockAcquired = FALSE; 01519 PWSTR Result; 01520 01521 Result = NULL; 01522 01523 try { 01524 01525 try { 01526 01527 // 01528 // Validate that HeapAddress points to a HEAP structure. 01529 // 01530 01531 if (RtlpCheckHeapSignature( Heap, "RtlQueryTagHeap" )) { 01532 01533 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01534 01535 // 01536 // Lock the heap 01537 // 01538 01539 if (!(Flags & HEAP_NO_SERIALIZE)) { 01540 01541 RtlAcquireLockRoutine( Heap->LockVariable ); 01542 01543 LockAcquired = TRUE; 01544 01545 Flags |= HEAP_NO_SERIALIZE; 01546 } 01547 01548 if (RtlpValidateHeap( Heap, FALSE )) { 01549 01550 Result = RtlQueryTagHeap( HeapHandle, Flags, TagIndex, ResetCounters, TagInfo ); 01551 } 01552 } 01553 01554 } except( EXCEPTION_EXECUTE_HANDLER ) { 01555 01556 SET_LAST_STATUS( GetExceptionCode() ); 01557 } 01558 01559 } finally { 01560 01561 if (LockAcquired) { 01562 01563 RtlReleaseLockRoutine( Heap->LockVariable ); 01564 } 01565 } 01566 01567 return Result; 01568 } 01569 01570 01571 NTSTATUS 01572 RtlDebugUsageHeap ( 01573 IN PVOID HeapHandle, 01574 IN ULONG Flags, 01575 IN OUT PRTL_HEAP_USAGE Usage 01576 ) 01577 01578 /*++ 01579 01580 Routine Description: 01581 01582 Arguments: 01583 01584 Return Value: 01585 01586 --*/ 01587 01588 { 01589 PHEAP Heap = (PHEAP)HeapHandle; 01590 NTSTATUS Status; 01591 BOOLEAN LockAcquired = FALSE; 01592 01593 IF_DEBUG_PAGE_HEAP_THEN_RETURN( HeapHandle, 01594 RtlpDebugPageHeapUsage( HeapHandle, Flags, Usage )); 01595 01596 Status = STATUS_SUCCESS; 01597 01598 try { 01599 01600 try { 01601 01602 // 01603 // Validate that HeapAddress points to a HEAP structure. 01604 // 01605 01606 if (!RtlpCheckHeapSignature( Heap, "RtlUsageHeap" )) { 01607 01608 Status = STATUS_INVALID_PARAMETER; 01609 leave; 01610 } 01611 01612 Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS; 01613 01614 // 01615 // Lock the heap 01616 // 01617 01618 if (!(Flags & HEAP_NO_SERIALIZE)) { 01619 01620 RtlAcquireLockRoutine( Heap->LockVariable ); 01621 01622 LockAcquired = TRUE; 01623 01624 Flags |= HEAP_NO_SERIALIZE; 01625 } 01626 01627 if (!RtlpValidateHeap( Heap, FALSE )) { 01628 01629 Status = STATUS_INVALID_PARAMETER; 01630 01631 } else { 01632 01633 Status = RtlUsageHeap( HeapHandle, Flags, Usage ); 01634 } 01635 01636 } except( EXCEPTION_EXECUTE_HANDLER ) { 01637 01638 Status = GetExceptionCode(); 01639 } 01640 01641 } finally { 01642 01643 if (LockAcquired) { 01644 01645 RtlReleaseLockRoutine( Heap->LockVariable ); 01646 } 01647 } 01648 01649 return Status; 01650 } 01651 01652 01653 BOOLEAN 01654 RtlDebugWalkHeap ( 01655 IN PVOID HeapHandle, 01656 IN OUT PRTL_HEAP_WALK_ENTRY Entry 01657 ) 01658 01659 /*++ 01660 01661 Routine Description: 01662 01663 Arguments: 01664 01665 Return Value: 01666 01667 --*/ 01668 01669 { 01670 PHEAP Heap = (PHEAP)HeapHandle; 01671 BOOLEAN Result; 01672 01673 // 01674 // Assumed the caller has serialized via RtlLockHeap or their own locking mechanism. 01675 // 01676 01677 Result = FALSE; 01678 01679 try { 01680 01681 if (RtlpCheckHeapSignature( Heap, "RtlWalkHeap" )) { 01682 01683 Result = RtlpValidateHeap( Heap, FALSE ); 01684 } 01685 01686 } except( EXCEPTION_EXECUTE_HANDLER ) { 01687 01688 SET_LAST_STATUS( GetExceptionCode() ); 01689 } 01690 01691 return Result; 01692 } 01693 01694 01695 BOOLEAN 01696 RtlpValidateHeapEntry ( 01697 IN PHEAP Heap, 01698 IN PHEAP_ENTRY BusyBlock, 01699 IN PCHAR Reason 01700 ) 01701 01702 /*++ 01703 01704 Routine Description: 01705 01706 Arguments: 01707 01708 Return Value: 01709 01710 --*/ 01711 01712 { 01713 PHEAP_SEGMENT Segment; 01714 UCHAR SegmentIndex; 01715 BOOLEAN Result; 01716 01717 if ((BusyBlock == NULL) 01718 01719 || 01720 01721 ((ULONG_PTR)BusyBlock & (HEAP_GRANULARITY-1)) 01722 01723 || 01724 01725 ((BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) && 01726 ((ULONG_PTR)BusyBlock & (PAGE_SIZE-1)) != FIELD_OFFSET( HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock )) 01727 01728 || 01729 01730 (!(BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) && 01731 ((BusyBlock->SegmentIndex >= HEAP_MAXIMUM_SEGMENTS) || 01732 !(Segment = Heap->Segments[ BusyBlock->SegmentIndex ]) || 01733 (BusyBlock < Segment->FirstEntry) || 01734 (BusyBlock >= Segment->LastValidEntry))) 01735 01736 || 01737 01738 !(BusyBlock->Flags & HEAP_ENTRY_BUSY) 01739 01740 || 01741 01742 ((BusyBlock->Flags & HEAP_ENTRY_FILL_PATTERN) && !RtlpCheckBusyBlockTail( BusyBlock ))) { 01743 01744 InvalidBlock: 01745 01746 HeapDebugPrint(( "Invalid Address specified to %s( %lx, %lx )\n", 01747 Reason, 01748 Heap, 01749 BusyBlock + 1 )); 01750 01751 HeapDebugBreak( BusyBlock ); 01752 01753 return FALSE; 01754 01755 } else { 01756 01757 if (BusyBlock->Flags & HEAP_ENTRY_VIRTUAL_ALLOC) { 01758 01759 Result = TRUE; 01760 01761 } else { 01762 01763 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 01764 01765 Segment = Heap->Segments[ SegmentIndex ]; 01766 01767 if (Segment) { 01768 01769 if ((BusyBlock >= Segment->FirstEntry) && 01770 (BusyBlock < Segment->LastValidEntry)) { 01771 01772 Result = TRUE; 01773 break; 01774 } 01775 } 01776 } 01777 } 01778 01779 if (!Result) { 01780 01781 goto InvalidBlock; 01782 } 01783 01784 return TRUE; 01785 } 01786 } 01787 01788 01789 BOOLEAN 01790 RtlpValidateHeapSegment ( 01791 IN PHEAP Heap, 01792 IN PHEAP_SEGMENT Segment, 01793 IN UCHAR SegmentIndex, 01794 IN OUT PULONG CountOfFreeBlocks, 01795 IN OUT PSIZE_T TotalFreeSize, 01796 OUT PVOID *BadAddress, 01797 IN OUT PSIZE_T ComputedTagEntries, 01798 IN OUT PSIZE_T ComputedPseudoTagEntries 01799 ) 01800 01801 /*++ 01802 01803 Routine Description: 01804 01805 Arguments: 01806 01807 Return Value: 01808 01809 --*/ 01810 01811 { 01812 PHEAP_ENTRY CurrentBlock, PreviousBlock; 01813 SIZE_T Size; 01814 USHORT PreviousSize, TagIndex; 01815 PHEAP_UNCOMMMTTED_RANGE UnCommittedRange; 01816 PHEAP_ENTRY_EXTRA ExtraStuff; 01817 ULONG NumberOfUnCommittedPages; 01818 ULONG NumberOfUnCommittedRanges; 01819 01820 RTL_PAGED_CODE(); 01821 01822 NumberOfUnCommittedPages = 0; 01823 NumberOfUnCommittedRanges = 0; 01824 01825 UnCommittedRange = Segment->UnCommittedRanges; 01826 01827 if (Segment->BaseAddress == Heap) { 01828 01829 CurrentBlock = &Heap->Entry; 01830 01831 } else { 01832 01833 CurrentBlock = &Segment->Entry; 01834 } 01835 01836 while (CurrentBlock < Segment->LastValidEntry) { 01837 01838 *BadAddress = CurrentBlock; 01839 01840 if ((UnCommittedRange != NULL) && 01841 ((ULONG_PTR)CurrentBlock >= UnCommittedRange->Address)) { 01842 01843 HeapDebugPrint(( "Heap entry %lx is beyond uncommited range [%x .. %x)\n", 01844 CurrentBlock, 01845 UnCommittedRange->Address, 01846 (PCHAR)UnCommittedRange->Address + UnCommittedRange->Size )); 01847 01848 return FALSE; 01849 } 01850 01851 PreviousSize = 0; 01852 01853 while (CurrentBlock < Segment->LastValidEntry) { 01854 01855 *BadAddress = CurrentBlock; 01856 01857 if (PreviousSize != CurrentBlock->PreviousSize) { 01858 01859 HeapDebugPrint(( "Heap entry %lx has incorrect PreviousSize field (%04x instead of %04x)\n", 01860 CurrentBlock, CurrentBlock->PreviousSize, PreviousSize )); 01861 01862 return FALSE; 01863 } 01864 01865 PreviousSize = CurrentBlock->Size; 01866 Size = (ULONG_PTR)CurrentBlock->Size << HEAP_GRANULARITY_SHIFT; 01867 01868 if (CurrentBlock->Flags & HEAP_ENTRY_BUSY) { 01869 01870 if (ComputedTagEntries != NULL) { 01871 01872 if (CurrentBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) { 01873 01874 ExtraStuff = RtlpGetExtraStuffPointer( CurrentBlock ); 01875 TagIndex = ExtraStuff->TagIndex; 01876 01877 } else { 01878 01879 TagIndex = CurrentBlock->SmallTagIndex; 01880 } 01881 01882 if (TagIndex != 0) { 01883 01884 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 01885 01886 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG; 01887 01888 if (TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) { 01889 01890 ComputedPseudoTagEntries[ TagIndex ] += CurrentBlock->Size; 01891 } 01892 01893 } else if (TagIndex & HEAP_GLOBAL_TAG) { 01894 01895 // 01896 // Ignore these since they are global across more than 01897 // one heap. 01898 // 01899 01900 } else if (TagIndex < Heap->NextAvailableTagIndex) { 01901 01902 ComputedTagEntries[ TagIndex ] += CurrentBlock->Size; 01903 } 01904 } 01905 } 01906 01907 if (CurrentBlock->Flags & HEAP_ENTRY_FILL_PATTERN) { 01908 01909 if (!RtlpCheckBusyBlockTail( CurrentBlock )) { 01910 01911 return FALSE; 01912 } 01913 } 01914 01915 } else { 01916 01917 *CountOfFreeBlocks += 1; 01918 *TotalFreeSize += CurrentBlock->Size; 01919 01920 if ((Heap->Flags & HEAP_FREE_CHECKING_ENABLED) && 01921 (CurrentBlock->Flags & HEAP_ENTRY_FILL_PATTERN)) { 01922 01923 SIZE_T cb, cbEqual; 01924 01925 cb = Size - sizeof( HEAP_FREE_ENTRY ); 01926 01927 if ((CurrentBlock->Flags & HEAP_ENTRY_EXTRA_PRESENT) && 01928 (cb > sizeof( HEAP_FREE_ENTRY_EXTRA ))) { 01929 01930 cb -= sizeof( HEAP_FREE_ENTRY_EXTRA ); 01931 } 01932 01933 cbEqual = RtlCompareMemoryUlong( (PCHAR)((PHEAP_FREE_ENTRY)CurrentBlock + 1), 01934 cb, 01935 FREE_HEAP_FILL ); 01936 01937 if (cbEqual != cb) { 01938 01939 HeapDebugPrint(( "Free Heap block %lx modified at %lx after it was freed\n", 01940 CurrentBlock, 01941 (PCHAR)(CurrentBlock + 1) + cbEqual )); 01942 01943 return FALSE; 01944 } 01945 } 01946 } 01947 01948 if (CurrentBlock->SegmentIndex != SegmentIndex) { 01949 01950 HeapDebugPrint(( "Heap block at %lx has incorrect segment index (%x)\n", 01951 CurrentBlock, 01952 SegmentIndex )); 01953 01954 return FALSE; 01955 } 01956 01957 if (CurrentBlock->Flags & HEAP_ENTRY_LAST_ENTRY) { 01958 01959 CurrentBlock = (PHEAP_ENTRY)((PCHAR)CurrentBlock + Size); 01960 01961 if (UnCommittedRange == NULL) { 01962 01963 if (CurrentBlock != Segment->LastValidEntry) { 01964 01965 HeapDebugPrint(( "Heap block at %lx is not last block in segment (%x)\n", 01966 CurrentBlock, 01967 Segment->LastValidEntry )); 01968 01969 return FALSE; 01970 } 01971 01972 } else if ((ULONG_PTR)CurrentBlock != UnCommittedRange->Address) { 01973 01974 HeapDebugPrint(( "Heap block at %lx does not match address of next uncommitted address (%x)\n", 01975 CurrentBlock, 01976 UnCommittedRange->Address )); 01977 01978 return FALSE; 01979 01980 } else { 01981 01982 NumberOfUnCommittedPages += (ULONG) (UnCommittedRange->Size / PAGE_SIZE); 01983 NumberOfUnCommittedRanges += 1; 01984 01985 CurrentBlock = (PHEAP_ENTRY) 01986 ((PCHAR)UnCommittedRange->Address + UnCommittedRange->Size); 01987 01988 UnCommittedRange = UnCommittedRange->Next; 01989 } 01990 01991 break; 01992 } 01993 01994 CurrentBlock = (PHEAP_ENTRY)((PCHAR)CurrentBlock + Size); 01995 } 01996 } 01997 01998 *BadAddress = Segment; 01999 02000 if (Segment->NumberOfUnCommittedPages != NumberOfUnCommittedPages) { 02001 02002 HeapDebugPrint(( "Heap Segment at %lx contains invalid NumberOfUnCommittedPages (%x != %x)\n", 02003 Segment, 02004 Segment->NumberOfUnCommittedPages, 02005 NumberOfUnCommittedPages )); 02006 02007 return FALSE; 02008 } 02009 02010 if (Segment->NumberOfUnCommittedRanges != NumberOfUnCommittedRanges) { 02011 02012 HeapDebugPrint(( "Heap Segment at %lx contains invalid NumberOfUnCommittedRanges (%x != %x)\n", 02013 Segment, 02014 Segment->NumberOfUnCommittedRanges, 02015 NumberOfUnCommittedRanges )); 02016 02017 return FALSE; 02018 } 02019 02020 return TRUE; 02021 } 02022 02023 02024 BOOLEAN 02025 RtlpValidateHeap ( 02026 IN PHEAP Heap, 02027 IN BOOLEAN AlwaysValidate 02028 ) 02029 02030 /*++ 02031 02032 Routine Description: 02033 02034 Arguments: 02035 02036 Return Value: 02037 02038 --*/ 02039 02040 { 02041 NTSTATUS Status; 02042 PHEAP_SEGMENT Segment; 02043 PLIST_ENTRY Head, Next; 02044 PHEAP_FREE_ENTRY FreeBlock; 02045 BOOLEAN EmptyFreeList; 02046 ULONG NumberOfFreeListEntries; 02047 ULONG CountOfFreeBlocks; 02048 SIZE_T TotalFreeSize; 02049 SIZE_T Size; 02050 USHORT PreviousSize; 02051 UCHAR SegmentIndex; 02052 PVOID BadAddress; 02053 PSIZE_T ComputedTagEntries = NULL; 02054 PSIZE_T ComputedPseudoTagEntries = NULL; 02055 PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock; 02056 USHORT TagIndex; 02057 02058 RTL_PAGED_CODE(); 02059 02060 BadAddress = Heap; 02061 02062 if (!RtlpValidateHeapHeaders( Heap, FALSE )) { 02063 02064 goto errorExit; 02065 } 02066 02067 if (!AlwaysValidate && !(Heap->Flags & HEAP_VALIDATE_ALL_ENABLED)) { 02068 02069 goto exit; 02070 } 02071 02072 NumberOfFreeListEntries = 0; 02073 Head = &Heap->FreeLists[ 0 ]; 02074 02075 for (Size = 0; Size < HEAP_MAXIMUM_FREELISTS; Size++) { 02076 02077 if (Size != 0) { 02078 02079 EmptyFreeList = (BOOLEAN)(IsListEmpty( Head )); 02080 BadAddress = &Heap->u.FreeListsInUseBytes[ Size / 8 ]; 02081 02082 if (Heap->u.FreeListsInUseBytes[ Size / 8 ] & (1 << (Size & 7)) ) { 02083 02084 if (EmptyFreeList) { 02085 02086 HeapDebugPrint(( "dedicated (%04x) free list empty but marked as non-empty\n", 02087 Size )); 02088 02089 goto errorExit; 02090 } 02091 02092 } else { 02093 02094 if (!EmptyFreeList) { 02095 02096 HeapDebugPrint(( "dedicated (%04x) free list non-empty but marked as empty\n", 02097 Size )); 02098 02099 goto errorExit; 02100 } 02101 } 02102 } 02103 02104 Next = Head->Flink; 02105 PreviousSize = 0; 02106 02107 while (Head != Next) { 02108 02109 FreeBlock = CONTAINING_RECORD( Next, HEAP_FREE_ENTRY, FreeList ); 02110 Next = Next->Flink; 02111 02112 BadAddress = FreeBlock; 02113 02114 if (FreeBlock->Flags & HEAP_ENTRY_BUSY) { 02115 02116 HeapDebugPrint(( "dedicated (%04x) free list element %lx is marked busy\n", 02117 Size, 02118 FreeBlock )); 02119 02120 goto errorExit; 02121 } 02122 02123 if ((Size != 0) && (FreeBlock->Size != Size)) { 02124 02125 HeapDebugPrint(( "Dedicated (%04x) free list element %lx is wrong size (%04x)\n", 02126 Size, 02127 FreeBlock, 02128 FreeBlock->Size )); 02129 02130 goto errorExit; 02131 02132 } else if ((Size == 0) && (FreeBlock->Size < HEAP_MAXIMUM_FREELISTS)) { 02133 02134 HeapDebugPrint(( "Non-Dedicated free list element %lx with too small size (%04x)\n", 02135 FreeBlock, 02136 FreeBlock->Size )); 02137 02138 goto errorExit; 02139 02140 } else if ((Size == 0) && (FreeBlock->Size < PreviousSize)) { 02141 02142 HeapDebugPrint(( "Non-Dedicated free list element %lx is out of order\n", 02143 FreeBlock )); 02144 02145 goto errorExit; 02146 02147 } else { 02148 02149 PreviousSize = FreeBlock->Size; 02150 } 02151 02152 NumberOfFreeListEntries++; 02153 } 02154 02155 Head++; 02156 } 02157 02158 Size = (HEAP_NUMBER_OF_PSEUDO_TAG + Heap->NextAvailableTagIndex + 1) * sizeof( SIZE_T ); 02159 02160 if ((RtlpValidateHeapTagsEnable) && (Heap->PseudoTagEntries != NULL)) { 02161 02162 Status = NtAllocateVirtualMemory( NtCurrentProcess(), 02163 &ComputedPseudoTagEntries, 02164 0, 02165 &Size, 02166 MEM_COMMIT, 02167 PAGE_READWRITE ); 02168 02169 if (NT_SUCCESS( Status )) { 02170 02171 ComputedTagEntries = ComputedPseudoTagEntries + HEAP_NUMBER_OF_PSEUDO_TAG; 02172 } 02173 } 02174 02175 Head = &Heap->VirtualAllocdBlocks; 02176 Next = Head->Flink; 02177 02178 while (Head != Next) { 02179 02180 VirtualAllocBlock = CONTAINING_RECORD( Next, HEAP_VIRTUAL_ALLOC_ENTRY, Entry ); 02181 02182 if (ComputedTagEntries != NULL) { 02183 02184 TagIndex = VirtualAllocBlock->ExtraStuff.TagIndex; 02185 02186 if (TagIndex != 0) { 02187 02188 if (TagIndex & HEAP_PSEUDO_TAG_FLAG) { 02189 02190 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG; 02191 02192 if (TagIndex < HEAP_NUMBER_OF_PSEUDO_TAG) { 02193 02194 ComputedPseudoTagEntries[ TagIndex ] += 02195 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT; 02196 } 02197 02198 } else if (TagIndex & HEAP_GLOBAL_TAG) { 02199 02200 // 02201 // Ignore these since they are global across more than 02202 // one heap. 02203 // 02204 02205 } else if (TagIndex < Heap->NextAvailableTagIndex) { 02206 02207 ComputedTagEntries[ TagIndex ] += 02208 VirtualAllocBlock->CommitSize >> HEAP_GRANULARITY_SHIFT; 02209 } 02210 } 02211 } 02212 02213 if (VirtualAllocBlock->BusyBlock.Flags & HEAP_ENTRY_FILL_PATTERN) { 02214 02215 if (!RtlpCheckBusyBlockTail( &VirtualAllocBlock->BusyBlock )) { 02216 02217 return FALSE; 02218 } 02219 } 02220 02221 Next = Next->Flink; 02222 } 02223 02224 CountOfFreeBlocks = 0; 02225 TotalFreeSize = 0; 02226 02227 for (SegmentIndex=0; SegmentIndex<HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) { 02228 02229 Segment = Heap->Segments[ SegmentIndex ]; 02230 02231 if (Segment) { 02232 02233 if (!RtlpValidateHeapSegment( Heap, 02234 Segment, 02235 SegmentIndex, 02236 &CountOfFreeBlocks, 02237 &TotalFreeSize, 02238 &BadAddress, 02239 ComputedTagEntries, 02240 ComputedPseudoTagEntries )) { 02241 02242 goto errorExit; 02243 } 02244 } 02245 } 02246 02247 BadAddress = Heap; 02248 02249 if (NumberOfFreeListEntries != CountOfFreeBlocks) { 02250 02251 HeapDebugPrint(( "Number of free blocks in arena (%ld) does not match number in the free lists (%ld)\n", 02252 CountOfFreeBlocks, 02253 NumberOfFreeListEntries )); 02254 02255 goto errorExit; 02256 } 02257 02258 if (Heap->TotalFreeSize != TotalFreeSize) { 02259 02260 HeapDebugPrint(( "Total size of free blocks in arena (%ld) does not match number total in heap header (%ld)\n", 02261 TotalFreeSize, 02262 Heap->TotalFreeSize )); 02263 02264 goto errorExit; 02265 } 02266 02267 if (ComputedPseudoTagEntries != NULL) { 02268 02269 PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries; 02270 PHEAP_TAG_ENTRY TagEntries; 02271 USHORT TagIndex; 02272 02273 PseudoTagEntries = Heap->PseudoTagEntries; 02274 02275 if (PseudoTagEntries != NULL) { 02276 02277 for (TagIndex=1; TagIndex<HEAP_NUMBER_OF_PSEUDO_TAG; TagIndex++) { 02278 02279 PseudoTagEntries += 1; 02280 02281 if (ComputedPseudoTagEntries[ TagIndex ] != PseudoTagEntries->Size) { 02282 02283 HeapDebugPrint(( "Pseudo Tag %04x size incorrect (%x != %x) %x\n", 02284 TagIndex, 02285 PseudoTagEntries->Size, 02286 ComputedPseudoTagEntries[ TagIndex ] 02287 &ComputedPseudoTagEntries[ TagIndex ] )); 02288 02289 goto errorExit; 02290 } 02291 } 02292 } 02293 02294 TagEntries = Heap->TagEntries; 02295 02296 if (TagEntries != NULL) { 02297 02298 for (TagIndex=1; TagIndex<Heap->NextAvailableTagIndex; TagIndex++) { 02299 02300 TagEntries += 1; 02301 02302 if (ComputedTagEntries[ TagIndex ] != TagEntries->Size) { 02303 02304 HeapDebugPrint(( "Tag %04x (%ws) size incorrect (%x != %x) %x\n", 02305 TagIndex, 02306 TagEntries->TagName, 02307 TagEntries->Size, 02308 ComputedTagEntries[ TagIndex ], 02309 &ComputedTagEntries[ TagIndex ] )); 02310 02311 goto errorExit; 02312 } 02313 } 02314 } 02315 02316 Size = 0; 02317 02318 NtFreeVirtualMemory( NtCurrentProcess(), 02319 &ComputedPseudoTagEntries, 02320 &Size, 02321 MEM_RELEASE ); 02322 } 02323 02324 exit: 02325 02326 return TRUE; 02327 02328 errorExit: 02329 02330 HeapDebugBreak( BadAddress ); 02331 02332 if (ComputedPseudoTagEntries != NULL) { 02333 02334 Size = 0; 02335 02336 NtFreeVirtualMemory( NtCurrentProcess(), 02337 &ComputedPseudoTagEntries, 02338 &Size, 02339 MEM_RELEASE ); 02340 } 02341 02342 return FALSE; 02343 02344 } 02345 02346 02347 BOOLEAN RtlpHeapInvalidBreakPoint; 02348 PVOID RtlpHeapInvalidBadAddress; 02349 02350 VOID 02351 RtlpBreakPointHeap ( 02352 IN PVOID BadAddress 02353 ) 02354 02355 /*++ 02356 02357 Routine Description: 02358 02359 Arguments: 02360 02361 Return Value: 02362 02363 --*/ 02364 02365 { 02366 if (NtCurrentPeb()->BeingDebugged) { 02367 02368 *(BOOLEAN volatile *)&RtlpHeapInvalidBreakPoint = TRUE; 02369 02370 RtlpHeapInvalidBadAddress = BadAddress; 02371 02372 DbgBreakPoint(); 02373 02374 *(BOOLEAN volatile *)&RtlpHeapInvalidBreakPoint = FALSE; 02375 } 02376 }

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