From: Thomas Faber Date: Thu, 5 Nov 2015 10:49:52 +0000 (+0000) Subject: [ATL] X-Git-Tag: ReactOS-0.4.0~243 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=0f4f3d7cd8c7bad828f18e4ce4dbb14bca4a6851;ds=sidebyside [ATL] - Implement more CComBSTR methods. Patch by Mark Jansen. CORE-10478 #resolve svn path=/trunk/; revision=69815 --- diff --git a/reactos/lib/atl/atlbase.h b/reactos/lib/atl/atlbase.h index 26d59b32d51..675b96d8cb7 100644 --- a/reactos/lib/atl/atlbase.h +++ b/reactos/lib/atl/atlbase.h @@ -929,6 +929,11 @@ class CComBSTR public: BSTR m_str; public: + CComBSTR() : + m_str(NULL) + { + } + CComBSTR(LPCOLESTR pSrc) { if (pSrc == NULL) @@ -936,16 +941,116 @@ public: else m_str = ::SysAllocString(pSrc); } + + CComBSTR(int length) + { + if (length == 0) + m_str = NULL; + else + m_str = ::SysAllocStringLen(NULL, length); + } + + CComBSTR(int length, LPCOLESTR pSrc) + { + if (length == 0) + m_str = NULL; + else + m_str = ::SysAllocStringLen(pSrc, length); + } + + CComBSTR(PCSTR pSrc) + { + if (pSrc) + { + int len = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, NULL, 0); + m_str = ::SysAllocStringLen(NULL, len - 1); + if (m_str) + { + int res = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, m_str, len); + ATLASSERT(res == len); + if (res != len) + { + ::SysFreeString(m_str); + m_str = NULL; + } + } + } + else + { + m_str = NULL; + } + } + + CComBSTR(const CComBSTR &other) + { + m_str = other.Copy(); + } + + CComBSTR(REFGUID guid) + { + OLECHAR szGuid[40]; + ::StringFromGUID2(guid, szGuid, 40); + m_str = ::SysAllocString(szGuid); + } + ~CComBSTR() { ::SysFreeString(m_str); m_str = NULL; } - + operator BSTR () const { return m_str; } + + BSTR *operator & () + { + return &m_str; + } + + CComBSTR &operator = (const CComBSTR &other) + { + ::SysFreeString(m_str); + m_str = other.Copy(); + return *this; + } + + BSTR Copy() const + { + if (!m_str) + return NULL; + return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); + } + + HRESULT CopyTo(BSTR *other) const + { + if (!other) + return E_POINTER; + *other = Copy(); + return S_OK; + } + + bool LoadString(HMODULE module, DWORD uID) + { + ::SysFreeString(m_str); + m_str = NULL; + const wchar_t *ptr = NULL; + int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0); + if (len) + m_str = ::SysAllocStringLen(ptr, len); + return m_str != NULL; + } + + unsigned int Length() const + { + return ::SysStringLen(m_str); + } + + unsigned int ByteLength() const + { + return ::SysStringByteLen(m_str); + } }; class CComVariant : public tagVARIANT diff --git a/rostests/apitests/atl/CComBSTR.cpp b/rostests/apitests/atl/CComBSTR.cpp new file mode 100644 index 00000000000..e0ad4ce861a --- /dev/null +++ b/rostests/apitests/atl/CComBSTR.cpp @@ -0,0 +1,140 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test for CComBSTR + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include +#include "resource.h" + +#define verify_str (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_str_imp +#define verify_str2 (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : verify_str_imp2 + + +static void verify_str_imp2(const CComBSTR& comstr, PCWSTR expected, size_t ExpectedLength) +{ + BSTR str = (BSTR)comstr; + if (expected || ExpectedLength) + { + winetest_ok(str != NULL, "Expected str to be a valid pointer\n"); + if (str) + { + if (expected) + { + winetest_ok(!wcscmp(str, expected), "Expected the string to be '%s', was '%s'\n", wine_dbgstr_w(expected), wine_dbgstr_w(str)); + } + size_t Length = comstr.Length(); + winetest_ok(Length == ExpectedLength, "Expected Length to be %u, was: %u\n", ExpectedLength, Length); + Length = comstr.ByteLength(); + ExpectedLength *= sizeof(WCHAR); + winetest_ok(Length == ExpectedLength, "Expected ByteLength to be %u, was: %u\n", ExpectedLength, Length); + } + } + else + { + winetest_ok(str == NULL || str[0] == '\0', "Expected str to be empty, was: '%s'\n", wine_dbgstr_w(str)); + } +} + +static void verify_str_imp(const CComBSTR& comstr, PCWSTR expected) +{ + verify_str_imp2(comstr, expected, expected ? wcslen(expected) : 0); +} + +void test_construction() +{ + CComBSTR empty1, empty2; + CComBSTR happyW(L"I am a happy BSTR"); + CComBSTR happyA("I am a happy BSTR"); + CComBSTR happyW4(4, L"I am a happy BSTR"); + CComBSTR fromlen1(1), fromlen10(10); + CComBSTR fromBSTRW(happyW), fromBSTRA(happyA), fromBSTRW4(happyW4); + CComBSTR fromBSTRlen1(fromlen1), fromBSTRlen10(fromlen10); + + verify_str(empty1, NULL); + verify_str(empty2, NULL); + verify_str(happyW, L"I am a happy BSTR"); + verify_str(happyA, L"I am a happy BSTR"); + verify_str(happyW4, L"I am"); + verify_str2(fromlen1, NULL, 1); + verify_str2(fromlen10, NULL, 10); + verify_str(fromBSTRW, L"I am a happy BSTR"); + verify_str(fromBSTRA, L"I am a happy BSTR"); + verify_str(fromBSTRW4, L"I am"); + verify_str2(fromBSTRlen1, NULL, 1); + verify_str2(fromBSTRlen10, NULL, 10); +} + +void test_copyassignment() +{ + CComBSTR happy(L"I am a happy BSTR"), empty, odd; + CComBSTR happyCopy1, happyCopy2, emptyCopy, oddCopy; + + odd = ::SysAllocStringByteLen("aaaaa", 3); + + happyCopy1 = happy.Copy(); + happyCopy2 = happy; // Calls happyW.Copy() + emptyCopy = empty.Copy(); + oddCopy = odd.Copy(); + + verify_str(happy, L"I am a happy BSTR"); + verify_str(empty, NULL); + verify_str2(odd, L"\u6161a", 2); + verify_str(happyCopy1, L"I am a happy BSTR"); + verify_str(happyCopy2, L"I am a happy BSTR"); + verify_str(emptyCopy, NULL); + verify_str2(oddCopy, L"\u6161a", 2); + ok((BSTR)happy != (BSTR)happyCopy1, "Expected pointers to be different\n"); + ok((BSTR)happy != (BSTR)happyCopy2, "Expected pointers to be different\n"); + + + happyCopy1 = (LPCOLESTR)NULL; + happyCopy2 = (LPCSTR)NULL; + + verify_str(happyCopy1, NULL); + verify_str(happyCopy2, NULL); + + HRESULT hr = happy.CopyTo(&happyCopy1); + ok(hr == S_OK, "Expected hr to be E_POINTER, was: %08lx\n", hr); + +#if 0 + // This asserts + hr = happy.CopyTo((BSTR*)NULL); + ok(hr == E_POINTER, "Expected hr to be E_POINTER, was: %u\n"); +#endif +} + +void test_fromguid() +{ + GUID guid = { 0x12345678, 0x9abc, 0xdef0, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0} }; + CComBSTR fromGuid(guid), empty; + verify_str(fromGuid, L"{12345678-9ABC-DEF0-1234-56789ABCDEF0}"); + verify_str(empty, NULL); + empty = fromGuid; + verify_str(empty, L"{12345678-9ABC-DEF0-1234-56789ABCDEF0}"); +} + +void test_loadres() +{ + CComBSTR test1, test2, test3; + HMODULE mod = GetModuleHandle(NULL); + + ok(true == test1.LoadString(mod, IDS_TEST1), "Expected LoadString to succeed\n"); + ok(true == test2.LoadString(mod, IDS_TEST2), "Expected LoadString to succeed\n"); + ok(false == test3.LoadString(mod, IDS_TEST2 + 1), "Expected LoadString to fail\n"); + + verify_str(test1, L"Test string one."); + verify_str(test2, L"I am a happy BSTR"); + verify_str(test3, NULL); +} + +START_TEST(CComBSTR) +{ + test_construction(); + test_copyassignment(); + test_fromguid(); + test_loadres(); +} diff --git a/rostests/apitests/atl/CMakeLists.txt b/rostests/apitests/atl/CMakeLists.txt index d19b3bf2671..db0bc0835d0 100644 --- a/rostests/apitests/atl/CMakeLists.txt +++ b/rostests/apitests/atl/CMakeLists.txt @@ -4,9 +4,12 @@ set_cpp(WITH_RUNTIME) include_directories(${REACTOS_SOURCE_DIR}/lib/atl) add_executable(atl_apitest + CComBSTR.cpp CComHeapPtr.cpp - testlist.c) + testlist.c + atl_apitest.rc) + target_link_libraries(atl_apitest wine uuid) set_module_type(atl_apitest win32cui) -add_importlibs(atl_apitest ole32 oleaut32 msvcrt kernel32) +add_importlibs(atl_apitest ole32 oleaut32 user32 msvcrt kernel32) add_cd_file(TARGET atl_apitest DESTINATION reactos/bin FOR all) diff --git a/rostests/apitests/atl/atl_apitest.rc b/rostests/apitests/atl/atl_apitest.rc new file mode 100644 index 00000000000..760690b6d76 --- /dev/null +++ b/rostests/apitests/atl/atl_apitest.rc @@ -0,0 +1,11 @@ +#include +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_TEST1 "Test string one." + IDS_TEST2 "I am a happy BSTR" +END + diff --git a/rostests/apitests/atl/resource.h b/rostests/apitests/atl/resource.h new file mode 100644 index 00000000000..bc0ff64cc3b --- /dev/null +++ b/rostests/apitests/atl/resource.h @@ -0,0 +1,3 @@ + +#define IDS_TEST1 2000 +#define IDS_TEST2 2001 diff --git a/rostests/apitests/atl/testlist.c b/rostests/apitests/atl/testlist.c index 0e626c9dd0a..5712c65c9e5 100644 --- a/rostests/apitests/atl/testlist.c +++ b/rostests/apitests/atl/testlist.c @@ -1,10 +1,12 @@ #define STANDALONE #include +extern void func_CComBSTR(void); extern void func_CComHeapPtr(void); const struct test winetest_testlist[] = { + { "CComBSTR", func_CComBSTR }, { "CComHeapPtr", func_CComHeapPtr }, { 0, 0 } };