diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2020-10-18 14:05:51 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2020-10-24 20:07:21 -0500 |
commit | bafc4f682a798eb375d32c1f4777664aceb1e15f (patch) | |
tree | cc9bcec75252a7e4025e6efc28f1918ac8361e62 | |
parent | 273c69f34311f4f4e5f6b5896e71d0788f12d96a (diff) | |
download | wix-bafc4f682a798eb375d32c1f4777664aceb1e15f.tar.gz wix-bafc4f682a798eb375d32c1f4777664aceb1e15f.tar.bz2 wix-bafc4f682a798eb375d32c1f4777664aceb1e15f.zip |
Update string versioning.
Update condition parsing to allow specific characters for versions.
Log every time an invalid version is parsed.
-rw-r--r-- | src/engine/condition.cpp | 125 | ||||
-rw-r--r-- | src/engine/engine.mc | 42 | ||||
-rw-r--r-- | src/engine/msiengine.cpp | 35 | ||||
-rw-r--r-- | src/engine/registration.cpp | 5 | ||||
-rw-r--r-- | src/engine/relatedbundle.cpp | 5 | ||||
-rw-r--r-- | src/engine/variable.cpp | 12 | ||||
-rw-r--r-- | src/engine/variant.cpp | 46 | ||||
-rw-r--r-- | src/engine/variant.h | 10 | ||||
-rw-r--r-- | src/test/BurnUnitTest/VariableTest.cpp | 1 |
9 files changed, 225 insertions, 56 deletions
diff --git a/src/engine/condition.cpp b/src/engine/condition.cpp index 32a7a0b8..224eb0da 100644 --- a/src/engine/condition.cpp +++ b/src/engine/condition.cpp | |||
@@ -73,6 +73,12 @@ struct BURN_CONDITION_PARSE_CONTEXT | |||
73 | BOOL fError; | 73 | BOOL fError; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | struct BURN_CONDITION_OPERAND | ||
77 | { | ||
78 | BOOL fHidden; | ||
79 | BURN_VARIANT Value; | ||
80 | }; | ||
81 | |||
76 | 82 | ||
77 | // internal function declarations | 83 | // internal function declarations |
78 | 84 | ||
@@ -92,9 +98,9 @@ static HRESULT ParseTerm( | |||
92 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, | 98 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, |
93 | __out BOOL* pf | 99 | __out BOOL* pf |
94 | ); | 100 | ); |
95 | static HRESULT ParseValue( | 101 | static HRESULT ParseOperand( |
96 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, | 102 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, |
97 | __out BURN_VARIANT* pValue | 103 | __out BURN_CONDITION_OPERAND* pOperand |
98 | ); | 104 | ); |
99 | static HRESULT Expect( | 105 | static HRESULT Expect( |
100 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, | 106 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, |
@@ -103,10 +109,10 @@ static HRESULT Expect( | |||
103 | static HRESULT NextSymbol( | 109 | static HRESULT NextSymbol( |
104 | __in BURN_CONDITION_PARSE_CONTEXT* pContext | 110 | __in BURN_CONDITION_PARSE_CONTEXT* pContext |
105 | ); | 111 | ); |
106 | static HRESULT CompareValues( | 112 | static HRESULT CompareOperands( |
107 | __in BURN_SYMBOL_TYPE comparison, | 113 | __in BURN_SYMBOL_TYPE comparison, |
108 | __in BURN_VARIANT leftOperand, | 114 | __in BURN_CONDITION_OPERAND* pLeftOperand, |
109 | __in BURN_VARIANT rightOperand, | 115 | __in BURN_CONDITION_OPERAND* pRightOperand, |
110 | __out BOOL* pfResult | 116 | __out BOOL* pfResult |
111 | ); | 117 | ); |
112 | static HRESULT CompareStringValues( | 118 | static HRESULT CompareStringValues( |
@@ -342,8 +348,8 @@ static HRESULT ParseTerm( | |||
342 | ) | 348 | ) |
343 | { | 349 | { |
344 | HRESULT hr = S_OK; | 350 | HRESULT hr = S_OK; |
345 | BURN_VARIANT firstValue = { }; | 351 | BURN_CONDITION_OPERAND firstOperand = { }; |
346 | BURN_VARIANT secondValue = { }; | 352 | BURN_CONDITION_OPERAND secondOperand = { }; |
347 | 353 | ||
348 | if (BURN_SYMBOL_TYPE_LPAREN == pContext->NextSymbol.Type) | 354 | if (BURN_SYMBOL_TYPE_LPAREN == pContext->NextSymbol.Type) |
349 | { | 355 | { |
@@ -359,8 +365,8 @@ static HRESULT ParseTerm( | |||
359 | ExitFunction1(hr = S_OK); | 365 | ExitFunction1(hr = S_OK); |
360 | } | 366 | } |
361 | 367 | ||
362 | hr = ParseValue(pContext, &firstValue); | 368 | hr = ParseOperand(pContext, &firstOperand); |
363 | ExitOnFailure(hr, "Failed to parse value."); | 369 | ExitOnFailure(hr, "Failed to parse operand."); |
364 | 370 | ||
365 | if (COMPARISON & pContext->NextSymbol.Type) | 371 | if (COMPARISON & pContext->NextSymbol.Type) |
366 | { | 372 | { |
@@ -369,24 +375,24 @@ static HRESULT ParseTerm( | |||
369 | hr = NextSymbol(pContext); | 375 | hr = NextSymbol(pContext); |
370 | ExitOnFailure(hr, "Failed to read next symbol."); | 376 | ExitOnFailure(hr, "Failed to read next symbol."); |
371 | 377 | ||
372 | hr = ParseValue(pContext, &secondValue); | 378 | hr = ParseOperand(pContext, &secondOperand); |
373 | ExitOnFailure(hr, "Failed to parse value."); | 379 | ExitOnFailure(hr, "Failed to parse operand."); |
374 | 380 | ||
375 | hr = CompareValues(comparison, firstValue, secondValue, pf); | 381 | hr = CompareOperands(comparison, &firstOperand, &secondOperand, pf); |
376 | ExitOnFailure(hr, "Failed to compare value."); | 382 | ExitOnFailure(hr, "Failed to compare operands."); |
377 | } | 383 | } |
378 | else | 384 | else |
379 | { | 385 | { |
380 | LONGLONG llValue = 0; | 386 | LONGLONG llValue = 0; |
381 | LPWSTR sczValue = NULL; | 387 | LPWSTR sczValue = NULL; |
382 | VERUTIL_VERSION* pVersion = NULL; | 388 | VERUTIL_VERSION* pVersion = NULL; |
383 | switch (firstValue.Type) | 389 | switch (firstOperand.Value.Type) |
384 | { | 390 | { |
385 | case BURN_VARIANT_TYPE_NONE: | 391 | case BURN_VARIANT_TYPE_NONE: |
386 | *pf = FALSE; | 392 | *pf = FALSE; |
387 | break; | 393 | break; |
388 | case BURN_VARIANT_TYPE_STRING: | 394 | case BURN_VARIANT_TYPE_STRING: |
389 | hr = BVariantGetString(&firstValue, &sczValue); | 395 | hr = BVariantGetString(&firstOperand.Value, &sczValue); |
390 | if (SUCCEEDED(hr)) | 396 | if (SUCCEEDED(hr)) |
391 | { | 397 | { |
392 | *pf = sczValue && *sczValue; | 398 | *pf = sczValue && *sczValue; |
@@ -394,7 +400,7 @@ static HRESULT ParseTerm( | |||
394 | StrSecureZeroFreeString(sczValue); | 400 | StrSecureZeroFreeString(sczValue); |
395 | break; | 401 | break; |
396 | case BURN_VARIANT_TYPE_NUMERIC: | 402 | case BURN_VARIANT_TYPE_NUMERIC: |
397 | hr = BVariantGetNumeric(&firstValue, &llValue); | 403 | hr = BVariantGetNumeric(&firstOperand.Value, &llValue); |
398 | if (SUCCEEDED(hr)) | 404 | if (SUCCEEDED(hr)) |
399 | { | 405 | { |
400 | *pf = 0 != llValue; | 406 | *pf = 0 != llValue; |
@@ -402,7 +408,7 @@ static HRESULT ParseTerm( | |||
402 | SecureZeroMemory(&llValue, sizeof(llValue)); | 408 | SecureZeroMemory(&llValue, sizeof(llValue)); |
403 | break; | 409 | break; |
404 | case BURN_VARIANT_TYPE_VERSION: | 410 | case BURN_VARIANT_TYPE_VERSION: |
405 | hr = BVariantGetVersion(&firstValue, &pVersion); | 411 | hr = BVariantGetVersionHidden(&firstOperand.Value, firstOperand.fHidden, &pVersion); |
406 | if (SUCCEEDED(hr)) | 412 | if (SUCCEEDED(hr)) |
407 | { | 413 | { |
408 | *pf = 0 != *pVersion->sczVersion; | 414 | *pf = 0 != *pVersion->sczVersion; |
@@ -415,14 +421,14 @@ static HRESULT ParseTerm( | |||
415 | } | 421 | } |
416 | 422 | ||
417 | LExit: | 423 | LExit: |
418 | BVariantUninitialize(&firstValue); | 424 | BVariantUninitialize(&firstOperand.Value); |
419 | BVariantUninitialize(&secondValue); | 425 | BVariantUninitialize(&secondOperand.Value); |
420 | return hr; | 426 | return hr; |
421 | } | 427 | } |
422 | 428 | ||
423 | static HRESULT ParseValue( | 429 | static HRESULT ParseOperand( |
424 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, | 430 | __in BURN_CONDITION_PARSE_CONTEXT* pContext, |
425 | __out BURN_VARIANT* pValue | 431 | __out BURN_CONDITION_OPERAND* pOperand |
426 | ) | 432 | ) |
427 | { | 433 | { |
428 | HRESULT hr = S_OK; | 434 | HRESULT hr = S_OK; |
@@ -434,16 +440,19 @@ static HRESULT ParseValue( | |||
434 | Assert(BURN_VARIANT_TYPE_STRING == pContext->NextSymbol.Value.Type); | 440 | Assert(BURN_VARIANT_TYPE_STRING == pContext->NextSymbol.Value.Type); |
435 | 441 | ||
436 | // find variable | 442 | // find variable |
437 | hr = VariableGetVariant(pContext->pVariables, pContext->NextSymbol.Value.sczValue, pValue); | 443 | hr = VariableGetVariant(pContext->pVariables, pContext->NextSymbol.Value.sczValue, &pOperand->Value); |
438 | if (E_NOTFOUND != hr) | 444 | if (E_NOTFOUND != hr) |
439 | { | 445 | { |
440 | ExitOnRootFailure(hr, "Failed to find variable."); | 446 | ExitOnRootFailure(hr, "Failed to find variable."); |
447 | |||
448 | hr = VariableIsHidden(pContext->pVariables, pContext->NextSymbol.Value.sczValue, &pOperand->fHidden); | ||
449 | ExitOnRootFailure(hr, "Failed to get if variable is hidden."); | ||
441 | } | 450 | } |
442 | 451 | ||
443 | if (BURN_VARIANT_TYPE_FORMATTED == pValue->Type) | 452 | if (BURN_VARIANT_TYPE_FORMATTED == pOperand->Value.Type) |
444 | { | 453 | { |
445 | // TODO: actually format the value? | 454 | // TODO: actually format the value? |
446 | hr = BVariantChangeType(pValue, BURN_VARIANT_TYPE_STRING); | 455 | hr = BVariantChangeType(&pOperand->Value, BURN_VARIANT_TYPE_STRING); |
447 | ExitOnRootFailure(hr, "Failed to change variable '%ls' type for condition '%ls'", pContext->NextSymbol.Value.sczValue, pContext->wzCondition); | 456 | ExitOnRootFailure(hr, "Failed to change variable '%ls' type for condition '%ls'", pContext->NextSymbol.Value.sczValue, pContext->wzCondition); |
448 | } | 457 | } |
449 | break; | 458 | break; |
@@ -451,8 +460,9 @@ static HRESULT ParseValue( | |||
451 | case BURN_SYMBOL_TYPE_NUMBER: __fallthrough; | 460 | case BURN_SYMBOL_TYPE_NUMBER: __fallthrough; |
452 | case BURN_SYMBOL_TYPE_LITERAL: __fallthrough; | 461 | case BURN_SYMBOL_TYPE_LITERAL: __fallthrough; |
453 | case BURN_SYMBOL_TYPE_VERSION: | 462 | case BURN_SYMBOL_TYPE_VERSION: |
463 | pOperand->fHidden = FALSE; | ||
454 | // steal value of symbol | 464 | // steal value of symbol |
455 | memcpy_s(pValue, sizeof(BURN_VARIANT), &pContext->NextSymbol.Value, sizeof(BURN_VARIANT)); | 465 | memcpy_s(&pOperand->Value, sizeof(BURN_VARIANT), &pContext->NextSymbol.Value, sizeof(BURN_VARIANT)); |
456 | memset(&pContext->NextSymbol.Value, 0, sizeof(BURN_VARIANT)); | 466 | memset(&pContext->NextSymbol.Value, 0, sizeof(BURN_VARIANT)); |
457 | break; | 467 | break; |
458 | 468 | ||
@@ -692,8 +702,13 @@ static HRESULT NextSymbol( | |||
692 | do | 702 | do |
693 | { | 703 | { |
694 | ++n; | 704 | ++n; |
695 | ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType); | 705 | } while (pContext->wzRead[n] >= L'0' && pContext->wzRead[n] <= L'9' || |
696 | } while (L'\0' != pContext->wzRead[n] && C1_BLANK != (C1_BLANK & charType)); | 706 | pContext->wzRead[n] >= L'A' && pContext->wzRead[n] <= L'Z' || |
707 | pContext->wzRead[n] >= L'a' && pContext->wzRead[n] <= L'z' || | ||
708 | pContext->wzRead[n] == L'_' || | ||
709 | pContext->wzRead[n] == L'+' || | ||
710 | pContext->wzRead[n] == L'-' || | ||
711 | pContext->wzRead[n] == L'.'); | ||
697 | 712 | ||
698 | // Symbols don't encrypt their value, so can access the value directly. | 713 | // Symbols don't encrypt their value, so can access the value directly. |
699 | hr = VerParseVersion(&pContext->wzRead[1], n - 1, FALSE, &pContext->NextSymbol.Value.pValue); | 714 | hr = VerParseVersion(&pContext->wzRead[1], n - 1, FALSE, &pContext->NextSymbol.Value.pValue); |
@@ -703,6 +718,10 @@ static HRESULT NextSymbol( | |||
703 | hr = E_INVALIDDATA; | 718 | hr = E_INVALIDDATA; |
704 | ExitOnRootFailure(hr, "Failed to parse condition \"%ls\". Invalid version format, at position %d.", pContext->wzCondition, iPosition); | 719 | ExitOnRootFailure(hr, "Failed to parse condition \"%ls\". Invalid version format, at position %d.", pContext->wzCondition, iPosition); |
705 | } | 720 | } |
721 | else if (pContext->NextSymbol.Value.pValue->fInvalid) | ||
722 | { | ||
723 | LogId(REPORT_WARNING, MSG_CONDITION_INVALID_VERSION, pContext->wzCondition, pContext->NextSymbol.Value.pValue->sczVersion); | ||
724 | } | ||
706 | 725 | ||
707 | pContext->NextSymbol.Value.Type = BURN_VARIANT_TYPE_VERSION; | 726 | pContext->NextSymbol.Value.Type = BURN_VARIANT_TYPE_VERSION; |
708 | pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_VERSION; | 727 | pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_VERSION; |
@@ -755,12 +774,12 @@ LExit: | |||
755 | } | 774 | } |
756 | 775 | ||
757 | // | 776 | // |
758 | // CompareValues - compares two variant values using a given comparison. | 777 | // CompareOperands - compares two variant values using a given comparison. |
759 | // | 778 | // |
760 | static HRESULT CompareValues( | 779 | static HRESULT CompareOperands( |
761 | __in BURN_SYMBOL_TYPE comparison, | 780 | __in BURN_SYMBOL_TYPE comparison, |
762 | __in BURN_VARIANT leftOperand, | 781 | __in BURN_CONDITION_OPERAND* pLeftOperand, |
763 | __in BURN_VARIANT rightOperand, | 782 | __in BURN_CONDITION_OPERAND* pRightOperand, |
764 | __out BOOL* pfResult | 783 | __out BOOL* pfResult |
765 | ) | 784 | ) |
766 | { | 785 | { |
@@ -771,37 +790,39 @@ static HRESULT CompareValues( | |||
771 | LONGLONG llRight = 0; | 790 | LONGLONG llRight = 0; |
772 | VERUTIL_VERSION* pVersionRight = 0; | 791 | VERUTIL_VERSION* pVersionRight = 0; |
773 | LPWSTR sczRight = NULL; | 792 | LPWSTR sczRight = NULL; |
793 | BURN_VARIANT* pLeftValue = &pLeftOperand->Value; | ||
794 | BURN_VARIANT* pRightValue = &pRightOperand->Value; | ||
774 | 795 | ||
775 | // get values to compare based on type | 796 | // get values to compare based on type |
776 | if (BURN_VARIANT_TYPE_STRING == leftOperand.Type && BURN_VARIANT_TYPE_STRING == rightOperand.Type) | 797 | if (BURN_VARIANT_TYPE_STRING == pLeftValue->Type && BURN_VARIANT_TYPE_STRING == pRightValue->Type) |
777 | { | 798 | { |
778 | hr = BVariantGetString(&leftOperand, &sczLeft); | 799 | hr = BVariantGetString(pLeftValue, &sczLeft); |
779 | ExitOnFailure(hr, "Failed to get the left string"); | 800 | ExitOnFailure(hr, "Failed to get the left string"); |
780 | hr = BVariantGetString(&rightOperand, &sczRight); | 801 | hr = BVariantGetString(pRightValue, &sczRight); |
781 | ExitOnFailure(hr, "Failed to get the right string"); | 802 | ExitOnFailure(hr, "Failed to get the right string"); |
782 | hr = CompareStringValues(comparison, sczLeft, sczRight, pfResult); | 803 | hr = CompareStringValues(comparison, sczLeft, sczRight, pfResult); |
783 | } | 804 | } |
784 | else if (BURN_VARIANT_TYPE_NUMERIC == leftOperand.Type && BURN_VARIANT_TYPE_NUMERIC == rightOperand.Type) | 805 | else if (BURN_VARIANT_TYPE_NUMERIC == pLeftValue->Type && BURN_VARIANT_TYPE_NUMERIC == pRightValue->Type) |
785 | { | 806 | { |
786 | hr = BVariantGetNumeric(&leftOperand, &llLeft); | 807 | hr = BVariantGetNumeric(pLeftValue, &llLeft); |
787 | ExitOnFailure(hr, "Failed to get the left numeric"); | 808 | ExitOnFailure(hr, "Failed to get the left numeric"); |
788 | hr = BVariantGetNumeric(&rightOperand, &llRight); | 809 | hr = BVariantGetNumeric(pRightValue, &llRight); |
789 | ExitOnFailure(hr, "Failed to get the right numeric"); | 810 | ExitOnFailure(hr, "Failed to get the right numeric"); |
790 | hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult); | 811 | hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult); |
791 | } | 812 | } |
792 | else if (BURN_VARIANT_TYPE_VERSION == leftOperand.Type && BURN_VARIANT_TYPE_VERSION == rightOperand.Type) | 813 | else if (BURN_VARIANT_TYPE_VERSION == pLeftValue->Type && BURN_VARIANT_TYPE_VERSION == pRightValue->Type) |
793 | { | 814 | { |
794 | hr = BVariantGetVersion(&leftOperand, &pVersionLeft); | 815 | hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft); |
795 | ExitOnFailure(hr, "Failed to get the left version"); | 816 | ExitOnFailure(hr, "Failed to get the left version"); |
796 | hr = BVariantGetVersion(&rightOperand, &pVersionRight); | 817 | hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight); |
797 | ExitOnFailure(hr, "Failed to get the right version"); | 818 | ExitOnFailure(hr, "Failed to get the right version"); |
798 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); | 819 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); |
799 | } | 820 | } |
800 | else if (BURN_VARIANT_TYPE_VERSION == leftOperand.Type && BURN_VARIANT_TYPE_STRING == rightOperand.Type) | 821 | else if (BURN_VARIANT_TYPE_VERSION == pLeftValue->Type && BURN_VARIANT_TYPE_STRING == pRightValue->Type) |
801 | { | 822 | { |
802 | hr = BVariantGetVersion(&leftOperand, &pVersionLeft); | 823 | hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft); |
803 | ExitOnFailure(hr, "Failed to get the left version"); | 824 | ExitOnFailure(hr, "Failed to get the left version"); |
804 | hr = BVariantGetVersion(&rightOperand, &pVersionRight); | 825 | hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight); |
805 | if (FAILED(hr)) | 826 | if (FAILED(hr)) |
806 | { | 827 | { |
807 | if (DISP_E_TYPEMISMATCH != hr) | 828 | if (DISP_E_TYPEMISMATCH != hr) |
@@ -816,11 +837,11 @@ static HRESULT CompareValues( | |||
816 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); | 837 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); |
817 | } | 838 | } |
818 | } | 839 | } |
819 | else if (BURN_VARIANT_TYPE_STRING == leftOperand.Type && BURN_VARIANT_TYPE_VERSION == rightOperand.Type) | 840 | else if (BURN_VARIANT_TYPE_STRING == pLeftValue->Type && BURN_VARIANT_TYPE_VERSION == pRightValue->Type) |
820 | { | 841 | { |
821 | hr = BVariantGetVersion(&rightOperand, &pVersionRight); | 842 | hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight); |
822 | ExitOnFailure(hr, "Failed to get the right version"); | 843 | ExitOnFailure(hr, "Failed to get the right version"); |
823 | hr = BVariantGetVersion(&leftOperand, &pVersionLeft); | 844 | hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft); |
824 | if (FAILED(hr)) | 845 | if (FAILED(hr)) |
825 | { | 846 | { |
826 | if (DISP_E_TYPEMISMATCH != hr) | 847 | if (DISP_E_TYPEMISMATCH != hr) |
@@ -835,11 +856,11 @@ static HRESULT CompareValues( | |||
835 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); | 856 | hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult); |
836 | } | 857 | } |
837 | } | 858 | } |
838 | else if (BURN_VARIANT_TYPE_NUMERIC == leftOperand.Type && BURN_VARIANT_TYPE_STRING == rightOperand.Type) | 859 | else if (BURN_VARIANT_TYPE_NUMERIC == pLeftValue->Type && BURN_VARIANT_TYPE_STRING == pRightValue->Type) |
839 | { | 860 | { |
840 | hr = BVariantGetNumeric(&leftOperand, &llLeft); | 861 | hr = BVariantGetNumeric(pLeftValue, &llLeft); |
841 | ExitOnFailure(hr, "Failed to get the left numeric"); | 862 | ExitOnFailure(hr, "Failed to get the left numeric"); |
842 | hr = BVariantGetNumeric(&rightOperand, &llRight); | 863 | hr = BVariantGetNumeric(pRightValue, &llRight); |
843 | if (FAILED(hr)) | 864 | if (FAILED(hr)) |
844 | { | 865 | { |
845 | if (DISP_E_TYPEMISMATCH != hr) | 866 | if (DISP_E_TYPEMISMATCH != hr) |
@@ -854,11 +875,11 @@ static HRESULT CompareValues( | |||
854 | hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult); | 875 | hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult); |
855 | } | 876 | } |
856 | } | 877 | } |
857 | else if (BURN_VARIANT_TYPE_STRING == leftOperand.Type && BURN_VARIANT_TYPE_NUMERIC == rightOperand.Type) | 878 | else if (BURN_VARIANT_TYPE_STRING == pLeftValue->Type && BURN_VARIANT_TYPE_NUMERIC == pRightValue->Type) |
858 | { | 879 | { |
859 | hr = BVariantGetNumeric(&rightOperand, &llRight); | 880 | hr = BVariantGetNumeric(pRightValue, &llRight); |
860 | ExitOnFailure(hr, "Failed to get the right numeric"); | 881 | ExitOnFailure(hr, "Failed to get the right numeric"); |
861 | hr = BVariantGetNumeric(&leftOperand, &llLeft); | 882 | hr = BVariantGetNumeric(pLeftValue, &llLeft); |
862 | if (FAILED(hr)) | 883 | if (FAILED(hr)) |
863 | { | 884 | { |
864 | if (DISP_E_TYPEMISMATCH != hr) | 885 | if (DISP_E_TYPEMISMATCH != hr) |
diff --git a/src/engine/engine.mc b/src/engine/engine.mc index fb2dd6e9..c8cd6d37 100644 --- a/src/engine/engine.mc +++ b/src/engine/engine.mc | |||
@@ -114,6 +114,13 @@ Language=English | |||
114 | Connected to elevated engine. | 114 | Connected to elevated engine. |
115 | . | 115 | . |
116 | 116 | ||
117 | MessageId=13 | ||
118 | Severity=Warning | ||
119 | SymbolicName=MSG_MANIFEST_INVALID_VERSION | ||
120 | Language=English | ||
121 | The manifest contains an invalid version string: '%1!ls!' | ||
122 | . | ||
123 | |||
117 | MessageId=51 | 124 | MessageId=51 |
118 | Severity=Error | 125 | Severity=Error |
119 | SymbolicName=MSG_FAILED_PARSE_CONDITION | 126 | SymbolicName=MSG_FAILED_PARSE_CONDITION |
@@ -156,6 +163,13 @@ Language=English | |||
156 | Application canceled operation: %2!ls!, error: %1!ls! | 163 | Application canceled operation: %2!ls!, error: %1!ls! |
157 | . | 164 | . |
158 | 165 | ||
166 | MessageId=57 | ||
167 | Severity=Warning | ||
168 | SymbolicName=MSG_CONDITION_INVALID_VERSION | ||
169 | Language=English | ||
170 | Condition '%1!ls!' contains invalid version string '%2!ls!'. | ||
171 | . | ||
172 | |||
159 | MessageId=100 | 173 | MessageId=100 |
160 | Severity=Success | 174 | Severity=Success |
161 | SymbolicName=MSG_DETECT_BEGIN | 175 | SymbolicName=MSG_DETECT_BEGIN |
@@ -233,6 +247,20 @@ Language=English | |||
233 | Could not calculate patch applicability for target product code: %1!ls!, context: %2!hs!, reason: 0x%3!x! | 247 | Could not calculate patch applicability for target product code: %1!ls!, context: %2!hs!, reason: 0x%3!x! |
234 | . | 248 | . |
235 | 249 | ||
250 | MessageId=122 | ||
251 | Severity=Warning | ||
252 | SymbolicName=MSG_RELATED_PACKAGE_INVALID_VERSION | ||
253 | Language=English | ||
254 | Related package: '%1!ls!' has invalid version: %2!ls! | ||
255 | . | ||
256 | |||
257 | MessageId=123 | ||
258 | Severity=Warning | ||
259 | SymbolicName=MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION | ||
260 | Language=English | ||
261 | Detected msi package with invalid version, product code: '%1!ls!', version: '%2!ls!' | ||
262 | . | ||
263 | |||
236 | MessageId=151 | 264 | MessageId=151 |
237 | Severity=Error | 265 | Severity=Error |
238 | SymbolicName=MSG_FAILED_DETECT_PACKAGE | 266 | SymbolicName=MSG_FAILED_DETECT_PACKAGE |
@@ -836,6 +864,20 @@ Language=English | |||
836 | Variable: %1!ls! | 864 | Variable: %1!ls! |
837 | . | 865 | . |
838 | 866 | ||
867 | MessageId=411 | ||
868 | Severity=Warning | ||
869 | SymbolicName=MSG_VARIABLE_INVALID_VERSION | ||
870 | Language=English | ||
871 | The variable '%1!ls!' is being set with an invalid version string. | ||
872 | . | ||
873 | |||
874 | MessageId=412 | ||
875 | Severity=Warning | ||
876 | SymbolicName=MSG_INVALID_VERSION_COERSION | ||
877 | Language=English | ||
878 | The string '%1!ls!' could not be coerced to a valid version. | ||
879 | . | ||
880 | |||
839 | MessageId=420 | 881 | MessageId=420 |
840 | Severity=Success | 882 | Severity=Success |
841 | SymbolicName=MSG_RESUME_AU_STARTING | 883 | SymbolicName=MSG_RESUME_AU_STARTING |
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp index e274df28..47211309 100644 --- a/src/engine/msiengine.cpp +++ b/src/engine/msiengine.cpp | |||
@@ -82,6 +82,11 @@ extern "C" HRESULT MsiEngineParsePackageFromXml( | |||
82 | hr = VerParseVersion(scz, 0, FALSE, &pPackage->Msi.pVersion); | 82 | hr = VerParseVersion(scz, 0, FALSE, &pPackage->Msi.pVersion); |
83 | ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); | 83 | ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); |
84 | 84 | ||
85 | if (pPackage->Msi.pVersion->fInvalid) | ||
86 | { | ||
87 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
88 | } | ||
89 | |||
85 | // @UpgradeCode | 90 | // @UpgradeCode |
86 | hr = XmlGetAttributeEx(pixnMsiPackage, L"UpgradeCode", &pPackage->Msi.sczUpgradeCode); | 91 | hr = XmlGetAttributeEx(pixnMsiPackage, L"UpgradeCode", &pPackage->Msi.sczUpgradeCode); |
87 | if (E_NOTFOUND != hr) | 92 | if (E_NOTFOUND != hr) |
@@ -420,6 +425,11 @@ extern "C" HRESULT MsiEngineDetectPackage( | |||
420 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pPackage->Msi.pInstalledVersion); | 425 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pPackage->Msi.pInstalledVersion); |
421 | ExitOnFailure(hr, "Failed to parse installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode); | 426 | ExitOnFailure(hr, "Failed to parse installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode); |
422 | 427 | ||
428 | if (pPackage->Msi.pInstalledVersion->fInvalid) | ||
429 | { | ||
430 | LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, pPackage->Msi.sczProductCode, sczInstalledVersion); | ||
431 | } | ||
432 | |||
423 | // compare versions | 433 | // compare versions |
424 | hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->Msi.pInstalledVersion, &nCompareResult); | 434 | hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->Msi.pInstalledVersion, &nCompareResult); |
425 | ExitOnFailure(hr, "Failed to compare version '%ls' to installed version: '%ls'", pPackage->Msi.pVersion->sczVersion, pPackage->Msi.pInstalledVersion->sczVersion); | 435 | ExitOnFailure(hr, "Failed to compare version '%ls' to installed version: '%ls'", pPackage->Msi.pVersion->sczVersion, pPackage->Msi.pInstalledVersion->sczVersion); |
@@ -460,6 +470,11 @@ extern "C" HRESULT MsiEngineDetectPackage( | |||
460 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); | 470 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); |
461 | ExitOnFailure(hr, "Failed to parse dependency version: '%ls' for ProductCode: %ls", sczInstalledVersion, sczInstalledProductCode); | 471 | ExitOnFailure(hr, "Failed to parse dependency version: '%ls' for ProductCode: %ls", sczInstalledVersion, sczInstalledProductCode); |
462 | 472 | ||
473 | if (pVersion->fInvalid) | ||
474 | { | ||
475 | LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, sczInstalledProductCode, sczInstalledVersion); | ||
476 | } | ||
477 | |||
463 | // compare versions | 478 | // compare versions |
464 | hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pVersion, &nCompareResult); | 479 | hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pVersion, &nCompareResult); |
465 | ExitOnFailure(hr, "Failed to compare version '%ls' to dependency version: '%ls'", pPackage->Msi.pVersion->sczVersion, pVersion->sczVersion); | 480 | ExitOnFailure(hr, "Failed to compare version '%ls' to dependency version: '%ls'", pPackage->Msi.pVersion->sczVersion, pVersion->sczVersion); |
@@ -536,6 +551,11 @@ extern "C" HRESULT MsiEngineDetectPackage( | |||
536 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); | 551 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion); |
537 | ExitOnFailure(hr, "Failed to parse related installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, wzProductCode); | 552 | ExitOnFailure(hr, "Failed to parse related installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, wzProductCode); |
538 | 553 | ||
554 | if (pVersion->fInvalid) | ||
555 | { | ||
556 | LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, wzProductCode, sczInstalledVersion); | ||
557 | } | ||
558 | |||
539 | // compare versions | 559 | // compare versions |
540 | if (pRelatedMsi->fMinProvided) | 560 | if (pRelatedMsi->fMinProvided) |
541 | { | 561 | { |
@@ -1052,6 +1072,11 @@ extern "C" HRESULT MsiEngineAddCompatiblePackage( | |||
1052 | 1072 | ||
1053 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pCompatiblePackage->Msi.pVersion); | 1073 | hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pCompatiblePackage->Msi.pVersion); |
1054 | ExitOnFailure(hr, "Failed to parse version: '%ls' for ProductCode: %ls", sczInstalledVersion, pCompatiblePackage->Msi.sczProductCode); | 1074 | ExitOnFailure(hr, "Failed to parse version: '%ls' for ProductCode: %ls", sczInstalledVersion, pCompatiblePackage->Msi.sczProductCode); |
1075 | |||
1076 | if (pCompatiblePackage->Msi.pVersion->fInvalid) | ||
1077 | { | ||
1078 | LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, pCompatiblePackage->Msi.sczProductCode, sczInstalledVersion); | ||
1079 | } | ||
1055 | } | 1080 | } |
1056 | 1081 | ||
1057 | // For now, copy enough information to support uninstalling the newer, compatible package. | 1082 | // For now, copy enough information to support uninstalling the newer, compatible package. |
@@ -1506,6 +1531,11 @@ static HRESULT ParseRelatedMsiFromXml( | |||
1506 | hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMinVersion); | 1531 | hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMinVersion); |
1507 | ExitOnFailure(hr, "Failed to parse @MinVersion: %ls", scz); | 1532 | ExitOnFailure(hr, "Failed to parse @MinVersion: %ls", scz); |
1508 | 1533 | ||
1534 | if (pRelatedMsi->pMinVersion->fInvalid) | ||
1535 | { | ||
1536 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
1537 | } | ||
1538 | |||
1509 | // flag that we have a min version | 1539 | // flag that we have a min version |
1510 | pRelatedMsi->fMinProvided = TRUE; | 1540 | pRelatedMsi->fMinProvided = TRUE; |
1511 | 1541 | ||
@@ -1523,6 +1553,11 @@ static HRESULT ParseRelatedMsiFromXml( | |||
1523 | hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMaxVersion); | 1553 | hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMaxVersion); |
1524 | ExitOnFailure(hr, "Failed to parse @MaxVersion: %ls", scz); | 1554 | ExitOnFailure(hr, "Failed to parse @MaxVersion: %ls", scz); |
1525 | 1555 | ||
1556 | if (pRelatedMsi->pMaxVersion->fInvalid) | ||
1557 | { | ||
1558 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
1559 | } | ||
1560 | |||
1526 | // flag that we have a max version | 1561 | // flag that we have a max version |
1527 | pRelatedMsi->fMaxProvided = TRUE; | 1562 | pRelatedMsi->fMaxProvided = TRUE; |
1528 | 1563 | ||
diff --git a/src/engine/registration.cpp b/src/engine/registration.cpp index 3c3dc95d..4e8c810d 100644 --- a/src/engine/registration.cpp +++ b/src/engine/registration.cpp | |||
@@ -136,6 +136,11 @@ extern "C" HRESULT RegistrationParseFromXml( | |||
136 | hr = VerParseVersion(scz, 0, FALSE, &pRegistration->pVersion); | 136 | hr = VerParseVersion(scz, 0, FALSE, &pRegistration->pVersion); |
137 | ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); | 137 | ExitOnFailure(hr, "Failed to parse @Version: %ls", scz); |
138 | 138 | ||
139 | if (pRegistration->pVersion->fInvalid) | ||
140 | { | ||
141 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
142 | } | ||
143 | |||
139 | // @ProviderKey | 144 | // @ProviderKey |
140 | hr = XmlGetAttributeEx(pixnRegistrationNode, L"ProviderKey", &pRegistration->sczProviderKey); | 145 | hr = XmlGetAttributeEx(pixnRegistrationNode, L"ProviderKey", &pRegistration->sczProviderKey); |
141 | ExitOnFailure(hr, "Failed to get @ProviderKey."); | 146 | ExitOnFailure(hr, "Failed to get @ProviderKey."); |
diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp index e6d6516a..7b0da4a4 100644 --- a/src/engine/relatedbundle.cpp +++ b/src/engine/relatedbundle.cpp | |||
@@ -414,6 +414,11 @@ static HRESULT LoadRelatedBundleFromKey( | |||
414 | hr = VerParseVersion(sczBundleVersion, 0, FALSE, &pRelatedBundle->pVersion); | 414 | hr = VerParseVersion(sczBundleVersion, 0, FALSE, &pRelatedBundle->pVersion); |
415 | ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", sczBundleVersion); | 415 | ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", sczBundleVersion); |
416 | 416 | ||
417 | if (pRelatedBundle->pVersion->fInvalid) | ||
418 | { | ||
419 | LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleId, sczBundleVersion); | ||
420 | } | ||
421 | |||
417 | hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath); | 422 | hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath); |
418 | ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId); | 423 | ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId); |
419 | 424 | ||
diff --git a/src/engine/variable.cpp b/src/engine/variable.cpp index 3069ccf7..c2192346 100644 --- a/src/engine/variable.cpp +++ b/src/engine/variable.cpp | |||
@@ -393,6 +393,11 @@ extern "C" HRESULT VariablesParseFromXml( | |||
393 | hr = BVariantChangeType(&value, valueType); | 393 | hr = BVariantChangeType(&value, valueType); |
394 | ExitOnFailure(hr, "Failed to change variant type."); | 394 | ExitOnFailure(hr, "Failed to change variant type."); |
395 | 395 | ||
396 | if (BURN_VARIANT_TYPE_VERSION == valueType && value.pValue->fInvalid) | ||
397 | { | ||
398 | LogId(REPORT_WARNING, MSG_VARIABLE_INVALID_VERSION, sczId); | ||
399 | } | ||
400 | |||
396 | // find existing variable | 401 | // find existing variable |
397 | hr = FindVariableIndexByName(pVariables, sczId, &iVariable); | 402 | hr = FindVariableIndexByName(pVariables, sczId, &iVariable); |
398 | ExitOnFailure(hr, "Failed to find variable value '%ls'.", sczId); | 403 | ExitOnFailure(hr, "Failed to find variable value '%ls'.", sczId); |
@@ -584,7 +589,7 @@ extern "C" HRESULT VariableGetVersion( | |||
584 | } | 589 | } |
585 | ExitOnFailure(hr, "Failed to get value of variable: %ls", wzVariable); | 590 | ExitOnFailure(hr, "Failed to get value of variable: %ls", wzVariable); |
586 | 591 | ||
587 | hr = BVariantGetVersion(&pVariable->Value, ppValue); | 592 | hr = BVariantGetVersionHidden(&pVariable->Value, pVariable->fHidden, ppValue); |
588 | ExitOnFailure(hr, "Failed to get value as version for variable: %ls", wzVariable); | 593 | ExitOnFailure(hr, "Failed to get value as version for variable: %ls", wzVariable); |
589 | 594 | ||
590 | LExit: | 595 | LExit: |
@@ -1575,6 +1580,11 @@ static HRESULT SetVariableValue( | |||
1575 | break; | 1580 | break; |
1576 | } | 1581 | } |
1577 | } | 1582 | } |
1583 | |||
1584 | if (BURN_VARIANT_TYPE_VERSION == pVariant->Type && pVariant->pValue->fInvalid) | ||
1585 | { | ||
1586 | LogId(REPORT_WARNING, MSG_VARIABLE_INVALID_VERSION, wzVariable); | ||
1587 | } | ||
1578 | } | 1588 | } |
1579 | 1589 | ||
1580 | // Update variable value. | 1590 | // Update variable value. |
diff --git a/src/engine/variant.cpp b/src/engine/variant.cpp index 28578691..9fdb82cd 100644 --- a/src/engine/variant.cpp +++ b/src/engine/variant.cpp | |||
@@ -6,6 +6,12 @@ | |||
6 | 6 | ||
7 | // internal function declarations | 7 | // internal function declarations |
8 | 8 | ||
9 | static HRESULT GetVersionInternal( | ||
10 | __in BURN_VARIANT* pVariant, | ||
11 | __in BOOL fHidden, | ||
12 | __in BOOL fSilent, | ||
13 | __out VERUTIL_VERSION** ppValue | ||
14 | ); | ||
9 | static HRESULT BVariantEncryptString( | 15 | static HRESULT BVariantEncryptString( |
10 | __in BURN_VARIANT* pVariant, | 16 | __in BURN_VARIANT* pVariant, |
11 | __in BOOL fEncrypt | 17 | __in BOOL fEncrypt |
@@ -130,6 +136,36 @@ extern "C" HRESULT BVariantGetVersion( | |||
130 | __out VERUTIL_VERSION** ppValue | 136 | __out VERUTIL_VERSION** ppValue |
131 | ) | 137 | ) |
132 | { | 138 | { |
139 | return GetVersionInternal(pVariant, FALSE, FALSE, ppValue); | ||
140 | } | ||
141 | |||
142 | // The contents of ppValue may be sensitive, should keep encrypted and SecureZeroMemory. | ||
143 | extern "C" HRESULT BVariantGetVersionHidden( | ||
144 | __in BURN_VARIANT* pVariant, | ||
145 | __in BOOL fHidden, | ||
146 | __out VERUTIL_VERSION** ppValue | ||
147 | ) | ||
148 | { | ||
149 | return GetVersionInternal(pVariant, fHidden, FALSE, ppValue); | ||
150 | } | ||
151 | |||
152 | // The contents of ppValue may be sensitive, should keep encrypted and SecureZeroMemory. | ||
153 | extern "C" HRESULT BVariantGetVersionSilent( | ||
154 | __in BURN_VARIANT* pVariant, | ||
155 | __in BOOL fSilent, | ||
156 | __out VERUTIL_VERSION** ppValue | ||
157 | ) | ||
158 | { | ||
159 | return GetVersionInternal(pVariant, FALSE, fSilent, ppValue); | ||
160 | } | ||
161 | |||
162 | static HRESULT GetVersionInternal( | ||
163 | __in BURN_VARIANT* pVariant, | ||
164 | __in BOOL fHidden, | ||
165 | __in BOOL fSilent, | ||
166 | __out VERUTIL_VERSION** ppValue | ||
167 | ) | ||
168 | { | ||
133 | HRESULT hr = S_OK; | 169 | HRESULT hr = S_OK; |
134 | LONGLONG llValue = 0; | 170 | LONGLONG llValue = 0; |
135 | LPWSTR sczValue = NULL; | 171 | LPWSTR sczValue = NULL; |
@@ -152,6 +188,10 @@ extern "C" HRESULT BVariantGetVersion( | |||
152 | { | 188 | { |
153 | hr = DISP_E_TYPEMISMATCH; | 189 | hr = DISP_E_TYPEMISMATCH; |
154 | } | 190 | } |
191 | else if (!fSilent && (*ppValue)->fInvalid) | ||
192 | { | ||
193 | LogId(REPORT_WARNING, MSG_INVALID_VERSION_COERSION, fHidden ? L"*****" : sczValue); | ||
194 | } | ||
155 | } | 195 | } |
156 | StrSecureZeroFreeString(sczValue); | 196 | StrSecureZeroFreeString(sczValue); |
157 | break; | 197 | break; |
@@ -282,7 +322,7 @@ extern "C" HRESULT BVariantSetValue( | |||
282 | StrSecureZeroFreeString(sczValue); | 322 | StrSecureZeroFreeString(sczValue); |
283 | break; | 323 | break; |
284 | case BURN_VARIANT_TYPE_VERSION: | 324 | case BURN_VARIANT_TYPE_VERSION: |
285 | hr = BVariantGetVersion(pValue, &pVersionValue); | 325 | hr = BVariantGetVersionSilent(pValue, TRUE, &pVersionValue); |
286 | if (SUCCEEDED(hr)) | 326 | if (SUCCEEDED(hr)) |
287 | { | 327 | { |
288 | hr = BVariantSetVersion(pVariant, pVersionValue); | 328 | hr = BVariantSetVersion(pVariant, pVersionValue); |
@@ -333,7 +373,7 @@ extern "C" HRESULT BVariantCopy( | |||
333 | StrSecureZeroFreeString(sczValue); | 373 | StrSecureZeroFreeString(sczValue); |
334 | break; | 374 | break; |
335 | case BURN_VARIANT_TYPE_VERSION: | 375 | case BURN_VARIANT_TYPE_VERSION: |
336 | hr = BVariantGetVersion(pSource, &pVersionValue); | 376 | hr = BVariantGetVersionSilent(pSource, TRUE, &pVersionValue); |
337 | if (SUCCEEDED(hr)) | 377 | if (SUCCEEDED(hr)) |
338 | { | 378 | { |
339 | hr = BVariantSetVersion(pTarget, pVersionValue); | 379 | hr = BVariantSetVersion(pTarget, pVersionValue); |
@@ -383,7 +423,7 @@ extern "C" HRESULT BVariantChangeType( | |||
383 | hr = BVariantGetString(pVariant, &variant.sczValue); | 423 | hr = BVariantGetString(pVariant, &variant.sczValue); |
384 | break; | 424 | break; |
385 | case BURN_VARIANT_TYPE_VERSION: | 425 | case BURN_VARIANT_TYPE_VERSION: |
386 | hr = BVariantGetVersion(pVariant, &variant.pValue); | 426 | hr = BVariantGetVersionSilent(pVariant, TRUE, &variant.pValue); |
387 | break; | 427 | break; |
388 | default: | 428 | default: |
389 | ExitFunction1(hr = E_INVALIDARG); | 429 | ExitFunction1(hr = E_INVALIDARG); |
diff --git a/src/engine/variant.h b/src/engine/variant.h index 23303e02..34d7a187 100644 --- a/src/engine/variant.h +++ b/src/engine/variant.h | |||
@@ -51,6 +51,16 @@ HRESULT BVariantGetVersion( | |||
51 | __in BURN_VARIANT* pVariant, | 51 | __in BURN_VARIANT* pVariant, |
52 | __out VERUTIL_VERSION** ppValue | 52 | __out VERUTIL_VERSION** ppValue |
53 | ); | 53 | ); |
54 | HRESULT BVariantGetVersionHidden( | ||
55 | __in BURN_VARIANT* pVariant, | ||
56 | __in BOOL fHidden, | ||
57 | __out VERUTIL_VERSION** ppValue | ||
58 | ); | ||
59 | HRESULT BVariantGetVersionSilent( | ||
60 | __in BURN_VARIANT* pVariant, | ||
61 | __in BOOL fSilent, | ||
62 | __out VERUTIL_VERSION** ppValue | ||
63 | ); | ||
54 | HRESULT BVariantSetNumeric( | 64 | HRESULT BVariantSetNumeric( |
55 | __in BURN_VARIANT* pVariant, | 65 | __in BURN_VARIANT* pVariant, |
56 | __in LONGLONG llValue | 66 | __in LONGLONG llValue |
diff --git a/src/test/BurnUnitTest/VariableTest.cpp b/src/test/BurnUnitTest/VariableTest.cpp index 405c8fab..f5511199 100644 --- a/src/test/BurnUnitTest/VariableTest.cpp +++ b/src/test/BurnUnitTest/VariableTest.cpp | |||
@@ -273,6 +273,7 @@ namespace Bootstrapper | |||
273 | Assert::True(EvaluateConditionHelper(&variables, L"vPROP21 = 1")); | 273 | Assert::True(EvaluateConditionHelper(&variables, L"vPROP21 = 1")); |
274 | Assert::True(EvaluateConditionHelper(&variables, L"PROP23 = v1.1.1")); | 274 | Assert::True(EvaluateConditionHelper(&variables, L"PROP23 = v1.1.1")); |
275 | Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 = PROP23")); | 275 | Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 = PROP23")); |
276 | Assert::False(EvaluateConditionHelper(&variables, L"v1.1.1<>PROP23")); | ||
276 | Assert::True(EvaluateConditionHelper(&variables, L"PROP1 <> v1.1.1")); | 277 | Assert::True(EvaluateConditionHelper(&variables, L"PROP1 <> v1.1.1")); |
277 | Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 <> PROP1")); | 278 | Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 <> PROP1")); |
278 | 279 | ||