diff --git a/build/AzurePipelinesTemplates/WindowsAppSDK-CreateNugetPackage-Job.yml b/build/AzurePipelinesTemplates/WindowsAppSDK-CreateNugetPackage-Job.yml index a0f273469c..1296147305 100644 --- a/build/AzurePipelinesTemplates/WindowsAppSDK-CreateNugetPackage-Job.yml +++ b/build/AzurePipelinesTemplates/WindowsAppSDK-CreateNugetPackage-Job.yml @@ -62,7 +62,7 @@ jobs: Copy-Item -Path "$targetsFilePath\Microsoft.WindowsAppSDK.Foundation.props" -Destination "$fullpackagePath\build\Microsoft.WindowsAppSDK.Foundation.props" Copy-Item -Path "$targetsFilePath\Microsoft.WindowsAppSDK.Bootstrap.CS.targets" -Destination "$fullpackagePath\build\Microsoft.WindowsAppSDK.Bootstrap.CS.targets" Copy-Item -Path "$targetsFilePath\WindowsAppSDK-Nuget-Native.Bootstrap.targets" -Destination "$fullpackagePath\build\native\WindowsAppSDK-Nuget-Native.Bootstrap.targets" - Copy-Item -Path "$targetsFilePath\Microsoft.WindowsAppSDK.MddCommon.targets" -Destination "$fullpackagePath\build\Microsoft.WindowsAppSDK.MddCommon.targets" + Copy-Item -Path "$targetsFilePath\Microsoft.WindowsAppSDK.BootstrapCommon.targets" -Destination "$fullpackagePath\build\Microsoft.WindowsAppSDK.BootstrapCommon.targets" Copy-Item -Path "$targetsFilePath\AppxManifest.xml" -Destination "$fullpackagePath\AppxManifest.xml" $manifestPath = $fullpackagePath+'\manifests'; @@ -70,7 +70,7 @@ jobs: $xslt = New-Object System.Xml.Xsl.XslCompiledTransform; $xslt.Load('build\TransformAppxManifest.xslt'); $xslt.Transform($fullpackagePath+'\AppxManifest.xml', $manifestPath+'\Microsoft.WindowsAppSdk.Foundation.manifest'); - + # - script: | # dir /s $(Build.SourcesDirectory) diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets index f2c0c619f9..40245ac05a 100644 --- a/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets +++ b/build/NuSpecs/Microsoft.WindowsAppSDK.Bootstrap.CS.targets @@ -1,7 +1,17 @@ - + - + + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI + $(DefineConstants);MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP + + + diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.MddCommon.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.BootstrapCommon.targets similarity index 100% rename from build/NuSpecs/Microsoft.WindowsAppSDK.MddCommon.targets rename to build/NuSpecs/Microsoft.WindowsAppSDK.BootstrapCommon.targets diff --git a/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets b/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets index 5db18898aa..6208013d3f 100644 --- a/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets +++ b/build/NuSpecs/Microsoft.WindowsAppSDK.Foundation.targets @@ -2,6 +2,6 @@ - + diff --git a/build/NuSpecs/WindowsAppSDK-Nuget-Native.Bootstrap.targets b/build/NuSpecs/WindowsAppSDK-Nuget-Native.Bootstrap.targets index f2201a59b9..573c99e2b1 100644 --- a/build/NuSpecs/WindowsAppSDK-Nuget-Native.Bootstrap.targets +++ b/build/NuSpecs/WindowsAppSDK-Nuget-Native.Bootstrap.targets @@ -1,11 +1,17 @@ - + - + - - NotUsing - + + NotUsing + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI;%(PreprocessorDefinitions) + MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP;%(PreprocessorDefinitions) + diff --git a/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets b/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets index 36c4b27764..53ca33980f 100644 --- a/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets +++ b/build/NuSpecs/WindowsAppSDK-Nuget-Native.targets @@ -61,7 +61,7 @@ - + diff --git a/dev/Bootstrap/CS/Microsoft.WindowsAppRuntime.Bootstrap.Net/Bootstrap.cs b/dev/Bootstrap/CS/Microsoft.WindowsAppRuntime.Bootstrap.Net/Bootstrap.cs index a36ce03a21..413864eabd 100644 --- a/dev/Bootstrap/CS/Microsoft.WindowsAppRuntime.Bootstrap.Net/Bootstrap.cs +++ b/dev/Bootstrap/CS/Microsoft.WindowsAppRuntime.Bootstrap.Net/Bootstrap.cs @@ -66,11 +66,11 @@ public override string ToString() internal static class NativeMethods { - [DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", EntryPoint = "MddBootstrapInitialize", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] - internal static extern void MddBootstrapInitialize_Throw(uint majorMinorVersion, string versionTag, PackageVersion packageVersion); + [DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", EntryPoint = "MddBootstrapInitialize2", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] + internal static extern void MddBootstrapInitialize2_Throw(uint majorMinorVersion, string versionTag, PackageVersion packageVersion, Bootstrap.InitializeOptions options); [DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] - internal static extern int MddBootstrapInitialize(uint majorMinorVersion, string versionTag, PackageVersion packageVersion); + internal static extern int MddBootstrapInitialize2(uint majorMinorVersion, string versionTag, PackageVersion packageVersion, Bootstrap.InitializeOptions options); [DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", ExactSpelling = true)] internal static extern void MddBootstrapShutdown(); @@ -79,17 +79,40 @@ internal static class NativeMethods // The Windows App SDK bootstrap initialization API. public class Bootstrap { + /// Options for Bootstrap initialization APIs. + public enum InitializeOptions : int + { + /// Default behavior + None = 0, + + /// If not successful call DebugBreak() + OnError_DebugBreak = 0x0001, + + /// If not successful call DebugBreak() if a debugger is attached to the process + OnError_DebugBreak_IfDebuggerAttached = 0x0002, + + /// If not successful perform a fail-fast + OnError_FailFast = 0x0004, + + /// If a compatible Windows App Runtime framework package is not found show UI + OnNoMatch_ShowUI = 0x0008, + + /// Do nothing (do not error) if the process has package identity + OnPackageIdentity_NOOP = 0x0010, + } + /// Initialize the calling process to use Windows App SDK's framework package. /// /// Find a Windows App SDK framework package meeting the criteria and make it available /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// - /// This is equivalent to `Initialize(majorMinorVersion, null, new PackageVersion())`. + /// This is equivalent to `Initialize(majorMinorVersion, null, new PackageVersion(), InitializeOptions.None)`. /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @see Initialize(uint, string) /// @see Initialize(uint, string, PackageVersion) + /// @see Initialize(uint, string, PackageVersion, InitializeOptions) /// @see Shutdown() public static void Initialize(uint majorMinorVersion) { @@ -102,12 +125,13 @@ public static void Initialize(uint majorMinorVersion) /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// - /// This is equivalent to `Initialize(majorMinorVersion, versionTag, new PackageVersion())`. + /// This is equivalent to `Initialize(majorMinorVersion, versionTag, new PackageVersion(), InitializeOptions.None)`. /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @see Initialize(uint) /// @see Initialize(uint, string, PackageVersion) + /// @see Initialize(uint, string, PackageVersion, InitializeOptions) /// @see Shutdown() public static void Initialize(uint majorMinorVersion, string versionTag) { @@ -120,15 +144,37 @@ public static void Initialize(uint majorMinorVersion, string versionTag) /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// + /// This is equivalent to `Initialize(majorMinorVersion, versionTag, minVersion, InitializeOptions.None)`. + /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". - /// @param minVersion the minimum version to use + /// @param minVersion the minimum version to use. /// @see Initialize(uint) /// @see Initialize(uint, string) + /// @see Initialize(uint, string, PackageVersion, InitializeOptions) /// @see Shutdown() public static void Initialize(uint majorMinorVersion, string versionTag, PackageVersion minVersion) { - NativeMethods.MddBootstrapInitialize_Throw(majorMinorVersion, versionTag, minVersion); + NativeMethods.MddBootstrapInitialize2_Throw(majorMinorVersion, versionTag, minVersion, InitializeOptions.None); + } + + /// Initialize the calling process to use Windows App SDK's framework package. + /// + /// Find a Windows App SDK framework package meeting the criteria and make it available + /// for use by the current process. If multiple packages meet the criteria the best + /// candidate is selected. + /// + /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). + /// @param versionTag version tag (if any), e.g. "preview1". + /// @param minVersion the minimum version to use. + /// @param options optional behavior. + /// @see Initialize(uint) + /// @see Initialize(uint, string) + /// @see Initialize(uint, string, PackageVersion) + /// @see Shutdown() + public static void Initialize(uint majorMinorVersion, string versionTag, PackageVersion minVersion, InitializeOptions options) + { + NativeMethods.MddBootstrapInitialize2_Throw(majorMinorVersion, versionTag, minVersion, options); } /// Initialize the calling process to use Windows App SDK's framework package. @@ -138,12 +184,12 @@ public static void Initialize(uint majorMinorVersion, string versionTag, Package /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// - /// This is equivalent to `TryInitialize(majorMinorVersion, null, new PackageVersion(), hresult)`. + /// This is equivalent to `TryInitialize(majorMinorVersion, null, new PackageVersion(), InitializeOptions.None, hresult)`. /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @retval true if successful, otherwise false is returned. /// @see TryInitialize(uint, string, out int) - /// @see TryInitialize(uint, string, PackageVersion, out int) + /// @see TryInitialize(uint, string, PackageVersion, InitializeOptions, out int) /// @see Shutdown() public static bool TryInitialize(uint majorMinorVersion, out int hresult) { @@ -157,13 +203,14 @@ public static bool TryInitialize(uint majorMinorVersion, out int hresult) /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// - /// This is equivalent to `TryInitialize(majorMinorVersion, versionTag, new PackageVersion(), hresult)`. + /// This is equivalent to `TryInitialize(majorMinorVersion, versionTag, new PackageVersion(), InitializeOptions.None, hresult)`. /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @retval true if successful, otherwise false is returned. /// @see TryInitialize(uint, out int) /// @see TryInitialize(uint, string, PackageVersion, out int) + /// @see TryInitialize(uint, string, PackageVersion, InitializeOptions, out int) /// @see Shutdown() public static bool TryInitialize(uint majorMinorVersion, string versionTag, out int hresult) { @@ -178,17 +225,43 @@ public static bool TryInitialize(uint majorMinorVersion, string versionTag, out /// for use by the current process. If multiple packages meet the criteria the best /// candidate is selected. /// + /// This is equivalent to `TryInitialize(majorMinorVersion, versionTag, minVersion, InitializeOptions.None, hresult)`. + /// /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @param minVersion the minimum version to use. + /// @param options optional behavior. /// @param hresult the error code if an error occurred. /// @retval true if successful, otherwise false is returned. /// @see TryInitialize(uint, out int) /// @see TryInitialize(uint, string, out int) + /// @see TryInitialize(uint, string, PackageVersion, out int) /// @see Shutdown() public static bool TryInitialize(uint majorMinorVersion, string versionTag, PackageVersion minVersion, out int hresult) { - hresult = NativeMethods.MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion); + return TryInitialize(majorMinorVersion, versionTag, minVersion, InitializeOptions.None, out hresult); + } + + /// Initialize the calling process to use Windows App SDK's framework package. + /// Failure returns false with the failure HRESULT in the hresult parameter. + /// + /// Find a Windows App SDK framework package meeting the criteria and make it available + /// for use by the current process. If multiple packages meet the criteria the best + /// candidate is selected. + /// + /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). + /// @param versionTag version tag (if any), e.g. "preview1". + /// @param minVersion the minimum version to use. + /// @param options optional behavior. + /// @param hresult the error code if an error occurred. + /// @retval true if successful, otherwise false is returned. + /// @see TryInitialize(uint, out int) + /// @see TryInitialize(uint, string, out int) + /// @see TryInitialize(uint, string, PackageVersion, out int) + /// @see Shutdown() + public static bool TryInitialize(uint majorMinorVersion, string versionTag, PackageVersion minVersion, InitializeOptions options, out int hresult) + { + hresult = NativeMethods.MddBootstrapInitialize2(majorMinorVersion, versionTag, minVersion, options); return hresult >= 0; } @@ -199,9 +272,11 @@ public static bool TryInitialize(uint majorMinorVersion, string versionTag, Pack /// @see Initialize(uint) /// @see Initialize(uint, string) /// @see Initialize(uint, string, PackageVersion) + /// @see Initialize(uint, string, PackageVersion, InitializeOptions options) /// @see TryInitialize(uint, out int) /// @see TryInitialize(uint, string, out int) /// @see TryInitialize(uint, string, PackageVersion, out int) + /// @see TryInitialize(uint, string, PackageVersion, InitializeOptions options, out int) public static void Shutdown() { NativeMethods.MddBootstrapShutdown(); diff --git a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp index fca34d048f..6f68ca591c 100644 --- a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp +++ b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.cpp @@ -12,6 +12,10 @@ #include +HRESULT _MddBootstrapInitialize( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion) noexcept; void VerifyInitializationIsCompatible( UINT32 majorMinorVersion, PCWSTR versionTag, @@ -54,6 +58,16 @@ void FindDDLMViaEnumeration( std::wstring& ddlmPackageFamilyName, std::wstring& ddlmPackageFullName); CLSID GetClsid(const winrt::Windows::ApplicationModel::AppExtensions::AppExtension& appExtension); +bool IsOptionEnabled(PCWSTR name); +HRESULT MddBootstrapInitialize_Log( + HRESULT hrInitialize, + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion) noexcept; +HRESULT MddBootstrapInitialize_ShowUI_OnNoMatch( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion); static std::mutex g_initializationLock; static std::atomic g_initializationCount{}; @@ -74,11 +88,76 @@ static std::wstring g_test_ddlmPackagePublisherId; STDAPI MddBootstrapInitialize( UINT32 majorMinorVersion, PCWSTR versionTag, - PACKAGE_VERSION minVersion) noexcept try + PACKAGE_VERSION minVersion) noexcept { - // Dynamic Dependencies Bootstrap API requires a non-packaged process - LOG_HR_IF(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), AppModel::Identity::IsPackagedProcess()); + return MddBootstrapInitialize2(majorMinorVersion, versionTag, minVersion, MddBootstrapInitializeOptions_None); +} + +STDAPI MddBootstrapInitialize2( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion, + MddBootstrapInitializeOptions options) noexcept try +{ + // Dynamic Dependencies Bootstrap API requires an unpackaged process? + HRESULT hr{}; + if (AppModel::Identity::IsPackagedProcess()) + { + if (WI_IsFlagSet(options, MddBootstrapInitializeOptions_OnPackageIdentity_NOOP)) + { + // The process has package identity but that's OK. Do nothing + return S_OK; + } + hr = LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "MddBootstrapInitialize called in a process with package identity"); + } + else + { + hr = _MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion); + } + if (FAILED(hr)) + { + LOG_IF_FAILED(MddBootstrapInitialize_Log(hr, majorMinorVersion, versionTag, minVersion)); + + // NOTE: IsDebuggerPresent()=TRUE if running under a debugger context. + // IsDebuggerPresent()=FALSE if not running under a debugger context, even if AEDebug is set. + if (WI_IsFlagSet(options, MddBootstrapInitializeOptions_OnError_DebugBreak) || + (WI_IsFlagSet(options, MddBootstrapInitializeOptions_OnError_DebugBreak_IfDebuggerAttached) && IsDebuggerPresent()) || + IsOptionEnabled(L"MICROSOFT_WINDOWSAPPRUNTIME_BOOTSTRAP_INITIALIZE_DEBUGBREAK")) + { + DebugBreak(); + } + if (hr == HRESULT_FROM_WIN32(ERROR_NO_MATCH)) + { + if (WI_IsFlagSet(options, MddBootstrapInitializeOptions_OnNoMatch_ShowUI) || + IsOptionEnabled(L"MICROSOFT_WINDOWSAPPRUNTIME_BOOTSTRAP_INITIALIZE_SHOWUI")) + { + LOG_IF_FAILED(MddBootstrapInitialize_ShowUI_OnNoMatch(majorMinorVersion, versionTag, minVersion)); + } + } + + if (WI_IsFlagSet(options, MddBootstrapInitializeOptions_OnError_FailFast) || + IsOptionEnabled(L"MICROSOFT_WINDOWSAPPRUNTIME_BOOTSTRAP_INITIALIZE_FAILFAST")) + { + FAIL_FAST_HR_MSG(hr, + "Bootstrap initialize(0x%08X, '%ls', %hu.%hu.%hu.%hu)", + majorMinorVersion, (!versionTag ? L"" : versionTag), + minVersion.Major, minVersion.Minor, minVersion.Build, minVersion.Revision); + } + RETURN_HR(hr); + } + + // Success! + ++g_initializationCount; + return S_OK; +} +CATCH_RETURN(); + +HRESULT _MddBootstrapInitialize( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion) noexcept try +{ // Are we already initialized? auto lock{ std::lock_guard(g_initializationLock) }; if (g_initializationCount > 0) @@ -91,9 +170,6 @@ STDAPI MddBootstrapInitialize( // First to the key! Do the initialization FirstTimeInitialization(majorMinorVersion, versionTag, minVersion); } - - // Success! - ++g_initializationCount; return S_OK; } CATCH_RETURN(); @@ -815,3 +891,126 @@ CLSID GetClsid(const winrt::Windows::ApplicationModel::AppExtensions::AppExtensi THROW_IF_WIN32_ERROR(UuidFromStringW(textRpcString, &clsid)); return clsid; } + +bool IsOptionEnabled(PCWSTR name) +{ + WCHAR value[1 + 1]{}; + if (GetEnvironmentVariableW(name, value, ARRAYSIZE(value)) == 1) + { + if (*value == L'0') + { + return false; + } + else if (*value == L'1') + { + return true; + } + } + return false; +} + +HRESULT MddBootstrapInitialize_Log( + HRESULT hrInitialize, + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion) noexcept try +{ + HANDLE hEventLog{ RegisterEventSourceW(nullptr, L"Windows App Runtime") }; + RETURN_LAST_ERROR_IF_NULL(hEventLog); + + const DWORD c_eventId{ static_cast(hrInitialize) }; + PCWSTR message1{ L"Windows App Runtime" }; + WCHAR message2[1024]{}; + PCWSTR message2Format{ L"ERROR 0x%08X: Bootstrapper initialization failed while looking for version %hu.%hu%s (MSIX package version >= %hu.%hu.%hu.%hu)" }; + const UINT16 majorVersion{ HIWORD(majorMinorVersion) }; + const UINT16 minorVersion{ LOWORD(majorMinorVersion) }; + WCHAR formattedVersionTag[64]{}; + if (versionTag && (versionTag[0] != L'\0')) + { + FAIL_FAST_IF_FAILED(StringCchPrintfW(formattedVersionTag, ARRAYSIZE(formattedVersionTag), L"-%s", versionTag)); + } + FAIL_FAST_IF_FAILED(StringCchPrintfW(message2, ARRAYSIZE(message2), message2Format, + hrInitialize, majorVersion, minorVersion, formattedVersionTag, + minVersion.Major, minVersion.Minor, minVersion.Build, minVersion.Revision)); + PCWSTR strings[2]{ message1, message2 }; + LOG_IF_WIN32_BOOL_FALSE(ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, 0, c_eventId, nullptr, ARRAYSIZE(strings), 0, strings, nullptr)); + + DeregisterEventSource(hEventLog); + + return S_OK; +} +CATCH_RETURN() + +HRESULT MddBootstrapInitialize_ShowUI_OnNoMatch( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion) +{ + // Get the message caption + PCWSTR caption{}; + wil::unique_cotaskmem_string captionString; + WCHAR captionOnError[100]{}; + try + { + PCWSTR executable{}; + wil::unique_cotaskmem_string module; + auto hr{ LOG_IF_FAILED(wil::GetModuleFileNameW(nullptr, module)) }; + if (SUCCEEDED(hr)) + { + auto delimiter{ wcsrchr(module.get(), L'\\') }; + if (delimiter) + { + executable = delimiter + 1; + } + else + { + executable = module.get(); + } + PCWSTR captionSuffix{ L"This application could not be started" }; + captionString = wil::str_printf(L"%s - %s", executable, captionSuffix); + caption = captionString.get(); + } + } + catch (...) + { + } + if (!caption) + { + LOG_IF_FAILED(StringCchPrintfW(captionOnError, ARRAYSIZE(captionOnError), + L" - This application could not be started", + GetCurrentProcessId())); + caption = captionOnError; + } + + // Get the message body + WCHAR text[1024]{}; + PCWSTR textFormat{ L"This application requires the Windows App Runtime\n" + L" Version %hu.%hu%s\n" + L" (MSIX package version >= %hu.%hu.%hu.%hu)\n" + L"\n" + L"Do you want to install a compatible Windows App Runtime now?" + }; + const UINT16 majorVersion{ HIWORD(majorMinorVersion) }; + const UINT16 minorVersion{ LOWORD(majorMinorVersion) }; + WCHAR formattedVersionTag[64]{}; + if (versionTag && (versionTag[0] != L'\0')) + { + FAIL_FAST_IF_FAILED(StringCchPrintfW(formattedVersionTag, ARRAYSIZE(formattedVersionTag), L"-%s", versionTag)); + } + FAIL_FAST_IF_FAILED(StringCchPrintfW(text, ARRAYSIZE(text), textFormat, + majorVersion, minorVersion, formattedVersionTag, + minVersion.Major, minVersion.Minor, minVersion.Build, minVersion.Revision)); + + // Show the prompt + const auto yesno{ MessageBoxW(nullptr, text, caption, MB_YESNO | MB_ICONERROR) }; + if (yesno == IDYES) + { + SHELLEXECUTEINFOW sei{}; + sei.cbSize = sizeof(sei); + sei.lpVerb = L"open"; + sei.lpFile = L"https://docs.microsoft.com/windows/apps/windows-app-sdk/downloads"; + sei.nShow = SW_SHOWNORMAL; + LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&sei)); + } + return S_OK; +} diff --git a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.h b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.h index ee7f38b461..9581bc4a88 100644 --- a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.h +++ b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrap.h @@ -6,6 +6,31 @@ #include +/// Options for Bootstrap initialization +typedef enum MddBootstrapInitializeOptions +{ + /// Default behavior + MddBootstrapInitializeOptions_None = 0, + + /// If not successful call DebugBreak() + MddBootstrapInitializeOptions_OnError_DebugBreak = 0x0001, + + /// If not successful call DebugBreak() if a debugger is attached to the process + MddBootstrapInitializeOptions_OnError_DebugBreak_IfDebuggerAttached = 0x0002, + + /// If not successful perform a fail-fast + MddBootstrapInitializeOptions_OnError_FailFast = 0x0004, + + /// If a compatible Windows App Runtime framework package is not found show UI + MddBootstrapInitializeOptions_OnNoMatch_ShowUI = 0x0008, + + /// Do nothing (do not error) if the process has package identity + MddBootstrapInitializeOptions_OnPackageIdentity_NOOP = 0x0010, +} MddBootstrapInitializeOptions; +#if defined(__cplusplus) +DEFINE_ENUM_FLAG_OPERATORS(MddBootstrapInitializeOptions) +#endif // defined(__cplusplus) + /// Initialize the calling process to use Windows App Runtime framework package. /// /// Find a Windows App Runtime framework package meeting the criteria and make it available @@ -25,9 +50,29 @@ STDAPI MddBootstrapInitialize( PCWSTR versionTag, PACKAGE_VERSION minVersion) noexcept; +/// Initialize the calling process to use Windows App Runtime framework package. +/// +/// Find a Windows App Runtime framework package meeting the criteria and make it available +/// for use by the current process. If multiple packages meet the criteria the best +/// candidate is selected. +/// +/// If called multiple times the parameters must be compatible with the framework package +/// resolved by the first initialization call (i.e. the framework package currently in use). +/// If the request is not compatible with the framework package currently in use +/// the API fails and an error is returned. +/// +/// @param majorMinorVersion the major and minor version to use, e..g 0x00010002 for Major.Minor=1.2 +/// @param versionTag the version pre-release identifier, or NULL if none. +/// @param minVersion the minimum version to use +STDAPI MddBootstrapInitialize2( + UINT32 majorMinorVersion, + PCWSTR versionTag, + PACKAGE_VERSION minVersion, + MddBootstrapInitializeOptions options) noexcept; + /// Undo the changes made by MddBoostrapInitialize(). /// -/// @warning Packages made available via MddBootstrapInitialize() and +/// @warning Packages made available via MddBootstrapInitialize2() and /// the Dynamic Dependencies API should not be used after this call. STDAPI_(void) MddBootstrapShutdown() noexcept; @@ -85,7 +130,6 @@ class PackageVersion : public PACKAGE_VERSION #endif }; -#if defined(WINDOWSAPPSDK_RELEASE_MAJORMINOR) && defined(WINDOWSAPPSDK_RELEASE_VERSION_TAG_W) && defined(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) namespace DynamicDependency::Bootstrap { // Automate Boostrap shutdown when leaving scope @@ -103,7 +147,33 @@ namespace DynamicDependency::Bootstrap } using unique_mddbootstrapshutdown = std::unique_ptr; - /// Call MddBootstrapInitialize and aborts the process (via std::abort()) if it fails; + /// Options for Bootstrap initialization APIs. + /// @see InitializeFailFast(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + /// @see Initialize(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + /// @see InitializeNoThrow(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + enum class InitializeOptions + { + /// Default behavior + None = MddBootstrapInitializeOptions_None, + + /// If not successful call DebugBreak() + OnError_DebugBreak = MddBootstrapInitializeOptions_OnError_DebugBreak, + + /// If not successful call DebugBreak() if a debugger is attached to the process + OnError_DebugBreak_IfDebuggerAttached = MddBootstrapInitializeOptions_OnError_DebugBreak_IfDebuggerAttached, + + /// If not successful perform a fail-fast + OnError_FailFast = MddBootstrapInitializeOptions_OnError_FailFast, + + /// If a compatible Windows App Runtime framework package is not found show UI + OnNoMatch_ShowUI = MddBootstrapInitializeOptions_OnNoMatch_ShowUI, + + /// Do nothing (do not error) if the process has package identity + OnPackageIdentity_NOOP = MddBootstrapInitializeOptions_OnPackageIdentity_NOOP, + }; + DEFINE_ENUM_FLAG_OPERATORS(InitializeOptions) + + /// Call MddBootstrapInitialize2() and aborts the process (via std::abort()) if it fails; /// returns an RAII object that reverts the initialization on success. /// /// Initialize the calling process to use Windows App SDK's framework package. @@ -115,8 +185,9 @@ namespace DynamicDependency::Bootstrap /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @param minVersion the minimum version to use - /// @see Initialize(uint32_t, PCWSTR, PackageVersion) - /// @see InitializeNoThrow(uint32_t, PCWSTR, PackageVersion) + /// @param options optional behavior + /// @see Initialize(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + /// @see InitializeNoThrow(uint32_t, PCWSTR, PackageVersion, InitializeOptions) /// @see Shutdown() /// ~~~~~ /// #include @@ -138,9 +209,10 @@ namespace DynamicDependency::Bootstrap [[nodiscard]] inline unique_mddbootstrapshutdown InitializeFailFast( uint32_t majorMinorVersion = WINDOWSAPPSDK_RELEASE_MAJORMINOR, PCWSTR versionTag = WINDOWSAPPSDK_RELEASE_VERSION_TAG_W, - PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) + PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64, + InitializeOptions options = ::Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::InitializeOptions::None) { - const auto hr{ ::MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion) }; + const auto hr{ ::MddBootstrapInitialize2(majorMinorVersion, versionTag, minVersion, static_cast(options)) }; if (FAILED(hr)) { std::abort(); @@ -149,7 +221,7 @@ namespace DynamicDependency::Bootstrap } #if defined(_CPPUNWIND) && defined(WINRT_BASE_H) - /// Call MddBootstrapInitialize and throws an exception if it fails; + /// Call MddBootstrapInitialize2() and throws an exception if it fails; /// returns an RAII object that reverts the initialization on success. /// /// Initialize the calling process to use Windows App SDK's framework package. @@ -161,8 +233,9 @@ namespace DynamicDependency::Bootstrap /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @param minVersion the minimum version to use - /// @see Initialize_failfast(uint32_t, PCWSTR, PackageVersion) - /// @see Initialize_nothrow(uint32_t, PCWSTR, PackageVersion) + /// @param options optional behavior + /// @see Initialize_failfast(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + /// @see Initialize_nothrow(uint32_t, PCWSTR, PackageVersion, InitializeOptions) /// @see Shutdown() /// @exception winrt::hresult_error thrown if intialization fails; see code() for more details. /// ~~~~~ @@ -196,14 +269,15 @@ namespace DynamicDependency::Bootstrap [[nodiscard]] inline unique_mddbootstrapshutdown Initialize( uint32_t majorMinorVersion = WINDOWSAPPSDK_RELEASE_MAJORMINOR, PCWSTR versionTag = WINDOWSAPPSDK_RELEASE_VERSION_TAG_W, - PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) + PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64, + InitializeOptions options = ::Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::InitializeOptions::None) { - winrt::check_hresult(::MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion)); + winrt::check_hresult(::MddBootstrapInitialize2(majorMinorVersion, versionTag, minVersion, static_cast(options))); return unique_mddbootstrapshutdown(reinterpret_cast(1)); } #endif // defined(_CPPUNWIND) && defined(WINRT_BASE_H) - /// Call MddBootstrapInitialize and returns a failure HRESULT if it fails. + /// Call MddBootstrapInitialize2() and returns a failure HRESULT if it fails. /// /// Initialize the calling process to use Windows App SDK's framework package. /// @@ -214,8 +288,9 @@ namespace DynamicDependency::Bootstrap /// @param majorMinorVersion major and minor version of Windows App SDK's framework package, encoded as `0xMMMMNNNN` where M=Major, N=Minor (e.g. 1.2 == 0x00010002). /// @param versionTag version tag (if any), e.g. "preview1". /// @param minVersion the minimum version to use - /// @see InitializeFailFast(uint32_t, PCWSTR, PackageVersion) - /// @see Initialize(uint32_t, PCWSTR, PackageVersion) + /// @param options optional behavior + /// @see InitializeFailFast(uint32_t, PCWSTR, PackageVersion, InitializeOptions) + /// @see Initialize(uint32_t, PCWSTR, PackageVersion, InitializeOptions) /// @see Shutdown() /// ~~~~~ /// #include @@ -243,14 +318,14 @@ namespace DynamicDependency::Bootstrap inline HRESULT InitializeNoThrow( uint32_t majorMinorVersion = WINDOWSAPPSDK_RELEASE_MAJORMINOR, PCWSTR versionTag = WINDOWSAPPSDK_RELEASE_VERSION_TAG_W, - PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) + PackageVersion minVersion = WINDOWSAPPSDK_RUNTIME_VERSION_UINT64, + InitializeOptions options = ::Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap::InitializeOptions::None) { - return ::MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion); + return ::MddBootstrapInitialize2(majorMinorVersion, versionTag, minVersion, static_cast(options)); } } -#endif // defined(WINDOWSAPPSDK_RELEASE_MAJORMINOR) && defined(WINDOWSAPPSDK_RELEASE_VERSION_TAG_W) && defined(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) } -#endif // defined(WINDOWSAPPSDK_RELEASE_MAJORMINOR) && defined(WINDOWSAPPSDK_RELEASE_VERSION_TAG_W) && defined()WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) +#endif // defined(WINDOWSAPPSDK_RELEASE_MAJORMINOR) && defined(WINDOWSAPPSDK_RELEASE_VERSION_TAG_W) && defined(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64) #endif // defined(__cplusplus) #endif // MDDBOOTSTRAP_H diff --git a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cpp b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cpp index 305f31b2e1..3f70659786 100644 --- a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cpp +++ b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cpp @@ -7,6 +7,18 @@ #include #include +// If any options are defined use them, else use the default +#if !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP) +// No options specified! Use the default +#define MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT +#endif + namespace Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap { struct AutoInitialize @@ -21,12 +33,42 @@ namespace Microsoft::Windows::ApplicationModel::DynamicDependency::Bootstrap ::MddBootstrapShutdown(); } + constexpr static MddBootstrapInitializeOptions Options() + { +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT) + // Use the default options + return MddBootstrapInitializeOptions_OnNoMatch_ShowUI; +#elif defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE) + // No options! + return MddBootstrapInitializeOptions_None; +#else + // Use the specified options + return MddBootstrapInitializeOptions_None +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK) + | MddBootstrapInitializeOptions_OnError_DebugBreak +#endif +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED) + | MddBootstrapInitializeOptions_OnError_DebugBreak_IfDebuggerAttached +#endif +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST) + | MddBootstrapInitializeOptions_OnError_FailFast +#endif +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI) + | MddBootstrapInitializeOptions_OnNoMatch_ShowUI +#endif +#if defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP) + | MddBootstrapInitializeOptions_OnPackageIdentity_NOOP +#endif + ; + } + static void Initialize() { const UINT32 c_majorMinorVersion{ WINDOWSAPPSDK_RELEASE_MAJORMINOR }; PCWSTR c_versionTag{ WINDOWSAPPSDK_RELEASE_VERSION_TAG_W }; const PACKAGE_VERSION c_minVersion{ WINDOWSAPPSDK_RUNTIME_VERSION_UINT64 }; - const HRESULT hr{ ::MddBootstrapInitialize(c_majorMinorVersion, c_versionTag, c_minVersion) }; + const auto c_options{ Options() }; + const HRESULT hr{ ::MddBootstrapInitialize2(c_majorMinorVersion, c_versionTag, c_minVersion, c_options }; if (FAILED(hr)) { exit(hr); diff --git a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cs b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cs index ab20d5dd5b..66a27d4ada 100644 --- a/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cs +++ b/dev/WindowsAppRuntime_BootstrapDLL/MddBootstrapAutoInitializer.cs @@ -1,6 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. +// If any options are defined use them, else use the default +#if !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI) && \ + !defined(MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP) +// No options specified! Use the default +#define MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT +#endif + namespace Microsoft.Windows.ApplicationModel.DynamicDependency.BootstrapCS { class AutoInitialize @@ -11,13 +23,44 @@ internal static void AccessWindowsAppSDK() uint majorMinorVersion = global::Microsoft.WindowsAppSDK.Release.MajorMinor; string versionTag = global::Microsoft.WindowsAppSDK.Release.VersionTag; var minVersion = new PackageVersion(global::Microsoft.WindowsAppSDK.Runtime.Version.UInt64); - try + var options = Options; + int hresult = 0; + if (!global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.TryInitialize(majorMinorVersion, versionTag, minVersion, options, out hresult)) { - global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.Initialize(majorMinorVersion, versionTag, minVersion); + global::System.Environment.Exit(hr); } - catch (global::System.Exception e) + } + + internal static global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions Options + { + get { - global::System.Environment.FailFast(e.Message); +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_DEFAULT + // Use the default options + return global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnNoMatch_ShowUI; +#elif MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_NONE + // No options! + return global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.None; +#else + // Use the specified options + var options = global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.None; +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK + options |= global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnError_DebugBreak; +#endif +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_DEBUGBREAK_IFDEBUGGERATTACHED + options | global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnError_DebugBreak_IfDebuggerAttached; +#endif +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONERROR_FAILFAST + options | global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnError_FailFast; +#endif +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONNOMATCH_SHOWUI + options | global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnNoMatch_ShowUI; +#endif +#if MICROSOFT_WINDOWSAPPSDK_BOOTSTRAP_AUTO_INITIALIZE_OPTIONS_ONPACKAGEIDENTITY_NOOP + options | global::Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap.InitializeOptions.OnPackageIdentity_NOOP; +#endif + return options; +#endif } } } diff --git a/dev/WindowsAppRuntime_BootstrapDLL/WindowsAppRuntime.Bootstrap.def b/dev/WindowsAppRuntime_BootstrapDLL/WindowsAppRuntime.Bootstrap.def index 42e6425dab..bde4458d72 100644 --- a/dev/WindowsAppRuntime_BootstrapDLL/WindowsAppRuntime.Bootstrap.def +++ b/dev/WindowsAppRuntime_BootstrapDLL/WindowsAppRuntime.Bootstrap.def @@ -3,5 +3,6 @@ EXPORTS MddBootstrapInitialize + MddBootstrapInitialize2 MddBootstrapShutdown MddBootstrapTestInitialize diff --git a/test/DynamicDependency/Test_Win32/TestMddBootstrap.cpp b/test/DynamicDependency/Test_Win32/TestMddBootstrap.cpp index 5f5f9277db..36aa8ace87 100644 --- a/test/DynamicDependency/Test_Win32/TestMddBootstrap.cpp +++ b/test/DynamicDependency/Test_Win32/TestMddBootstrap.cpp @@ -372,4 +372,70 @@ namespace Test::DynamicDependency } #endif }; + + class BootstrapPackagedTests + { + public: + BEGIN_TEST_CLASS(BootstrapPackagedTests) + TEST_CLASS_PROPERTY(L"IsolationLevel", L"Method") + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + TEST_CLASS_PROPERTY(L"RunAs", L"UAP") + TEST_CLASS_PROPERTY(L"UAP:NoSplashScreen", L"true") + TEST_CLASS_PROPERTY(L"UAP:RuntimeBehavior", L"PackagedClassicApp") + TEST_CLASS_PROPERTY(L"UAP:TrustLevel", L"MediumIL") + END_TEST_CLASS() + + TEST_CLASS_SETUP(Setup) + { + return BootstrapFixtures::Setup(); + } + + TEST_CLASS_CLEANUP(Cleanup) + { + return BootstrapFixtures::Cleanup(); + } + + TEST_METHOD(Initialize_Packaged_NotSupported) + { + VERIFY_ARE_EQUAL(S_OK, MddBootstrapTestInitialize(Test::Packages::DynamicDependencyLifetimeManager::c_PackageNamePrefix, Test::Packages::DynamicDependencyLifetimeManager::c_PackagePublisherId)); + + // Major.Minor version, MinVersion=0 to find any framework package for this major.minor version + const UINT32 c_Version_MajorMinor{ Test::Packages::DynamicDependencyLifetimeManager::c_Version_MajorMinor }; + const PACKAGE_VERSION c_minVersion{}; + VERIFY_ARE_EQUAL(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), MddBootstrapInitialize(c_Version_MajorMinor, nullptr, c_minVersion)); + } + + TEST_METHOD(Initialize_Packaged_NOP) + { + VERIFY_ARE_EQUAL(S_OK, MddBootstrapTestInitialize(Test::Packages::DynamicDependencyLifetimeManager::c_PackageNamePrefix, Test::Packages::DynamicDependencyLifetimeManager::c_PackagePublisherId)); + + // Major.Minor version, MinVersion=0 to find any framework package for this major.minor version + const UINT32 c_Version_MajorMinor{ Test::Packages::DynamicDependencyLifetimeManager::c_Version_MajorMinor }; + const PACKAGE_VERSION c_minVersion{}; + const auto c_options{ MddBootstrapInitializeOptions_OnPackageIdentity_NOOP }; + VERIFY_ARE_EQUAL(S_OK, MddBootstrapInitialize2(c_Version_MajorMinor, nullptr, c_minVersion, c_options)); + + MddBootstrapShutdown(); + } + + TEST_METHOD(Initialize_Packaged_NOP_Multiple) + { + VERIFY_ARE_EQUAL(S_OK, MddBootstrapTestInitialize(Test::Packages::DynamicDependencyLifetimeManager::c_PackageNamePrefix, Test::Packages::DynamicDependencyLifetimeManager::c_PackagePublisherId)); + + // Major.Minor version, MinVersion=0 to find any framework package for this major.minor version + const UINT32 c_Version_MajorMinor{ Test::Packages::DynamicDependencyLifetimeManager::c_Version_MajorMinor }; + const PACKAGE_VERSION c_minVersion{}; + const auto c_options{ MddBootstrapInitializeOptions_OnPackageIdentity_NOOP }; + VERIFY_ARE_EQUAL(S_OK, MddBootstrapInitialize2(c_Version_MajorMinor, nullptr, c_minVersion, c_options)); + VERIFY_ARE_EQUAL(S_OK, MddBootstrapInitialize2(c_Version_MajorMinor, nullptr, c_minVersion, c_options)); + + MddBootstrapShutdown(); + MddBootstrapShutdown(); + + VERIFY_ARE_EQUAL(S_OK, MddBootstrapInitialize2(c_Version_MajorMinor, nullptr, c_minVersion, c_options)); + VERIFY_ARE_EQUAL(S_OK, MddBootstrapInitialize2(c_Version_MajorMinor, nullptr, c_minVersion, c_options)); + + MddBootstrapShutdown(); + } + }; } diff --git a/test/DynamicDependency/Test_Win32/TestMddBootstrapCppInitialize.cpp b/test/DynamicDependency/Test_Win32/TestMddBootstrapCppInitialize.cpp index b22b624ddd..c23025d953 100644 --- a/test/DynamicDependency/Test_Win32/TestMddBootstrapCppInitialize.cpp +++ b/test/DynamicDependency/Test_Win32/TestMddBootstrapCppInitialize.cpp @@ -31,23 +31,41 @@ HRESULT TestCompile() AM::PackageVersion pv7(0x0001000200030004ul); AM::PackageVersion pv8(0x0001000200030004ull); + B::InitializeOptions opt0{}; + B::InitializeOptions opt1{ B::InitializeOptions::None }; + B::InitializeOptions opt2{ B::InitializeOptions::OnError_DebugBreak | + B::InitializeOptions::OnError_DebugBreak_IfDebuggerAttached | + B::InitializeOptions::OnError_FailFast | + B::InitializeOptions::OnNoMatch_ShowUI | + B::InitializeOptions::OnPackageIdentity_NOOP + }; + auto f1 = B::InitializeFailFast(); auto f2 = B::InitializeFailFast(0x12345678); auto f3 = B::InitializeFailFast(0x12345678, L"versiontag"); auto f4 = B::InitializeFailFast(0x12345678, L"versiontag", AM::PackageVersion(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64)); auto f5 = B::InitializeFailFast(0x12345678, L"versiontag", pv0); + auto f6 = B::InitializeFailFast(0x12345678, L"versiontag", pv0, opt0); + auto f7 = B::InitializeFailFast(0x12345678, L"versiontag", pv0, opt1); + auto f8 = B::InitializeFailFast(0x12345678, L"versiontag", pv0, opt2); auto t1 = B::Initialize(); auto t2 = B::Initialize(0x12345678); auto t3 = B::Initialize(0x12345678, L"versiontag"); auto t4 = B::Initialize(0x12345678, L"versiontag", AM::PackageVersion(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64)); auto t5 = B::Initialize(0x12345678, L"versiontag", pv0); + auto t6 = B::Initialize(0x12345678, L"versiontag", pv0, opt0); + auto t7 = B::Initialize(0x12345678, L"versiontag", pv0, opt1); + auto t8 = B::Initialize(0x12345678, L"versiontag", pv0, opt2); const auto h1{ B::InitializeNoThrow() }; const auto h2{ B::InitializeNoThrow(0x12345678) }; const auto h3{ B::InitializeNoThrow(0x12345678, L"versiontag") }; const auto h4{ B::InitializeNoThrow(0x12345678, L"versiontag", AM::PackageVersion(WINDOWSAPPSDK_RUNTIME_VERSION_UINT64)) }; const auto h5{ B::InitializeNoThrow(0x12345678, L"versiontag", pv0) }; + const auto h6{ B::InitializeNoThrow(0x12345678, L"versiontag", pv0, opt0) }; + const auto h7{ B::InitializeNoThrow(0x12345678, L"versiontag", pv0, opt1) }; + const auto h8{ B::InitializeNoThrow(0x12345678, L"versiontag", pv0, opt2) }; return S_OK; }