winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 926a2f51704f2e767e259c746596213a5eb4268a
parent 2df595704f6a090ad828a7e7c531d1437a396765
Author: sreadingMSFT <74242768+sreadingMSFT@users.noreply.github.com>
Date:   Fri,  9 Jul 2021 11:49:36 -0700

Add Capability checks for callers to the packagedAPI (#1198)

* Check caller capabilities

* Revert line ending change.

* Allow packageQuery for Connect operations

* Update from pr comments.

* Skip unnecessary token step in getting caller id.
Diffstat:
M.github/actions/spelling/allow.txt | 1120++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/AppInstallerCLICore/COMContext.h | 2++
Msrc/AppInstallerCLICore/ExecutionContext.h | 2--
Asrc/Microsoft.Management.Deployment/Helpers.cpp | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Microsoft.Management.Deployment/Helpers.h | 32++++++++++++++++++++++++++++++--
Msrc/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj | 1+
Msrc/Microsoft.Management.Deployment/PackageCatalog.cpp | 88+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/Microsoft.Management.Deployment/PackageCatalogReference.cpp | 21+++++++++++++++------
Msrc/Microsoft.Management.Deployment/PackageManager.cpp | 73+++++++++++++++++++++++++++++--------------------------------------------
9 files changed, 774 insertions(+), 662 deletions(-)

diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt @@ -1,559 +1,561 @@ -abi -ACCESSDENIED -addmanifest -addstore -admins -alloc -anonymize -api -appdata -appinst -appinstaller -appmodel -apps -appx -appxbundle -appxmanifest -appxsdk -APSTUDIO -argc -args -argv -ARRAYSIZE -aspirational -aspnet -authn -authz -autocomplete -auxdata -azureedge -bcp -bcp47 -bcrypt -binver -Bitmask -blog -Blog -boolalpha -bstr -bugfix -BUILDNUMBER -bytearray -cdecl -cer -certutil -chrono -cin -cla -CLSCTX -cmake -cmp -CNG -cnt -codepage -COMMANDBARFLYOUT -Commandline -comparand -conemu -config -Configurability -constexpr -Contoso -copyable -COSTDEFERRED -cotaskmem -cout -cpp -cppreference -cpprest -cpprestsdk -cppwinrt -CPRWL -createnew -createtables -cref -csproj -CStr -CURSORPOSITON -cwctype -datatelemetry -dbconn -DBId -declspec -decltype -declval -defaultlocale -delstore -Demitrius -denelon -depersist -Deserialize -deserializer -deserializing -dest -devblogs -differentpath -distro -DIRECTONLY -dll -dllexport -docx -dotnet -downlevel -downloader -downloaders -dword -DWORDLONG -elseif -emoji -endif -endl -ensureandinsert -ensurepathexists -ENU -enum -EOAC -errorlevel -errstr -esrp -etag -ETW -EVENTTAG -exe -executables -exeenus -exeinteractive -exelog -exesilent -exeswp -exitcode -expr -EXTRAFLAGS -FAILIFTHERE -fakeswitch -FIELDTAG -FILEFLAGS -FILEFLAGSMASK -FILELOGGER -FILEOS -filepath -FILESUBTYPE -filesystem -FILETYPE -FILEVERSION -foreach -fstream -func -gcount -gdi -getline -github -githubusercontent -hfile -HGLOBAL -hinternet -HKEY -hmac -HMODULE -homepage -Homepage -hostname -hpp -HRESULT -hresult -HRSRC -hstring -html -http -https -Hyperlink -IApplication -IAppx -IAsync -IBuffer -icu -IDisposable -IDX -IEnumerable -IFACEMETHOD -ifdef -ifndef -ifstream -IInput -IInspectable -IIS -ILogger -impl -Inet -inno -INPROC -installertype -Installeruniqueness -installlocation -INSTALLPATH -interop -INVALIDARG -iomanip -iostream -IOutput -IProgress -IRandom -IRest -ISAPPROVEDFOROUTPUT -ISource -isspace -istream -istringstream -IUnknown -json -junit -langutil -lastwritetime -LCID -LCIDTo -LEN -Linux -LLVM -llvmorg -LOCALAPPDATA -localtime -LOGPATH -logsql -logto -LONGLONG -LPCGUID -LPVOID -mailto -MAJORVERSION -makeappx -MAKEINTRESOURCE -makemsix -MANIFESTSCHEMA -MANIFESTVERSION -MBs -mday -memset -metadata -microsoft -mimetype -Minimatch -MINORVERSION -mkdir -monostate -motw -mrm -msbuild -msdata -MSDN -msi -msiexec -msix -msixbundle -msixinfo -msixsdk -msixsdkx -msixtest -msrc -Multifile -Multimatch -mutex -mutexes -namespace -namespaces -Nelon -netcoreapp -newid -NOCLOSEPROCESS -nodiscard -noexcept -nomem -NOMINMAX -NONAME -nonexistentsetting -NONINFRINGEMENT -NOTHROW -NOTIMPL -NOTNULL -npos -NTFS -NTSTATUS -nuget -nullptr -nullsoft -nupkg -nuspec -nunit -OAuth -ofstream -opencode -opensource -ostream -ostringstream -OSVERSIONINFOEXW -outfile -OUTOFMEMORY -OWC -PACKAGESSCHEMA -Params -params -parentidx -pathpart -Pathto -PBYTE -pch -PCWSTR -pdb -PEVENT -pfp -PGP -PII -pipssource -placeholders -png -posix -powershell -PPV -pplx -pragma -PRECONFIG -preindexed -prepareforpackaging -PRIMARYKEY -prioritization -PRODUCTNAME -PRODUCTVERSION -psz -ptr -publiccontainer -PUCHAR -PVOID -pwa -QCol -RAII -rclsid -rdbuf -README -READONLY -READWRITE -realloc -REALTIME -Redistributable -REFCLSID -regex -regexp -removemanifest -repolibtest -rescap -resheader -resmimetype -RESTSOURCE -resw -resx -roadmap -robuffer -rowcount -rowid -rubengustorage -ruleset -runsettings -runtimes -safecast -SANITIZERS -savepoint -screenshots -SCROLLER -SCROLLVIEWER -sdk -seekg -seinfo -selectany -SERVICEPACKMAJOR -SERVICEPACKMINOR -setfill -setschemaversion -setvariable -setw -shcore -shellapi -SHELLEXEC -SHELLEXECUTEINFO -SHELLEXECUTEINFOA -SHELLEXECUTEINFOW -Shlwapi -signtool -silentwithprogress -simplesave -simpletest -sizeof -sln -SNAME -snprintf -sourced -Specv -sprintf -sql -sqlbuilder -sqlite -sqliteicu -sqliteindex -sqliteindexsource -sqlitewrapper -srand -src -srwlock -sscanf -sstream -STATFLAG -STATSTG -stdcall -stderr -stdexcept -stdout -STGM -stmt -stoi -stoll -stoull -strcoll -streamoff -streampos -stricmp -strikethrough -STRINGID -STRINGIFY -STRINGIZE -stringstream -strstr -subcontext -SUBLANG -subresource -subselect -substr -SWIPECONTROL -SYMED -Sys -sz -TARG -TARGETDIR -targetentrypoint -targetnametoken -tdbuild -tdd -tellg -tempdb -terabyte -testcontainer -testmoniker -Testrun -testsettingname -TEXTFORMAT -TEXTINCLUDE -there're -Timeline -todo -tolower -toupper -towlower -TRACELOGGING -triaged -trunc -TRUSTEDPEOPLE -tt -ttl -typedef -typename -UAC -uap -UBool -UBreak -ubrk -uchar -ucol -UCollation -UCollator -UError -UIA -UIF -uint -Uknown -ulong -ULONGLONG -uncomment -und -undef -unicode -UNICODESTRING -uninstall -uninstalling -Unregister -updatemanifest -UPLEVEL -upvote -uregex -URegular -uri -url -urlmon -userguide -USERPROFILE -usersources -utext -utf -uuidof -validator -valijson -vcvars -vcxitems -vcxproj -vdproj -versioned -VERSIONINFO -versioning -VERYSILENT -VFT -visualstudio -vm -VOS -vso -wapproj -wchar -wcout -wcsicmp -webpage -wekyb -wil -WINAPI -WINEVENT -winget -wininet -winmeta -winres -winrt -winsqlite -wix -wmain -woah -wofstream -workaround -workflow -wostringstream -wostream -wpfn -wrl -WStr -wstring -wstringstream -www -xamarin -xlang -xml -xmlns -XElement -XName -XResource -xsd -XTOKEN -yaml -yml -yy -zh +abi +ACCESSDENIED +addmanifest +addstore +admins +alloc +anonymize +api +appdata +appinst +appinstaller +appmodel +apps +appx +appxbundle +appxmanifest +appxsdk +APSTUDIO +argc +args +argv +ARRAYSIZE +aspirational +aspnet +authn +authz +autocomplete +auxdata +azureedge +bcp +bcp47 +bcrypt +binver +Bitmask +blog +Blog +boolalpha +bstr +bugfix +BUILDNUMBER +bytearray +cdecl +cer +certutil +chrono +cin +cla +CLSCTX +cmake +cmp +CNG +cnt +codepage +COMMANDBARFLYOUT +Commandline +comparand +conemu +config +Configurability +constexpr +Contoso +copyable +COSTDEFERRED +cotaskmem +cout +cpp +cppreference +cpprest +cpprestsdk +cppwinrt +CPRWL +createnew +createtables +cref +csproj +CStr +CURSORPOSITON +cwctype +datatelemetry +dbconn +DBId +declspec +decltype +declval +defaultlocale +delstore +Demitrius +denelon +depersist +Deserialize +deserializer +deserializing +dest +devblogs +differentpath +distro +DIRECTONLY +dll +dllexport +docx +dotnet +downlevel +downloader +downloaders +dword +DWORDLONG +elseif +emoji +endif +endl +ensureandinsert +ensurepathexists +ENU +enum +EOAC +errorlevel +errstr +esrp +etag +ETW +EVENTTAG +exe +executables +exeenus +exeinteractive +exelog +exesilent +exeswp +exitcode +expr +EXTRAFLAGS +FAILIFTHERE +fakeswitch +FIELDTAG +FILEFLAGS +FILEFLAGSMASK +FILELOGGER +FILEOS +filepath +FILESUBTYPE +filesystem +FILETYPE +FILEVERSION +foreach +fstream +func +gcount +gdi +getline +github +githubusercontent +hfile +HGLOBAL +hinternet +HKEY +hmac +HMODULE +homepage +Homepage +hostname +hpp +HRESULT +hresult +HRSRC +hstring +html +http +https +Hyperlink +IApplication +IAppx +IAsync +IBuffer +icu +IDisposable +IDX +IEnumerable +IFACEMETHOD +ifdef +ifndef +ifstream +IInput +IInspectable +IIS +ILogger +impl +Inet +inno +INPROC +Inq +installertype +Installeruniqueness +installlocation +INSTALLPATH +interop +INVALIDARG +iomanip +iostream +IOutput +IProgress +IRandom +IRest +ISAPPROVEDFOROUTPUT +ISource +isspace +istream +istringstream +IUnknown +json +junit +langutil +lastwritetime +LCID +LCIDTo +LEN +Linux +LLVM +llvmorg +LOCALAPPDATA +localtime +LOGPATH +logsql +logto +LONGLONG +LPCGUID +LPVOID +mailto +MAJORVERSION +makeappx +MAKEINTRESOURCE +makemsix +MANIFESTSCHEMA +MANIFESTVERSION +MBs +mday +memset +metadata +microsoft +mimetype +Minimatch +MINORVERSION +mkdir +monostate +motw +mrm +msbuild +msdata +MSDN +msi +msiexec +msix +msixbundle +msixinfo +msixsdk +msixsdkx +msixtest +msrc +Multifile +Multimatch +mutex +mutexes +namespace +namespaces +Nelon +netcoreapp +newid +NOCLOSEPROCESS +nodiscard +noexcept +nomem +NOMINMAX +NONAME +nonexistentsetting +NONINFRINGEMENT +NOTHROW +NOTIMPL +NOTNULL +npos +NTFS +NTSTATUS +nuget +nullptr +nullsoft +nupkg +nuspec +nunit +OAuth +ofstream +opencode +opensource +ostream +ostringstream +OSVERSIONINFOEXW +outfile +OUTOFMEMORY +OWC +PACKAGESSCHEMA +Params +params +parentidx +pathpart +Pathto +PBYTE +pch +PCWSTR +pdb +PEVENT +pfp +PGP +PII +pipssource +placeholders +png +posix +powershell +PPV +pplx +pragma +PRECONFIG +preindexed +prepareforpackaging +PRIMARYKEY +prioritization +PRODUCTNAME +PRODUCTVERSION +psz +ptr +publiccontainer +PUCHAR +PVOID +pwa +QCol +RAII +rclsid +rdbuf +README +READONLY +READWRITE +realloc +REALTIME +Redistributable +REFCLSID +regex +regexp +removemanifest +repolibtest +rescap +resheader +resmimetype +RESTSOURCE +resw +resx +roadmap +robuffer +rowcount +rowid +Rpc +rubengustorage +ruleset +runsettings +runtimes +safecast +SANITIZERS +savepoint +screenshots +SCROLLER +SCROLLVIEWER +sdk +seekg +seinfo +selectany +SERVICEPACKMAJOR +SERVICEPACKMINOR +setfill +setschemaversion +setvariable +setw +shcore +shellapi +SHELLEXEC +SHELLEXECUTEINFO +SHELLEXECUTEINFOA +SHELLEXECUTEINFOW +Shlwapi +signtool +silentwithprogress +simplesave +simpletest +sizeof +sln +SNAME +snprintf +sourced +Specv +sprintf +sql +sqlbuilder +sqlite +sqliteicu +sqliteindex +sqliteindexsource +sqlitewrapper +srand +src +srwlock +sscanf +sstream +STATFLAG +STATSTG +stdcall +stderr +stdexcept +stdout +STGM +stmt +stoi +stoll +stoull +strcoll +streamoff +streampos +stricmp +strikethrough +STRINGID +STRINGIFY +STRINGIZE +stringstream +strstr +subcontext +SUBLANG +subresource +subselect +substr +SWIPECONTROL +SYMED +Sys +sz +TARG +TARGETDIR +targetentrypoint +targetnametoken +tdbuild +tdd +tellg +tempdb +terabyte +testcontainer +testmoniker +Testrun +testsettingname +TEXTFORMAT +TEXTINCLUDE +there're +Timeline +todo +tolower +toupper +towlower +TRACELOGGING +triaged +trunc +TRUSTEDPEOPLE +tt +ttl +typedef +typename +UAC +uap +UBool +UBreak +ubrk +uchar +ucol +UCollation +UCollator +UError +UIA +UIF +uint +Uknown +ulong +ULONGLONG +uncomment +und +undef +unicode +UNICODESTRING +uninstall +uninstalling +Unregister +updatemanifest +UPLEVEL +upvote +uregex +URegular +uri +url +urlmon +userguide +USERPROFILE +usersources +utext +utf +uuidof +validator +valijson +vcvars +vcxitems +vcxproj +vdproj +versioned +VERSIONINFO +versioning +VERYSILENT +VFT +visualstudio +vm +VOS +vso +wapproj +wchar +wcout +wcsicmp +webpage +wekyb +wil +WINAPI +WINEVENT +winget +wininet +winmeta +winres +winrt +winsqlite +wix +wmain +woah +wofstream +workaround +workflow +wostringstream +wostream +wpfn +wrl +WStr +wstring +wstringstream +www +xamarin +xlang +xml +xmlns +XElement +XName +XResource +xsd +XTOKEN +yaml +yml +yy +zh diff --git a/src/AppInstallerCLICore/COMContext.h b/src/AppInstallerCLICore/COMContext.h @@ -56,6 +56,8 @@ namespace AppInstaller //Execution::Context void SetExecutionStage(CLI::Workflow::ExecutionStage executionPhase, bool); + CLI::Workflow::ExecutionStage GetExecutionStage() const { return m_executionStage; } + void SetProgressCallbackFunction(ProgressCallBackFunction&& f) { m_comProgressCallback = std::move(f); diff --git a/src/AppInstallerCLICore/ExecutionContext.h b/src/AppInstallerCLICore/ExecutionContext.h @@ -107,8 +107,6 @@ namespace AppInstaller::CLI::Execution virtual void SetExecutionStage(Workflow::ExecutionStage stage, bool); - Workflow::ExecutionStage GetExecutionStage() const { return m_executionStage; } - #ifndef AICLI_DISABLE_TEST_HOOKS // Enable tests to override behavior virtual bool ShouldExecuteWorkflowTask(const Workflow::WorkflowTask&) { return true; } diff --git a/src/Microsoft.Management.Deployment/Helpers.cpp b/src/Microsoft.Management.Deployment/Helpers.cpp @@ -0,0 +1,96 @@ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include <wil/resource.h> +#include <wil/win32_helpers.h> +#include <winrt/Windows.Security.Authorization.AppCapabilityAccess.h> +#include <appmodel.h> +#include <Helpers.h> + +using namespace std::string_literals; +using namespace std::string_view_literals; + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + std::optional<DWORD> GetCallerProcessId() + { + RPC_STATUS rpcStatus = RPC_S_OK; + RPC_CALL_ATTRIBUTES callAttributes = {}; + callAttributes.Version = RPC_CALL_ATTRIBUTES_VERSION; + callAttributes.Flags = RPC_QUERY_CLIENT_PID; + rpcStatus = RpcServerInqCallAttributes(nullptr, &callAttributes); + + if ((rpcStatus != RPC_S_NO_CALL_ACTIVE) && + !((rpcStatus == RPC_S_OK) && HandleToULong(callAttributes.ClientPID) == GetCurrentProcessId())) + { + DWORD callerProcessId = HandleToULong(callAttributes.ClientPID); + return callerProcessId; + } + return {}; + } + + std::wstring_view GetStringForCapability(Capability capability) + { + switch (capability) + { + case Capability::PackageManagement: + return L"packageManagement"sv; + case Capability::PackageQuery: + return L"packageQuery"sv; + default: + winrt::throw_hresult(E_UNEXPECTED); + } + } + + HRESULT EnsureProcessHasCapability(Capability requiredCapability, DWORD callerProcessId) + { + // Get the caller process id and use it to check if the caller has permissions to access the feature. + winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus status = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::DeniedBySystem; + + auto capability = winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapability::CreateWithProcessIdForUser(nullptr, GetStringForCapability(requiredCapability), callerProcessId); + status = capability.CheckAccess(); + RETURN_HR_IF(E_ACCESSDENIED, status != winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::Allowed); + + return S_OK; + } + + HRESULT EnsureComCallerHasCapability(Capability requiredCapability) + { + auto callerProcessId = GetCallerProcessId(); + RETURN_HR_IF(E_ACCESSDENIED, !callerProcessId.has_value()); + HRESULT hr = EnsureProcessHasCapability(requiredCapability, callerProcessId.value()); + // The Windows.Management.Deployment API has set the precedent that packageManagement is a superset of packageQuery + // and packageQuery does not need to be declared separately. + if (FAILED(hr) && requiredCapability == Capability::PackageQuery) + { + return EnsureProcessHasCapability(Capability::PackageManagement, callerProcessId.value()); + } + return hr; + } + + // Best effort at getting caller info. This should only be used for logging. + std::wstring TryGetCallerProcessInfo(DWORD callerProcessId) + { + wil::unique_process_handle processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, callerProcessId)); + if (processHandle) + { + WCHAR packageFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH]{}; + UINT32 length = ARRAYSIZE(packageFamilyName); + if (::GetPackageFamilyName(processHandle.get(), &length, packageFamilyName) == ERROR_SUCCESS) + { + return { packageFamilyName }; + } + + // if the caller doesn't have an AppUserModelID then fall back to the executable name + wil::unique_cotaskmem_string imageName = nullptr; + if (SUCCEEDED(wil::QueryFullProcessImageNameW(processHandle.get(), 0, imageName)) && + (imageName.get() != nullptr)) + { + return imageName.get(); + } + } + + return {}; + } +}+ \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/Helpers.h b/src/Microsoft.Management.Deployment/Helpers.h @@ -3,4 +3,32 @@ //A version of CoCreatableCppWinRtClass that lets you pass in a uuid rather than getting it from a class property. #define CoCreatableClassWithCLSIDWithFactory(className, instance, clsid, factory) \ InternalWrlCreateCreatorMap(className##instance##_COM, clsid, nullptr, ::Microsoft::WRL::Details::CreateClassFactory<factory>, "minATL$__f") -#define CoCreatableCppWinRtClassWithCLSID(className, instance, clsid) CoCreatableClassWithCLSIDWithFactory(className, instance, clsid, ::wil::wrl_factory_for_winrt_com_class<className>)- \ No newline at end of file +#define CoCreatableCppWinRtClassWithCLSID(className, instance, clsid) CoCreatableClassWithCLSIDWithFactory(className, instance, clsid, ::wil::wrl_factory_for_winrt_com_class<className>) + +#define WINGET_CATCH_RESULT_EXCEPTION_STORE(exceptionHR) catch (const wil::ResultException& re) { exceptionHR = re.GetErrorCode(); } +#define WINGET_CATCH_HRESULT_EXCEPTION_STORE(exceptionHR) catch (const winrt::hresult_error& hre) { exceptionHR = hre.code(); } +#define WINGET_CATCH_COMMAND_EXCEPTION_STORE(exceptionHR) catch (const ::AppInstaller::CLI::CommandException&) { exceptionHR = APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS; } +#define WINGET_CATCH_POLICY_EXCEPTION_STORE(exceptionHR) catch (const ::AppInstaller::Settings::GroupPolicyException&) { exceptionHR = APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS; } +#define WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR) catch (const std::exception&) { exceptionHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; } +#define WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR) catch (...) { exceptionHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; } +#define WINGET_CATCH_STORE(exceptionHR) \ + WINGET_CATCH_RESULT_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_HRESULT_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_COMMAND_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_POLICY_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_STD_EXCEPTION_STORE(exceptionHR) \ + WINGET_CATCH_ALL_EXCEPTION_STORE(exceptionHR) + +namespace winrt::Microsoft::Management::Deployment::implementation +{ + enum class Capability + { + PackageManagement, + PackageQuery + }; + + HRESULT EnsureProcessHasCapability(Capability requiredCapability, DWORD callerProcessId); + HRESULT EnsureComCallerHasCapability(Capability requiredCapability); + std::optional<DWORD> GetCallerProcessId(); + std::wstring TryGetCallerProcessInfo(DWORD callerProcessId); +}+ \ No newline at end of file diff --git a/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj b/src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj @@ -152,6 +152,7 @@ <ClCompile Include="CreateCompositePackageCatalogOptions.cpp" /> <ClCompile Include="FindPackagesOptions.cpp" /> <ClCompile Include="FindPackagesResult.cpp" /> + <ClCompile Include="Helpers.cpp" /> <ClCompile Include="InstallOptions.cpp" /> <ClCompile Include="InstallResult.cpp" /> <ClCompile Include="MatchResult.cpp" /> diff --git a/src/Microsoft.Management.Deployment/PackageCatalog.cpp b/src/Microsoft.Management.Deployment/PackageCatalog.cpp @@ -11,6 +11,8 @@ #include "FindPackagesResult.h" #include "MatchResult.h" #include "CatalogPackage.h" +#include "Commands/RootCommand.h" +#include "Helpers.h" #pragma warning( push ) #pragma warning ( disable : 4467 6388) // 6388 Allow CreateInstance. @@ -107,6 +109,16 @@ namespace winrt::Microsoft::Management::Deployment::implementation return S_OK; } + winrt::Microsoft::Management::Deployment::FindPackagesResult GetFindPackagesResult(HRESULT hr, bool isTruncated, Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::MatchResult> matches) + { + auto findPackagesResult = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::FindPackagesResult>>(); + // TODO: Add search timeout and error code. + winrt::Microsoft::Management::Deployment::FindPackagesResultStatus status = FindPackagesResultStatus(hr); + findPackagesResult->Initialize(status, isTruncated, matches); + return *findPackagesResult; + } + winrt::Microsoft::Management::Deployment::FindPackagesResult PackageCatalog::FindPackages(winrt::Microsoft::Management::Deployment::FindPackagesOptions const& options) { winrt::Microsoft::Management::Deployment::FindPackagesResultStatus::Ok; @@ -114,63 +126,41 @@ namespace winrt::Microsoft::Management::Deployment::implementation Windows::Foundation::Collections::IVector<Microsoft::Management::Deployment::MatchResult> matches{ winrt::single_threaded_vector<Microsoft::Management::Deployment::MatchResult>() }; ::AppInstaller::Repository::SearchRequest searchRequest; - HRESULT hr = PopulateSearchRequest(&searchRequest, options); - if (SUCCEEDED(hr)) + HRESULT hr = S_OK; + try { - searchRequest.MaximumResults = options.ResultLimit(); - try + // No need to check for caller capability again since packageQuery was required in order to get the PackageCatalog object through Connect + + if (FAILED(hr = PopulateSearchRequest(&searchRequest, options))) { - auto searchResult = m_source->Search(searchRequest); + return GetFindPackagesResult(hr, isTruncated, matches); + } + + searchRequest.MaximumResults = options.ResultLimit(); + auto searchResult = m_source->Search(searchRequest); - // Build the result object from the searchResult - for (size_t i = 0; i < searchResult.Matches.size(); ++i) - { - auto match = searchResult.Matches[i]; - auto catalogPackage = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::CatalogPackage>>(); - catalogPackage->Initialize(m_source, match.Package); + // Build the result object from the searchResult + for (size_t i = 0; i < searchResult.Matches.size(); ++i) + { + auto match = searchResult.Matches[i]; + auto catalogPackage = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::CatalogPackage>>(); + catalogPackage->Initialize(m_source, match.Package); - auto packageMatchFilter = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::PackageMatchFilter>>(); - packageMatchFilter->Initialize(match.MatchCriteria); + auto packageMatchFilter = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::PackageMatchFilter>>(); + packageMatchFilter->Initialize(match.MatchCriteria); - auto matchResult = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::MatchResult>>(); - matchResult->Initialize(*catalogPackage, *packageMatchFilter); + auto matchResult = winrt::make_self<wil::details::module_count_wrapper< + winrt::Microsoft::Management::Deployment::implementation::MatchResult>>(); + matchResult->Initialize(*catalogPackage, *packageMatchFilter); - matches.Append(*matchResult); - } - isTruncated = searchResult.Truncated; - } - // Exceptions that may occur in the process of executing an arbitrary command - catch (const wil::ResultException& re) - { - hr = re.GetErrorCode(); - } - catch (const winrt::hresult_error& hre) - { - hr = hre.code(); - } - catch (const ::AppInstaller::Settings::GroupPolicyException&) - { - // Policy could have changed since server started. - hr = APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY; - } - catch (const std::exception&) - { - hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; - } - catch (...) - { - hr = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; + matches.Append(*matchResult); } + isTruncated = searchResult.Truncated; } - auto findPackagesResult = winrt::make_self<wil::details::module_count_wrapper< - winrt::Microsoft::Management::Deployment::implementation::FindPackagesResult>>(); - // TODO: Add search timeout and error code. - winrt::Microsoft::Management::Deployment::FindPackagesResultStatus status = FindPackagesResultStatus(hr); - findPackagesResult->Initialize(status, isTruncated, matches); + WINGET_CATCH_STORE(hr); - return *findPackagesResult; + return GetFindPackagesResult(hr, isTruncated, matches); } } diff --git a/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp b/src/Microsoft.Management.Deployment/PackageCatalogReference.cpp @@ -13,6 +13,7 @@ #include <wil\cppwinrt_wrl.h> #include <winget/GroupPolicy.h> #include <AppInstallerErrors.h> +#include <Helpers.h> namespace winrt::Microsoft::Management::Deployment::implementation { @@ -37,10 +38,22 @@ namespace winrt::Microsoft::Management::Deployment::implementation { co_return Connect(); } + winrt::Microsoft::Management::Deployment::ConnectResult GetConnectCatalogErrorResult() + { + auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); + connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); + return *connectResult; + } winrt::Microsoft::Management::Deployment::ConnectResult PackageCatalogReference::Connect() { try { + if (FAILED(EnsureComCallerHasCapability(Capability::PackageQuery))) + { + // TODO: When more error codes are added, this should go back as something other than CatalogError. + return GetConnectCatalogErrorResult(); + } + ::AppInstaller::ProgressCallback progress; std::shared_ptr<::AppInstaller::Repository::ISource> source; if (m_compositePackageCatalogOptions) @@ -56,9 +69,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation if (!remoteSource) { // If source is null, return the error. There's no way to get the hresult that caused the error right now. - auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); - connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); - return *connectResult; + return GetConnectCatalogErrorResult(); } remoteSources.emplace_back(std::move(remoteSource)); } @@ -84,9 +95,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation if (!source) { // If source is null, return the error. There's no way to get the hresult that caused the error right now. - auto connectResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::ConnectResult>>(); - connectResult->Initialize(winrt::Microsoft::Management::Deployment::ConnectResultStatus::CatalogError, nullptr); - return *connectResult; + return GetConnectCatalogErrorResult(); } // Have to make another package catalog info because source->GetDetails has more fields than m_info does. diff --git a/src/Microsoft.Management.Deployment/PackageManager.cpp b/src/Microsoft.Management.Deployment/PackageManager.cpp @@ -120,19 +120,37 @@ namespace winrt::Microsoft::Management::Deployment::implementation winrt::hresult result = ::AppInstaller::CLI::Execute(context, command); return result; } + winrt::Microsoft::Management::Deployment::InstallResult GetInstallResult(::AppInstaller::CLI::Workflow::ExecutionStage executionStage, winrt::hresult terminationHR, winrt::hstring correlationData, bool rebootRequired) + { + winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(executionStage, terminationHR); + auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); + installResult->Initialize(installResultStatus, terminationHR, correlationData, rebootRequired); + return *installResult; + } winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Microsoft::Management::Deployment::InstallResult, winrt::Microsoft::Management::Deployment::InstallProgress> PackageManager::InstallPackageAsync(winrt::Microsoft::Management::Deployment::CatalogPackage package, winrt::Microsoft::Management::Deployment::InstallOptions options) { - auto report_progress{ co_await winrt::get_progress_token() }; - auto cancellationToken{ co_await winrt::get_cancellation_token() }; - - InstallProgress queuedProgress{ PackageInstallProgressState::Queued, 0, 0, 0 }; - report_progress(queuedProgress); - winrt::hresult terminationHR = S_OK; ::AppInstaller::CLI::Workflow::ExecutionStage executionStage = ::AppInstaller::CLI::Workflow::ExecutionStage::Initial; try { + std::optional<DWORD> callerProcessId = GetCallerProcessId(); + if (!callerProcessId.has_value()) + { + co_return GetInstallResult(executionStage, E_ACCESSDENIED, options.CorrelationData(), false); + } + if (FAILED(terminationHR = EnsureProcessHasCapability(Capability::PackageManagement, callerProcessId.value()))) + { + co_return GetInstallResult(executionStage, terminationHR, options.CorrelationData(), false); + } + std::wstring callerProcessInfoString = TryGetCallerProcessInfo(callerProcessId.value()); + + auto report_progress{ co_await winrt::get_progress_token() }; + auto cancellationToken{ co_await winrt::get_cancellation_token() }; + + InstallProgress queuedProgress{ PackageInstallProgressState::Queued, 0, 0, 0 }; + report_progress(queuedProgress); + Microsoft::Management::Deployment::PackageVersionId versionId{ nullptr }; if (options) { @@ -153,18 +171,13 @@ namespace winrt::Microsoft::Management::Deployment::implementation if (!packageVersionInfo) { // If no package version was found on the catalog then return a failure. This is unexpected, a catalog with no latest version should not be in the catalog. - terminationHR = APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER; - winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(executionStage, terminationHR); - auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); - installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); - co_return *installResult; + co_return GetInstallResult(executionStage, APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER, options.CorrelationData(), false); } // Handle the progress from the installer ::AppInstaller::COMContext context; - // TODO: Exact ComCaller's process name needs to be retrieved from COM Client side in the future - context.SetLoggerContext(options.CorrelationData(), "COMCaller"); + context.SetLoggerContext(options.CorrelationData(), ::AppInstaller::Utility::ConvertToUTF8(callerProcessInfoString)); // Convert the options to arguments for the installer. context.Args.AddArg(::AppInstaller::CLI::Execution::Args::Type::Id, ::AppInstaller::Utility::ConvertToUTF8(package.Id())); @@ -316,38 +329,10 @@ namespace winrt::Microsoft::Management::Deployment::implementation executionStage = context.GetExecutionStage(); } - // Exceptions that may occur in the process of executing an arbitrary command - catch (const wil::ResultException& re) - { - terminationHR = re.GetErrorCode(); - } - catch (const winrt::hresult_error& hre) - { - terminationHR = hre.code(); - } - catch (const ::AppInstaller::CLI::CommandException&) - { - terminationHR = APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS; - } - catch (const ::AppInstaller::Settings::GroupPolicyException&) - { - // Policy could have changed since server started - // or catalog could have been disabled since being returned. - terminationHR = APPINSTALLER_CLI_ERROR_BLOCKED_BY_POLICY; - } - catch (const std::exception&) - { - terminationHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; - } - catch (...) - { - terminationHR = APPINSTALLER_CLI_ERROR_COMMAND_FAILED; - } + WINGET_CATCH_STORE(terminationHR); + // TODO - RebootRequired not yet populated, msi arguments not returned from Execute. - winrt::Microsoft::Management::Deployment::InstallResultStatus installResultStatus = GetInstallResultStatus(executionStage, terminationHR); - auto installResult = winrt::make_self<wil::details::module_count_wrapper<winrt::Microsoft::Management::Deployment::implementation::InstallResult>>(); - installResult->Initialize(installResultStatus, terminationHR, options.CorrelationData(), false); - co_return *installResult; + co_return GetInstallResult(executionStage, terminationHR, options.CorrelationData(), false); } CoCreatableCppWinRtClassWithCLSID(PackageManager, 1, &PackageManagerCLSID1); CoCreatableCppWinRtClassWithCLSID(PackageManager, 2, &PackageManagerCLSID2);