Skip to content

Commit

Permalink
Move user-facing strings to resource files (#1109)
Browse files Browse the repository at this point in the history
Create resource files for WinRT.Host, WinRT Authoring Diagnostics, and WinRT.Runtime.
  • Loading branch information
j0shuams authored Mar 23, 2022
1 parent 090a279 commit 1acc2bc
Show file tree
Hide file tree
Showing 41 changed files with 2,208 additions and 551 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ stages:
Contents: |
WinRT.Host.dll
WinRT.Host.pdb
WinRT.Host.dll.mui
TargetFolder: $(Build.ArtifactStagingDirectory)\native

# Stage Unit Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ stages:
command: pack
searchPatternPack: nuget/Microsoft.Windows.CsWinRT.nuspec
configurationToPack: Release
buildProperties: cswinrt_nuget_version=$(NugetVersion);cswinrt_exe=$(Build.SourcesDirectory)\cswinrt.exe;interop_winmd=$(Build.SourcesDirectory)\WinRT.Interop.winmd;netstandard2_runtime=$(Build.SourcesDirectory)\netstandard2.0\WinRT.Runtime.dll;net5_runtime=$(Build.SourcesDirectory)\net5.0\WinRT.Runtime.dll;source_generator=$(Build.SourcesDirectory)\netstandard2.0\WinRT.SourceGenerator.dll;winrt_shim=$(Build.SourcesDirectory)\net5.0\WinRT.Host.Shim.dll;winrt_host_x86=$(Build.SourcesDirectory)\release_x86\WinRT.Host.dll;winrt_host_x64=$(Build.SourcesDirectory)\release_x64\WinRT.Host.dll;winrt_host_arm64=$(Build.SourcesDirectory)\release_arm64\WinRT.Host.dll;guid_patch=$(Build.SourcesDirectory)\net5.0\IIDOptimizer\*.*
buildProperties: cswinrt_nuget_version=$(NugetVersion);cswinrt_exe=$(Build.SourcesDirectory)\cswinrt.exe;interop_winmd=$(Build.SourcesDirectory)\WinRT.Interop.winmd;netstandard2_runtime=$(Build.SourcesDirectory)\netstandard2.0\WinRT.Runtime.dll;net5_runtime=$(Build.SourcesDirectory)\net5.0\WinRT.Runtime.dll;source_generator=$(Build.SourcesDirectory)\netstandard2.0\WinRT.SourceGenerator.dll;winrt_shim=$(Build.SourcesDirectory)\net5.0\WinRT.Host.Shim.dll;winrt_host_x86=$(Build.SourcesDirectory)\release_x86\WinRT.Host.dll;winrt_host_x64=$(Build.SourcesDirectory)\release_x64\WinRT.Host.dll;winrt_host_arm64=$(Build.SourcesDirectory)\release_arm64\WinRT.Host.dll;winrt_host_resource_x86=$(Build.SourcesDirectory)\release_x86\WinRT.Host.dll.mui;winrt_host_resource_x64=$(Build.SourcesDirectory)\release_x64\WinRT.Host.dll.mui;winrt_host_resource_arm64=$(Build.SourcesDirectory)\release_arm64\WinRT.Host.dll.mui;guid_patch=$(Build.SourcesDirectory)\net5.0\IIDOptimizer\*.*

# ESRP CodeSigning
- task: EsrpCodeSigning@1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<HostingAssets Include="$(MSBuildThisFileDirectory)..\build\native\WinRT.Host.runtimeconfig.json"/>
<!-- Get the proper WinRT.Host.dll -->
<HostingAssets Include="$(MSBuildThisFileDirectory)..\runtimes\win-$(_NormalizedPlatform)\native\WinRT.Host.dll" />
<HostingAssets Include="$(MSBuildThisFileDirectory)..\runtimes\win-$(_NormalizedPlatform)\native\en-us\WinRT.Host.dll.mui" />
</ItemGroup>

<!-- Add the WinMD file as a reference of the native app so a projection gets made -->
Expand Down
29 changes: 24 additions & 5 deletions nuget/Microsoft.Windows.CsWinRT.Authoring.targets
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

<None Condition="Exists('$(CsWinRTPath)runtimes\win-$(CsWinRTAuthoring_Platform)\native\en-us\WinRT.Host.dll.mui')"
Include="$(CsWinRTPath)runtimes\win-$(CsWinRTAuthoring_Platform)\native\en-us\WinRT.Host.dll.mui">
<TargetPath>WinRT.Host.dll.mui</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

</ItemGroup>

<!-- Any managed dependencies of the WinRT component won't automatically be brought
Expand Down Expand Up @@ -320,26 +326,39 @@ Copyright (C) Microsoft Corporation. All rights reserved.
</Content>

<!-- We package a version of WinRT.Host.dll for each possible architecture -->
<!-- x64 -->
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-x64\native\WinRT.Host.dll')" Include="$(CsWinRTPath)runtimes\win-x64\native\WinRT.Host.dll">
<Pack>true</Pack>
<PackagePath>runtimes\win-x64\native</PackagePath>
</Content>
<!-- x86 -->
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-x86\native\WinRT.Host.dll')" Include="$(CsWinRTPath)runtimes\win-x86\native\WinRT.Host.dll">
<Pack>true</Pack>
<PackagePath>runtimes\win-x86\native</PackagePath>
</Content>
<!-- arm -->
</Content>
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-arm\native\WinRT.Host.dll')" Include="$(CsWinRTPath)runtimes\win-arm\native\WinRT.Host.dll">
<Pack>true</Pack>
<PackagePath>runtimes\win-arm\native</PackagePath>
</Content>
<!-- arm64 -->
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-arm64\native\WinRT.Host.dll')" Include="$(CsWinRTPath)runtimes\win-arm64\native\WinRT.Host.dll">
<Pack>true</Pack>
<PackagePath>runtimes\win-arm64\native</PackagePath>
</Content>
<!-- Package the MUI for WinRT.Host error strings -->
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-x64\native\en-us\WinRT.Host.dll.mui')" Include="$(CsWinRTPath)runtimes\win-x64\native\en-us\WinRT.Host.dll.mui">
<Pack>true</Pack>
<PackagePath>runtimes\win-x64\native\en-us</PackagePath>
</Content>
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-x86\native\en-us\WinRT.Host.Host.dll.mui')" Include="$(CsWinRTPath)runtimes\win-x86\native\en-us\WinRT.Host.dll.mui">
<Pack>true</Pack>
<PackagePath>runtimes\win-x86\native\en-us</PackagePath>
</Content>
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-arm\native\en-us\WinRT.Host.dll.mui')" Include="$(CsWinRTPath)runtimes\win-arm\native\en-us\WinRT.Host.dll.mui">
<Pack>true</Pack>
<PackagePath>runtimes\win-arm\native\en-us</PackagePath>
</Content>
<Content Condition="Exists('$(CsWinRTPath)runtimes\win-arm64\native\en-us\WinRT.Host.dll.mui')" Include="$(CsWinRTPath)runtimes\win-arm64\native\en-us\WinRT.Host.dll.mui">
<Pack>true</Pack>
<PackagePath>runtimes\win-arm64\native\en-us</PackagePath>
</Content>
</ItemGroup>

</Target>
Expand Down
4 changes: 4 additions & 0 deletions nuget/Microsoft.Windows.CsWinRT.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<file src="$winrt_host_x86$" target ="runtimes\win-x86\native"/>
<file src="$winrt_host_arm$" target ="runtimes\win-arm\native"/>
<file src="$winrt_host_arm64$" target ="runtimes\win-arm64\native"/>
<file src="$winrt_host_resource_x64$" target ="runtimes\win-x64\native\en-us"/>
<file src="$winrt_host_resource_x86$" target ="runtimes\win-x86\native\en-us"/>
<file src="$winrt_host_resource_arm$" target ="runtimes\win-arm\native\en-us"/>
<file src="$winrt_host_resource_arm64$" target ="runtimes\win-arm64\native\en-us"/>
<file src="$winrt_shim$" target ="lib\net5.0\"/>

<!-- Add the WinRT.Runtime sources to the pkg for embedded scenarios -->
Expand Down
28 changes: 28 additions & 0 deletions src/Authoring/WinRT.Host/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!--
***********************************************************************************************
Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<Target Name="SplitWinRTHostIntoMUI"
Inputs="$(OutDir)WinRT.Host.dll"
Outputs="$(OutDir)WinRT.Host.dll;$(OutDir)WinRT.Host.dll.mui"
AfterTargets="CopyFilesToOutputDirectory">

<!-- Invoke the muicrt tool to split Winrt.Host into language neutral parts and localizable resources
Then invoke the tool again to apply the checksum from the neutral part to the mui
Finally, replace the initially built WinRT.Host with the language neutral version -->
<PropertyGroup>
<WinRTHostMuirctCommand>Muirct.exe -q "$(MSBuildThisFileDirectory)WinRTHost.rcconfig.xml" -v 2 -x 0x0409 -g 0x0409 "$(OutDir)WinRT.Host.dll" "$(OutDir)WinRT.Host_LN.dll" "$(OutDir)WinRT.Host.dll.mui"
muirct.exe -c "$(OutDir)WinRT.Host_LN.dll" -e "$(OutDir)WinRT.Host.dll.mui"
copy /y "$(OutDir)WinRT.Host.dll" "$(OutDir)WinRT.Host.Original.exe"
copy /y "$(OutDir)WinRT.Host_LN.dll" "$(OutDir)WinRT.Host.dll"
del "$(OutDir)WinRT.Host_LN.dll"
</WinRTHostMuirctCommand>
</PropertyGroup>

<Exec Command="$(WinRTHostMuirctCommand)" />
</Target>

</Project>
114 changes: 77 additions & 37 deletions src/Authoring/WinRT.Host/WinRT.Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
#include <winrt/Windows.Storage.h>
#include <roerrorapi.h>

// provides CString, used to retrieve error messages from Resource string table
#include "atlstr.h"
// provides mappings for hostfxr error codes and error strings
#include "resource.h"

using namespace winrt;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::Data::Json;
Expand All @@ -28,6 +33,10 @@ using namespace winrt::Windows::Data::Json;

#include <mscoree.h>

#define SUFFICIENTLY_LARGE_ERROR_BUFFER (1024*2)
#define SUFFICIENTLY_LARGE_STRING_BUFFER (MAX_PATH*2)
#define WINRT_HOST_FILE_PATH (L"WinRT.Host.dll.mui")

// Global function pointers
typedef int (CORECLR_DELEGATE_CALLTYPE* get_activation_factory_fn)(
void* hstr_target_path, void* hstr_class_id, void** activation_factory);
Expand All @@ -43,51 +52,82 @@ static load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_
static const struct
{
HostFxrStatus status;
const wchar_t* message;
int resourceID;
}
hostfxr_status_messages[] =
{
{ InvalidArgFailure, L"One of the specified arguments for the operation is invalid." },
{ CoreHostLibLoadFailure, L"There was a failure loading a dependent library." },
{ CoreHostLibMissingFailure, L"One of the dependent libraries is missing." },
{ CoreHostEntryPointFailure, L"One of the dependent libraries is missing a required entry point." },
{ CoreHostCurHostFindFailure, L"Could not deduce installation location from current module." },
{ CoreClrResolveFailure, L"The coreclr library could not be found." },
{ CoreClrBindFailure, L"The loaded coreclr library doesn't have one of the required entry points." },
{ CoreClrInitFailure, L"The call to coreclr_initialize failed." },
{ CoreClrExeFailure, L"The call to coreclr_execute_assembly failed." },
{ ResolverInitFailure, L"Initialization of the hostpolicy dependency resolver failed." },
{ ResolverResolveFailure, L"Resolution of dependencies in hostpolicy failed." },
{ LibHostCurExeFindFailure, L"Failure to determine the location of the current executable." },
{ LibHostInitFailure, L"Initialization of the hostpolicy library failed." },
{ LibHostSdkFindFailure, L"Failure to find the requested SDK. This happens in the hostfxr when an SDK(also called CLI) command is used with dotnet. In this case the hosting layer tries to find an installed. NET SDK to run the command on. The search is based on deduced install locationand on the requested version from potential global. json file. If either no matching SDK version can be found, or that version exists, but it's missing the dotnet. dll file, this error code is returned." },
{ LibHostInvalidArgs, L"Arguments to hostpolicy are invalid." },
{ InvalidConfigFile, L"The .runtimeconfig.json file is invalid." },
{ AppArgNotRunnable, L"The command line for dotnet.exe doesn't contain the path to the application." },
{ AppHostExeNotBoundFailure, L"Apphost failed to determine which application to run." },
{ FrameworkMissingFailure, L"It was not possible to find a compatible framework version." },
{ HostApiFailed, L"The hostpolicy could not calculate the NATIVE_DLL_SEARCH_DIRECTORIES." },
{ HostApiBufferTooSmall, L"The buffer specified to an API is not big enough to fit the requested value." },
{ LibHostUnknownCommand, L"The corehost_main_with_output_buffer is called with unsupported host command." },
{ LibHostAppRootFindFailure, L"The imprinted application path doesn't exist." },
{ SdkResolverResolveFailure, L"hostfxr_resolve_sdk2 failed to find matching SDK." },
{ FrameworkCompatFailure, L"The .runtimeconfig.json contains two incompatible framework references." },
{ FrameworkCompatRetry, L"A previously processed framework reference was reprocessed." },
{ BundleExtractionFailure, L"Error extracting single-file apphost bundle." },
{ BundleExtractionIOError, L"Error reading or writing files during single-file apphost bundle extraction." },
{ LibHostDuplicateProperty, L"The .runtimeconfig.json contains a runtime property which is also produced by the hosting layer." },
{ HostApiUnsupportedVersion, L"Feature which requires certain version of the hosting layer binaries was used on a version which doesn't support it." },
{ HostInvalidState, L"The current state is incompatible with the requested operation." },
{ HostPropertyNotFound, L"A property requested by hostfxr_get_runtime_property_value doesn't exist." },
{ CoreHostIncompatibleConfig, L"The component being initialized requires framework which is not available" },
{ HostApiUnsupportedScenario, L"hostfxr doesn't currently support requesting the given delegate type using the given context." },
{ InvalidArgFailure, InvalidArgFailureStr },
{ CoreHostLibLoadFailure, CoreHostLibLoadFailureStr },
{ CoreHostLibMissingFailure, CoreHostLibMissingFailureStr },
{ CoreHostEntryPointFailure, CoreHostEntryPointFailureStr },
{ CoreHostCurHostFindFailure, CoreHostCurHostFindFailureStr },
{ CoreClrResolveFailure, CoreClrResolveFailureStr },
{ CoreClrBindFailure, CoreClrBindFailureStr },
{ CoreClrInitFailure, CoreClrInitFailureStr },
{ CoreClrExeFailure, CoreClrExeFailureStr },
{ ResolverInitFailure, ResolverInitFailureStr },
{ ResolverResolveFailure, ResolverResolveFailureStr },
{ LibHostCurExeFindFailure, LibHostCurExeFindFailureStr },
{ LibHostInitFailure, LibHostInitFailureStr },
{ LibHostSdkFindFailure, LibHostSdkFindFailureStr },
{ LibHostInvalidArgs, LibHostInvalidArgsStr },
{ InvalidConfigFile, InvalidConfigFileStr },
{ AppArgNotRunnable, AppArgNotRunnableStr },
{ AppHostExeNotBoundFailure, AppHostExeNotBoundFailureStr },
{ FrameworkMissingFailure, FrameworkMissingFailureStr },
{ HostApiFailed, HostApiFailedStr },
{ HostApiBufferTooSmall, HostApiBufferTooSmallStr },
{ LibHostUnknownCommand, LibHostUnknownCommandStr },
{ LibHostAppRootFindFailure, LibHostAppRootFindFailureStr },
{ SdkResolverResolveFailure, SdkResolverResolveFailureStr },
{ FrameworkCompatFailure, FrameworkCompatFailureStr },
{ FrameworkCompatRetry, FrameworkCompatRetryStr },
{ BundleExtractionFailure, BundleExtractionFailureStr },
{ BundleExtractionIOError, BundleExtractionIOErrorStr },
{ LibHostDuplicateProperty, LibHostDuplicatePropertyStr },
{ HostApiUnsupportedVersion, HostApiUnsupportedVersionStr },
{ HostInvalidState, HostInvalidStateStr },
{ HostPropertyNotFound, HostPropertyNotFoundStr },
{ CoreHostIncompatibleConfig, CoreHostIncompatibleConfigStr },
{ HostApiUnsupportedScenario, HostApiUnsupportedScenarioStr },
};

auto string_table_entry = 0;
for (auto&& elem : hostfxr_status_messages)
{
{
if (elem.status == result)
{
throw hresult_error(result, elem.message);
string_table_entry = elem.resourceID;
break;
}
}

if (string_table_entry != 0)
{
WCHAR error_string[SUFFICIENTLY_LARGE_STRING_BUFFER];
WCHAR error_string_buffer[SUFFICIENTLY_LARGE_ERROR_BUFFER];

HMODULE resources_handle = LoadLibraryExW(WINRT_HOST_FILE_PATH, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);

if (!resources_handle)
{
// Error if we fail to load WinRT.Host resource file
swprintf_s(error_string_buffer, SUFFICIENTLY_LARGE_ERROR_BUFFER, L"Error: Unable to load the resource container module, last error = %d", GetLastError());
throw hresult_error(result, error_string_buffer);
}
else if (LoadStringW(resources_handle, string_table_entry, error_string, SUFFICIENTLY_LARGE_STRING_BUFFER) == 0)
{
// Error if we fail to load the string
swprintf_s(error_string_buffer, SUFFICIENTLY_LARGE_ERROR_BUFFER, L"Error: Unable to load the resource string, last error = %d.", GetLastError());
FreeLibrary(resources_handle);
throw hresult_error(result, error_string_buffer);
}
else
{
// Everything loaded fine, load the retrieved string and finish
swprintf_s(error_string_buffer, SUFFICIENTLY_LARGE_STRING_BUFFER, L"%s", error_string);
FreeLibrary(resources_handle);
throw hresult_error(result, error_string_buffer);
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/Authoring/WinRT.Host/WinRT.Host.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,15 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<!-- Temporarily disable LinkTimeCodeGen to work around incompatibility of VS16.7-built libnethost.lib and VS16.8-built winrt.host:
<!-- Temporarily disable LinkTimeCodeGen to work around incompatibility of VS16.7-built libnethost.lib and VS16.8-built winrt.host:
LINK : fatal error C1047: The object or library file ...libnethost.lib was created by a different version of the compiler than other objects like dllmain.obj... -->
<AdditionalOptions>/GL- %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="hostfxr_status.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
Expand All @@ -282,6 +283,7 @@
<ClCompile Include="WinRT.Host.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="Directory.Build.targets" />
<None Include="module.def" />
<None Include="NetHost.targets" />
<None Include="NetHostDir.csproj" />
Expand All @@ -292,6 +294,12 @@
<Project>{0bb8f82d-874e-45aa-bca3-20ce0562164a}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WinRTHostErrorStrings.rc" />
</ItemGroup>
<ItemGroup>
<Xml Include="WinRTHost.rcconfig.xml" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
Expand Down
Loading

0 comments on commit 1acc2bc

Please sign in to comment.