Nui
Loading...
Searching...
No Matches
corewrappers.h
Go to the documentation of this file.
1//
2// Copyright (C) Microsoft Corporation
3// All rights reserved.
4//
5// Code in details namespace is for internal usage within the library code
6//
7#pragma once
8
9#include <windows.h>
10#include <intsafe.h>
11#include <winstring.h>
12#include <roapi.h>
13#ifdef BUILD_WINDOWS
14# include <winrt.h>
15#endif
16
17#include <wrl\def.h>
18#include <wrl\internal.h>
19
20// Set packing
21#pragma pack(push, 8)
22
23namespace Microsoft
24{
25 namespace WRL
26 {
27
28 namespace Details
29 {
30 // Need a type that isn't assignable from int (see other overloads of Initialize, that accept int as second
31 // arg) this is needed as part of EnableIf
32 struct Dummy
33 {};
34 }
35
36 namespace Wrappers
37 {
38
39 namespace HandleTraits
40 {
41 // Handle specializations for implemented RAII wrappers
43 {
44 typedef HANDLE Type;
45
46 inline static bool Close(_In_ Type h) throw()
47 {
48 return ::CloseHandle(h) != FALSE;
49 }
50
51 inline static Type GetInvalidValue() throw()
52 {
53 return nullptr;
54 }
55 };
56
58 {
59 typedef HANDLE Type;
60
61 inline static bool Close(_In_ Type h) throw()
62 {
63 return ::CloseHandle(h) != FALSE;
64 }
65
66 inline static HANDLE GetInvalidValue() throw()
67 {
68 return INVALID_HANDLE_VALUE;
69 }
70 };
71
74
76 {
77 typedef CRITICAL_SECTION* Type;
78
79 inline static Type GetInvalidValue() throw()
80 {
81 return nullptr;
82 }
83
84 _Releases_lock_(*cs) inline static void Unlock(_In_ Type cs) throw()
85 {
86 ::LeaveCriticalSection(cs);
87 }
88 };
89
91 {
92 _Releases_lock_(h) inline static void Unlock(_In_ Type h) throw()
93 {
94 if (::ReleaseMutex(h) == FALSE)
95 {
96 // If we cannot release mutex it indicates
97 // bug in somebody code thus we raise an exception
98 ::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
99 }
100 }
101 };
102
104 {
105 inline static void Unlock(_In_ Type h) throw()
106 {
107 if (::ReleaseSemaphore(h, 1, NULL) == FALSE)
108 {
109 // If we cannot release semaphore it indicates
110 // bug in somebody code thus we raise an exception
111 ::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
112 }
113 }
114 };
115
118
120 {
121 typedef SRWLOCK* Type;
122
123 inline static Type GetInvalidValue() throw()
124 {
125 return nullptr;
126 }
127
128 _Releases_shared_lock_(*srwlock) inline static void Unlock(_In_ Type srwlock) throw()
129 {
130 ::ReleaseSRWLockShared(srwlock);
131 }
132 };
133
135 {
136 typedef SRWLOCK* Type;
137
138 inline static Type GetInvalidValue() throw()
139 {
140 return nullptr;
141 }
142
143 _Releases_exclusive_lock_(*srwlock) inline static void Unlock(_In_ Type srwlock) throw()
144 {
145 ::ReleaseSRWLockExclusive(srwlock);
146 }
147 };
148
149 } // namespace HandleTraits
150
151 // Handle object implementation specialized with traits
152 template <typename HandleTraits>
154 {
155 public:
156 explicit HandleT(typename HandleTraits::Type h = HandleTraits::GetInvalidValue()) throw()
157 : handle_(h)
158 {}
159
160 HandleT(_Inout_ HandleT&& h) throw()
161 : handle_(h.handle_)
162 {
163 h.handle_ = HandleTraits::GetInvalidValue();
164 }
165
166 virtual ~HandleT() throw()
167 {
168 Close();
169 }
170
171 HandleT& operator=(_Inout_ HandleT&& h) throw()
172 {
173 Close();
174 handle_ = h.handle_;
175 h.handle_ = HandleTraits::GetInvalidValue();
176 return *this;
177 }
178
179 void Attach(typename HandleTraits::Type h) throw()
180 {
181 if (h != handle_)
182 {
183 Close();
184 handle_ = h;
185 }
186 }
187
188 typename HandleTraits::Type Detach() throw()
189 {
190 typename HandleTraits::Type h = handle_;
191 handle_ = HandleTraits::GetInvalidValue();
192 return h;
193 }
194
195 typename HandleTraits::Type Get() const throw()
196 {
197 return handle_;
198 }
199
200 void Close() throw()
201 {
202 if (handle_ != HandleTraits::GetInvalidValue())
203 {
204 bool ret = InternalClose();
205 if (!ret)
206 {
207 // If we cannot close the handle it indicates
208 // bug in somebody code thus we raise an exception
209 ::Microsoft::WRL::Details::RaiseException(HRESULT_FROM_WIN32(GetLastError()));
210 }
211 handle_ = HandleTraits::GetInvalidValue();
212 }
213 }
214
215 bool IsValid() const throw()
216 {
217 return handle_ != HandleTraits::GetInvalidValue();
218 }
219
220 typename HandleTraits::Type* GetAddressOf() throw()
221 {
222 return &handle_;
223 }
224
225 typename HandleTraits::Type* ReleaseAndGetAddressOf() throw()
226 {
227 Close();
228 return &handle_;
229 }
230
231 typedef HandleTraits Traits;
232
233 protected:
234 virtual bool InternalClose() throw()
235 {
236 return HandleTraits::Close(handle_);
237 }
238
239 typename HandleTraits::Type handle_;
240
241 private:
242 HandleT(const HandleT&);
243 HandleT& operator=(const HandleT&);
244 };
245
246 // HandleT comparison operators
247 template <class T>
248 bool operator==(const HandleT<T>& rhs, const HandleT<T>& lhs) throw()
249 {
250 return rhs.Get() == lhs.Get();
251 }
252
253 template <class T>
254 bool operator==(const typename HandleT<T>::Traits::Type& lhs, const HandleT<T>& rhs) throw()
255 {
256 return lhs == rhs.Get();
257 }
258
259 template <class T>
260 bool operator==(const HandleT<T>& lhs, const typename HandleT<T>::Traits::Type& rhs) throw()
261 {
262 return lhs.Get() == rhs;
263 }
264
265 template <class T>
266 bool operator!=(const HandleT<T>& lhs, const HandleT<T>& rhs) throw()
267 {
268 return lhs.Get() != rhs.Get();
269 }
270
271 template <class T>
272 bool operator!=(const typename HandleT<T>::Traits::Type& lhs, const HandleT<T>& rhs) throw()
273 {
274 return lhs != rhs.Get();
275 }
276
277 template <class T>
278 bool operator!=(const HandleT<T>& lhs, const typename HandleT<T>::Traits::Type& rhs) throw()
279 {
280 return lhs.Get() != rhs;
281 }
282
283 template <class T>
284 bool operator<(const HandleT<T>& lhs, const HandleT<T>& rhs) throw()
285 {
286 return lhs.Get() < rhs.Get();
287 }
288
290
291 // Forward declarations
292 class CriticalSection;
293 class Mutex;
294 class Semaphore;
295 class SRWLock;
296
297 namespace Details
298 {
299
300#ifdef _MSC_VER
301# pragma warning(push)
302// Disable unheld lock warning for RIAA objects
303# pragma warning(disable : 26165)
304#endif
305
306 // Shared lock object for CriticalSection
307 class SyncLockCriticalSection
308 {
309 public:
310 SyncLockCriticalSection(_Inout_ SyncLockCriticalSection&& other) throw()
311 : sync_(other.sync_)
312 {
314 }
315
316 _Releases_lock_(*sync_) ~SyncLockCriticalSection() throw()
317 {
318 InternalUnlock();
319 }
320
321 _Releases_lock_(*sync_) void Unlock() throw()
322 {
323 __WRL_ASSERT__(IsLocked());
324 InternalUnlock();
325 }
326
327 bool IsLocked() const throw()
328 {
330 }
331
332 friend class Wrappers::CriticalSection;
333
334 protected:
335 explicit SyncLockCriticalSection(
336 CRITICAL_SECTION* sync = HandleTraits::CriticalSectionTraits::GetInvalidValue()) throw()
337 : sync_(sync)
338 {}
339
340 CRITICAL_SECTION* sync_;
341
342 private:
343 // Disallow copy and assignment
344 SyncLockCriticalSection(const SyncLockCriticalSection&);
345 SyncLockCriticalSection& operator=(const SyncLockCriticalSection&);
346
347 _Releases_lock_(*sync_) void InternalUnlock() throw()
348 {
349 if (IsLocked())
350 {
351 // Instances of this class should be used on the stack
352 // and should not be passed across threads.
353 // Unlock can fail if it is called from the wrong thread
354 // or with an Invalid Handle, both of which are bugs
355 // Traits::Unlock should raise an SEH in case it cannot
356 // release the lock
357
360 }
361 }
362 };
363
364 // Exclusive lock object for SRWLock
365 class SyncLockExclusive
366 {
367 public:
368 SyncLockExclusive(_Inout_ SyncLockExclusive&& other) throw()
369 : sync_(other.sync_)
370 {
372 }
373
374 _Releases_exclusive_lock_(*sync_) ~SyncLockExclusive() throw()
375 {
376 InternalUnlock();
377 }
378
379 _Releases_exclusive_lock_(*sync_) void Unlock() throw()
380 {
381 __WRL_ASSERT__(IsLocked());
382 InternalUnlock();
383 }
384
385 bool IsLocked() const throw()
386 {
388 }
389
390 friend class Wrappers::SRWLock;
391
392 protected:
393 explicit SyncLockExclusive(
395 : sync_(sync)
396 {}
397
398 SRWLOCK* sync_;
399
400 private:
401 // Disallow copy and assignment
402 SyncLockExclusive(const SyncLockExclusive&);
403 SyncLockExclusive& operator=(const SyncLockExclusive&);
404
405 _Releases_exclusive_lock_(*sync_) void InternalUnlock() throw()
406 {
407 if (IsLocked())
408 {
411 ;
412 }
413 }
414 };
415
416 // Shared lock object for SRWLock
417 class SyncLockShared
418 {
419 public:
420 SyncLockShared(_Inout_ SyncLockShared&& other) throw()
421 : sync_(other.sync_)
422 {
424 }
425
426 _Releases_shared_lock_(*sync_) ~SyncLockShared() throw()
427 {
428 InternalUnlock();
429 }
430
431 _Releases_shared_lock_(*sync_) void Unlock() throw()
432 {
433 __WRL_ASSERT__(IsLocked());
434 InternalUnlock();
435 }
436
437 bool IsLocked() const throw()
438 {
440 }
441
442 friend class Wrappers::SRWLock;
443
444 protected:
445 explicit SyncLockShared(
447 : sync_(sync)
448 {}
449
450 SRWLOCK* sync_;
451
452 private:
453 // Disallow copy and assignment
454 SyncLockShared(const SyncLockShared&);
455 SyncLockShared& operator=(const SyncLockShared&);
456
457 _Releases_shared_lock_(*sync_) void InternalUnlock() throw()
458 {
459 if (IsLocked())
460 {
463 }
464 }
465 };
466
467#ifdef _MSC_VER
468# pragma warning(pop)
469
470# pragma warning(push)
471// Missing annotation _Releases_*
472// Possibly releasing unheld lock
473# pragma warning(disable : 26165 26167 26135)
474#endif
475 // Lock object implemenatation customzed with traits
476 template <typename SyncTraits>
477 class SyncLockWithStatusT
478 {
479 public:
480 SyncLockWithStatusT(_Inout_ SyncLockWithStatusT&& other) throw()
481 : sync_(other.sync_)
482 , status_(other.status_)
483 {
484 other.sync_ = SyncTraits::GetInvalidValue();
485 }
486
487 ~SyncLockWithStatusT() throw()
488 {
489 InternalUnlock();
490 }
491
492 void Unlock() throw()
493 {
494 __WRL_ASSERT__(IsLocked());
495 InternalUnlock();
496 }
497
498 bool IsLocked() const throw()
499 {
500 return sync_ != SyncTraits::GetInvalidValue() && (status_ == 0 || status_ == WAIT_ABANDONED);
501 }
502 // status value 0 indicates success
503 DWORD GetStatus() const throw()
504 {
505 return status_;
506 }
507
508 friend class Wrappers::Mutex;
509 friend class Wrappers::Semaphore;
510
511 protected:
512 explicit SyncLockWithStatusT(typename SyncTraits::Type sync, DWORD status) throw()
513 : status_(status)
514 , sync_(sync)
515 {}
516
517 DWORD status_;
518 typename SyncTraits::Type sync_;
519
520 private:
521 // Disallow copy and assignment
522 SyncLockWithStatusT(const SyncLockWithStatusT&);
523 SyncLockWithStatusT& operator=(const SyncLockWithStatusT&);
524
525 void InternalUnlock() throw()
526 {
527 if (IsLocked())
528 {
529 // Instances of this class should be used on the stack
530 // and should not be passed across threads.
531 // Unlock can fail if it is called from the wrong thread
532 // or with an Invalid Handle, both of which are bugs
533 // Traits::Unlock should raise an SEH in case it cannot
534 // release the lock
535
536// Cannot use _Analysis_assume_lock_held_(sync)
537// because template instantiations have differing
538// levels of indirection to the lock
539#ifdef _MSC_VER
540# pragma warning(suppress : 26110)
541#endif
542 SyncTraits::Unlock(sync_);
543 sync_ = SyncTraits::GetInvalidValue();
544 }
545 }
546 };
547
548#ifdef _MSC_VER
549# pragma warning(pop)
550#endif
551
552 } // namespace Details
553
554 // Critical section implementation
556 {
557 public:
558 typedef Details::SyncLockCriticalSection SyncLock;
559
560 explicit CriticalSection(ULONG spincount = 0) throw()
561 {
562 ::InitializeCriticalSectionEx(&cs_, spincount, 0);
563 }
564
566 {
567 ::DeleteCriticalSection(&cs_);
568 }
569
570 _Acquires_lock_(*return.sync_) _Post_same_lock_(*return.sync_, cs_) SyncLock Lock() throw()
571 {
572 return Lock(&cs_);
573 }
574
575 _Acquires_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *cs) static SyncLock
576 Lock(_In_ CRITICAL_SECTION* cs) throw()
577 {
578 ::EnterCriticalSection(cs);
579 return SyncLock(cs);
580 }
581
582 _Acquires_lock_(*return.sync_) _Post_same_lock_(*return.sync_, cs_) SyncLock TryLock() throw()
583 {
584 return TryLock(&cs_);
585 }
586
587 _Acquires_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *cs) static SyncLock
588 TryLock(_In_ CRITICAL_SECTION* cs) throw()
589 {
590 bool acquired = !!::TryEnterCriticalSection(cs);
591 _Analysis_assume_lock_held_(*cs);
592 return SyncLock((acquired) ? cs : nullptr);
593 }
594
595 bool IsValid() const throw()
596 {
597 return true;
598 }
599
600 protected:
601 CRITICAL_SECTION cs_;
602
603 private:
604 // Disallow copy and assignment
606 CriticalSection& operator=(const CriticalSection&);
607 };
608
609 // Mutex handle implementation
610 class Mutex : public HandleT<HandleTraits::MutexTraits>
611 {
612 public:
613 typedef Details::SyncLockWithStatusT<HandleTraits::MutexTraits> SyncLock;
614
615 explicit Mutex(HANDLE h) throw()
616 : HandleT(h)
617 {}
618
619 Mutex(_Inout_ Mutex&& h) throw()
621 {}
622
623 Mutex& operator=(_Inout_ Mutex&& h) throw()
624 {
625 *static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
626 return *this;
627 }
628
629 SyncLock Lock(DWORD milliseconds = INFINITE) throw()
630 {
631 return Lock(Get(), milliseconds);
632 }
633
634 static SyncLock Lock(HANDLE h, DWORD milliseconds = INFINITE) throw()
635 {
636 DWORD const status = ::WaitForSingleObjectEx(h, milliseconds, FALSE);
637 return SyncLock(h, status == WAIT_OBJECT_0 ? 0 : status);
638 }
639
640 private:
641 void Close();
642 HANDLE Detach();
643 void Attach(HANDLE);
644 HANDLE* GetAddressOf();
645 HANDLE* ReleaseAndGetAddressOf();
646 };
647
648 // Semaphore handle implementation
649 class Semaphore : public HandleT<HandleTraits::SemaphoreTraits>
650 {
651 public:
652 typedef Details::SyncLockWithStatusT<HandleTraits::SemaphoreTraits> SyncLock;
653
654 explicit Semaphore(HANDLE h) throw()
655 : HandleT(h)
656 {}
657
658 Semaphore(_Inout_ Semaphore&& h) throw()
660 {}
661
662 Semaphore& operator=(_Inout_ Semaphore&& h) throw()
663 {
664 *static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
665 return *this;
666 }
667
668 SyncLock Lock(DWORD milliseconds = INFINITE) throw()
669 {
670 return Lock(Get(), milliseconds);
671 }
672
673 static SyncLock Lock(HANDLE h, DWORD milliseconds = INFINITE) throw()
674 {
675 DWORD const status = ::WaitForSingleObjectEx(h, milliseconds, FALSE);
676 return SyncLock(h, status == WAIT_OBJECT_0 ? 0 : status);
677 }
678
679 private:
680 void Close();
681 HANDLE Detach();
682 void Attach(HANDLE);
683 HANDLE* GetAddressOf();
684 HANDLE* ReleaseAndGetAddressOf();
685 };
686
687 // Event handle implementation
688 class Event : public HandleT<HandleTraits::EventTraits>
689 {
690 public:
691 explicit Event(HANDLE h = HandleT::Traits::GetInvalidValue()) throw()
692 : HandleT(h)
693 {}
694
695 Event(_Inout_ Event&& h) throw()
697 {}
698
699 Event& operator=(_Inout_ Event&& h) throw()
700 {
701 *static_cast<HandleT*>(this) = ::Microsoft::WRL::Details::Move(h);
702 return *this;
703 }
704 };
705
706 // SRW lock implementation
708 {
709 public:
710 typedef Details::SyncLockExclusive SyncLockExclusive;
711 typedef Details::SyncLockShared SyncLockShared;
712
713 SRWLock() throw()
714 {
715 ::InitializeSRWLock(&SRWLock_);
716 }
717
718 ~SRWLock() throw()
719 {}
720
721 _Acquires_exclusive_lock_(*return.sync_) _Post_same_lock_(*return.sync_, SRWLock_) SyncLockExclusive
723 {
724 return LockExclusive(&SRWLock_);
725 }
726
727 _Acquires_exclusive_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *lock) static SyncLockExclusive
728 LockExclusive(_In_ SRWLOCK* lock) throw()
729 {
730 ::AcquireSRWLockExclusive(lock);
731 return SyncLockExclusive(lock);
732 }
733
734 _Acquires_exclusive_lock_(*return.sync_) _Post_same_lock_(*return.sync_, SRWLock_) SyncLockExclusive
736 {
737 return TryLockExclusive(&SRWLock_);
738 }
739
740 _Acquires_exclusive_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *lock) static SyncLockExclusive
741 TryLockExclusive(_In_ SRWLOCK* lock) throw()
742 {
743 bool acquired = !!::TryAcquireSRWLockExclusive(lock);
744 _Analysis_assume_lock_held_(*lock);
745 return SyncLockExclusive((acquired) ? lock : nullptr);
746 }
747
748 _Acquires_shared_lock_(*return.sync_) _Post_same_lock_(*return.sync_, SRWLock_) SyncLockShared
749 LockShared() throw()
750 {
751 return LockShared(&SRWLock_);
752 }
753
754 _Acquires_shared_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *lock) static SyncLockShared
755 LockShared(_In_ SRWLOCK* lock) throw()
756 {
757 ::AcquireSRWLockShared(lock);
758 return SyncLockShared(lock);
759 }
760
761 _Acquires_shared_lock_(*return.sync_) _Post_same_lock_(*return.sync_, SRWLock_) SyncLockShared
763 {
764 return TryLockShared(&SRWLock_);
765 }
766
767 _Acquires_shared_lock_(*return.sync_) _Post_same_lock_(*return.sync_, *lock) static SyncLockShared
768 TryLockShared(_In_ SRWLOCK* lock) throw()
769 {
770 bool acquired = !!::TryAcquireSRWLockShared(lock);
771 _Analysis_assume_lock_held_(*lock);
772 return SyncLockShared((acquired) ? lock : nullptr);
773 }
774
775 protected:
776 SRWLOCK SRWLock_;
777
778 private:
779 // Disallow copy and assignment
780 SRWLock(const SRWLock&);
781 SRWLock& operator=(const SRWLock&);
782 };
783
784 class HStringReference;
785
787 {
788 public:
789 HString() throw()
790 : hstr_(nullptr)
791 {}
792
793 HString(_Inout_ HString&& other) throw()
794 : hstr_(other.hstr_)
795 {
796 other.hstr_ = nullptr;
797 }
798
799 ~HString() throw()
800 {
801 Release();
802 }
803
804 HString& operator=(_Inout_ HString&& other) throw()
805 {
806 Release();
807 hstr_ = other.hstr_;
808 other.hstr_ = nullptr;
809 return *this;
810 }
811
812 // Initialize this string from a source string. A copy is made in this call.
813 // The str parameter doesn't need to be null terminated, and it may have embedded NUL characters.
814 HRESULT Set(_In_reads_opt_(len) const wchar_t* str, unsigned int len) throw()
815 {
816 Release();
817 return ::WindowsCreateString(str, len, &hstr_);
818 }
819
820 // Initialize the string from a const array of wchar_t. A copy is made in this call.
821 // The primary scenario here is the creation of a buffer from a string literal. Because the size is
822 // known, there is no need for length to be an explicit parameter.
823 template <size_t sizeDest>
824 HRESULT Set(const wchar_t (&str)[sizeDest]) throw()
825 {
826 static_assert(
827 static_cast<size_t>(static_cast<UINT32>(sizeDest - 1)) == sizeDest - 1,
828 "String length underflow or overflow");
829
830 return Set(str, sizeDest - 1);
831 }
832
833 // Initialize the string from a non-const array of wchar_t. A copy is made in this call.
834 // The input array must include a terminating NULL. This case differs from the
835 // one immediately above. This is intended to handle the case where the buffer size is known
836 // but the buffer may be oversized. This practice of using a buffer of known size that is
837 // guaranteed to be larger than necessary is a common optimization. This overload of initialize
838 // calls wcslen to get the length of the string and uses the size up to the first null as the length.
839 // If the caller desires to use a non-const buffer but is interested in getting support for
840 // embedded nulls, then the caller should use the overload that takes a length.
841 // Without this overload, the template above would match, and we actually want different behavior.
842 template <size_t sizeDest>
843 HRESULT Set(_In_z_ wchar_t (&strRef)[sizeDest]) throw()
844 {
845 const wchar_t* str = static_cast<const wchar_t*>(strRef);
846 unsigned int length;
847 HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
848 if (SUCCEEDED(hr))
849 {
850 hr = Set(str, length);
851 }
852
853 return hr;
854 }
855
856 // Initialize this string from a source string. A copy is made in this call. The input string must have
857 // a terminating NULL. The EnableIf ensures that this overload is only for type convertible to const
858 // wchar_t*. Without the EnableIf, this overload would be chosen for type that is implicitly
859 // convertible to HSTRING, but we want the HSTRING overload to be chosen in such cases. A template
860 // version that matches a const wchar_t* is required because a simple non-templated overload with const
861 // wchar_t* argument would match before any templated version. And so the templated version above that
862 // infers length would never get called.
863 //
864 // WARNING: If Initialize is invoked with an extern wchar_t array of unknown size, this overload will be
865 // selected, but a compilation error will occur, reporting that the unknown-size array parameter could
866 // not be converted to 'const unsigned short (&)[1]' (or 'const wchar_t (&)[1]', depending on compiler
867 // switches). If such a compilation error is encountered, replace the extern declaration in a header
868 // file with an extern selectany initialization:
869 // extern const __declspec(selectany) WCHAR SomeString[] = L"SomeText";
870 // Alternatively, (but delivering less efficiency,) add an explicit static_cast to const wchar_t* at the
871 // call site.
872 template <typename T>
873 HRESULT
874 Set(__in_opt const T& strRef, // const-ref required in case caller has a type convertible to const
875 // wchar_t*, but not copy-able
876 typename ::Microsoft::WRL::Details::EnableIf<
877 __is_convertible_to(T, const wchar_t*),
879 {
880 HRESULT hr = E_POINTER;
881 const wchar_t* str = static_cast<PCWSTR>(strRef);
882 _Analysis_assume_nullterminated_(static_cast<void*>(const_cast<wchar_t*>(
883 str))); // we trust the caller's conversion gave us a null-terminated string as-advertised.
884
885 if (str != nullptr)
886 {
887 unsigned int length;
888 hr = SizeTToUInt32(::wcslen(str), &length);
889 if (SUCCEEDED(hr))
890 {
891 hr = Set(str, length);
892 }
893 }
894 return hr;
895 }
896
897 // Initialize this string from an HSTRING. A copy is made in this call.
898 HRESULT Set(const HSTRING& str) throw()
899 {
900 HRESULT hr = S_OK;
901
902 // Guard against the case where this method is called with the argument this->hstr_ when this->hstr_
903 // is a valid HSTRING. If it's called with nullptr, allow ::WindowsDuplicateString() to return
904 // E_INVALIDARG no matter the value of this->hstr_
905 // if (static_cast<HSTRING>(str) == nullptr || static_cast<HSTRING>(str) != hstr_)
906 if (str == nullptr || str != hstr_)
907 {
908 Release();
909 hr = ::WindowsDuplicateString(str, &hstr_);
910 }
911
912 return hr;
913 }
914
915 void Attach(_In_opt_ HSTRING hstr) throw()
916 {
917 ::WindowsDeleteString(hstr_);
918 hstr_ = hstr;
919 }
920
921 HSTRING Detach() throw()
922 {
923 HSTRING tmp = hstr_;
924 hstr_ = nullptr;
925 return tmp;
926 }
927
928 HSTRING* GetAddressOf() throw()
929 {
930 Release();
931 return &hstr_;
932 }
933
934 HSTRING Get() const throw()
935 {
936 return hstr_;
937 }
938
939 void Release() throw()
940 {
941 ::WindowsDeleteString(hstr_);
942 hstr_ = nullptr;
943 }
944
945 bool IsValid() const throw()
946 {
947 return hstr_ != nullptr;
948 }
949
950 const wchar_t* GetRawBuffer(_Out_opt_ unsigned int* length) const
951 {
952 return ::WindowsGetStringRawBuffer(hstr_, length);
953 }
954
955 HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING* str) const throw()
956 {
957 return ::WindowsDuplicateString(hstr_, str);
958 }
959
960 template <unsigned int sizeDest>
961 static HStringReference MakeReference(wchar_t const (&str)[sizeDest]) throw();
962
963 template <unsigned int sizeDest>
964 static HStringReference MakeReference(wchar_t const (&str)[sizeDest], unsigned int len) throw();
965
966 protected:
967 HSTRING hstr_;
968
969 private:
970 HString(_In_ const HString&) throw();
971 HString& operator=(_In_ const HString&) throw();
972 };
973
975 {
976 private:
977 void CreateReference(const wchar_t* str, unsigned int bufferLen, unsigned int len)
978 {
979 __WRL_ASSERT__(len < bufferLen);
980 if (len >= bufferLen)
981 {
982 len = bufferLen - 1;
983 }
984
985 HRESULT hr = ::WindowsCreateStringReference(str, len, &header_, &hstr_);
986 // Failfast if developers try to create a reference to a non-NUL terminated string
987 if (FAILED(hr))
988 {
990 }
991 }
992
994 : hstr_(nullptr)
995 {}
996
997 public:
998 // Constructor which takes an existing string buffer and its length as the parameters.
999 // It fills an HSTRING_HEADER struct with the parameter.
1000 //
1001 // Warning: The caller must ensure the lifetime of the buffer outlives this
1002 // object as it does not make a copy of the wide string memory.
1003 HStringReference(const wchar_t* str, unsigned int len) throw()
1004 : hstr_(nullptr)
1005 {
1006 CreateReference(str, len + 1, len);
1007 }
1008
1009 // Constructor which takes an existing literal string or const string buffer and infers its length.
1010 // It fills an HSTRING_HEADER struct with the parameter and length.
1011 template <unsigned int sizeDest>
1012 explicit HStringReference(wchar_t const (&str)[sizeDest]) throw()
1013 : hstr_(nullptr)
1014 {
1015 static_assert(
1016 static_cast<size_t>(static_cast<unsigned int>(sizeDest - 1)) == sizeDest - 1,
1017 "String length underflow or overflow");
1018
1019 CreateReference(str, sizeDest, sizeDest - 1);
1020 }
1021
1022 // Constructor which takes an non-const string buffer, and uses wcslen() to determine the string's
1023 // length. It fills an HSTRING_HEADER struct with the parameter and length. For additional information,
1024 // see the comments for String.Initialize above that takes the same template parameters
1025 template <size_t sizeDest>
1026 explicit HStringReference(_In_z_ wchar_t (&strRef)[sizeDest]) throw()
1027 {
1028 const wchar_t* str = static_cast<const wchar_t*>(strRef);
1029
1030 unsigned int length;
1031 HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
1032 if (FAILED(hr))
1033 {
1035 }
1036
1037 CreateReference(str, length + 1, length);
1038 }
1039
1040 // Constructor which takes an existing zero-terminated string buffer.
1041 // It fills an HSTRING_HEADER struct with the parameter and length.
1042 template <typename T>
1044 _In_ const T& strRef, // const-ref required in case caller has a type convertible to const wchar_t*,
1045 // but not copy-able
1046 typename ::Microsoft::WRL::Details::EnableIf<
1047 __is_convertible_to(T, const wchar_t*),
1049 : hstr_(nullptr)
1050 {
1051 const wchar_t* str = static_cast<const wchar_t*>(strRef);
1052 _Analysis_assume_nullterminated_(static_cast<void*>(const_cast<wchar_t*>(str)));
1053 _Analysis_assume_(strlen(reinterpret_cast<const char*>(str)) >= sizeof(wchar_t));
1054
1055 unsigned int length;
1056 HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
1057 if (FAILED(hr))
1058 {
1060 }
1061
1062 CreateReference(str, length + 1, length);
1063 }
1064
1065 HStringReference(_In_ const HStringReference& other) throw()
1066 : hstr_(nullptr)
1067 {
1068 unsigned int length = 0;
1069 const wchar_t* value = other.GetRawBuffer(&length);
1070 CreateReference(value, length + 1, length);
1071 }
1072
1074 {
1075 hstr_ = nullptr;
1076 }
1077
1078 HStringReference& operator=(_In_ const HStringReference& other) throw()
1079 {
1080 unsigned int length = 0;
1081 const wchar_t* value = other.GetRawBuffer(&length);
1082 CreateReference(value, length + 1, length);
1083
1084 return *this;
1085 }
1086
1087 HSTRING Get() const throw()
1088 {
1089 return hstr_;
1090 }
1091
1092 const wchar_t* GetRawBuffer(_Out_opt_ unsigned int* length) const
1093 {
1094 return ::WindowsGetStringRawBuffer(hstr_, length);
1095 }
1096
1097 HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING* str) const throw()
1098 {
1099 return ::WindowsDuplicateString(hstr_, str);
1100 }
1101
1102 friend class HString;
1103
1104 protected:
1105 HSTRING_HEADER header_;
1106 HSTRING hstr_;
1107 };
1108
1109 template <unsigned int sizeDest>
1110 inline HStringReference HString::MakeReference(wchar_t const (&str)[sizeDest]) throw()
1111 {
1112 static_assert(
1113 static_cast<size_t>(static_cast<unsigned int>(sizeDest - 1)) == sizeDest - 1,
1114 "String length underflow or overflow");
1115
1116 HStringReference hstringRef;
1117 hstringRef.CreateReference(str, sizeDest, sizeDest - 1);
1118 return hstringRef;
1119 }
1120
1121 template <unsigned int sizeDest>
1122 inline HStringReference HString::MakeReference(wchar_t const (&str)[sizeDest], unsigned int len) throw()
1123 {
1124 HStringReference hstringRef;
1125 hstringRef.CreateReference(str, sizeDest, len);
1126 return hstringRef;
1127 }
1128
1129 namespace Details
1130 {
1131 inline INT32 CompareStringOrdinal(HSTRING lhs, HSTRING rhs)
1132 {
1133 INT32 result = 0;
1134 HRESULT hr = S_OK;
1135 // Ignore the HRESULT from the following call
1136 hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
1137 if (SUCCEEDED(hr))
1138 {
1139 return result;
1140 }
1141 else
1142 {
1144 return 0;
1145 }
1146 }
1147
1148 } // namespace Details
1149
1150 // Specialization for HString
1151 inline bool operator==(const HString& lhs, const HString& rhs) throw()
1152 {
1153 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
1154 }
1155
1156 inline bool operator==(const HString& lhs, const HStringReference& rhs) throw()
1157 {
1158 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
1159 }
1160
1161 inline bool operator==(const HStringReference& lhs, const HString& rhs) throw()
1162 {
1163 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
1164 }
1165
1166 inline bool operator==(const HSTRING& lhs, const HString& rhs) throw()
1167 {
1168 return Details::CompareStringOrdinal(lhs, rhs.Get()) == 0;
1169 }
1170
1171 inline bool operator==(const HString& lhs, const HSTRING& rhs) throw()
1172 {
1173 return Details::CompareStringOrdinal(lhs.Get(), rhs) == 0;
1174 }
1175
1176 inline bool operator!=(const HString& lhs, const HString& rhs) throw()
1177 {
1178 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
1179 }
1180
1181 inline bool operator!=(const HStringReference& lhs, const HString& rhs) throw()
1182 {
1183 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
1184 }
1185
1186 inline bool operator!=(const HString& lhs, const HStringReference& rhs) throw()
1187 {
1188 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
1189 }
1190
1191 inline bool operator!=(const HSTRING& lhs, const HString& rhs) throw()
1192 {
1193 return Details::CompareStringOrdinal(lhs, rhs.Get()) != 0;
1194 }
1195
1196 inline bool operator!=(const HString& lhs, const HSTRING& rhs) throw()
1197 {
1198 return Details::CompareStringOrdinal(lhs.Get(), rhs) != 0;
1199 }
1200
1201 inline bool operator<(const HString& lhs, const HString& rhs) throw()
1202 {
1203 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 1;
1204 }
1205
1206 // Specialization for HStringReference
1207 inline bool operator==(const HStringReference& rhs, const HStringReference& lhs) throw()
1208 {
1209 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 0;
1210 }
1211
1212 inline bool operator==(const HSTRING& lhs, const HStringReference& rhs) throw()
1213 {
1214 return Details::CompareStringOrdinal(lhs, rhs.Get()) == 0;
1215 }
1216
1217 inline bool operator==(const HStringReference& lhs, const HSTRING& rhs) throw()
1218 {
1219 return Details::CompareStringOrdinal(lhs.Get(), rhs) == 0;
1220 }
1221
1222 inline bool operator!=(const HStringReference& lhs, const HStringReference& rhs) throw()
1223 {
1224 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) != 0;
1225 }
1226
1227 inline bool operator!=(const HSTRING& lhs, const HStringReference& rhs) throw()
1228 {
1229 return Details::CompareStringOrdinal(lhs, rhs.Get()) != 0;
1230 }
1231
1232 inline bool operator!=(const HStringReference& lhs, const HSTRING& rhs) throw()
1233 {
1234 return Details::CompareStringOrdinal(lhs.Get(), rhs) != 0;
1235 }
1236
1237 inline bool operator<(const HStringReference& lhs, const HStringReference& rhs) throw()
1238 {
1239 return Details::CompareStringOrdinal(lhs.Get(), rhs.Get()) == 1;
1240 }
1241
1243 {
1244 HRESULT _hr;
1245
1246 public:
1247 RoInitializeWrapper(RO_INIT_TYPE flags)
1248 {
1249 _hr = ::Windows::Foundation::Initialize(flags);
1250 }
1252 {
1253 if (SUCCEEDED(_hr))
1254 {
1255 ::Windows::Foundation::Uninitialize();
1256 }
1257 }
1258 operator HRESULT()
1259 {
1260 return _hr;
1261 }
1262 };
1263
1264 }
1265 }
1266} // namespace ::Microsoft::WRL::Wrappers
1267
1268// Restore packing
1269#pragma pack(pop)
Definition corewrappers.h:556
_Acquires_lock_ return _Post_same_lock_ return SyncLock TryLock()
Definition corewrappers.h:582
_Acquires_lock_ return _Post_same_lock_ static return SyncLock TryLock(_In_ CRITICAL_SECTION *cs)
Definition corewrappers.h:588
Details::SyncLockCriticalSection SyncLock
Definition corewrappers.h:558
~CriticalSection()
Definition corewrappers.h:565
_Acquires_lock_ return _Post_same_lock_ static return SyncLock Lock(_In_ CRITICAL_SECTION *cs)
Definition corewrappers.h:576
CRITICAL_SECTION cs_
Definition corewrappers.h:601
_Acquires_lock_ return _Post_same_lock_ return SyncLock Lock()
Definition corewrappers.h:570
bool IsValid() const
Definition corewrappers.h:595
CriticalSection(ULONG spincount=0)
Definition corewrappers.h:560
Definition corewrappers.h:689
Event & operator=(_Inout_ Event &&h)
Definition corewrappers.h:699
Event(HANDLE h=HandleT::Traits::GetInvalidValue())
Definition corewrappers.h:691
Event(_Inout_ Event &&h)
Definition corewrappers.h:695
Definition corewrappers.h:975
HStringReference(_In_z_ wchar_t(&strRef)[sizeDest])
Definition corewrappers.h:1026
HStringReference(_In_ const HStringReference &other)
Definition corewrappers.h:1065
HStringReference(const wchar_t *str, unsigned int len)
Definition corewrappers.h:1003
~HStringReference()
Definition corewrappers.h:1073
HSTRING hstr_
Definition corewrappers.h:1106
HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING *str) const
Definition corewrappers.h:1097
const wchar_t * GetRawBuffer(_Out_opt_ unsigned int *length) const
Definition corewrappers.h:1092
HStringReference(_In_ const T &strRef, typename ::Microsoft::WRL::Details::EnableIf< __is_convertible_to(T, const wchar_t *), ::Microsoft::WRL::Details::Dummy >::type=::Microsoft::WRL::Details::Dummy())
Definition corewrappers.h:1043
HSTRING_HEADER header_
Definition corewrappers.h:1105
HStringReference(wchar_t const (&str)[sizeDest])
Definition corewrappers.h:1012
HSTRING Get() const
Definition corewrappers.h:1087
HStringReference & operator=(_In_ const HStringReference &other)
Definition corewrappers.h:1078
Definition corewrappers.h:787
bool IsValid() const
Definition corewrappers.h:945
HSTRING Detach()
Definition corewrappers.h:921
void Attach(_In_opt_ HSTRING hstr)
Definition corewrappers.h:915
HSTRING hstr_
Definition corewrappers.h:967
HRESULT CopyTo(_Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING *str) const
Definition corewrappers.h:955
const wchar_t * GetRawBuffer(_Out_opt_ unsigned int *length) const
Definition corewrappers.h:950
static HStringReference MakeReference(wchar_t const (&str)[sizeDest])
Definition corewrappers.h:1110
~HString()
Definition corewrappers.h:799
void Release()
Definition corewrappers.h:939
HString()
Definition corewrappers.h:789
HRESULT Set(_In_reads_opt_(len) const wchar_t *str, unsigned int len)
Definition corewrappers.h:814
HString(_Inout_ HString &&other)
Definition corewrappers.h:793
HString & operator=(_Inout_ HString &&other)
Definition corewrappers.h:804
HSTRING * GetAddressOf()
Definition corewrappers.h:928
HRESULT Set(const wchar_t(&str)[sizeDest])
Definition corewrappers.h:824
HRESULT Set(__in_opt const T &strRef, typename ::Microsoft::WRL::Details::EnableIf< __is_convertible_to(T, const wchar_t *), ::Microsoft::WRL::Details::Dummy >::type=::Microsoft::WRL::Details::Dummy())
Definition corewrappers.h:874
HSTRING Get() const
Definition corewrappers.h:934
HRESULT Set(_In_z_ wchar_t(&strRef)[sizeDest])
Definition corewrappers.h:843
HRESULT Set(const HSTRING &str)
Definition corewrappers.h:898
Definition corewrappers.h:154
virtual bool InternalClose()
Definition corewrappers.h:234
HandleT(typename HandleTraits::Type h=HandleTraits::GetInvalidValue())
Definition corewrappers.h:156
HandleTraits::Type * ReleaseAndGetAddressOf()
Definition corewrappers.h:225
HandleTraits::Type Detach()
Definition corewrappers.h:188
HandleT & operator=(_Inout_ HandleT &&h)
Definition corewrappers.h:171
virtual ~HandleT()
Definition corewrappers.h:166
HandleT(_Inout_ HandleT &&h)
Definition corewrappers.h:160
HandleTraits Traits
Definition corewrappers.h:231
void Close()
Definition corewrappers.h:200
HandleTraits::Type handle_
Definition corewrappers.h:239
void Attach(typename HandleTraits::Type h)
Definition corewrappers.h:179
bool IsValid() const
Definition corewrappers.h:215
HandleTraits::Type Get() const
Definition corewrappers.h:195
HandleTraits::Type * GetAddressOf()
Definition corewrappers.h:220
Definition corewrappers.h:611
Mutex & operator=(_Inout_ Mutex &&h)
Definition corewrappers.h:623
Mutex(_Inout_ Mutex &&h)
Definition corewrappers.h:619
SyncLock Lock(DWORD milliseconds=INFINITE)
Definition corewrappers.h:629
static SyncLock Lock(HANDLE h, DWORD milliseconds=INFINITE)
Definition corewrappers.h:634
Mutex(HANDLE h)
Definition corewrappers.h:615
Details::SyncLockWithStatusT< HandleTraits::MutexTraits > SyncLock
Definition corewrappers.h:613
Definition corewrappers.h:1243
~RoInitializeWrapper()
Definition corewrappers.h:1251
RoInitializeWrapper(RO_INIT_TYPE flags)
Definition corewrappers.h:1247
Definition corewrappers.h:708
SRWLOCK SRWLock_
Definition corewrappers.h:776
_Acquires_shared_lock_ return _Post_same_lock_ static return SyncLockShared LockShared(_In_ SRWLOCK *lock)
Definition corewrappers.h:755
Details::SyncLockExclusive SyncLockExclusive
Definition corewrappers.h:710
Details::SyncLockShared SyncLockShared
Definition corewrappers.h:711
SRWLock()
Definition corewrappers.h:713
~SRWLock()
Definition corewrappers.h:718
_Acquires_exclusive_lock_ return _Post_same_lock_ return SyncLockExclusive LockExclusive()
Definition corewrappers.h:722
_Acquires_shared_lock_ return _Post_same_lock_ return SyncLockShared TryLockShared()
Definition corewrappers.h:762
_Acquires_exclusive_lock_ return _Post_same_lock_ static return SyncLockExclusive LockExclusive(_In_ SRWLOCK *lock)
Definition corewrappers.h:728
_Acquires_exclusive_lock_ return _Post_same_lock_ static return SyncLockExclusive TryLockExclusive(_In_ SRWLOCK *lock)
Definition corewrappers.h:741
_Acquires_shared_lock_ return _Post_same_lock_ return SyncLockShared LockShared()
Definition corewrappers.h:749
_Acquires_exclusive_lock_ return _Post_same_lock_ return SyncLockExclusive TryLockExclusive()
Definition corewrappers.h:735
_Acquires_shared_lock_ return _Post_same_lock_ static return SyncLockShared TryLockShared(_In_ SRWLOCK *lock)
Definition corewrappers.h:768
Definition corewrappers.h:650
Semaphore & operator=(_Inout_ Semaphore &&h)
Definition corewrappers.h:662
Semaphore(HANDLE h)
Definition corewrappers.h:654
Semaphore(_Inout_ Semaphore &&h)
Definition corewrappers.h:658
SyncLock Lock(DWORD milliseconds=INFINITE)
Definition corewrappers.h:668
static SyncLock Lock(HANDLE h, DWORD milliseconds=INFINITE)
Definition corewrappers.h:673
Details::SyncLockWithStatusT< HandleTraits::SemaphoreTraits > SyncLock
Definition corewrappers.h:652
#define __WRL_ASSERT__(cond)
Definition internal.h:13
RemoveReference< T >::Type && Move(_Inout_ T &&arg)
Definition internal.h:95
void RaiseException(HRESULT hr, DWORD dwExceptionFlags=EXCEPTION_NONCONTINUABLE)
Definition internal.h:49
INT32 CompareStringOrdinal(HSTRING lhs, HSTRING rhs)
Definition corewrappers.h:1131
bool operator==(const HandleT< T > &rhs, const HandleT< T > &lhs)
Definition corewrappers.h:248
bool operator<(const HandleT< T > &lhs, const HandleT< T > &rhs)
Definition corewrappers.h:284
HandleT< HandleTraits::FileHandleTraits > FileHandle
Definition corewrappers.h:289
bool operator!=(const HandleT< T > &lhs, const HandleT< T > &rhs)
Definition corewrappers.h:266
This file has no copyright assigned and is placed in the Public Domain.
Definition client.h:26
Definition corewrappers.h:33
CRITICAL_SECTION * Type
Definition corewrappers.h:77
_Releases_lock_ static cs void Unlock(_In_ Type cs)
Definition corewrappers.h:84
static Type GetInvalidValue()
Definition corewrappers.h:79
static Type GetInvalidValue()
Definition corewrappers.h:51
static bool Close(_In_ Type h)
Definition corewrappers.h:46
static bool Close(_In_ Type h)
Definition corewrappers.h:61
static HANDLE GetInvalidValue()
Definition corewrappers.h:66
HANDLE Type
Definition corewrappers.h:59
_Releases_lock_(h) inline static void Unlock(_In_ Type h)
Definition corewrappers.h:92
_Releases_exclusive_lock_ static srwlock void Unlock(_In_ Type srwlock)
Definition corewrappers.h:143
static Type GetInvalidValue()
Definition corewrappers.h:138
static Type GetInvalidValue()
Definition corewrappers.h:123
_Releases_shared_lock_ static srwlock void Unlock(_In_ Type srwlock)
Definition corewrappers.h:128
static void Unlock(_In_ Type h)
Definition corewrappers.h:105