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:
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);