summaryrefslogtreecommitdiff
path: root/src/inc/winrt/windowsstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/winrt/windowsstring.h')
-rw-r--r--src/inc/winrt/windowsstring.h774
1 files changed, 774 insertions, 0 deletions
diff --git a/src/inc/winrt/windowsstring.h b/src/inc/winrt/windowsstring.h
new file mode 100644
index 0000000000..aa18eb6f49
--- /dev/null
+++ b/src/inc/winrt/windowsstring.h
@@ -0,0 +1,774 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//
+
+#pragma once
+
+#ifndef WindowsString_h
+#define WindowsString_h
+
+#include <tchar.h> // Required by strsafe.h
+#include <intsafe.h> // For SizeTToUInt32
+#include <strsafe.h> // For StringCchLengthW.
+#include <winstring.h> // The Windows SDK header file for HSTRING and HSTRING_HEADER.
+
+//---------------------------------------------------------------------------------------------------------------------------
+// Forward declarations
+void DECLSPEC_NORETURN ThrowHR(HRESULT hr);
+
+//---------------------------------------------------------------------------------------------------------------------------
+namespace clr
+{
+ namespace winrt
+ {
+ //-------------------------------------------------------------------------------------------------------------------
+ // The internal Windows Runtime String wrapper class which doesn't throw exception when a failure occurs
+ // Note String class doesn't provide copy constructor and copy assigment. This is because the *fast* string duplicate
+ // can fail, which makes the copy constructor unusable in contexts where exceptions are not expected because it would
+ // need to throw on failure. However, a move constructor and move assignment are provided. These require a String &&
+ // argument, which prevents a *fast* string from being moved (StringReference can be cast to const String&, but not
+ // String&&).
+ class String
+ {
+ public:
+ String() throw() : _hstring(nullptr)
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ }
+
+ // Move Constructor
+ String(__inout String&& other) throw()
+ : _hstring(other._hstring)
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ other._hstring = nullptr;
+ }
+
+ // Move assignment
+ String & operator = (__inout String&& other) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ Release();
+ _hstring = other._hstring;
+ other._hstring = nullptr;
+ return *this;
+ }
+
+ // Initialize this string from a source string. A copy is made in this call.
+ // The str parameter doesn't need to be null terminated, and it may have embedded NUL characters.
+ HRESULT Initialize(_In_reads_opt_(length) const wchar_t *str, UINT32 length) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsCreateString(str, length, &local);
+ return FreeAndAssignOnSuccess(hr, local, &_hstring);
+ }
+
+ // Initialize this string from a source string. A copy is made in this call. The input string must have a terminating NULL.
+ HRESULT Initialize(__in PCWSTR str) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HRESULT hr = S_OK;
+
+ if (nullptr == str)
+ { // HSTRING functions promote null string pointers to the empty string, so we should too.
+ str = L"";
+ }
+
+ size_t length = 0;
+ if (SUCCEEDED(hr))
+ {
+ hr = StringCchLengthW(str, STRSAFE_MAX_CCH, &length);
+ }
+
+ HSTRING local = nullptr;
+ if (SUCCEEDED(hr))
+ {
+ hr = WindowsCreateString(str, static_cast<UINT32>(length), &local);
+ }
+
+ return FreeAndAssignOnSuccess(hr, local, &_hstring);
+ }
+
+ // Initialize this string from an HSTRING. A copy is made in this call.
+ HRESULT Initialize(const HSTRING& other) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsDuplicateString(other, &local);
+ return FreeAndAssignOnSuccess(hr, local, &_hstring);
+ }
+
+ ~String() throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ if (_hstring)
+ {
+ WindowsDeleteString(_hstring);
+ }
+ }
+
+ // Release the current HSTRING object and reset the member variable to empty
+ void Release() throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ if (_hstring)
+ {
+ WindowsDeleteString(_hstring);
+ _hstring = nullptr;
+ }
+ }
+
+ // Detach the current HSTRING
+ void Detach(__out HSTRING *phstring) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ *phstring = _hstring;
+ _hstring = nullptr;
+ }
+
+ // Duplicate from another String.
+ HRESULT Duplicate(__in const String& other) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsDuplicateString(other, &local);
+ return FreeAndAssignOnSuccess(hr, local, &_hstring);
+ }
+
+ // Copy/duplicate into a bare HSTRING
+ HRESULT CopyTo(__out HSTRING *phstring) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return WindowsDuplicateString(this->_hstring, phstring);
+ }
+
+ // HSTRING operator
+ operator const HSTRING&() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _hstring;
+ }
+
+ // Explicit conversion to HSTRING
+ HSTRING Get() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _hstring;
+ }
+
+ // Retrieve the address of the held hstring
+ HSTRING* Address()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return &_hstring;
+ }
+
+ // Return the address of the internal HSTRING so that the caller can overwrite it,
+ // trusting that the caller will not leak the previously held value
+ HSTRING* GetAddressOf()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return &_hstring;
+ }
+
+ // Return the address of the internal HSTRING so that the caller can overwrite it,
+ // but release the previous HSTRING to prevent a leak
+ HSTRING* ReleaseAndGetAddressOf()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ if (_hstring != nullptr)
+ {
+ WindowsDeleteString(_hstring);
+ _hstring = nullptr;
+ }
+ return &_hstring;
+ }
+
+ // Allow the wrapper to assign a new HSTRING to this wrapper, releasing the old HSTRING
+ void Attach(__in_opt HSTRING string)
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ WindowsDeleteString(_hstring);
+ _hstring = string;
+ }
+
+ // Data Access
+ UINT32 length() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return WindowsGetStringLen(_hstring);
+ }
+
+ // The size() function is an alias for length(), included to parallel stl conventions.
+ // The length() function is preferred.
+ UINT32 size() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return length();
+ }
+
+ BOOL IsEmpty() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return WindowsIsStringEmpty(_hstring);
+ }
+
+ BOOL HasEmbeddedNull() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ BOOL answer;
+ // Not capturing HRESULT
+ WindowsStringHasEmbeddedNull(_hstring, &answer);
+ return answer;
+ }
+
+ LPCWSTR GetRawBuffer(__out_opt UINT32 *length = nullptr) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return WindowsGetStringRawBuffer(_hstring, length);
+ }
+
+ HRESULT GetLpcwstr(__deref_out LPCWSTR *ppsz) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ if (HasEmbeddedNull())
+ {
+ *ppsz = nullptr;
+ return E_INVALIDARG;
+ }
+ *ppsz = WindowsGetStringRawBuffer(_hstring, nullptr);
+ return S_OK;
+ }
+
+ // CompareOrdinal
+ INT32 CompareOrdinal(const String& other) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(_hstring, other, &result);
+
+ return result;
+ }
+
+ // Concatenation
+ HRESULT Concat(const String& string, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsConcatString(_hstring, string, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ // Trim
+ HRESULT TrimStart(const String& trimString, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsTrimStringStart(_hstring, trimString, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ HRESULT TrimEnd(const String& trimString, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsTrimStringEnd(_hstring, trimString, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ // Substring
+ HRESULT Substring(UINT32 startIndex, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsSubstring(_hstring, startIndex, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ HRESULT Substring(UINT32 startIndex, UINT32 length, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsSubstringWithSpecifiedLength(_hstring, startIndex, length, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ // Replace
+ HRESULT Replace(const String& stringReplaced, const String& stringReplaceWith, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HSTRING local;
+ HRESULT hr = WindowsReplaceString(_hstring, stringReplaced, stringReplaceWith, &local);
+ return FreeAndAssignOnSuccess(hr, local, &newString._hstring);
+ }
+
+ private:
+
+ // No Copy Constructor
+ String(const String& other);
+
+ // No Copy assignment because if it can fail
+ String & operator = (const String& other);
+
+ //
+ // helper function, always returns the passed in HRESULT
+ //
+ // if the HRESULT indicates success, frees any previous *target string,
+ // and over-writes it with newValue
+ //
+ // if the HRESULT indicates failure, does nothing
+ //
+ static HRESULT FreeAndAssignOnSuccess(HRESULT hr, HSTRING newValue, __inout HSTRING *target)
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ if (SUCCEEDED(hr))
+ {
+ // InterlockedExchangePointer wouldn't have much value, unless we also modified
+ // all readers of *target to insert a ReadBarrier.
+ HSTRING oldValue = *target;
+ *target = newValue;
+ WindowsDeleteString(oldValue);
+ }
+ return hr;
+ }
+
+ HSTRING _hstring;
+ };
+
+ static_assert(sizeof(String[2]) == sizeof(HSTRING[2]), "clr::winrt::String must be same size as HSTRING!");
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // String Comparison Operators
+ inline
+ bool operator == (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return 0 == result;
+ }
+
+ inline
+ bool operator != (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return 0 != result;
+ }
+
+ inline
+ bool operator < (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return -1 == result;
+ }
+
+ inline
+ bool operator <= (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return -1 == result || 0 == result;
+ }
+
+ inline
+ bool operator > (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return 1 == result;
+ }
+
+ inline
+ bool operator >= (const String& left, const String& right) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ INT32 result = 0;
+ // Ignore the HRESULT from the following call.
+ WindowsCompareStringOrdinal(left, right, &result);
+
+ return 1 == result || 0 == result;
+ }
+
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // The internal Windows Runtime String wrapper class for passing a reference of an existing string buffer.
+ // This class is allocated on stack.
+ class StringReference
+ {
+ public:
+
+ // Constructor which takes an existing string buffer and its length as the parameters.
+ // It fills an HSTRING_HEADER struct with the parameter.
+ //
+ // Warning: The caller must ensure the lifetime of the buffer outlives this
+ // object as it does not make a copy of the wide string memory.
+ StringReference(__in_opt PCWSTR stringRef, UINT32 length) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring);
+
+ // Failfast if internal developers try to create a reference to a non-NUL terminated string
+ if (FAILED(hr))
+ {
+ RaiseException(static_cast<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
+ }
+ }
+
+ // Constructor for use with string literals.
+ // It fills an HSTRING_HEADER struct with the parameter.
+ template <UINT32 N>
+ StringReference(__in WCHAR const (&stringRef)[N]) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+
+ HRESULT hr = WindowsCreateStringReference(stringRef, N - 1 /* remove terminating NUL from length */, &_header, &_hstring);
+
+ // Failfast if internal developers try to create a reference to a non-NUL terminated string. This constructor
+ // should only be used with string literals, but someone could mistakenly use this with a local WCHAR array and
+ // forget to NUL-terminate it.
+ if (FAILED(hr))
+ {
+ RaiseException(static_cast<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
+ }
+ }
+
+ // Contructor which takes an HSTRING as the parameter. The new StringReference will not create a new copy of the original HSTRING.
+ //
+ // Warning: The caller must ensure the lifetime of the hstring argument outlives this
+ // object as it does not make a copy.
+ explicit StringReference(const HSTRING& hstring) throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ // Create the StringReference without using the _header member, but instead with whatever header is used in hstring so that we
+ // prevent copying when Duplicate() is called on this object. There is no addref, nor decrement in the destructor, since we
+ // don't know or care if it's refcounted or truly a stack allocated reference.
+ _hstring = hstring;
+ }
+
+ // const String& operator
+ operator const String&() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString();
+ }
+
+ // const HSTRING& operator
+ operator const HSTRING&() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _hstring;
+ }
+
+ // Explicit conversion to HSTRING
+ HSTRING Get() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _hstring;
+ }
+
+ // CompareOrdinal
+ INT32 CompareOrdinal(const String& other) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().CompareOrdinal(other);
+ }
+
+ // Data Access
+ UINT32 length() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().length();
+ }
+
+ UINT32 size() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().size();
+ }
+
+ BOOL IsEmpty() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().IsEmpty();
+ }
+
+ BOOL HasEmbeddedNull() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().HasEmbeddedNull();
+ }
+
+ LPCWSTR GetRawBuffer(__out_opt UINT32 *length) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().GetRawBuffer(length);
+ }
+
+ HRESULT GetLpcwstr(__deref_out LPCWSTR *ppsz) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().GetLpcwstr(ppsz);
+ }
+
+ HRESULT CopyTo(__out HSTRING *phstring) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return WindowsDuplicateString(this->_hstring, phstring);
+ }
+
+ // Concatenation
+ HRESULT Concat(const String& otherString, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().Concat(otherString, newString);
+ }
+
+ // Trim
+ HRESULT TrimStart(const String& trimString, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().TrimStart(trimString, newString);
+ }
+
+ HRESULT TrimEnd(const String& trimString, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().TrimEnd(trimString, newString);
+ }
+
+ // Substring
+ HRESULT Substring(UINT32 startIndex, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().Substring(startIndex, newString);
+ }
+
+ HRESULT Substring(UINT32 startIndex, UINT32 length, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().Substring(startIndex, length, newString);
+ }
+
+ // Replace
+ HRESULT Replace(const String& stringReplaced, const String& stringReplaceWith, __out String& newString) const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return _AsString().Replace(stringReplaced, stringReplaceWith, newString);
+ }
+
+ private:
+ // No Copy Constructor
+ StringReference(const String& other);
+
+ // No non-const WCHAR array constructor
+ template <UINT32 N>
+ StringReference(__in WCHAR (&stringRef)[N]);
+
+ // No Copy assigment
+ const StringReference & operator = (const String& other);
+
+ // No new operator
+ static void * operator new(size_t size);
+
+ // No delete operator
+ static void operator delete(void *p, size_t size);
+
+ // const String& operator
+ const String& _AsString() const throw()
+ {
+ STATIC_CONTRACT_LIMITED_METHOD;
+ return reinterpret_cast<const String&>(_hstring);
+ }
+
+ HSTRING _hstring;
+ HSTRING_HEADER _header;
+ };
+ } // namespace winrt
+} // namespace clr
+
+typedef clr::winrt::String WinRtString;
+typedef clr::winrt::StringReference WinRtStringRef;
+
+// ==========================================================
+// WinRT-specific DuplicateString variations.
+
+LPWSTR DuplicateString(
+ LPCWSTR wszString,
+ size_t cchString);
+
+LPWSTR DuplicateStringThrowing(
+ LPCWSTR wszString,
+ size_t cchString);
+
+inline
+LPWSTR DuplicateString(WinRtString const & str)
+{
+ STATIC_CONTRACT_NOTHROW;
+ UINT32 cchStr;
+ LPCWSTR wzStr = str.GetRawBuffer(&cchStr);
+ return DuplicateString(wzStr, cchStr);
+}
+
+inline
+LPWSTR DuplicateStringThrowing(WinRtString const & str)
+{
+ STATIC_CONTRACT_THROWS;
+ UINT32 cchStr;
+ LPCWSTR wzStr = str.GetRawBuffer(&cchStr);
+ return DuplicateStringThrowing(wzStr, cchStr);
+}
+
+inline
+LPWSTR DuplicateString(HSTRING const & hStr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ WinRtStringRef str(hStr);
+ UINT32 cchStr;
+ LPCWSTR wzStr = str.GetRawBuffer(&cchStr);
+ return DuplicateString(wzStr, cchStr);
+}
+
+inline
+LPWSTR DuplicateStringThrowing(HSTRING const & hStr)
+{
+ STATIC_CONTRACT_THROWS;
+ WinRtStringRef str(hStr);
+ UINT32 cchStr;
+ LPCWSTR wzStr = str.GetRawBuffer(&cchStr);
+ return DuplicateStringThrowing(wzStr, cchStr);
+}
+
+// ==========================================================
+// Convenience overloads of StringCchLength
+
+// A convenience overload that assumes cchMax is STRSAFE_MAX_CCH.
+inline
+HRESULT StringCchLength(
+ __in LPCWSTR wz,
+ __out size_t *pcch)
+{
+ // To align with HSTRING functionality (which always promotes null
+ // string pointers to the empty string), this wrapper also promotes
+ // null string pointers to empty string before forwarding to Windows'
+ // implementation. Don't skip the call to StringCchLength for null
+ // pointers because we want to continue to align with the return value
+ // when passed a null length out parameter.
+ return StringCchLengthW(wz == nullptr ? L"" : wz, size_t(STRSAFE_MAX_CCH), pcch);
+}
+
+#ifdef _WIN64
+ // A UINT32-specific overload with built-in overflow check.
+ inline
+ HRESULT StringCchLength(
+ __in LPCWSTR wz,
+ __out UINT32 *pcch)
+ {
+ if (pcch == nullptr)
+ return E_INVALIDARG;
+
+ size_t cch;
+ HRESULT hr = StringCchLength(wz, &cch);
+ if (FAILED(hr))
+ return hr;
+
+ return SizeTToUInt32(cch, pcch);
+ }
+#endif // _WIN64
+
+#ifndef DACCESS_COMPILE
+ //=====================================================================================================================
+ // Holder of CoTaskMem-allocated array of HSTRING (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::GetFileNameListForNamespace).
+ class CoTaskMemHSTRINGArrayHolder
+ {
+ public:
+ CoTaskMemHSTRINGArrayHolder()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ m_cValues = 0;
+ m_rgValues = nullptr;
+ }
+ ~CoTaskMemHSTRINGArrayHolder()
+ {
+ LIMITED_METHOD_CONTRACT;
+ Destroy();
+ }
+
+ // Destroys current array and holds new array rgValues of size cValues.
+ void Init(HSTRING * rgValues, DWORD cValues)
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ Destroy();
+ _ASSERTE(m_cValues == 0);
+
+ _ASSERTE(((cValues == 0) && (rgValues == nullptr)) ||
+ ((cValues > 0) && (rgValues != nullptr)));
+
+ m_rgValues = rgValues;
+ m_cValues = cValues;
+ }
+
+ HSTRING GetAt(DWORD index) const
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_rgValues[index];
+ }
+
+ DWORD GetCount()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_cValues;
+ }
+
+ private:
+ void Destroy()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ for (DWORD i = 0; i < m_cValues; i++)
+ {
+ if (m_rgValues[i] != nullptr)
+ {
+ WindowsDeleteString(m_rgValues[i]);
+ }
+ }
+ m_cValues = 0;
+
+ if (m_rgValues != nullptr)
+ {
+ CoTaskMemFree(m_rgValues);
+ m_rgValues = nullptr;
+ }
+ }
+
+ private:
+ DWORD m_cValues;
+ HSTRING * m_rgValues;
+ }; // class CoTaskMemHSTRINGArrayHolder
+#endif //!DACCESS_COMPILE
+
+
+#endif // WindowsString_h
+