Skip to content

Commit 4e6eed2

Browse files
authored
Simplify use of WINRT_NO_MODULE_LOCK in DLLs (#1032)
1 parent 24af032 commit 4e6eed2

File tree

4 files changed

+25
-1
lines changed

4 files changed

+25
-1
lines changed

cppwinrt.sln

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ EndProject
8787
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}"
8888
ProjectSection(ProjectDependencies) = postProject
8989
{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
90+
{13333A6F-6A4A-48CD-865C-0F65135EB018} = {13333A6F-6A4A-48CD-865C-0F65135EB018}
91+
{0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E} = {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}
9092
EndProjectSection
9193
EndProject
9294
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}"

strings/base_agile_ref.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ WINRT_EXPORT namespace winrt
33
{
44
#if defined (WINRT_NO_MODULE_LOCK)
55

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

99
constexpr auto get_module_lock() noexcept
@@ -19,6 +19,11 @@ WINRT_EXPORT namespace winrt
1919
{
2020
return 0;
2121
}
22+
23+
constexpr explicit operator bool() noexcept
24+
{
25+
return true;
26+
}
2227
};
2328

2429
return lock{};

test/test_component_base/pch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
11
#pragma once
2+
3+
#define WINRT_NO_MODULE_LOCK
4+
#include "winrt/base.h"
5+
6+
// get_module_lock will always return true if WINRT_NO_MODULE_LOCK is defined.
7+
// This ensures that if the DLL unecessarily exports DllCanUnloadNow that it
8+
// will in turn return S_FALSE.
9+
static_assert(winrt::get_module_lock());

test/test_module_lock_none/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#define CATCH_CONFIG_RUNNER
22
#include "catch.hpp"
3+
#include <windows.h>
34

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

5455
REQUIRE(first == second);
56+
57+
// Validates that test_component_base is pinned by virtue of it defining WINRT_NO_MODULE_LOCK.
58+
59+
auto can_unload = reinterpret_cast<HRESULT(__stdcall*)()>(GetProcAddress(LoadLibraryA("test_component_base.dll"), "DllCanUnloadNow"));
60+
REQUIRE(can_unload() == S_FALSE);
61+
62+
auto cannot_unload = reinterpret_cast<HRESULT(__stdcall*)()>(GetProcAddress(LoadLibraryA("test_component_derived.dll"), "DllCanUnloadNow"));
63+
REQUIRE(cannot_unload() == S_OK);
5564
}
5665

5766
int main(int const argc, char** argv)

0 commit comments

Comments
 (0)