From f3c96bcab560cb09355e9366eac3f4195479d95d Mon Sep 17 00:00:00 2001 From: Jacob Hoover Date: Fri, 11 Jun 2021 17:05:06 -0500 Subject: Allow access to persisted variables from related bundles. Implements #3704 --- src/libs/dutil/WixToolset.DUtil/butil.cpp | 105 +++++++++++++++++++++++--- src/libs/dutil/WixToolset.DUtil/inc/butil.h | 11 ++- src/libs/dutil/WixToolset.DUtil/inc/regutil.h | 8 ++ src/libs/dutil/WixToolset.DUtil/regutil.cpp | 47 ++++++++++++ 4 files changed, 158 insertions(+), 13 deletions(-) (limited to 'src/libs') diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp index e04b52e9..cda2a658 100644 --- a/src/libs/dutil/WixToolset.DUtil/butil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp @@ -20,6 +20,7 @@ const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCode"; const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; +const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; // Forward declarations. /******************************************************************** @@ -29,10 +30,13 @@ NOTE: caller is responsible for closing key ********************************************************************/ static HRESULT OpenBundleKey( __in_z LPCWSTR wzBundleId, - __in BUNDLE_INSTALL_CONTEXT context, - __inout HKEY *key); - + __in BUNDLE_INSTALL_CONTEXT context, + __in_opt LPCWSTR szSubKey, + __inout HKEY* key); +/******************************************************************** +BundleGetBundleInfo - Read the registration data for a gven bundle +********************************************************************/ extern "C" HRESULT DAPI BundleGetBundleInfo( __in_z LPCWSTR wzBundleId, __in_z LPCWSTR wzAttribute, @@ -43,7 +47,6 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( Assert(wzBundleId && wzAttribute); HRESULT hr = S_OK; - BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; LPWSTR sczValue = NULL; HKEY hkBundle = NULL; DWORD cchSource = 0; @@ -55,8 +58,8 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); } - if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, &hkBundle)) && - FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, &hkBundle))) + if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, NULL, &hkBundle)) && + FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, NULL, &hkBundle))) { ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); } @@ -108,7 +111,10 @@ LExit: return hr; } -HRESULT DAPI BundleEnumRelatedBundle( +/******************************************************************** +********************************************************************/ + +extern "C" HRESULT DAPI BundleEnumRelatedBundle( __in_z LPCWSTR wzUpgradeCode, __in BUNDLE_INSTALL_CONTEXT context, __inout PDWORD pdwStartIndex, @@ -231,11 +237,80 @@ LExit: return hr; } +/******************************************************************** +BundleGetBundleVariable - Queries the bundle installation metadata for a given variable, +the caller is expected to free the memory returned vis psczValue +RETURNS: +S_OK + Success, if the variable had a value, it's returned in psczValue +E_INVALIDARG + An invalid parameter was passed to the function. +HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) + The bundle is not installed +HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) + The variable is unrecognized +E_NOTIMPL: + Tried to read a bundle variable for a type which has not been implemented + +All other returns are unexpected returns from other dutil methods. +********************************************************************/ + +extern "C" HRESULT DAPI BundleGetBundleVariable( + __in_z LPCWSTR wzBundleId, + __in_z LPCWSTR wzVariable, + __deref_out_z LPWSTR * psczValue +) +{ + Assert(wzBundleId && wzVariable); + + HRESULT hr = S_OK; + BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; + HKEY hkBundle = NULL; + DWORD dwType = 0; + + if (!wzBundleId || !wzVariable || !psczValue) + { + ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); + } + + if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle)) && + FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle))) + { + ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key variable path."); + } + + // If the bundle doesn't have the shared variable defined, return ERROR_UNKNOWN_PROPERTY + hr = RegGetType(hkBundle, wzVariable, &dwType); + ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) : hr, "Failed to locate bundle variable."); + + switch (dwType) + { + case REG_SZ: + hr = RegReadString(hkBundle, wzVariable, psczValue); + ButilExitOnFailure(hr, "Failed to read string shared variable."); + break; + case REG_NONE: + hr = S_OK; + break; + default: + ButilExitOnFailure(hr = E_NOTIMPL, "Reading bundle variable of type 0x%x not implemented.", dwType); + + } + +LExit: + ReleaseRegKey(hkBundle); + return hr; + +} +/******************************************************************** +* +********************************************************************/ HRESULT OpenBundleKey( __in_z LPCWSTR wzBundleId, - __in BUNDLE_INSTALL_CONTEXT context, - __inout HKEY *key) + __in BUNDLE_INSTALL_CONTEXT context, + __in_opt LPCWSTR szSubKey, + __inout HKEY* key) { Assert(key && wzBundleId); AssertSz(NULL == *key, "*key should be null"); @@ -244,9 +319,16 @@ HRESULT OpenBundleKey( HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; LPWSTR sczKeypath = NULL; - hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); + if (szSubKey) + { + hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId, szSubKey); + } + else + { + hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); + } ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); - + hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); @@ -255,3 +337,4 @@ LExit: return hr; } + diff --git a/src/libs/dutil/WixToolset.DUtil/inc/butil.h b/src/libs/dutil/WixToolset.DUtil/inc/butil.h index d1ec73bc..d910c113 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/butil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/butil.h @@ -6,11 +6,11 @@ extern "C" { #endif -enum BUNDLE_INSTALL_CONTEXT +typedef enum BUNDLE_INSTALL_CONTEXT { BUNDLE_INSTALL_CONTEXT_MACHINE, BUNDLE_INSTALL_CONTEXT_USER, -}; +} BUNDLE_INSTALL_CONTEXT; /******************************************************************** @@ -55,6 +55,13 @@ HRESULT DAPI BundleEnumRelatedBundle( __out_ecount(MAX_GUID_CHARS+1) LPWSTR lpBundleIdBuf ); +HRESULT DAPI BundleGetBundleVariable( + __in_z LPCWSTR wzBundleId, + __in_z LPCWSTR wzVariable, + __deref_out_z LPWSTR* psczValue +); + + #ifdef __cplusplus } #endif diff --git a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h index 75284940..fcf13054 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/regutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/regutil.h @@ -178,6 +178,10 @@ HRESULT DAPI RegReadVersion( __in_z_opt LPCWSTR wzName, __out DWORD64* pdw64Version ); +HRESULT DAPI RegReadNone( + __in HKEY hk, + __in_z_opt LPCWSTR wzName +); HRESULT DAPI RegReadNumber( __in HKEY hk, __in_z_opt LPCWSTR wzName, @@ -211,6 +215,10 @@ HRESULT DAPI RegWriteStringFormatted( __in __format_string LPCWSTR szFormat, ... ); +HRESULT DAPI RegWriteNone( + __in HKEY hk, + __in_z_opt LPCWSTR wzName +); HRESULT DAPI RegWriteNumber( __in HKEY hk, __in_z_opt LPCWSTR wzName, diff --git a/src/libs/dutil/WixToolset.DUtil/regutil.cpp b/src/libs/dutil/WixToolset.DUtil/regutil.cpp index cb617932..458d8586 100644 --- a/src/libs/dutil/WixToolset.DUtil/regutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/regutil.cpp @@ -672,6 +672,34 @@ LExit: return hr; } +/******************************************************************** + RegReadNone - reads a NONE registry key value. + +*********************************************************************/ +extern "C" HRESULT DAPI RegReadNone( + __in HKEY hk, + __in_z_opt LPCWSTR wzName) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + DWORD dwType = 0; + + er = vpfnRegQueryValueExW(hk, wzName, NULL, &dwType, NULL, NULL); + if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) + { + ExitFunction1(hr = E_FILENOTFOUND); + } + RegExitOnWin32Error(er, hr, "Failed to query registry key value."); + + if (REG_NONE != dwType) + { + hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE); + RegExitOnRootFailure(hr, "Error reading version registry value due to unexpected data type: %u", dwType); + } + +LExit: + return hr; +} /******************************************************************** RegReadNumber - reads a DWORD registry key value as a number. @@ -885,6 +913,25 @@ LExit: return hr; } +/******************************************************************** + RegWriteNone - writes a registry key value as none. + +*********************************************************************/ +extern "C" HRESULT DAPI RegWriteNone( + __in HKEY hk, + __in_z_opt LPCWSTR wzName +) +{ + HRESULT hr = S_OK; + DWORD er = ERROR_SUCCESS; + + er = vpfnRegSetValueExW(hk, wzName, 0, REG_NONE, NULL, NULL); + RegExitOnWin32Error(er, hr, "Failed to set %ls value.", wzName); + +LExit: + return hr; +} + /******************************************************************** RegWriteNumber - writes a registry key value as a number. -- cgit v1.2.3-55-g6feb