fd2d0e6cf7255f654a160bba8efad6c081400b3a
[reactos.git] / reactos / dll / appcompat / apphelp / sdbapi.c
1 /*
2 * Copyright 2011 André Hentschel
3 * Copyright 2013 Mislav Blažević
4 * Copyright 2015 Mark Jansen
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #include "windows.h"
23 #include "ntndk.h"
24 #include "strsafe.h"
25 #include "apphelp.h"
26
27 #include "wine/unicode.h"
28
29
30 static HANDLE SdbpHeap(void);
31
32 #if SDBAPI_DEBUG_ALLOC
33
34 typedef struct SHIM_ALLOC_ENTRY
35 {
36 PVOID Address;
37 SIZE_T Size;
38 int Line;
39 const char* File;
40 PVOID Next;
41 PVOID Prev;
42 } SHIM_ALLOC_ENTRY, *PSHIM_ALLOC_ENTRY;
43
44
45 static RTL_AVL_TABLE g_SdbpAllocationTable;
46
47
48 static RTL_GENERIC_COMPARE_RESULTS
49 NTAPI ShimAllocCompareRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID FirstStruct, _In_ PVOID SecondStruct)
50 {
51 PVOID First = ((PSHIM_ALLOC_ENTRY)FirstStruct)->Address;
52 PVOID Second = ((PSHIM_ALLOC_ENTRY)SecondStruct)->Address;
53
54 if (First < Second)
55 return GenericLessThan;
56 else if (First == Second)
57 return GenericEqual;
58 return GenericGreaterThan;
59 }
60
61 static PVOID NTAPI ShimAllocAllocateRoutine(_In_ PRTL_AVL_TABLE Table, _In_ CLONG ByteSize)
62 {
63 return HeapAlloc(SdbpHeap(), HEAP_ZERO_MEMORY, ByteSize);
64 }
65
66 static VOID NTAPI ShimAllocFreeRoutine(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)
67 {
68 HeapFree(SdbpHeap(), 0, Buffer);
69 }
70
71 static void SdbpInsertAllocation(PVOID address, SIZE_T size, int line, const char* file)
72 {
73 SHIM_ALLOC_ENTRY Entry = {0};
74
75 Entry.Address = address;
76 Entry.Size = size;
77 Entry.Line = line;
78 Entry.File = file;
79 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Entry, sizeof(Entry), NULL);
80 }
81
82 static void SdbpUpdateAllocation(PVOID address, PVOID newaddress, SIZE_T size, int line, const char* file)
83 {
84 SHIM_ALLOC_ENTRY Lookup = {0};
85 PSHIM_ALLOC_ENTRY Entry;
86 Lookup.Address = address;
87 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
88
89 if (address == newaddress)
90 {
91 Entry->Size = size;
92 }
93 else
94 {
95 Lookup.Address = newaddress;
96 Lookup.Size = size;
97 Lookup.Line = line;
98 Lookup.File = file;
99 Lookup.Prev = address;
100 RtlInsertElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup, sizeof(Lookup), NULL);
101 Entry->Next = newaddress;
102 }
103 }
104
105 static void SdbpRemoveAllocation(PVOID address, int line, const char* file)
106 {
107 char buf[512];
108 SHIM_ALLOC_ENTRY Lookup = {0};
109 PSHIM_ALLOC_ENTRY Entry;
110
111 sprintf(buf, "\r\n===============\r\n%s(%d): SdbpFree called, tracing alloc:\r\n", file, line);
112 OutputDebugStringA(buf);
113
114 Lookup.Address = address;
115 while (Lookup.Address)
116 {
117 Entry = RtlLookupElementGenericTableAvl(&g_SdbpAllocationTable, &Lookup);
118 if (Entry)
119 {
120 Lookup = *Entry;
121 RtlDeleteElementGenericTableAvl(&g_SdbpAllocationTable, Entry);
122
123 sprintf(buf, " > %s(%d): %s%sAlloc( %d ) ==> %p\r\n", Lookup.File, Lookup.Line,
124 Lookup.Next ? "Invalidated " : "", Lookup.Prev ? "Re" : "", Lookup.Size, Lookup.Address);
125 OutputDebugStringA(buf);
126 Lookup.Address = Lookup.Prev;
127 }
128 else
129 {
130 Lookup.Address = NULL;
131 }
132 }
133 sprintf(buf, "\r\n===============\r\n");
134 OutputDebugStringA(buf);
135 }
136
137 #endif
138
139 static HANDLE g_Heap;
140 void SdbpHeapInit(void)
141 {
142 #if SDBAPI_DEBUG_ALLOC
143 RtlInitializeGenericTableAvl(&g_SdbpAllocationTable, ShimAllocCompareRoutine,
144 ShimAllocAllocateRoutine, ShimAllocFreeRoutine, NULL);
145 #endif
146 g_Heap = HeapCreate(0, 0x10000, 0);
147 }
148
149 void SdbpHeapDeinit(void)
150 {
151 #if SDBAPI_DEBUG_ALLOC
152 if (g_SdbpAllocationTable.NumberGenericTableElements != 0)
153 __debugbreak();
154 #endif
155 HeapDestroy(g_Heap);
156 }
157
158 DWORD SdbpStrlen(PCWSTR string)
159 {
160 return (lstrlenW(string) + 1) * sizeof(WCHAR);
161 }
162
163 static HANDLE SdbpHeap(void)
164 {
165 return g_Heap;
166 }
167
168 LPVOID SdbpAlloc(SIZE_T size
169 #if SDBAPI_DEBUG_ALLOC
170 , int line, const char* file
171 #endif
172 )
173 {
174 LPVOID mem = HeapAlloc(SdbpHeap(), HEAP_ZERO_MEMORY, size);
175 #if SDBAPI_DEBUG_ALLOC
176 SdbpInsertAllocation(mem, size, line, file);
177 #endif
178 return mem;
179 }
180
181 LPVOID SdbpReAlloc(LPVOID mem, SIZE_T size
182 #if SDBAPI_DEBUG_ALLOC
183 , int line, const char* file
184 #endif
185 )
186 {
187 LPVOID newmem = HeapReAlloc(SdbpHeap(), HEAP_ZERO_MEMORY, mem, size);
188 #if SDBAPI_DEBUG_ALLOC
189 SdbpUpdateAllocation(mem, newmem, size, line, file);
190 #endif
191 return newmem;
192 }
193
194 void SdbpFree(LPVOID mem
195 #if SDBAPI_DEBUG_ALLOC
196 , int line, const char* file
197 #endif
198 )
199 {
200 #if SDBAPI_DEBUG_ALLOC
201 SdbpRemoveAllocation(mem, line, file);
202 #endif
203 HeapFree(SdbpHeap(), 0, mem);
204 }