[ATL]
authorThomas Faber <thomas.faber@reactos.org>
Sun, 18 Oct 2015 10:46:11 +0000 (10:46 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 18 Oct 2015 10:46:11 +0000 (10:46 +0000)
- Add CComHeapPtr implementation and tests. Patch by Mark Jansen.
CORE-10344 #resolve

svn path=/trunk/; revision=69593

reactos/lib/atl/atlbase.h
rostests/apitests/CMakeLists.txt
rostests/apitests/atl/CComHeapPtr.cpp [new file with mode: 0644]
rostests/apitests/atl/CMakeLists.txt [new file with mode: 0644]
rostests/apitests/atl/testlist.c [new file with mode: 0644]

index 02ceb81..bc9e9e1 100644 (file)
@@ -836,6 +836,94 @@ public:
     }
 };
 
     }
 };
 
+
+// TODO: When someone needs it, make the allocator a template, so you can use it for both
+//       CoTask* allocations, and CRT-like allocations (malloc, realloc, free)
+template<class T>
+class CComHeapPtr
+{
+public:
+    CComHeapPtr() :
+        m_Data(NULL)
+    {
+    }
+
+    explicit CComHeapPtr(T *lp) :
+        m_Data(lp)
+    {
+    }
+
+    explicit CComHeapPtr(CComHeapPtr<T> &lp)
+    {
+        m_Data = lp.Detach();
+    }
+
+    ~CComHeapPtr()
+    {
+        Release();
+    }
+
+    T *operator = (CComHeapPtr<T> &lp)
+    {
+        if (lp.m_Data != m_Data)
+            Attach(lp.Detach());
+        return *this;
+    }
+
+    bool Allocate(size_t nElements = 1)
+    {
+        ATLASSERT(m_Data == NULL);
+        m_Data = static_cast<T*>(::CoTaskMemAlloc(nElements * sizeof(T)));
+        return m_Data != NULL;
+    }
+
+    bool Reallocate(_In_ size_t nElements)
+    {
+        T* newData = static_cast<T*>(::CoTaskMemRealloc(m_Data, nElements * sizeof(T)));
+        if (newData == NULL)
+            return false;
+        m_Data = newData;
+        return true;
+    }
+
+    void Release()
+    {
+        if (m_Data)
+        {
+            ::CoTaskMemFree(m_Data);
+            m_Data = NULL;
+        }
+    }
+
+    void Attach(T *lp)
+    {
+        Release();
+        m_Data = lp;
+    }
+
+    T *Detach()
+    {
+        T *saveP = m_Data;
+        m_Data = NULL;
+        return saveP;
+    }
+
+    T **operator &()
+    {
+        ATLASSERT(m_Data == NULL);
+        return &m_Data;
+    }
+
+    operator T* () const
+    {
+        return m_Data;
+    }
+
+protected:
+    T *m_Data;
+};
+
+
 class CComBSTR
 {
 public:
 class CComBSTR
 {
 public:
index 5423e69..c111e9c 100644 (file)
@@ -4,6 +4,7 @@ add_library(apitest apitest.c)
 add_dependencies(apitest xdk)
 
 add_subdirectory(advapi32)
 add_dependencies(apitest xdk)
 
 add_subdirectory(advapi32)
+add_subdirectory(atl)
 add_subdirectory(browseui)
 add_subdirectory(com)
 add_subdirectory(crt)
 add_subdirectory(browseui)
 add_subdirectory(com)
 add_subdirectory(crt)
diff --git a/rostests/apitests/atl/CComHeapPtr.cpp b/rostests/apitests/atl/CComHeapPtr.cpp
new file mode 100644 (file)
index 0000000..6c56148
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * PROJECT:         ReactOS api tests
+ * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
+ * PURPOSE:         Test for CComHeapPtr
+ * PROGRAMMER:      Mark Jansen
+ */
+
+#include <apitest.h>
+#include <atlbase.h>
+#include <atlcom.h>
+
+static PDWORD test_Alloc(DWORD value)
+{
+    PDWORD ptr = (PDWORD)::CoTaskMemAlloc(sizeof(DWORD));
+    *ptr = value;
+    return ptr;
+}
+
+
+static LONG g_OpenAllocations = 0;
+static LONG g_Reallocations = 0;
+
+struct CMallocSpy : public IMallocSpy
+{
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
+    {
+        if (IsEqualGUID(riid, IID_IMallocSpy))
+        {
+            *ppvObject = this;
+        }
+        return S_OK;
+    }
+
+    virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; }
+    virtual ULONG STDMETHODCALLTYPE Release() { return 1; }
+    virtual ULONG STDMETHODCALLTYPE PreAlloc(ULONG cbRequest) { return cbRequest; }
+    virtual LPVOID STDMETHODCALLTYPE PostAlloc(LPVOID pActual)
+    {
+        InterlockedIncrement(&g_OpenAllocations);
+        return pActual;
+    }
+    virtual LPVOID STDMETHODCALLTYPE PreFree(LPVOID pRequest, BOOL) { return pRequest; }
+    virtual void STDMETHODCALLTYPE PostFree(BOOL fSpyed)
+    {
+        if (fSpyed)
+            InterlockedDecrement(&g_OpenAllocations);
+    }
+    virtual ULONG STDMETHODCALLTYPE PreRealloc(LPVOID pRequest, ULONG cbRequest, LPVOID *ppNewRequest, BOOL)
+    {
+        *ppNewRequest = pRequest;
+        return cbRequest;
+    }
+    virtual LPVOID STDMETHODCALLTYPE PostRealloc(LPVOID pActual, BOOL fSpyed)
+    {
+        if (fSpyed)
+            InterlockedIncrement(&g_Reallocations);
+        return pActual;
+    }
+    virtual LPVOID STDMETHODCALLTYPE PreGetSize(LPVOID pRequest, BOOL) { return pRequest; }
+    virtual ULONG STDMETHODCALLTYPE PostGetSize(ULONG cbActual, BOOL) { return cbActual; }
+    virtual LPVOID STDMETHODCALLTYPE PreDidAlloc(LPVOID pRequest, BOOL) { return pRequest; }
+    virtual int STDMETHODCALLTYPE PostDidAlloc(LPVOID, BOOL, int fActual) { return fActual; }
+    virtual void STDMETHODCALLTYPE PreHeapMinimize() {}
+    virtual void STDMETHODCALLTYPE PostHeapMinimize() {}
+};
+
+static CMallocSpy g_Spy;
+
+
+START_TEST(CComHeapPtr)
+{
+    HRESULT hr = CoRegisterMallocSpy(&g_Spy);
+    ok(SUCCEEDED(hr), "Expected CoRegisterMallocSpy to succeed, but it failed: 0x%lx\n", hr);
+
+    {
+        ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
+        CComHeapPtr<DWORD> heapPtr1;
+        ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
+        CComHeapPtr<DWORD> heapPtr2(test_Alloc(0x11111111));
+        ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+
+        ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
+        ok((PDWORD)heapPtr2 != NULL, "Expected heapPtr2 to not be NULL\n");
+        ok(*heapPtr2 == 0x11111111, "Expected *heapPtr2 to be 0x11111111, but was: 0x%lx\n", *heapPtr2);
+
+        {
+            ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+            CComHeapPtr<DWORD> heapPtrSteal1(heapPtr1);
+            ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+            ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
+            ok((PDWORD)heapPtrSteal1 == NULL, "Expected heapPtrSteal1 to be NULL, was: 0x%p\n", (PDWORD)heapPtrSteal1);
+            CComHeapPtr<DWORD> heapPtrSteal2(heapPtr2);
+            ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+            ok((PDWORD)heapPtr2 == NULL, "Expected heapPtr2 to be NULL, was: 0x%p\n", (PDWORD)heapPtr2);
+            ok((PDWORD)heapPtrSteal2 != NULL, "Expected heapPtrSteal2 to not be NULL\n");
+            ok(*heapPtrSteal2 == 0x11111111, "Expected *heapPtrSteal2 to be 0x11111111, but was: 0x%lx\n", *heapPtrSteal2);
+        }
+        ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
+
+        ok(heapPtr1.Allocate(1), "Expected Allocate to succeed\n");
+        ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+        ok(g_Reallocations == 0, "Expected there to be 0 reallocations, was: %ld\n", g_Reallocations);
+
+        *heapPtr1 = 0x22222222;
+        ok(*heapPtr1 == 0x22222222, "Expected *heapPtr1 to be 0x22222222, but was: 0x%lx\n", *heapPtr1);
+
+        ok(heapPtr1.Reallocate(2), "Expected Reallocate to succeed\n");
+        heapPtr1[1] = 0x33333333;
+        ok(*heapPtr1 == 0x22222222, "Expected *heapPtr1 to be 0x22222222, but was: 0x%lx\n", *heapPtr1);
+        ok(g_Reallocations == 1, "Expected there to be 1 reallocations, was: %ld\n", g_Reallocations);
+        ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+
+        heapPtr2 = heapPtr1;
+        ok(g_OpenAllocations == 1, "Expected there to be 1 allocations, was: %ld\n", g_OpenAllocations);
+        ok(*heapPtr2 == 0x22222222, "Expected *heapPtr2 to be 0x33333333, but was: 0x%lx\n", *heapPtr2);
+        ok(heapPtr2[1] == 0x33333333, "Expected heapPtr2[1] to be 0x33333333, but was: 0x%lx\n", heapPtr2[1]);
+        ok((PDWORD)heapPtr1 == NULL, "Expected heapPtr1 to be NULL, was: 0x%p\n", (PDWORD)heapPtr1);
+    }
+    ok(g_OpenAllocations == 0, "Expected there to be 0 allocations, was: %ld\n", g_OpenAllocations);
+
+    hr = CoRevokeMallocSpy();
+    ok(SUCCEEDED(hr), "Expected CoRevokeMallocSpy to succeed, but it failed: 0x%lx\n", hr);
+}
diff --git a/rostests/apitests/atl/CMakeLists.txt b/rostests/apitests/atl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d19b3bf
--- /dev/null
@@ -0,0 +1,12 @@
+
+set_cpp(WITH_RUNTIME)
+
+include_directories(${REACTOS_SOURCE_DIR}/lib/atl)
+
+add_executable(atl_apitest
+    CComHeapPtr.cpp
+    testlist.c)
+target_link_libraries(atl_apitest wine uuid)
+set_module_type(atl_apitest win32cui)
+add_importlibs(atl_apitest ole32 oleaut32 msvcrt kernel32)
+add_cd_file(TARGET atl_apitest DESTINATION reactos/bin FOR all)
diff --git a/rostests/apitests/atl/testlist.c b/rostests/apitests/atl/testlist.c
new file mode 100644 (file)
index 0000000..0e626c9
--- /dev/null
@@ -0,0 +1,10 @@
+#define STANDALONE
+#include <apitest.h>
+
+extern void func_CComHeapPtr(void);
+
+const struct test winetest_testlist[] =
+{
+    { "CComHeapPtr", func_CComHeapPtr },
+    { 0, 0 }
+};