Update string versioning.
Update condition parsing to allow specific characters for versions. Log every time an invalid version is parsed.
Sean Hall committed
Oct 18, 2020 at 14:05 UTC
bafc4f682a798eb375d32c1f4777664aceb1e15f
9 files changed
+225
-56
src/engine/condition.cpp
+73
-52
@@ -73,6 +73,12 @@ struct BURN_CONDITION_PARSE_CONTEXT
73
BOOL fError;
74
};
75
76
+struct BURN_CONDITION_OPERAND
77
+{
78
+ BOOL fHidden;
79
+ BURN_VARIANT Value;
80
+};
81
+
82
83
// internal function declarations
84
@@ -92,9 +98,9 @@ static HRESULT ParseTerm(
98
__in BURN_CONDITION_PARSE_CONTEXT* pContext,
99
__out BOOL* pf
100
);
95
-static HRESULT ParseValue(
101
+static HRESULT ParseOperand(
102
__in BURN_CONDITION_PARSE_CONTEXT* pContext,
97
- __out BURN_VARIANT* pValue
103
+ __out BURN_CONDITION_OPERAND* pOperand
104
);
105
static HRESULT Expect(
106
__in BURN_CONDITION_PARSE_CONTEXT* pContext,
@@ -103,10 +109,10 @@ static HRESULT Expect(
109
static HRESULT NextSymbol(
110
__in BURN_CONDITION_PARSE_CONTEXT* pContext
111
);
106
-static HRESULT CompareValues(
112
+static HRESULT CompareOperands(
113
__in BURN_SYMBOL_TYPE comparison,
108
- __in BURN_VARIANT leftOperand,
109
- __in BURN_VARIANT rightOperand,
114
+ __in BURN_CONDITION_OPERAND* pLeftOperand,
115
+ __in BURN_CONDITION_OPERAND* pRightOperand,
116
__out BOOL* pfResult
117
);
118
static HRESULT CompareStringValues(
@@ -342,8 +348,8 @@ static HRESULT ParseTerm(
348
)
349
{
350
HRESULT hr = S_OK;
345
- BURN_VARIANT firstValue = { };
346
- BURN_VARIANT secondValue = { };
351
+ BURN_CONDITION_OPERAND firstOperand = { };
352
+ BURN_CONDITION_OPERAND secondOperand = { };
353
354
if (BURN_SYMBOL_TYPE_LPAREN == pContext->NextSymbol.Type)
355
{
@@ -359,8 +365,8 @@ static HRESULT ParseTerm(
365
ExitFunction1(hr = S_OK);
366
}
367
362
- hr = ParseValue(pContext, &firstValue);
363
- ExitOnFailure(hr, "Failed to parse value.");
368
+ hr = ParseOperand(pContext, &firstOperand);
369
+ ExitOnFailure(hr, "Failed to parse operand.");
370
371
if (COMPARISON & pContext->NextSymbol.Type)
372
{
@@ -369,24 +375,24 @@ static HRESULT ParseTerm(
375
hr = NextSymbol(pContext);
376
ExitOnFailure(hr, "Failed to read next symbol.");
377
372
- hr = ParseValue(pContext, &secondValue);
373
- ExitOnFailure(hr, "Failed to parse value.");
378
+ hr = ParseOperand(pContext, &secondOperand);
379
+ ExitOnFailure(hr, "Failed to parse operand.");
380
375
- hr = CompareValues(comparison, firstValue, secondValue, pf);
376
- ExitOnFailure(hr, "Failed to compare value.");
381
+ hr = CompareOperands(comparison, &firstOperand, &secondOperand, pf);
382
+ ExitOnFailure(hr, "Failed to compare operands.");
383
}
384
else
385
{
386
LONGLONG llValue = 0;
387
LPWSTR sczValue = NULL;
388
VERUTIL_VERSION* pVersion = NULL;
383
- switch (firstValue.Type)
389
+ switch (firstOperand.Value.Type)
390
{
391
case BURN_VARIANT_TYPE_NONE:
392
*pf = FALSE;
393
break;
394
case BURN_VARIANT_TYPE_STRING:
389
- hr = BVariantGetString(&firstValue, &sczValue);
395
+ hr = BVariantGetString(&firstOperand.Value, &sczValue);
396
if (SUCCEEDED(hr))
397
{
398
*pf = sczValue && *sczValue;
@@ -394,7 +400,7 @@ static HRESULT ParseTerm(
400
StrSecureZeroFreeString(sczValue);
401
break;
402
case BURN_VARIANT_TYPE_NUMERIC:
397
- hr = BVariantGetNumeric(&firstValue, &llValue);
403
+ hr = BVariantGetNumeric(&firstOperand.Value, &llValue);
404
if (SUCCEEDED(hr))
405
{
406
*pf = 0 != llValue;
@@ -402,7 +408,7 @@ static HRESULT ParseTerm(
408
SecureZeroMemory(&llValue, sizeof(llValue));
409
break;
410
case BURN_VARIANT_TYPE_VERSION:
405
- hr = BVariantGetVersion(&firstValue, &pVersion);
411
+ hr = BVariantGetVersionHidden(&firstOperand.Value, firstOperand.fHidden, &pVersion);
412
if (SUCCEEDED(hr))
413
{
414
*pf = 0 != *pVersion->sczVersion;
@@ -415,14 +421,14 @@ static HRESULT ParseTerm(
421
}
422
423
LExit:
418
- BVariantUninitialize(&firstValue);
419
- BVariantUninitialize(&secondValue);
424
+ BVariantUninitialize(&firstOperand.Value);
425
+ BVariantUninitialize(&secondOperand.Value);
426
return hr;
427
}
428
423
-static HRESULT ParseValue(
429
+static HRESULT ParseOperand(
430
__in BURN_CONDITION_PARSE_CONTEXT* pContext,
425
- __out BURN_VARIANT* pValue
431
+ __out BURN_CONDITION_OPERAND* pOperand
432
)
433
{
434
HRESULT hr = S_OK;
@@ -434,16 +440,19 @@ static HRESULT ParseValue(
440
Assert(BURN_VARIANT_TYPE_STRING == pContext->NextSymbol.Value.Type);
441
442
// find variable
437
- hr = VariableGetVariant(pContext->pVariables, pContext->NextSymbol.Value.sczValue, pValue);
443
+ hr = VariableGetVariant(pContext->pVariables, pContext->NextSymbol.Value.sczValue, &pOperand->Value);
444
if (E_NOTFOUND != hr)
445
{
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.");
450
}
451
443
- if (BURN_VARIANT_TYPE_FORMATTED == pValue->Type)
452
+ if (BURN_VARIANT_TYPE_FORMATTED == pOperand->Value.Type)
453
{
454
// TODO: actually format the value?
446
- hr = BVariantChangeType(pValue, BURN_VARIANT_TYPE_STRING);
455
+ hr = BVariantChangeType(&pOperand->Value, BURN_VARIANT_TYPE_STRING);
456
ExitOnRootFailure(hr, "Failed to change variable '%ls' type for condition '%ls'", pContext->NextSymbol.Value.sczValue, pContext->wzCondition);
457
}
458
break;
@@ -451,8 +460,9 @@ static HRESULT ParseValue(
460
case BURN_SYMBOL_TYPE_NUMBER: __fallthrough;
461
case BURN_SYMBOL_TYPE_LITERAL: __fallthrough;
462
case BURN_SYMBOL_TYPE_VERSION:
463
+ pOperand->fHidden = FALSE;
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));
466
memset(&pContext->NextSymbol.Value, 0, sizeof(BURN_VARIANT));
467
break;
468
@@ -692,8 +702,13 @@ static HRESULT NextSymbol(
702
do
703
{
704
++n;
695
- ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType);
696
- } while (L'\0' != pContext->wzRead[n] && C1_BLANK != (C1_BLANK & charType));
705
+ } while (pContext->wzRead[n] >= L'0' && pContext->wzRead[n] <= L'9' ||
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'.');
712
713
// Symbols don't encrypt their value, so can access the value directly.
714
hr = VerParseVersion(&pContext->wzRead[1], n - 1, FALSE, &pContext->NextSymbol.Value.pValue);
@@ -703,6 +718,10 @@ static HRESULT NextSymbol(
718
hr = E_INVALIDDATA;
719
ExitOnRootFailure(hr, "Failed to parse condition \"%ls\". Invalid version format, at position %d.", pContext->wzCondition, iPosition);
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
+ }
725
726
pContext->NextSymbol.Value.Type = BURN_VARIANT_TYPE_VERSION;
727
pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_VERSION;
@@ -755,12 +774,12 @@ LExit:
774
}
775
776
//
758
-// CompareValues - compares two variant values using a given comparison.
777
+// CompareOperands - compares two variant values using a given comparison.
778
//
760
-static HRESULT CompareValues(
779
+static HRESULT CompareOperands(
780
__in BURN_SYMBOL_TYPE comparison,
762
- __in BURN_VARIANT leftOperand,
763
- __in BURN_VARIANT rightOperand,
781
+ __in BURN_CONDITION_OPERAND* pLeftOperand,
782
+ __in BURN_CONDITION_OPERAND* pRightOperand,
783
__out BOOL* pfResult
784
)
785
{
@@ -771,37 +790,39 @@ static HRESULT CompareValues(
790
LONGLONG llRight = 0;
791
VERUTIL_VERSION* pVersionRight = 0;
792
LPWSTR sczRight = NULL;
793
+ BURN_VARIANT* pLeftValue = &pLeftOperand->Value;
794
+ BURN_VARIANT* pRightValue = &pRightOperand->Value;
795
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)
798
{
778
- hr = BVariantGetString(&leftOperand, &sczLeft);
799
+ hr = BVariantGetString(pLeftValue, &sczLeft);
800
ExitOnFailure(hr, "Failed to get the left string");
780
- hr = BVariantGetString(&rightOperand, &sczRight);
801
+ hr = BVariantGetString(pRightValue, &sczRight);
802
ExitOnFailure(hr, "Failed to get the right string");
803
hr = CompareStringValues(comparison, sczLeft, sczRight, pfResult);
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)
806
{
786
- hr = BVariantGetNumeric(&leftOperand, &llLeft);
807
+ hr = BVariantGetNumeric(pLeftValue, &llLeft);
808
ExitOnFailure(hr, "Failed to get the left numeric");
788
- hr = BVariantGetNumeric(&rightOperand, &llRight);
809
+ hr = BVariantGetNumeric(pRightValue, &llRight);
810
ExitOnFailure(hr, "Failed to get the right numeric");
811
hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult);
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)
814
{
794
- hr = BVariantGetVersion(&leftOperand, &pVersionLeft);
815
+ hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft);
816
ExitOnFailure(hr, "Failed to get the left version");
796
- hr = BVariantGetVersion(&rightOperand, &pVersionRight);
817
+ hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight);
818
ExitOnFailure(hr, "Failed to get the right version");
819
hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult);
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)
822
{
802
- hr = BVariantGetVersion(&leftOperand, &pVersionLeft);
823
+ hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft);
824
ExitOnFailure(hr, "Failed to get the left version");
804
- hr = BVariantGetVersion(&rightOperand, &pVersionRight);
825
+ hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight);
826
if (FAILED(hr))
827
{
828
if (DISP_E_TYPEMISMATCH != hr)
@@ -816,11 +837,11 @@ static HRESULT CompareValues(
837
hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult);
838
}
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)
841
{
821
- hr = BVariantGetVersion(&rightOperand, &pVersionRight);
842
+ hr = BVariantGetVersionHidden(pRightValue, pRightOperand->fHidden, &pVersionRight);
843
ExitOnFailure(hr, "Failed to get the right version");
823
- hr = BVariantGetVersion(&leftOperand, &pVersionLeft);
844
+ hr = BVariantGetVersionHidden(pLeftValue, pLeftOperand->fHidden, &pVersionLeft);
845
if (FAILED(hr))
846
{
847
if (DISP_E_TYPEMISMATCH != hr)
@@ -835,11 +856,11 @@ static HRESULT CompareValues(
856
hr = CompareVersionValues(comparison, pVersionLeft, pVersionRight, pfResult);
857
}
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)
860
{
840
- hr = BVariantGetNumeric(&leftOperand, &llLeft);
861
+ hr = BVariantGetNumeric(pLeftValue, &llLeft);
862
ExitOnFailure(hr, "Failed to get the left numeric");
842
- hr = BVariantGetNumeric(&rightOperand, &llRight);
863
+ hr = BVariantGetNumeric(pRightValue, &llRight);
864
if (FAILED(hr))
865
{
866
if (DISP_E_TYPEMISMATCH != hr)
@@ -854,11 +875,11 @@ static HRESULT CompareValues(
875
hr = CompareIntegerValues(comparison, llLeft, llRight, pfResult);
876
}
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)
879
{
859
- hr = BVariantGetNumeric(&rightOperand, &llRight);
880
+ hr = BVariantGetNumeric(pRightValue, &llRight);
881
ExitOnFailure(hr, "Failed to get the right numeric");
861
- hr = BVariantGetNumeric(&leftOperand, &llLeft);
882
+ hr = BVariantGetNumeric(pLeftValue, &llLeft);
883
if (FAILED(hr))
884
{
885
if (DISP_E_TYPEMISMATCH != hr)
src/engine/engine.mc
+42
@@ -114,6 +114,13 @@ Language=English
114
Connected to elevated engine.
115
.
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
+
124
MessageId=51
125
Severity=Error
126
SymbolicName=MSG_FAILED_PARSE_CONDITION
@@ -156,6 +163,13 @@ Language=English
163
Application canceled operation: %2!ls!, error: %1!ls!
164
.
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
+
173
MessageId=100
174
Severity=Success
175
SymbolicName=MSG_DETECT_BEGIN
@@ -233,6 +247,20 @@ Language=English
247
Could not calculate patch applicability for target product code: %1!ls!, context: %2!hs!, reason: 0x%3!x!
248
.
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
+
264
MessageId=151
265
Severity=Error
266
SymbolicName=MSG_FAILED_DETECT_PACKAGE
@@ -836,6 +864,20 @@ Language=English
864
Variable: %1!ls!
865
.
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
+
881
MessageId=420
882
Severity=Success
883
SymbolicName=MSG_RESUME_AU_STARTING
src/engine/msiengine.cpp
+35
@@ -82,6 +82,11 @@ extern "C" HRESULT MsiEngineParsePackageFromXml(
82
hr = VerParseVersion(scz, 0, FALSE, &pPackage->Msi.pVersion);
83
ExitOnFailure(hr, "Failed to parse @Version: %ls", scz);
84
85
+ if (pPackage->Msi.pVersion->fInvalid)
86
+ {
87
+ LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz);
88
+ }
89
+
90
// @UpgradeCode
91
hr = XmlGetAttributeEx(pixnMsiPackage, L"UpgradeCode", &pPackage->Msi.sczUpgradeCode);
92
if (E_NOTFOUND != hr)
@@ -420,6 +425,11 @@ extern "C" HRESULT MsiEngineDetectPackage(
425
hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pPackage->Msi.pInstalledVersion);
426
ExitOnFailure(hr, "Failed to parse installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, pPackage->Msi.sczProductCode);
427
428
+ if (pPackage->Msi.pInstalledVersion->fInvalid)
429
+ {
430
+ LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, pPackage->Msi.sczProductCode, sczInstalledVersion);
431
+ }
432
+
433
// compare versions
434
hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pPackage->Msi.pInstalledVersion, &nCompareResult);
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(
470
hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion);
471
ExitOnFailure(hr, "Failed to parse dependency version: '%ls' for ProductCode: %ls", sczInstalledVersion, sczInstalledProductCode);
472
473
+ if (pVersion->fInvalid)
474
+ {
475
+ LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, sczInstalledProductCode, sczInstalledVersion);
476
+ }
477
+
478
// compare versions
479
hr = VerCompareParsedVersions(pPackage->Msi.pVersion, pVersion, &nCompareResult);
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(
551
hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pVersion);
552
ExitOnFailure(hr, "Failed to parse related installed version: '%ls' for ProductCode: %ls", sczInstalledVersion, wzProductCode);
553
554
+ if (pVersion->fInvalid)
555
+ {
556
+ LogId(REPORT_WARNING, MSG_DETECTED_MSI_PACKAGE_INVALID_VERSION, wzProductCode, sczInstalledVersion);
557
+ }
558
+
559
// compare versions
560
if (pRelatedMsi->fMinProvided)
561
{
@@ -1052,6 +1072,11 @@ extern "C" HRESULT MsiEngineAddCompatiblePackage(
1072
1073
hr = VerParseVersion(sczInstalledVersion, 0, FALSE, &pCompatiblePackage->Msi.pVersion);
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
+ }
1080
}
1081
1082
// For now, copy enough information to support uninstalling the newer, compatible package.
@@ -1506,6 +1531,11 @@ static HRESULT ParseRelatedMsiFromXml(
1531
hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMinVersion);
1532
ExitOnFailure(hr, "Failed to parse @MinVersion: %ls", scz);
1533
1534
+ if (pRelatedMsi->pMinVersion->fInvalid)
1535
+ {
1536
+ LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz);
1537
+ }
1538
+
1539
// flag that we have a min version
1540
pRelatedMsi->fMinProvided = TRUE;
1541
@@ -1523,6 +1553,11 @@ static HRESULT ParseRelatedMsiFromXml(
1553
hr = VerParseVersion(scz, 0, FALSE, &pRelatedMsi->pMaxVersion);
1554
ExitOnFailure(hr, "Failed to parse @MaxVersion: %ls", scz);
1555
1556
+ if (pRelatedMsi->pMaxVersion->fInvalid)
1557
+ {
1558
+ LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz);
1559
+ }
1560
+
1561
// flag that we have a max version
1562
pRelatedMsi->fMaxProvided = TRUE;
1563
src/engine/registration.cpp
+5
@@ -136,6 +136,11 @@ extern "C" HRESULT RegistrationParseFromXml(
136
hr = VerParseVersion(scz, 0, FALSE, &pRegistration->pVersion);
137
ExitOnFailure(hr, "Failed to parse @Version: %ls", scz);
138
139
+ if (pRegistration->pVersion->fInvalid)
140
+ {
141
+ LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz);
142
+ }
143
+
144
// @ProviderKey
145
hr = XmlGetAttributeEx(pixnRegistrationNode, L"ProviderKey", &pRegistration->sczProviderKey);
146
ExitOnFailure(hr, "Failed to get @ProviderKey.");
src/engine/relatedbundle.cpp
+5
@@ -414,6 +414,11 @@ static HRESULT LoadRelatedBundleFromKey(
414
hr = VerParseVersion(sczBundleVersion, 0, FALSE, &pRelatedBundle->pVersion);
415
ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", sczBundleVersion);
416
417
+ if (pRelatedBundle->pVersion->fInvalid)
418
+ {
419
+ LogId(REPORT_WARNING, MSG_RELATED_PACKAGE_INVALID_VERSION, wzRelatedBundleId, sczBundleVersion);
420
+ }
421
+
422
hr = RegReadString(hkBundleId, BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH, &sczCachePath);
423
ExitOnFailure(hr, "Failed to read cache path from registry for bundle: %ls", wzRelatedBundleId);
424
src/engine/variable.cpp
+11
-1
@@ -393,6 +393,11 @@ extern "C" HRESULT VariablesParseFromXml(
393
hr = BVariantChangeType(&value, valueType);
394
ExitOnFailure(hr, "Failed to change variant type.");
395
396
+ if (BURN_VARIANT_TYPE_VERSION == valueType && value.pValue->fInvalid)
397
+ {
398
+ LogId(REPORT_WARNING, MSG_VARIABLE_INVALID_VERSION, sczId);
399
+ }
400
+
401
// find existing variable
402
hr = FindVariableIndexByName(pVariables, sczId, &iVariable);
403
ExitOnFailure(hr, "Failed to find variable value '%ls'.", sczId);
@@ -584,7 +589,7 @@ extern "C" HRESULT VariableGetVersion(
589
}
590
ExitOnFailure(hr, "Failed to get value of variable: %ls", wzVariable);
591
587
- hr = BVariantGetVersion(&pVariable->Value, ppValue);
592
+ hr = BVariantGetVersionHidden(&pVariable->Value, pVariable->fHidden, ppValue);
593
ExitOnFailure(hr, "Failed to get value as version for variable: %ls", wzVariable);
594
595
LExit:
@@ -1575,6 +1580,11 @@ static HRESULT SetVariableValue(
1580
break;
1581
}
1582
}
1583
+
1584
+ if (BURN_VARIANT_TYPE_VERSION == pVariant->Type && pVariant->pValue->fInvalid)
1585
+ {
1586
+ LogId(REPORT_WARNING, MSG_VARIABLE_INVALID_VERSION, wzVariable);
1587
+ }
1588
}
1589
1590
// Update variable value.
src/engine/variant.cpp
+43
-3
@@ -6,6 +6,12 @@
6
7
// internal function declarations
8
9
+static HRESULT GetVersionInternal(
10
+ __in BURN_VARIANT* pVariant,
11
+ __in BOOL fHidden,
12
+ __in BOOL fSilent,
13
+ __out VERUTIL_VERSION** ppValue
14
+ );
15
static HRESULT BVariantEncryptString(
16
__in BURN_VARIANT* pVariant,
17
__in BOOL fEncrypt
@@ -129,6 +135,36 @@ extern "C" HRESULT BVariantGetVersion(
135
__in BURN_VARIANT* pVariant,
136
__out VERUTIL_VERSION** ppValue
137
)
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
{
169
HRESULT hr = S_OK;
170
LONGLONG llValue = 0;
@@ -152,6 +188,10 @@ extern "C" HRESULT BVariantGetVersion(
188
{
189
hr = DISP_E_TYPEMISMATCH;
190
}
191
+ else if (!fSilent && (*ppValue)->fInvalid)
192
+ {
193
+ LogId(REPORT_WARNING, MSG_INVALID_VERSION_COERSION, fHidden ? L"*****" : sczValue);
194
+ }
195
}
196
StrSecureZeroFreeString(sczValue);
197
break;
@@ -282,7 +322,7 @@ extern "C" HRESULT BVariantSetValue(
322
StrSecureZeroFreeString(sczValue);
323
break;
324
case BURN_VARIANT_TYPE_VERSION:
285
- hr = BVariantGetVersion(pValue, &pVersionValue);
325
+ hr = BVariantGetVersionSilent(pValue, TRUE, &pVersionValue);
326
if (SUCCEEDED(hr))
327
{
328
hr = BVariantSetVersion(pVariant, pVersionValue);
@@ -333,7 +373,7 @@ extern "C" HRESULT BVariantCopy(
373
StrSecureZeroFreeString(sczValue);
374
break;
375
case BURN_VARIANT_TYPE_VERSION:
336
- hr = BVariantGetVersion(pSource, &pVersionValue);
376
+ hr = BVariantGetVersionSilent(pSource, TRUE, &pVersionValue);
377
if (SUCCEEDED(hr))
378
{
379
hr = BVariantSetVersion(pTarget, pVersionValue);
@@ -383,7 +423,7 @@ extern "C" HRESULT BVariantChangeType(
423
hr = BVariantGetString(pVariant, &variant.sczValue);
424
break;
425
case BURN_VARIANT_TYPE_VERSION:
386
- hr = BVariantGetVersion(pVariant, &variant.pValue);
426
+ hr = BVariantGetVersionSilent(pVariant, TRUE, &variant.pValue);
427
break;
428
default:
429
ExitFunction1(hr = E_INVALIDARG);
src/engine/variant.h
+10
@@ -51,6 +51,16 @@ HRESULT BVariantGetVersion(
51
__in BURN_VARIANT* pVariant,
52
__out VERUTIL_VERSION** ppValue
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
+ );
64
HRESULT BVariantSetNumeric(
65
__in BURN_VARIANT* pVariant,
66
__in LONGLONG llValue
src/test/BurnUnitTest/VariableTest.cpp
+1
@@ -273,6 +273,7 @@ namespace Bootstrapper
273
Assert::True(EvaluateConditionHelper(&variables, L"vPROP21 = 1"));
274
Assert::True(EvaluateConditionHelper(&variables, L"PROP23 = v1.1.1"));
275
Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 = PROP23"));
276
+ Assert::False(EvaluateConditionHelper(&variables, L"v1.1.1<>PROP23"));
277
Assert::True(EvaluateConditionHelper(&variables, L"PROP1 <> v1.1.1"));
278
Assert::True(EvaluateConditionHelper(&variables, L"v1.1.1 <> PROP1"));
279