diff options
author | Jacob Hoover <jacob.hoover@greenheck.com> | 2021-06-11 17:05:06 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-07-18 14:41:21 -0500 |
commit | f3c96bcab560cb09355e9366eac3f4195479d95d (patch) | |
tree | 1585c1f2af7e3582e14663c29c033702e910d12f /src/libs | |
parent | 5b2b06c9bffb4e6f17409cec41bc0b4b8dab4c90 (diff) | |
download | wix-f3c96bcab560cb09355e9366eac3f4195479d95d.tar.gz wix-f3c96bcab560cb09355e9366eac3f4195479d95d.tar.bz2 wix-f3c96bcab560cb09355e9366eac3f4195479d95d.zip |
Allow access to persisted variables from related bundles.
Implements #3704
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/butil.cpp | 105 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/butil.h | 11 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/regutil.h | 8 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/regutil.cpp | 47 |
4 files changed, 158 insertions, 13 deletions
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 @@ | |||
20 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; | 20 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; |
21 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCode"; | 21 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgradeCode"; |
22 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; | 22 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; |
23 | const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; | ||
23 | 24 | ||
24 | // Forward declarations. | 25 | // Forward declarations. |
25 | /******************************************************************** | 26 | /******************************************************************** |
@@ -29,10 +30,13 @@ NOTE: caller is responsible for closing key | |||
29 | ********************************************************************/ | 30 | ********************************************************************/ |
30 | static HRESULT OpenBundleKey( | 31 | static HRESULT OpenBundleKey( |
31 | __in_z LPCWSTR wzBundleId, | 32 | __in_z LPCWSTR wzBundleId, |
32 | __in BUNDLE_INSTALL_CONTEXT context, | 33 | __in BUNDLE_INSTALL_CONTEXT context, |
33 | __inout HKEY *key); | 34 | __in_opt LPCWSTR szSubKey, |
34 | 35 | __inout HKEY* key); | |
35 | 36 | ||
37 | /******************************************************************** | ||
38 | BundleGetBundleInfo - Read the registration data for a gven bundle | ||
39 | ********************************************************************/ | ||
36 | extern "C" HRESULT DAPI BundleGetBundleInfo( | 40 | extern "C" HRESULT DAPI BundleGetBundleInfo( |
37 | __in_z LPCWSTR wzBundleId, | 41 | __in_z LPCWSTR wzBundleId, |
38 | __in_z LPCWSTR wzAttribute, | 42 | __in_z LPCWSTR wzAttribute, |
@@ -43,7 +47,6 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( | |||
43 | Assert(wzBundleId && wzAttribute); | 47 | Assert(wzBundleId && wzAttribute); |
44 | 48 | ||
45 | HRESULT hr = S_OK; | 49 | HRESULT hr = S_OK; |
46 | BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; | ||
47 | LPWSTR sczValue = NULL; | 50 | LPWSTR sczValue = NULL; |
48 | HKEY hkBundle = NULL; | 51 | HKEY hkBundle = NULL; |
49 | DWORD cchSource = 0; | 52 | DWORD cchSource = 0; |
@@ -55,8 +58,8 @@ extern "C" HRESULT DAPI BundleGetBundleInfo( | |||
55 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); | 58 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); |
56 | } | 59 | } |
57 | 60 | ||
58 | if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, &hkBundle)) && | 61 | if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, NULL, &hkBundle)) && |
59 | FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, &hkBundle))) | 62 | FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, NULL, &hkBundle))) |
60 | { | 63 | { |
61 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); | 64 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); |
62 | } | 65 | } |
@@ -108,7 +111,10 @@ LExit: | |||
108 | return hr; | 111 | return hr; |
109 | } | 112 | } |
110 | 113 | ||
111 | HRESULT DAPI BundleEnumRelatedBundle( | 114 | /******************************************************************** |
115 | ********************************************************************/ | ||
116 | |||
117 | extern "C" HRESULT DAPI BundleEnumRelatedBundle( | ||
112 | __in_z LPCWSTR wzUpgradeCode, | 118 | __in_z LPCWSTR wzUpgradeCode, |
113 | __in BUNDLE_INSTALL_CONTEXT context, | 119 | __in BUNDLE_INSTALL_CONTEXT context, |
114 | __inout PDWORD pdwStartIndex, | 120 | __inout PDWORD pdwStartIndex, |
@@ -231,11 +237,80 @@ LExit: | |||
231 | return hr; | 237 | return hr; |
232 | } | 238 | } |
233 | 239 | ||
240 | /******************************************************************** | ||
241 | BundleGetBundleVariable - Queries the bundle installation metadata for a given variable, | ||
242 | the caller is expected to free the memory returned vis psczValue | ||
243 | RETURNS: | ||
244 | S_OK | ||
245 | Success, if the variable had a value, it's returned in psczValue | ||
246 | E_INVALIDARG | ||
247 | An invalid parameter was passed to the function. | ||
248 | HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) | ||
249 | The bundle is not installed | ||
250 | HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) | ||
251 | The variable is unrecognized | ||
252 | E_NOTIMPL: | ||
253 | Tried to read a bundle variable for a type which has not been implemented | ||
254 | |||
255 | All other returns are unexpected returns from other dutil methods. | ||
256 | ********************************************************************/ | ||
257 | |||
258 | extern "C" HRESULT DAPI BundleGetBundleVariable( | ||
259 | __in_z LPCWSTR wzBundleId, | ||
260 | __in_z LPCWSTR wzVariable, | ||
261 | __deref_out_z LPWSTR * psczValue | ||
262 | ) | ||
263 | { | ||
264 | Assert(wzBundleId && wzVariable); | ||
265 | |||
266 | HRESULT hr = S_OK; | ||
267 | BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE; | ||
268 | HKEY hkBundle = NULL; | ||
269 | DWORD dwType = 0; | ||
270 | |||
271 | if (!wzBundleId || !wzVariable || !psczValue) | ||
272 | { | ||
273 | ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); | ||
274 | } | ||
275 | |||
276 | if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle)) && | ||
277 | FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle))) | ||
278 | { | ||
279 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key variable path."); | ||
280 | } | ||
281 | |||
282 | // If the bundle doesn't have the shared variable defined, return ERROR_UNKNOWN_PROPERTY | ||
283 | hr = RegGetType(hkBundle, wzVariable, &dwType); | ||
284 | ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) : hr, "Failed to locate bundle variable."); | ||
285 | |||
286 | switch (dwType) | ||
287 | { | ||
288 | case REG_SZ: | ||
289 | hr = RegReadString(hkBundle, wzVariable, psczValue); | ||
290 | ButilExitOnFailure(hr, "Failed to read string shared variable."); | ||
291 | break; | ||
292 | case REG_NONE: | ||
293 | hr = S_OK; | ||
294 | break; | ||
295 | default: | ||
296 | ButilExitOnFailure(hr = E_NOTIMPL, "Reading bundle variable of type 0x%x not implemented.", dwType); | ||
297 | |||
298 | } | ||
299 | |||
300 | LExit: | ||
301 | ReleaseRegKey(hkBundle); | ||
234 | 302 | ||
303 | return hr; | ||
304 | |||
305 | } | ||
306 | /******************************************************************** | ||
307 | * | ||
308 | ********************************************************************/ | ||
235 | HRESULT OpenBundleKey( | 309 | HRESULT OpenBundleKey( |
236 | __in_z LPCWSTR wzBundleId, | 310 | __in_z LPCWSTR wzBundleId, |
237 | __in BUNDLE_INSTALL_CONTEXT context, | 311 | __in BUNDLE_INSTALL_CONTEXT context, |
238 | __inout HKEY *key) | 312 | __in_opt LPCWSTR szSubKey, |
313 | __inout HKEY* key) | ||
239 | { | 314 | { |
240 | Assert(key && wzBundleId); | 315 | Assert(key && wzBundleId); |
241 | AssertSz(NULL == *key, "*key should be null"); | 316 | AssertSz(NULL == *key, "*key should be null"); |
@@ -244,9 +319,16 @@ HRESULT OpenBundleKey( | |||
244 | HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; | 319 | HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; |
245 | LPWSTR sczKeypath = NULL; | 320 | LPWSTR sczKeypath = NULL; |
246 | 321 | ||
247 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); | 322 | if (szSubKey) |
323 | { | ||
324 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId, szSubKey); | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId); | ||
329 | } | ||
248 | ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); | 330 | ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); |
249 | 331 | ||
250 | hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); | 332 | hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); |
251 | ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); | 333 | ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); |
252 | 334 | ||
@@ -255,3 +337,4 @@ LExit: | |||
255 | 337 | ||
256 | return hr; | 338 | return hr; |
257 | } | 339 | } |
340 | |||
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 @@ | |||
6 | extern "C" { | 6 | extern "C" { |
7 | #endif | 7 | #endif |
8 | 8 | ||
9 | enum BUNDLE_INSTALL_CONTEXT | 9 | typedef enum BUNDLE_INSTALL_CONTEXT |
10 | { | 10 | { |
11 | BUNDLE_INSTALL_CONTEXT_MACHINE, | 11 | BUNDLE_INSTALL_CONTEXT_MACHINE, |
12 | BUNDLE_INSTALL_CONTEXT_USER, | 12 | BUNDLE_INSTALL_CONTEXT_USER, |
13 | }; | 13 | } BUNDLE_INSTALL_CONTEXT; |
14 | 14 | ||
15 | 15 | ||
16 | /******************************************************************** | 16 | /******************************************************************** |
@@ -55,6 +55,13 @@ HRESULT DAPI BundleEnumRelatedBundle( | |||
55 | __out_ecount(MAX_GUID_CHARS+1) LPWSTR lpBundleIdBuf | 55 | __out_ecount(MAX_GUID_CHARS+1) LPWSTR lpBundleIdBuf |
56 | ); | 56 | ); |
57 | 57 | ||
58 | HRESULT DAPI BundleGetBundleVariable( | ||
59 | __in_z LPCWSTR wzBundleId, | ||
60 | __in_z LPCWSTR wzVariable, | ||
61 | __deref_out_z LPWSTR* psczValue | ||
62 | ); | ||
63 | |||
64 | |||
58 | #ifdef __cplusplus | 65 | #ifdef __cplusplus |
59 | } | 66 | } |
60 | #endif | 67 | #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( | |||
178 | __in_z_opt LPCWSTR wzName, | 178 | __in_z_opt LPCWSTR wzName, |
179 | __out DWORD64* pdw64Version | 179 | __out DWORD64* pdw64Version |
180 | ); | 180 | ); |
181 | HRESULT DAPI RegReadNone( | ||
182 | __in HKEY hk, | ||
183 | __in_z_opt LPCWSTR wzName | ||
184 | ); | ||
181 | HRESULT DAPI RegReadNumber( | 185 | HRESULT DAPI RegReadNumber( |
182 | __in HKEY hk, | 186 | __in HKEY hk, |
183 | __in_z_opt LPCWSTR wzName, | 187 | __in_z_opt LPCWSTR wzName, |
@@ -211,6 +215,10 @@ HRESULT DAPI RegWriteStringFormatted( | |||
211 | __in __format_string LPCWSTR szFormat, | 215 | __in __format_string LPCWSTR szFormat, |
212 | ... | 216 | ... |
213 | ); | 217 | ); |
218 | HRESULT DAPI RegWriteNone( | ||
219 | __in HKEY hk, | ||
220 | __in_z_opt LPCWSTR wzName | ||
221 | ); | ||
214 | HRESULT DAPI RegWriteNumber( | 222 | HRESULT DAPI RegWriteNumber( |
215 | __in HKEY hk, | 223 | __in HKEY hk, |
216 | __in_z_opt LPCWSTR wzName, | 224 | __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: | |||
672 | return hr; | 672 | return hr; |
673 | } | 673 | } |
674 | 674 | ||
675 | /******************************************************************** | ||
676 | RegReadNone - reads a NONE registry key value. | ||
677 | |||
678 | *********************************************************************/ | ||
679 | extern "C" HRESULT DAPI RegReadNone( | ||
680 | __in HKEY hk, | ||
681 | __in_z_opt LPCWSTR wzName) | ||
682 | { | ||
683 | HRESULT hr = S_OK; | ||
684 | DWORD er = ERROR_SUCCESS; | ||
685 | DWORD dwType = 0; | ||
686 | |||
687 | er = vpfnRegQueryValueExW(hk, wzName, NULL, &dwType, NULL, NULL); | ||
688 | if (E_FILENOTFOUND == HRESULT_FROM_WIN32(er)) | ||
689 | { | ||
690 | ExitFunction1(hr = E_FILENOTFOUND); | ||
691 | } | ||
692 | RegExitOnWin32Error(er, hr, "Failed to query registry key value."); | ||
693 | |||
694 | if (REG_NONE != dwType) | ||
695 | { | ||
696 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE); | ||
697 | RegExitOnRootFailure(hr, "Error reading version registry value due to unexpected data type: %u", dwType); | ||
698 | } | ||
699 | |||
700 | LExit: | ||
701 | return hr; | ||
702 | } | ||
675 | 703 | ||
676 | /******************************************************************** | 704 | /******************************************************************** |
677 | RegReadNumber - reads a DWORD registry key value as a number. | 705 | RegReadNumber - reads a DWORD registry key value as a number. |
@@ -886,6 +914,25 @@ LExit: | |||
886 | } | 914 | } |
887 | 915 | ||
888 | /******************************************************************** | 916 | /******************************************************************** |
917 | RegWriteNone - writes a registry key value as none. | ||
918 | |||
919 | *********************************************************************/ | ||
920 | extern "C" HRESULT DAPI RegWriteNone( | ||
921 | __in HKEY hk, | ||
922 | __in_z_opt LPCWSTR wzName | ||
923 | ) | ||
924 | { | ||
925 | HRESULT hr = S_OK; | ||
926 | DWORD er = ERROR_SUCCESS; | ||
927 | |||
928 | er = vpfnRegSetValueExW(hk, wzName, 0, REG_NONE, NULL, NULL); | ||
929 | RegExitOnWin32Error(er, hr, "Failed to set %ls value.", wzName); | ||
930 | |||
931 | LExit: | ||
932 | return hr; | ||
933 | } | ||
934 | |||
935 | /******************************************************************** | ||
889 | RegWriteNumber - writes a registry key value as a number. | 936 | RegWriteNumber - writes a registry key value as a number. |
890 | 937 | ||
891 | *********************************************************************/ | 938 | *********************************************************************/ |