| Server IP : 209.209.40.120 / Your IP : 216.73.217.112 Web Server : Microsoft-IIS/10.0 System : Windows NT NEWWWW 10.0 build 17763 (Windows Server 2019) i586 User : NEWWWW$ ( 0) PHP Version : 8.3.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0/winrt/wrl/wrappers/ |
Upload File : |
//
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// Code in details namespace is for internal usage within the library code
//
#ifndef _WRL_COREWRAPPERS_H_
#define _WRL_COREWRAPPERS_H_
#ifdef _MSC_VER
#pragma once
#endif // _MSC_VER
#include <windows.h>
#include <intsafe.h>
#include <winstring.h>
#include <roapi.h>
#ifdef BUILD_WINDOWS
#include <winrt.h>
#endif
#include <wrl\def.h>
#include <wrl\internal.h>
// Set packing
#include <pshpack8.h>
namespace Microsoft {
namespace WRL {
namespace Details {
// Need a type that isn't assignable from int (see other overloads of Initialize, that accept int as second arg)
// this is needed as part of EnableIf
struct Dummy {};
}
namespace Wrappers {
namespace HandleTraits
{
// Handle specializations for implemented RAII wrappers
struct HANDLENullTraits
{
typedef HANDLE Type;
inline static bool Close(_In_ Type h) throw()
{
return ::CloseHandle(h) != FALSE;
}
inline static Type GetInvalidValue() throw()
{
return nullptr;
}
};
struct HANDLETraits
{
typedef HANDLE Type;
inline static bool Close(_In_ Type h) throw()
{
return ::CloseHandle(h) != FALSE;
}
inline static HANDLE GetInvalidValue() throw()
{
return INVALID_HANDLE_VALUE;
}
};
struct FileHandleTraits : HANDLETraits
{
};
struct CriticalSectionTraits
{
typedef CRITICAL_SECTION* Type;
inline static Type GetInvalidValue() throw()
{
return nullptr;
}
_Releases_lock_(*cs)
inline static void Unlock(_In_ Type cs) throw()
{
::LeaveCriticalSection(cs);
}
};
struct MutexTraits : HANDLENullTraits
{
_Releases_lock_(h)
inline static void Unlock(_In_ Type h) throw()
{
if (::ReleaseMutex(h) == FALSE)
{
// If we cannot release mutex it indicates
// bug in somebody code thus we raise an exception
::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
}
};
struct SemaphoreTraits : HANDLENullTraits
{
inline static void Unlock(_In_ Type h) throw()
{
if (::ReleaseSemaphore(h, 1, NULL) == FALSE)
{
// If we cannot release semaphore it indicates
// bug in somebody code thus we raise an exception
::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
}
};
struct EventTraits : HANDLENullTraits
{
};
struct SRWLockSharedTraits
{
typedef SRWLOCK* Type;
inline static Type GetInvalidValue() throw()
{
return nullptr;
}
_Releases_shared_lock_(*srwlock)
inline static void Unlock(_In_ Type srwlock) throw()
{
::ReleaseSRWLockShared(srwlock);
}
};
struct SRWLockExclusiveTraits
{
typedef SRWLOCK* Type;
inline static Type GetInvalidValue() throw()
{
return nullptr;
}
_Releases_exclusive_lock_(*srwlock)
inline static void Unlock(_In_ Type srwlock) throw()
{
::ReleaseSRWLockExclusive(srwlock);
}
};
} // namespace HandleTraits
// Handle object implementation specialized with traits
template <typename HandleTraits>
class HandleT
{
public:
explicit HandleT(typename HandleTraits::Type h = HandleTraits::GetInvalidValue()) throw() :
handle_(h)
{
}
HandleT(_Inout_ HandleT&& h) throw() : handle_(h.handle_)
{
h.handle_ = HandleTraits::GetInvalidValue();
}
HandleT(const HandleT&) = delete;
HandleT& operator=(const HandleT&) = delete;
~HandleT() throw()
{
Close();
}
HandleT& operator=(_Inout_ HandleT&& h) throw()
{
Close();
handle_ = h.handle_;
h.handle_ = HandleTraits::GetInvalidValue();
return *this;
}
void Attach(typename HandleTraits::Type h) throw()
{
if (h != handle_)
{
Close();
handle_ = h;
}
}
typename HandleTraits::Type Detach() throw()
{
typename HandleTraits::Type h = handle_;
handle_ = HandleTraits::GetInvalidValue();
return h;
}
typename HandleTraits::Type Get() const throw()
{
return handle_;
}
void Close() throw()
{
if (handle_ != HandleTraits::GetInvalidValue())
{
bool ret = InternalClose();
if (!ret)
{
// If we cannot close the handle it indicates
// bug in somebody code thus we raise an exception
::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
}
handle_ = HandleTraits::GetInvalidValue();
}
}
bool IsValid() const throw()
{
return handle_ != HandleTraits::GetInvalidValue();
}
typename HandleTraits::Type* GetAddressOf() throw()
{
return &handle_;
}
typename HandleTraits::Type* ReleaseAndGetAddressOf() throw()
{
Close();
return &handle_;
}
typedef HandleTraits Traits;
protected:
virtual bool InternalClose() throw()
{
return HandleTraits::Close(handle_);
}
typename HandleTraits::Type handle_;
};
// HandleT comparison operators
template<class T>
bool operator==(const HandleT<T>& rhs, const HandleT<T>& lhs) throw()
{
return rhs.Get() == lhs.Get();
}
template<class T>
bool operator==(const typename HandleT<T>::Traits::Type& lhs, const HandleT<T>& rhs) throw()
{
return lhs == rhs.Get();
}
template<class T>
bool operator==(const HandleT<T>& lhs, const typename HandleT<T>::Traits::Type& rhs) throw()
{
return lhs.Get() == rhs;
}
template<class T>
bool operator!=(const HandleT<T>& lhs, const HandleT<T>& rhs) throw()
{
return lhs.Get() != rhs.Get();
}
template<class T>
bool operator!=(const typename HandleT<T>::Traits::Type& lhs, const HandleT<T>& rhs) throw()
{
return lhs != rhs.Get();
}
template<class T>
bool operator!=(const HandleT<T>& lhs, const typename HandleT<T>::Traits::Type& rhs) throw()
{
return lhs.Get() != rhs;
}
template<class T>
bool operator<(const HandleT<T>& lhs, const HandleT<T>& rhs) throw()
{
return lhs.Get() < rhs.Get();
}
typedef HandleT<HandleTraits::FileHandleTraits> FileHandle;
// Forward declarations
class CriticalSection;
class Mutex;
class Semaphore;
class SRWLock;
namespace Details {
#pragma warning(push)
// Disable unheld lock warning for RIAA objects
#pragma warning(disable: 26165)
// Shared lock object for CriticalSection
class SyncLockCriticalSection
{
public:
SyncLockCriticalSection(_Inout_ SyncLockCriticalSection&& other) throw() : sync_(other.sync_)
{
other.sync_ = HandleTraits::CriticalSectionTraits::GetInvalidValue();
}
SyncLockCriticalSection(const SyncLockCriticalSection&) = delete;
SyncLockCriticalSection& operator=(const SyncLockCriticalSection&) = delete;
_Releases_lock_(*sync_)
~SyncLockCriticalSection() throw()
{
InternalUnlock();
}
_Releases_lock_(*sync_)
void Unlock() throw()
{
__WRL_ASSERT__(IsLocked());
InternalUnlock();
}
bool IsLocked() const throw()
{
return (sync_ != HandleTraits::CriticalSectionTraits::GetInvalidValue());
}
friend class Wrappers::CriticalSection;
protected:
explicit SyncLockCriticalSection(CRITICAL_SECTION* sync = HandleTraits::CriticalSectionTraits::GetInvalidValue()) throw() : sync_(sync)
{
}
CRITICAL_SECTION* sync_;
private:
_Releases_lock_(*sync_)
void InternalUnlock() throw()
{
if (IsLocked())
{
// Instances of this class should be used on the stack
// and should not be passed across threads.
// Unlock can fail if it is called from the wrong thread
// or with an Invalid Handle, both of which are bugs
// Traits::Unlock should raise an SEH in case it cannot
// release the lock
HandleTraits::CriticalSectionTraits::Unlock(sync_);
sync_ = HandleTraits::CriticalSectionTraits::GetInvalidValue();
}
}
};
// Exclusive lock object for SRWLock
class SyncLockExclusive
{
public:
SyncLockExclusive(_Inout_ SyncLockExclusive&& other) throw() : sync_(other.sync_)
{
other.sync_ = HandleTraits::SRWLockExclusiveTraits::GetInvalidValue();
}
SyncLockExclusive(const SyncLockExclusive&) = delete;
SyncLockExclusive& operator=(const SyncLockExclusive&) = delete;
_Releases_exclusive_lock_(*sync_)
~SyncLockExclusive() throw()
{
InternalUnlock();
}
_Releases_exclusive_lock_(*sync_)
void Unlock() throw()
{
__WRL_ASSERT__(IsLocked());
InternalUnlock();
}
bool IsLocked() const throw()
{
return (sync_ != HandleTraits::SRWLockExclusiveTraits::GetInvalidValue());
}
friend class Wrappers::SRWLock;
protected:
explicit SyncLockExclusive(SRWLOCK* sync = HandleTraits::SRWLockExclusiveTraits::GetInvalidValue()) throw() : sync_(sync)
{
}
SRWLOCK* sync_;
private:
_Releases_exclusive_lock_(*sync_)
void InternalUnlock() throw()
{
if(IsLocked())
{
HandleTraits::SRWLockExclusiveTraits::Unlock(sync_);
sync_ = HandleTraits::SRWLockExclusiveTraits::GetInvalidValue();;
}
}
};
// Shared lock object for SRWLock
class SyncLockShared
{
public:
SyncLockShared(_Inout_ SyncLockShared&& other) throw() : sync_(other.sync_)
{
other.sync_ = HandleTraits::SRWLockSharedTraits::GetInvalidValue();
}
SyncLockShared(const SyncLockShared&) = delete;
SyncLockShared& operator=(const SyncLockShared&) = delete;
_Releases_shared_lock_(*sync_)
~SyncLockShared() throw()
{
InternalUnlock();
}
_Releases_shared_lock_(*sync_)
void Unlock() throw()
{
__WRL_ASSERT__(IsLocked());
InternalUnlock();
}
bool IsLocked() const throw()
{
return (sync_ != HandleTraits::SRWLockSharedTraits::GetInvalidValue());
}
friend class Wrappers::SRWLock;
protected:
explicit SyncLockShared(SRWLOCK* sync = HandleTraits::SRWLockSharedTraits::GetInvalidValue()) throw() : sync_(sync)
{
}
SRWLOCK* sync_;
private:
_Releases_shared_lock_(*sync_)
void InternalUnlock() throw()
{
if(IsLocked())
{
HandleTraits::SRWLockSharedTraits::Unlock(sync_);
sync_ = HandleTraits::SRWLockSharedTraits::GetInvalidValue();
}
}
};
#pragma warning(pop)
#pragma warning(push)
// Missing annotation _Releases_*
// Possibly releasing unheld lock
#pragma warning(disable: 26165 26167 26135)
// Lock object implemenatation customzed with traits
template <typename SyncTraits>
class SyncLockWithStatusT
{
public:
SyncLockWithStatusT(_Inout_ SyncLockWithStatusT&& other) throw()
: status_(other.status_), sync_(other.sync_)
{
other.sync_ = SyncTraits::GetInvalidValue();
}
SyncLockWithStatusT(const SyncLockWithStatusT&) = delete;
SyncLockWithStatusT& operator=(const SyncLockWithStatusT&) = delete;
~SyncLockWithStatusT() throw()
{
InternalUnlock();
}
void Unlock() throw()
{
__WRL_ASSERT__(IsLocked());
InternalUnlock();
}
bool IsLocked() const throw()
{
return sync_ != SyncTraits::GetInvalidValue() && (status_ == 0 || status_ == WAIT_ABANDONED);
}
// status value 0 indicates success
DWORD GetStatus() const throw()
{
return status_;
}
friend class Wrappers::Mutex;
friend class Wrappers::Semaphore;
protected:
explicit SyncLockWithStatusT(typename SyncTraits::Type sync, DWORD status) throw()
: status_(status), sync_(sync)
{
}
DWORD status_;
typename SyncTraits::Type sync_;
private:
void InternalUnlock() throw()
{
if (IsLocked())
{
// Instances of this class should be used on the stack
// and should not be passed across threads.
// Unlock can fail if it is called from the wrong thread
// or with an Invalid Handle, both of which are bugs
// Traits::Unlock should raise an SEH in case it cannot
// release the lock
// Cannot use _Analysis_assume_lock_held_(sync)
// because template instantiations have differing
// levels of indirection to the lock
#pragma warning(suppress:26110)
SyncTraits::Unlock(sync_);
sync_ = SyncTraits::GetInvalidValue();
}
}
};
#pragma warning(pop)
} // namespace Details
// Critical section implementation
class CriticalSection
{
public:
typedef Details::SyncLockCriticalSection SyncLock;
explicit CriticalSection(ULONG spincount = 0) throw()
{
::InitializeCriticalSectionEx(&cs_, spincount, 0);
}
CriticalSection(const CriticalSection&) = delete;
CriticalSection& operator=(const CriticalSection&) = delete;
~CriticalSection() throw()
{
::DeleteCriticalSection(&cs_);
}
_Acquires_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, cs_)
SyncLock Lock() throw()
{
return Lock(&cs_);
}
_Acquires_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *cs)
static SyncLock Lock(_In_ CRITICAL_SECTION* cs) throw()
{
::EnterCriticalSection(cs);
return SyncLock(cs);
}
_Acquires_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, cs_)
SyncLock TryLock() throw()
{
return TryLock(&cs_);
}
_Acquires_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *cs)
static SyncLock TryLock(_In_ CRITICAL_SECTION* cs) throw()
{
bool acquired = !!::TryEnterCriticalSection(cs);
_Analysis_assume_lock_held_(*cs);
return SyncLock((acquired) ? cs : nullptr);
}
bool IsValid() const throw()
{
return true;
}
protected:
CRITICAL_SECTION cs_;
};
// Mutex handle implementation
class Mutex : public HandleT<HandleTraits::MutexTraits>
{
public:
typedef Details::SyncLockWithStatusT<HandleTraits::MutexTraits> SyncLock;
explicit Mutex(HANDLE h) throw() : HandleT(h)
{
}
Mutex(_Inout_ Mutex&& h) throw() : HandleT(::Microsoft::WRL::Details::Move(h))
{
}
Mutex& operator=(_Inout_ Mutex&& h) throw()
{
*static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
return *this;
}
SyncLock Lock(DWORD milliseconds = INFINITE) throw()
{
return Lock(Get(), milliseconds);
}
static SyncLock Lock(HANDLE h, DWORD milliseconds = INFINITE) throw()
{
DWORD const status = ::WaitForSingleObjectEx(h, milliseconds, FALSE);
return SyncLock(h, status == WAIT_OBJECT_0 ? 0 : status);
}
private:
void Close();
HANDLE Detach();
void Attach(HANDLE);
HANDLE* GetAddressOf();
HANDLE* ReleaseAndGetAddressOf();
};
// Semaphore handle implementation
class Semaphore : public HandleT<HandleTraits::SemaphoreTraits>
{
public:
typedef Details::SyncLockWithStatusT<HandleTraits::SemaphoreTraits> SyncLock;
explicit Semaphore(HANDLE h) throw() : HandleT(h)
{
}
Semaphore(_Inout_ Semaphore&& h) throw() : HandleT(::Microsoft::WRL::Details::Move(h))
{
}
Semaphore& operator=(_Inout_ Semaphore&& h) throw()
{
*static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
return *this;
}
SyncLock Lock(DWORD milliseconds = INFINITE) throw()
{
return Lock(Get(), milliseconds);
}
static SyncLock Lock(HANDLE h, DWORD milliseconds = INFINITE) throw()
{
DWORD const status = ::WaitForSingleObjectEx(h, milliseconds, FALSE);
return SyncLock(h, status == WAIT_OBJECT_0 ? 0 : status);
}
private:
void Close();
HANDLE Detach();
void Attach(HANDLE);
HANDLE* GetAddressOf();
HANDLE* ReleaseAndGetAddressOf();
};
// Event handle implementation
class Event : public HandleT<HandleTraits::EventTraits>
{
public:
explicit Event(HANDLE h = HandleT::Traits::GetInvalidValue()) throw() : HandleT(h)
{
}
Event(_Inout_ Event&& h) throw() : HandleT(::Microsoft::WRL::Details::Move(h))
{
}
Event& operator=(_Inout_ Event&& h) throw()
{
*static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
return *this;
}
};
// SRW lock implementation
class SRWLock
{
public:
typedef Details::SyncLockExclusive SyncLockExclusive;
typedef Details::SyncLockShared SyncLockShared;
SRWLock() throw()
{
::InitializeSRWLock(&SRWLock_);
}
SRWLock(const SRWLock&) = delete;
SRWLock& operator=(const SRWLock&) = delete;
~SRWLock() throw()
{
}
_Acquires_exclusive_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, SRWLock_)
SyncLockExclusive LockExclusive() throw()
{
return LockExclusive(&SRWLock_);
}
_Acquires_exclusive_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *lock)
static SyncLockExclusive LockExclusive(_In_ SRWLOCK* lock) throw()
{
::AcquireSRWLockExclusive(lock);
return SyncLockExclusive(lock);
}
_Acquires_exclusive_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, SRWLock_)
SyncLockExclusive TryLockExclusive() throw()
{
return TryLockExclusive(&SRWLock_);
}
_Acquires_exclusive_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *lock)
static SyncLockExclusive TryLockExclusive(_In_ SRWLOCK* lock) throw()
{
bool acquired = !!::TryAcquireSRWLockExclusive(lock);
_Analysis_assume_lock_held_(*lock);
return SyncLockExclusive((acquired) ? lock : nullptr);
}
_Acquires_shared_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, SRWLock_)
SyncLockShared LockShared() throw()
{
return LockShared(&SRWLock_);
}
_Acquires_shared_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *lock)
static SyncLockShared LockShared(_In_ SRWLOCK* lock) throw()
{
::AcquireSRWLockShared(lock);
return SyncLockShared(lock);
}
_Acquires_shared_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, SRWLock_)
SyncLockShared TryLockShared() throw()
{
return TryLockShared(&SRWLock_);
}
_Acquires_shared_lock_(*return.sync_)
_Post_same_lock_(*return.sync_, *lock)
static SyncLockShared TryLockShared(_In_ SRWLOCK* lock) throw()
{
bool acquired = !!::TryAcquireSRWLockShared(lock);
_Analysis_assume_lock_held_(*lock);
return SyncLockShared((acquired) ? lock : nullptr);
}
protected:
SRWLOCK SRWLock_;
};
#pragma region Application Family or OneCore Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
class HStringReference;
class HString
{
public:
HString() throw() : hstr_(nullptr)
{
}
HString(_Inout_ HString&& other) throw() : hstr_(other.hstr_)
{
other.hstr_ = nullptr;
}
HString(_In_ const HString&) = delete;
HString& operator=(_In_ const HString&) = delete;
~HString() throw()
{
Release();
}
HString& operator=(_Inout_ HString&& other) throw()
{
Release();
hstr_ = other.hstr_;
other.hstr_ = 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 Set(_In_reads_opt_(len) const wchar_t* str, unsigned int len) throw()
{
Release();
return ::WindowsCreateString(str, len, &hstr_);
}
// Initialize the string from a const array of wchar_t. A copy is made in this call.
// The primary scenario here is the creation of a buffer from a string literal. Because the size is
// known, there is no need for length to be an explicit parameter.
template <size_t sizeDest>
HRESULT Set(const wchar_t (&str)[sizeDest]) throw()
{
static_assert(static_cast<size_t>(static_cast<UINT32>(sizeDest-1)) == sizeDest - 1, "String length underflow or overflow");
return Set(str, sizeDest - 1);
}
// Initialize the string from a non-const array of wchar_t. A copy is made in this call.
// The input array must include a terminating NULL. This case differs from the
// one immediately above. This is intended to handle the case where the buffer size is known
// but the buffer may be oversized. This practice of using a buffer of known size that is
// guaranteed to be larger than necessary is a common optimization. This overload of initialize
// calls wcslen to get the length of the string and uses the size up to the first null as the length.
// If the caller desires to use a non-const buffer but is interested in getting support for
// embedded nulls, then the caller should use the overload that takes a length.
// Without this overload, the template above would match, and we actually want different behavior.
template <size_t sizeDest>
HRESULT Set(_In_z_ wchar_t (&strRef)[sizeDest]) throw()
{
const wchar_t* str = static_cast<const wchar_t*>(strRef);
unsigned int length;
HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
if (SUCCEEDED(hr))
{
hr = Set(str, length);
}
return hr;
}
// Initialize this string from a source string. A copy is made in this call. The input string must have a terminating NULL.
// The EnableIf ensures that this overload is only for type convertible to const wchar_t*. Without the EnableIf,
// this overload would be chosen for type that is implicitly convertible to HSTRING, but we want the HSTRING overload
// to be chosen in such cases. A template version that matches a const wchar_t* is required because a
// simple non-templated overload with const wchar_t* argument would match before any templated version.
// And so the templated version above that infers length would never get called.
//
// WARNING: If Initialize is invoked with an extern wchar_t array of unknown size, this overload will be selected,
// but a compilation error will occur, reporting that the unknown-size array parameter could not be converted to
// 'const unsigned short (&)[1]' (or 'const wchar_t (&)[1]', depending on compiler switches). If such a compilation
// error is encountered, replace the extern declaration in a header file with an extern selectany initialization:
// extern const __declspec(selectany) WCHAR SomeString[] = L"SomeText";
// Alternatively, (but delivering less efficiency,) add an explicit static_cast to const wchar_t* at the call site.
template <typename T>
HRESULT Set(
__in_opt const T &strRef, // const-ref required in case caller has a type convertible to const wchar_t*, but not copy-able
typename ::Microsoft::WRL::Details::EnableIf< __is_convertible_to(T,const wchar_t*), ::Microsoft::WRL::Details::Dummy>::type = ::Microsoft::WRL::Details::Dummy()) throw()
{
HRESULT hr = S_OK;
const wchar_t* str = static_cast<PCWSTR>(strRef);
_Analysis_assume_nullterminated_(static_cast<void*>(const_cast<wchar_t*>(str))); // we trust the caller's conversion gave us a null-terminated string as-advertised.
if (str != nullptr)
{
unsigned int length;
hr = SizeTToUInt32(::wcslen(str), &length);
if (SUCCEEDED(hr))
{
hr = Set(str, length);
}
}
else
{
hr = Set(L"", 0);
}
return hr;
}
// Initialize this string from an HSTRING. A copy is made in this call.
HRESULT Set(const HSTRING& str) throw()
{
HRESULT hr = S_OK;
// Guard against the case where this method is called with the argument this->hstr_ when this->hstr_ is a valid HSTRING.
// If it's called with nullptr, allow ::WindowsDuplicateString() to return E_INVALIDARG no matter the value of this->hstr_
//if (static_cast<HSTRING>(str) == nullptr || static_cast<HSTRING>(str) != hstr_)
if (str == nullptr || str != hstr_)
{
Release();
hr = ::WindowsDuplicateString(str, &hstr_);
}
return hr;
}
void Attach(_In_opt_ HSTRING hstr) throw()
{
::WindowsDeleteString(hstr_);
hstr_ = hstr;
}
HSTRING Detach() throw()
{
HSTRING tmp = hstr_;
hstr_ = nullptr;
return tmp;
}
HSTRING* GetAddressOf() throw()
{
Release(); // Note, this is a non-standard implementation, others don't release the resource.
return &hstr_;
}
HSTRING* ReleaseAndGetAddressOf() throw()
{
Release();
return &hstr_;
}
HSTRING Get() const throw()
{
return hstr_;
}
void Release() throw()
{
::WindowsDeleteString(hstr_);
hstr_ = nullptr;
}
bool IsValid() const throw()
{
return hstr_ != nullptr;
}
const wchar_t* GetRawBuffer(_Out_opt_ unsigned int* length) const
{
return ::WindowsGetStringRawBuffer(hstr_, length);
}
HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING *str) const throw()
{
return ::WindowsDuplicateString(hstr_, str);
}
template<unsigned int sizeDest>
static HStringReference MakeReference(wchar_t const (&str)[sizeDest]) throw();
template<unsigned int sizeDest>
static HStringReference MakeReference(wchar_t const (&str)[sizeDest], unsigned int len) throw();
protected:
HSTRING hstr_;
};
class HStringReference
{
private:
void CreateReference(const wchar_t* str, unsigned int bufferLen, unsigned int len)
{
__WRL_ASSERT__(len < bufferLen);
if (len >= bufferLen)
{
len = bufferLen - 1;
}
HRESULT hr = ::WindowsCreateStringReference(str, len, &header_, &hstr_);
// Failfast if developers try to create a reference to a non-NUL terminated string
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
}
HStringReference() : hstr_(nullptr)
{
}
// Returns 1 + augend
// Failfast on addition overflow
static unsigned int AddOne(const unsigned int augend) throw()
{
unsigned int result = 0; // init to make compiler happy
HRESULT hr = UIntAdd(augend, 1, &result);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
return result;
}
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.
HStringReference(const wchar_t* str, unsigned int len) throw() : hstr_(nullptr)
{
unsigned int lenPlusOne = AddOne(len);
CreateReference(str, lenPlusOne, len);
}
// Constructor which takes an existing literal string or const string buffer and infers its length.
// It fills an HSTRING_HEADER struct with the parameter and length.
template<unsigned int sizeDest>
explicit HStringReference(wchar_t const (&str)[sizeDest]) throw() : hstr_(nullptr)
{
static_assert(static_cast<size_t>(static_cast<unsigned int>(sizeDest-1)) == sizeDest-1,
"String length underflow or overflow");
CreateReference(str, sizeDest, sizeDest - 1);
}
// Constructor which takes an non-const string buffer, and uses wcslen() to determine the string's length.
// It fills an HSTRING_HEADER struct with the parameter and length.
// For additional information, see the comments for String.Initialize above that takes the same template parameters
template <size_t sizeDest>
explicit HStringReference(_In_z_ wchar_t (&strRef)[sizeDest]) throw()
{
const wchar_t* str = static_cast<const wchar_t*>(strRef);
unsigned int length;
HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
unsigned int lengthPlusOne = AddOne(length);
CreateReference(str, lengthPlusOne, length);
}
// Constructor which takes an existing zero-terminated string buffer.
// It fills an HSTRING_HEADER struct with the parameter and length.
template<typename T>
explicit HStringReference(
_In_ const T& strRef, // const-ref required in case caller has a type convertible to const wchar_t*, but not copy-able
typename ::Microsoft::WRL::Details::EnableIf<__is_convertible_to(T, const wchar_t*), ::Microsoft::WRL::Details::Dummy>::type = ::Microsoft::WRL::Details::Dummy()) throw() : hstr_(nullptr)
{
const wchar_t* str = static_cast<const wchar_t*>(strRef);
_Analysis_assume_nullterminated_(static_cast<void*>(const_cast<wchar_t*>(str)));
unsigned int length;
HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
unsigned int lengthPlusOne = AddOne(length);
CreateReference(str, lengthPlusOne, length);
}
HStringReference(_In_ const HStringReference& other) throw() : hstr_(nullptr)
{
unsigned int length = 0;
const wchar_t* value = other.GetRawBuffer(&length);
unsigned int lengthPlusOne = AddOne(length);
CreateReference(value, lengthPlusOne, length);
}
~HStringReference() throw()
{
hstr_ = nullptr;
}
HStringReference& operator=(_In_ const HStringReference& other) throw()
{
unsigned int length = 0;
const wchar_t* value = other.GetRawBuffer(&length);
unsigned int lengthPlusOne = AddOne(length);
CreateReference(value, lengthPlusOne, length);
return *this;
}
HSTRING Get() const throw()
{
return hstr_;
}
const wchar_t* GetRawBuffer(_Out_opt_ unsigned int* length) const
{
return ::WindowsGetStringRawBuffer(hstr_, length);
}
HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING *str) const throw()
{
return ::WindowsDuplicateString(hstr_, str);
}
friend class HString;
protected:
HSTRING_HEADER header_;
HSTRING hstr_;
};
template<unsigned int sizeDest>
inline HStringReference HString::MakeReference(wchar_t const (&str)[sizeDest]) throw()
{
static_assert(static_cast<size_t>(static_cast<unsigned int>(sizeDest-1)) == sizeDest-1,
"String length underflow or overflow");
HStringReference hstringRef;
hstringRef.CreateReference(str, sizeDest, sizeDest - 1);
return hstringRef;
}
template<unsigned int sizeDest>
inline HStringReference HString::MakeReference(wchar_t const (&str)[sizeDest], unsigned int len) throw()
{
HStringReference hstringRef;
hstringRef.CreateReference(str, sizeDest, len);
return hstringRef;
}
namespace Details {
inline INT32 CompareStringOrdinal(HSTRING lhs, HSTRING rhs)
{
INT32 result = 0;
HRESULT hr = S_OK;
// Ignore the HRESULT from the following call
hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
if (SUCCEEDED(hr))
{
return result;
}
else
{
::Microsoft::WRL::Details::RaiseException(hr);
}
}
} // namespace Details
// Specialization for HString
inline bool operator==(const HString& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
}
inline bool operator==(const HString& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
}
inline bool operator==(const HStringReference& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
}
inline bool operator==(const HSTRING& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs, rhs.Get()) == 0;
}
inline bool operator==(const HString& lhs, const HSTRING& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs) == 0;
}
inline bool operator!=(const HString& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
}
inline bool operator!=(const HStringReference& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
}
inline bool operator!=(const HString& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
}
inline bool operator!=(const HSTRING& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs, rhs.Get()) != 0;
}
inline bool operator!=(const HString& lhs, const HSTRING& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs) != 0;
}
inline bool operator<(const HString& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == -1;
}
inline bool operator>(const HString& lhs, const HString& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 1;
}
// Specialization for HStringReference
inline bool operator==(const HStringReference& rhs, const HStringReference& lhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
}
inline bool operator==(const HSTRING& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs, rhs.Get()) == 0;
}
inline bool operator==(const HStringReference& lhs, const HSTRING& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs) == 0;
}
inline bool operator!=(const HStringReference& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
}
inline bool operator!=(const HSTRING& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs, rhs.Get()) != 0;
}
inline bool operator!=(const HStringReference& lhs, const HSTRING& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs) != 0;
}
inline bool operator<(const HStringReference& lhs, const HStringReference& rhs) throw()
{
return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 1;
}
class RoInitializeWrapper
{
HRESULT _hr;
public:
RoInitializeWrapper(RO_INIT_TYPE flags)
{
_hr = ::Windows::Foundation::Initialize(flags);
}
~RoInitializeWrapper()
{
if (SUCCEEDED(_hr))
{
::Windows::Foundation::Uninitialize();
}
}
operator HRESULT()
{
return _hr;
}
};
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) */
#pragma endregion
} } } // namespace ::Microsoft::WRL::Wrappers
// Restore packing
#include <poppack.h>
#endif // _WRL_COREWRAPPERS_H_