522
return version;
523
}
524
525
+namespace {
526
+
527
+// Returns true if Windows Admin Protection (shadow admin) is enabled on
528
+// this system. The message is shown for both elevated and non-elevated
529
+// callers because either side may be missing the other's distributions.
530
+// Caches the DLL lookup on first call.
531
+bool IsAdminProtectionEnabled()
532
+{
533
+ using ShadowAdminEnabledFn = BOOL(WINAPI)();
534
+ static std::optional<LxssDynamicFunction<ShadowAdminEnabledFn>> s_fn;
535
+ static std::once_flag s_initFlag;
536
+
537
+ std::call_once(s_initFlag, []() {
538
+ LxssDynamicFunction<ShadowAdminEnabledFn> fn{DynamicFunctionErrorLogs::None};
539
+ if (SUCCEEDED(fn.load(L"SecurityHealthUdk.dll", "Shield_LUAIsShadowAdminEnabled")))
540
+ {
541
+ s_fn.emplace(std::move(fn));
542
+ }
543
+ });
544
+
545
+ return s_fn.has_value() && (*s_fn)();
546
+}
547
+
548
+} // anonymous namespace
549
+
550
std::wstring wsl::windows::common::wslutil::GetErrorString(HRESULT result)
551
{
552
ULONG buildNumber = 0;
553
std::wstring kbUrl;
554
+ std::wstring errorString;
555
556
switch (result)
557
{
571
return Localization::MessageHigherIntegrity();
572
573
case WSL_E_DEFAULT_DISTRO_NOT_FOUND:
548
- return Localization::MessageNoDefaultDistro();
574
+ errorString = Localization::MessageNoDefaultDistro();
575
+ break;
576
577
case HRESULT_FROM_WIN32(WSAECONNABORTED):
578
case HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS):
579
return Localization::MessageInstanceTerminated();
580
581
case WSL_E_DISTRO_NOT_FOUND:
555
- return Localization::MessageDistroNotFound();
582
+ errorString = Localization::MessageDistroNotFound();
583
+ break;
584
585
case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
586
return Localization::MessageDistroNameAlreadyExists();
723
}
724
}
725
698
- return GetSystemErrorString(result);
726
+ if (errorString.empty())
727
+ {
728
+ return GetSystemErrorString(result);
729
+ }
730
+
731
+ // If Admin Protection is enabled, prepend an informational message for
732
+ // errors that may be caused by the shadow admin's separate registry hive.
733
+ try
734
+ {
735
+ if (IsAdminProtectionEnabled())
736
+ {
737
+ auto message = Localization::MessageAdminProtectionEnabled();
738
+ message += L"\n\n";
739
+ message += errorString;
740
+ return message;
741
+ }
742
+ }
743
+ CATCH_LOG()
744
+
745
+ return errorString;
746
}
747
748
std::optional<std::pair<std::wstring, GitHubReleaseAsset>> wsl::windows::common::wslutil::GetGitHubAssetFromRelease(const GitHubRelease& Release)