diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln index fb2adede2a..d36b1388a6 100644 --- a/WindowsAppRuntime.sln +++ b/WindowsAppRuntime.sln @@ -690,6 +690,9 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Decimal", "Decimal", "{5012149E-F09F-4F18-A03C-FFE597203821}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Windows.Foundation.Projection", "dev\Projections\CS\Microsoft.Windows.Foundation\Microsoft.Windows.Foundation.Projection.csproj", "{8EBA8758-19D5-AE31-FD9C-86BBA3BFF6CA}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CPP", "CPP", "{7C0F3E70-BDB3-40B2-84E1-B1B77A80CB53}" EndProject diff --git a/dev/Interop/StoragePickers/PickerCommon.cpp b/dev/Interop/StoragePickers/PickerCommon.cpp index 3ba9effe05..35193f71e5 100644 --- a/dev/Interop/StoragePickers/PickerCommon.cpp +++ b/dev/Interop/StoragePickers/PickerCommon.cpp @@ -180,7 +180,7 @@ namespace PickerCommon { return; } - for (int i = 0; i < value.size(); i++) + for (size_t i = 0; i < value.size(); i++) { if (value[i] == L'\0') { @@ -203,7 +203,7 @@ namespace PickerCommon { PickerLocalization::GetStoragePickersLocalizationText(ImproperFileExtensionLocalizationKey)); } - for (int i = 1; i < filter.size(); i++) + for (size_t i = 1; i < filter.size(); i++) { if (filter[i] == L'.' || filter[i] == L'*' || filter[i] == L'?') { @@ -243,7 +243,7 @@ namespace PickerCommon { } // The method SHSimpleIDListFromPath does syntax check on the path string. - wil::unique_cotaskmem_ptr pidl(SHSimpleIDListFromPath(path.c_str())); + wil::unique_cotaskmem_ptr pidl{ SHSimpleIDListFromPath(path.c_str()) }; if (!pidl) { throw std::invalid_argument(propertyName); @@ -428,11 +428,11 @@ namespace PickerCommon { if (FileTypeFilterPara.size() > 0) { - check_hresult(dialog->SetFileTypes((UINT)FileTypeFilterPara.size(), FileTypeFilterPara.data())); + check_hresult(dialog->SetFileTypes(static_cast(FileTypeFilterPara.size()), FileTypeFilterPara.data())); if (FocusLastFilter) { - check_hresult(dialog->SetFileTypeIndex(FileTypeFilterPara.size())); + check_hresult(dialog->SetFileTypeIndex(static_cast(FileTypeFilterPara.size()))); } } } diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp b/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp index b288c7dc4f..3d05f55434 100644 --- a/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp +++ b/dev/PackageManager/API/M.W.M.D.PackageVolume.cpp @@ -5,19 +5,64 @@ #include "M.W.M.D.PackageVolume.h" #include "Microsoft.Windows.Management.Deployment.PackageVolume.g.cpp" +#include "M.W.M.D.PackageDeploymentResult.h" + +#include "PackageVolumeTelemetry.h" + #include namespace winrt::Microsoft::Windows::Management::Deployment::implementation { + bool PackageVolume::IsFeatureSupported(winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature feature) + { + switch (feature) + { + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::GetDefault: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::SetDefault: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::Add: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::Remove: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::SetOffline: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::SetOnline: + { + return true; + } + case winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature::GetAvailableSpace: + { + return true; + } + default: + { + std::ignore = LOG_HR_MSG(E_UNEXPECTED, "Feature:%d", static_cast(feature)); + return false; + } + } + } PackageVolume::PackageVolume(winrt::Windows::Management::Deployment::PackageVolume const& value) { + m_windowsPackageVolume = value; m_isSystemVolume = value.IsSystemVolume(); m_mountPoint = value.MountPoint(); m_name = value.Name(); m_packageStorePath = value.PackageStorePath(); m_supportsHardLinks = value.SupportsHardLinks(); - m_isFullTrustPackageSupported = value.IsFullTrustPackageSupported(); m_isAppxInstallSupported = value.IsAppxInstallSupported(); + m_isFullTrustPackageSupported = value.IsFullTrustPackageSupported(); + m_isOffline = value.IsOffline(); } winrt::Windows::Foundation::Collections::IVector PackageVolume::FindPackageVolumes() { @@ -32,7 +77,25 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation } return microsoftPackageVolumes; } - winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::FindPackageVolumeByPath(hstring const& path) + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::FindPackageVolumeByPath(hstring const& packageStorePath) + { + const auto c_volumePathNameMaxLength{ MAX_PATH }; + wchar_t volumePathName[c_volumePathNameMaxLength]{};//AKA volumeMountPoint + THROW_IF_WIN32_BOOL_FALSE_MSG(::GetVolumePathNameW(packageStorePath.c_str(), volumePathName, ARRAYSIZE(volumePathName)), "Path:%ls", packageStorePath.c_str()); + GUID mediaId{}; + const size_t c_volumeNameMaxLength{ 50 }; // "\\?\Volume{GUID}\" == 11 + 11111111-2222-3333-4444-555555555555 + 2 + null-terminator == 11 + 36 + 3 = 50 + wchar_t volumeName[c_volumeNameMaxLength]{}; + THROW_IF_WIN32_BOOL_FALSE_MSG(::GetVolumeNameForVolumeMountPoint(volumePathName, volumeName, ARRAYSIZE(volumeName)), "Path:%ls VolumePathName:%ls", packageStorePath.c_str(), volumePathName); + const auto volumeNameLength{ wcslen(volumeName) }; + THROW_HR_IF_MSG(E_UNEXPECTED, volumeNameLength == 0, "Path:%ls VolumePathName:%ls", packageStorePath.c_str(), volumePathName); + const auto offset{ volumeNameLength - 1 }; + if (volumeName[offset] == L'\\') + { + volumeName[offset] = L'\0'; + } + return FindPackageVolumeByName(winrt::hstring{ volumeName }); + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::GetPackageVolumeByPath(hstring const& path) { const auto c_volumePathNameMaxLength{ MAX_PATH }; wchar_t volumePathName[c_volumePathNameMaxLength]{};//AKA volumeMountPoint @@ -48,7 +111,7 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation { volumeName[offset] = L'\0'; } - return FindPackageVolumeByName(winrt::hstring{ volumeName }); + return GetPackageVolumeByName(winrt::hstring{ volumeName }); } winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::FindPackageVolumeByName(hstring const& name) { @@ -56,6 +119,47 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ packageManager.FindPackageVolume(name) }; return winrt::make(windowsPackageVolume); } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::GetPackageVolumeByName(hstring const& name) + { + try + { + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ packageManager.FindPackageVolume(name) }; + return winrt::make(windowsPackageVolume); + } + catch (winrt::hresult_error const& exception) + { + if (exception.code() != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + throw; + } + } + return winrt::Microsoft::Windows::Management::Deployment::PackageVolume(nullptr); + } + winrt::Microsoft::Windows::Management::Deployment::PackageVolume PackageVolume::GetDefault() + { + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ packageManager.GetDefaultPackageVolume() }; + return winrt::make(windowsPackageVolume); + } + winrt::Windows::Foundation::IAsyncOperation PackageVolume::AddAsync(hstring packageStorePath) + { + auto logTelemetry{ PackageVolumeTelemetry::Add::Start(packageStorePath) }; + + //auto strong{ get_strong() }; + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + logTelemetry.IgnoreCurrentThread(); + co_await resume_background(); // Allow to register the progress and complete handler + + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ co_await packageManager.AddPackageVolumeAsync(packageStorePath) }; + + logTelemetry.Stop(windowsPackageVolume.MountPoint(), windowsPackageVolume.Name(), windowsPackageVolume.PackageStorePath()); + co_return winrt::make(windowsPackageVolume); + } bool PackageVolume::IsSystemVolume() { return m_isSystemVolume; @@ -105,4 +209,312 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation auto msixPackageVolumeRepair{ ::ExportLoader::GetFunction(dll.get(), "MsixPackageVolumeRepair") }; THROW_IF_FAILED(msixPackageVolumeRepair(m_packageStorePath.c_str())); } + + bool PackageVolume::IsOffline() + { + return m_isOffline; + } + + void PackageVolume::SetDefault() + { + THROW_HR_IF_NULL(E_ILLEGAL_METHOD_CALL, m_windowsPackageVolume); + + winrt::Windows::Management::Deployment::PackageManager packageManager; + packageManager.SetDefaultPackageVolume(m_windowsPackageVolume); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageVolume::RemoveAsync() + { + THROW_HR_IF_NULL(E_ILLEGAL_METHOD_CALL, m_windowsPackageVolume); + + auto logTelemetry{ PackageVolumeTelemetry::Remove::Start(m_mountPoint, m_name, m_packageStorePath) }; + + auto strong{ get_strong() }; + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + logTelemetry.IgnoreCurrentThread(); + co_await resume_background(); // Allow to register the progress and complete handler + auto logTelemetryContinuation{ logTelemetry.ContinueOnCurrentThread() }; + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress{ + PackageDeploymentProgressStatus::Queued, 0} }; + progress(packageDeploymentProgress); + + HRESULT error{}; + HRESULT extendedError{}; + winrt::hstring errorText; + winrt::guid activityId{}; + try + { + error = LOG_IF_FAILED_MSG(Remove(packageDeploymentProgress, progress, extendedError, errorText, activityId), + "ExtendedError:0x%08X PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + catch (...) + { + const auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + error = LOG_HR_MSG(exception.code(), + "ExtendedError:0x%08X PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + if (FAILED(error)) + { + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, activityId, error, extendedError, errorText); + } + + logTelemetry.Stop(static_cast(S_OK)); + co_return winrt::make(PackageDeploymentStatus::CompletedSuccess, activityId); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageVolume::SetOfflineAsync() + { + THROW_HR_IF_NULL(E_ILLEGAL_METHOD_CALL, m_windowsPackageVolume); + + auto logTelemetry{ PackageVolumeTelemetry::SetOffline::Start(m_mountPoint, m_name, m_packageStorePath) }; + + auto strong{ get_strong() }; + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + logTelemetry.IgnoreCurrentThread(); + co_await resume_background(); // Allow to register the progress and complete handler + auto logTelemetryContinuation{ logTelemetry.ContinueOnCurrentThread() }; + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress{ + PackageDeploymentProgressStatus::Queued, 0} }; + progress(packageDeploymentProgress); + + HRESULT error{}; + HRESULT extendedError{}; + winrt::hstring errorText; + winrt::guid activityId{}; + try + { + error = LOG_IF_FAILED_MSG(SetOnline(false, packageDeploymentProgress, progress, extendedError, errorText, activityId), + "ExtendedError:0x%08X PackageVolume.SetOffline MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + catch (...) + { + const auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + error = LOG_HR_MSG(exception.code(), + "ExtendedError:0x%08X PackageVolume.SetOffline MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + if (FAILED(error)) + { + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, activityId, error, extendedError, errorText); + } + + logTelemetry.Stop(static_cast(S_OK)); + co_return winrt::make(PackageDeploymentStatus::CompletedSuccess, activityId); + } + + winrt::Windows::Foundation::IAsyncOperationWithProgress PackageVolume::SetOnlineAsync() + { + THROW_HR_IF_NULL(E_ILLEGAL_METHOD_CALL, m_windowsPackageVolume); + + auto logTelemetry{ PackageVolumeTelemetry::SetOnline::Start(m_mountPoint, m_name, m_packageStorePath) }; + + auto strong{ get_strong() }; + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + logTelemetry.IgnoreCurrentThread(); + co_await resume_background(); // Allow to register the progress and complete handler + auto logTelemetryContinuation{ logTelemetry.ContinueOnCurrentThread() }; + + auto progress{ co_await winrt::get_progress_token() }; + auto packageDeploymentProgress{ + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress{ + PackageDeploymentProgressStatus::Queued, 0} }; + progress(packageDeploymentProgress); + + HRESULT error{}; + HRESULT extendedError{}; + winrt::hstring errorText; + winrt::guid activityId{}; + try + { + error = LOG_IF_FAILED_MSG(SetOnline(true, packageDeploymentProgress, progress, extendedError, errorText, activityId), + "ExtendedError:0x%08X PackageVolume.SetOnline MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + catch (...) + { + const auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + error = LOG_HR_MSG(exception.code(), + "ExtendedError:0x%08X PackageVolume.SetOnline MountPoint:%ls Name:%ls PackageStorePath:%ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + if (FAILED(error)) + { + co_return winrt::make( + PackageDeploymentStatus::CompletedFailure, activityId, error, extendedError, errorText); + } + + logTelemetry.Stop(static_cast(S_OK)); + co_return winrt::make(PackageDeploymentStatus::CompletedSuccess, activityId); + } + + winrt::Windows::Foundation::IAsyncOperation PackageVolume::GetAvailableSpaceAsync() + { + THROW_HR_IF_NULL(E_ILLEGAL_METHOD_CALL, m_windowsPackageVolume); + + auto logTelemetry{ PackageVolumeTelemetry::GetAvailableSpace::Start(m_mountPoint, m_name, m_packageStorePath) }; + + auto strong{ get_strong() }; + + auto cancellation{ co_await winrt::get_cancellation_token() }; + cancellation.enable_propagation(true); + + uint64_t availableSpace{}; + availableSpace = co_await m_windowsPackageVolume.GetAvailableSpaceAsync(); + + logTelemetry.Stop(availableSpace); + co_return availableSpace; + } + + HRESULT PackageVolume::Remove( + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress& packageDeploymentProgress, + wistd::function progress, + HRESULT& extendedError, + winrt::hstring& errorText, + winrt::guid& activityId) + { + extendedError = S_OK; + errorText.clear(); + activityId = winrt::guid{}; + + winrt::Windows::Management::Deployment::PackageManager packageManager; + auto deploymentOperation{ packageManager.RemovePackageVolumeAsync(m_windowsPackageVolume) }; + deploymentOperation.Progress([&](winrt::Windows::Foundation::IAsyncOperationWithProgress< + winrt::Windows::Management::Deployment::DeploymentResult, + winrt::Windows::Management::Deployment::DeploymentProgress> const& /*sender*/, + winrt::Windows::Management::Deployment::DeploymentProgress const& progressInfo) + { + packageDeploymentProgress.Status = PackageDeploymentProgressStatus::InProgress; + packageDeploymentProgress.Progress = static_cast(progressInfo.percentage) / 100.0; + progress(packageDeploymentProgress); + }); + deploymentOperation.get(); + try + { + const auto deploymentResult{ deploymentOperation.GetResults() }; + const HRESULT error{ static_cast(deploymentOperation.ErrorCode()) }; + extendedError = deploymentResult.ExtendedErrorCode(); + errorText = deploymentResult.ErrorText(); + activityId = deploymentResult.ActivityId(); + const auto status{ deploymentOperation.Status() }; + if (status == winrt::Windows::Foundation::AsyncStatus::Error) + { + RETURN_IF_FAILED_MSG(error, + "ExtendedError:0x%08X PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + + // Status=Error but SUCCEEDED(error) == This.Should.Never.Happen. + FAIL_FAST_HR_MSG(E_UNEXPECTED, + "ExtendedError:0x%08X PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + else if (status == winrt::Windows::Foundation::AsyncStatus::Canceled) + { + RETURN_WIN32_MSG(ERROR_CANCELLED, + "PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls", + m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + FAIL_FAST_HR_IF_MSG(E_UNEXPECTED, status != winrt::Windows::Foundation::AsyncStatus::Completed, + "Status:%d PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + static_cast(status), m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + THROW_HR_MSG(exception.code(), + "ExtendedError:0x%08X PackageVolume.Remove MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + return S_OK; + } + + HRESULT PackageVolume::SetOnline( + const bool online, + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress& packageDeploymentProgress, + wistd::function progress, + HRESULT& extendedError, + winrt::hstring& errorText, + winrt::guid& activityId) + { + extendedError = S_OK; + errorText.clear(); + activityId = winrt::guid{}; + + winrt::Windows::Management::Deployment::PackageManager packageManager; + winrt::Windows::Foundation::IAsyncOperationWithProgress deploymentOperation; + if (online) + { + deploymentOperation = packageManager.SetPackageVolumeOnlineAsync(m_windowsPackageVolume); + } + else + { + deploymentOperation = packageManager.SetPackageVolumeOfflineAsync(m_windowsPackageVolume); + } + deploymentOperation.Progress([&](winrt::Windows::Foundation::IAsyncOperationWithProgress< + winrt::Windows::Management::Deployment::DeploymentResult, + winrt::Windows::Management::Deployment::DeploymentProgress> const& /*sender*/, + winrt::Windows::Management::Deployment::DeploymentProgress const& progressInfo) + { + packageDeploymentProgress.Status = PackageDeploymentProgressStatus::InProgress; + packageDeploymentProgress.Progress = static_cast(progressInfo.percentage) / 100.0; + progress(packageDeploymentProgress); + }); + deploymentOperation.get(); + try + { + const auto deploymentResult{ deploymentOperation.GetResults() }; + const HRESULT error{ static_cast(deploymentOperation.ErrorCode()) }; + extendedError = deploymentResult.ExtendedErrorCode(); + errorText = deploymentResult.ErrorText(); + activityId = deploymentResult.ActivityId(); + const auto status{ deploymentOperation.Status() }; + if (status == winrt::Windows::Foundation::AsyncStatus::Error) + { + RETURN_IF_FAILED_MSG(error, + "ExtendedError:0x%08X PackageVolume.Set%hs MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, online ? "Online" : "Offline", m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + + // Status=Error but SUCCEEDED(error) == This.Should.Never.Happen. + FAIL_FAST_HR_MSG(E_UNEXPECTED, + "ExtendedError:0x%08X PackageVolume.Set%hs MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, online ? "Online" : "Offline", m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + else if (status == winrt::Windows::Foundation::AsyncStatus::Canceled) + { + RETURN_WIN32_MSG(ERROR_CANCELLED, + "PackageVolume.Set%hs MountPoint:%ls Name:%ls PackageStorePath:%ls", + online ? "Online" : "Offline", m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str()); + } + FAIL_FAST_HR_IF_MSG(E_UNEXPECTED, status != winrt::Windows::Foundation::AsyncStatus::Completed, + "Status:%d PackageVolume.Set%hs MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + static_cast(status), online ? "Online" : "Offline", m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + catch (...) + { + auto exception{ hresult_error(to_hresult(), take_ownership_from_abi) }; + THROW_HR_MSG(exception.code(), + "ExtendedError:0x%08X PackageVolume.Set%hs MountPoint:%ls Name:%ls PackageStorePath:%ls : %ls", + extendedError, online ? "Online" : "Offline", m_mountPoint.c_str(), m_name.c_str(), m_packageStorePath.c_str(), errorText.c_str()); + } + return S_OK; + } } diff --git a/dev/PackageManager/API/M.W.M.D.PackageVolume.h b/dev/PackageManager/API/M.W.M.D.PackageVolume.h index 5d8ce07b6c..7a4ba6893e 100644 --- a/dev/PackageManager/API/M.W.M.D.PackageVolume.h +++ b/dev/PackageManager/API/M.W.M.D.PackageVolume.h @@ -9,31 +9,60 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation { struct PackageVolume : PackageVolumeT { - PackageVolume() = delete; + PackageVolume() = default; PackageVolume(winrt::Windows::Management::Deployment::PackageVolume const& value); + static bool IsFeatureSupported(winrt::Microsoft::Windows::Management::Deployment::PackageVolumeFeature feature); static winrt::Windows::Foundation::Collections::IVector FindPackageVolumes(); static winrt::Microsoft::Windows::Management::Deployment::PackageVolume FindPackageVolumeByPath(hstring const& packageStorePath); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume GetPackageVolumeByPath(hstring const& path); static winrt::Microsoft::Windows::Management::Deployment::PackageVolume FindPackageVolumeByName(hstring const& name); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume GetPackageVolumeByName(hstring const& name); + static winrt::Microsoft::Windows::Management::Deployment::PackageVolume GetDefault(); + static winrt::Windows::Foundation::IAsyncOperation AddAsync(hstring packageStorePath); bool IsSystemVolume(); hstring MountPoint(); hstring Name(); hstring PackageStorePath(); bool SupportsHardLinks(); - bool IsFullTrustPackageSupported(); bool IsAppxInstallSupported(); + bool IsFullTrustPackageSupported(); bool IsRepairNeeded(); void Repair(); + bool IsOffline(); + void SetDefault(); + winrt::Windows::Foundation::IAsyncOperationWithProgress RemoveAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress SetOfflineAsync(); + winrt::Windows::Foundation::IAsyncOperationWithProgress SetOnlineAsync(); + winrt::Windows::Foundation::IAsyncOperation GetAvailableSpaceAsync(); private: + HRESULT Remove( + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress& packageDeploymentProgress, + wistd::function progress, + HRESULT& extendedError, + winrt::hstring& errorText, + winrt::guid& activityId); + + HRESULT SetOnline( + const bool online, + winrt::Microsoft::Windows::Management::Deployment::PackageDeploymentProgress& packageDeploymentProgress, + wistd::function progress, + HRESULT& extendedError, + winrt::hstring& errorText, + winrt::guid& activityId); + + private: + winrt::Windows::Management::Deployment::PackageVolume m_windowsPackageVolume{ nullptr }; bool m_isSystemVolume{}; hstring m_mountPoint; hstring m_name; hstring m_packageStorePath; bool m_supportsHardLinks{}; - bool m_isFullTrustPackageSupported{}; bool m_isAppxInstallSupported{}; + bool m_isFullTrustPackageSupported{}; + bool m_isOffline{}; }; } namespace winrt::Microsoft::Windows::Management::Deployment::factory_implementation diff --git a/dev/PackageManager/API/PackageManager.idl b/dev/PackageManager/API/PackageManager.idl index 1a2a0e27b2..e1bd689dd5 100644 --- a/dev/PackageManager/API/PackageManager.idl +++ b/dev/PackageManager/API/PackageManager.idl @@ -7,7 +7,7 @@ import "M.AM.DynamicDependency.idl"; namespace Microsoft.Windows.Management.Deployment { - [contractversion(2)] + [contractversion(3)] apicontract PackageDeploymentContract{}; /// Features can be queried if currently available/enabled. @@ -23,6 +23,76 @@ namespace Microsoft.Windows.Management.Deployment ProvisionPackage_Framework = 6, }; + /// Features can be queried if currently available/enabled. + /// @see PackageVolume.IsFeatureSupported() + [contract(PackageDeploymentContract, 3)] + enum PackageVolumeFeature + { + GetDefault = 1, + SetDefault = 2, + Add = 3, + Remove = 4, + SetOffline = 5, + SetOnline = 6, + GetAvailableSpace = 7, + }; + + /// The progress status of the deployment request. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress.state + [contract(PackageDeploymentContract, 1)] + enum PackageDeploymentProgressStatus + { + Queued = 0, // The request is queued + InProgress = 1, // The request is in progress + CompletedSuccess = 2, // The request completed successfully + CompletedFailure = 3, // The request failed with some critical internal error. + }; + + /// Contains progress information for the deployment request. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress + [contract(PackageDeploymentContract, 1)] + struct PackageDeploymentProgress + { + PackageDeploymentProgressStatus Status; + + /// The progress percentage of the deployment request. + /// @note This is a double with values 0.0-1.0. Windows.Management.Deployment.DeploymentProgress.percentage is uint32 with values 0-100. + Double Progress; + }; + + /// The status of the deployment request. + /// @see PackageDeploymentResult.Status + [contract(PackageDeploymentContract, 1)] + enum PackageDeploymentStatus + { + InProgress = 0, // The request is in progress + CompletedSuccess = 1, // The request completed successfully + CompletedFailure = 2, // The request failed with some critical internal error. + }; + + /// Provides the result of a deployment request. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult + [contract(PackageDeploymentContract, 1)] + runtimeclass PackageDeploymentResult + { + PackageDeploymentStatus Status { get; }; + + /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. + HRESULT Error { get; }; + + /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.extendederrorcode + HRESULT ExtendedError { get; }; + + /// Gets extended error text for the error if the deployment operation is not successful. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.errortext + String ErrorText { get; }; + + /// Gets the activity identifier used to look up an event in Windows Event Viewer. Gets the activity identifier used to look up an event. All events of a deployment operation are logged with the same activityId. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.activityid + Guid ActivityId { get; }; + } + /// Represents a package storage volume. /// @note A volume 'name' is the volume's media ID (you can treat 'Volume Name' == 'Volume Media ID'). /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume @@ -37,40 +107,127 @@ namespace Microsoft.Windows.Management.Deployment static IVector FindPackageVolumes(); /// Get the specified volume. + /// @param packageStorePath a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\" + /// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid. + /// @note The packageStorePath parameter is used to identify the device Volume. + /// The actual path for packages in a PackageVolume is defined by Windows. + /// @return the volume or null if not found. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + /// @see GetPackageVolumeByPath() + /// + /// @note This API is deprecated and will be removed in a future release. + /// Use GetPackageVolumeByPath(). static PackageVolume FindPackageVolumeByPath(String packageStorePath); + /// Get the specified volume. + /// @param path a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\" + /// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid. + /// @note The path parameter is used to identify the device Volume. + /// The actual path for packages in a PackageVolume is defined by Windows. + /// @return the volume or null if not found. + /// @see GetPackageVolumeByName() + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetPackageVolumeByPath(String path); + /// Get the specified volume. /// @name The volume media ID (a GUID value) + /// @see GetPackageVolumeByName() /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + /// + /// @note This API is deprecated and will be removed in a future release. + /// Use GetPackageVolumeByName(). static PackageVolume FindPackageVolumeByName(String name); + /// Get the specified volume. + /// @name The volume media ID (a GUID value) + /// @see GetPackageVolumeByPath() + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetPackageVolumeByName(String name); + + /// Return true if the package volume is an internal system volume mapped to the %SYSTEMDRIVER% environment variable. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.issystemvolume Boolean IsSystemVolume{ get; }; + /// Get the path of the last known mount point for the package volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.mountpoint String MountPoint{ get; }; + /// Get the media ID of the package volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.name String Name{ get; }; + /// Get the absolute path for the Package store on the volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.packagestorepath String PackageStorePath{ get; }; + /// Return true if the package volume supports the creation of hard links in its file system. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.supportshardlinks Boolean SupportsHardLinks{ get; }; + /// Return true if APPX installing is supported. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isappxinstallsupported + Boolean IsAppxInstallSupported{ get; }; + + /// Return true if full-trust packages are supported. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isfulltrustpackagesupported Boolean IsFullTrustPackageSupported{ get; }; - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isappxinstallsupported - Boolean IsAppxInstallSupported{ get; }; + /// Return true if the package volume is in an offline state. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isoffline + [contract(PackageDeploymentContract, 3)] + Boolean IsOffline(); /// Return true if the package volume is damaged and needs to be repaired. Boolean IsRepairNeeded(); /// Repair the package volume (if necessary). void Repair(); + + [contract(PackageDeploymentContract, 3)] + static Boolean IsFeatureSupported(PackageVolumeFeature feature); + + /// Return the default package volume. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.getdefaultpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetDefault(); + + /// Set the default package volume. + /// @see //learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setdefaultpackagevolume + [contract(PackageDeploymentContract, 3)] + void SetDefault(); + + /// Create a new package volume. + /// @param packageStorePath The absolute path of the Package store. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.addpackagevolumeasync + [contract(PackageDeploymentContract, 3)] + static Windows.Foundation.IAsyncOperation AddAsync(String packageStorePath); + + /// @note The caller must be running with Medium IL (or higher) + /// OR running in an AppContainer with the packageManagement restricted capability + /// OR caller has package identity and the publisher matches the publisher of the volume being removed. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.removepackagevolumeasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress RemoveAsync(); + + /// Set the package volume to an offline state. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeofflineasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress SetOfflineAsync(); + + /// Set the package volume to an online state. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeonlineasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress SetOnlineAsync(); + + /// Get the available space (bytes). + /// @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagevolume.getavailablespaceasync?view=winrt-26100 + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperation GetAvailableSpaceAsync(); }; /// Defines the stub behavior for an app package that is being added or staged. @@ -93,62 +250,6 @@ namespace Microsoft.Windows.Management.Deployment NewerAvailable = 2, }; - /// The progress status of the deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress.state - [contract(PackageDeploymentContract, 1)] - enum PackageDeploymentProgressStatus - { - Queued = 0, // The request is queued - InProgress = 1, // The request is in progress - CompletedSuccess = 2, // The request completed successfully - CompletedFailure = 3, // The request failed with some critical internal error. - }; - - /// Contains progress information for the deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress - [contract(PackageDeploymentContract, 1)] - struct PackageDeploymentProgress - { - PackageDeploymentProgressStatus Status; - - /// The progress percentage of the deployment request. - /// @note This is a double with values 0.0-1.0. Windows.Management.Deployment.DeploymentProgress.percentage is uint32 with values 0-100. - Double Progress; - }; - - /// The status of the deployment request. - /// @see PackageDeploymentResult.Status - [contract(PackageDeploymentContract, 1)] - enum PackageDeploymentStatus - { - InProgress = 0, // The request is in progress - CompletedSuccess = 1, // The request completed successfully - CompletedFailure = 2, // The request failed with some critical internal error. - }; - - /// Provides the result of a deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult - [contract(PackageDeploymentContract, 1)] - runtimeclass PackageDeploymentResult - { - PackageDeploymentStatus Status { get; }; - - /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. - HRESULT Error { get; }; - - /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.extendederrorcode - HRESULT ExtendedError { get; }; - - /// Gets extended error text for the error if the deployment operation is not successful. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.errortext - String ErrorText { get; }; - - /// Gets the activity identifier used to look up an event in Windows Event Viewer. Gets the activity identifier used to look up an event. All events of a deployment operation are logged with the same activityId. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.activityid - Guid ActivityId { get; }; - } - [contract(PackageDeploymentContract, 1)] runtimeclass PackageSetItem { @@ -301,11 +402,12 @@ namespace Microsoft.Windows.Management.Deployment // IsReady // Return true if the package(s) are present and available for use - Boolean IsPackageReady(String package); + // Return true if the package(s) are present and available for use Boolean IsPackageReadyByUri(Windows.Foundation.Uri packageUri); + // Return true if the package(s) are present and available for use /// @note packageSet[Item].PackageUri is optional Boolean IsPackageSetReady(PackageSet packageSet); @@ -313,13 +415,14 @@ namespace Microsoft.Windows.Management.Deployment // IsReadyOrNewerAvailable // Return true if the package(s) are present and available for use - [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailable(String package); + // Return true if the package(s) are present and available for use [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailableByUri(Windows.Foundation.Uri packageUri); + // Return true if the package(s) are present and available for use /// @note packageSet[Item].PackageUri is optional [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageSetReadyOrNewerAvailable(PackageSet packageSet); @@ -431,13 +534,14 @@ namespace Microsoft.Windows.Management.Deployment // IsProvisioned // Return true if the package(s) are provisioned - [contract(PackageDeploymentContract, 2)] Boolean IsPackageProvisioned(String package); + // Return true if the package(s) are provisioned [contract(PackageDeploymentContract, 2)] Boolean IsPackageProvisionedByUri(Windows.Foundation.Uri packageUri); + // Return true if the package(s) are provisioned /// @note packageSet[Item].PackageUri is optional [contract(PackageDeploymentContract, 2)] Boolean IsPackageSetProvisioned(PackageSet packageSet); @@ -471,11 +575,11 @@ namespace Microsoft.Windows.Management.Deployment //------------------------------------------------------------- // IsRegistrationPending - /// @warning The parameter is should be "packageFullName" but can't due to http://task.ms/53280356. + /// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356. /// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name. Boolean IsPackageRegistrationPending(String packageFamilyName); - /// @warning The parameter is should be "packageFullName" but can't due to http://task.ms/53280356. + /// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356. /// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name. Boolean IsPackageRegistrationPendingForUser(String userSecurityId, String packageFamilyName); } diff --git a/dev/PackageManager/API/PackageManager.vcxitems.filters b/dev/PackageManager/API/PackageManager.vcxitems.filters index e41fd8b76e..b06d2bb016 100644 --- a/dev/PackageManager/API/PackageManager.vcxitems.filters +++ b/dev/PackageManager/API/PackageManager.vcxitems.filters @@ -110,4 +110,4 @@ - + \ No newline at end of file diff --git a/dev/PackageManager/API/PackageVolumeTelemetry.h b/dev/PackageManager/API/PackageVolumeTelemetry.h new file mode 100644 index 0000000000..f5388d0dff --- /dev/null +++ b/dev/PackageManager/API/PackageVolumeTelemetry.h @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT license. + +#pragma once + +#include + +#include "M.W.M.D.PackageDeploymentManager.h" + +DECLARE_TRACELOGGING_CLASS(PackageVolumeTelemetryProvider, + "Microsoft.WindowsAppSDK.Deployment.PackageVolumeTelemetry", + // {e1647c65-18e6-413d-8f81-28ab44c0f4f0} + (0xe1647c65, 0x18e6, 0x413d, 0x8f, 0x81, 0x28, 0xab, 0x44, 0xc0, 0xf4, 0xf0)); + +class PackageVolumeTelemetry : public wil::TraceLoggingProvider +{ + IMPLEMENT_TELEMETRY_CLASS(PackageVolumeTelemetry, PackageVolumeTelemetryProvider); + +public: + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(Add, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStart( + Add, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + DEFINE_ACTIVITY_STOP(winrt::hstring const& mountPoint, winrt::hstring const& name, winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStop( + Add, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(mountPoint.c_str(), "MountPoint"), + TraceLoggingWideString(name.c_str(), "Name"), + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(Remove, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(winrt::hstring const& mountPoint, winrt::hstring const& name, winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStart( + Remove, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(mountPoint.c_str(), "MountPoint"), + TraceLoggingWideString(name.c_str(), "Name"), + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + DEFINE_ACTIVITY_STOP() noexcept try + { + TraceLoggingClassWriteStop( + Remove, + _GENERIC_PARTB_FIELDS_ENABLED); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(SetOffline, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(winrt::hstring const& mountPoint, winrt::hstring const& name, winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStart( + SetOffline, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(mountPoint.c_str(), "MountPoint"), + TraceLoggingWideString(name.c_str(), "Name"), + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + DEFINE_ACTIVITY_STOP() noexcept try + { + TraceLoggingClassWriteStop( + SetOffline, + _GENERIC_PARTB_FIELDS_ENABLED); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(SetOnline, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(winrt::hstring const& mountPoint, winrt::hstring const& name, winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStart( + SetOnline, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(mountPoint.c_str(), "MountPoint"), + TraceLoggingWideString(name.c_str(), "Name"), + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + DEFINE_ACTIVITY_STOP() noexcept try + { + TraceLoggingClassWriteStop( + SetOnline, + _GENERIC_PARTB_FIELDS_ENABLED); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); + BEGIN_COMPLIANT_MEASURES_ACTIVITY_CLASS(GetAvailableSpace, PDT_ProductAndServicePerformance); + DEFINE_ACTIVITY_START(winrt::hstring const& mountPoint, winrt::hstring const& name, winrt::hstring const& packageStorePath) noexcept try + { + TraceLoggingClassWriteStart( + GetAvailableSpace, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingWideString(mountPoint.c_str(), "MountPoint"), + TraceLoggingWideString(name.c_str(), "Name"), + TraceLoggingWideString(packageStorePath.c_str(), "PackageStorePath")); + } + CATCH_LOG() + DEFINE_ACTIVITY_STOP(const uint64_t availableSpace) noexcept try + { + TraceLoggingClassWriteStop( + GetAvailableSpace, + _GENERIC_PARTB_FIELDS_ENABLED, + TraceLoggingUInt64(availableSpace, "AvailableSpace")); + } + CATCH_LOG() + END_ACTIVITY_CLASS(); +}; diff --git a/specs/packagemanager/PackageManagement.md b/specs/packagemanager/PackageManagement.md index b8e4cb541b..e689345b88 100644 --- a/specs/packagemanager/PackageManagement.md +++ b/specs/packagemanager/PackageManagement.md @@ -940,7 +940,7 @@ if (options.IsLimitToExistingPackagesSupported) ```c# (but really MIDL3) namespace Microsoft.Windows.Management.Deployment { - [contractversion(2)] + [contractversion(3)] apicontract PackageDeploymentContract{}; /// Represents a package storage volume. @@ -957,40 +957,127 @@ namespace Microsoft.Windows.Management.Deployment static IVector FindPackageVolumes(); /// Get the specified volume. + /// @param packageStorePath a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\" + /// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid. + /// @note The packageStorePath parameter is used to identify the device Volume. + /// The actual path for packages in a PackageVolume is defined by Windows. + /// @return the volume or null if not found. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + /// @see GetPackageVolumeByPath() + /// + /// @note This API is deprecated and will be removed in a future release. + /// Use GetPackageVolumeByPath(). static PackageVolume FindPackageVolumeByPath(String packageStorePath); + /// Get the specified volume. + /// @param path a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\" + /// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid. + /// @note The path parameter is used to identify the device Volume. + /// The actual path for packages in a PackageVolume is defined by Windows. + /// @return the volume or null if not found. + /// @see GetPackageVolumeByName() + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetPackageVolumeByPath(String path); + /// Get the specified volume. /// @name The volume media ID (a GUID value) + /// @see GetPackageVolumeByName() /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + /// + /// @note This API is deprecated and will be removed in a future release. + /// Use GetPackageVolumeByName(). static PackageVolume FindPackageVolumeByName(String name); + /// Get the specified volume. + /// @name The volume media ID (a GUID value) + /// @see GetPackageVolumeByPath() + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetPackageVolumeByName(String name); + + /// Return true if the package volume is an internal system volume mapped to the %SYSTEMDRIVER% environment variable. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.issystemvolume Boolean IsSystemVolume{ get; }; + /// Get the path of the last known mount point for the package volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.mountpoint String MountPoint{ get; }; + /// Get the media ID of the package volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.name String Name{ get; }; + /// Get the absolute path for the Package store on the volume. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.packagestorepath String PackageStorePath{ get; }; + /// Return true if the package volume supports the creation of hard links in its file system. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.supportshardlinks Boolean SupportsHardLinks{ get; }; + /// Return true if APPX installing is supported. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isappxinstallsupported + Boolean IsAppxInstallSupported{ get; }; + + /// Return true if full-trust packages are supported. /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isfulltrustpackagesupported Boolean IsFullTrustPackageSupported{ get; }; - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isappxinstallsupported - Boolean IsAppxInstallSupported{ get; }; + /// Return true if the package volume is in an offline state. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isoffline + [contract(PackageDeploymentContract, 3)] + Boolean IsOffline(); /// Return true if the package volume is damaged and needs to be repaired. Boolean IsRepairNeeded(); /// Repair the package volume (if necessary). void Repair(); + + [contract(PackageDeploymentContract, 3)] + static Boolean IsFeatureSupported(PackageVolumeFeature feature); + + /// Return the default package volume. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.getdefaultpackagevolume + [contract(PackageDeploymentContract, 3)] + static PackageVolume GetDefault(); + + /// Set the default package volume. + /// @see //learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setdefaultpackagevolume + [contract(PackageDeploymentContract, 3)] + void SetDefault(); + + /// Create a new package volume. + /// @param packageStorePath The absolute path of the Package store. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.addpackagevolumeasync + [contract(PackageDeploymentContract, 3)] + static Windows.Foundation.IAsyncOperation AddAsync(String packageStorePath); + + /// @note The caller must be running with Medium IL (or higher) + /// OR running in an AppContainer with the packageManagement restricted capability + /// OR caller has package identity and the publisher matches the publisher of the volume being removed. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.removepackagevolumeasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress RemoveAsync(); + + /// Set the package volume to an offline state. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeofflineasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress SetOfflineAsync(); + + /// Set the package volume to an online state. + /// @note This requires admin privilege. + /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeonlineasync + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperationWithProgress SetOnlineAsync(); + + /// Get the available space (bytes). + /// @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagevolume.getavailablespaceasync?view=winrt-26100 + [contract(PackageDeploymentContract, 3)] + Windows.Foundation.IAsyncOperation GetAvailableSpaceAsync(); }; /// Defines the stub behavior for an app package that is being added or staged. @@ -1050,62 +1137,6 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.TypedEventHandler Handler{ get; }; } - /// The progress status of the deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress.state - [contract(PackageDeploymentContract, 1)] - enum PackageDeploymentProgressStatus - { - Queued = 0, // The request is queued - InProgress = 1, // The request is in progress - CompletedSuccess = 2, // The request completed successfully - CompletedFailure = 3, // The request failed with some critical internal error. - }; - - /// Contains progress information for the deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentprogress - [contract(PackageDeploymentContract, 1)] - struct PackageDeploymentProgress - { - PackageDeploymentProgressStatus Status; - - /// The progress percentage of the deployment request. - /// @note This is a double with values 0.0-1.0. Windows.Management.Deployment.DeploymentProgress.percentage is uint32 with values 0-100. - Double Progress; - }; - - /// The status of the deployment request. - /// @see PackageDeploymentResult.Status - [contract(PackageDeploymentContract, 1)] - enum PackageDeploymentStatus - { - InProgress = 0, // The request is in progress - CompletedSuccess = 1, // The request completed successfully - CompletedFailure = 2, // The request failed with some critical internal error. - }; - - /// Provides the result of a deployment request. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult - [contract(PackageDeploymentContract, 1)] - runtimeclass PackageDeploymentResult - { - PackageDeploymentStatus Status { get; }; - - /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. - HRESULT Error { get; }; - - /// The extended error code can be used to distinguish a specific error condition which needs to be handled differently from the general error indicated by the return code. The extended error code may provide a more specific reason for the failure that caused the general error. Also, it usually corresponds directly to the specific message in the ErrorText. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.extendederrorcode - HRESULT ExtendedError { get; }; - - /// Gets extended error text for the error if the deployment operation is not successful. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.errortext - String ErrorText { get; }; - - /// Gets the activity identifier used to look up an event in Windows Event Viewer. Gets the activity identifier used to look up an event. All events of a deployment operation are logged with the same activityId. - /// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.deploymentresult.activityid - Guid ActivityId { get; }; - } - [contract(PackageDeploymentContract, 1)] runtimeclass PackageSetItem { @@ -1256,7 +1287,7 @@ namespace Microsoft.Windows.Management.Deployment AddPackageOptions AddPackageOptions { get; }; - [contractversion(2)] + [contract(PackageDeploymentContract, 2)] Boolean RegisterNewerIfAvailable; } @@ -1266,29 +1297,39 @@ namespace Microsoft.Windows.Management.Deployment // Get an instance of the manager static PackageDeploymentManager GetDefault(); + //------------------------------------------------------------- + // IsPackageDeploymentFeatureSupported + + [contract(PackageDeploymentContract, 2)] + static Boolean IsPackageDeploymentFeatureSupported(PackageDeploymentFeature feature); + //------------------------------------------------------------- // IsReady // Return true if the package(s) are present and available for use - Boolean IsPackageReady(String package); + // Return true if the package(s) are present and available for use Boolean IsPackageReadyByUri(Windows.Foundation.Uri packageUri); + // Return true if the package(s) are present and available for use + /// @note packageSet[Item].PackageUri is optional Boolean IsPackageSetReady(PackageSet packageSet); //------------------------------------------------------------- // IsReadyOrNewerAvailable // Return true if the package(s) are present and available for use - - [contractversion(2)] + [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailable(String package); - [contractversion(2)] + // Return true if the package(s) are present and available for use + [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailableByUri(Windows.Foundation.Uri packageUri); - [contractversion(2)] + // Return true if the package(s) are present and available for use + /// @note packageSet[Item].PackageUri is optional + [contract(PackageDeploymentContract, 2)] PackageReadyOrNewerAvailableStatus IsPackageSetReadyOrNewerAvailable(PackageSet packageSet); //------------------------------------------------------------- @@ -1306,6 +1347,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress EnsurePackageReadyByUriAsync(Windows.Foundation.Uri packageUri, EnsureReadyOptions options); + /// @note packageSet[Item].PackageUri is required Windows.Foundation.IAsyncOperationWithProgress EnsurePackageSetReadyAsync(PackageSet packageSet, EnsureReadyOptions options); @@ -1318,6 +1360,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress AddPackageByUriAsync(Windows.Foundation.Uri packageUri, AddPackageOptions options); + /// @note packageSet[Item].PackageUri is required Windows.Foundation.IAsyncOperationWithProgress AddPackageSetAsync(PackageSet packageSet, AddPackageOptions options); @@ -1330,6 +1373,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress StagePackageByUriAsync(Windows.Foundation.Uri packageUri, StagePackageOptions options); + /// @note packageSet[Item].PackageUri is required Windows.Foundation.IAsyncOperationWithProgress StagePackageSetAsync(PackageSet packageSet, StagePackageOptions options); @@ -1342,6 +1386,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress RegisterPackageByUriAsync(Windows.Foundation.Uri packageUri, RegisterPackageOptions options); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress RegisterPackageSetAsync(PackageSet packageSet, RegisterPackageOptions options); @@ -1360,6 +1405,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress RemovePackageByUriAsync(Windows.Foundation.Uri packageUri, RemovePackageOptions options); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress RemovePackageSetAsync(PackageSet packageSet, RemovePackageOptions options); @@ -1372,6 +1418,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress ResetPackageByUriAsync(Windows.Foundation.Uri packageUri); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress ResetPackageSetAsync(PackageSet packageSet); @@ -1384,6 +1431,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress RepairPackageByUriAsync(Windows.Foundation.Uri packageUri); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress RepairPackageSetAsync(PackageSet packageSet); @@ -1391,13 +1439,14 @@ namespace Microsoft.Windows.Management.Deployment // IsProvisioned // Return true if the package(s) are provisioned - [contract(PackageDeploymentContract, 2)] Boolean IsPackageProvisioned(String package); + // Return true if the package(s) are provisioned [contract(PackageDeploymentContract, 2)] Boolean IsPackageProvisionedByUri(Windows.Foundation.Uri packageUri); + // Return true if the package(s) are provisioned /// @note packageSet[Item].PackageUri is optional [contract(PackageDeploymentContract, 2)] Boolean IsPackageSetProvisioned(PackageSet packageSet); @@ -1411,6 +1460,7 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress ProvisionPackageByUriAsync(Windows.Foundation.Uri packageUri, ProvisionPackageOptions options); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress ProvisionPackageSetAsync(PackageSet packageSet, ProvisionPackageOptions options); @@ -1423,15 +1473,20 @@ namespace Microsoft.Windows.Management.Deployment Windows.Foundation.IAsyncOperationWithProgress DeprovisionPackageByUriAsync(Windows.Foundation.Uri packageUri); + /// @note packageSet[Item].PackageUri is optional Windows.Foundation.IAsyncOperationWithProgress DeprovisionPackageSetAsync(PackageSet packageSet); //------------------------------------------------------------- // IsRegistrationPending - Boolean IsPackageRegistrationPending(String packageFullName); + /// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356. + /// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name. + Boolean IsPackageRegistrationPending(String packageFamilyName); - Boolean IsPackageRegistrationPendingForUser(String userSecurityId, String packageFullName); + /// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356. + /// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name. + Boolean IsPackageRegistrationPendingForUser(String userSecurityId, String packageFamilyName); } [contract(PackageDeploymentContract, 1)] diff --git a/test/ABForward/FunctionalTests.cpp b/test/ABForward/FunctionalTests.cpp index b05d3d33cc..743f2b2e5c 100644 --- a/test/ABForward/FunctionalTests.cpp +++ b/test/ABForward/FunctionalTests.cpp @@ -50,7 +50,7 @@ namespace Test::ABForward public: FunctionalTests() = default; - + BEGIN_TEST_CLASS(FunctionalTests) TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") @@ -110,7 +110,7 @@ namespace Test::ABForward TEST_METHOD(BatteryStatus) { - auto batteryStatus{ winrt::Microsoft::Windows::System::Power::PowerManager::BatteryStatus() }; + [[maybe_unused]] const auto batteryStatus{ winrt::Microsoft::Windows::System::Power::PowerManager::BatteryStatus() }; } TEST_METHOD(DeploymentManager) diff --git a/test/DynamicDependency/Test_Win32/Test_Win32_Create_Add_Architectures_Explicit_NoMatch.cpp b/test/DynamicDependency/Test_Win32/Test_Win32_Create_Add_Architectures_Explicit_NoMatch.cpp index 5bd575bfb3..cd208c9ac5 100644 --- a/test/DynamicDependency/Test_Win32/Test_Win32_Create_Add_Architectures_Explicit_NoMatch.cpp +++ b/test/DynamicDependency/Test_Win32/Test_Win32_Create_Add_Architectures_Explicit_NoMatch.cpp @@ -55,6 +55,7 @@ void Test::DynamicDependency::Test_Win32::Create_Add_Architectures_Explicit_NoMa const HRESULT expectedHR{ STATEREPOSITORY_E_DEPENDENCY_NOT_RESOLVED }; wil::unique_process_heap_string packageFullName_FrameworkMathAdd; MDD_PACKAGEDEPENDENCY_CONTEXT packageDependencyContext_FrameworkMathAdd{ Mdd_Add(expectedHR, packageDependencyId_FrameworkMathAdd.get(), packageFullName_FrameworkMathAdd) }; + VERIFY_IS_NULL(packageDependencyContext_FrameworkMathAdd); VERIFY_IS_NULL(packageFullName_FrameworkMathAdd.get(), WEX::Common::String().Format(L"PackageFullName=%s Expected=not-", !packageFullName_FrameworkMathAdd ? L"" : packageFullName_FrameworkMathAdd.get())); VerifyPackageInPackageGraph(expectedPackageFullName_WindowsAppRuntimeFramework, S_OK); VerifyPackageNotInPackageGraph(expectedPackageFullName_FrameworkMathAdd, S_OK); diff --git a/test/PackageManager/API/PackageDeploymentManagerTests.cpp b/test/PackageManager/API/PackageDeploymentManagerTests.cpp index ffb44b1191..be6c0b2fee 100644 --- a/test/PackageManager/API/PackageDeploymentManagerTests.cpp +++ b/test/PackageManager/API/PackageDeploymentManagerTests.cpp @@ -72,3 +72,22 @@ void Test::PackageManager::Tests::VerifyDeploymentSucceeded( deploymentResult.Status(), deploymentResult.Error(), deploymentResult.ExtendedError(), deploymentResult.ErrorText().c_str(), message)); } + +void Test::PackageManager::Tests::VerifyDeploymentSucceeded( + const winrt::Windows::Management::Deployment::DeploymentResult& deploymentResult, + PCSTR filename, + int line, + PCSTR function) +{ + WEX::Common::String source; + source.Format(L"File: %hs, Function: %hs, Line: %d", filename, function, line); + PCWSTR message{ static_cast(source) }; + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"VERIFY Deployment Suceeded: %ls", message)); + + const bool ok{ (deploymentResult.ExtendedErrorCode() == S_OK) && + deploymentResult.ErrorText().empty() }; + VERIFY_IS_TRUE(ok, WEX::Common::String().Format(L"ExtendedError:0x%X ErrorText:%ls %ls", + deploymentResult.ExtendedErrorCode(), + deploymentResult.ErrorText().c_str(), message)); +} diff --git a/test/PackageManager/API/PackageDeploymentManagerTests.h b/test/PackageManager/API/PackageDeploymentManagerTests.h index bd74f63735..d513e06f19 100644 --- a/test/PackageManager/API/PackageDeploymentManagerTests.h +++ b/test/PackageManager/API/PackageDeploymentManagerTests.h @@ -105,6 +105,12 @@ namespace Test::PackageManager::Tests int line, PCSTR function); + void VerifyDeploymentSucceeded( + const winrt::Windows::Management::Deployment::DeploymentResult& deploymentResult, + PCSTR filename, + int line, + PCSTR function); + class PackageDeploymentManagerTests_Base { protected: @@ -153,11 +159,53 @@ namespace Test::PackageManager::Tests AsyncOperationProgressHandler progressCallback( [&](const IAsyncOperationWithProgress&, PackageDeploymentProgress progress) { - WEX::Logging::Log::Comment(WEX::Common::String().Format(L"...State:%d Percentage:%lf", static_cast(progress.Status), progress.Progress)); - if (progress.Progress != 0) + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"...Status:%d Progress:%lf", static_cast(progress.Status), progress.Progress)); + VERIFY_IS_LESS_THAN_OR_EQUAL(progress.Progress, 1.0); + VERIFY_IS_GREATER_THAN_OR_EQUAL(progress.Progress, 0.0); + if (progress.Progress >= 1.0) + { + VERIFY_IS_TRUE((progress.Status == PackageDeploymentProgressStatus::InProgress) || + (progress.Status == PackageDeploymentProgressStatus::CompletedSuccess) || + (progress.Status == PackageDeploymentProgressStatus::CompletedFailure)); + } + else if (progress.Progress > 0) { VERIFY_ARE_EQUAL(PackageDeploymentProgressStatus::InProgress, progress.Status); } + else if (progress.Progress == 0) + { + VERIFY_ARE_EQUAL(PackageDeploymentProgressStatus::Queued, progress.Status); + } + } + ); + deploymentOperation.Progress(progressCallback); + auto deploymentResult{ deploymentOperation.get() }; + return deploymentResult; + } + + winrt::Windows::Management::Deployment::DeploymentResult WaitForDeploymentOperation( + winrt::Windows::Foundation::IAsyncOperationWithProgress& deploymentOperation) + { + using namespace winrt::Windows::Foundation; + using namespace winrt::Windows::Management::Deployment; + AsyncOperationProgressHandler progressCallback( + [&](const IAsyncOperationWithProgress&, DeploymentProgress progress) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"...State:%d Percentage:%u", static_cast(progress.state), progress.percentage)); + VERIFY_IS_LESS_THAN_OR_EQUAL(progress.percentage, 100u); + VERIFY_IS_GREATER_THAN_OR_EQUAL(progress.percentage, 0u); + if (progress.percentage >= 100u) + { + VERIFY_IS_TRUE(progress.state == DeploymentProgressState::Processing); + } + else if (progress.percentage > 0u) + { + VERIFY_ARE_EQUAL(DeploymentProgressState::Processing, progress.state); + } + else if (progress.percentage == 0u) + { + VERIFY_ARE_EQUAL(DeploymentProgressState::Queued, progress.state); + } } ); deploymentOperation.Progress(progressCallback); diff --git a/test/PackageManager/API/PackageManagerTests.vcxproj b/test/PackageManager/API/PackageManagerTests.vcxproj index 96d55f4590..7137f9d59f 100644 --- a/test/PackageManager/API/PackageManagerTests.vcxproj +++ b/test/PackageManager/API/PackageManagerTests.vcxproj @@ -127,6 +127,7 @@ + diff --git a/test/PackageManager/API/PackageManagerTests.vcxproj.filters b/test/PackageManager/API/PackageManagerTests.vcxproj.filters index aa5b312029..813f4e643c 100644 --- a/test/PackageManager/API/PackageManagerTests.vcxproj.filters +++ b/test/PackageManager/API/PackageManagerTests.vcxproj.filters @@ -69,6 +69,9 @@ Source Files + + Source Files + diff --git a/test/PackageManager/API/PackageVolumeTests.cpp b/test/PackageManager/API/PackageVolumeTests.cpp new file mode 100644 index 0000000000..c08a099358 --- /dev/null +++ b/test/PackageManager/API/PackageVolumeTests.cpp @@ -0,0 +1,447 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include "pch.h" + +#include "PackageDeploymentManagerTests.h" + +#include + +namespace TD = ::Test::Diagnostics; +namespace TB = ::Test::Bootstrap; +namespace TP = ::Test::Packages; +namespace TPF = ::Test::Packages::Framework; +namespace TPM = ::Test::Packages::Main; +namespace TPMT = ::Test::PackageManager::Tests; + +namespace Test::PackageManager::Tests +{ + class PackageVolumeTests_Base : protected PackageDeploymentManagerTests_Base + { + protected: + const winrt::hstring& GetTempDirectory() const + { + return m_tempPath; + } + + bool VerifyTestVolume(PCWSTR drive) + { + VERIFY_IS_NOT_NULL(drive); + VERIFY_IS_TRUE(wcslen(drive) == 1, WEX::Common::String().Format(L"/p:PackageVolume.Drive=%s not valid", drive)); + VERIFY_IS_TRUE(CompareStringOrdinal(drive, -1, L"C", -1, TRUE) != CSTR_EQUAL, WEX::Common::String().Format(L"/p:PackageVolume.Drive=%s not valid (cannot be system drive)", drive)); + + m_tempPath = std::format(L"{}:\\WindowsApps", drive).c_str(); + + return VerifyTestVolume(); + } + + bool VerifyTestVolume() + { + if (m_tempPath.empty()) + { + return false; + } + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Path %sfound: %s", TempDirectoryExists() ? L"" : L"not ", m_tempPath.c_str())); + + winrt::Windows::Management::Deployment::PackageManager packageManager; + try + { + auto packageVolume{ packageManager.FindPackageVolume(m_tempPath) }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume found: %s", m_tempPath.c_str())); + + VERIFY_IS_FALSE(packageVolume.IsSystemVolume(), + WEX::Common::String().Format(L"Invalid test path (%s) - cannot be system drive)", m_tempPath.c_str())); + VERIFY_IS_TRUE(CompareStringOrdinal(packageVolume.PackageStorePath().c_str(), -1, m_tempPath.c_str(), -1, TRUE) == CSTR_EQUAL, + WEX::Common::String().Format(L"Invalid test path %s != PackageVolume.PackageStorePath %s", m_tempPath.c_str(), packageVolume.PackageStorePath().c_str())); + } + catch (winrt::hresult_error& e) + { + if (e.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume not found: %s", m_tempPath.c_str())); + return false; + } + else + { + std::ignore = LOG_HR_MSG(e.code(), + "PackageVolume.GetPackageVolumeByPath PackageStorePath:%ls : %ls", + m_tempPath.c_str(), e.message().c_str()); + throw; + } + } + catch (...) + { + const auto exception{ winrt::hresult_error(winrt::to_hresult(), winrt::take_ownership_from_abi) }; + if (exception.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume not found: %s", m_tempPath.c_str())); + return false; + } + else + { + std::ignore = LOG_HR_MSG(exception.code(), + "PackageVolume.FindPackageVolumeByPath PackageStorePath:%ls : %ls", + m_tempPath.c_str(), exception.message().c_str()); + throw; + } + } + + return true; + } + + bool BlockIfTestVolumeExists(PCWSTR drive) + { + const auto exists{ VerifyTestVolume(drive) }; + if (exists) + { + WEX::Logging::Log::Result(WEX::Logging::TestResults::Blocked, + WEX::Common::String().Format(L"Test PackageVolume exists (%s). Blocking tests", m_tempPath.c_str())); + } + return exists; + } + + bool TempDirectoryExists() const + { + return DirectoryExists(m_tempPath); + } + + bool DirectoryExists(const winrt::hstring& path) const + { + return !path.empty() && std::filesystem::is_directory(path.c_str()); + } + + protected: + void Dump( + const winrt::Microsoft::Windows::Management::Deployment::PackageVolume& packageVolume) const + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume: Microsoft\n" + L" MountPoint: %s\n" + L" Name: %s\n" + L" PackageStorePath: %s\n" + L" State:%s%s%s%s%s\n", + packageVolume.MountPoint().c_str(), + packageVolume.Name().c_str(), + packageVolume.PackageStorePath().c_str(), + packageVolume.IsSystemVolume() ? L" System" : L"", + packageVolume.IsOffline() ? L" Offline" : L" Online", + packageVolume.SupportsHardLinks() ? L" Hardlinks" : L"", + packageVolume.IsAppxInstallSupported() ? L" AppxInstall" : L"", + packageVolume.IsFullTrustPackageSupported() ? L" FullTrust" : L"")); + //TODO IsRepairNeeded + } + + void Dump( + const winrt::Windows::Management::Deployment::PackageVolume& packageVolume) const + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume: Windows\n" + L" MountPoint: %s\n" + L" Name: %s\n" + L" PackageStorePath: %s\n" + L" State:%s%s%s%s%s\n", + packageVolume.MountPoint().c_str(), + packageVolume.Name().c_str(), + packageVolume.PackageStorePath().c_str(), + packageVolume.IsSystemVolume() ? L" System" : L"", + packageVolume.IsOffline() ? L" Offline" : L" Online", + packageVolume.SupportsHardLinks() ? L" Hardlinks" : L"", + packageVolume.IsAppxInstallSupported() ? L" AppxInstall" : L"", + packageVolume.IsFullTrustPackageSupported() ? L" FullTrust" : L"")); + } + + winrt::Microsoft::Windows::Management::Deployment::PackageVolume Dump( + const winrt::hstring& path) const + { + auto packageVolume{ winrt::Microsoft::Windows::Management::Deployment::PackageVolume::GetPackageVolumeByPath(path) }; + Dump(packageVolume); + return packageVolume; + } + + protected: + void Verify( + const winrt::Microsoft::Windows::Management::Deployment::PackageVolume& packageVolume, + const winrt::Windows::Management::Deployment::PackageVolume& windowsPackageVolume) + { + VERIFY_ARE_EQUAL(packageVolume.IsSystemVolume(), windowsPackageVolume.IsSystemVolume()); + VERIFY_ARE_EQUAL(packageVolume.MountPoint(), windowsPackageVolume.MountPoint()); + VERIFY_ARE_EQUAL(packageVolume.Name(), windowsPackageVolume.Name()); + VERIFY_ARE_EQUAL(packageVolume.PackageStorePath(), windowsPackageVolume.PackageStorePath()); + VERIFY_ARE_EQUAL(packageVolume.SupportsHardLinks(), windowsPackageVolume.SupportsHardLinks()); + VERIFY_ARE_EQUAL(packageVolume.IsAppxInstallSupported(), windowsPackageVolume.IsAppxInstallSupported()); + VERIFY_ARE_EQUAL(packageVolume.IsFullTrustPackageSupported(), windowsPackageVolume.IsFullTrustPackageSupported()); + VERIFY_ARE_EQUAL(packageVolume.IsOffline(), windowsPackageVolume.IsOffline()); + } + + void Verify( + const winrt::Microsoft::Windows::Management::Deployment::PackageVolume& actual, + const winrt::Microsoft::Windows::Management::Deployment::PackageVolume& expected) + { + VERIFY_ARE_EQUAL(expected.IsSystemVolume(), actual.IsSystemVolume()); + VERIFY_ARE_EQUAL(expected.MountPoint(), actual.MountPoint()); + VERIFY_ARE_EQUAL(expected.Name(), actual.Name()); + VERIFY_ARE_EQUAL(expected.PackageStorePath(), actual.PackageStorePath()); + VERIFY_ARE_EQUAL(expected.SupportsHardLinks(), actual.SupportsHardLinks()); + VERIFY_ARE_EQUAL(expected.IsAppxInstallSupported(), actual.IsAppxInstallSupported()); + VERIFY_ARE_EQUAL(expected.IsFullTrustPackageSupported(), actual.IsFullTrustPackageSupported()); + VERIFY_ARE_EQUAL(expected.IsOffline(), actual.IsOffline()); + } + + protected: + bool RemovePackageVolumeIfNecessary() + { + if (m_tempPath.empty()) + { + WEX::Common::String drive; + if (!::Test::TAEF::TryGetOption(L"PackageVolume.Drive", drive)) + { + WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped, L"/p:PackageVolume.Drive= not specified. Skipping tests"); + return true; + } + const auto exists{ VerifyTestVolume(drive) }; + if (!exists) + { + return true; + } + } + + winrt::Windows::Management::Deployment::PackageManager packageManager; + try + { + auto packageVolume{ packageManager.FindPackageVolume(m_tempPath) }; + if (packageVolume) + { + VERIFY_IS_FALSE(packageVolume.IsSystemVolume(), + WEX::Common::String().Format(L"Invalid test path (%s) - cannot be system drive)", m_tempPath.c_str())); + VERIFY_IS_TRUE(CompareStringOrdinal(packageVolume.PackageStorePath().c_str(), -1, m_tempPath.c_str(), -1, TRUE) == CSTR_EQUAL, + WEX::Common::String().Format(L"Invalid test path %s != PackageVolume.PackageStorePath %s", m_tempPath.c_str(), packageVolume.PackageStorePath().c_str())); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"Removing PackageVolume %s", m_tempPath.c_str())); + auto deploymentOperation{ packageManager.RemovePackageVolumeAsync(packageVolume) }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + } + } + catch (winrt::hresult_error& e) + { + if (e.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume not found: %s", m_tempPath.c_str())); + } + else + { + std::ignore = LOG_HR_MSG(e.code(), + "PackageVolume.GetPackageVolumeByPath PackageStorePath:%ls : %ls", + m_tempPath.c_str(), e.message().c_str()); + throw; + } + } + catch (...) + { + const auto exception{ winrt::hresult_error(winrt::to_hresult(), winrt::take_ownership_from_abi) }; + if (exception.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume not found: %s", m_tempPath.c_str())); + } + else + { + std::ignore = LOG_HR_MSG(exception.code(), + "PackageVolume.FindPackageVolumeByPath PackageStorePath:%ls : %ls", + m_tempPath.c_str(), exception.message().c_str()); + throw; + } + } + + try + { + winrt::Windows::Management::Deployment::PackageVolume windowsPackageVolume{ packageManager.FindPackageVolume(m_tempPath) }; + } + catch (winrt::hresult_error const& e) + { + if (e.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageVolume not defined for %s", m_tempPath.c_str())); + } + else + { + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackageManager.FindPackageVolume(%ls) = 0x%08X", m_tempPath.c_str(), e.code())); + throw; + } + } + return true; + } + + protected: + winrt::hstring m_tempPath; + }; + + class PackageVolumeTests_Elevated : protected PackageVolumeTests_Base + { + public: + BEGIN_TEST_CLASS(PackageVolumeTests_Elevated) + TEST_METHOD_PROPERTY(L"RunAs", L"ElevatedUser") + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + ::TB::Setup(); + + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + const auto exists{ VerifyTestVolume() }; + + ::TB::Cleanup(); + return exists; + } + + public: + TEST_METHOD(GetDefault) + { + const auto packageVolume{ winrt::Microsoft::Windows::Management::Deployment::PackageVolume::GetDefault() }; + winrt::Windows::Management::Deployment::PackageManager packageManager; + const auto windowsPackageVolume{ packageManager.GetDefaultPackageVolume() }; + Verify(packageVolume, windowsPackageVolume); + } + + TEST_METHOD(GetAvailableSpace) + { + const auto packageVolume{ winrt::Microsoft::Windows::Management::Deployment::PackageVolume::GetDefault() }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"PackgeVolume.Default: MountPoint=%ls Name=%ls PackageStorePath=%ls", + packageVolume.MountPoint().c_str(), packageVolume.Name().c_str(), packageVolume.PackageStorePath().c_str())); + std::uint64_t availableSpace{ packageVolume.GetAvailableSpaceAsync().get() }; + std::uint64_t kb{ availableSpace / 1024 }; + std::uint64_t mb{ kb / 1024 }; + std::uint64_t gb{ mb / 1024 }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"AvailableSpace=%llu bytes / %lluKB / %lluMB / %lluGB", availableSpace, kb, mb, gb)); + } + }; + + class PackageVolumeTests_System : protected PackageVolumeTests_Base + { + public: + BEGIN_TEST_CLASS(PackageVolumeTests_System) + TEST_METHOD_PROPERTY(L"RunAs", L"ElevatedUser") + TEST_METHOD_PROPERTY(L"RunFixtureAs", L"System") + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassSetup) + { + return true; + } + + TEST_CLASS_CLEANUP(ClassCleanup) + { + return RemovePackageVolumeIfNecessary(); + } + + TEST_METHOD(Add_Online_Offline_Remove) + { + ::TB::Setup(); + auto cleanup{ wil::scope_exit([this]{ + ::TB::Cleanup(); + }) }; + + WEX::Common::String drive; + if (!::Test::TAEF::TryGetOption(L"PackageVolume.Drive", drive)) + { + WEX::Logging::Log::Result(WEX::Logging::TestResults::Skipped, L"/p:PackageVolume.Drive= not specified. Skipping tests"); + return; + } + if (BlockIfTestVolumeExists(drive)) + { + return; + } + + // Add a package volume + auto asyncOperation{ winrt::Microsoft::Windows::Management::Deployment::PackageVolume::AddAsync(GetTempDirectory()) }; + const auto hr{ static_cast(asyncOperation.ErrorCode()) }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"AddAsync: Status=%d ErrorCode=0x%X", asyncOperation.Status(), hr)); + auto packageVolumeAdded{ asyncOperation.get() }; + Dump(packageVolumeAdded); + // + // NOTE: Newly created PackageVolumes are Online + VERIFY_IS_FALSE(packageVolumeAdded.IsOffline()); + + // Verify the new package volume is query'able + { + auto packageVolume{ Dump(GetTempDirectory()) }; + Verify(packageVolumeAdded, packageVolume); + } + + VERIFY_IS_FALSE(packageVolumeAdded.IsOffline()); + + // Set the package volume Offline (or 'Dismount-PackageVolume' in Powershell-speak) + // FYI interactively: powershell -c "Get-AppxVolume -Path X: | Dismount-AppxVolume" + { + auto packageVolumeBefore{ Dump(GetTempDirectory()) }; + VERIFY_IS_FALSE(packageVolumeBefore.IsOffline()); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"SetOfflineAsync...")); + auto deploymentOperation{ packageVolumeAdded.SetOfflineAsync() }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + + auto packageVolumeAfter{ Dump(GetTempDirectory()) }; + VERIFY_IS_TRUE(packageVolumeAfter.IsOffline()); + } + + // Set the package volume Offline again (Offline->Offline == Offline (no change)) + { + auto packageVolumeBefore{ Dump(GetTempDirectory()) }; + VERIFY_IS_TRUE(packageVolumeBefore.IsOffline()); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"SetOfflineAsync...")); + auto deploymentOperation{ packageVolumeAdded.SetOfflineAsync() }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + + auto packageVolumeAfter{ Dump(GetTempDirectory()) }; + VERIFY_IS_TRUE(packageVolumeAfter.IsOffline()); + } + + // Set the package volume Online (or 'Mount-PackageVolume' in Powershell-speak) + // FYI interactively: powershell -c "Get-AppxVolume -Path X: | Mount-AppxVolume" + { + auto packageVolumeBefore{ Dump(GetTempDirectory()) }; + VERIFY_IS_TRUE(packageVolumeBefore.IsOffline()); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"SetOnlineAsync...")); + auto deploymentOperation{ packageVolumeAdded.SetOnlineAsync() }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + + auto packageVolumeAfter{ Dump(GetTempDirectory()) }; + VERIFY_IS_FALSE(packageVolumeAfter.IsOffline()); + } + + // Set the package volume Online again (Online->Online == Online (no change)) + { + auto packageVolumeBefore{ Dump(GetTempDirectory()) }; + VERIFY_IS_FALSE(packageVolumeBefore.IsOffline()); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"SetOnlineAsync...")); + auto deploymentOperation{ packageVolumeAdded.SetOnlineAsync() }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + + auto packageVolumeAfter{ Dump(GetTempDirectory()) }; + VERIFY_IS_FALSE(packageVolumeAfter.IsOffline()); + } + + // Remove the package volume + // + // FYI interactively: powershell -c "Get-AppxVolume -Path X: | Remove-AppxVolume" + { + auto packageVolume{ Dump(GetTempDirectory()) }; + VERIFY_IS_FALSE(packageVolume.IsOffline()); + + auto deploymentOperation{ packageVolumeAdded.RemoveAsync() }; + auto deploymentResult{ WaitForDeploymentOperation(deploymentOperation) }; + TPMT::VerifyDeploymentSucceeded(deploymentResult, __FILE__, __LINE__, __FUNCTION__); + } + } + }; +} diff --git a/test/PackageManager/API/Test.testdef b/test/PackageManager/API/Test.testdef index 21cdbb48a8..763b4ec623 100644 --- a/test/PackageManager/API/Test.testdef +++ b/test/PackageManager/API/Test.testdef @@ -91,5 +91,12 @@ "Architectures": ["x86", "x64"], "Status": "Enabled" } + { + "Description": "PackageManagerTests.PackageVolume* tests for feature PackageManager (arm64 not currently enabled)", + "Filename": "PackageManagerTests.dll", + "Parameters": "/name=Test::PackageManager::Tests::PackageVolumeTests*", + "Architectures": ["x86", "x64"], + "Status": "Enabled" + } ] } diff --git a/test/PackageManager/API/pch.h b/test/PackageManager/API/pch.h index 900c25a3d3..f329a4cbbe 100644 --- a/test/PackageManager/API/pch.h +++ b/test/PackageManager/API/pch.h @@ -8,8 +8,9 @@ #include -#include #include +#include +#include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include "PackageManagerTests.Packages.h" diff --git a/test/PowerNotifications/APITests.cpp b/test/PowerNotifications/APITests.cpp index d2346eb87e..5642123297 100644 --- a/test/PowerNotifications/APITests.cpp +++ b/test/PowerNotifications/APITests.cpp @@ -81,7 +81,7 @@ namespace Test::PowerNotifications auto batteryStat = BatteryStatus::Discharging; auto powerStat = PowerSupplyStatus::Inadequate; int32_t remainingCharge = 15; - auto token = PowerManager::BatteryStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::BatteryStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { batteryStat = PowerManager::BatteryStatus(); powerStat = PowerManager::PowerSupplyStatus(); @@ -108,7 +108,7 @@ namespace Test::PowerNotifications THROW_LAST_ERROR_IF_NULL(event.get()); auto value = winrt::Windows::Foundation::TimeSpan(1s); - auto token = PowerManager::RemainingDischargeTimeChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::RemainingDischargeTimeChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::RemainingDischargeTime(); SetEvent(event.get()); @@ -129,7 +129,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = EnergySaverStatus::Disabled; - auto token = PowerManager::EnergySaverStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::EnergySaverStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::EnergySaverStatus(); SetEvent(event.get()); @@ -151,7 +151,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = PowerSourceKind::DC; - auto token = PowerManager::PowerSourceKindChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::PowerSourceKindChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::PowerSourceKind(); SetEvent(event.get()); @@ -173,7 +173,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = DisplayStatus::Off; - auto token = PowerManager::DisplayStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::DisplayStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::DisplayStatus(); SetEvent(event.get()); @@ -193,7 +193,7 @@ namespace Test::PowerNotifications END_TEST_METHOD_PROPERTIES() auto callback_success = false; - auto token = PowerManager::SystemIdleStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::SystemIdleStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { callback_success = true; }); @@ -213,7 +213,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = UserPresenceStatus::Absent; - auto token = PowerManager::UserPresenceStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::UserPresenceStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::UserPresenceStatus(); SetEvent(event.get()); diff --git a/test/PowerNotifications/FunctionalTests.cpp b/test/PowerNotifications/FunctionalTests.cpp index 4058d2a5e1..06fba49e69 100644 --- a/test/PowerNotifications/FunctionalTests.cpp +++ b/test/PowerNotifications/FunctionalTests.cpp @@ -63,7 +63,7 @@ namespace Test::PowerNotifications auto batteryStat = BatteryStatus::Discharging; auto powerStat = PowerSupplyStatus::Inadequate; int32_t remainingCharge = 15; - auto token = PowerManager::BatteryStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::BatteryStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { batteryStat = PowerManager::BatteryStatus(); powerStat = PowerManager::PowerSupplyStatus(); @@ -90,7 +90,7 @@ namespace Test::PowerNotifications THROW_LAST_ERROR_IF_NULL(event.get()); auto value = winrt::Windows::Foundation::TimeSpan(1s); - auto token = PowerManager::RemainingDischargeTimeChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::RemainingDischargeTimeChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::RemainingDischargeTime(); SetEvent(event.get()); @@ -111,7 +111,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = EnergySaverStatus::Disabled; - auto token = PowerManager::EnergySaverStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::EnergySaverStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::EnergySaverStatus(); SetEvent(event.get()); @@ -133,7 +133,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = PowerSourceKind::DC; - auto token = PowerManager::PowerSourceKindChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::PowerSourceKindChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::PowerSourceKind(); SetEvent(event.get()); @@ -155,7 +155,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = DisplayStatus::Off; - auto token = PowerManager::DisplayStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::DisplayStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::DisplayStatus(); SetEvent(event.get()); @@ -175,7 +175,7 @@ namespace Test::PowerNotifications END_TEST_METHOD_PROPERTIES() auto callback_success = false; - auto token = PowerManager::SystemIdleStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::SystemIdleStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { callback_success = true; }); @@ -195,7 +195,7 @@ namespace Test::PowerNotifications wil::unique_handle event(CreateEvent(nullptr, false, false, nullptr)); THROW_LAST_ERROR_IF_NULL(event.get()); auto value = UserPresenceStatus::Absent; - auto token = PowerManager::UserPresenceStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable obj) + auto token = PowerManager::UserPresenceStatusChanged([&](const auto&, winrt::Windows::Foundation::IInspectable /*obj*/) { value = PowerManager::UserPresenceStatus(); SetEvent(event.get()); diff --git a/test/StoragePickersTests/StoragePickersTests.cpp b/test/StoragePickersTests/StoragePickersTests.cpp index 97721e7c2a..ff4647b3aa 100644 --- a/test/StoragePickersTests/StoragePickersTests.cpp +++ b/test/StoragePickersTests/StoragePickersTests.cpp @@ -192,7 +192,6 @@ namespace Test::StoragePickersTests TEST_METHOD(VerifyFolderPickerOptionsAreReadCorrectly) { - auto parentWindow = ::GetForegroundWindow(); winrt::Microsoft::UI::WindowId windowId{}; winrt::Microsoft::Windows::Storage::Pickers::FolderPicker picker(windowId);