[APPHELP] Try Dos and Nt path formats in SdbGetFileAttributes.
[reactos.git] / dll / appcompat / apphelp / dbgheap.c
1 /*
2 * PROJECT: ReactOS Application compatibility module
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: SDB Debug heap functionality
5 * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #define WIN32_NO_STATUS
9 #include "ntndk.h"
10
11
12 #if SDBAPI_DEBUG_ALLOC
13
14 #define TRACE_ALL_FREE_CALLS 1
15
16 typedef struct SHIM_ALLOC_ENTRY
17 {
18 PVOID Address;
19 SIZE_T Size;
20 int Line;
21 const char* File;
22 PVOID Next;
23 PVOID Prev;
24 } SHIM_ALLOC_ENTRY, *PSHIM_ALLOC_ENTRY;
25
26 static RTL_CRITICAL_SECTION g_SdbpAllocationLock;
27 static RTL_AVL_TABLE g_SdbpAllocationTable;
28 static HANDLE g_PrivAllocationHeap;
29
30 static RTL_GENERIC_COMPARE_RESULTS
31 NTAPI ShimAllocCompareRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID FirstStruct, _In_ PVOID SecondStruct)
32 {
33 PVOID First = ((PSHIM_ALLOC_ENTRY)FirstStruct)->Address;
34 PVOID Second = ((PSHIM_ALLOC_ENTRY)SecondStruct)->Address;
35
36 if (First < Second)
37 return GenericLessThan;
38 else if (First == Second)
39 return GenericEqual;
40 return GenericGreaterThan;
41 }
42
43 static PVOID NTAPI ShimAllocAllocateRoutine(_In_ PRTL_AVL_TABLE Table, _In_ CLONG ByteSize)
44 {
45 return RtlAllocateHeap(g_PrivAllocationHeap, HEAP_ZERO_MEMORY, ByteSize);
46 }
47
48 static VOID NTAPI ShimAllocFreeRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
49 {
50 RtlFreeHeap(g_PrivAllocationHeap, 0, Buffer);
51 }
52
53 void SdbpInsertAllocation(PVOID address, SIZE_T size, int line, const char* file)
54 {
55 SHIM_ALLOC_ENTRY Entry = {0};
56
57 Entry.Address = address;
58 Entry.Size = size;
59 Entry.Line = line;
60 Entry.File = file;
61
62 RtlEnterCriticalSection(&g_SdbpAllocationLock);
63 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Entry, sizeof(Entry), NULL);
64 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
65 }
66
67 void SdbpUpdateAllocation(PVOID address, PVOID newaddress, SIZE_T size, int line, const char* file)
68 {
69 SHIM_ALLOC_ENTRY Lookup = {0};
70 PSHIM_ALLOC_ENTRY Entry;
71 Lookup.Address = address;
72
73 RtlEnterCriticalSection(&g_SdbpAllocationLock);
74 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
75
76 if (address == newaddress)
77 {
78 Entry->Size = size;
79 }
80 else
81 {
82 Lookup.Address = newaddress;
83 Lookup.Size = size;
84 Lookup.Line = line;
85 Lookup.File = file;
86 Lookup.Prev = address;
87 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup, sizeof(Lookup), NULL);
88 Entry->Next = newaddress;
89 }
90 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
91 }
92
93 static void SdbpPrintSingleAllocation(PSHIM_ALLOC_ENTRY Entry)
94 {
95 DbgPrint(" > %s(%d): %s%sAlloc( %d ) ==> %p\r\n", Entry->File, Entry->Line,
96 Entry->Next ? "Invalidated " : "", Entry->Prev ? "Re" : "", Entry->Size, Entry->Address);
97
98 }
99
100 void SdbpRemoveAllocation(PVOID address, int line, const char* file)
101 {
102 SHIM_ALLOC_ENTRY Lookup = {0};
103 PSHIM_ALLOC_ENTRY Entry;
104
105 #if TRACE_ALL_FREE_CALLS
106 DbgPrint("\r\n===============\r\n%s(%d): SdbpFree called, tracing alloc:\r\n", file, line);
107 #endif
108
109 Lookup.Address = address;
110 RtlEnterCriticalSection(&g_SdbpAllocationLock);
111 while (Lookup.Address)
112 {
113 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
114 if (Entry)
115 {
116 Lookup = *Entry;
117 RtlDeleteElementGenericTableAvl(&g_SdbpAllocationTable, Entry);
118
119 #if TRACE_ALL_FREE_CALLS
120 SdbpPrintSingleAllocation(&Lookup);
121 #endif
122 Lookup.Address = Lookup.Prev;
123 }
124 else
125 {
126 Lookup.Address = NULL;
127 }
128 }
129 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
130 #if TRACE_ALL_FREE_CALLS
131 DbgPrint("===============\r\n");
132 #endif
133 }
134
135 void SdbpDebugHeapInit(HANDLE privateHeapPtr)
136 {
137 g_PrivAllocationHeap = privateHeapPtr;
138
139 RtlInitializeCriticalSection(&g_SdbpAllocationLock);
140 RtlInitializeGenericTableAvl(&g_SdbpAllocationTable, ShimAllocCompareRoutine,
141 ShimAllocAllocateRoutine, ShimAllocFreeRoutine, NULL);
142 }
143
144 void SdbpDebugHeapDeinit(void)
145 {
146 if (g_SdbpAllocationTable.NumberGenericTableElements != 0)
147 {
148 PSHIM_ALLOC_ENTRY Entry;
149
150 DbgPrint("\r\n===============\r\n===============\r\nSdbpHeapDeinit: Dumping leaks\r\n");
151 RtlEnterCriticalSection(&g_SdbpAllocationLock);
152 Entry = RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable, TRUE);
153
154 while (Entry)
155 {
156 SdbpPrintSingleAllocation(Entry);
157 Entry = RtlEnumerateGenericTableAvl(&g_SdbpAllocationTable, FALSE);
158 }
159 RtlLeaveCriticalSection(&g_SdbpAllocationLock);
160 DbgPrint("===============\r\n===============\r\n");
161 }
162 /*__debugbreak();*/
163 /*RtlDeleteCriticalSection(&g_SdbpAllocationLock);*/
164 }
165
166 #endif