1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Test for CComHeapPtr
5  * COPYRIGHT:   Copyright 2015-2020 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #ifdef HAVE_APITEST
9 #include <apitest.h>
10 #else
11 #include "atltest.h"
12 #endif
13 #include <atlbase.h>
14 
15 static PDWORD
16 test_Alloc(DWORD value)
17 {
18     PDWORD ptr = (PDWORD)::CoTaskMemAlloc(sizeof(DWORD));
19     *ptr = value;
20     return ptr;
21 }
22 
23 
24 static LONG g_OpenAllocations = 0;
25 static LONG g_Reallocations = 0;
26 
27 struct CMallocSpy : public IMallocSpy
28 {
29     STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
30     {
31         if (IsEqualGUID(riid, IID_IMallocSpy))
32         {
33             *ppvObject = this;
34         }
35         return S_OK;
36     }
37 
38     virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; }
39     virtual ULONG STDMETHODCALLTYPE Release() { return 1; }
40     virtual SIZE_T STDMETHODCALLTYPE PreAlloc(SIZE_T cbRequest) { return cbRequest; }
41     virtual LPVOID STDMETHODCALLTYPE PostAlloc(LPVOID pActual)
42     {
43         InterlockedIncrement(&g_OpenAllocations);
44         return pActual;
45     }
46     virtual LPVOID STDMETHODCALLTYPE PreFree(LPVOID pRequest, BOOL) { return pRequest; }
47     virtual void STDMETHODCALLTYPE PostFree(BOOL fSpyed)
48     {
49         if (fSpyed)
50             InterlockedDecrement(&g_OpenAllocations);
51     }
52     virtual SIZE_T STDMETHODCALLTYPE PreRealloc(LPVOID pRequest, SIZE_T cbRequest, LPVOID *ppNewRequest, BOOL)
53     {
54         *ppNewRequest = pRequest;
55         return cbRequest;
56     }
57     virtual LPVOID STDMETHODCALLTYPE PostRealloc(LPVOID pActual, BOOL fSpyed)
58     {
59         if (fSpyed)
60             InterlockedIncrement(&g_Reallocations);
61         return pActual;
62     }
63     virtual LPVOID STDMETHODCALLTYPE PreGetSize(LPVOID pRequest, BOOL) { return pRequest; }
64     virtual SIZE_T STDMETHODCALLTYPE PostGetSize(SIZE_T cbActual, BOOL) { return cbActual; }
65     virtual LPVOID STDMETHODCALLTYPE PreDidAlloc(LPVOID pRequest, BOOL) { return pRequest; }
66     virtual int STDMETHODCALLTYPE PostDidAlloc(LPVOID, BOOL, int fActual) { return fActual; }
67     virtual void STDMETHODCALLTYPE PreHeapMinimize() {}
68     virtual void STDMETHODCALLTYPE PostHeapMinimize() {}
69 };
70 
71 static CMallocSpy g_Spy;
72 
73 
74 START_TEST(CComHeapPtr)
75 {
76     HRESULT hr = CoRegisterMallocSpy(&g_Spy);
77     ok(SUCCEEDED(hr), "Expected CoRegisterMallocSpy to succeed, but it failed: 0x%lx\n", hr);
78 
79     {
80         ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
81         CComHeapPtr<DWORD> heapPtr1;
82         ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
83         CComHeapPtr<DWORD> heapPtr2(test_Alloc(0x11111111));
84         ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
85 
86         ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
87         ok((PDWORD)heapPtr2 != NULL, "Expected heapPtr2 to not be NULL\n");
88         ok(*heapPtr2 == 0x11111111, "Expected *heapPtr2 to be 0x11111111, but was: 0x%lx\n", *heapPtr2);
89 
90         {
91             ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
92             CComHeapPtr<DWORD> heapPtrSteal1(heapPtr1);
93             ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
94             ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
95             ok((PDWORD)heapPtrSteal1 == NULL, "Expected heapPtrSteal1 to be NULL, was: 0x%p\n", (PDWORD)heapPtrSteal1);
96             CComHeapPtr<DWORD> heapPtrSteal2(heapPtr2);
97             ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
98             ok((PDWORD)heapPtr2 == NULL, "Expected heapPtr2 to be NULL, was: 0x%p\n", (PDWORD)heapPtr2);
99             ok((PDWORD)heapPtrSteal2 != NULL, "Expected heapPtrSteal2 to not be NULL\n");
100             ok(*heapPtrSteal2 == 0x11111111, "Expected *heapPtrSteal2 to be 0x11111111, but was: 0x%lx\n", *heapPtrSteal2);
101         }
102         ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
103 
104         ok(heapPtr1.Allocate(1), "Expected Allocate to succeed\n");
105         ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
106         ok(g_Reallocations == 0, "Expected there to be 0 reallocations, was: %ld\n", g_Reallocations);
107 
108         *heapPtr1 = 0x22222222;
109         ok(*heapPtr1 == 0x22222222, "Expected *heapPtr1 to be 0x22222222, but was: 0x%lx\n", *heapPtr1);
110 
111         ok(heapPtr1.Reallocate(2), "Expected Reallocate to succeed\n");
112         heapPtr1[1] = 0x33333333;
113         ok(*heapPtr1 == 0x22222222, "Expected *heapPtr1 to be 0x22222222, but was: 0x%lx\n", *heapPtr1);
114         ok(g_Reallocations == 1, "Expected there to be 1 reallocations, was: %ld\n", g_Reallocations);
115         ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
116 
117         heapPtr2 = heapPtr1;
118         ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
119         ok(*heapPtr2 == 0x22222222, "Expected *heapPtr2 to be 0x33333333, but was: 0x%lx\n", *heapPtr2);
120         ok(heapPtr2[1] == 0x33333333, "Expected heapPtr2[1] to be 0x33333333, but was: 0x%lx\n", heapPtr2[1]);
121         ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
122     }
123     ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
124 
125     hr = CoRevokeMallocSpy();
126     ok(SUCCEEDED(hr), "Expected CoRevokeMallocSpy to succeed, but it failed: 0x%lx\n", hr);
127 }
128