diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index f85423ea85..521cc3c4af 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -117,4 +117,6 @@ AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam) return FALSE; } +#define SHAlloc CoTaskMemAlloc + #endif /* _PRECOMP_H__ */ diff --git a/dll/win32/shell32/wine/shell32_main.h b/dll/win32/shell32/wine/shell32_main.h index 170d844b4b..31c7e468db 100644 --- a/dll/win32/shell32/wine/shell32_main.h +++ b/dll/win32/shell32/wine/shell32_main.h @@ -192,6 +192,8 @@ LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT HRESULT WINAPI DoRegisterServer(void); HRESULT WINAPI DoUnregisterServer(void); +#define SHAlloc CoTaskMemAlloc + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/dll/win32/shell32/wine/shellole.c b/dll/win32/shell32/wine/shellole.c index ae9a39bb8f..cb942266b0 100644 --- a/dll/win32/shell32/wine/shellole.c +++ b/dll/win32/shell32/wine/shellole.c @@ -306,6 +306,7 @@ HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal) * SEE ALSO * CoTaskMemAlloc, SHLoadOLE */ +#undef SHAlloc LPVOID WINAPI SHAlloc(SIZE_T len) { LPVOID ret; @@ -314,6 +315,7 @@ LPVOID WINAPI SHAlloc(SIZE_T len) TRACE("%u bytes at %p\n",len, ret); return ret; } +#define SHAlloc CoTaskMemAlloc /************************************************************************* * SHFree [SHELL32.195] diff --git a/sdk/lib/rtl/heap.c b/sdk/lib/rtl/heap.c index 1c6df2996f..b75dcdf556 100644 --- a/sdk/lib/rtl/heap.c +++ b/sdk/lib/rtl/heap.c @@ -1911,7 +1911,7 @@ RtlpAllocateNonDedicated(PHEAP Heap, * @implemented */ PVOID NTAPI -RtlAllocateHeap(IN PVOID HeapPtr, +RtlAllocateHeap2(IN PVOID HeapPtr, IN ULONG Flags, IN SIZE_T Size) { @@ -2155,7 +2155,7 @@ RtlAllocateHeap(IN PVOID HeapPtr, * * @implemented */ -BOOLEAN NTAPI RtlFreeHeap( +BOOLEAN NTAPI RtlFreeHeap2( HANDLE HeapPtr, /* [in] Handle of heap */ ULONG Flags, /* [in] Heap freeing flags */ PVOID Ptr /* [in] Address of memory to free */ @@ -2290,6 +2290,179 @@ BOOLEAN NTAPI RtlFreeHeap( return TRUE; } +#define NUM_FRAMES 6 +struct +{ + PVOID Ptr; + ULONG BacktraceHash; +} HeapAllocations[8192]; +LONG HeapAllocationHint; +struct +{ + ULONG BacktraceHash; + PVOID Backtrace[NUM_FRAMES]; + LONG Count; +} HeapCallers[16384]; + +VOID +DumpTopCallers(VOID) +{ +#define N_MAX 2 + ULONG Index; + LONG MaxCount[N_MAX] = { 0 }; + ULONG MaxIndex[N_MAX] = { 0 }; + ULONG iMax; + static LARGE_INTEGER LastDumpTime = { { 0 } }; + LARGE_INTEGER CurrentTime; + + NtQuerySystemTime(&CurrentTime); + if (CurrentTime.QuadPart - LastDumpTime.QuadPart < 20000000) + { + return; + } + LastDumpTime = CurrentTime; + + for (Index = 0; Index < RTL_NUMBER_OF(HeapCallers); Index++) + { + for (iMax = 0; iMax < N_MAX; iMax++) + { + if (HeapCallers[Index].Count > MaxCount[iMax]) + { + if (iMax < N_MAX - 1) + { + MoveMemory(&MaxIndex[iMax + 1], + &MaxIndex[iMax], + (N_MAX - iMax - 1) * sizeof(MaxIndex[0])); + MoveMemory(&MaxCount[iMax + 1], + &MaxCount[iMax], + (N_MAX - iMax - 1) * sizeof(MaxCount[0])); + } + MaxIndex[iMax] = Index; + MaxCount[iMax] = HeapCallers[Index].Count; + break; + } + } + } + + for (iMax = 0; iMax < N_MAX; iMax++) + { + DPRINT1("[%wZ] Top %lu caller with %ld allocations is %p %p %p %p %p %p\n", + &NtCurrentPeb()->ProcessParameters->ImagePathName, iMax + 1, MaxCount[iMax], + HeapCallers[MaxIndex[iMax]].Backtrace[0], HeapCallers[MaxIndex[iMax]].Backtrace[1], + HeapCallers[MaxIndex[iMax]].Backtrace[2], HeapCallers[MaxIndex[iMax]].Backtrace[3], + HeapCallers[MaxIndex[iMax]].Backtrace[4], HeapCallers[MaxIndex[iMax]].Backtrace[5]); + } +} + +PVOID NTAPI +RtlAllocateHeap( + _In_ PVOID HeapPtr, + _In_ ULONG Flags, + _In_ SIZE_T Size) +{ + LONG Index; + ULONG Iterations = 0; + PVOID Ptr; + PVOID Backtrace[NUM_FRAMES]; + ULONG Hash = 0; + LONG Value; + + Ptr = RtlAllocateHeap2(HeapPtr, Flags, Size); + if (Ptr == NULL) + { + return Ptr; + } + + while (Iterations++ < RTL_NUMBER_OF(HeapAllocations)) + { + Index = (InterlockedIncrement(&HeapAllocationHint) - 1) % RTL_NUMBER_OF(HeapAllocations); + if (Index == RTL_NUMBER_OF(HeapAllocations) - 1) + { + DumpTopCallers(); + } + if (InterlockedCompareExchangePointer(&HeapAllocations[Index].Ptr, Ptr, NULL) == NULL) + { + RtlCaptureStackBackTrace(1, NUM_FRAMES, Backtrace, &Hash); + HeapAllocations[Index].BacktraceHash = Hash; + break; + } + } + if (Hash == 0) + { + //ASSERT(Hash != 0); + return Ptr; + } + for (Index = 0; Index < RTL_NUMBER_OF(HeapCallers); Index++) + { + if (HeapCallers[Index].BacktraceHash == Hash) + { + Value = InterlockedIncrement(&HeapCallers[Index].Count); + ASSERT(Value > 0); + break; + } + if (HeapCallers[Index].BacktraceHash == 0) + { + if (InterlockedCompareExchange((PLONG)&HeapCallers[Index].BacktraceHash, Hash, 0) == 0) + { + Value = InterlockedIncrement(&HeapCallers[Index].Count); + ASSERT(Value > 0); + RtlCopyMemory(HeapCallers[Index].Backtrace, + Backtrace, + sizeof(Backtrace)); + break; + } + else + { + Index--; + } + } + } + ASSERT(Index != RTL_NUMBER_OF(HeapCallers)); + return Ptr; +} + +BOOLEAN NTAPI RtlFreeHeap( + _In_ HANDLE HeapPtr, + _In_ ULONG Flags, + _In_ PVOID Ptr) +{ + LONG Index; + BOOLEAN Ret; + ULONG Hash = 0; + LONG Value; + + for (Index = 0; Index < RTL_NUMBER_OF(HeapAllocations); Index++) + { + if (HeapAllocations[Index].Ptr == Ptr) + { + Hash = HeapAllocations[Index].BacktraceHash; + HeapAllocations[Index].BacktraceHash = 0; + if (InterlockedExchangePointer(&HeapAllocations[Index].Ptr, NULL) != Ptr) + { + ASSERT(FALSE); + } + break; + } + } + //ASSERT(Hash != 0); + if (Hash != 0) + { + for (Index = 0; Index < RTL_NUMBER_OF(HeapCallers); Index++) + { + if (HeapCallers[Index].BacktraceHash == Hash) + { + Value = InterlockedDecrement(&HeapCallers[Index].Count); + ASSERT(Value >= 0); + break; + } + } + ASSERT(Index != RTL_NUMBER_OF(HeapCallers)); + } + Ret = RtlFreeHeap2(HeapPtr, Flags, Ptr); + return Ret; +} + + BOOLEAN NTAPI RtlpGrowBlockInPlace (IN PHEAP Heap, IN ULONG Flags,