diff --git a/cppwinrt.sln b/cppwinrt.sln
index 2e81621fe..3189d1555 100644
--- a/cppwinrt.sln
+++ b/cppwinrt.sln
@@ -96,6 +96,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", "
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3C7EA5F8-6E8C-4376-B499-2CAF596384B0}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7\test_win7.vcxproj", "{2EF696B9-7F4A-410F-AE5C-5301565C0F08}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
+ {F1C915B3-2C64-4992-AFB7-7F035B1A7607} = {F1C915B3-2C64-4992-AFB7-7F035B1A7607}
+ {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -412,6 +419,22 @@ Global
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32
{08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.Build.0 = Debug|ARM
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.ActiveCfg = Debug|x64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.Build.0 = Debug|x64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.ActiveCfg = Debug|Win32
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.Build.0 = Debug|Win32
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.ActiveCfg = Release|ARM
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.Build.0 = Release|ARM
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.Build.0 = Release|ARM64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.ActiveCfg = Release|x64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -433,6 +456,7 @@ Global
{303CC0FE-7D66-4F9F-B7A1-0AF7F9359074} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
{08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
+ {2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA}
diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj
index 342c3b3d3..4b0372508 100644
--- a/cppwinrt/cppwinrt.vcxproj
+++ b/cppwinrt/cppwinrt.vcxproj
@@ -201,6 +201,7 @@
Disabled
..\inc;$(OutputPath);$(WinMDPackageDir);
+ MultiThreadedDebug
Console
@@ -217,6 +218,7 @@
Disabled
..\inc;$(OutputPath);$(WinMDPackageDir);
+ MultiThreadedDebug
Console
@@ -233,6 +235,7 @@
Disabled
..\inc;$(OutputPath);$(WinMDPackageDir);
+ MultiThreadedDebug
Console
@@ -249,6 +252,7 @@
Disabled
..\inc;$(OutputPath);$(WinMDPackageDir);
+ MultiThreadedDebug
Console
diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj
index a6015bd53..92df71b65 100644
--- a/prebuild/prebuild.vcxproj
+++ b/prebuild/prebuild.vcxproj
@@ -125,6 +125,7 @@
Disabled
..\cppwinrt
+ MultiThreadedDebug
Console
@@ -134,6 +135,7 @@
Disabled
..\cppwinrt
+ MultiThreadedDebug
Console
@@ -143,6 +145,7 @@
Disabled
..\cppwinrt
+ MultiThreadedDebug
Console
@@ -152,6 +155,7 @@
Disabled
..\cppwinrt
+ MultiThreadedDebug
Console
@@ -163,6 +167,7 @@
true
true
..\cppwinrt
+ MultiThreaded
Console
@@ -176,6 +181,7 @@
true
true
..\cppwinrt
+ MultiThreaded
Console
@@ -189,6 +195,7 @@
true
true
..\cppwinrt
+ MultiThreaded
Console
@@ -202,6 +209,7 @@
true
true
..\cppwinrt
+ MultiThreaded
Console
diff --git a/run_tests.cmd b/run_tests.cmd
index c60c0fd9b..d63741994 100644
--- a/run_tests.cmd
+++ b/run_tests.cmd
@@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64
if "%target_configuration%"=="" set target_configuration=Debug
call :run_test test
+call :run_test test_win7
call :run_test test_fast
call :run_test test_slow
call :run_test test_old
diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj
index d65af2e48..ae9bca8fb 100644
--- a/scratch/scratch.vcxproj
+++ b/scratch/scratch.vcxproj
@@ -130,6 +130,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreaded
Console
@@ -151,6 +152,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreadedDebug
Console
@@ -170,6 +172,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreadedDebug
Console
@@ -189,6 +192,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreadedDebug
Console
@@ -208,6 +212,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreadedDebug
Console
@@ -229,6 +234,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreaded
Console
@@ -252,6 +258,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreaded
Console
@@ -275,6 +282,7 @@
$(OutputPath);Generated Files;..\..\..\library
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
/await %(AdditionalOptions)
+ MultiThreaded
Console
diff --git a/strings/base_activation.h b/strings/base_activation.h
index fe7b94b84..1d3817977 100644
--- a/strings/base_activation.h
+++ b/strings/base_activation.h
@@ -34,8 +34,15 @@ namespace winrt::impl
if (hr == impl::error_not_initialized)
{
+ auto usage = static_cast(WINRT_GetProcAddress(WINRT_LoadLibraryW(L"combase.dll"), "CoIncrementMTAUsage"));
+
+ if (!usage)
+ {
+ return hr;
+ }
+
void* cookie;
- WINRT_CoIncrementMTAUsage(&cookie);
+ usage(&cookie);
hr = handler(*(void**)(&name), guid_of(), result);
}
diff --git a/strings/base_extern.h b/strings/base_extern.h
index 194e32fa1..f6c0bc24e 100644
--- a/strings/base_extern.h
+++ b/strings/base_extern.h
@@ -13,7 +13,6 @@ extern "C"
int32_t __stdcall WINRT_GetErrorInfo(uint32_t reserved, void** info) noexcept;
int32_t __stdcall WINRT_CoInitializeEx(void*, uint32_t type) noexcept;
void __stdcall WINRT_CoUninitialize() noexcept;
- int32_t __stdcall WINRT_CoIncrementMTAUsage(void** cookie) noexcept;
int32_t __stdcall WINRT_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept;
int32_t __stdcall WINRT_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept;
@@ -96,7 +95,6 @@ WINRT_IMPL_LINK(SetErrorInfo, 8)
WINRT_IMPL_LINK(GetErrorInfo, 8)
WINRT_IMPL_LINK(CoInitializeEx, 8)
WINRT_IMPL_LINK(CoUninitialize, 0)
-WINRT_IMPL_LINK(CoIncrementMTAUsage, 4)
WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8)
WINRT_IMPL_LINK(CoCreateInstance, 20)
diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj
index 89323600c..9511f5de1 100644
--- a/test/test/test.vcxproj
+++ b/test/test/test.vcxproj
@@ -129,6 +129,7 @@
true
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -148,6 +149,7 @@
Disabled
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -165,6 +167,7 @@
Disabled
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -182,6 +185,7 @@
Disabled
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -199,6 +203,7 @@
Disabled
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -218,6 +223,7 @@
true
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -239,6 +245,7 @@
true
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -260,6 +267,7 @@
true
$(OutputPath);Generated Files;..;..\..\cppwinrt
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -275,7 +283,6 @@
-
@@ -287,6 +294,32 @@
+
+
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+
+
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+
+
+
+
+
+
@@ -298,35 +331,23 @@
-
-
- NotUsing
-
NotUsing
-
- NotUsing
-
NotUsing
-
-
-
-
-
NotUsing
- NotUsing
- NotUsing
NotUsing
- NotUsing
+ NotUsing
NotUsing
+ NotUsing
+ NotUsing
NotUsing
NotUsing
@@ -335,11 +356,11 @@
NotUsing
- NotUsing
- NotUsing
NotUsing
- NotUsing
+ NotUsing
NotUsing
+ NotUsing
+ NotUsing
NotUsing
NotUsing
@@ -352,11 +373,11 @@
NotUsing
- NotUsing
- NotUsing
NotUsing
- NotUsing
+ NotUsing
NotUsing
+ NotUsing
+ NotUsing
NotUsing
NotUsing
@@ -364,7 +385,14 @@
- NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
+ NotUsing
diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj
index a404f884d..ef66896e9 100644
--- a/test/test_component/test_component.vcxproj
+++ b/test/test_component/test_component.vcxproj
@@ -157,6 +157,7 @@
Disabled
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreadedDebug
exports.def
@@ -204,6 +205,7 @@
Disabled
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreadedDebug
exports.def
@@ -265,6 +267,7 @@
Disabled
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreadedDebug
exports.def
@@ -326,6 +329,7 @@
Disabled
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreadedDebug
exports.def
@@ -375,6 +379,7 @@
true
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreaded
true
@@ -426,6 +431,7 @@
true
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreaded
true
@@ -491,6 +497,7 @@
true
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreaded
true
@@ -556,6 +563,7 @@
true
.;$(OutputPath);Generated Files
/Zc:threadSafeInit- /we4640 %(AdditionalOptions)
+ MultiThreaded
true
diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj
index 0ac0b01aa..43f67d347 100644
--- a/test/test_component_base/test_component_base.vcxproj
+++ b/test/test_component_base/test_component_base.vcxproj
@@ -157,6 +157,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -204,6 +205,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -265,6 +267,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -326,6 +329,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -375,6 +379,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -426,6 +431,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -491,6 +497,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -556,6 +563,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj
index 2e9bf9cbc..fcb82ee3b 100644
--- a/test/test_component_derived/test_component_derived.vcxproj
+++ b/test/test_component_derived/test_component_derived.vcxproj
@@ -157,6 +157,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -205,6 +206,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -267,6 +269,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -329,6 +332,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -379,6 +383,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreaded
true
@@ -431,6 +436,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreaded
true
@@ -497,6 +503,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreaded
true
@@ -563,6 +570,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files
4100
+ MultiThreaded
true
diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj
index 030c61341..55d1ed371 100644
--- a/test/test_component_fast/test_component_fast.vcxproj
+++ b/test/test_component_fast/test_component_fast.vcxproj
@@ -159,6 +159,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreadedDebug
exports.def
@@ -207,6 +208,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreadedDebug
exports.def
@@ -269,6 +271,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreadedDebug
exports.def
@@ -331,6 +334,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreadedDebug
exports.def
@@ -381,6 +385,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreaded
true
@@ -433,6 +438,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreaded
true
@@ -499,6 +505,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreaded
true
@@ -565,6 +572,7 @@
$(ProjectDir);$(OutputPath);Generated Files
/DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions)
4100
+ MultiThreaded
true
diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj
index 4ea524f1d..d470ed048 100644
--- a/test/test_component_folders/test_component_folders.vcxproj
+++ b/test/test_component_folders/test_component_folders.vcxproj
@@ -157,6 +157,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -204,6 +205,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -265,6 +267,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -326,6 +329,7 @@
Disabled
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreadedDebug
exports.def
@@ -375,6 +379,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -426,6 +431,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -491,6 +497,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
@@ -556,6 +563,7 @@
true
$(ProjectDir);$(OutputPath);Generated Files
4100
+ MultiThreaded
true
diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj
index 932aaac27..e6ca64dc1 100644
--- a/test/test_component_no_pch/test_component_no_pch.vcxproj
+++ b/test/test_component_no_pch/test_component_no_pch.vcxproj
@@ -158,6 +158,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreadedDebug
exports.def
@@ -206,6 +207,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreadedDebug
exports.def
@@ -268,6 +270,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreadedDebug
exports.def
@@ -330,6 +333,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreadedDebug
exports.def
@@ -380,6 +384,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreaded
true
@@ -432,6 +437,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreaded
true
@@ -498,6 +504,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreaded
true
@@ -564,6 +571,7 @@
$(ProjectDir);$(OutputPath);Generated Files
4100
NotUsing
+ MultiThreaded
true
diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj
index 974468a85..567c8f8f2 100644
--- a/test/test_fast/test_fast.vcxproj
+++ b/test/test_fast/test_fast.vcxproj
@@ -129,6 +129,7 @@
true
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -149,6 +150,7 @@
Disabled
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -167,6 +169,7 @@
Disabled
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -185,6 +188,7 @@
Disabled
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -203,6 +207,7 @@
Disabled
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -223,6 +228,7 @@
true
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -245,6 +251,7 @@
true
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -267,6 +274,7 @@
true
$(OutputPath);Generated Files;..\;
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj
index 4afb13aee..14b559bcd 100644
--- a/test/test_fast_fwd/test_fast_fwd.vcxproj
+++ b/test/test_fast_fwd/test_fast_fwd.vcxproj
@@ -325,6 +325,28 @@
false
+ MultiThreaded
+
+
+ MultiThreaded
+
+
+ MultiThreaded
+
+
+ MultiThreaded
+
+
+ MultiThreadedDebug
+
+
+ MultiThreadedDebug
+
+
+ MultiThreadedDebug
+
+
+ MultiThreadedDebug
diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj
index 2aea222b8..fab6a61f6 100644
--- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj
+++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj
@@ -129,6 +129,7 @@
true
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -149,6 +150,7 @@
Disabled
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -167,6 +169,7 @@
Disabled
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -185,6 +188,7 @@
Disabled
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -203,6 +207,7 @@
Disabled
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -223,6 +228,7 @@
true
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -245,6 +251,7 @@
true
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -267,6 +274,7 @@
true
$(OutputPath);Generated Files;..\;
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj
index 450ce9f91..fb64f7d94 100644
--- a/test/test_module_lock_none/test_module_lock_none.vcxproj
+++ b/test/test_module_lock_none/test_module_lock_none.vcxproj
@@ -129,6 +129,7 @@
true
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -149,6 +150,7 @@
Disabled
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -167,6 +169,7 @@
Disabled
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -185,6 +188,7 @@
Disabled
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -203,6 +207,7 @@
Disabled
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -223,6 +228,7 @@
true
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -245,6 +251,7 @@
true
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -267,6 +274,7 @@
true
$(OutputPath);Generated Files;..\
NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj
index cda245c3c..492f05848 100644
--- a/test/test_slow/test_slow.vcxproj
+++ b/test/test_slow/test_slow.vcxproj
@@ -129,6 +129,7 @@
true
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -148,6 +149,7 @@
Disabled
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -165,6 +167,7 @@
Disabled
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -182,6 +185,7 @@
Disabled
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -199,6 +203,7 @@
Disabled
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreadedDebug
Console
@@ -218,6 +223,7 @@
true
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -239,6 +245,7 @@
true
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
@@ -260,6 +267,7 @@
true
$(OutputPath);Generated Files;..\
WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions)
+ MultiThreaded
Console
diff --git a/test/test_win7/GetMany.cpp b/test/test_win7/GetMany.cpp
new file mode 100644
index 000000000..23ea63e1e
--- /dev/null
+++ b/test/test_win7/GetMany.cpp
@@ -0,0 +1,378 @@
+#include "pch.h"
+
+using namespace winrt;
+using namespace Windows::Foundation::Collections;
+
+//
+// Now that all of the generics are generated (rather than hand-written), it's far less likely
+// that something like GetMany is incorrect. And the "FillArray" pattern used by GetMany is
+// tested elsewhere in the out_params and return_params tests. However since C++/WinRT provides
+// an implementation of GetMany over and above the projection, these tests validate the this
+// implementation is correct. Other tests exist for collections under 'old_tests' but new
+// optimizations are coming for GetMany and I want to make sure that GetMany is completely
+// covered.
+//
+
+namespace
+{
+ template
+ IIterator single_threaded_generator(std::vector&& values = {})
+ {
+ // This iterator may only be advanced once, ensuring the GetMany complexity optimization
+ // is actually enforced with this test.
+
+ struct generator_container
+ {
+ explicit generator_container(IIterator const& first) : m_current(first)
+ {
+ if (!m_current.HasCurrent())
+ {
+ m_current = nullptr;
+ }
+ }
+
+ IIterator begin() const { return m_current; }
+ IIterator end() const { return nullptr; }
+
+ private:
+ IIterator m_current;
+ };
+
+ struct generator : implements>, iterable_base
+ {
+ explicit generator(IIterator const& first) : m_container(first)
+ {
+ }
+
+ auto& get_container() noexcept
+ {
+ return m_container;
+ }
+
+ auto& get_container() const noexcept
+ {
+ return m_container;
+ }
+
+ private:
+ generator_container m_container;
+ };
+
+ auto v = single_threaded_vector(std::move(values));
+ return make(v.First()).First();
+ }
+}
+
+TEST_CASE("GetMany")
+{
+ // All
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ }
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ }
+
+ // None
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(0 == v.GetMany(3, buffer));
+ REQUIRE(buffer[0] == 0xCC);
+ REQUIRE(buffer[1] == 0xCC);
+ REQUIRE(buffer[2] == 0xCC);
+ }
+ {
+ auto v = single_threaded_vector({ 1,2,3,4 });
+ auto pos = v.First();
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ buffer = { 0xCC, 0xCC, 0xCC };
+ REQUIRE(1 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == 4);
+ REQUIRE(buffer[1] == 0xCC);
+ REQUIRE(buffer[2] == 0xCC);
+ buffer = { 0xCC, 0xCC, 0xCC };
+ REQUIRE(0 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == 0xCC);
+ REQUIRE(buffer[1] == 0xCC);
+ REQUIRE(buffer[2] == 0xCC);
+ }
+
+ // Less
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC };
+ REQUIRE(2 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ }
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC };
+ REQUIRE(2 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ }
+
+ // More
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ REQUIRE(buffer[3] == 0xCC);
+ }
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ REQUIRE(buffer[3] == 0xCC);
+ }
+
+ // Offset
+ {
+ auto v = single_threaded_vector({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
+ REQUIRE(2 == v.GetMany(1, buffer));
+ REQUIRE(buffer[0] == 2);
+ REQUIRE(buffer[1] == 3);
+ REQUIRE(buffer[2] == 0xCC);
+ REQUIRE(buffer[3] == 0xCC);
+ }
+
+ // The same tests but with a non-trivially destructible type...
+
+ // All
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(3 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ }
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(3 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ }
+
+ // None
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(0 == v.GetMany(3, buffer));
+ REQUIRE(buffer[0] == L"");
+ REQUIRE(buffer[1] == L"");
+ REQUIRE(buffer[2] == L"");
+ }
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3",L"4" });
+ auto pos = v.First();
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(3 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ buffer = { L"old", L"old", L"old" };
+ REQUIRE(1 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == L"4");
+ REQUIRE(buffer[1] == L"");
+ REQUIRE(buffer[2] == L"");
+ buffer = { L"old", L"old", L"old" };
+ REQUIRE(0 == pos.GetMany(buffer));
+ REQUIRE(buffer[0] == L"");
+ REQUIRE(buffer[1] == L"");
+ REQUIRE(buffer[2] == L"");
+ }
+
+ // Less
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old" };
+ REQUIRE(2 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ }
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old" };
+ REQUIRE(2 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ }
+
+ // More
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old", L"old" };
+ REQUIRE(3 == v.GetMany(0, buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ REQUIRE(buffer[3] == L"");
+ }
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old", L"old" };
+ REQUIRE(3 == v.First().GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ REQUIRE(buffer[3] == L"");
+ }
+
+ // Offset
+ {
+ auto v = single_threaded_vector({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old", L"old" };
+ REQUIRE(2 == v.GetMany(1, buffer));
+ REQUIRE(buffer[0] == L"2");
+ REQUIRE(buffer[1] == L"3");
+ REQUIRE(buffer[2] == L"");
+ REQUIRE(buffer[3] == L"");
+ }
+
+ // Similar tests but with a list to ensure optimal code gen for containers that don't offer random access.
+
+ // All
+ {
+ IIterator v = single_threaded_generator({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ }
+
+ // None
+ {
+ IIterator v = single_threaded_generator({ 1,2,3,4,5 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ buffer = { 0xCC, 0xCC, 0xCC };
+ REQUIRE(2 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 4);
+ REQUIRE(buffer[1] == 5);
+ REQUIRE(buffer[2] == 0xCC);
+ buffer = { 0xCC, 0xCC, 0xCC };
+ REQUIRE(0 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 0xCC);
+ REQUIRE(buffer[1] == 0xCC);
+ REQUIRE(buffer[2] == 0xCC);
+ }
+
+ // Less
+ {
+ IIterator v = single_threaded_generator({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC };
+ REQUIRE(2 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ }
+
+ // More
+ {
+ IIterator v = single_threaded_generator({ 1,2,3 });
+ std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == 1);
+ REQUIRE(buffer[1] == 2);
+ REQUIRE(buffer[2] == 3);
+ REQUIRE(buffer[3] == 0xCC);
+ }
+
+ // The same tests but with a non-trivially destructible type...
+
+ // All
+ {
+ IIterator v = single_threaded_generator({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ }
+
+ // None
+ {
+ IIterator v = single_threaded_generator({ L"1",L"2",L"3",L"4" });
+ std::array buffer{ L"old", L"old", L"old" };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ buffer = { L"old", L"old", L"old" };
+ REQUIRE(1 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"4");
+ REQUIRE(buffer[1] == L"");
+ REQUIRE(buffer[2] == L"");
+ buffer = { L"old", L"old", L"old" };
+ REQUIRE(0 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"");
+ REQUIRE(buffer[1] == L"");
+ REQUIRE(buffer[2] == L"");
+ }
+
+ // Less
+ {
+ IIterator v = single_threaded_generator({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old" };
+ REQUIRE(2 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ }
+
+ // More
+ {
+ IIterator v = single_threaded_generator({ L"1",L"2",L"3" });
+ std::array buffer{ L"old", L"old", L"old", L"old" };
+ REQUIRE(3 == v.GetMany(buffer));
+ REQUIRE(buffer[0] == L"1");
+ REQUIRE(buffer[1] == L"2");
+ REQUIRE(buffer[2] == L"3");
+ REQUIRE(buffer[3] == L"");
+ }
+
+ // Pair
+ {
+ auto m = single_threaded_map();
+ m.Insert(1, L"1");
+ m.Insert(2, L"2");
+ m.Insert(3, L"3");
+ m.Insert(4, L"4");
+ std::array, 3> buffer;
+ REQUIRE(3 == m.First().GetMany(buffer));
+ REQUIRE(buffer[0].Key() == 1);
+ REQUIRE(buffer[1].Key() == 2);
+ REQUIRE(buffer[2].Key() == 3);
+ REQUIRE(buffer[0].Value() == L"1");
+ REQUIRE(buffer[1].Value() == L"2");
+ REQUIRE(buffer[2].Value() == L"3");
+ }
+}
diff --git a/test/test_win7/abi_guard.cpp b/test/test_win7/abi_guard.cpp
new file mode 100644
index 000000000..c0244a475
--- /dev/null
+++ b/test/test_win7/abi_guard.cpp
@@ -0,0 +1,293 @@
+#include "pch.h"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+
+namespace
+{
+ //
+ // This implemenetation uses the simplest abi_enter and abi_exit methods
+ //
+ struct Simple : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ void abi_enter()
+ {
+ ++m_enter;
+ }
+
+ void abi_exit()
+ {
+ ++m_exit;
+ }
+
+ int m_enter{};
+ int m_exit{};
+ };
+
+ //
+ // This implemenetation uses the abi_enter but omits the abi_exit method
+ //
+ struct OnlyEnter : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ void abi_enter()
+ {
+ ++m_enter;
+ }
+
+ int m_enter{};
+ };
+
+ //
+ // This implemenetation throws from the abi_enter method
+ //
+ struct Throwing : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ void abi_enter()
+ {
+ throw hresult_wrong_thread();
+ }
+
+ void abi_exit()
+ {
+ ++m_exit;
+ }
+
+ int m_exit{};
+ };
+
+ //
+ // This implemenetation provides a nested abi_guard
+ //
+ struct NestedGuard : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ int m_enter{};
+ int m_exit{};
+
+ struct abi_guard
+ {
+ abi_guard(NestedGuard& that) :
+ m_that(that)
+ {
+ ++m_that.m_enter;
+ }
+
+ ~abi_guard()
+ {
+ ++m_that.m_exit;
+ }
+
+ private:
+
+ NestedGuard& m_that;
+ };
+ };
+
+ template
+ struct CountGuard
+ {
+ CountGuard(T& that) :
+ m_that(that)
+ {
+ ++m_that.m_enter;
+ }
+
+ ~CountGuard()
+ {
+ ++m_that.m_exit;
+ }
+
+ private:
+
+ T& m_that;
+ };
+
+ //
+ // This implemenetation use an abi_guard type alias
+ //
+ struct GuardAlias : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ int m_enter{};
+ int m_exit{};
+
+ using abi_guard = CountGuard;
+ };
+
+ template
+ struct ThrowGuard
+ {
+ ThrowGuard(T&)
+ {
+ throw hresult_wrong_thread();
+ }
+ };
+
+ //
+ // This implemenetation use an abi_guard type alias that thows
+ //
+ struct ThrowAlias : implements
+ {
+ void Close()
+ {
+ }
+
+ hstring ToString()
+ {
+ return L"";
+ }
+
+ using abi_guard = ThrowGuard;
+ };
+}
+
+TEST_CASE("abi_guard")
+{
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+ REQUIRE(impl->m_enter == 0);
+ REQUIRE(impl->m_exit == 0);
+
+ IClosable closable = impl.as();
+ closable.Close();
+ REQUIRE(impl->m_enter == 1);
+ REQUIRE(impl->m_exit == 1);
+
+ IStringable stringable = impl.as();
+ stringable.ToString();
+ REQUIRE(impl->m_enter == 2);
+ REQUIRE(impl->m_exit == 2);
+ }
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+
+ REQUIRE(impl->m_enter == 0);
+
+ IClosable closable = impl.as();
+ closable.Close();
+
+ REQUIRE(impl->m_enter == 1);
+
+ IStringable stringable = impl.as();
+ stringable.ToString();
+
+ REQUIRE(impl->m_enter == 2);
+ }
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+
+ IClosable closable = impl.as();
+ REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread);
+
+ IStringable stringable = impl.as();
+ REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread);
+
+ REQUIRE(impl->m_exit == 0);
+ }
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+
+ REQUIRE(impl->m_enter == 0);
+ REQUIRE(impl->m_exit == 0);
+
+ IClosable closable = impl.as();
+ closable.Close();
+
+ REQUIRE(impl->m_enter == 1);
+ REQUIRE(impl->m_exit == 1);
+
+ IStringable stringable = impl.as();
+ stringable.ToString();
+
+ REQUIRE(impl->m_enter == 2);
+ REQUIRE(impl->m_exit == 2);
+ }
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+
+ REQUIRE(impl->m_enter == 0);
+ REQUIRE(impl->m_exit == 0);
+
+ IClosable closable = impl.as();
+ closable.Close();
+
+ REQUIRE(impl->m_enter == 1);
+ REQUIRE(impl->m_exit == 1);
+
+ IStringable stringable = impl.as();
+ stringable.ToString();
+
+ REQUIRE(impl->m_enter == 2);
+ REQUIRE(impl->m_exit == 2);
+ }
+ {
+ com_ptr impl = make_self();
+
+ impl->Close();
+ impl->ToString();
+
+ IClosable closable = impl.as();
+ REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread);
+
+ IStringable stringable = impl.as();
+ REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread);
+ }
+}
diff --git a/test/test_win7/agile_ref.cpp b/test/test_win7/agile_ref.cpp
new file mode 100644
index 000000000..e0ab43a34
--- /dev/null
+++ b/test/test_win7/agile_ref.cpp
@@ -0,0 +1,54 @@
+#include "pch.h"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+
+namespace
+{
+ struct Object : implements