2 * Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define WIN32_NO_STATUS
23 #if SDBAPI_DEBUG_ALLOC
25 #define TRACE_ALL_FREE_CALLS 1
27 typedef struct SHIM_ALLOC_ENTRY
35 } SHIM_ALLOC_ENTRY
, *PSHIM_ALLOC_ENTRY
;
37 static RTL_CRITICAL_SECTION g_SdbpAllocationLock
;
38 static RTL_AVL_TABLE g_SdbpAllocationTable
;
39 static HANDLE g_PrivAllocationHeap
;
41 static RTL_GENERIC_COMPARE_RESULTS
42 NTAPI
ShimAllocCompareRoutine(_In_ PRTL_AVL_TABLE Table
, _In_ PVOID FirstStruct
, _In_ PVOID SecondStruct
)
44 PVOID First
= ((PSHIM_ALLOC_ENTRY
)FirstStruct
)->Address
;
45 PVOID Second
= ((PSHIM_ALLOC_ENTRY
)SecondStruct
)->Address
;
48 return GenericLessThan
;
49 else if (First
== Second
)
51 return GenericGreaterThan
;
54 static PVOID NTAPI
ShimAllocAllocateRoutine(_In_ PRTL_AVL_TABLE Table
, _In_ CLONG ByteSize
)
56 return RtlAllocateHeap(g_PrivAllocationHeap
, HEAP_ZERO_MEMORY
, ByteSize
);
59 static VOID NTAPI
ShimAllocFreeRoutine(_In_ PRTL_AVL_TABLE Table
, _In_ PVOID Buffer
)
61 RtlFreeHeap(g_PrivAllocationHeap
, 0, Buffer
);
64 void SdbpInsertAllocation(PVOID address
, SIZE_T size
, int line
, const char* file
)
66 SHIM_ALLOC_ENTRY Entry
= {0};
68 Entry
.Address
= address
;
73 RtlEnterCriticalSection(&g_SdbpAllocationLock
);
74 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable
, &Entry
, sizeof(Entry
), NULL
);
75 RtlLeaveCriticalSection(&g_SdbpAllocationLock
);
78 void SdbpUpdateAllocation(PVOID address
, PVOID newaddress
, SIZE_T size
, int line
, const char* file
)
80 SHIM_ALLOC_ENTRY Lookup
= {0};
81 PSHIM_ALLOC_ENTRY Entry
;
82 Lookup
.Address
= address
;
84 RtlEnterCriticalSection(&g_SdbpAllocationLock
);
85 Entry
= RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable
, &Lookup
);
87 if (address
== newaddress
)
93 Lookup
.Address
= newaddress
;
97 Lookup
.Prev
= address
;
98 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable
, &Lookup
, sizeof(Lookup
), NULL
);
99 Entry
->Next
= newaddress
;
101 RtlLeaveCriticalSection(&g_SdbpAllocationLock
);
104 static void SdbpPrintSingleAllocation(PSHIM_ALLOC_ENTRY Entry
)
106 DbgPrint(" > %s(%d): %s%sAlloc( %d ) ==> %p\r\n", Entry
->File
, Entry
->Line
,
107 Entry
->Next
? "Invalidated " : "", Entry
->Prev
? "Re" : "", Entry
->Size
, Entry
->Address
);
111 void SdbpRemoveAllocation(PVOID address
, int line
, const char* file
)
113 SHIM_ALLOC_ENTRY Lookup
= {0};
114 PSHIM_ALLOC_ENTRY Entry
;
116 #if TRACE_ALL_FREE_CALLS
117 DbgPrint("\r\n===============\r\n%s(%d): SdbpFree called, tracing alloc:\r\n", file
, line
);
120 Lookup
.Address
= address
;
121 RtlEnterCriticalSection(&g_SdbpAllocationLock
);
122 while (Lookup
.Address
)
124 Entry
= RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable
, &Lookup
);
128 RtlDeleteElementGenericTableAvl(&g_SdbpAllocationTable
, Entry
);
130 #if TRACE_ALL_FREE_CALLS
131 SdbpPrintSingleAllocation(&Lookup
);
133 Lookup
.Address
= Lookup
.Prev
;
137 Lookup
.Address
= NULL
;
140 RtlLeaveCriticalSection(&g_SdbpAllocationLock
);
141 #if TRACE_ALL_FREE_CALLS
142 DbgPrint("===============\r\n");
146 void SdbpDebugHeapInit(HANDLE privateHeapPtr
)
148 g_PrivAllocationHeap
= privateHeapPtr
;
150 RtlInitializeCriticalSection(&g_SdbpAllocationLock
);
151 RtlInitializeGenericTableAvl(&g_SdbpAllocationTable
, ShimAllocCompareRoutine
,
152 ShimAllocAllocateRoutine
, ShimAllocFreeRoutine
, NULL
);
155 void SdbpDebugHeapDeinit(void)
157 if (g_SdbpAllocationTable
.NumberGenericTableElements
!= 0)
159 PSHIM_ALLOC_ENTRY Entry
;
161 DbgPrint("\r\n===============\r\n===============\r\nSdbpHeapDeinit: Dumping leaks\r\n");
162 RtlEnterCriticalSection(&g_SdbpAllocationLock
);
163 Entry
= RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable
, TRUE
);
167 SdbpPrintSingleAllocation(Entry
);
168 Entry
= RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable
, FALSE
);
170 RtlLeaveCriticalSection(&g_SdbpAllocationLock
);
171 DbgPrint("===============\r\n===============\r\n");
174 /*RtlDeleteCriticalSection(&g_SdbpAllocationLock);*/