Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenheapdbg.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
1.7.6.1
|