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