1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 7 #ifdef MY_USE_INTERNAL_MEMMANAGER 8 9 #ifdef _X86_ 10 11 __inline VOID DbgTouch(IN PVOID addr) 12 { 13 __asm { 14 mov eax,addr 15 mov al,[byte ptr eax] 16 } 17 } 18 19 #else // NO X86 optimization , use generic C/C++ 20 21 __inline VOID DbgTouch(IN PVOID addr) 22 { 23 UCHAR a = ((PUCHAR)addr)[0]; 24 } 25 26 #endif // _X86_ 27 28 //MEM_ALLOC_DESC Allocs[MY_HEAP_MAX_BLOCKS]; 29 30 MEM_FRAME_ALLOC_DESC FrameList[MY_HEAP_MAX_FRAMES]; 31 #ifdef MEM_LOCK_BY_SPINLOCK 32 KSPIN_LOCK FrameLock; 33 KIRQL oldIrql; 34 #define LockMemoryManager() KeAcquireSpinLock(&FrameLock, &oldIrql) 35 #define UnlockMemoryManager() KeReleaseSpinLock(&FrameLock, oldIrql) 36 __inline 37 NTSTATUS 38 InitLockMemoryManager() { 39 KeInitializeSpinLock(&FrameLock); 40 return STATUS_SUCCESS; 41 } 42 #define DeinitLockMemoryManager() {NOTHING;} 43 #else //MEM_LOCK_BY_SPINLOCK 44 ERESOURCE FrameLock; 45 #define LockMemoryManager() ExAcquireResourceExclusiveLite(&FrameLock, TRUE) 46 #define UnlockMemoryManager() ExReleaseResourceForThreadLite(&FrameLock, ExGetCurrentResourceThread()) 47 #define InitLockMemoryManager() ExInitializeResourceLite(&FrameLock) 48 #define DeinitLockMemoryManager() ExDeleteResourceLite(&FrameLock) 49 #endif //MEM_LOCK_BY_SPINLOCK 50 ULONG FrameCount; 51 ULONG LastFrame; 52 BOOLEAN MyMemInitialized = FALSE; 53 54 #define MyAllocIsFrameFree(FrameList, i) \ 55 (!(FrameList[i].LastUsed || FrameList[i].FirstFree)) 56 57 #ifdef UDF_DBG 58 ULONG MemTotalAllocated; 59 PCHAR BreakAddr; 60 61 VOID 62 MyAllocDumpDescr( 63 PMEM_ALLOC_DESC Allocs, 64 ULONG i 65 ) 66 { 67 BOOLEAN Used; 68 69 Used = (Allocs[i].Len & MY_HEAP_FLAG_USED) ? TRUE : FALSE; 70 UDFPrint(("block %x \t%s addr %x len %x \t", i, Used ? "used" : "free", Allocs[i].Addr, (Allocs[i].Len) & MY_HEAP_FLAG_LEN_MASK)); 71 #ifdef MY_HEAP_TRACK_OWNERS 72 UDFPrint(("src %x \t line %d \t", Allocs[i].Src, Allocs[i].Line)); 73 #endif 74 #ifdef MY_HEAP_TRACK_REF 75 UDFPrint(("%s%s", Used ? " " : "-", Allocs[i].Tag ? Allocs[i].Tag : "")); 76 #endif 77 UDFPrint(("\n")); 78 } 79 80 //#define CHECK_ALLOC_FRAMES 81 82 #define DUMP_MEM_FRAMES 83 84 #ifdef DUMP_MEM_FRAMES 85 ULONG MyDumpMem = FALSE; 86 #endif //DUMP_MEM_FRAMES 87 88 #define DUMP_MEM_FRAMES2 89 90 //#ifdef CHECK_ALLOC_FRAMES 91 VOID 92 MyAllocDumpFrame( 93 ULONG Frame 94 ) 95 { 96 ULONG i; 97 PMEM_ALLOC_DESC Allocs; 98 Allocs = FrameList[Frame].Frame; 99 ULONG k=0; 100 BOOLEAN Used; 101 #ifdef DUMP_MEM_FRAMES 102 if(!MyDumpMem) 103 #endif //DUMP_MEM_FRAMES 104 return; 105 106 UDFPrint(("Dumping frame %x\n",Frame)); 107 UDFPrint(("FirstFree %x LastUsed %x ", FrameList[Frame].FirstFree, FrameList[Frame].LastUsed)); 108 UDFPrint(("Type %x\n", FrameList[Frame].Type)); 109 if(Allocs) { 110 for(i=0;i< (MY_HEAP_MAX_BLOCKS/*-1*/);i++) { 111 Used = (Allocs[i].Len & MY_HEAP_FLAG_USED) ? TRUE : FALSE; 112 UDFPrint(("block %x \t%s addr %x len %x \t", i, Used ? "used" : "free", Allocs[i].Addr, (Allocs[i].Len) & MY_HEAP_FLAG_LEN_MASK)); 113 #ifdef MY_HEAP_TRACK_OWNERS 114 UDFPrint(("src %x \t line %d \t", Allocs[i].Src, Allocs[i].Line)); 115 #endif 116 #ifdef MY_HEAP_TRACK_REF 117 UDFPrint(("%s%s", Used ? " " : "-", Allocs[i].Tag ? Allocs[i].Tag : "")); 118 #endif 119 UDFPrint(("\n")); 120 if(!(Allocs[i].Len) && !(Allocs[i].Addr)) { 121 break; 122 } 123 if(Allocs[i].Len & MY_HEAP_FLAG_USED) 124 k += ((Allocs[i].Len) & MY_HEAP_FLAG_LEN_MASK); 125 } 126 } 127 UDFPrint((" Wasted %x bytes from %x\n", MY_HEAP_FRAME_SIZE - k, MY_HEAP_FRAME_SIZE)); 128 } // end MyAllocDumpFrame() 129 130 VOID 131 MyAllocDumpFrames( 132 VOID 133 ) 134 { 135 ULONG i; 136 137 for(i=0;i<MY_HEAP_MAX_FRAMES; i++) { 138 if(FrameList[i].Frame) { 139 MyAllocDumpFrame(i); 140 } 141 } 142 143 UDFPrint(("\n")); 144 145 for(i=0;i<MY_HEAP_MAX_FRAMES; i++) { 146 if(FrameList[i].Frame) { 147 UDFPrint(("Addr %x ", FrameList[i].Frame)); 148 UDFPrint(("Type %x\n" , FrameList[i].Type)); 149 } 150 } 151 152 } // end MyAllocDumpFrame() 153 154 VOID 155 MyAllocCheck( 156 ULONG Frame 157 ) 158 { 159 ULONG i, j; 160 PMEM_ALLOC_DESC Allocs; 161 Allocs = FrameList[Frame].Frame; 162 ULONG len, addr; 163 164 for(i=0;i< (MY_HEAP_MAX_BLOCKS-1);i++) { 165 len = (Allocs[i].Len & MY_HEAP_FLAG_LEN_MASK); 166 addr = Allocs[i].Addr; 167 if( len != (Allocs[i+1].Addr - addr) ) { 168 if(Allocs[i+1].Addr) { 169 UDFPrint(("ERROR! Memory block aliasing\n")); 170 UDFPrint(("block %x, frame %x\n", i, Frame)); 171 UDFPrint(("block descriptor %x\n", &(Allocs[i]) )); 172 BrutePoint(); 173 MyAllocDumpFrame(Frame); 174 } 175 } 176 #ifdef MY_HEAP_CHECK_BOUNDS 177 if(*((PULONG)(addr+len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) != 0xBAADF00D) { 178 MyAllocDumpDescr(Allocs, i); 179 } 180 #endif //MY_HEAP_CHECK_BOUNDS 181 } 182 } // end MyAllocCheck() 183 184 //#endif //CHECK_ALLOC_FRAMES 185 #else 186 187 #define MyAllocDumpFrame(a) {} 188 #define MyAllocCheck(a) {} 189 #define MyAllocDumpFrames() {} 190 191 #endif // UDF_DBG 192 193 PCHAR 194 #ifndef MY_HEAP_TRACK_OWNERS 195 __fastcall 196 #endif 197 MyAllocatePoolInFrame( 198 ULONG Frame, 199 ULONG size 200 #ifdef MY_HEAP_TRACK_OWNERS 201 ,USHORT Src, 202 USHORT Line 203 #endif 204 #ifdef MY_HEAP_TRACK_REF 205 ,PCHAR Tag 206 #endif //MY_HEAP_TRACK_REF 207 ) 208 { 209 ULONG addr; 210 ULONG i; 211 ULONG min_len; 212 ULONG best_i; 213 PMEM_ALLOC_DESC Allocs; 214 PMEM_ALLOC_DESC Allocs0; 215 ULONG LastUsed, FirstFree; 216 ULONG l; 217 218 #ifdef CHECK_ALLOC_FRAMES 219 MyAllocCheck(Frame); 220 #endif 221 222 if(!size) return NULL; 223 #ifdef MY_HEAP_CHECK_BOUNDS 224 size+=MY_HEAP_CHECK_BOUNDS_BSZ; 225 #endif 226 227 /* if(size == 0x70) { 228 BrutePoint(); 229 }*/ 230 // lock frame 231 Allocs0 = FrameList[Frame].Frame; 232 if(!Allocs0) return NULL; 233 best_i = MY_HEAP_MAX_BLOCKS; 234 min_len = 0; 235 LastUsed = FrameList[Frame].LastUsed; 236 FirstFree = FrameList[Frame].FirstFree; 237 238 if(LastUsed >= (MY_HEAP_MAX_BLOCKS-1)) 239 return NULL; 240 241 for(i=FirstFree, Allocs = &(Allocs0[i]);i<=LastUsed;i++, Allocs++) { 242 if( !((l = Allocs->Len) & MY_HEAP_FLAG_USED) && 243 ((l &= MY_HEAP_FLAG_LEN_MASK) >= size) ) { 244 // check if minimal 245 // check for first occurence 246 if(l < min_len || !min_len) { 247 min_len = l; 248 best_i = i; 249 } 250 if(l == size) 251 break; 252 } 253 } 254 // not enough resources 255 if(best_i >= MY_HEAP_MAX_BLOCKS) return NULL; 256 // mark as used 257 Allocs = Allocs0+best_i; 258 addr = Allocs->Addr; 259 // create entry for unallocated tail 260 if(Allocs->Len != size) { // this element is always FREE 261 if(Allocs[1].Len) { 262 if(Allocs0[MY_HEAP_MAX_BLOCKS-1].Len) return NULL; 263 /* for(i=MY_HEAP_MAX_BLOCKS-1;i>best_i;i--) { 264 Allocs[i] = Allocs[i-1]; 265 }*/ 266 RtlMoveMemory(&(Allocs[1]), &(Allocs[0]), (LastUsed-best_i+1)*sizeof(MEM_ALLOC_DESC)); 267 } 268 Allocs[1].Addr = Allocs->Addr + size; 269 if(Allocs[1].Len) { 270 Allocs[1].Len -= size; 271 } else { 272 Allocs[1].Len = MY_HEAP_FRAME_SIZE - (addr - Allocs0[0].Addr) - size; 273 } 274 // Allocs[best_i+1].Used = FALSE; // this had been done by prev. ops. 275 FrameList[Frame].LastUsed++; 276 } 277 // update FirstFree pointer 278 if(FirstFree == best_i) { 279 for(i=best_i+1, Allocs++; (i<=LastUsed) && (Allocs->Len & MY_HEAP_FLAG_USED);i++, Allocs++) { 280 // do nothing but scan 281 } 282 FrameList[Frame].FirstFree = i; 283 Allocs = Allocs0+best_i; 284 } 285 Allocs->Len = size | MY_HEAP_FLAG_USED; 286 #ifdef MY_HEAP_TRACK_OWNERS 287 Allocs->Src = Src; 288 Allocs->Line = Line; 289 #endif 290 #ifdef MY_HEAP_TRACK_REF 291 Allocs->Tag = Tag; 292 #endif //MY_HEAP_TRACK_REF 293 294 // UDFPrint(( "Mem: Allocated %x at addr %x\n", size, (ULONG)addr )); 295 // this will set IntegrityTag to zero 296 *((PULONG)addr) = 0x00000000; 297 #ifdef MY_HEAP_CHECK_BOUNDS 298 for(i=0; i<MY_HEAP_CHECK_BOUNDS_SZ; i++) { 299 *((PULONG)(addr+size+(i*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) = 0xBAADF00D; 300 } 301 #endif //MY_HEAP_CHECK_BOUNDS 302 303 #ifdef UDF_DBG 304 MemTotalAllocated += size; 305 #endif 306 return (PCHAR)addr; 307 } // end MyAllocatePoolInFrame() 308 309 LONG 310 __fastcall 311 MyFindMemDescByAddr( 312 ULONG Frame, 313 PCHAR addr 314 ) 315 { 316 ULONG i; 317 ULONG left; 318 ULONG right; 319 PMEM_ALLOC_DESC Allocs; 320 321 Allocs = FrameList[Frame].Frame; 322 // i = FrameList[Frame].LastUsed >> 1; 323 // UDFPrint(("Mem: Freeing %x\n", (ULONG)addr)); DEADDA7A 324 // for(i=0;i<MY_HEAP_MAX_BLOCKS;i++) { 325 left = 0; 326 right = FrameList[Frame].LastUsed; 327 if(!right && FrameList[Frame].FirstFree) 328 right = 1; 329 while(left != right) { 330 i = (right + left) >> 1; 331 if( (Allocs[i].Len & MY_HEAP_FLAG_USED) && (Allocs[i].Addr == (ULONG)addr) ) { 332 FIF_Found: 333 return i; 334 } 335 if(right - left == 1) { 336 if( (Allocs[i+1].Len & MY_HEAP_FLAG_USED) && (Allocs[i+1].Addr == (ULONG)addr) ) { 337 i++; 338 goto FIF_Found; 339 } 340 break; 341 } 342 if(Allocs[i].Addr && (Allocs[i].Addr < (ULONG)addr)) { 343 left = i; 344 } else { 345 right = i; 346 } 347 } 348 return -1; 349 } // end MyFindMemDescByAddr() 350 351 VOID 352 __fastcall 353 MyFreePoolInFrame( 354 ULONG Frame, 355 PCHAR addr 356 ) 357 { 358 LONG i, j; 359 ULONG pc; 360 ULONG len, len2; 361 PMEM_ALLOC_DESC Allocs; 362 363 Allocs = FrameList[Frame].Frame; 364 pc = 0; 365 i = MyFindMemDescByAddr(Frame, addr); 366 if(i < 0) { 367 UDFPrint(("Mem: <<<*** WARNING ***>>> Double deallocation at %x !!! ;( \n", addr)); 368 MyAllocDumpFrame(Frame); 369 BrutePoint(); 370 return; 371 } 372 Allocs[i].Len &= ~MY_HEAP_FLAG_USED; 373 len = Allocs[i].Len; // USED bit is already cleared 374 375 #ifdef MY_HEAP_CHECK_BOUNDS 376 for(j=0; j<MY_HEAP_CHECK_BOUNDS_SZ; j++) { 377 ASSERT(*((PULONG)(addr+len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) == 0xBAADF00D); 378 if(*((PULONG)(addr+len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) != 0xBAADF00D) { 379 MyAllocDumpDescr(Allocs, i); 380 } 381 } 382 #endif //MY_HEAP_CHECK_BOUNDS 383 384 #ifdef UDF_DBG 385 // this is a marker of deallocated blocks 386 // some structures have DWORD IntegrityTag as a first member 387 // so, if IntegrityTag is equal to 0xDEADDA7A we shall return 388 // a <<<*** BIG ERROR MESSAGE ***>>> when somebody try to use it 389 *((PULONG)addr) = 0xDEADDA7A; 390 MemTotalAllocated -= len; 391 #endif 392 if((i<MY_HEAP_MAX_BLOCKS-1) && !((len2 = Allocs[i+1].Len) & MY_HEAP_FLAG_USED)) { 393 // pack up 394 if((len2 &= MY_HEAP_FLAG_LEN_MASK)) { 395 len += len2; 396 } else { 397 len = MY_HEAP_FRAME_SIZE - (Allocs[i].Addr - Allocs[0].Addr); 398 } 399 pc++; 400 } 401 if((i>0) && !((len2 = Allocs[i-1].Len) & MY_HEAP_FLAG_USED)) { 402 // pack down 403 len += (len2 & MY_HEAP_FLAG_LEN_MASK); 404 pc++; 405 i--; 406 } 407 if(pc) { 408 // pack 409 410 Allocs[i+pc].Addr = Allocs[i].Addr; 411 Allocs[i+pc].Len = len; 412 /* for(;i<MY_HEAP_MAX_BLOCKS-pc;i++) { 413 Allocs[i] = Allocs[i+pc]; 414 }*/ 415 RtlMoveMemory(&(Allocs[i]), &(Allocs[i+pc]), (MY_HEAP_MAX_BLOCKS-pc-i)*sizeof(MEM_ALLOC_DESC) ); 416 /* for(i=MY_HEAP_MAX_BLOCKS-pc;i<MY_HEAP_MAX_BLOCKS;i++) { 417 Allocs[i].Addr = 418 Allocs[i].Len = 419 Allocs[i].Used = 0; 420 }*/ 421 RtlZeroMemory(&(Allocs[MY_HEAP_MAX_BLOCKS-pc]), pc*sizeof(MEM_ALLOC_DESC)); 422 } 423 if(FrameList[Frame].FirstFree > (ULONG)i) 424 FrameList[Frame].FirstFree = (ULONG)i; 425 //ASSERT(FrameList[Frame].LastUsed >= pc); 426 if(FrameList[Frame].LastUsed < pc) { 427 FrameList[Frame].LastUsed = 0; 428 } else { 429 FrameList[Frame].LastUsed -= pc; 430 } 431 return; 432 } // end MyFreePoolInFrame() 433 434 BOOLEAN 435 __fastcall 436 MyResizePoolInFrame( 437 ULONG Frame, 438 PCHAR addr, 439 ULONG new_len 440 #ifdef MY_HEAP_TRACK_REF 441 ,PCHAR* Tag 442 #endif //MY_HEAP_TRACK_REF 443 ) 444 { 445 LONG i, j; 446 ULONG len, len2; 447 PMEM_ALLOC_DESC Allocs; 448 449 if(FrameList[Frame].LastUsed >= (MY_HEAP_MAX_BLOCKS-1)) 450 return FALSE; 451 Allocs = FrameList[Frame].Frame; 452 i = MyFindMemDescByAddr(Frame, addr); 453 if(i < 0) { 454 UDFPrint(("Mem: <<<*** WARNING ***>>> Double deallocation at %x !!! ;( \n", addr)); 455 MyAllocDumpFrame(Frame); 456 BrutePoint(); 457 return FALSE; 458 } 459 if(i>=(MY_HEAP_MAX_BLOCKS-2)) 460 return FALSE; 461 462 #ifdef MY_HEAP_TRACK_REF 463 *Tag = Allocs[i].Tag; 464 #endif //MY_HEAP_TRACK_REF 465 466 len = (Allocs[i].Len & MY_HEAP_FLAG_LEN_MASK); 467 468 #ifdef MY_HEAP_CHECK_BOUNDS 469 new_len += MY_HEAP_CHECK_BOUNDS_BSZ; 470 for(j=0; j<MY_HEAP_CHECK_BOUNDS_SZ; j++) { 471 ASSERT(*((PULONG)(addr+len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) == 0xBAADF00D); 472 if(*((PULONG)(addr+len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) != 0xBAADF00D) { 473 MyAllocDumpDescr(Allocs, i); 474 } 475 } 476 #endif //MY_HEAP_CHECK_BOUNDS 477 478 if(new_len > len ) { 479 if(Allocs[i+1].Len & MY_HEAP_FLAG_USED) 480 return FALSE; 481 if(len + (Allocs[i+1].Len & MY_HEAP_FLAG_LEN_MASK) < new_len) 482 return FALSE; 483 Allocs[i].Len += (len2 = (new_len - len)); 484 Allocs[i+1].Len -= len2; 485 Allocs[i+1].Addr += len2; 486 487 #ifdef MY_HEAP_CHECK_BOUNDS 488 for(j=0; j<MY_HEAP_CHECK_BOUNDS_SZ; j++) { 489 *((PULONG)(addr+new_len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) = 0xBAADF00D; 490 } 491 #endif //MY_HEAP_CHECK_BOUNDS 492 493 if(!Allocs[i+1].Len) { 494 i++; 495 RtlMoveMemory(&(Allocs[i]), &(Allocs[i+1]), (MY_HEAP_MAX_BLOCKS-1-i)*sizeof(MEM_ALLOC_DESC) ); 496 RtlZeroMemory(&(Allocs[MY_HEAP_MAX_BLOCKS-1]), sizeof(MEM_ALLOC_DESC)); 497 if((ULONG)i<FrameList[Frame].LastUsed) 498 FrameList[Frame].LastUsed--; 499 if(FrameList[Frame].FirstFree == (ULONG)i) { 500 for(;i<MY_HEAP_MAX_BLOCKS;i++) { 501 if(!(Allocs[i].Len & MY_HEAP_FLAG_USED)) 502 break; 503 } 504 FrameList[Frame].FirstFree = i; 505 } 506 } 507 #ifdef UDF_DBG 508 MemTotalAllocated += len; 509 #endif 510 } else { 511 512 len2 = len - new_len; 513 if(!len2) return TRUE; 514 515 #ifdef MY_HEAP_CHECK_BOUNDS 516 for(j=0; j<MY_HEAP_CHECK_BOUNDS_SZ; j++) { 517 *((PULONG)(addr+new_len+(j*sizeof(ULONG))-MY_HEAP_CHECK_BOUNDS_BSZ)) = 0xBAADF00D; 518 } 519 #endif //MY_HEAP_CHECK_BOUNDS 520 521 Allocs[i].Len -= len2; 522 if(Allocs[i+1].Len & MY_HEAP_FLAG_USED) { 523 i++; 524 RtlMoveMemory(&(Allocs[i+1]), &(Allocs[i]), (MY_HEAP_MAX_BLOCKS-i-1)*sizeof(MEM_ALLOC_DESC) ); 525 526 Allocs[i].Len = len2; 527 Allocs[i].Addr = Allocs[i-1].Addr + new_len; 528 529 if(FrameList[Frame].FirstFree > (ULONG)i) 530 FrameList[Frame].FirstFree = i; 531 FrameList[Frame].LastUsed++; 532 533 } else { 534 Allocs[i+1].Len += len2; 535 Allocs[i+1].Addr -= len2; 536 } 537 #ifdef UDF_DBG 538 MemTotalAllocated -= len2; 539 #endif 540 } 541 542 return TRUE; 543 } // end MyResizePoolInFrame() 544 545 VOID 546 __fastcall 547 MyAllocInitFrame( 548 ULONG Type, 549 ULONG Frame 550 ) 551 { 552 PMEM_ALLOC_DESC Allocs; 553 554 Allocs = (PMEM_ALLOC_DESC)DbgAllocatePool(NonPagedPool, sizeof(MEM_ALLOC_DESC)*(MY_HEAP_MAX_BLOCKS+1)); 555 if(!Allocs) { 556 UDFPrint(("Insufficient resources to allocate frame descriptor\n")); 557 FrameList[Frame].Frame = NULL; 558 MyAllocDumpFrames(); 559 BrutePoint(); 560 return; 561 } 562 RtlZeroMemory(Allocs, sizeof(MEM_ALLOC_DESC)*(MY_HEAP_MAX_BLOCKS+1)); 563 // alloc heap 564 Allocs[0].Addr = (ULONG)DbgAllocatePool((POOL_TYPE)Type, MY_HEAP_FRAME_SIZE); 565 if(!Allocs[0].Addr) { 566 UDFPrint(("Insufficient resources to allocate frame\n")); 567 DbgFreePool(Allocs); 568 FrameList[Frame].Frame = NULL; 569 MyAllocDumpFrames(); 570 BrutePoint(); 571 return; 572 } 573 Allocs[0].Len = MY_HEAP_FRAME_SIZE; 574 // Allocs[0].Used = FALSE; 575 FrameList[Frame].Frame = Allocs; 576 FrameList[Frame].LastUsed = 577 FrameList[Frame].FirstFree = 0; 578 FrameList[Frame].Type = Type; 579 FrameCount++; 580 if(LastFrame < Frame) 581 LastFrame = Frame; 582 } // end MyAllocInitFrame() 583 584 VOID 585 __fastcall 586 MyAllocFreeFrame( 587 ULONG Frame 588 ) 589 { 590 // check if already deinitialized 591 if(!FrameList[Frame].Frame) { 592 BrutePoint(); 593 return; 594 } 595 DbgFreePool((PVOID)(FrameList[Frame].Frame)[0].Addr); 596 DbgFreePool((PVOID)(FrameList[Frame].Frame)); 597 FrameList[Frame].Frame = NULL; 598 FrameCount--; 599 if(LastFrame == Frame) { 600 LONG i; 601 for(i=LastFrame; i>0; i--) { 602 if(FrameList[i].Frame) 603 break; 604 } 605 LastFrame = i; 606 } 607 } // end MyAllocFreeFrame() 608 609 PCHAR 610 #ifndef MY_HEAP_TRACK_OWNERS 611 __fastcall 612 #endif 613 MyAllocatePool( 614 ULONG type, 615 ULONG size 616 #ifdef MY_HEAP_TRACK_OWNERS 617 ,USHORT Src, 618 USHORT Line 619 #endif 620 #ifdef MY_HEAP_TRACK_REF 621 ,PCHAR Tag 622 #endif //MY_HEAP_TRACK_REF 623 ) 624 { 625 ULONG i; 626 ULONG addr; 627 628 // UDFPrint(("MemFrames: %x\n",FrameCount)); 629 630 if(!size || (size > MY_HEAP_FRAME_SIZE)) return NULL; 631 632 #ifdef DUMP_MEM_FRAMES2 633 if(MyDumpMem) 634 MyAllocDumpFrames(); 635 #endif 636 637 LockMemoryManager(); 638 for(i=0;i<MY_HEAP_MAX_FRAMES; i++) { 639 if( FrameList[i].Frame && 640 (FrameList[i].Type == type) && 641 (addr = (ULONG)MyAllocatePoolInFrame(i,size 642 #ifdef MY_HEAP_TRACK_OWNERS 643 ,Src,Line 644 #endif 645 #ifdef MY_HEAP_TRACK_REF 646 ,Tag 647 #endif //MY_HEAP_TRACK_REF 648 )) ) { 649 650 #ifdef UDF_DBG 651 // if(addr >= (ULONG)BreakAddr && addr < sizeof(UDF_FILE_INFO) + (ULONG)BreakAddr) { 652 // if(addr<=(ULONG)BreakAddr && addr+sizeof(UDF_FILE_INFO) > (ULONG)BreakAddr) { 653 // UDFPrint(("ERROR !!! Allocating in examined block\n")); 654 // UDFPrint(("addr %x\n", addr)); 655 // MyAllocDumpFrame(i); 656 // BrutePoint(); 657 // } 658 #endif //UDF_DBG 659 660 UnlockMemoryManager(); 661 DbgTouch((PVOID)addr); 662 return (PCHAR)addr; 663 } 664 } 665 #ifdef DUMP_MEM_FRAMES2 666 MyAllocDumpFrames(); 667 #endif 668 addr = 0; 669 for(i=0;i<MY_HEAP_MAX_FRAMES; i++) { 670 // MyAllocDumpFrame(i); 671 if(!(FrameList[i].Frame)) { 672 MyAllocInitFrame(type, i); 673 if(FrameList[i].Frame && 674 (addr = (ULONG)MyAllocatePoolInFrame(i,size 675 #ifdef MY_HEAP_TRACK_OWNERS 676 ,Src,Line 677 #endif 678 #ifdef MY_HEAP_TRACK_REF 679 ,Tag 680 #endif //MY_HEAP_TRACK_REF 681 )) ) { 682 683 #ifdef UDF_DBG 684 // if(addr >= (ULONG)BreakAddr && addr < sizeof(UDF_FILE_INFO) + (ULONG)BreakAddr) { 685 // if(addr<=(ULONG)BreakAddr && addr+sizeof(UDF_FILE_INFO) > (ULONG)BreakAddr) { 686 // UDFPrint(("ERROR !!! Allocating in examined block\n")); 687 // UDFPrint(("addr %x\n", addr)); 688 // MyAllocDumpFrame(i); 689 // BrutePoint(); 690 // } 691 // } else { 692 // addr = 0; 693 #endif //UDF_DBG 694 } 695 #ifdef DUMP_MEM_FRAMES2 696 MyAllocDumpFrames(); 697 #endif 698 break; 699 } 700 } 701 UnlockMemoryManager(); 702 return (PCHAR)addr; 703 } // end MyAllocatePool() 704 705 LONG 706 __fastcall 707 MyFindFrameByAddr( 708 PCHAR addr 709 ) 710 { 711 ULONG i; 712 // ULONG j; 713 PMEM_ALLOC_DESC Allocs; 714 715 for(i=0;i<=LastFrame; i++) { 716 if( (Allocs = FrameList[i].Frame) && 717 (Allocs[0].Addr <= (ULONG)addr) && 718 (Allocs[0].Addr + MY_HEAP_FRAME_SIZE > (ULONG)addr) ) { 719 return i; 720 } 721 } 722 return -1; 723 } 724 725 VOID 726 __fastcall 727 MyFreePool( 728 PCHAR addr 729 ) 730 { 731 LONG i; 732 733 // UDFPrint(("MemFrames: %x\n",FrameCount)); 734 735 LockMemoryManager(); 736 i = MyFindFrameByAddr(addr); 737 if(i < 0) { 738 UnlockMemoryManager(); 739 UDFPrint(("Mem: <<<*** WARNING ***>>> Double deallocation at %x !!! ;( \n", addr)); 740 BrutePoint(); 741 return; 742 } 743 744 #ifdef UDF_DBG 745 // BreakAddr <= addr < BreakAddr + sizeof(UDF_FILE_INFO) 746 // if((ULONG)addr >= (ULONG)BreakAddr && (ULONG)addr < sizeof(UDF_FILE_INFO) + (ULONG)BreakAddr) { 747 // UDFPrint(("Deallocating in examined block\n")); 748 // UDFPrint(("addr %x\n", addr)); 749 // MyAllocDumpFrame(i); 750 // BrutePoint(); 751 // BreakAddr = NULL; 752 // } 753 #endif //UDF_DBG 754 755 MyFreePoolInFrame(i,addr); 756 /* for(j=0;j<MY_HEAP_MAX_BLOCKS; j++) { 757 if((Allocs[j].Len & MY_HEAP_FLAG_USED) || (FrameCount<=1)) { 758 return; 759 } 760 }*/ 761 if(MyAllocIsFrameFree(FrameList, i)) { 762 MyAllocFreeFrame(i); 763 } 764 UnlockMemoryManager(); 765 return; 766 } // end MyFreePool() 767 768 ULONG 769 #ifndef MY_HEAP_TRACK_OWNERS 770 __fastcall 771 #endif 772 MyReallocPool( 773 IN PCHAR addr, 774 IN ULONG OldLength, 775 OUT PCHAR* NewBuff, 776 IN ULONG NewLength 777 #ifdef MY_HEAP_TRACK_OWNERS 778 ,USHORT Src, 779 USHORT Line 780 #endif 781 ) 782 { 783 ULONG i; 784 PCHAR new_buff; 785 #ifdef MY_HEAP_TRACK_REF 786 PCHAR Tag; 787 #endif 788 789 // UDFPrint(("MemFrames: %x\n",FrameCount)); 790 (*NewBuff) = addr; 791 if(OldLength == NewLength) return OldLength; 792 793 if(!NewLength) { 794 BrutePoint(); 795 return 0; 796 } 797 798 LockMemoryManager(); 799 i = MyFindFrameByAddr(addr); 800 if(i < 0) { 801 UnlockMemoryManager(); 802 UDFPrint(("Mem: <<<*** WARNING ***>>> Double deallocation at %x !!! ;( \n", addr)); 803 BrutePoint(); 804 return 0; 805 } 806 807 if(MyResizePoolInFrame(i,addr,NewLength 808 #ifdef MY_HEAP_TRACK_REF 809 , &Tag 810 #endif 811 )) { 812 #ifdef CHECK_ALLOC_FRAMES 813 MyAllocCheck(i); 814 #endif 815 816 (*NewBuff) = addr; 817 DbgTouch((PVOID)addr); 818 UnlockMemoryManager(); 819 return NewLength; 820 } 821 822 new_buff = MyAllocatePool(FrameList[i].Type, MyAlignSize__(NewLength) 823 #ifdef MY_HEAP_TRACK_OWNERS 824 ,Src,Line 825 #endif 826 #ifdef MY_HEAP_TRACK_REF 827 ,Tag 828 #endif //MY_HEAP_TRACK_REF 829 ); 830 if(!new_buff) { 831 UnlockMemoryManager(); 832 return 0; 833 } 834 835 if(OldLength > NewLength) OldLength = NewLength; 836 RtlCopyMemory(new_buff, addr, OldLength); 837 838 MyFreePoolInFrame(i,addr); 839 840 if(MyAllocIsFrameFree(FrameList, i)) { 841 MyAllocFreeFrame(i); 842 } 843 UnlockMemoryManager(); 844 845 DbgTouch((PVOID)new_buff); 846 (*NewBuff) = new_buff; 847 return OldLength; 848 849 } // end MyReallocPool() 850 851 #ifdef UDF_DBG 852 LONG 853 MyFindMemDescByRangeInFrame( 854 ULONG Frame, 855 PCHAR addr 856 ) 857 { 858 ULONG i; 859 ULONG left; 860 ULONG right; 861 PMEM_ALLOC_DESC Allocs; 862 ULONG curaddr; 863 ULONG curlen; 864 865 Allocs = FrameList[Frame].Frame; 866 // i = FrameList[Frame].LastUsed >> 1; 867 // UDFPrint(("Mem: Freeing %x\n", (ULONG)addr)); DEADDA7A 868 // for(i=0;i<MY_HEAP_MAX_BLOCKS;i++) { 869 left = 0; 870 right = FrameList[Frame].LastUsed; 871 if(!right && FrameList[Frame].FirstFree) 872 right = 1; 873 while(left != right) { 874 i = (right + left) >> 1; 875 curaddr = Allocs[i].Addr; 876 curlen = Allocs[i].Len; 877 if( (curlen & MY_HEAP_FLAG_USED) && 878 (curaddr <= (ULONG)addr) && 879 ((curaddr+(curlen & MY_HEAP_FLAG_LEN_MASK)) > (ULONG)addr) ) { 880 FIF_Found: 881 return i; 882 } 883 if(right - left == 1) { 884 if( (Allocs[i+1].Len & MY_HEAP_FLAG_USED) && (Allocs[i+1].Addr == (ULONG)addr) ) { 885 i++; 886 goto FIF_Found; 887 } 888 break; 889 } 890 if(Allocs[i].Addr && (Allocs[i].Addr < (ULONG)addr)) { 891 left = i; 892 } else { 893 right = i; 894 } 895 } 896 return -1; 897 } // end MyFindMemDescByRangeInFrame() 898 899 LONG 900 MyFindMemBaseByAddr( 901 PCHAR addr 902 ) 903 { 904 ULONG Frame, Base, i; 905 906 LockMemoryManager(); 907 Frame = MyFindFrameByAddr(addr); 908 if(Frame < 0) { 909 UnlockMemoryManager(); 910 UDFPrint(("Mem: <<<*** WARNING ***>>> Unknown base for %x !!! ;( \n", addr)); 911 BrutePoint(); 912 return -1; 913 } 914 i = MyFindMemDescByRangeInFrame(Frame, addr); 915 Base = FrameList[Frame].Frame[i].Addr; 916 UnlockMemoryManager(); 917 return Base; 918 } // end MyFindMemBaseByAddr() 919 #endif //UDF_DBG 920 921 BOOLEAN 922 MyAllocInit(VOID) 923 { 924 RtlZeroMemory(&FrameList, sizeof(FrameList)); 925 if(!OS_SUCCESS(InitLockMemoryManager())) { 926 return FALSE; 927 } 928 MyAllocInitFrame(NonPagedPool, 0); 929 LastFrame = 0; 930 return (MyMemInitialized = TRUE); 931 } // end MyAllocInit() 932 933 VOID 934 MyAllocRelease(VOID) 935 { 936 ULONG i; 937 PMEM_ALLOC_DESC Allocs; 938 939 if(!MyMemInitialized) 940 return; 941 LockMemoryManager(); 942 for(i=0;i<MY_HEAP_MAX_FRAMES; i++) { 943 if(Allocs = FrameList[i].Frame) { 944 MyAllocFreeFrame(i); 945 } 946 } 947 RtlZeroMemory(&FrameList, sizeof(FrameList)); 948 UnlockMemoryManager(); 949 DeinitLockMemoryManager(); 950 MyMemInitialized = FALSE; 951 } // end MyAllocRelease() 952 953 #endif //MY_USE_INTERNAL_MEMMANAGER 954