Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cppwinrt.sln
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "test\test_module_lock_none\test_module_lock_none.vcxproj", "{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}"
ProjectSection(ProjectDependencies) = postProject
{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
{13333A6F-6A4A-48CD-865C-0F65135EB018} = {13333A6F-6A4A-48CD-865C-0F65135EB018}
{0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E} = {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", "test\test_module_lock_custom\test_module_lock_custom.vcxproj", "{08C40663-B6A3-481E-8755-AE32BAD99501}"
Expand Down
7 changes: 6 additions & 1 deletion strings/base_agile_ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ WINRT_EXPORT namespace winrt
{
#if defined (WINRT_NO_MODULE_LOCK)

// Defining WINRT_NO_MODULE_LOCK is appropriate for apps (executables) that don't implement something like DllCanUnloadNow
// Defining WINRT_NO_MODULE_LOCK is appropriate for apps (executables) or pinned DLLs (that don't support unloading)
// and can thus avoid the synchronization overhead imposed by the default module lock.

constexpr auto get_module_lock() noexcept
Expand All @@ -19,6 +19,11 @@ WINRT_EXPORT namespace winrt
{
return 0;
}

constexpr explicit operator bool() noexcept
{
return true;
}
};

return lock{};
Expand Down
8 changes: 8 additions & 0 deletions test/test_component_base/pch.h
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
#pragma once

#define WINRT_NO_MODULE_LOCK
#include "winrt/base.h"

// get_module_lock will always return true if WINRT_NO_MODULE_LOCK is defined.
// This ensures that if the DLL unecessarily exports DllCanUnloadNow that it
// will in turn return S_FALSE.
static_assert(winrt::get_module_lock());
9 changes: 9 additions & 0 deletions test/test_module_lock_none/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <windows.h>

// Defining WINRT_NO_MODULE_LOCK means that winrt::get_module_lock is not defined and calls to it are elided from C++/WinRT.
// This is an optimization for apps (executables) that don't implement something like DllCanUnloadNow.
Expand Down Expand Up @@ -52,6 +53,14 @@ TEST_CASE("module_lock_none")
winrt::clear_factory_cache();

REQUIRE(first == second);

// Validates that test_component_base is pinned by virtue of it defining WINRT_NO_MODULE_LOCK.

auto can_unload = reinterpret_cast<HRESULT(__stdcall*)()>(GetProcAddress(LoadLibraryA("test_component_base.dll"), "DllCanUnloadNow"));
REQUIRE(can_unload() == S_FALSE);

auto cannot_unload = reinterpret_cast<HRESULT(__stdcall*)()>(GetProcAddress(LoadLibraryA("test_component_derived.dll"), "DllCanUnloadNow"));
REQUIRE(cannot_unload() == S_OK);
}

int main(int const argc, char** argv)
Expand Down