aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/butil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/butil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/butil.cpp192
1 files changed, 118 insertions, 74 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp
index cda2a658..ca73f0c3 100644
--- a/src/libs/dutil/WixToolset.DUtil/butil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp
@@ -8,6 +8,7 @@
8#define ButilExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__) 8#define ButilExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__)
9#define ButilExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__) 9#define ButilExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__)
10#define ButilExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__) 10#define ButilExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__)
11#define ButilExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_BUTIL, x, e, s, __VA_ARGS__)
11#define ButilExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__) 12#define ButilExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_BUTIL, x, s, __VA_ARGS__)
12#define ButilExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_BUTIL, p, x, e, s, __VA_ARGS__) 13#define ButilExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_BUTIL, p, x, e, s, __VA_ARGS__)
13#define ButilExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_BUTIL, p, x, s, __VA_ARGS__) 14#define ButilExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_BUTIL, p, x, s, __VA_ARGS__)
@@ -22,8 +23,30 @@ const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = L"BundleUpgrade
22const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey"; 23const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = L"BundleProviderKey";
23const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY = L"variables"; 24const LPCWSTR BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY = L"variables";
24 25
26enum INTERNAL_BUNDLE_STATUS
27{
28 INTERNAL_BUNDLE_STATUS_SUCCESS,
29 INTERNAL_BUNDLE_STATUS_UNKNOWN_BUNDLE,
30 INTERNAL_BUNDLE_STATUS_UNKNOWN_PROPERTY,
31};
32
25// Forward declarations. 33// Forward declarations.
26/******************************************************************** 34/********************************************************************
35LocateAndQueryBundleValue - Locates the requested key for the bundle,
36 then queries the registry type for requested value.
37
38NOTE: caller is responsible for closing key
39********************************************************************/
40static HRESULT LocateAndQueryBundleValue(
41 __in_z LPCWSTR wzBundleId,
42 __in_opt LPCWSTR wzSubKey,
43 __in LPCWSTR wzValueName,
44 __inout HKEY* phKey,
45 __inout DWORD* pdwType,
46 __out INTERNAL_BUNDLE_STATUS* pStatus
47 );
48
49/********************************************************************
27OpenBundleKey - Opens the bundle uninstallation key for a given bundle 50OpenBundleKey - Opens the bundle uninstallation key for a given bundle
28 51
29NOTE: caller is responsible for closing key 52NOTE: caller is responsible for closing key
@@ -31,43 +54,44 @@ NOTE: caller is responsible for closing key
31static HRESULT OpenBundleKey( 54static HRESULT OpenBundleKey(
32 __in_z LPCWSTR wzBundleId, 55 __in_z LPCWSTR wzBundleId,
33 __in BUNDLE_INSTALL_CONTEXT context, 56 __in BUNDLE_INSTALL_CONTEXT context,
34 __in_opt LPCWSTR szSubKey, 57 __in_opt LPCWSTR wzSubKey,
35 __inout HKEY* key); 58 __inout HKEY* phKey
59 );
36 60
37/******************************************************************** 61DAPI_(HRESULT) BundleGetBundleInfo(
38BundleGetBundleInfo - Read the registration data for a gven bundle 62 __in_z LPCWSTR wzBundleId,
39********************************************************************/ 63 __in_z LPCWSTR wzAttribute,
40extern "C" HRESULT DAPI BundleGetBundleInfo( 64 __out_ecount_opt(*pcchValueBuf) LPWSTR lpValueBuf,
41 __in_z LPCWSTR wzBundleId, 65 __inout_opt LPDWORD pcchValueBuf
42 __in_z LPCWSTR wzAttribute, 66 )
43 __out_ecount_opt(*pcchValueBuf) LPWSTR lpValueBuf,
44 __inout_opt LPDWORD pcchValueBuf
45 )
46{ 67{
47 Assert(wzBundleId && wzAttribute); 68 Assert(wzBundleId && wzAttribute);
48 69
49 HRESULT hr = S_OK; 70 HRESULT hr = S_OK;
50 LPWSTR sczValue = NULL; 71 LPWSTR sczValue = NULL;
51 HKEY hkBundle = NULL; 72 HKEY hkBundle = NULL;
73 INTERNAL_BUNDLE_STATUS status = INTERNAL_BUNDLE_STATUS_SUCCESS;
52 DWORD cchSource = 0; 74 DWORD cchSource = 0;
53 DWORD dwType = 0; 75 DWORD dwType = 0;
54 DWORD dwValue = 0; 76 DWORD dwValue = 0;
55 77
56 if ((lpValueBuf && !pcchValueBuf) || !wzBundleId || !wzAttribute) 78 if ((lpValueBuf && !pcchValueBuf) || !wzBundleId || !wzAttribute)
57 { 79 {
58 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); 80 ButilExitWithRootFailure(hr, E_INVALIDARG, "An invalid parameter was passed to the function.");
59 } 81 }
60 82
61 if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, NULL, &hkBundle)) && 83 hr = LocateAndQueryBundleValue(wzBundleId, NULL, wzAttribute, &hkBundle, &dwType, &status);
62 FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, NULL, &hkBundle))) 84 ButilExitOnFailure(hr, "Failed to locate and query bundle attribute.");
85
86 switch (status)
63 { 87 {
64 ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key path."); 88 case INTERNAL_BUNDLE_STATUS_UNKNOWN_BUNDLE:
89 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT));
90 case INTERNAL_BUNDLE_STATUS_UNKNOWN_PROPERTY:
91 // If the bundle doesn't have the property defined, return ERROR_UNKNOWN_PROPERTY
92 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY));
65 } 93 }
66 94
67 // If the bundle doesn't have the property defined, return ERROR_UNKNOWN_PROPERTY
68 hr = RegGetType(hkBundle, wzAttribute, &dwType);
69 ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) : hr, "Failed to locate bundle property.");
70
71 switch (dwType) 95 switch (dwType)
72 { 96 {
73 case REG_SZ: 97 case REG_SZ:
@@ -82,12 +106,11 @@ extern "C" HRESULT DAPI BundleGetBundleInfo(
82 ButilExitOnFailure(hr, "Failed to format dword property as string."); 106 ButilExitOnFailure(hr, "Failed to format dword property as string.");
83 break; 107 break;
84 default: 108 default:
85 ButilExitOnFailure(hr = E_NOTIMPL, "Reading bundle info of type 0x%x not implemented.", dwType); 109 ButilExitWithRootFailure(hr, E_NOTIMPL, "Reading bundle info of type 0x%x not implemented.", dwType);
86
87 } 110 }
88 111
89 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchSource)); 112 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchSource));
90 ButilExitOnFailure(hr, "Failed to calculate length of string"); 113 ButilExitOnRootFailure(hr, "Failed to calculate length of string.");
91 114
92 if (lpValueBuf) 115 if (lpValueBuf)
93 { 116 {
@@ -95,11 +118,11 @@ extern "C" HRESULT DAPI BundleGetBundleInfo(
95 if (*pcchValueBuf <= cchSource) 118 if (*pcchValueBuf <= cchSource)
96 { 119 {
97 *pcchValueBuf = ++cchSource; 120 *pcchValueBuf = ++cchSource;
98 ButilExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA), "A buffer is too small to hold the requested data."); 121 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA));
99 } 122 }
100 123
101 hr = ::StringCchCatNExW(lpValueBuf, *pcchValueBuf, sczValue, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); 124 hr = ::StringCchCatNExW(lpValueBuf, *pcchValueBuf, sczValue, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
102 ButilExitOnFailure(hr, "Failed to copy the property value to the output buffer."); 125 ButilExitOnRootFailure(hr, "Failed to copy the property value to the output buffer.");
103 126
104 *pcchValueBuf = cchSource++; 127 *pcchValueBuf = cchSource++;
105 } 128 }
@@ -111,10 +134,8 @@ LExit:
111 return hr; 134 return hr;
112} 135}
113 136
114/********************************************************************
115********************************************************************/
116 137
117extern "C" HRESULT DAPI BundleEnumRelatedBundle( 138DAPI_(HRESULT) BundleEnumRelatedBundle(
118 __in_z LPCWSTR wzUpgradeCode, 139 __in_z LPCWSTR wzUpgradeCode,
119 __in BUNDLE_INSTALL_CONTEXT context, 140 __in BUNDLE_INSTALL_CONTEXT context,
120 __inout PDWORD pdwStartIndex, 141 __inout PDWORD pdwStartIndex,
@@ -170,6 +191,7 @@ extern "C" HRESULT DAPI BundleEnumRelatedBundle(
170 case REG_SZ: 191 case REG_SZ:
171 hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue); 192 hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
172 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property."); 193 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
194
173 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1)) 195 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
174 { 196 {
175 *pdwStartIndex = dwIndex; 197 *pdwStartIndex = dwIndex;
@@ -202,8 +224,7 @@ extern "C" HRESULT DAPI BundleEnumRelatedBundle(
202 break; 224 break;
203 225
204 default: 226 default:
205 ButilExitOnFailure(hr = E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType); 227 ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
206
207 } 228 }
208 229
209 if (fUpgradeCodeFound) 230 if (fUpgradeCodeFound)
@@ -211,10 +232,10 @@ extern "C" HRESULT DAPI BundleEnumRelatedBundle(
211 if (lpBundleIdBuf) 232 if (lpBundleIdBuf)
212 { 233 {
213 hr = ::StringCchLengthW(sczUninstallSubKey, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchUninstallSubKey)); 234 hr = ::StringCchLengthW(sczUninstallSubKey, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchUninstallSubKey));
214 ButilExitOnFailure(hr, "Failed to calculate length of string"); 235 ButilExitOnRootFailure(hr, "Failed to calculate length of string");
215 236
216 hr = ::StringCchCopyNExW(lpBundleIdBuf, MAX_GUID_CHARS + 1, sczUninstallSubKey, cchUninstallSubKey, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); 237 hr = ::StringCchCopyNExW(lpBundleIdBuf, MAX_GUID_CHARS + 1, sczUninstallSubKey, cchUninstallSubKey, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
217 ButilExitOnFailure(hr, "Failed to copy the property value to the output buffer."); 238 ButilExitOnRootFailure(hr, "Failed to copy the property value to the output buffer.");
218 } 239 }
219 240
220 break; 241 break;
@@ -237,52 +258,37 @@ LExit:
237 return hr; 258 return hr;
238} 259}
239 260
240/********************************************************************
241BundleGetBundleVariable - Queries the bundle installation metadata for a given variable,
242the caller is expected to free the memory returned vis psczValue
243RETURNS:
244S_OK
245 Success, if the variable had a value, it's returned in psczValue
246E_INVALIDARG
247 An invalid parameter was passed to the function.
248HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT)
249 The bundle is not installed
250HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY)
251 The variable is unrecognized
252E_NOTIMPL:
253 Tried to read a bundle variable for a type which has not been implemented
254
255All other returns are unexpected returns from other dutil methods.
256********************************************************************/
257 261
258extern "C" HRESULT DAPI BundleGetBundleVariable( 262DAPI_(HRESULT) BundleGetBundleVariable(
259 __in_z LPCWSTR wzBundleId, 263 __in_z LPCWSTR wzBundleId,
260 __in_z LPCWSTR wzVariable, 264 __in_z LPCWSTR wzVariable,
261 __deref_out_z LPWSTR * psczValue 265 __deref_out_z LPWSTR* psczValue
262) 266 )
263{ 267{
264 Assert(wzBundleId && wzVariable); 268 Assert(wzBundleId && wzVariable);
265 269
266 HRESULT hr = S_OK; 270 HRESULT hr = S_OK;
267 BUNDLE_INSTALL_CONTEXT context = BUNDLE_INSTALL_CONTEXT_MACHINE;
268 HKEY hkBundle = NULL; 271 HKEY hkBundle = NULL;
272 INTERNAL_BUNDLE_STATUS status = INTERNAL_BUNDLE_STATUS_SUCCESS;
269 DWORD dwType = 0; 273 DWORD dwType = 0;
270 274
271 if (!wzBundleId || !wzVariable || !psczValue) 275 if (!wzBundleId || !wzVariable || !psczValue)
272 { 276 {
273 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); 277 ButilExitWithRootFailure(hr, E_INVALIDARG, "An invalid parameter was passed to the function.");
274 } 278 }
275 279
276 if (FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_MACHINE, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle)) && 280 hr = LocateAndQueryBundleValue(wzBundleId, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, wzVariable, &hkBundle, &dwType, &status);
277 FAILED(hr = OpenBundleKey(wzBundleId, context = BUNDLE_INSTALL_CONTEXT_USER, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_VARIABLE_KEY, &hkBundle))) 281 ButilExitOnFailure(hr, "Failed to locate and query bundle variable.");
282
283 switch (status)
278 { 284 {
279 ButilExitOnFailure(E_FILENOTFOUND == hr ? HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) : hr, "Failed to locate bundle uninstall key variable path."); 285 case INTERNAL_BUNDLE_STATUS_UNKNOWN_BUNDLE:
286 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT));
287 case INTERNAL_BUNDLE_STATUS_UNKNOWN_PROPERTY:
288 // If the bundle doesn't have the shared variable defined, return ERROR_UNKNOWN_PROPERTY
289 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY));
280 } 290 }
281 291
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) 292 switch (dwType)
287 { 293 {
288 case REG_SZ: 294 case REG_SZ:
@@ -293,35 +299,74 @@ extern "C" HRESULT DAPI BundleGetBundleVariable(
293 hr = S_OK; 299 hr = S_OK;
294 break; 300 break;
295 default: 301 default:
296 ButilExitOnFailure(hr = E_NOTIMPL, "Reading bundle variable of type 0x%x not implemented.", dwType); 302 ButilExitWithRootFailure(hr, E_NOTIMPL, "Reading bundle variable of type 0x%x not implemented.", dwType);
297
298 } 303 }
299 304
300LExit: 305LExit:
301 ReleaseRegKey(hkBundle); 306 ReleaseRegKey(hkBundle);
302 307
303 return hr; 308 return hr;
309}
310
311static HRESULT LocateAndQueryBundleValue(
312 __in_z LPCWSTR wzBundleId,
313 __in_opt LPCWSTR wzSubKey,
314 __in LPCWSTR wzValueName,
315 __inout HKEY* phKey,
316 __inout DWORD* pdwType,
317 __out INTERNAL_BUNDLE_STATUS* pStatus
318 )
319{
320 HRESULT hr = S_OK;
321
322 *pStatus = INTERNAL_BUNDLE_STATUS_SUCCESS;
304 323
324 if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, wzSubKey, phKey)) &&
325 FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, wzSubKey, phKey)))
326 {
327 if (E_FILENOTFOUND == hr)
328 {
329 *pStatus = INTERNAL_BUNDLE_STATUS_UNKNOWN_BUNDLE;
330 ExitFunction1(hr = S_OK);
331 }
332
333 ButilExitOnFailure(hr, "Failed to open bundle key.");
334 }
335
336 // If the bundle doesn't have the value defined, return ERROR_UNKNOWN_PROPERTY
337 hr = RegGetType(*phKey, wzValueName, pdwType);
338 if (FAILED(hr))
339 {
340 if (E_FILENOTFOUND == hr)
341 {
342 *pStatus = INTERNAL_BUNDLE_STATUS_UNKNOWN_PROPERTY;
343 ExitFunction1(hr = S_OK);
344 }
345
346 ButilExitOnFailure(hr, "Failed to read bundle value.");
347 }
348
349LExit:
350 return hr;
305} 351}
306/******************************************************************** 352
307* 353static HRESULT OpenBundleKey(
308********************************************************************/
309HRESULT OpenBundleKey(
310 __in_z LPCWSTR wzBundleId, 354 __in_z LPCWSTR wzBundleId,
311 __in BUNDLE_INSTALL_CONTEXT context, 355 __in BUNDLE_INSTALL_CONTEXT context,
312 __in_opt LPCWSTR szSubKey, 356 __in_opt LPCWSTR wzSubKey,
313 __inout HKEY* key) 357 __inout HKEY* phKey
358 )
314{ 359{
315 Assert(key && wzBundleId); 360 Assert(phKey && wzBundleId);
316 AssertSz(NULL == *key, "*key should be null"); 361 AssertSz(NULL == *phKey, "*key should be null");
317 362
318 HRESULT hr = S_OK; 363 HRESULT hr = S_OK;
319 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 364 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
320 LPWSTR sczKeypath = NULL; 365 LPWSTR sczKeypath = NULL;
321 366
322 if (szSubKey) 367 if (wzSubKey)
323 { 368 {
324 hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId, szSubKey); 369 hr = StrAllocFormatted(&sczKeypath, L"%ls\\%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, wzBundleId, wzSubKey);
325 } 370 }
326 else 371 else
327 { 372 {
@@ -329,7 +374,7 @@ HRESULT OpenBundleKey(
329 } 374 }
330 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); 375 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
331 376
332 hr = RegOpen(hkRoot, sczKeypath, KEY_READ, key); 377 hr = RegOpen(hkRoot, sczKeypath, KEY_READ, phKey);
333 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); 378 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
334 379
335LExit: 380LExit:
@@ -337,4 +382,3 @@ LExit:
337 382
338 return hr; 383 return hr;
339} 384}
340