From 273c69f34311f4f4e5f6b5896e71d0788f12d96a Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sat, 17 Oct 2020 19:12:21 -0500 Subject: WIXFEAT:6210 Change data type of versions to strings. --- src/engine/EngineForApplication.cpp | 118 ++++++++++++++++++------------------ src/engine/EngineForExtension.cpp | 118 ++++++++++++++++++------------------ src/engine/condition.cpp | 88 +++++++++++---------------- src/engine/dependency.cpp | 10 +-- src/engine/detect.cpp | 40 +++++++----- src/engine/elevation.cpp | 11 +++- src/engine/engine.vcxproj | 4 +- src/engine/logging.cpp | 17 ------ src/engine/logging.h | 5 -- src/engine/msiengine.cpp | 94 +++++++++++++++++----------- src/engine/package.h | 8 +-- src/engine/packages.config | 2 +- src/engine/plan.cpp | 10 ++- src/engine/plan.h | 2 +- src/engine/precomp.h | 1 + src/engine/registration.cpp | 12 ++-- src/engine/registration.h | 4 +- src/engine/relatedbundle.cpp | 9 ++- src/engine/search.cpp | 9 ++- src/engine/userexperience.cpp | 24 ++++---- src/engine/userexperience.h | 12 ++-- src/engine/variable.cpp | 75 ++++++++++++++--------- src/engine/variable.h | 4 +- src/engine/variant.cpp | 71 +++++++++++----------- src/engine/variant.h | 6 +- 25 files changed, 391 insertions(+), 363 deletions(-) (limited to 'src/engine') diff --git a/src/engine/EngineForApplication.cpp b/src/engine/EngineForApplication.cpp index 81eec2fc..d034c2bf 100644 --- a/src/engine/EngineForApplication.cpp +++ b/src/engine/EngineForApplication.cpp @@ -2,6 +2,13 @@ #include "precomp.h" + +static HRESULT CopyStringToBA( + __in LPWSTR wzValue, + __in LPWSTR wzBuffer, + __inout DWORD* pcchBuffer + ); + static HRESULT BAEngineGetPackageCount( __in BOOTSTRAPPER_ENGINE_CONTEXT* pContext, __in BAENGINE_GETPACKAGECOUNT_ARGS* /*pArgs*/, @@ -46,7 +53,6 @@ static HRESULT BAEngineGetVariableString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - size_t cchRemaining = 0; LPCWSTR wzVariable = pArgs->wzVariable; LPWSTR wzValue = pResults->wzValue; DWORD* pcchValue = &pResults->cchValue; @@ -56,24 +62,7 @@ static HRESULT BAEngineGetVariableString( hr = VariableGetString(&pContext->pEngineState->variables, wzVariable, &sczValue); if (SUCCEEDED(hr)) { - if (wzValue) - { - hr = ::StringCchCopyExW(wzValue, *pcchValue, sczValue, NULL, &cchRemaining, STRSAFE_FILL_BEHIND_NULL); - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchValue = cchRemaining + 1; - } - } - else - { - hr = E_MOREDATA; - - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchValue = cchRemaining + 1; - } + hr = CopyStringToBA(sczValue, wzValue, pcchValue); } } else @@ -92,18 +81,26 @@ static HRESULT BAEngineGetVariableVersion( ) { HRESULT hr = S_OK; + VERUTIL_VERSION* pVersion = NULL; LPCWSTR wzVariable = pArgs->wzVariable; - DWORD64* pqwValue = &pResults->qwValue; + LPWSTR wzValue = pResults->wzValue; + DWORD* pcchValue = &pResults->cchValue; if (wzVariable && *wzVariable) { - hr = VariableGetVersion(&pContext->pEngineState->variables, wzVariable, pqwValue); + hr = VariableGetVersion(&pContext->pEngineState->variables, wzVariable, &pVersion); + if (SUCCEEDED(hr)) + { + hr = CopyStringToBA(pVersion->sczVersion, wzValue, pcchValue); + } } else { hr = E_INVALIDARG; } + ReleaseVerutilVersion(pVersion); + return hr; } @@ -115,33 +112,16 @@ static HRESULT BAEngineFormatString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - DWORD cchValue = 0; LPCWSTR wzIn = pArgs->wzIn; LPWSTR wzOut = pResults->wzOut; DWORD* pcchOut = &pResults->cchOut; if (wzIn && *wzIn) { - hr = VariableFormatString(&pContext->pEngineState->variables, wzIn, &sczValue, &cchValue); + hr = VariableFormatString(&pContext->pEngineState->variables, wzIn, &sczValue, NULL); if (SUCCEEDED(hr)) { - if (wzOut) - { - hr = ::StringCchCopyExW(wzOut, *pcchOut, sczValue, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); - if (FAILED(hr)) - { - *pcchOut = cchValue; - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - } - } - } - else - { - hr = E_MOREDATA; - *pcchOut = cchValue; - } + hr = CopyStringToBA(sczValue, wzOut, pcchOut); } } else @@ -161,7 +141,6 @@ static HRESULT BAEngineEscapeString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - size_t cchRemaining = 0; LPCWSTR wzIn = pArgs->wzIn; LPWSTR wzOut = pResults->wzOut; DWORD* pcchOut = &pResults->cchOut; @@ -171,21 +150,7 @@ static HRESULT BAEngineEscapeString( hr = VariableEscapeString(wzIn, &sczValue); if (SUCCEEDED(hr)) { - if (wzOut) - { - hr = ::StringCchCopyExW(wzOut, *pcchOut, sczValue, NULL, &cchRemaining, STRSAFE_FILL_BEHIND_NULL); - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchOut = cchRemaining; - } - } - else - { - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchOut = cchRemaining; - } + hr = CopyStringToBA(sczValue, wzOut, pcchOut); } } else @@ -613,11 +578,15 @@ static HRESULT BAEngineSetVariableVersion( { HRESULT hr = S_OK; LPCWSTR wzVariable = pArgs->wzVariable; - DWORD64 qwValue = pArgs->qwValue; + LPCWSTR wzValue = pArgs->wzValue; + VERUTIL_VERSION* pVersion = NULL; if (wzVariable && *wzVariable) { - hr = VariableSetVersion(&pContext->pEngineState->variables, wzVariable, qwValue, FALSE); + hr = VerParseVersion(wzValue, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to parse new version value."); + + hr = VariableSetVersion(&pContext->pEngineState->variables, wzVariable, pVersion, FALSE); ExitOnFailure(hr, "Failed to set version variable."); } else @@ -627,6 +596,8 @@ static HRESULT BAEngineSetVariableVersion( } LExit: + ReleaseVerutilVersion(pVersion); + return hr; } @@ -898,3 +869,34 @@ HRESULT WINAPI EngineForApplicationProc( LExit: return hr; } + +static HRESULT CopyStringToBA( + __in LPWSTR wzValue, + __in LPWSTR wzBuffer, + __inout DWORD* pcchBuffer + ) +{ + HRESULT hr = S_OK; + BOOL fTooSmall = !wzBuffer; + + if (!fTooSmall) + { + hr = ::StringCchCopyExW(wzBuffer, *pcchBuffer, wzValue, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); + if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) + { + fTooSmall = TRUE; + } + } + + if (fTooSmall) + { + hr = ::StringCchLengthW(wzValue, STRSAFE_MAX_CCH, reinterpret_cast(pcchBuffer)); + if (SUCCEEDED(hr)) + { + hr = E_MOREDATA; + *pcchBuffer += 1; // null terminator. + } + } + + return hr; +} diff --git a/src/engine/EngineForExtension.cpp b/src/engine/EngineForExtension.cpp index fdfa59b1..6ec80a0f 100644 --- a/src/engine/EngineForExtension.cpp +++ b/src/engine/EngineForExtension.cpp @@ -2,6 +2,13 @@ #include "precomp.h" + +static HRESULT CopyStringToBE( + __in LPWSTR wzValue, + __in LPWSTR wzBuffer, + __inout DWORD* pcchBuffer + ); + static HRESULT BEEngineEscapeString( __in BURN_EXTENSION_ENGINE_CONTEXT* /*pContext*/, __in BUNDLE_EXTENSION_ENGINE_ESCAPESTRING_ARGS* pArgs, @@ -10,7 +17,6 @@ static HRESULT BEEngineEscapeString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - size_t cchRemaining = 0; LPCWSTR wzIn = pArgs->wzIn; LPWSTR wzOut = pResults->wzOut; DWORD* pcchOut = &pResults->cchOut; @@ -20,21 +26,7 @@ static HRESULT BEEngineEscapeString( hr = VariableEscapeString(wzIn, &sczValue); if (SUCCEEDED(hr)) { - if (wzOut) - { - hr = ::StringCchCopyExW(wzOut, *pcchOut, sczValue, NULL, &cchRemaining, STRSAFE_FILL_BEHIND_NULL); - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchOut = cchRemaining; - } - } - else - { - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchOut = cchRemaining; - } + hr = CopyStringToBE(sczValue, wzOut, pcchOut); } } else @@ -76,33 +68,16 @@ static HRESULT BEEngineFormatString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - DWORD cchValue = 0; LPCWSTR wzIn = pArgs->wzIn; LPWSTR wzOut = pResults->wzOut; DWORD* pcchOut = &pResults->cchOut; if (wzIn && *wzIn) { - hr = VariableFormatString(&pContext->pEngineState->variables, wzIn, &sczValue, &cchValue); + hr = VariableFormatString(&pContext->pEngineState->variables, wzIn, &sczValue, NULL); if (SUCCEEDED(hr)) { - if (wzOut) - { - hr = ::StringCchCopyExW(wzOut, *pcchOut, sczValue, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); - if (FAILED(hr)) - { - *pcchOut = cchValue; - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - } - } - } - else - { - hr = E_MOREDATA; - *pcchOut = cchValue; - } + hr = CopyStringToBE(sczValue, wzOut, pcchOut); } } else @@ -144,7 +119,6 @@ static HRESULT BEEngineGetVariableString( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; - size_t cchRemaining = 0; LPCWSTR wzVariable = pArgs->wzVariable; LPWSTR wzValue = pResults->wzValue; DWORD* pcchValue = &pResults->cchValue; @@ -154,24 +128,7 @@ static HRESULT BEEngineGetVariableString( hr = VariableGetString(&pContext->pEngineState->variables, wzVariable, &sczValue); if (SUCCEEDED(hr)) { - if (wzValue) - { - hr = ::StringCchCopyExW(wzValue, *pcchValue, sczValue, NULL, &cchRemaining, STRSAFE_FILL_BEHIND_NULL); - if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) - { - hr = E_MOREDATA; - - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchValue = cchRemaining + 1; - } - } - else - { - hr = E_MOREDATA; - - ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchRemaining); - *pcchValue = cchRemaining + 1; - } + hr = CopyStringToBE(sczValue, wzValue, pcchValue); } } else @@ -190,18 +147,26 @@ static HRESULT BEEngineGetVariableVersion( ) { HRESULT hr = S_OK; + VERUTIL_VERSION* pVersion = NULL; LPCWSTR wzVariable = pArgs->wzVariable; - DWORD64* pqwValue = &pResults->qwValue; + LPWSTR wzValue = pResults->wzValue; + DWORD* pcchValue = &pResults->cchValue; if (wzVariable && *wzVariable) { - hr = VariableGetVersion(&pContext->pEngineState->variables, wzVariable, pqwValue); + hr = VariableGetVersion(&pContext->pEngineState->variables, wzVariable, &pVersion); + if (SUCCEEDED(hr)) + { + hr = CopyStringToBE(pVersion->sczVersion, wzValue, pcchValue); + } } else { hr = E_INVALIDARG; } + ReleaseVerutilVersion(pVersion); + return hr; } @@ -303,11 +268,15 @@ static HRESULT BEEngineSetVariableVersion( { HRESULT hr = S_OK; LPCWSTR wzVariable = pArgs->wzVariable; - DWORD64 qwValue = pArgs->qwValue; + LPCWSTR wzValue = pArgs->wzValue; + VERUTIL_VERSION* pVersion = NULL; if (wzVariable && *wzVariable) { - hr = VariableSetVersion(&pContext->pEngineState->variables, wzVariable, qwValue, FALSE); + hr = VerParseVersion(wzValue, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to parse new version value."); + + hr = VariableSetVersion(&pContext->pEngineState->variables, wzVariable, pVersion, FALSE); ExitOnFailure(hr, "Failed to set version variable."); } else @@ -317,6 +286,8 @@ static HRESULT BEEngineSetVariableVersion( } LExit: + ReleaseVerutilVersion(pVersion); + return hr; } @@ -375,3 +346,34 @@ HRESULT WINAPI EngineForExtensionProc( LExit: return hr; } + +static HRESULT CopyStringToBE( + __in LPWSTR wzValue, + __in LPWSTR wzBuffer, + __inout DWORD* pcchBuffer + ) +{ + HRESULT hr = S_OK; + BOOL fTooSmall = !wzBuffer; + + if (!fTooSmall) + { + hr = ::StringCchCopyExW(wzBuffer, *pcchBuffer, wzValue, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); + if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) + { + fTooSmall = TRUE; + } + } + + if (fTooSmall) + { + hr = ::StringCchLengthW(wzValue, STRSAFE_MAX_CCH, reinterpret_cast(pcchBuffer)); + if (SUCCEEDED(hr)) + { + hr = E_MOREDATA; + *pcchBuffer += 1; // null terminator. + } + } + + return hr; +} diff --git a/src/engine/condition.cpp b/src/engine/condition.cpp index cd346680..32a7a0b8 100644 --- a/src/engine/condition.cpp +++ b/src/engine/condition.cpp @@ -123,8 +123,8 @@ static HRESULT CompareIntegerValues( ); static HRESULT CompareVersionValues( __in BURN_SYMBOL_TYPE comparison, - __in DWORD64 qwLeftOperand, - __in DWORD64 qwRightOperand, + __in VERUTIL_VERSION* pLeftOperand, + __in VERUTIL_VERSION* pRightOperand, __out BOOL* pfResult ); @@ -379,7 +379,7 @@ static HRESULT ParseTerm( { LONGLONG llValue = 0; LPWSTR sczValue = NULL; - DWORD64 qwValue = 0; + VERUTIL_VERSION* pVersion = NULL; switch (firstValue.Type) { case BURN_VARIANT_TYPE_NONE: @@ -402,12 +402,12 @@ static HRESULT ParseTerm( SecureZeroMemory(&llValue, sizeof(llValue)); break; case BURN_VARIANT_TYPE_VERSION: - hr = BVariantGetVersion(&firstValue, &qwValue); + hr = BVariantGetVersion(&firstValue, &pVersion); if (SUCCEEDED(hr)) { - *pf = 0 != qwValue; + *pf = 0 != *pVersion->sczVersion; } - SecureZeroMemory(&llValue, sizeof(qwValue)); + ReleaseVerutilVersion(pVersion); break; default: ExitFunction1(hr = E_UNEXPECTED); @@ -689,33 +689,14 @@ static HRESULT NextSymbol( if (L'v' == pContext->wzRead[0] && C1_DIGIT & charType) { // version - DWORD cParts = 1; - for (;;) + do { ++n; - if (L'.' == pContext->wzRead[n]) - { - ++cParts; - if (4 < cParts) - { - // error, too many parts in version - pContext->fError = TRUE; - hr = E_INVALIDDATA; - ExitOnRootFailure(hr, "Failed to parse condition \"%ls\". Version can have a maximum of 4 parts, at position %d.", pContext->wzCondition, iPosition); - } - } - else - { - ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType); - if (C1_DIGIT != (C1_DIGIT & charType)) - { - break; - } - } - } + ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType); + } while (L'\0' != pContext->wzRead[n] && C1_BLANK != (C1_BLANK & charType)); // Symbols don't encrypt their value, so can access the value directly. - hr = FileVersionFromStringEx(&pContext->wzRead[1], n - 1, &pContext->NextSymbol.Value.qwValue); + hr = VerParseVersion(&pContext->wzRead[1], n - 1, FALSE, &pContext->NextSymbol.Value.pValue); if (FAILED(hr)) { pContext->fError = TRUE; @@ -785,10 +766,10 @@ static HRESULT CompareValues( { HRESULT hr = S_OK; LONGLONG llLeft = 0; - DWORD64 qwLeft = 0; + VERUTIL_VERSION* pVersionLeft = 0; LPWSTR sczLeft = NULL; LONGLONG llRight = 0; - DWORD64 qwRight = 0; + VERUTIL_VERSION* pVersionRight = 0; LPWSTR sczRight = NULL; // get values to compare based on type @@ -810,17 +791,17 @@ static HRESULT CompareValues( } else if (BURN_VARIANT_TYPE_VERSION == leftOperand.Type && BURN_VARIANT_TYPE_VERSION == rightOperand.Type) { - hr = BVariantGetVersion(&leftOperand, &qwLeft); + hr = BVariantGetVersion(&leftOperand, &pVersionLeft); ExitOnFailure(hr, "Failed to get the left version"); - hr = BVariantGetVersion(&rightOperand, &qwRight); + hr = BVariantGetVersion(&rightOperand, &pVersionRight); ExitOnFailure(hr, "Failed to get the right version"); - hr = CompareVersionValues(comparison, qwLeft, qwRight, pfResult); + hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); } else if (BURN_VARIANT_TYPE_VERSION == leftOperand.Type && BURN_VARIANT_TYPE_STRING == rightOperand.Type) { - hr = BVariantGetVersion(&leftOperand, &qwLeft); + hr = BVariantGetVersion(&leftOperand, &pVersionLeft); ExitOnFailure(hr, "Failed to get the left version"); - hr = BVariantGetVersion(&rightOperand, &qwRight); + hr = BVariantGetVersion(&rightOperand, &pVersionRight); if (FAILED(hr)) { if (DISP_E_TYPEMISMATCH != hr) @@ -832,14 +813,14 @@ static HRESULT CompareValues( } else { - hr = CompareVersionValues(comparison, qwLeft, qwRight, pfResult); + hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); } } else if (BURN_VARIANT_TYPE_STRING == leftOperand.Type && BURN_VARIANT_TYPE_VERSION == rightOperand.Type) { - hr = BVariantGetVersion(&rightOperand, &qwRight); + hr = BVariantGetVersion(&rightOperand, &pVersionRight); ExitOnFailure(hr, "Failed to get the right version"); - hr = BVariantGetVersion(&leftOperand, &qwLeft); + hr = BVariantGetVersion(&leftOperand, &pVersionLeft); if (FAILED(hr)) { if (DISP_E_TYPEMISMATCH != hr) @@ -851,7 +832,7 @@ static HRESULT CompareValues( } else { - hr = CompareVersionValues(comparison, qwLeft, qwRight, pfResult); + hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); } } else if (BURN_VARIANT_TYPE_NUMERIC == leftOperand.Type && BURN_VARIANT_TYPE_STRING == rightOperand.Type) @@ -899,10 +880,10 @@ static HRESULT CompareValues( } LExit: - SecureZeroMemory(&qwLeft, sizeof(DWORD64)); + ReleaseVerutilVersion(pVersionLeft); SecureZeroMemory(&llLeft, sizeof(LONGLONG)); StrSecureZeroFreeString(sczLeft); - SecureZeroMemory(&qwRight, sizeof(DWORD64)); + ReleaseVerutilVersion(pVersionRight); SecureZeroMemory(&llRight, sizeof(LONGLONG)); StrSecureZeroFreeString(sczRight); @@ -1010,24 +991,25 @@ LExit: // static HRESULT CompareVersionValues( __in BURN_SYMBOL_TYPE comparison, - __in DWORD64 qwLeftOperand, - __in DWORD64 qwRightOperand, + __in VERUTIL_VERSION* pLeftOperand, + __in VERUTIL_VERSION* pRightOperand, __out BOOL* pfResult ) { HRESULT hr = S_OK; + int nResult = 0; + + hr = VerCompareParsedVersions(pLeftOperand, pRightOperand, &nResult); + ExitOnFailure(hr, "Failed to compare condition versions: '%ls', '%ls'", pLeftOperand->sczVersion, pRightOperand->sczVersion); switch (comparison) { - case BURN_SYMBOL_TYPE_LT: *pfResult = qwLeftOperand < qwRightOperand; break; - case BURN_SYMBOL_TYPE_GT: *pfResult = qwLeftOperand > qwRightOperand; break; - case BURN_SYMBOL_TYPE_LE: *pfResult = qwLeftOperand <= qwRightOperand; break; - case BURN_SYMBOL_TYPE_GE: *pfResult = qwLeftOperand >= qwRightOperand; break; - case BURN_SYMBOL_TYPE_EQ: *pfResult = qwLeftOperand == qwRightOperand; break; - case BURN_SYMBOL_TYPE_NE: *pfResult = qwLeftOperand != qwRightOperand; break; - case BURN_SYMBOL_TYPE_BAND: *pfResult = (qwLeftOperand & qwRightOperand) ? TRUE : FALSE; break; - case BURN_SYMBOL_TYPE_HIEQ: *pfResult = ((qwLeftOperand >> 16) & 0xFFFF) == qwRightOperand; break; - case BURN_SYMBOL_TYPE_LOEQ: *pfResult = (qwLeftOperand & 0xFFFF) == qwRightOperand; break; + case BURN_SYMBOL_TYPE_LT: *pfResult = nResult < 0; break; + case BURN_SYMBOL_TYPE_GT: *pfResult = nResult > 0; break; + case BURN_SYMBOL_TYPE_LE: *pfResult = nResult <= 0; break; + case BURN_SYMBOL_TYPE_GE: *pfResult = nResult >= 0; break; + case BURN_SYMBOL_TYPE_EQ: *pfResult = nResult == 0; break; + case BURN_SYMBOL_TYPE_NE: *pfResult = nResult != 0; break; default: ExitFunction1(hr = E_INVALIDARG); } diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp index c7c6e024..c01449b6 100644 --- a/src/engine/dependency.cpp +++ b/src/engine/dependency.cpp @@ -593,20 +593,14 @@ extern "C" HRESULT DependencyRegisterBundle( ) { HRESULT hr = S_OK; - LPWSTR sczVersion = NULL; - hr = FileVersionToStringEx(pRegistration->qwVersion, &sczVersion); - ExitOnFailure(hr, "Failed to format the registration version string."); - - LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_REGISTER, pRegistration->sczProviderKey, sczVersion); + LogId(REPORT_VERBOSE, MSG_DEPENDENCY_BUNDLE_REGISTER, pRegistration->sczProviderKey, pRegistration->pVersion->sczVersion); // Register the bundle provider key. - hr = DepRegisterDependency(pRegistration->hkRoot, pRegistration->sczProviderKey, sczVersion, pRegistration->sczDisplayName, pRegistration->sczId, 0); + hr = DepRegisterDependency(pRegistration->hkRoot, pRegistration->sczProviderKey, pRegistration->pVersion->sczVersion, pRegistration->sczDisplayName, pRegistration->sczId, 0); ExitOnFailure(hr, "Failed to register the bundle dependency provider."); LExit: - ReleaseStr(sczVersion); - return hr; } diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp index 7953daf5..9e4681bb 100644 --- a/src/engine/detect.cpp +++ b/src/engine/detect.cpp @@ -90,6 +90,7 @@ extern "C" HRESULT DetectForwardCompatibleBundle( HRESULT hr = S_OK; BOOL fRecommendIgnore = TRUE; BOOL fIgnoreBundle = FALSE; + int nCompareResult = 0; if (pRegistration->sczDetectedProviderKeyBundleId && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRegistration->sczId, -1)) @@ -122,22 +123,27 @@ extern "C" HRESULT DetectForwardCompatibleBundle( fIgnoreBundle = fRecommendIgnore; if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType && - pRegistration->qwVersion <= pRelatedBundle->qwVersion && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1)) { - hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, &fIgnoreBundle); - ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); + hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion->sczVersion, pRelatedBundle->pVersion->sczVersion); - if (!fIgnoreBundle) + if (nCompareResult <= 0) { - hr = PseudoBundleInitializePassthrough(&pRegistration->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package); - ExitOnFailure(hr, "Failed to initialize update bundle."); + hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, &fIgnoreBundle); + ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); - pRegistration->fEnabledForwardCompatibleBundle = TRUE; - } + if (!fIgnoreBundle) + { + hr = PseudoBundleInitializePassthrough(&pRegistration->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package); + ExitOnFailure(hr, "Failed to initialize update bundle."); - LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingBoolToString(pRegistration->fEnabledForwardCompatibleBundle)); - break; + pRegistration->fEnabledForwardCompatibleBundle = TRUE; + } + + LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRegistration->fEnabledForwardCompatibleBundle)); + break; + } } } } @@ -154,6 +160,7 @@ extern "C" HRESULT DetectReportRelatedBundles( ) { HRESULT hr = S_OK; + int nCompareResult = 0; for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle) { @@ -165,11 +172,14 @@ extern "C" HRESULT DetectReportRelatedBundles( case BOOTSTRAPPER_RELATION_UPGRADE: if (BOOTSTRAPPER_RELATION_UPGRADE != relationType && BOOTSTRAPPER_ACTION_UNINSTALL < action) { - if (pRegistration->qwVersion > pRelatedBundle->qwVersion) + hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion, pRelatedBundle->pVersion); + + if (nCompareResult > 0) { operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE; } - else if (pRegistration->qwVersion < pRelatedBundle->qwVersion) + else if (nCompareResult < 0) { operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; } @@ -202,9 +212,9 @@ extern "C" HRESULT DetectReportRelatedBundles( break; } - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingRelatedOperationToString(operation)); + LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingRelatedOperationToString(operation)); - hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, operation); + hr = UserExperienceOnDetectRelatedBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, operation); ExitOnRootFailure(hr, "BA aborted detect related bundle."); } @@ -405,7 +415,7 @@ static HRESULT DetectAtomFeedUpdate( hr = UserExperienceOnDetectUpdate(pUX, pAppUpdateEntry->rgEnclosures ? pAppUpdateEntry->rgEnclosures->wzUrl : NULL, pAppUpdateEntry->rgEnclosures ? pAppUpdateEntry->rgEnclosures->dw64Size : 0, - pAppUpdateEntry->dw64Version, pAppUpdateEntry->wzTitle, + pAppUpdateEntry->pVersion, pAppUpdateEntry->wzTitle, pAppUpdateEntry->wzSummary, pAppUpdateEntry->wzContentType, pAppUpdateEntry->wzContent, &fStopProcessingUpdates); ExitOnRootFailure(hr, "BA aborted detect update."); diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp index d0652270..9ce04630 100644 --- a/src/engine/elevation.cpp +++ b/src/engine/elevation.cpp @@ -1087,7 +1087,7 @@ extern "C" HRESULT ElevationLoadCompatiblePackageAction( hr = BuffWriteString(&pbData, &cbData, pExecuteAction->compatiblePackage.sczInstalledProductCode); ExitOnFailure(hr, "Failed to write installed ProductCode to message buffer."); - hr = BuffWriteNumber64(&pbData, &cbData, pExecuteAction->compatiblePackage.qwInstalledVersion); + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->compatiblePackage.pInstalledVersion->sczVersion); ExitOnFailure(hr, "Failed to write installed version to message buffer."); // Send the message. @@ -2566,6 +2566,7 @@ static HRESULT OnLoadCompatiblePackage( HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; + LPWSTR sczVersion = NULL; BURN_EXECUTE_ACTION executeAction = { }; executeAction.type = BURN_EXECUTE_ACTION_TYPE_COMPATIBLE_PACKAGE; @@ -2581,20 +2582,24 @@ static HRESULT OnLoadCompatiblePackage( hr = BuffReadString(pbData, cbData, &iData, &executeAction.compatiblePackage.sczInstalledProductCode); ExitOnFailure(hr, "Failed to read installed ProductCode from message buffer."); - hr = BuffReadNumber64(pbData, cbData, &iData, &executeAction.compatiblePackage.qwInstalledVersion); + hr = BuffReadString(pbData, cbData, &iData, &sczVersion); ExitOnFailure(hr, "Failed to read installed version from message buffer."); + hr = VerParseVersion(sczVersion, 0, FALSE, &executeAction.compatiblePackage.pInstalledVersion); + ExitOnFailure(hr, "Failed to parse installed version from compatible package."); + // Copy the installed data to the reference package. hr = StrAllocString(&executeAction.compatiblePackage.pReferencePackage->Msi.sczInstalledProductCode, executeAction.compatiblePackage.sczInstalledProductCode, 0); ExitOnFailure(hr, "Failed to copy installed ProductCode."); - executeAction.compatiblePackage.pReferencePackage->Msi.qwInstalledVersion = executeAction.compatiblePackage.qwInstalledVersion; + executeAction.compatiblePackage.pReferencePackage->Msi.pInstalledVersion = executeAction.compatiblePackage.pInstalledVersion; // Load the compatible package and add it to the list. hr = MsiEngineAddCompatiblePackage(pPackages, executeAction.compatiblePackage.pReferencePackage, NULL); ExitOnFailure(hr, "Failed to load compatible package."); LExit: + ReleaseStr(sczVersion); ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); diff --git a/src/engine/engine.vcxproj b/src/engine/engine.vcxproj index ef5c1602..d3f5b61e 100644 --- a/src/engine/engine.vcxproj +++ b/src/engine/engine.vcxproj @@ -2,7 +2,7 @@ - + @@ -165,7 +165,7 @@ rc.exe -fo "$(OutDir)engine.res" "$(IntDir)engine.messages.rc" This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp index 55b65336..a6412da9 100644 --- a/src/engine/logging.cpp +++ b/src/engine/logging.cpp @@ -583,23 +583,6 @@ extern "C" LPWSTR LoggingStringOrUnknownIfNull( return wz ? wz : L"Unknown"; } -// Note: this function is not thread safe. -extern "C" LPCSTR LoggingVersionToString( - __in DWORD64 dw64Version - ) -{ - static CHAR szVersion[40] = { 0 }; - HRESULT hr = S_OK; - - hr = ::StringCchPrintfA(szVersion, countof(szVersion), "%I64u.%I64u.%I64u.%I64u", dw64Version >> 48 & 0xFFFF, dw64Version >> 32 & 0xFFFF, dw64Version >> 16 & 0xFFFF, dw64Version & 0xFFFF); - if (FAILED(hr)) - { - memset(szVersion, 0, sizeof(szVersion)); - } - - return szVersion; -} - // internal function declarations diff --git a/src/engine/logging.h b/src/engine/logging.h index cea4d31d..22dd54d9 100644 --- a/src/engine/logging.h +++ b/src/engine/logging.h @@ -133,11 +133,6 @@ LPWSTR LoggingStringOrUnknownIfNull( __in LPCWSTR wz ); -// Note: this function is not thread safe. -LPCSTR LoggingVersionToString( - __in DWORD64 dw64Version - ); - #if defined(__cplusplus) } diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index e7cffd62..e274df28 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp @@ -79,7 +79,7 @@ extern "C" HRESULT MsiEngineParsePackageFromXml( hr = XmlGetAttributeEx(pixnMsiPackage, L"Version", &scz); ExitOnFailure(hr, "Failed to get @Version."); - hr = FileVersionFromStringEx(scz, 0, &pPackage->Msi.qwVersion); + hr = VerParseVersion(scz, 0, FALSE, &pPackage->Msi.pVersion); ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); // @UpgradeCode @@ -399,6 +399,7 @@ extern "C" HRESULT MsiEngineDetectPackage( Trace(REPORT_STANDARD, "Detecting MSI package 0x%p", pPackage); HRESULT hr = S_OK; + int nCompareResult = 0; LPWSTR sczInstalledVersion = NULL; LPWSTR sczInstalledLanguage = NULL; LPWSTR sczInstalledProductCode = NULL; @@ -407,7 +408,7 @@ extern "C" HRESULT MsiEngineDetectPackage( BOOTSTRAPPER_RELATED_OPERATION operation = BOOTSTRAPPER_RELATED_OPERATION_NONE; BOOTSTRAPPER_RELATED_OPERATION relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_NONE; WCHAR wzProductCode[MAX_GUID_CHARS + 1] = { }; - DWORD64 qwVersion = 0; + VERUTIL_VERSION* pVersion = NULL; UINT uLcid = 0; BOOL fPerMachine = FALSE; @@ -416,18 +417,21 @@ extern "C" HRESULT MsiEngineDetectPackage( hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); if (SUCCEEDED(hr)) { - hr = FileVersionFromStringEx(sczInstalledVersion, 0, &pPackage->Msi.qwInstalledVersion); - ExitOnFailure(hr, "Failed to convert version: %ls to DWORD64 for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode); + hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pPackage->Msi.pInstalledVersion); + ExitOnFailure(hr, "Failed to parse installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode); // compare versions - if (pPackage->Msi.qwVersion < pPackage->Msi.qwInstalledVersion) + hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->Msi.pInstalledVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare version '%ls' to installed version: '%ls'", pPackage->Msi.pVersion->sczVersion, pPackage->Msi.pInstalledVersion->sczVersion); + + if (nCompareResult < 0) { operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED; } else { - if (pPackage->Msi.qwVersion > pPackage->Msi.qwInstalledVersion) + if (nCompareResult > 0) { operation = BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE; } @@ -438,9 +442,9 @@ extern "C" HRESULT MsiEngineDetectPackage( // Report related MSI package to BA. if (BOOTSTRAPPER_RELATED_OPERATION_NONE != operation) { - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, pPackage->Msi.sczProductCode, LoggingPerMachineToString(pPackage->fPerMachine), LoggingVersionToString(pPackage->Msi.qwInstalledVersion), pPackage->Msi.dwLanguage, LoggingRelatedOperationToString(operation)); + LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, pPackage->Msi.sczProductCode, LoggingPerMachineToString(pPackage->fPerMachine), pPackage->Msi.pInstalledVersion->sczVersion, pPackage->Msi.dwLanguage, LoggingRelatedOperationToString(operation)); - hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pPackage->Msi.sczUpgradeCode, pPackage->Msi.sczProductCode, pPackage->fPerMachine, pPackage->Msi.qwInstalledVersion, operation); + hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pPackage->Msi.sczUpgradeCode, pPackage->Msi.sczProductCode, pPackage->fPerMachine, pPackage->Msi.pInstalledVersion, operation); ExitOnRootFailure(hr, "BA aborted detect related MSI package."); } } @@ -453,21 +457,26 @@ extern "C" HRESULT MsiEngineDetectPackage( hr = WiuGetProductInfoEx(sczInstalledProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); if (SUCCEEDED(hr)) { - hr = FileVersionFromStringEx(sczInstalledVersion, 0, &qwVersion); - ExitOnFailure(hr, "Failed to convert version: %ls to DWORD64 for ProductCode: %ls", sczInstalledVersion, sczInstalledProductCode); + hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to parse dependency version: '%ls' for ProductCode: %ls", sczInstalledVersion, sczInstalledProductCode); + + // compare versions + hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare version '%ls' to dependency version: '%ls'", pPackage->Msi.pVersion->sczVersion, pVersion->sczVersion); - if (pPackage->Msi.qwVersion < qwVersion) + if (nCompareResult < 0) { LogId(REPORT_STANDARD, MSG_DETECTED_COMPATIBLE_PACKAGE_FROM_PROVIDER, pPackage->sczId, sczInstalledProviderKey, sczInstalledProductCode, sczInstalledVersion, pPackage->Msi.sczProductCode); - hr = UserExperienceOnDetectCompatibleMsiPackage(pUserExperience, pPackage->sczId, sczInstalledProductCode, qwVersion); + hr = UserExperienceOnDetectCompatibleMsiPackage(pUserExperience, pPackage->sczId, sczInstalledProductCode, pVersion); ExitOnRootFailure(hr, "BA aborted detect compatible MSI package."); hr = StrAllocString(&pPackage->Msi.sczInstalledProductCode, sczInstalledProductCode, 0); ExitOnFailure(hr, "Failed to copy the installed ProductCode to the package."); - pPackage->Msi.qwInstalledVersion = qwVersion; + pPackage->Msi.pInstalledVersion = pVersion; pPackage->Msi.fCompatibleInstalled = TRUE; + pVersion = NULL; } } } @@ -524,18 +533,30 @@ extern "C" HRESULT MsiEngineDetectPackage( } } - hr = FileVersionFromStringEx(sczInstalledVersion, 0, &qwVersion); - ExitOnFailure(hr, "Failed to convert version: %ls to DWORD64 for ProductCode: %ls", sczInstalledVersion, wzProductCode); + hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to parse related installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, wzProductCode); // compare versions - if (pRelatedMsi->fMinProvided && (pRelatedMsi->fMinInclusive ? (qwVersion < pRelatedMsi->qwMinVersion) : (qwVersion <= pRelatedMsi->qwMinVersion))) + if (pRelatedMsi->fMinProvided) { - continue; + hr = VerCompareParsedVersions(pVersion, pRelatedMsi->pMinVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare related installed version '%ls' to related min version: '%ls'", pVersion->sczVersion, pRelatedMsi->pMinVersion->sczVersion); + + if (pRelatedMsi->fMinInclusive ? (nCompareResult < 0) : (nCompareResult <= 0)) + { + continue; + } } - if (pRelatedMsi->fMaxProvided && (pRelatedMsi->fMaxInclusive ? (qwVersion > pRelatedMsi->qwMaxVersion) : (qwVersion >= pRelatedMsi->qwMaxVersion))) + if (pRelatedMsi->fMaxProvided) { - continue; + hr = VerCompareParsedVersions(pVersion, pRelatedMsi->pMaxVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare related installed version '%ls' to related max version: '%ls'", pVersion->sczVersion, pRelatedMsi->pMaxVersion->sczVersion); + + if (pRelatedMsi->fMaxInclusive ? (nCompareResult > 0) : (nCompareResult >= 0)) + { + continue; + } } // Filter by language if necessary. @@ -605,10 +626,10 @@ extern "C" HRESULT MsiEngineDetectPackage( operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE; } - LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, wzProductCode, LoggingPerMachineToString(fPerMachine), LoggingVersionToString(qwVersion), uLcid, LoggingRelatedOperationToString(relatedMsiOperation)); + LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_PACKAGE, wzProductCode, LoggingPerMachineToString(fPerMachine), pVersion->sczVersion, uLcid, LoggingRelatedOperationToString(relatedMsiOperation)); // Pass to BA. - hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pRelatedMsi->sczUpgradeCode, wzProductCode, fPerMachine, qwVersion, relatedMsiOperation); + hr = UserExperienceOnDetectRelatedMsiPackage(pUserExperience, pPackage->sczId, pRelatedMsi->sczUpgradeCode, wzProductCode, fPerMachine, pVersion, relatedMsiOperation); ExitOnRootFailure(hr, "BA aborted detect related MSI package."); } } @@ -667,6 +688,7 @@ LExit: ReleaseStr(sczInstalledProductCode); ReleaseStr(sczInstalledLanguage); ReleaseStr(sczInstalledVersion); + ReleaseVerutilVersion(pVersion); return hr; } @@ -684,8 +706,9 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( Trace(REPORT_STANDARD, "Planning MSI package 0x%p", pPackage); HRESULT hr = S_OK; - DWORD64 qwVersion = pPackage->Msi.qwVersion; - DWORD64 qwInstalledVersion = pPackage->Msi.qwInstalledVersion; + VERUTIL_VERSION* pVersion = pPackage->Msi.pVersion; + VERUTIL_VERSION* pInstalledVersion = pPackage->Msi.pInstalledVersion; + int nCompareResult = 0; BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE; BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE; BOOL fFeatureActionDelta = FALSE; @@ -739,10 +762,13 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage( case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED: if (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested) { + hr = VerCompareParsedVersions(pVersion, pInstalledVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare '%ls' to '%ls' for planning.", pVersion->sczVersion, pInstalledVersion->sczVersion); + // Take a look at the version and determine if this is a potential // minor upgrade (same ProductCode newer ProductVersion), otherwise, // there is a newer version so no work necessary. - if (qwVersion > qwInstalledVersion) + if (nCompareResult > 0) { execute = BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE; } @@ -1014,20 +1040,18 @@ extern "C" HRESULT MsiEngineAddCompatiblePackage( } // Read in the compatible ProductVersion if not already available. - if (pPackage->Msi.qwInstalledVersion) + if (pPackage->Msi.pInstalledVersion) { - pCompatiblePackage->Msi.qwVersion = pPackage->Msi.qwInstalledVersion; - - hr = FileVersionToStringEx(pCompatiblePackage->Msi.qwVersion, &sczInstalledVersion); - ExitOnFailure(hr, "Failed to format version number string."); + hr = VerCopyVersion(pPackage->Msi.pInstalledVersion, &pCompatiblePackage->Msi.pVersion); + ExitOnFailure(hr, "Failed to copy version for compatible package."); } else { hr = WiuGetProductInfoEx(pCompatiblePackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); ExitOnFailure(hr, "Failed to read version from compatible package."); - hr = FileVersionFromStringEx(sczInstalledVersion, 0, &pCompatiblePackage->Msi.qwVersion); - ExitOnFailure(hr, "Failed to convert version: %ls to DWORD64 for ProductCode: %ls", sczInstalledVersion, pCompatiblePackage->Msi.sczProductCode); + hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pCompatiblePackage->Msi.pVersion); + ExitOnFailure(hr, "Failed to parse version: '%ls' for ProductCode: %ls", sczInstalledVersion, pCompatiblePackage->Msi.sczProductCode); } // For now, copy enough information to support uninstalling the newer, compatible package. @@ -1046,7 +1070,7 @@ extern "C" HRESULT MsiEngineAddCompatiblePackage( ExitOnFailure(hr, "Failed to format log path variable for compatible package."); // Use the default cache ID generation from the binder. - hr = StrAllocFormatted(&pCompatiblePackage->sczCacheId, L"%lsv%ls", pCompatiblePackage->sczId, sczInstalledVersion); + hr = StrAllocFormatted(&pCompatiblePackage->sczCacheId, L"%lsv%ls", pCompatiblePackage->sczId, pCompatiblePackage->Msi.pVersion->sczVersion); ExitOnFailure(hr, "Failed to format cache ID for compatible package."); pCompatiblePackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; @@ -1068,7 +1092,7 @@ extern "C" HRESULT MsiEngineAddCompatiblePackage( ExitOnFailure(hr, "Failed to copy the compatible provider key."); // Assume the package version is the same as the provider version. - hr = StrAllocString(&pCompatibleProvider->sczVersion, sczInstalledVersion, 0); + hr = StrAllocString(&pCompatibleProvider->sczVersion, pCompatiblePackage->Msi.pVersion->sczVersion, 0); ExitOnFailure(hr, "Failed to copy the compatible provider version."); // Assume provider keys are similarly authored for this package. @@ -1479,7 +1503,7 @@ static HRESULT ParseRelatedMsiFromXml( { ExitOnFailure(hr, "Failed to get @MinVersion."); - hr = FileVersionFromStringEx(scz, 0, &pRelatedMsi->qwMinVersion); + hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMinVersion); ExitOnFailure(hr, "Failed to parse @MinVersion: %ls", scz); // flag that we have a min version @@ -1496,7 +1520,7 @@ static HRESULT ParseRelatedMsiFromXml( { ExitOnFailure(hr, "Failed to get @MaxVersion."); - hr = FileVersionFromStringEx(scz, 0, &pRelatedMsi->qwMaxVersion); + hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMaxVersion); ExitOnFailure(hr, "Failed to parse @MaxVersion: %ls", scz); // flag that we have a max version diff --git a/src/engine/package.h b/src/engine/package.h index 05965a16..c5873765 100644 --- a/src/engine/package.h +++ b/src/engine/package.h @@ -123,8 +123,8 @@ typedef struct _BURN_MSIFEATURE typedef struct _BURN_RELATED_MSI { LPWSTR sczUpgradeCode; - DWORD64 qwMinVersion; - DWORD64 qwMaxVersion; + VERUTIL_VERSION* pMinVersion; + VERUTIL_VERSION* pMaxVersion; BOOL fMinProvided; BOOL fMaxProvided; BOOL fMinInclusive; @@ -236,9 +236,9 @@ typedef struct _BURN_PACKAGE { LPWSTR sczProductCode; DWORD dwLanguage; - DWORD64 qwVersion; + VERUTIL_VERSION* pVersion; LPWSTR sczInstalledProductCode; - DWORD64 qwInstalledVersion; + VERUTIL_VERSION* pInstalledVersion; LPWSTR sczUpgradeCode; BURN_MSIPROPERTY* rgProperties; diff --git a/src/engine/packages.config b/src/engine/packages.config index e7fa32d0..68222d34 100644 --- a/src/engine/packages.config +++ b/src/engine/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp index 0b040bf8..f6b681b6 100644 --- a/src/engine/plan.cpp +++ b/src/engine/plan.cpp @@ -530,7 +530,7 @@ extern "C" HRESULT PlanPackages( pAction->type = BURN_EXECUTE_ACTION_TYPE_COMPATIBLE_PACKAGE; pAction->compatiblePackage.pReferencePackage = pPackage; - pAction->compatiblePackage.qwInstalledVersion = pCompatiblePackage->Msi.qwVersion; + pAction->compatiblePackage.pInstalledVersion = pCompatiblePackage->Msi.pVersion; hr = StrAllocString(&pAction->compatiblePackage.sczInstalledProductCode, pCompatiblePackage->Msi.sczProductCode, 0); ExitOnFailure(hr, "Failed to copy installed ProductCode"); @@ -880,7 +880,7 @@ static HRESULT ProcessPackage( { AssertSz(BURN_PACKAGE_TYPE_MSI == pPackage->type, "Currently only MSI packages have compatible packages."); - hr = UserExperienceOnPlanCompatibleMsiPackageBegin(pUX, pCompatiblePackageParent->sczId, pPackage->sczId, pPackage->Msi.qwVersion, &pPackage->requested); + hr = UserExperienceOnPlanCompatibleMsiPackageBegin(pUX, pCompatiblePackageParent->sczId, pPackage->sczId, pPackage->Msi.pVersion, &pPackage->requested); ExitOnRootFailure(hr, "BA aborted plan compatible MSI package begin."); } else @@ -1207,6 +1207,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin( LPWSTR* rgsczAncestors = NULL; UINT cAncestors = 0; STRINGDICT_HANDLE sdAncestors = NULL; + int nCompareResult = 0; if (pRegistration->sczAncestors) { @@ -1261,7 +1262,10 @@ extern "C" HRESULT PlanRelatedBundlesBegin( case BOOTSTRAPPER_RELATION_UPGRADE: if (BOOTSTRAPPER_RELATION_UPGRADE != relationType && BOOTSTRAPPER_ACTION_UNINSTALL < pPlan->action) { - pRelatedBundle->package.requested = (pRegistration->qwVersion > pRelatedBundle->qwVersion) ? BOOTSTRAPPER_REQUEST_STATE_ABSENT : BOOTSTRAPPER_REQUEST_STATE_NONE; + hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); + ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion, pRelatedBundle->pVersion); + + pRelatedBundle->package.requested = (nCompareResult > 0) ? BOOTSTRAPPER_REQUEST_STATE_ABSENT : BOOTSTRAPPER_REQUEST_STATE_NONE; } break; case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; diff --git a/src/engine/plan.h b/src/engine/plan.h index db9745e9..4fd3380e 100644 --- a/src/engine/plan.h +++ b/src/engine/plan.h @@ -305,7 +305,7 @@ typedef struct _BURN_EXECUTE_ACTION { BURN_PACKAGE* pReferencePackage; LPWSTR sczInstalledProductCode; - DWORD64 qwInstalledVersion; + VERUTIL_VERSION* pInstalledVersion; } compatiblePackage; }; } BURN_EXECUTE_ACTION; diff --git a/src/engine/precomp.h b/src/engine/precomp.h index b5c5e65e..2bceab58 100644 --- a/src/engine/precomp.h +++ b/src/engine/precomp.h @@ -24,6 +24,7 @@ #define DUTIL_SOURCE_DEFAULT DUTIL_SOURCE_EXTERNAL #include +#include #include #include #include diff --git a/src/engine/registration.cpp b/src/engine/registration.cpp index eace62ce..3c3dc95d 100644 --- a/src/engine/registration.cpp +++ b/src/engine/registration.cpp @@ -133,7 +133,7 @@ extern "C" HRESULT RegistrationParseFromXml( hr = XmlGetAttributeEx(pixnRegistrationNode, L"Version", &scz); ExitOnFailure(hr, "Failed to get @Version."); - hr = FileVersionFromStringEx(scz, 0, &pRegistration->qwVersion); + hr = VerParseVersion(scz, 0, FALSE, &pRegistration->pVersion); ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); // @ProviderKey @@ -436,7 +436,7 @@ extern "C" HRESULT RegistrationSetVariables( hr = VariableSetString(pVariables, BURN_BUNDLE_TAG, pRegistration->sczTag, TRUE, FALSE); ExitOnFailure(hr, "Failed to overwrite the bundle tag built-in variable."); - hr = VariableSetVersion(pVariables, BURN_BUNDLE_VERSION, pRegistration->qwVersion, TRUE); + hr = VariableSetVersion(pVariables, BURN_BUNDLE_VERSION, pRegistration->pVersion, TRUE); ExitOnFailure(hr, "Failed to overwrite the bundle tag built-in variable."); LExit: @@ -630,15 +630,13 @@ extern "C" HRESULT RegistrationSessionBegin( hr = RegWriteStringArray(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_PATCH_CODE, pRegistration->rgsczPatchCodes, pRegistration->cPatchCodes); ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_PATCH_CODE); - hr = RegWriteStringFormatted(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, L"%hu.%hu.%hu.%hu", - static_cast(pRegistration->qwVersion >> 48), static_cast(pRegistration->qwVersion >> 32), - static_cast(pRegistration->qwVersion >> 16), static_cast(pRegistration->qwVersion)); + hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, pRegistration->pVersion->sczVersion); ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION); - hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_VERSION_MAJOR, static_cast(pRegistration->qwVersion >> 48)); + hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_VERSION_MAJOR, pRegistration->pVersion->dwMajor); ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_VERSION_MAJOR); - hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_VERSION_MINOR, static_cast(pRegistration->qwVersion >> 32)); + hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_VERSION_MINOR, pRegistration->pVersion->dwMinor); ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_VERSION_MINOR); if (pRegistration->sczProviderKey) diff --git a/src/engine/registration.h b/src/engine/registration.h index c830a06d..fa7be368 100644 --- a/src/engine/registration.h +++ b/src/engine/registration.h @@ -59,7 +59,7 @@ typedef struct _BURN_RELATED_BUNDLE { BOOTSTRAPPER_RELATION_TYPE relationType; - DWORD64 qwVersion; + VERUTIL_VERSION* pVersion; LPWSTR sczTag; BURN_PACKAGE package; @@ -105,7 +105,7 @@ typedef struct _BURN_REGISTRATION LPWSTR *rgsczPatchCodes; DWORD cPatchCodes; - DWORD64 qwVersion; + VERUTIL_VERSION* pVersion; LPWSTR sczActiveParent; LPWSTR sczProviderKey; LPWSTR sczExecutableName; diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp index 87794177..e6d6516a 100644 --- a/src/engine/relatedbundle.cpp +++ b/src/engine/relatedbundle.cpp @@ -396,6 +396,7 @@ static HRESULT LoadRelatedBundleFromKey( { HRESULT hr = S_OK; DWORD64 qwEngineVersion = 0; + LPWSTR sczBundleVersion = NULL; LPWSTR sczCachePath = NULL; DWORD64 qwFileSize = 0; BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; @@ -407,9 +408,12 @@ static HRESULT LoadRelatedBundleFromKey( hr = S_OK; } - hr = RegReadVersion(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, &pRelatedBundle->qwVersion); + hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION, &sczBundleVersion); ExitOnFailure(hr, "Failed to read version from registry for bundle: %ls", wzRelatedBundleId); + hr = VerParseVersion(sczBundleVersion, 0, FALSE, &pRelatedBundle->pVersion); + ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", sczBundleVersion); + hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath); ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId); @@ -423,7 +427,7 @@ static HRESULT LoadRelatedBundleFromKey( dependencyProvider.fImported = TRUE; - hr = FileVersionToStringEx(pRelatedBundle->qwVersion, &dependencyProvider.sczVersion); + hr = StrAllocString(&dependencyProvider.sczVersion, pRelatedBundle->pVersion->sczVersion, 0); ExitOnFailure(hr, "Failed to copy version for bundle: %ls", wzRelatedBundleId); hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME, &dependencyProvider.sczDisplayName); @@ -452,6 +456,7 @@ static HRESULT LoadRelatedBundleFromKey( LExit: DependencyUninitialize(&dependencyProvider); ReleaseStr(sczCachePath); + ReleaseStr(sczBundleVersion); return hr; } diff --git a/src/engine/search.cpp b/src/engine/search.cpp index 2978edd3..1dbcf56b 100644 --- a/src/engine/search.cpp +++ b/src/engine/search.cpp @@ -754,6 +754,7 @@ static HRESULT FileSearchVersion( HRESULT hr = S_OK; ULARGE_INTEGER uliVersion = { }; LPWSTR sczPath = NULL; + VERUTIL_VERSION* pVersion = NULL; // format path hr = VariableFormatString(pVariables, pSearch->FileSearch.sczPath, &sczPath, NULL); @@ -767,14 +768,18 @@ static HRESULT FileSearchVersion( LogStringLine(REPORT_STANDARD, "File search: %ls, did not find path: %ls", pSearch->sczKey, sczPath); ExitFunction1(hr = S_OK); } - ExitOnFailure(hr, "Failed get file version."); + ExitOnFailure(hr, "Failed to get file version."); + + hr = VerVersionFromQword(uliVersion.QuadPart, &pVersion); + ExitOnFailure(hr, "Failed to create version from file version."); // set variable - hr = VariableSetVersion(pVariables, pSearch->sczVariable, uliVersion.QuadPart, FALSE); + hr = VariableSetVersion(pVariables, pSearch->sczVariable, pVersion, FALSE); ExitOnFailure(hr, "Failed to set variable."); LExit: StrSecureZeroFreeString(sczPath); + ReleaseVerutilVersion(pVersion); return hr; } diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp index 6b0e3bf5..6ab28cde 100644 --- a/src/engine/userexperience.cpp +++ b/src/engine/userexperience.cpp @@ -646,7 +646,7 @@ EXTERN_C BAAPI UserExperienceOnDetectCompatibleMsiPackage( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzCompatiblePackageId, - __in DWORD64 dw64CompatiblePackageVersion + __in VERUTIL_VERSION* pCompatiblePackageVersion ) { HRESULT hr = S_OK; @@ -656,7 +656,7 @@ EXTERN_C BAAPI UserExperienceOnDetectCompatibleMsiPackage( args.cbSize = sizeof(args); args.wzPackageId = wzPackageId; args.wzCompatiblePackageId = wzCompatiblePackageId; - args.dw64CompatiblePackageVersion = dw64CompatiblePackageVersion; + args.wzCompatiblePackageVersion = pCompatiblePackageVersion->sczVersion; results.cbSize = sizeof(results); @@ -699,7 +699,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __inout BOOL* pfIgnoreBundle ) { @@ -712,7 +712,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle( args.relationType = relationType; args.wzBundleTag = wzBundleTag; args.fPerMachine = fPerMachine; - args.dw64Version = dw64Version; + args.wzVersion = pVersion->sczVersion; results.cbSize = sizeof(results); results.fIgnoreBundle = *pfIgnoreBundle; @@ -817,7 +817,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in BOOTSTRAPPER_RELATED_OPERATION operation ) { @@ -830,7 +830,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedBundle( args.relationType = relationType; args.wzBundleTag = wzBundleTag; args.fPerMachine = fPerMachine; - args.dw64Version = dw64Version; + args.wzVersion = pVersion->sczVersion; args.operation = operation; results.cbSize = sizeof(results); @@ -853,7 +853,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedMsiPackage( __in_z LPCWSTR wzUpgradeCode, __in_z LPCWSTR wzProductCode, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in BOOTSTRAPPER_RELATED_OPERATION operation ) { @@ -866,7 +866,7 @@ EXTERN_C BAAPI UserExperienceOnDetectRelatedMsiPackage( args.wzUpgradeCode = wzUpgradeCode; args.wzProductCode = wzProductCode; args.fPerMachine = fPerMachine; - args.dw64Version = dw64Version; + args.wzVersion = pVersion->sczVersion; args.operation = operation; results.cbSize = sizeof(results); @@ -917,7 +917,7 @@ EXTERN_C BAAPI UserExperienceOnDetectUpdate( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzUpdateLocation, __in DWORD64 dw64Size, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in_z_opt LPCWSTR wzTitle, __in_z_opt LPCWSTR wzSummary, __in_z_opt LPCWSTR wzContentType, @@ -932,7 +932,7 @@ EXTERN_C BAAPI UserExperienceOnDetectUpdate( args.cbSize = sizeof(args); args.wzUpdateLocation = wzUpdateLocation; args.dw64Size = dw64Size; - args.dw64Version = dw64Version; + args.wzVersion = pVersion->sczVersion; args.wzTitle = wzTitle; args.wzSummary = wzSummary; args.wzContentType = wzContentType; @@ -1414,7 +1414,7 @@ EXTERN_C BAAPI UserExperienceOnPlanCompatibleMsiPackageBegin( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzCompatiblePackageId, - __in DWORD64 dw64CompatiblePackageVersion, + __in VERUTIL_VERSION* pCompatiblePackageVersion, __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState ) { @@ -1425,7 +1425,7 @@ EXTERN_C BAAPI UserExperienceOnPlanCompatibleMsiPackageBegin( args.cbSize = sizeof(args); args.wzPackageId = wzPackageId; args.wzCompatiblePackageId = wzCompatiblePackageId; - args.dw64CompatiblePackageVersion = dw64CompatiblePackageVersion; + args.wzCompatiblePackageVersion = pCompatiblePackageVersion->sczVersion; args.recommendedState = *pRequestedState; results.cbSize = sizeof(results); diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h index a5a97ffa..0ebd1b68 100644 --- a/src/engine/userexperience.h +++ b/src/engine/userexperience.h @@ -171,7 +171,7 @@ BAAPI UserExperienceOnDetectCompatibleMsiPackage( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzCompatiblePackageId, - __in DWORD64 dw64CompatiblePackageVersion + __in VERUTIL_VERSION* pCompatiblePackageVersion ); BAAPI UserExperienceOnDetectComplete( __in BURN_USER_EXPERIENCE* pUserExperience, @@ -183,7 +183,7 @@ BAAPI UserExperienceOnDetectForwardCompatibleBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __inout BOOL* pfIgnoreBundle ); BAAPI UserExperienceOnDetectMsiFeature( @@ -208,7 +208,7 @@ BAAPI UserExperienceOnDetectRelatedBundle( __in BOOTSTRAPPER_RELATION_TYPE relationType, __in_z LPCWSTR wzBundleTag, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in BOOTSTRAPPER_RELATED_OPERATION operation ); BAAPI UserExperienceOnDetectRelatedMsiPackage( @@ -217,7 +217,7 @@ BAAPI UserExperienceOnDetectRelatedMsiPackage( __in_z LPCWSTR wzUpgradeCode, __in_z LPCWSTR wzProductCode, __in BOOL fPerMachine, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in BOOTSTRAPPER_RELATED_OPERATION operation ); BAAPI UserExperienceOnDetectTargetMsiPackage( @@ -230,7 +230,7 @@ BAAPI UserExperienceOnDetectUpdate( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzUpdateLocation, __in DWORD64 dw64Size, - __in DWORD64 dw64Version, + __in VERUTIL_VERSION* pVersion, __in_z_opt LPCWSTR wzTitle, __in_z_opt LPCWSTR wzSummary, __in_z_opt LPCWSTR wzContentType, @@ -333,7 +333,7 @@ BAAPI UserExperienceOnPlanCompatibleMsiPackageBegin( __in BURN_USER_EXPERIENCE* pUserExperience, __in_z LPCWSTR wzPackageId, __in_z LPCWSTR wzCompatiblePackageId, - __in DWORD64 dw64CompatiblePackageVersion, + __in VERUTIL_VERSION* pCompatiblePackageVersion, __inout BOOTSTRAPPER_REQUEST_STATE* pRequestedState ); BAAPI UserExperienceOnPlanCompatibleMsiPackageComplete( diff --git a/src/engine/variable.cpp b/src/engine/variable.cpp index fb4b74e2..3069ccf7 100644 --- a/src/engine/variable.cpp +++ b/src/engine/variable.cpp @@ -268,7 +268,7 @@ extern "C" HRESULT VariableInitialize( {BURN_BUNDLE_SOURCE_PROCESS_FOLDER, InitializeVariableString, NULL, FALSE, TRUE}, {BURN_BUNDLE_TAG, InitializeVariableString, (DWORD_PTR)L"", FALSE, TRUE}, {BURN_BUNDLE_UILEVEL, InitializeVariableNumeric, 0, FALSE, TRUE}, - {BURN_BUNDLE_VERSION, InitializeVariableVersion, 0, FALSE, TRUE}, + {BURN_BUNDLE_VERSION, InitializeVariableVersion, (DWORD_PTR)L"0", FALSE, TRUE}, }; for (DWORD i = 0; i < countof(vrgBuiltInVariables); ++i) @@ -561,11 +561,11 @@ LExit: return hr; } -// The contents of pqwValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroMemory. +// The contents of ppValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroMemory. extern "C" HRESULT VariableGetVersion( __in BURN_VARIABLES* pVariables, __in_z LPCWSTR wzVariable, - __in DWORD64* pqwValue + __in VERUTIL_VERSION** ppValue ) { HRESULT hr = S_OK; @@ -584,7 +584,7 @@ extern "C" HRESULT VariableGetVersion( } ExitOnFailure(hr, "Failed to get value of variable: %ls", wzVariable); - hr = BVariantGetVersion(&pVariable->Value, pqwValue); + hr = BVariantGetVersion(&pVariable->Value, ppValue); ExitOnFailure(hr, "Failed to get value as version for variable: %ls", wzVariable); LExit: @@ -701,14 +701,14 @@ extern "C" HRESULT VariableSetString( extern "C" HRESULT VariableSetVersion( __in BURN_VARIABLES* pVariables, __in_z LPCWSTR wzVariable, - __in DWORD64 qwValue, + __in VERUTIL_VERSION* pValue, __in BOOL fOverwriteBuiltIn ) { BURN_VARIANT variant = { }; // We're not going to encrypt this value, so can access the value directly. - variant.qwValue = qwValue; + variant.pValue = pValue; variant.Type = BURN_VARIANT_TYPE_VERSION; return SetVariableValue(pVariables, wzVariable, &variant, fOverwriteBuiltIn ? SET_VARIABLE_OVERRIDE_BUILTIN : SET_VARIABLE_NOT_BUILTIN, TRUE); @@ -810,7 +810,6 @@ extern "C" HRESULT VariableSerialize( BOOL fIncluded = FALSE; LONGLONG ll = 0; LPWSTR scz = NULL; - DWORD64 qw = 0; ::EnterCriticalSection(&pVariables->csAccess); @@ -859,15 +858,7 @@ extern "C" HRESULT VariableSerialize( SecureZeroMemory(&ll, sizeof(ll)); break; - case BURN_VARIANT_TYPE_VERSION: - hr = BVariantGetVersion(&pVariable->Value, &qw); - ExitOnFailure(hr, "Failed to get version."); - - hr = BuffWriteNumber64(ppbBuffer, piBuffer, qw); - ExitOnFailure(hr, "Failed to write variable value as number."); - - SecureZeroMemory(&qw, sizeof(qw)); - break; + case BURN_VARIANT_TYPE_VERSION: __fallthrough; case BURN_VARIANT_TYPE_FORMATTED: __fallthrough; case BURN_VARIANT_TYPE_STRING: hr = BVariantGetString(&pVariable->Value, &scz); @@ -887,7 +878,6 @@ extern "C" HRESULT VariableSerialize( LExit: ::LeaveCriticalSection(&pVariables->csAccess); SecureZeroMemory(&ll, sizeof(ll)); - SecureZeroMemory(&qw, sizeof(qw)); StrSecureZeroFreeString(scz); return hr; @@ -908,6 +898,7 @@ extern "C" HRESULT VariableDeserialize( BURN_VARIANT value = { }; LPWSTR scz = NULL; DWORD64 qw = 0; + VERUTIL_VERSION* pVersion = NULL; ::EnterCriticalSection(&pVariables->csAccess); @@ -950,10 +941,13 @@ extern "C" HRESULT VariableDeserialize( SecureZeroMemory(&qw, sizeof(qw)); break; case BURN_VARIANT_TYPE_VERSION: - hr = BuffReadNumber64(pbBuffer, cbBuffer, piBuffer, &qw); - ExitOnFailure(hr, "Failed to read variable value as number."); + hr = BuffReadString(pbBuffer, cbBuffer, piBuffer, &scz); + ExitOnFailure(hr, "Failed to read variable value as string."); + + hr = VerParseVersion(scz, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to parse variable value as version."); - hr = BVariantSetVersion(&value, qw); + hr = BVariantSetVersion(&value, pVersion); ExitOnFailure(hr, "Failed to set variable value."); SecureZeroMemory(&qw, sizeof(qw)); @@ -984,6 +978,7 @@ extern "C" HRESULT VariableDeserialize( LExit: ::LeaveCriticalSection(&pVariables->csAccess); + ReleaseVerutilVersion(pVersion); ReleaseStr(sczName); BVariantUninitialize(&value); SecureZeroMemory(&qw, sizeof(qw)); @@ -1572,7 +1567,7 @@ static HRESULT SetVariableValue( break; case BURN_VARIANT_TYPE_VERSION: - LogStringLine(REPORT_STANDARD, "Setting version variable '%ls' to value '%hu.%hu.%hu.%hu'", wzVariable, (WORD)(pVariant->qwValue >> 48), (WORD)(pVariant->qwValue >> 32), (WORD)(pVariant->qwValue >> 16), (WORD)(pVariant->qwValue)); + LogStringLine(REPORT_STANDARD, "Setting version variable '%ls' to value '%ls'", wzVariable, pVariant->pValue->sczVersion); break; default: @@ -1609,6 +1604,7 @@ static HRESULT InitializeVariableVersionNT( RTL_GET_VERSION rtlGetVersion = NULL; RTL_OSVERSIONINFOEXW ovix = { }; BURN_VARIANT value = { }; + VERUTIL_VERSION* pVersion = NULL; if (!::GetModuleHandleExW(0, L"ntdll", &ntdll)) { @@ -1630,12 +1626,15 @@ static HRESULT InitializeVariableVersionNT( case OS_INFO_VARIABLE_ServicePackLevel: if (0 != ovix.wServicePackMajor) { - value.qwValue = static_cast(ovix.wServicePackMajor); + value.llValue = static_cast(ovix.wServicePackMajor); value.Type = BURN_VARIANT_TYPE_NUMERIC; } break; case OS_INFO_VARIABLE_VersionNT: - value.qwValue = MAKEQWORDVERSION(ovix.dwMajorVersion, ovix.dwMinorVersion, 0, 0); + hr = VerVersionFromQword(MAKEQWORDVERSION(ovix.dwMajorVersion, ovix.dwMinorVersion, 0, 0), &pVersion); + ExitOnFailure(hr, "Failed to create VersionNT from QWORD."); + + value.pValue = pVersion; value.Type = BURN_VARIANT_TYPE_VERSION; break; case OS_INFO_VARIABLE_VersionNT64: @@ -1647,13 +1646,16 @@ static HRESULT InitializeVariableVersionNT( if (fIsWow64) #endif { - value.qwValue = MAKEQWORDVERSION(ovix.dwMajorVersion, ovix.dwMinorVersion, 0, 0); + hr = VerVersionFromQword(MAKEQWORDVERSION(ovix.dwMajorVersion, ovix.dwMinorVersion, 0, 0), &pVersion); + ExitOnFailure(hr, "Failed to create VersionNT64 from QWORD."); + + value.pValue = pVersion; value.Type = BURN_VARIANT_TYPE_VERSION; } } break; case OS_INFO_VARIABLE_WindowsBuildNumber: - value.qwValue = static_cast(ovix.dwBuildNumber); + value.llValue = static_cast(ovix.dwBuildNumber); value.Type = BURN_VARIANT_TYPE_NUMERIC; default: AssertSz(FALSE, "Unknown OS info type."); @@ -1669,6 +1671,8 @@ LExit: FreeLibrary(ntdll); } + ReleaseVerutilVersion(pVersion); + return hr; } @@ -1805,15 +1809,14 @@ LExit: } static HRESULT InitializeVariableVersionMsi( - __in DWORD_PTR dwpData, + __in DWORD_PTR /*dwpData*/, __inout BURN_VARIANT* pValue ) { - UNREFERENCED_PARAMETER(dwpData); - HRESULT hr = S_OK; DLLGETVERSIONPROC pfnMsiDllGetVersion = NULL; DLLVERSIONINFO msiVersionInfo = { }; + VERUTIL_VERSION* pVersion = NULL; // get DllGetVersion proc address pfnMsiDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(::GetModuleHandleW(L"msi"), "DllGetVersion"); @@ -1824,10 +1827,15 @@ static HRESULT InitializeVariableVersionMsi( hr = pfnMsiDllGetVersion(&msiVersionInfo); ExitOnFailure(hr, "Failed to get msi.dll version info."); - hr = BVariantSetVersion(pValue, MAKEQWORDVERSION(msiVersionInfo.dwMajorVersion, msiVersionInfo.dwMinorVersion, 0, 0)); + hr = VerVersionFromQword(MAKEQWORDVERSION(msiVersionInfo.dwMajorVersion, msiVersionInfo.dwMinorVersion, 0, 0), &pVersion); + ExitOnFailure(hr, "Failed to create msi.dll version from QWORD."); + + hr = BVariantSetVersion(pValue, pVersion); ExitOnFailure(hr, "Failed to set variant value."); LExit: + ReleaseVerutilVersion(pVersion); + return hr; } @@ -2270,12 +2278,19 @@ static HRESULT InitializeVariableVersion( ) { HRESULT hr = S_OK; + LPCWSTR wzValue = (LPCWSTR)dwpData; + VERUTIL_VERSION* pVersion = NULL; + + hr = VerParseVersion(wzValue, 0, FALSE, &pVersion); + ExitOnFailure(hr, "Failed to initialize version."); // set value - hr = BVariantSetVersion(pValue, static_cast(dwpData)); + hr = BVariantSetVersion(pValue, pVersion); ExitOnFailure(hr, "Failed to set variant value."); LExit: + ReleaseVerutilVersion(pVersion); + return hr; } diff --git a/src/engine/variable.h b/src/engine/variable.h index 648c5daf..6437c32f 100644 --- a/src/engine/variable.h +++ b/src/engine/variable.h @@ -85,7 +85,7 @@ HRESULT VariableGetString( HRESULT VariableGetVersion( __in BURN_VARIABLES* pVariables, __in_z LPCWSTR wzVariable, - __in DWORD64* pqwValue + __in VERUTIL_VERSION** ppValue ); HRESULT VariableGetVariant( __in BURN_VARIABLES* pVariables, @@ -113,7 +113,7 @@ HRESULT VariableSetString( HRESULT VariableSetVersion( __in BURN_VARIABLES* pVariables, __in_z LPCWSTR wzVariable, - __in DWORD64 qwValue, + __in VERUTIL_VERSION* pValue, __in BOOL fOverwriteBuiltIn ); HRESULT VariableSetVariant( diff --git a/src/engine/variant.cpp b/src/engine/variant.cpp index 43bc19c4..28578691 100644 --- a/src/engine/variant.cpp +++ b/src/engine/variant.cpp @@ -23,7 +23,7 @@ static HRESULT BVariantRetrieveDecryptedString( static void BVariantRetrieveVersion( __in BURN_VARIANT* pVariant, - __out DWORD64* pqwValue + __out VERUTIL_VERSION** ppValue ); // function definitions @@ -48,6 +48,7 @@ extern "C" HRESULT BVariantGetNumeric( { HRESULT hr = S_OK; LPWSTR sczValue = NULL; + VERUTIL_VERSION* pVersionValue = NULL; switch (pVariant->Type) { @@ -68,7 +69,13 @@ extern "C" HRESULT BVariantGetNumeric( StrSecureZeroFreeString(sczValue); break; case BURN_VARIANT_TYPE_VERSION: - BVariantRetrieveVersion(pVariant, (DWORD64*)pllValue); + BVariantRetrieveVersion(pVariant, &pVersionValue); + + hr = StrStringToInt64(pVersionValue->sczVersion, 0, pllValue); + if (FAILED(hr)) + { + hr = DISP_E_TYPEMISMATCH; + } break; default: hr = E_INVALIDARG; @@ -86,7 +93,7 @@ extern "C" HRESULT BVariantGetString( { HRESULT hr = S_OK; LONGLONG llValue = 0; - DWORD64 qwValue = 0; + VERUTIL_VERSION* pVersionValue = NULL; switch (pVariant->Type) { @@ -104,17 +111,9 @@ extern "C" HRESULT BVariantGetString( hr = BVariantRetrieveDecryptedString(pVariant, psczValue); break; case BURN_VARIANT_TYPE_VERSION: - BVariantRetrieveVersion(pVariant, &qwValue); - if (SUCCEEDED(hr)) - { - hr = StrAllocFormattedSecure(psczValue, L"%hu.%hu.%hu.%hu", - (WORD)(qwValue >> 48), - (WORD)(qwValue >> 32), - (WORD)(qwValue >> 16), - (WORD)qwValue); - ExitOnFailure(hr, "Failed to convert version to string."); - } - SecureZeroMemory(&qwValue, sizeof(qwValue)); + BVariantRetrieveVersion(pVariant, &pVersionValue); + + hr = StrAllocStringSecure(psczValue, pVersionValue->sczVersion, 0); break; default: hr = E_INVALIDARG; @@ -125,26 +124,30 @@ LExit: return hr; } -// The contents of pqwValue may be sensitive, should keep encrypted and SecureZeroMemory. +// The contents of ppValue may be sensitive, should keep encrypted and SecureZeroMemory. extern "C" HRESULT BVariantGetVersion( __in BURN_VARIANT* pVariant, - __out DWORD64* pqwValue + __out VERUTIL_VERSION** ppValue ) { HRESULT hr = S_OK; + LONGLONG llValue = 0; LPWSTR sczValue = NULL; + VERUTIL_VERSION* pValue = NULL; switch (pVariant->Type) { case BURN_VARIANT_TYPE_NUMERIC: - BVariantRetrieveNumeric(pVariant, (LONGLONG*)pqwValue); + BVariantRetrieveNumeric(pVariant, &llValue); + + hr = VerVersionFromQword(llValue, ppValue); break; case BURN_VARIANT_TYPE_FORMATTED: __fallthrough; case BURN_VARIANT_TYPE_STRING: hr = BVariantRetrieveDecryptedString(pVariant, &sczValue); if (SUCCEEDED(hr)) { - hr = FileVersionFromStringEx(sczValue, 0, pqwValue); + hr = VerParseVersion(sczValue, 0, FALSE, ppValue); if (FAILED(hr)) { hr = DISP_E_TYPEMISMATCH; @@ -153,7 +156,9 @@ extern "C" HRESULT BVariantGetVersion( StrSecureZeroFreeString(sczValue); break; case BURN_VARIANT_TYPE_VERSION: - BVariantRetrieveVersion(pVariant, pqwValue); + BVariantRetrieveVersion(pVariant, &pValue); + + hr = VerCopyVersion(pValue, ppValue); break; default: hr = E_INVALIDARG; @@ -224,7 +229,7 @@ LExit: extern "C" HRESULT BVariantSetVersion( __in BURN_VARIANT* pVariant, - __in DWORD64 qwValue + __in VERUTIL_VERSION* pValue ) { HRESULT hr = S_OK; @@ -236,7 +241,7 @@ extern "C" HRESULT BVariantSetVersion( StrSecureZeroFreeString(pVariant->sczValue); } memset(pVariant, 0, sizeof(BURN_VARIANT)); - pVariant->qwValue = qwValue; + hr = VerCopyVersion(pValue, &pVariant->pValue); pVariant->Type = BURN_VARIANT_TYPE_VERSION; BVariantSetEncryption(pVariant, fEncryptValue); @@ -251,7 +256,7 @@ extern "C" HRESULT BVariantSetValue( HRESULT hr = S_OK; LONGLONG llValue = 0; LPWSTR sczValue = NULL; - DWORD64 qwValue = 0; + VERUTIL_VERSION* pVersionValue = NULL; BOOL fEncrypt = pVariant->fEncryptString; switch (pValue->Type) @@ -277,12 +282,11 @@ extern "C" HRESULT BVariantSetValue( StrSecureZeroFreeString(sczValue); break; case BURN_VARIANT_TYPE_VERSION: - hr = BVariantGetVersion(pValue, &qwValue); + hr = BVariantGetVersion(pValue, &pVersionValue); if (SUCCEEDED(hr)) { - hr = BVariantSetVersion(pVariant, qwValue); + hr = BVariantSetVersion(pVariant, pVersionValue); } - SecureZeroMemory(&qwValue, sizeof(qwValue)); break; default: hr = E_INVALIDARG; @@ -303,7 +307,7 @@ extern "C" HRESULT BVariantCopy( HRESULT hr = S_OK; LONGLONG llValue = 0; LPWSTR sczValue = NULL; - DWORD64 qwValue = 0; + VERUTIL_VERSION* pVersionValue = 0; BVariantUninitialize(pTarget); @@ -329,12 +333,11 @@ extern "C" HRESULT BVariantCopy( StrSecureZeroFreeString(sczValue); break; case BURN_VARIANT_TYPE_VERSION: - hr = BVariantGetVersion(pSource, &qwValue); + hr = BVariantGetVersion(pSource, &pVersionValue); if (SUCCEEDED(hr)) { - hr = BVariantSetVersion(pTarget, qwValue); + hr = BVariantSetVersion(pTarget, pVersionValue); } - SecureZeroMemory(&qwValue, sizeof(qwValue)); break; default: hr = E_INVALIDARG; @@ -380,13 +383,13 @@ extern "C" HRESULT BVariantChangeType( hr = BVariantGetString(pVariant, &variant.sczValue); break; case BURN_VARIANT_TYPE_VERSION: - hr = BVariantGetVersion(pVariant, &variant.qwValue); + hr = BVariantGetVersion(pVariant, &variant.pValue); break; default: ExitFunction1(hr = E_INVALIDARG); } - ExitOnFailure(hr, "Failed to copy variant value."); variant.Type = type; + ExitOnFailure(hr, "Failed to copy variant value."); BVariantUninitialize(pVariant); memcpy_s(pVariant, sizeof(BURN_VARIANT), &variant, sizeof(BURN_VARIANT)); @@ -524,10 +527,10 @@ LExit: static void BVariantRetrieveVersion( __in BURN_VARIANT* pVariant, - __out DWORD64* pqwValue + __out VERUTIL_VERSION** ppValue ) { - Assert(NULL != pqwValue); + Assert(ppValue); - *pqwValue = pVariant->qwValue; + *ppValue = pVariant->pValue; } diff --git a/src/engine/variant.h b/src/engine/variant.h index 35463479..23303e02 100644 --- a/src/engine/variant.h +++ b/src/engine/variant.h @@ -26,7 +26,7 @@ typedef struct _BURN_VARIANT union { LONGLONG llValue; - DWORD64 qwValue; + VERUTIL_VERSION* pValue; LPWSTR sczValue; }; BURN_VARIANT_TYPE Type; @@ -49,7 +49,7 @@ HRESULT BVariantGetString( ); HRESULT BVariantGetVersion( __in BURN_VARIANT* pVariant, - __out DWORD64* pqwValue + __out VERUTIL_VERSION** ppValue ); HRESULT BVariantSetNumeric( __in BURN_VARIANT* pVariant, @@ -63,7 +63,7 @@ HRESULT BVariantSetString( ); HRESULT BVariantSetVersion( __in BURN_VARIANT* pVariant, - __in DWORD64 qwValue + __in VERUTIL_VERSION* pValue ); /******************************************************************** BVariantSetValue - Convenience function that calls BVariantUninitialize, -- cgit v1.2.3-55-g6feb