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

heapdbg.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Runtime Library
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            lib/rtl/heapdbg.c
00005  * PURPOSE:         Heap manager debug heap
00006  * PROGRAMMERS:     Copyright 2010 Aleksey Bragin
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <rtl.h>
00012 #include <heap.h>
00013 
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 /* FUNCTIONS ******************************************************************/
00018 
00019 HANDLE NTAPI
00020 RtlDebugCreateHeap(ULONG Flags,
00021                    PVOID Addr,
00022                    SIZE_T ReserveSize,
00023                    SIZE_T CommitSize,
00024                    PVOID Lock,
00025                    PRTL_HEAP_PARAMETERS Parameters)
00026 {
00027     MEMORY_BASIC_INFORMATION MemoryInfo;
00028     NTSTATUS Status;
00029     PHEAP Heap;
00030 
00031     /* Validate parameters */
00032     if (ReserveSize <= HEAP_ENTRY_SIZE)
00033     {
00034         DPRINT1("HEAP: Incorrect ReserveSize %x\n", ReserveSize);
00035         return NULL;
00036     }
00037 
00038     if (ReserveSize < CommitSize)
00039     {
00040         DPRINT1("HEAP: Incorrect CommitSize %x\n", CommitSize);
00041         return NULL;
00042     }
00043 
00044     if (Flags & HEAP_NO_SERIALIZE && Lock)
00045     {
00046         DPRINT1("HEAP: Can't specify Lock routine and have HEAP_NO_SERIALIZE flag set\n");
00047         return NULL;
00048     }
00049 
00050     /* If the address is specified, check it's virtual memory */
00051     if (Addr)
00052     {
00053         Status = ZwQueryVirtualMemory(NtCurrentProcess(),
00054                                       Addr,
00055                                       MemoryBasicInformation,
00056                                       &MemoryInfo,
00057                                       sizeof(MemoryInfo),
00058                                       NULL);
00059 
00060         if (!NT_SUCCESS(Status))
00061         {
00062             DPRINT1("HEAP: Specified heap base address %p is invalid, Status 0x%08X\n", Addr, Status);
00063             return NULL;
00064         }
00065 
00066         if (MemoryInfo.BaseAddress != Addr)
00067         {
00068             DPRINT1("HEAP: Specified heap base address %p is not really a base one %p\n", Addr, MemoryInfo.BaseAddress);
00069             return NULL;
00070         }
00071 
00072         if (MemoryInfo.State == MEM_FREE)
00073         {
00074             DPRINT1("HEAP: Specified heap base address %p is free\n", Addr);
00075             return NULL;
00076         }
00077     }
00078 
00079     /* All validation performed, now call the real routine with skip validation check flag */
00080     Flags |= HEAP_SKIP_VALIDATION_CHECKS |
00081              HEAP_TAIL_CHECKING_ENABLED |
00082              HEAP_FREE_CHECKING_ENABLED;
00083 
00084     Heap = RtlCreateHeap(Flags, Addr, ReserveSize, CommitSize, Lock, Parameters);
00085     if (!Heap) return NULL;
00086 
00087     // FIXME: Capture stack backtrace
00088 
00089     RtlpValidateHeapHeaders(Heap, TRUE);
00090 
00091     return Heap;
00092 }
00093 
00094 BOOLEAN NTAPI
00095 RtlDebugDestroyHeap(HANDLE HeapPtr)
00096 {
00097     SIZE_T Size = 0;
00098     PHEAP Heap = (PHEAP)HeapPtr;
00099 
00100     if (Heap == RtlGetCurrentPeb()->ProcessHeap)
00101     {
00102         DPRINT1("HEAP: It's forbidden delete process heap!");
00103         return FALSE;
00104     }
00105 
00106     if (Heap->Signature != HEAP_SIGNATURE)
00107     {
00108         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00109         return FALSE;
00110     }
00111 
00112     if (!RtlpValidateHeap(Heap, FALSE)) return FALSE;
00113 
00114     /* Make heap invalid by zeroing its signature */
00115     Heap->Signature = 0;
00116 
00117     /* Free validate headers copy if it was existing */
00118     if (Heap->HeaderValidateCopy)
00119     {
00120         ZwFreeVirtualMemory(NtCurrentProcess(),
00121                             &Heap->HeaderValidateCopy,
00122                             &Size,
00123                             MEM_RELEASE);
00124     }
00125 
00126     return TRUE;
00127 }
00128 
00129 PVOID NTAPI
00130 RtlDebugAllocateHeap(PVOID HeapPtr,
00131                      ULONG Flags,
00132                      SIZE_T Size)
00133 {
00134     PHEAP Heap = (PHEAP)HeapPtr;
00135     SIZE_T AllocSize = 1;
00136     BOOLEAN HeapLocked = FALSE;
00137     PVOID Result;
00138 
00139     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00140         return RtlpPageHeapAllocate(HeapPtr, Flags, Size);
00141 
00142     if (Heap->Signature != HEAP_SIGNATURE)
00143     {
00144         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00145         return NULL;
00146     }
00147 
00148     /* Add settable user value flag */
00149     Flags |= Heap->ForceFlags | HEAP_SETTABLE_USER_VALUE | HEAP_SKIP_VALIDATION_CHECKS;
00150 
00151     /* Calculate size */
00152     if (Size) AllocSize = Size;
00153     AllocSize = ((AllocSize + Heap->AlignRound) & Heap->AlignMask) + sizeof(HEAP_ENTRY_EXTRA);
00154 
00155     /* Check if size didn't exceed max one */
00156     if (AllocSize < Size ||
00157         AllocSize > Heap->MaximumAllocationSize)
00158     {
00159         DPRINT1("HEAP: Too big allocation size %x (max allowed %x)\n", Size, Heap->MaximumAllocationSize);
00160         return NULL;
00161     }
00162 
00163     /* Lock the heap ourselves */
00164     if (!(Flags & HEAP_NO_SERIALIZE))
00165     {
00166         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00167         HeapLocked = TRUE;
00168 
00169         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00170         Flags |= HEAP_NO_SERIALIZE;
00171     }
00172 
00173     /* Validate the heap if necessary */
00174     RtlpValidateHeap(Heap, FALSE);
00175 
00176     /* Call main routine to do the stuff */
00177     Result = RtlAllocateHeap(HeapPtr, Flags, Size);
00178 
00179     /* Validate heap headers */
00180     RtlpValidateHeapHeaders(Heap, TRUE);
00181 
00182     if (Result)
00183     {
00184         if (Heap->Flags & HEAP_VALIDATE_ALL_ENABLED)
00185             RtlpValidateHeap(Heap, FALSE);
00186     }
00187 
00188     /* Release the lock */
00189     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00190 
00191     return Result;
00192 }
00193 
00194 PVOID NTAPI
00195 RtlDebugReAllocateHeap(HANDLE HeapPtr,
00196                        ULONG Flags,
00197                        PVOID Ptr,
00198                        SIZE_T Size)
00199 {
00200     PHEAP Heap = (PHEAP)HeapPtr;
00201     SIZE_T AllocSize = 1;
00202     BOOLEAN HeapLocked = FALSE;
00203     PVOID Result = NULL;
00204     PHEAP_ENTRY HeapEntry;
00205 
00206     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00207         return RtlpPageHeapReAllocate(HeapPtr, Flags, Ptr, Size);
00208 
00209     if (Heap->Signature != HEAP_SIGNATURE)
00210     {
00211         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00212         return NULL;
00213     }
00214 
00215     /* Add settable user value flag */
00216     Flags |= Heap->ForceFlags | HEAP_SETTABLE_USER_VALUE | HEAP_SKIP_VALIDATION_CHECKS;
00217 
00218     /* Calculate size */
00219     if (Size) AllocSize = Size;
00220     AllocSize = ((AllocSize + Heap->AlignRound) & Heap->AlignMask) + sizeof(HEAP_ENTRY_EXTRA);
00221 
00222     /* Check if size didn't exceed max one */
00223     if (AllocSize < Size ||
00224         AllocSize > Heap->MaximumAllocationSize)
00225     {
00226         DPRINT1("HEAP: Too big allocation size %x (max allowed %x)\n", Size, Heap->MaximumAllocationSize);
00227         return NULL;
00228     }
00229 
00230     /* Lock the heap ourselves */
00231     if (!(Flags & HEAP_NO_SERIALIZE))
00232     {
00233         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00234         HeapLocked = TRUE;
00235 
00236         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00237         Flags |= HEAP_NO_SERIALIZE;
00238     }
00239 
00240     /* Validate the heap if necessary */
00241     RtlpValidateHeap(Heap, FALSE);
00242 
00243     /* Get the existing heap entry */
00244     HeapEntry = (PHEAP_ENTRY)Ptr - 1;
00245 
00246     /* Validate it */
00247     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00248     {
00249         /* Call main routine to do the stuff */
00250         Result = RtlReAllocateHeap(HeapPtr, Flags, Ptr, Size);
00251 
00252         if (Result)
00253         {
00254             /* Validate heap headers and then heap itself */
00255             RtlpValidateHeapHeaders(Heap, TRUE);
00256             RtlpValidateHeap(Heap, FALSE);
00257         }
00258     }
00259 
00260     /* Release the lock */
00261     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00262 
00263     return Result;
00264 }
00265 
00266 BOOLEAN NTAPI
00267 RtlDebugFreeHeap(HANDLE HeapPtr,
00268                  ULONG Flags,
00269                  PVOID Ptr)
00270 {
00271     PHEAP Heap = (PHEAP)HeapPtr;
00272     BOOLEAN HeapLocked = FALSE;
00273     PHEAP_ENTRY HeapEntry;
00274     BOOLEAN Result = FALSE;
00275 
00276     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00277         return RtlpPageHeapFree(HeapPtr, Flags, Ptr);
00278 
00279     if (Heap->Signature != HEAP_SIGNATURE)
00280     {
00281         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00282         return FALSE;
00283     }
00284 
00285     /* Add skip validation flag */
00286     Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS;
00287 
00288     /* Lock the heap ourselves */
00289     if (!(Flags & HEAP_NO_SERIALIZE))
00290     {
00291         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00292         HeapLocked = TRUE;
00293 
00294         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00295         Flags |= HEAP_NO_SERIALIZE;
00296     }
00297 
00298     /* Validate the heap if necessary */
00299     RtlpValidateHeap(Heap, FALSE);
00300 
00301     /* Get the existing heap entry */
00302     HeapEntry = (PHEAP_ENTRY)Ptr - 1;
00303 
00304     /* Validate it */
00305     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00306     {
00307         /* If it succeeded - call the main routine */
00308         Result = RtlFreeHeap(HeapPtr, Flags, Ptr);
00309 
00310         /* Validate heap headers and then heap itself */
00311         RtlpValidateHeapHeaders(Heap, TRUE);
00312         RtlpValidateHeap(Heap, FALSE);
00313     }
00314 
00315     /* Release the lock */
00316     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00317 
00318     return Result;
00319 }
00320 
00321 BOOLEAN NTAPI
00322 RtlDebugGetUserInfoHeap(PVOID HeapHandle,
00323                         ULONG Flags,
00324                         PVOID BaseAddress,
00325                         PVOID *UserValue,
00326                         PULONG UserFlags)
00327 {
00328     PHEAP Heap = (PHEAP)HeapHandle;
00329     BOOLEAN HeapLocked = FALSE;
00330     PHEAP_ENTRY HeapEntry;
00331     BOOLEAN Result = FALSE;
00332 
00333     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00334         return RtlpPageHeapGetUserInfo(HeapHandle, Flags, BaseAddress, UserValue, UserFlags);
00335 
00336     if (Heap->Signature != HEAP_SIGNATURE)
00337     {
00338         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00339         return FALSE;
00340     }
00341 
00342     /* Add skip validation flag */
00343     Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS;
00344 
00345     /* Lock the heap ourselves */
00346     if (!(Flags & HEAP_NO_SERIALIZE))
00347     {
00348         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00349         HeapLocked = TRUE;
00350 
00351         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00352         Flags |= HEAP_NO_SERIALIZE;
00353     }
00354 
00355     /* Validate the heap if necessary */
00356     RtlpValidateHeap(Heap, FALSE);
00357 
00358     /* Get the existing heap entry */
00359     HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
00360 
00361     /* Validate it */
00362     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00363     {
00364         /* If it succeeded - call the main routine */
00365         Result = RtlGetUserInfoHeap(HeapHandle, Flags, BaseAddress, UserValue, UserFlags);
00366     }
00367 
00368     /* Release the lock */
00369     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00370 
00371     return Result;
00372 }
00373 
00374 BOOLEAN NTAPI
00375 RtlDebugSetUserValueHeap(PVOID HeapHandle,
00376                          ULONG Flags,
00377                          PVOID BaseAddress,
00378                          PVOID UserValue)
00379 {
00380     PHEAP Heap = (PHEAP)HeapHandle;
00381     BOOLEAN HeapLocked = FALSE;
00382     PHEAP_ENTRY HeapEntry;
00383     BOOLEAN Result = FALSE;
00384 
00385     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00386         return RtlpPageHeapSetUserValue(HeapHandle, Flags, BaseAddress, UserValue);
00387 
00388     if (Heap->Signature != HEAP_SIGNATURE)
00389     {
00390         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00391         return FALSE;
00392     }
00393 
00394     /* Add skip validation flag */
00395     Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS;
00396 
00397     /* Lock the heap ourselves */
00398     if (!(Flags & HEAP_NO_SERIALIZE))
00399     {
00400         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00401         HeapLocked = TRUE;
00402 
00403         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00404         Flags |= HEAP_NO_SERIALIZE;
00405     }
00406 
00407     /* Validate the heap if necessary */
00408     RtlpValidateHeap(Heap, FALSE);
00409 
00410     /* Get the existing heap entry */
00411     HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
00412 
00413     /* Validate it */
00414     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00415     {
00416         /* If it succeeded - call the main routine */
00417         Result = RtlSetUserValueHeap(HeapHandle, Flags, BaseAddress, UserValue);
00418 
00419         /* Validate the heap */
00420         RtlpValidateHeap(Heap, FALSE);
00421     }
00422 
00423     /* Release the lock */
00424     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00425 
00426     return Result;
00427 }
00428 
00429 BOOLEAN
00430 NTAPI
00431 RtlDebugSetUserFlagsHeap(PVOID HeapHandle,
00432                          ULONG Flags,
00433                          PVOID BaseAddress,
00434                          ULONG UserFlagsReset,
00435                          ULONG UserFlagsSet)
00436 {
00437     PHEAP Heap = (PHEAP)HeapHandle;
00438     BOOLEAN HeapLocked = FALSE;
00439     PHEAP_ENTRY HeapEntry;
00440     BOOLEAN Result = FALSE;
00441 
00442     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00443         return RtlpPageHeapSetUserFlags(HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet);
00444 
00445     /* Check if this heap allows flags to be set at all */
00446     if (UserFlagsSet & ~HEAP_SETTABLE_USER_FLAGS ||
00447         UserFlagsReset & ~HEAP_SETTABLE_USER_FLAGS)
00448     {
00449         return FALSE;
00450     }
00451 
00452     if (Heap->Signature != HEAP_SIGNATURE)
00453     {
00454         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00455         return FALSE;
00456     }
00457 
00458     /* Add skip validation flag */
00459     Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS;
00460 
00461     /* Lock the heap ourselves */
00462     if (!(Flags & HEAP_NO_SERIALIZE))
00463     {
00464         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00465         HeapLocked = TRUE;
00466 
00467         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00468         Flags |= HEAP_NO_SERIALIZE;
00469     }
00470 
00471     /* Validate the heap if necessary */
00472     RtlpValidateHeap(Heap, FALSE);
00473 
00474     /* Get the existing heap entry */
00475     HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
00476 
00477     /* Validate it */
00478     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00479     {
00480         /* If it succeeded - call the main routine */
00481         Result = RtlSetUserFlagsHeap(HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet);
00482 
00483         /* Validate the heap */
00484         RtlpValidateHeap(Heap, FALSE);
00485     }
00486 
00487     /* Release the lock */
00488     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00489 
00490     return Result;
00491 }
00492 
00493 SIZE_T NTAPI
00494 RtlDebugSizeHeap(HANDLE HeapPtr,
00495                  ULONG Flags,
00496                  PVOID Ptr)
00497 {
00498     PHEAP Heap = (PHEAP)HeapPtr;
00499     BOOLEAN HeapLocked = FALSE;
00500     PHEAP_ENTRY HeapEntry;
00501     SIZE_T Result = ~(SIZE_T)0;
00502 
00503     if (Heap->ForceFlags & HEAP_FLAG_PAGE_ALLOCS)
00504         return RtlpPageHeapSize(HeapPtr, Flags, Ptr);
00505 
00506     /* Check heap signature */
00507     if (Heap->Signature != HEAP_SIGNATURE)
00508     {
00509         DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature);
00510         return FALSE;
00511     }
00512 
00513     /* Add skip validation flag */
00514     Flags |= Heap->ForceFlags | HEAP_SKIP_VALIDATION_CHECKS;
00515 
00516     /* Lock the heap ourselves */
00517     if (!(Flags & HEAP_NO_SERIALIZE))
00518     {
00519         RtlEnterHeapLock(Heap->LockVariable, TRUE);
00520         HeapLocked = TRUE;
00521 
00522         /* Add no serialize flag so that the main routine won't try to acquire the lock again */
00523         Flags |= HEAP_NO_SERIALIZE;
00524     }
00525 
00526     /* Validate the heap if necessary */
00527     RtlpValidateHeap(Heap, FALSE);
00528 
00529     /* Get the existing heap entry */
00530     HeapEntry = (PHEAP_ENTRY)Ptr - 1;
00531 
00532     /* Validate it */
00533     if (RtlpValidateHeapEntry(Heap, HeapEntry))
00534     {
00535         /* If it succeeded - call the main routine */
00536         Result = RtlSizeHeap(HeapPtr, Flags, Ptr);
00537     }
00538 
00539     /* Release the lock */
00540     if (HeapLocked) RtlLeaveHeapLock(Heap->LockVariable);
00541 
00542     return Result;
00543 }
00544 
00545 /* EOF */

Generated on Sat May 26 2012 04:35:21 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.