Skip to content

Windows Runtime helpers

Michael Ratanapintha edited this page Aug 11, 2020 · 14 revisions

In the wil/winrt.h and wil/wrl.h header files, WIL provides helpers to facilitate consumption of Windows Runtime APIs at the ABI (unprojected) layer:

#include <wil/winrt.h>
#include <wil/wrl.h>

These helpers work well together with the smart pointers and other WinRT and COM wrappers in wil/com.h.

Note: These helpers have been superseded by the C++/WinRT projection. You should prefer C++/WinRT in new code, perhaps along with WIL's integration with C++/WinRT.

Windows Runtime DateTime

The time helpers require that <time.h> be included before including wil/winrt.h.

SecondsToStartOf1970

long long const SecondsToStartOf1970 = 0x2b6109100;

The number of seconds from the Windows Runtime epoch to January 1, 1970. The Windows Runtime epoch is January 1, 1601.

HundredNanoSecondsInSecond

long long const HundredNanoSecondsInSecond = 10000000LL;

The number of Windows Runtime time units per second. One Windows Runtime time unit is 100ns.

DateTime_to_time_t

__time64_t DateTime_to_time_t(DateTime dateTime);

Converts a Windows Runtime DateTime to a 64-bit C runtime (Unix-style) time value. The 64-bit C runtime time format has a larger range than the Windows Runtime DateTime format, but cannot represent fractional seconds. Fractional seconds are discarded in the conversion.

The C++/WinRT equivalent is winrt::clock::to_time_t().

time_t_to_DateTime

DateTime time_t_to_DateTime(__time64_t timeT);

Converts a 64-bit C runtime (Unix-style) time value to a Windows Runtime DateTime.

The result is undefined if the 64-bit C runtime time value represents a point in time that cannot be represented by a DateTime (approximate range 27,400 B.C.E to 29,000 C.E.).

The C++/WinRT equivalent is winrt::clock::from_time_t().

Windows Runtime strings

HasEmbeddedNull

bool HasEmbeddedNull(_In_opt_ HSTRING value);

Returns true if the string contains an embedded null character.

The C++/WinRT equivalent is winrt::embedded_null(hstring const&).

TwoPhaseHStringConstructor

The TwoPhaseHStringConstructor is a helper class for constructing HSTRING objects. It is movable but not copyable.

The C++/WinRT equivalent is to construct the string using std::wstring or any other convenient string container, then construct an hstring from it.

Usage

// Preallocate space for a string of a specific length.
// The length does not include the null terminator.
auto stringConstructor = wil::TwoPhaseHStringConstructor::Preallocate(length);
RETURN_IF_NULL_ALLOC(stringConstructor.Get());

// Fill the buffer with exactly length characters.
RETURN_IF_FAILED(stream->Read(stringConstructor.Get(),
                              stringConstructor.ByteSize(), &bytesRead));

// Validate stream contents: Sizes must match, and
// preallocated null terminator must still be present.
RETURN_IF_FAILED(stringConstructor.Validate(bytesRead));

Microsoft::WRL::Wrappers::HString string;
string.Attach(stringConstructor.Promote());

Details

Constructors

  • static TwoPhaseHStringConstructor TwoPhaseHStringConstructor::Preallocate(UINT32 characterLength) (factory)
    Create a new TwoPhaseHStringConstructor that will eventually hold a string of characterLength characters (not counting the null terminator).

  • TwoPhaseHStringConstructor(TwoPhaseHStringConstructor&& other) (move constructor)
    Transfer the state of a TwoPhaseHStringConstructor to a new object.

Destructor

  • ~TwoPhaseHStringConstructor
    It is acceptable to destruct the object without calling Promote. In that case, the construction of the HSTRING is abandoned.

Methods

  • wchar_t* Get()
    Returns a pointer to the buffer into which the string should be generated.

  • ULONG ByteSize() const
    Returns the size of the buffer in bytes.

  • HRESULT Validate(ULONG bytesRead) const
    Validates that the number of bytes is equal to the size of the buffer, not including the null terminator. Also validates that the buffer's null terminator has not been corrupted.

    Calling Validate() is optional.

  • HSTRING Promote()
    Construct the Windows Runtime HSTRING object from the information in the buffer. The caller is responsible for the lifetime of the resulting HSTRING. It is typically placed into an RAII type such as wil::unique_hstring. Once the string is promoted, the only thing you can do with the object is destruct it.

    The Promote() method fails fast on usage error, such as if the null terminator has been corrupted, or if you attempt to Promote() twice.

Operators

  • operator PCWSTR() const
    Returns the buffer into which the string was generated.

hstring_less and hstring_insensitive_less

The hstring_less and hstring_insensitive_less structures perform case-sensitive or case-insensitive (respectively) ordinal string comparisons on HSTRING objects.

They are transparent comparators which permit more efficient use of HSTRINGs as keys in associative containers such as std::set and std::map. Transparency permits looking up items using any of the following:

  • HSTRING
  • const Microsoft::WRL::Wrappers::HString&
  • const Microsoft::WRL::Wrappers::HStringReference&
  • const wil::unique_hstring&
  • const wchar_t* (null-terminated string, null pointer treated as empty string)
  • const std::string& (if exceptions are enabled)

Note that the const wchar_t* version cannot be used to search for strings with embedded nulls, because the embedded null will be treated as a string terminator.

The hstring_less structure is used as the default std::less comparator for Microsoft::WRL::HString and wil::unique_hstring.

Examples:

std::map<Microsoft::WRL::HString, int, wil::hstring_less> map;

Microsoft::WRL::HString str = ...;
wil::unique_hstring uniqueStr = ...;
wchar_t buffer[...];

map.find(str);                  // Traditional lookup via Microsoft::WRL::HString
map.find(str.Get());            // Transparent lookup accepts HSTRING
map.find(uniqueStr);            // Transparent lookup accepts wil::unique_hstring
map.find(L"literal");           // Transparent lookup accepts const wchar_t*
map.find(buffer);               // Transparent lookup accepts wchar_t*
map.find(std::wstring(buffer)); // Transparent lookup accepts std::wstring

Iterating over Windows Runtime collections

The get_range adapters permit use of range-based for loops to iterate over Windows Runtime collections.

Adapter Error model
get_range Exceptions
get_range_nothrow Error codes
get_range_failfast Fail fast

C++/WinRT does not require an adapter. Range-based for loops are natively supported over C++/WinRT collections (anything that supports Windows.Foundation.IIterable<T>).

See Ad-hoc range helpers for other iterator helpers.

Examples

// assume collection is IVector<T>*, IVectorView<T>*, or IIterable<T>*

for (auto const& element : wil::get_range(collection)) ...
for (auto const& element : wil::get_range_failfast(collection)) ...
for (auto const& element : wil::get_range_nothrow(collection)) ...
for (auto const& element : wil::get_range_nothrow(collection, &hr)) ...

In the case of get_range_nothrow, an optional HRESULT* parameter receives the HRESULT that caused the iteration to stop. If the iterator ran to completion successfully, or if the loop was explicitly exited with a break statement, then the value will be S_OK.

Warnings

  • It is the caller's responsibility to ensure that the collection lifetime extends to the completion of the for loop.
  • The collection's lifetime must encompass the use of the iterators you obtain from the get_range functions.
  • The iterators obtained from get_range and get_range_failfast are bidirectional iterators which also support constant-time bidirectional advance.
  • The iterators obtained from get_range_nothrow function are input iterators which also support constant-time bidirectional advance. However, only one iterator may be dereferenced.
extern Microsoft::WRL::ComPtr<IVector<T>> GetCollection();

// WRONG! The smart pointer returned by GetCollection() is temporary
// and will be destructed before the loop body runs.
for (auto const& element : wil::get_range(GetCollection().Get())) ...

// FIXED! Explicitly extend the lifetime of the collection.
auto collection = GetCollection();
for (auto const& element : wil::get_range(collection.Get())) ...

// WRONG! The smart pointer returned by GetCollections() is temporary
// and will be destructed while there are still active iterators.
auto range = wil::get_range(GetCollection().Get());
auto it = std::lower_bound(range.begin(), range.end(), value);

// FIXED! Explicitly extend the lifetime of the collection.
auto collection = GetCollection();
auto range = wil::get_range(collection.Get());
auto it = std::lower_bound(range.begin(), range.end(), value);

// WRONG! The iterators produced by get_range_nothrow
// are not forward iterators.
auto collection = GetCollection();
auto range = wil::get_range_nothrow(collection.Get());
auto it = std::adjacent_find(range.begin(), range.end());

Windows Runtime asynchronous operations

These functions permit basic operations with Windows Runtime asynchronous operations, but they have been superseded by C++/WinRT.

For all the asynchronous operation helpers, the operation can be

  • An "action", which has no result: IAsyncAction* or IAsyncActionWithProgress<TProgress>*
  • An "operation": IAsyncOperation<TResult>* or IAsyncOperationWithProgress<TResult, TProgress>*

Running code when an asynchronous operation completes

These functions have been superseded by C++/WinRT. Prefer to use C++/WinRT and co_await to consume asynchronous operations.

Function Error model
run_when_complete Exceptions
run_when_complete_nothrow Error codes
(no fail fast version)

The general shape of the run_when_complete family of functions is

template<typename TAgility>
run_when_complete(operation, functor)

The TAgility can be explicitly specified as Microsoft::WRL::FtmBase to specify that the functor can be called on any thread. By default, the functor will be called back in the same apartment.

The functor's operator() can take one of the following forms:

  • For an action:
    • HRESULT func(HRESULT hr);
    • void func(HRESULT hr);
  • For an operation whose result is an interface type
    • HRESULT func(HRESULT hr, TResult* result);
    • void func(HRESULT hr, TResult* result);
  • For an operation whose result is a value type
    • HRESULT func(HRESULT hr, TResult result);
    • void func(HRESULT hr, TResult result);

The hr reports whether the asynchronous operation completed successfully.

The result is the result of the asynchronous operation. If the asynchronous operation failed, then result is meaningless.

If the functor returns an HRESULT, then that HRESULT is the return value of the continuation.

If the functor returns void, then exceptions thrown by THROW_IF_FAILED are caught and treated as the return value of the continuation.

The run_when_complete function throws an exception if the continuation cannot be scheduled.

The run_when_complete_nothrow function returns an HRESULT specifying whether the continuation was successfully scheduled.

template<typename TAgility = IUnknown, typename TFunc>
void run_when_complete(IAsyncAction* operation, TFunc&& func);

template<typename TAgility = IUnknown, typename TProgress, typename TFunc>
void run_when_complete(IAsyncActionWithProgress<TProgress>* operation, TFunc&& func);

template<typename TAgility = IUnknown, typename TResult, typename TFunc>
void run_when_complete(IAsyncOperation<TResult>* operation, TFunc&& func);

template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>
void run_when_complete(IAsyncOperationWithProgress<TResult, TProgress>* operation,
                       TFunc&& func);

template<typename TAgility = IUnknown, typename TFunc>
HRESULT run_when_complete_nothrow(IAsyncAction* operation, TFunc&& func) noexcept;

template<typename TAgility = IUnknown, typename TProgress, typename TFunc>
HRESULT run_when_complete_nothrow(IAsyncActionWithProgress<TProgress>* operation,
                                  TFunc&& func) noexcept;

template<typename TAgility = IUnknown, typename TResult, typename TFunc>
HRESULT run_when_complete_nothrow(IAsyncOperation<TResult>* operation, TFunc&& func) noexcept;

template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>
HRESULT run_when_complete_nothrow(IAsyncOperationWithProgress<TResult, TProgress>* operation,
                                  TFunc&& func) noexcept;

Examples:

void CopyToParentFolderFireAndForget(IStorageFile* file)
{
    Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> fileOperation;
    THROW_iF_FAILED(file->GetParentAsync(&fileOperation));

    // Must extend lifetime of "file" into the lambda.
    run_when_complete(fileOperation.Get(),
      [file = wil::com_ptr<IStorageFile>(file)](HRESULT result, IStorageFolder* folder)
    {
        THROW_IF_FAILED(result);
        Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> copyOperation;
        THROW_IF_FAILED(file->CopyAsync(folder, &copyOperation));
        run_when_complete(copyOperation.Get(),
          [](HRESULT result, IStorageFile* /* copiedFile */)
        {
            THROW_IF_FAILED(result);
        });
    });
}

// To permit the continuation to run in any thread, use FtmBase.
run_when_complete<FtmBase>(fileOperation.Get(), [](HRESULT result, IStorageFile* file)
{
   THROW_IF_FAILED(result);
   DoSomethingWith(file);
});

Note that the lambda must extend the lifetimes of any objects it needs, because its execution is deferred until the completion of the asynchronous operation. In particular, it must not capture by reference.

Preferred C++/WinRT alternative:

// "file" parameter is non-const because we use it in the continuation.
winrt::fire_and_forget CopyToParentFolder(StorageFile file)
{
    auto folder = co_await file.GetParentAsync();
    co_await file.CopyAsync(folder);
}

Waiting for an asynchronous operation to complete

These functions have been superseded by C++/WinRT. Prefer to use C++/WinRT and get() to consume asynchronous operations synchronously.

Function Error model
wait_for_completion Exceptions
wait_for_completion_nothrow Error codes
(no fail fast version)
wait_for_completion_or_timeout_nothrow Error codes
call_and_wait_for_completion Exceptions

These functions wait for an asynchronous operation to complete or be canceled. Use them to wait synchronously from background threads. Do not use them from UI threads or STA threads as reentrancy will result.

The general shape of the wait_for_completion family of functions is

HRESULT hr = wait_for_completion_nothrow(operation, &result);
auto result = wait_for_completion(operation);

If the operation is an action, then wait_for_completion_nothrow has no result parameter, and wait_for_completion returns void.

An optional final parameter of type COWAIT_FLAGS can be provided to customize how the thread waits for the operation to complete. The default is COWAIT_DISPATCH_CALLS.

If the function is unable to wait for the operation, or if the operation does not complete successfully, the error code is thrown (wait_for_completion) or returned (wait_for_completion_nothrow). No value is placed into result.

void wait_for_completion(IAsyncAction* operation,
                         COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);

void wait_for_completion(IAsyncActionWithProgress<TProgress>* operation,
                         COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);

details::MapToSmartType<TResult>
    wait_for_completion(IAsyncOperation<TResult>* operation,
                        COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);

details::MapToSmartType<TResult>
    wait_for_completion(IAsyncOperationWithProgress<TResult, TProgress>* operation,
                        COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);

HRESULT wait_for_completion_nothrow(
    IAsyncAction* operation,
    COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_nothrow(
    IAsyncActionWithProgress<TProgress>* operation,
    COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_nothrow(
    IAsyncOperation<TResult>* operation,
    details::MapAsyncOpResultType<TResult>::type* result,
    COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_nothrow(
    IAsyncOperationWithProgress<TResult, TProgress>* operation,
    details::MapAsyncOpResultType<TResult>::type* result,
    COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;

details::MapToSmartType<TResult> depends on the nature of TResult:

  • If TResult is HSTRING, then details::MapToSmartType<TResult> is Microsoft::WRL::Wrappers::HString, with an additional method ReleaseAndGetAddressOf.
  • If TResult is an interface type, then details::MapToSmartType<TResult> is Microsoft::WRL::ComPtr<TResult>.
  • If TResult is a value type, then details::MapToSmartType<TResult> is a custom type which behaves similarly to Microsoft::WRL::ComPtr.
    • operator TResult() const (conversion operator)
      returns the wrapped value.
    • TResult Get() const
      returns the wrapped value.
    • TResult&& Get()
      returns the wrapped value as an rvalue reference.
    • HRESULT CopyTo(TResult* result) const
      copies the wrapped value, always returns S_OK.
    • TResult* GetAddressOf()
      returns the address of the wrapped value.
    • TResult* ReleaseAndGetAddressOf()
      returns the address of the wrapped value.
    • TResult* operator&()
      returns the address of the wrapped value.

details::MapAsyncOpResultType<TResult>::type also depends on the nature of TResult:

  • If TResult is an interface type, then details::MapAsyncOpResultType<TResult>::type is TResult*.
  • Otherwise, details::MapAsyncOpResultType<TResult>::type is TResult.

Waiting for completion with a timeout is done with the wait_for_completion_or_timeout_nothrow function:

HRESULT hr = wait_for_completion_or_timeout_nothrow(operation, &result, timeout, &timedOut);

Again the result is omitted if the operation is an action.

The timeout is expressed in milliseconds. If the operation fails to complete before the timeout elapses, the wait_for_completion_or_timeout_nothrow function returns S_OK and sets timedOut to true. In all other cases, timedOut is false.

Aside from the timeout, the function behaves the same as wait_for_completion_nothrow.

HRESULT wait_for_completion_or_timeout_nothrow(
    IAsyncAction* operation,
    DWORD timeout,
    bool* timedOut,
    flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_or_timeout_nothrow(
    IAsyncActionWithProgress<TProgress>* operation,
    DWORD timeout,
    bool* timedOut,
    flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_or_timeout_nothrow(
    IAsyncOperation<TResult>* operation,
    details::MapAsyncOpResultType<TResult>::type* result,
    DWORD timeout,
    bool* timedOut,
    flags = COWAIT_DISPATCH_CALLS) noexcept;

HRESULT wait_for_completion_or_timeout_nothrow(
    IAsyncOperationWithProgress<TResult, TProgress>* operation,
    details::MapAsyncOpResultType<TResult>::type* result,
    DWORD timeout,
    bool* timedOut,
    flags = COWAIT_DISPATCH_CALLS) noexcept;

The call_and_wait_for_completion variant uses the following pattern:

auto result = call_and_wait_for_completion(object, &Object::Method, args...);

It invokes the method on the object with the args..., and then performs a wait_for_completion on the operation.

template<typename I, typename ...P, typename ...Args>
auto call_and_wait_for_completion(I* object, HRESULT(STDMETHODCALLTYPE I::*func)(P...),
                                  Args&&... args);

Examples:

IAsyncAction* action = ...;
IAsyncOperation<int> intOperation = ...;
IAsyncOperation<IInspectable> inspectableOperation = ...;

// Waits for the action to complete, or throws if the action fails.
wait_for_completion(action);

// Waits for the operation to complete and returns the result.
auto intResult = wait_for_completion(intOperation).Get();

auto result = wait_for_completion(inspectableOperation);
IInspectable* inspectable = result.Get(); // lifetime controlled by "result"

// Call an asynchronous method and wait for the result.
Microsoft::WRL::ComPtr<ILauncherStatics> launcherStatics = ...;
auto result = call_and_wait_for_completion(
                launcherStatics.Get(), &ILauncherStatics::LaunchUriAsync, uri.Get());
bool succeeded = result.Get();

Preferred C++/WinRT alternative:

IAsyncAction action = ...;
IAsyncOperation<int32_t> intOperation = ...;
IAsyncOperation<IInspectable> inspectableOperation = ...;

// Waits for the action to complete, or throws if the action fails.
action.get();

// Waits for the operation to complete and returns the result.
auto intResult = intOperation.get();

IInspectable inspectable = inspectableOperation.get();

// Call an asynchronous method and wait for the result.
bool succeeded = winrt::Windows::System::Launcher::LaunchUriAsync(uri).get();

Creating already-completed asynchronous operations

These functions have been superseded by C++/WinRT. Prefer to use C++/WinRT and co_return to produce asynchronous operations.

The make_synchronous_async_... functions create asynchronous operations which have already completed with a particular result. They are primarily intended for testing and mocking purposes.

Function Error model
make_synchronous_async_action Exceptions
make_synchronous_async_operation Exceptions
make_synchronous_async_action_nothrow Error codes
make_synchronous_async_operation_nothrow Error codes
(no fail fast version)
void make_synchronous_async_action(IAsyncAction** result);
void make_synchronous_async_operation(IAsyncOperation<TResult>** result,
                                      const TResult& value);

HRESULT make_synchronous_async_action_nothrow(IAsyncAction** result);
HRESULT make_synchronous_async_operation_nothrow(IAsyncOperation<TResult>** result,
                                                 const TResult& value);

The make_synchronous_async_action and make_synchronous_async_action_nothrow functions create an already-completed IAsyncAction.

The make_synchronous_async_operation and make_synchronous_async_operation_nothrow functions create an already-completed IAsyncOperation<TResult>, with the specified value as the completion result.

Windows Runtime object construction

These functions have been superseded by C++/WinRT. Prefer to use C++/WinRT to access static methods and construct objects.

GetActivationFactory

template<typename TInterface>
com_ptr<TInterface> GetActivationFactory(PCWSTR runtimeClass);

The GetActivationFactory function gets the activation factory for the named Windows Runtime class.

The TInterface is the desired factory interface, usually a ISomethingStatics interface.

If the factory could not be obtained, or the factory does not support the specified interface, then an exception is thrown.

Example:

// Invoking a static method.
using namespace ABI::Windows::Security::Cryptography;
auto statics = wil::GetActivationFactory<ICryptographicBufferStatics>(
    RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer);
uint32_t number;
THROW_IF_FAILED(statics->GenerateRandomNumber(&number));

// Constructing with parameters.
using namespace ABI::Windows::Security::Credentials;
auto factory = wil::GetActivationFactory<IPasswordCredentialFactory>(
    RuntimeClass_Windows_Security_Credentials_PasswordCredential);
wil::unique_hstring resource = ...;
wil::unique_hstring userName = ...;
wil::unique_hstring password = ...;
wil::com_ptr<IPasswordCredential> credential;
THROW_IF_FAILED(factory->CreatePasswordCredential(
    resource.get(), userName.get(), password.get(), &credential));

Preferred C++/WinRT alternative:

// Invoking a static method.
using namespace winrt::Windows::Security::Cryptography;
uint32_t number = CryptographicBuffer::GenerateRandomNumber();

// Constructing with parameters.
using namespace winrt::Windows::Security::Credentials;
winrt::hstring resource = ...;
winrt::hstring userName = ...;
winrt::hstring password = ...;
PasswordCredential credential{ resource, userName, password };

ActivateInstance

template <typename TInterface>
com_ptr<TInterface> ActivateInstance(PCWSTR runtimeClass);

The ActivateInstance function activates an instance of the named Windows Runtime class with no parameters. In projected languages, this is equivalent to invoking the default constructor.

The TInterface is the desired interface on the resulting object. It is usually the object's default interface.

If the object could not be activated, or the object does not support the specified interface, then an exception is thrown.

Example:

using namespace ABI::Windows::Security::Credentials;
wil::com_ptr<IPasswordCredential> credential =
    wil::ActivationInstance<IPasswordCredential>();

Preferred C++/WinRT alternative:

using namespace winrt::Windows::Security::Credentials;
PasswordCredential credential;

Windows Runtime events

These macros have been superseded by C++/WinRT. Prefer to use C++/WinRT to consume Windows Runtime events.

The unique_winrt_event_token RAII types manage the EventRegistrationToken for Windows Runtime events and unregister the event handler at destruction.

These types are often used in member variables.

The unique_winrt_event_token types maintain a weak reference to the event source. The WI_MakeUniqueWinrtEventToken macros will fail if the event source does not support weak references.

  • WI_MakeUniqueWinRtEventToken(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler. The token is stored in a unique_winrt_event_token<Source>. Throws an exception on failure.

  • WI_MakeUniqueWinRtEventTokenFailFast(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler. The token is stored in a unique_winrt_event_token<Source>. Fails fast on failure.

  • WI_MakeUniqueWinRtEventTokenNoThrow(EventName, eventSource, handler, &token)
    Registers for the eventSource::EventName event with the specified handler. The token is stored in a unique_winrt_event_token<Source>. Returns an HRESULT to indicate whether the operation succeeded.

  • WI_MakeUniqueWinRtEventTokenCx(EventName, eventSource, handler)
    Registers for the eventSource::EventName event with the specified handler. The token is returned as a unique_winrt_event_token_cx<Source>. Throws an exception on failure.

  • WI_MakeUniqueWinRtStaticEventTokenCx(EventName, Source, handler)
    Registers for the static Source::EventName event with the specified handler. The token is returned as a unique_winrt_event_token_cx<Source>. Throws an exception on failure.

Note that only WI_MakeUniqueWinRtStaticEventTokenCx supports static events.

Usage

Example of ABI usage:

wil::com_ptr<Widget> widget = ...;
wil::com_ptr<TypedEventHandler<Widget, WidgetClosedEventArgs>> handler = ...;
wil::unique_winrt_event_token<Widget> token;

// Using exceptions.
WI_MakeUniqueWinRtEventToken(Closed, widget.get(), handler.get(), &token);

// Using fail-fast.
WI_MakeUniqueWinRtEventTokenFailFast(Closed, widget.get(), handler.get(), &token);

// Using HRESULTs.
RETURN_IF_FAILED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, widget.get(), handler.get(), &token));

Example of C++/CX usage:

Widget^ widget = ...;
TypedEventHandler<Widget, WidgetClosedEventArgs>^ handler = ...;

// Register an instance event, throws on failure.
wil::unique_winrt_event_token_cx<Widget> token =
    WI_MakeUniqueWinRtEventTokenCx(Closed, widget, handler);

// Register a static event, throws on failure.
EventHandler<WidgetAddedEventArgs>^ handler = ...;
wil::unique_winrt_event_token_cx<Widget> token =
    WI_MakeUniqueWinRtStaticEventTokenCx(WidgetAdded, Widget, handler);

The C++/WinRT equivalent is winrt::event_revoker.

Clone this wiki locally