master
  1/**
  2 * This file has no copyright assigned and is placed in the Public Domain.
  3 * This file is part of the mingw-w64 runtime package.
  4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5 */
  6
  7#ifndef _WRL_COREWRAPPERS_H_
  8#define _WRL_COREWRAPPERS_H_
  9
 10#include <type_traits>
 11
 12#include <windows.h>
 13#include <intsafe.h>
 14#include <winstring.h>
 15#include <roapi.h>
 16
 17/* #include <wrl/def.h> */
 18#include <wrl/internal.h>
 19
 20namespace Microsoft {
 21    namespace WRL {
 22        namespace Details {
 23            struct Dummy {};
 24        }
 25
 26        namespace Wrappers {
 27            class HStringReference;
 28
 29            class HString {
 30            public:
 31                HString() throw() : hstr_(nullptr) {}
 32
 33                HString(HString&& o) throw() : hstr_(o.hstr_) {
 34                    o.hstr_ = nullptr;
 35                }
 36
 37                HString(const HString&) = delete;
 38                HString& operator=(const HString&) = delete;
 39
 40                operator HSTRING() const throw() {
 41                    return hstr_;
 42                }
 43
 44                ~HString() throw() {
 45                    Release();
 46                }
 47
 48                HString& operator=(HString&& o) throw() {
 49                    Release();
 50                    hstr_ = o.hstr_;
 51                    o.hstr_ = nullptr;
 52                    return *this;
 53                }
 54
 55                HRESULT Set(const wchar_t *s, unsigned int l) throw() {
 56                    Release();
 57                    return ::WindowsCreateString(s, l, &hstr_);
 58                }
 59
 60                template <size_t s>
 61                HRESULT Set(const wchar_t (&str)[s]) throw() {
 62                    static_assert(static_cast<size_t>(static_cast<UINT32>(s - 1)) == s - 1, "mismatch string length");
 63                    return Set(str, s - 1);
 64                }
 65
 66                template <size_t s>
 67                HRESULT Set(wchar_t (&strRef)[s]) throw() {
 68                    const wchar_t *str = static_cast<const wchar_t *>(strRef);
 69                    unsigned int l;
 70                    HRESULT hr = SizeTToUInt32(::wcslen(str), &l);
 71                    if (SUCCEEDED(hr))
 72                        hr = Set(str, l);
 73                    return hr;
 74                }
 75
 76                template <typename T>
 77                HRESULT Set(const T& s, typename ::std::enable_if<::std::is_convertible<const T&, const wchar_t *>::value, ::Microsoft::WRL::Details::Dummy>::type = ::Microsoft::WRL::Details::Dummy()) throw() {
 78                    HRESULT hr = S_OK;
 79                    const wchar_t *str = static_cast<PCWSTR>(s);
 80                    if (str != nullptr) {
 81                        unsigned int l;
 82                        hr = SizeTToUInt32(::wcslen(str), &l);
 83                        if (SUCCEEDED(hr))
 84                            hr = Set(str, l);
 85                    }
 86                    else
 87                        hr = Set(L"", 0);
 88                    return hr;
 89                }
 90
 91                HRESULT Set(const HSTRING& s) throw() {
 92                    HRESULT hr = S_OK;
 93                    if (s == nullptr || s != hstr_) {
 94                        Release();
 95                        hr = ::WindowsDuplicateString(s, &hstr_);
 96                    }
 97                    return hr;
 98                }
 99
100                void Attach(HSTRING h) throw() {
101                    ::WindowsDeleteString(hstr_);
102                    hstr_ = h;
103                }
104
105                HSTRING Detach() throw() {
106                    HSTRING t = hstr_;
107                    hstr_ = nullptr;
108                    return t;
109                }
110
111                HSTRING* GetAddressOf() throw() {
112                    Release();
113                    return &hstr_;
114                }
115
116                HSTRING* ReleaseAndGetAddressOf() throw() {
117                    Release();
118                    return &hstr_;
119                }
120
121                HSTRING Get() const throw() {
122                    return hstr_;
123                }
124
125                void Release() throw() {
126                    ::WindowsDeleteString(hstr_);
127                    hstr_ = nullptr;
128                }
129
130                bool IsValid() const throw() {
131                    return hstr_ != nullptr;
132                }
133
134                UINT32 Length() const throw() {
135                    return ::WindowsGetStringLen(hstr_);
136                }
137
138                const wchar_t* GetRawBuffer(unsigned int *l) const {
139                    return ::WindowsGetStringRawBuffer(hstr_, l);
140                }
141
142                HRESULT CopyTo(HSTRING *s) const throw() {
143                    return ::WindowsDuplicateString(hstr_, s);
144                }
145
146                HRESULT Duplicate(const HString& o) throw() {
147                    HSTRING l;
148                    HRESULT hr = ::WindowsDuplicateString(o, &l);
149                    return ReleaseAndAssignOnSuccess(hr, l, *this);
150                }
151
152                bool IsEmpty() const throw() {
153                    return hstr_ == nullptr;
154                }
155
156                HRESULT Concat(const HString& s, HString& n) const throw() {
157                    HSTRING l;
158                    HRESULT hr = ::WindowsConcatString(hstr_, s, &l);
159                    return ReleaseAndAssignOnSuccess(hr, l, n);
160                }
161
162                HRESULT TrimStart(const HString& t, HString& n) const throw() {
163                    HSTRING l;
164                    HRESULT hr = ::WindowsTrimStringStart(hstr_, t, &l);
165                    return ReleaseAndAssignOnSuccess(hr, l, n);
166                }
167
168                HRESULT TrimEnd(const HString& t, HString& n) const throw() {
169                    HSTRING l;
170                    HRESULT hr = ::WindowsTrimStringEnd(hstr_, t, &l);
171                    return ReleaseAndAssignOnSuccess(hr, l, n);
172                }
173
174                HRESULT Substring(UINT32 s, HString& n) const throw() {
175                    HSTRING l;
176                    HRESULT hr = ::WindowsSubstring(hstr_, s, &l);
177                    return ReleaseAndAssignOnSuccess(hr, l, n);
178                }
179
180                HRESULT Substring(UINT32 s, UINT32 len, HString& n) const throw() {
181                    HSTRING l;
182                    HRESULT hr = ::WindowsSubstringWithSpecifiedLength(hstr_, s, len, &l);
183                    return ReleaseAndAssignOnSuccess(hr, l, n);
184                }
185
186                HRESULT Replace(const HString& s1, const HString& s2, HString& n) const throw() {
187                    HSTRING l;
188                    HRESULT hr = ::WindowsReplaceString(hstr_, s1, s2, &l);
189                    return ReleaseAndAssignOnSuccess(hr, l, n);
190                }
191
192                template<unsigned int s>
193                static HStringReference MakeReference(wchar_t const (&str)[s]) throw();
194
195                template<unsigned int s>
196                static HStringReference MakeReference(wchar_t const (&str)[s], unsigned int l) throw();
197
198            private:
199                static HRESULT ReleaseAndAssignOnSuccess(HRESULT hr, HSTRING n, HString& t) {
200                    if (SUCCEEDED(hr)) {
201                        *t.ReleaseAndGetAddressOf() = n;
202                    }
203                    return hr;
204                }
205
206            protected:
207                HSTRING hstr_;
208            };
209
210            class HStringReference {
211            private:
212                void Init(const wchar_t* str, unsigned int len) {
213                    HRESULT hres = ::WindowsCreateStringReference(str, len, &header_, &hstr_);
214                    if (FAILED(hres))
215                        ::Microsoft::WRL::Details::RaiseException(hres);
216                }
217
218                HStringReference() : hstr_(nullptr) {}
219
220            public:
221                HStringReference(const wchar_t* str, unsigned int len) throw() : hstr_(nullptr) {
222                    Init(str, len);
223                }
224
225                template<unsigned int sizeDest>
226                 explicit HStringReference(wchar_t const (&str)[sizeDest]) throw() : hstr_(nullptr) {
227                    Init(str, sizeDest - 1);
228                }
229
230                template <size_t sizeDest>
231                explicit HStringReference(wchar_t (&strRef)[sizeDest]) throw() {
232                    const wchar_t *str = static_cast<const wchar_t*>(strRef);
233                    Init(str, ::wcslen(str));
234                }
235
236                template<typename T>
237                explicit HStringReference(const T &strRef) throw() : hstr_(nullptr) {
238                    const wchar_t* str = static_cast<const wchar_t*>(strRef);
239                    size_t len = ::wcslen(str);
240                    if(static_cast<size_t>(static_cast<unsigned int>(len)) != len)
241                        ::Microsoft::WRL::Details::RaiseException(INTSAFE_E_ARITHMETIC_OVERFLOW);
242                    Init(str, len);
243                }
244
245                HStringReference(const HStringReference &other) throw() : hstr_(nullptr) {
246                    unsigned int len = 0;
247                    const wchar_t* value = other.GetRawBuffer(&len);
248                    Init(value, len);
249                }
250
251                ~HStringReference() throw() {
252                    hstr_ = nullptr;
253                }
254
255                HStringReference& operator=(const HStringReference &other) throw() {
256                    unsigned int len = 0;
257                    const wchar_t* value = other.GetRawBuffer(&len);
258                    Init(value, len);
259                    return *this;
260                }
261
262                HSTRING Get() const throw() {
263                    return hstr_;
264                }
265
266                const wchar_t *GetRawBuffer(unsigned int *len) const {
267                    return ::WindowsGetStringRawBuffer(hstr_, len);
268                }
269
270                HRESULT CopyTo(HSTRING *str) const throw() {
271                    return ::WindowsDuplicateString(hstr_, str);
272                }
273
274                friend class HString;
275
276            protected:
277                HSTRING_HEADER header_;
278                HSTRING hstr_;
279            };
280
281            class RoInitializeWrapper {
282            public:
283                RoInitializeWrapper(RO_INIT_TYPE flags) {
284                    hres = ::Windows::Foundation::Initialize(flags);
285                }
286
287                ~RoInitializeWrapper() {
288                    if(SUCCEEDED(hres))
289                        ::Windows::Foundation::Uninitialize();
290                }
291
292                operator HRESULT() {
293                    return hres;
294                }
295            private:
296                HRESULT hres;
297            };
298        }
299    }
300}
301
302#endif