diff options
Diffstat (limited to 'src')
| -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 | ||
