Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues in UndockedRegFreeWinRT auto-initializer and support for Self-contained #2502

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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<Target Name="GenerateUndockedRegFreeWinRTCS" BeforeTargets="BeforeCompile">
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\include\MddUndockedRegFreeWinRT-AutoInitializer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\include\UndockedRegFreeWinRT-AutoInitializer.cs" />
</ItemGroup>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
<WindowsAppSdkUndockedRegFreeWinRTInitialize>true</WindowsAppSdkUndockedRegFreeWinRTInitialize>
</PropertyGroup>

<PropertyGroup Condition="'$(WindowsAppSdkUndockedRegFreeWinRTInitializeLoadLibrary)'=='' and '$(WindowsAppSdkUndockedRegFreeWinRTInitialize)'=='true'">
<WindowsAppSdkUndockedRegFreeWinRTInitializeLoadLibrary>true</WindowsAppSdkUndockedRegFreeWinRTInitializeLoadLibrary>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<Target Name="GenerateUndockedRegFreeWinRTCpp" BeforeTargets="ClCompile">
<Target Name="GenerateUndockedRegFreeWinRTCpp" BeforeTargets="ClCompile" Condition="'$(WindowsAppSdkUndockedRegFreeWinRTInitialize)' == 'true'">
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\include\MddUndockedRegFreeWinRT-AutoInitializer.cpp" />
<ClCompile>
<PreprocessorDefinitions>MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(WindowsAppSdkUndockedRegFreeWinRTInitializeLoadLibrary)' == 'true'">MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE_LOADLIBRARY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\include\UndockedRegFreeWinRT-AutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(WindowsAppSdkUndockedRegFreeWinRTInitializeLoadLibrary)' == 'true'">MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE_LOADLIBRARY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
</Target>

Expand Down
45 changes: 31 additions & 14 deletions dev/UndockedRegFreeWinRT/UndockedRegFreeWinRT-AutoInitializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,41 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include <Windows.h>
#include <stdlib.h>

// Do nothing. Just exist.
//
// This ensures the including PE file has an import reference
// to the WindowsAppSDK runtime DLL and thus gets loaded when
// Ensure the including PE file has an import reference to
// the WindowsAppSDK runtime DLL and thus gets loaded when
// the including PE file gets loaded.

STDAPI UndockedRegFreeWinRT_EnsureIsLoaded();
STDAPI WindowsAppRuntime_EnsureIsLoaded();

// NOTE: Disable optimizations to ensure this unreferenced symbol
// doesn't get 'optimized away'. We need the end compiled binary
// to import this symbol from the Windows App SDK runtime DLL.
#pragma optimize("", off)
namespace Microsoft::Windows::Foundation::UndockedRegFreeWinRT
{
static void EnsureIsLoaded()
{
(void) UndockedRegFreeWinRT_EnsureIsLoaded();
}
struct AutoInitialize
{
AutoInitialize()
{
// Load the Windows App SDK runtime DLL. The only reason this could fail
// is if the loading application using WinAppSDK/SelfContained has a
// damaged self-contained configuration of the Windows App SDK's runtime.

// Define MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE_LOADLIBRARY
// if Microsoft.WindowsAppRuntime.dll is DelayLoad'd and thus we need
// to explicitly load the DLL at runtime. Otherwise we can implicitly
// link the library and get an import reference causing Windows to
// resolve our import at load-time.
#if defined(MICROSOFT_WINDOWSAPPSDK_UNDOCKEDREGFREEWINRT_AUTO_INITIALIZE_LOADLIBRARY)
static HMODULE dll{ LoadLibraryExW(L"Microsoft.WindowsAppRuntime.dll", nullptr, 0) };
if (!dll)
{
const auto lastError{ GetLastError() };
DebugBreak();
exit(HRESULT_FROM_WIN32(lastError));
}
#else
(void) WindowsAppRuntime_EnsureIsLoaded();
#endif
}
};
static AutoInitialize g_autoInitialize;
}
#pragma optimize("", on)
10 changes: 2 additions & 8 deletions dev/UndockedRegFreeWinRT/UndockedRegFreeWinRT-AutoInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,19 @@ namespace Microsoft.Windows.Foundation.UndockedRegFreeWinRTCS
internal static class NativeMethods
{
[DllImport("Microsoft.WindowsAppRuntime.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern int UndockedRegFreeWinRT_EnsureIsLoaded();
internal static extern int WindowsAppRuntime_EnsureIsLoaded();
}

class AutoInitialize
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void AccessWindowsAppSDK()
{
// Do nothing if we're being loaded for reflection (rather than execcution)
if (Assembly.GetEntryAssembly() != Assembly.GetExecutingAssembly())
{
return;
}

// No error handling needed as the target function does nothing (just {return S_OK}).
// It's the act of calling the function causing the DllImport to load the DLL that
// matters. This provides the moral equivalent of a native DLL's Import Address
// Table (IAT) have an entry that's resolved when this module is loaded.
NativeMethods.UndockedRegFreeWinRT_EnsureIsLoaded();
NativeMethods.WindowsAppRuntime_EnsureIsLoaded();
}
}
}
6 changes: 3 additions & 3 deletions dev/UndockedRegFreeWinRT/catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ HRESULT LoadManifestFromPath(std::wstring path)
return COR_E_ARGUMENT;
}
std::wstring ext(path.substr(path.size() - 4, path.size()));
if ((CompareStringOrdinal(ext.c_str(), -1, L".exe.", -1, TRUE) == CSTR_EQUAL) ||
(CompareStringOrdinal(ext.c_str(), -1, L".dll.", -1, TRUE) == CSTR_EQUAL))
if ((CompareStringOrdinal(ext.c_str(), -1, L".exe", -1, TRUE) == CSTR_EQUAL) ||
(CompareStringOrdinal(ext.c_str(), -1, L".dll", -1, TRUE) == CSTR_EQUAL))
{
return LoadFromEmbeddedManifest(path.c_str());
}
Expand Down Expand Up @@ -405,7 +405,7 @@ HRESULT WinRTGetMetadataFile(
// will create an instance of the metadata reader to dispense metadata files.
if (metaDataDispenser == nullptr)
{
// Avoid using CoCreateInstance here, which will trigger a Feature-On-Demand (FOD)
// Avoid using CoCreateInstance here, which will trigger a Feature-On-Demand (FOD)
// installation request of .NET Framework 3.5 if it's not already installed. In the
// mean time, Windows App SDK runtime doesn't need .NET Framework 3.5.
RETURN_IF_FAILED(MetaDataGetDispenser(CLSID_CorMetaDataDispenser,
Expand Down
2 changes: 1 addition & 1 deletion dev/UndockedRegFreeWinRT/urfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ HRESULT UrfwInitialize() noexcept
DetourAttach(&(PVOID&)TrueRoResolveNamespace, RoResolveNamespaceDetour);
try
{
ExtRoLoadCatalog();
RETURN_IF_FAILED(ExtRoLoadCatalog());
}
catch (...)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ class AutoInitialize
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void AccessWindowsAppSDK()
{
// Do nothing if we're being loaded for reflection (rather than execcution)
if (Assembly.GetEntryAssembly() != Assembly.GetExecutingAssembly())
{
return;
}

uint majorMinorVersion = global::Microsoft.WindowsAppSDK.Release.MajorMinor;
string versionTag = global::Microsoft.WindowsAppSDK.Release.VersionTag;
var minVersion = new PackageVersion(global::Microsoft.WindowsAppSDK.Runtime.Version.UInt64);
Expand Down