Enforce payload and container verification.
Sean Hall committed
May 3, 2021 at 12:23 UTC
cd921db764df9578733c85c29e8c6c368f4c7e78
9 files changed
+209
-92
src/burn/engine/apply.cpp
+2
-2
@@ -1410,12 +1410,12 @@ static HRESULT AcquireContainerOrPayload(
1410
fMinimumFileSize = TRUE;
1411
qwFileSize = pContainer->qwAttachedOffset + pContainer->qwFileSize;
1412
}
1413
- else if (pContainer->pbHash && pContext->wzLayoutDirectory)
1413
+ else
1414
{
1415
qwFileSize = pContainer->qwFileSize;
1416
}
1417
}
1418
- else if (pPayload->pbHash)
1418
+ else if (BURN_PAYLOAD_VERIFICATION_HASH == pPayload->verification || BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE == pPayload->verification)
1419
{
1420
qwFileSize = pPayload->qwFileSize;
1421
}
src/burn/engine/cache.cpp
+80
-15
@@ -114,10 +114,16 @@ static HRESULT RemoveBundleOrPackage(
114
__in_z LPCWSTR wzBundleOrPackageId,
115
__in_z LPCWSTR wzCacheId
116
);
117
+static HRESULT VerifyFileSize(
118
+ __in HANDLE hFile,
119
+ __in DWORD64 qwFileSize,
120
+ __in_z LPCWSTR wzUnverifiedPayloadPath
121
+ );
122
static HRESULT VerifyHash(
123
__in BYTE* pbHash,
124
__in DWORD cbHash,
125
__in DWORD64 qwFileSize,
126
+ __in BOOL fVerifyFileSize,
127
__in_z LPCWSTR wzUnverifiedPayloadPath,
128
__in HANDLE hFile,
129
__in BURN_CACHE_STEP cacheStep,
@@ -1513,11 +1519,16 @@ static HRESULT VerifyThenTransferContainer(
1519
ExitWithLastError(hr, "Failed to open container in working path: %ls", wzUnverifiedContainerPath);
1520
}
1521
1516
- // Container should have a hash we can use to verify with.
1517
- if (pContainer->pbHash)
1522
+
1523
+ switch (pContainer->verification)
1524
{
1519
- hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1525
+ case BURN_CONTAINER_VERIFICATION_HASH:
1526
+ hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, TRUE, wzUnverifiedContainerPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1527
ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath);
1528
+ break;
1529
+ default:
1530
+ ExitOnRootFailure(hr = E_INVALIDARG, "Container has no verification information: %ls", pContainer->sczId);
1531
+ break;
1532
}
1533
1534
LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath);
@@ -1550,10 +1561,16 @@ static HRESULT VerifyThenTransferPayload(
1561
ExitWithLastError(hr, "Failed to open payload in working path: %ls", wzUnverifiedPayloadPath);
1562
}
1563
1553
- if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1564
+ switch (pPayload->verification)
1565
{
1555
- hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1566
+ case BURN_PAYLOAD_VERIFICATION_HASH:
1567
+ hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, TRUE, wzUnverifiedPayloadPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1568
ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath);
1569
+ break;
1570
+ case BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE: __fallthrough;
1571
+ default:
1572
+ ExitOnRootFailure(hr = E_INVALIDARG, "Payload has no verification information: %ls", pPayload->sczKey);
1573
+ break;
1574
}
1575
1576
LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath);
@@ -1627,10 +1644,15 @@ static HRESULT VerifyFileAgainstContainer(
1644
ExitOnRootFailure(hr, "Failed to open container at path: %ls", wzVerifyPath);
1645
}
1646
1630
- if (pContainer->pbHash) // the container should have a hash we can use to verify it.
1647
+ switch (pContainer->verification)
1648
{
1632
- hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1649
+ case BURN_CONTAINER_VERIFICATION_HASH:
1650
+ hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, TRUE, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1651
ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId);
1652
+ break;
1653
+ default:
1654
+ ExitOnRootFailure(hr = E_INVALIDARG, "Container has no verification information: %ls", pContainer->sczId);
1655
+ break;
1656
}
1657
1658
if (fAlreadyCached)
@@ -1667,6 +1689,7 @@ static HRESULT VerifyFileAgainstPayload(
1689
{
1690
HRESULT hr = S_OK;
1691
HANDLE hFile = INVALID_HANDLE_VALUE;
1692
+ BOOL fVerifyFileSize = FALSE;
1693
1694
// Get the payload on disk actual hash.
1695
hFile = ::CreateFileW(wzVerifyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
@@ -1680,10 +1703,33 @@ static HRESULT VerifyFileAgainstPayload(
1703
ExitOnRootFailure(hr, "Failed to open payload at path: %ls", wzVerifyPath);
1704
}
1705
1683
- if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1706
+ switch (pPayload->verification)
1707
{
1685
- hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1708
+ case BURN_PAYLOAD_VERIFICATION_HASH:
1709
+ fVerifyFileSize = TRUE;
1710
+
1711
+ hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, fVerifyFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1712
ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
1713
+
1714
+ break;
1715
+ case BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE:
1716
+ fVerifyFileSize = 0 != pPayload->qwFileSize;
1717
+
1718
+ if (pPayload->pbHash)
1719
+ {
1720
+ hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, fVerifyFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1721
+ ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
1722
+ }
1723
+ else if (fVerifyFileSize)
1724
+ {
1725
+ hr = VerifyFileSize(hFile, pPayload->qwFileSize, wzVerifyPath);
1726
+ ExitOnFailure(hr, "Failed to verify file size for path: %ls", wzVerifyPath);
1727
+ }
1728
+
1729
+ break;
1730
+ default:
1731
+ ExitOnRootFailure(hr = E_INVALIDARG, "Payload has no verification information: %ls", pPayload->sczKey);
1732
+ break;
1733
}
1734
1735
if (fAlreadyCached)
@@ -2015,10 +2061,32 @@ LExit:
2061
return hr;
2062
}
2063
2064
+static HRESULT VerifyFileSize(
2065
+ __in HANDLE hFile,
2066
+ __in DWORD64 qwFileSize,
2067
+ __in_z LPCWSTR wzUnverifiedPayloadPath
2068
+ )
2069
+{
2070
+ HRESULT hr = S_OK;
2071
+ LONGLONG llSize = 0;
2072
+
2073
+ hr = FileSizeByHandle(hFile, &llSize);
2074
+ ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath);
2075
+
2076
+ if (static_cast<DWORD64>(llSize) != qwFileSize)
2077
+ {
2078
+ ExitOnRootFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize);
2079
+ }
2080
+
2081
+LExit:
2082
+ return hr;
2083
+}
2084
+
2085
static HRESULT VerifyHash(
2086
__in BYTE* pbHash,
2087
__in DWORD cbHash,
2088
__in DWORD64 qwFileSize,
2089
+ __in BOOL fVerifyFileSize,
2090
__in_z LPCWSTR wzUnverifiedPayloadPath,
2091
__in HANDLE hFile,
2092
__in BURN_CACHE_STEP cacheStep,
@@ -2032,19 +2100,16 @@ static HRESULT VerifyHash(
2100
HRESULT hr = S_OK;
2101
BYTE rgbActualHash[SHA512_HASH_LEN] = { };
2102
DWORD64 qwHashedBytes = 0;
2035
- LONGLONG llSize = 0;
2103
LPWSTR pszExpected = NULL;
2104
LPWSTR pszActual = NULL;
2105
2106
hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep);
2107
ExitOnFailure(hr, "Aborted cache verify hash begin.");
2108
2042
- hr = FileSizeByHandle(hFile, &llSize);
2043
- ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath);
2044
-
2045
- if (static_cast<DWORD64>(llSize) != qwFileSize)
2109
+ if (fVerifyFileSize)
2110
{
2047
- ExitOnFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize);
2111
+ hr = VerifyFileSize(hFile, qwFileSize, wzUnverifiedPayloadPath);
2112
+ ExitOnFailure(hr, "Failed to verify file size for path: %ls", wzUnverifiedPayloadPath);
2113
}
2114
2115
// TODO: create a cryp hash file that sends progress.
src/burn/engine/container.cpp
+27
-23
@@ -50,16 +50,9 @@ extern "C" HRESULT ContainersParseFromXml(
50
hr = XmlGetAttributeEx(pixnNode, L"Id", &pContainer->sczId);
51
ExitOnFailure(hr, "Failed to get @Id.");
52
53
- // @Primary
54
- hr = XmlGetYesNoAttribute(pixnNode, L"Primary", &pContainer->fPrimary);
55
- if (E_NOTFOUND != hr)
56
- {
57
- ExitOnFailure(hr, "Failed to get @Primary.");
58
- }
59
-
53
// @Attached
54
hr = XmlGetYesNoAttribute(pixnNode, L"Attached", &pContainer->fAttached);
62
- if (E_NOTFOUND != hr || pContainer->fPrimary) // if it is a primary container, it has to be attached
55
+ if (E_NOTFOUND != hr)
56
{
57
ExitOnFailure(hr, "Failed to get @Attached.");
58
}
@@ -87,10 +80,7 @@ extern "C" HRESULT ContainersParseFromXml(
80
{
81
// @FilePath
82
hr = XmlGetAttributeEx(pixnNode, L"FilePath", &pContainer->sczFilePath);
90
- if (E_NOTFOUND != hr)
91
- {
92
- ExitOnFailure(hr, "Failed to get @FilePath.");
93
- }
83
+ ExitOnFailure(hr, "Failed to get @FilePath.");
84
}
85
86
// The source path starts as the file path.
@@ -99,23 +89,32 @@ extern "C" HRESULT ContainersParseFromXml(
89
90
// @DownloadUrl
91
hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pContainer->downloadSource.sczUrl);
102
- if (E_NOTFOUND != hr || (!pContainer->fPrimary && !pContainer->sczSourcePath)) // if the package is not a primary package, it must have a source path or a download url
92
+ if (E_NOTFOUND != hr)
93
{
104
- ExitOnFailure(hr, "Failed to get @DownloadUrl. Either @SourcePath or @DownloadUrl needs to be provided.");
94
+ ExitOnFailure(hr, "Failed to get @DownloadUrl.");
95
}
96
97
// @Hash
98
hr = XmlGetAttributeEx(pixnNode, L"Hash", &pContainer->sczHash);
109
- if (SUCCEEDED(hr))
110
- {
111
- hr = StrAllocHexDecode(pContainer->sczHash, &pContainer->pbHash, &pContainer->cbHash);
112
- ExitOnFailure(hr, "Failed to hex decode the Container/@Hash.");
113
- }
114
- else if (E_NOTFOUND != hr)
99
+ ExitOnFailure(hr, "Failed to get @Hash.");
100
+
101
+ hr = StrAllocHexDecode(pContainer->sczHash, &pContainer->pbHash, &pContainer->cbHash);
102
+ ExitOnFailure(hr, "Failed to hex decode the Container/@Hash.");
103
+
104
+ // @FileSize
105
+ hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz);
106
+ ExitOnFailure(hr, "Failed to get @FileSize.");
107
+
108
+ hr = StrStringToUInt64(scz, 0, &pContainer->qwFileSize);
109
+ ExitOnFailure(hr, "Failed to parse @FileSize.");
110
+
111
+ if (!pContainer->qwFileSize)
112
{
116
- ExitOnFailure(hr, "Failed to get @Hash.");
113
+ ExitOnRootFailure(hr = E_INVALIDDATA, "File size is required when verifying by hash for container: %ls", pContainer->sczId);
114
}
115
116
+ pContainer->verification = BURN_CONTAINER_VERIFICATION_HASH;
117
+
118
// prepare next iteration
119
ReleaseNullObject(pixnNode);
120
}
@@ -136,6 +135,7 @@ extern "C" HRESULT ContainersInitialize(
135
)
136
{
137
HRESULT hr = S_OK;
138
+ DWORD64 qwSize = 0;
139
140
if (pContainers->rgContainers)
141
{
@@ -147,8 +147,13 @@ extern "C" HRESULT ContainersInitialize(
147
// manifest contained and get the offset to the container.
148
if (pContainer->fAttached)
149
{
150
- hr = SectionGetAttachedContainerInfo(pSection, pContainer->dwAttachedIndex, pContainer->type, &pContainer->qwAttachedOffset, &pContainer->qwFileSize, &pContainer->fActuallyAttached);
150
+ hr = SectionGetAttachedContainerInfo(pSection, pContainer->dwAttachedIndex, pContainer->type, &pContainer->qwAttachedOffset, &qwSize, &pContainer->fActuallyAttached);
151
ExitOnFailure(hr, "Failed to get attached container information.");
152
+
153
+ if (qwSize != pContainer->qwFileSize)
154
+ {
155
+ ExitOnFailure(hr, "Attached container '%ls' size '%llu' didn't match size from manifest: '%llu'", pContainer->sczId, qwSize, pContainer->qwFileSize);
156
+ }
157
}
158
}
159
}
@@ -195,7 +200,6 @@ extern "C" HRESULT ContainerOpenUX(
200
201
// open attached container
202
container.type = BURN_CONTAINER_TYPE_CABINET;
198
- container.fPrimary = TRUE;
203
container.fAttached = TRUE;
204
container.dwAttachedIndex = 0;
205
src/burn/engine/container.h
+7
-1
@@ -52,6 +52,12 @@ enum BURN_CAB_OPERATION
52
BURN_CAB_OPERATION_CLOSE,
53
};
54
55
+enum BURN_CONTAINER_VERIFICATION
56
+{
57
+ BURN_CONTAINER_VERIFICATION_NONE,
58
+ BURN_CONTAINER_VERIFICATION_HASH,
59
+};
60
+
61
62
// structs
63
@@ -59,7 +65,6 @@ typedef struct _BURN_CONTAINER
65
{
66
LPWSTR sczId;
67
BURN_CONTAINER_TYPE type;
62
- BOOL fPrimary;
68
BOOL fAttached;
69
DWORD dwAttachedIndex;
70
DWORD64 qwFileSize;
@@ -69,6 +74,7 @@ typedef struct _BURN_CONTAINER
74
75
BYTE* pbHash;
76
DWORD cbHash;
77
+ BURN_CONTAINER_VERIFICATION verification;
78
DWORD64 qwAttachedOffset;
79
BOOL fActuallyAttached; // indicates whether an attached container is attached or missing.
80
src/burn/engine/payload.cpp
+77
-50
@@ -27,6 +27,8 @@ extern "C" HRESULT PayloadsParseFromXml(
27
IXMLDOMNode* pixnNode = NULL;
28
DWORD cNodes = 0;
29
LPWSTR scz = NULL;
30
+ BOOL fChainPayload = pContainers && pLayoutPayloads; // These are required when parsing chain payloads.
31
+ BOOL fValidFileSize = FALSE;
32
33
// select payload nodes
34
hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes);
@@ -51,6 +53,7 @@ extern "C" HRESULT PayloadsParseFromXml(
53
for (DWORD i = 0; i < cNodes; ++i)
54
{
55
BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i];
56
+ fValidFileSize = FALSE;
57
58
hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
59
ExitOnFailure(hr, "Failed to get next node.");
@@ -63,27 +66,36 @@ extern "C" HRESULT PayloadsParseFromXml(
66
hr = XmlGetAttributeEx(pixnNode, L"FilePath", &pPayload->sczFilePath);
67
ExitOnFailure(hr, "Failed to get @FilePath.");
68
66
- // @Packaging
67
- hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz);
68
- ExitOnFailure(hr, "Failed to get @Packaging.");
69
+ // @SourcePath
70
+ hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath);
71
+ ExitOnFailure(hr, "Failed to get @SourcePath.");
72
70
- if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1))
73
+ if (!fChainPayload)
74
{
75
+ // All non-chain payloads are embedded in the UX container.
76
pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED;
77
}
74
- else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1))
75
- {
76
- pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
77
- }
78
else
79
{
80
- hr = E_INVALIDARG;
81
- ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz);
82
- }
80
+ // @Packaging
81
+ hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz);
82
+ ExitOnFailure(hr, "Failed to get @Packaging.");
83
84
- // @Container
85
- if (pContainers)
86
- {
84
+ if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1))
85
+ {
86
+ pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED;
87
+ }
88
+ else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1))
89
+ {
90
+ pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
91
+ }
92
+ else
93
+ {
94
+ hr = E_INVALIDARG;
95
+ ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz);
96
+ }
97
+
98
+ // @Container
99
hr = XmlGetAttributeEx(pixnNode, L"Container", &scz);
100
if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging)
101
{
@@ -93,52 +105,67 @@ extern "C" HRESULT PayloadsParseFromXml(
105
hr = ContainerFindById(pContainers, scz, &pPayload->pContainer);
106
ExitOnFailure(hr, "Failed to to find container: %ls", scz);
107
}
96
- }
108
98
- // @LayoutOnly
99
- hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly);
100
- if (E_NOTFOUND != hr)
101
- {
102
- ExitOnFailure(hr, "Failed to get @LayoutOnly.");
103
- }
109
+ // @LayoutOnly
110
+ hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly);
111
+ if (E_NOTFOUND != hr)
112
+ {
113
+ ExitOnFailure(hr, "Failed to get @LayoutOnly.");
114
+ }
115
105
- // @SourcePath
106
- hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath);
107
- ExitOnFailure(hr, "Failed to get @SourcePath.");
116
+ // @DownloadUrl
117
+ hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl);
118
+ if (E_NOTFOUND != hr)
119
+ {
120
+ ExitOnFailure(hr, "Failed to get @DownloadUrl.");
121
+ }
122
109
- // @DownloadUrl
110
- hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl);
111
- if (E_NOTFOUND != hr)
112
- {
113
- ExitOnFailure(hr, "Failed to get @DownloadUrl.");
114
- }
123
+ // @FileSize
124
+ hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz);
125
+ if (E_NOTFOUND != hr)
126
+ {
127
+ ExitOnFailure(hr, "Failed to get @FileSize.");
128
116
- // @FileSize
117
- hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz);
118
- if (E_NOTFOUND != hr)
119
- {
120
- ExitOnFailure(hr, "Failed to get @FileSize.");
129
+ hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize);
130
+ ExitOnFailure(hr, "Failed to parse @FileSize.");
131
122
- hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize);
123
- ExitOnFailure(hr, "Failed to parse @FileSize.");
124
- }
132
+ fValidFileSize = TRUE;
133
+ }
134
+
135
+ // @Hash
136
+ hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz);
137
+ if (E_NOTFOUND != hr)
138
+ {
139
+ ExitOnFailure(hr, "Failed to get @Hash.");
140
126
- // @Hash
127
- hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz);
128
- ExitOnFailure(hr, "Failed to get @Hash.");
141
+ hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash);
142
+ ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash.");
143
130
- hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash);
131
- ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash.");
144
+ if (BURN_PAYLOAD_VERIFICATION_NONE == pPayload->verification)
145
+ {
146
+ pPayload->verification = BURN_PAYLOAD_VERIFICATION_HASH;
147
+ }
148
+ }
149
133
- if (pPayload->fLayoutOnly && pLayoutPayloads)
134
- {
135
- hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5);
136
- ExitOnFailure(hr, "Failed to allocate memory for layout payloads.");
150
+ if (BURN_PAYLOAD_VERIFICATION_NONE == pPayload->verification)
151
+ {
152
+ ExitOnRootFailure(hr = E_INVALIDDATA, "There was no verification information for payload: %ls", pPayload->sczKey);
153
+ }
154
+ else if (BURN_PAYLOAD_VERIFICATION_HASH == pPayload->verification && !fValidFileSize)
155
+ {
156
+ ExitOnRootFailure(hr = E_INVALIDDATA, "File size is required when verifying by hash for payload: %ls", pPayload->sczKey);
157
+ }
158
138
- pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload;
139
- ++pLayoutPayloads->cItems;
159
+ if (pPayload->fLayoutOnly)
160
+ {
161
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5);
162
+ ExitOnFailure(hr, "Failed to allocate memory for layout payloads.");
163
141
- pLayoutPayloads->qwTotalSize += pPayload->qwFileSize;
164
+ pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload;
165
+ ++pLayoutPayloads->cItems;
166
+
167
+ pLayoutPayloads->qwTotalSize += pPayload->qwFileSize;
168
+ }
169
}
170
171
// prepare next iteration
src/burn/engine/payload.h
+8
@@ -23,6 +23,13 @@ enum BURN_PAYLOAD_STATE
23
BURN_PAYLOAD_STATE_CACHED,
24
};
25
26
+enum BURN_PAYLOAD_VERIFICATION
27
+{
28
+ BURN_PAYLOAD_VERIFICATION_NONE,
29
+ BURN_PAYLOAD_VERIFICATION_HASH,
30
+ BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE,
31
+};
32
+
33
34
// structs
35
@@ -36,6 +43,7 @@ typedef struct _BURN_PAYLOAD
43
44
BYTE* pbHash;
45
DWORD cbHash;
46
+ BURN_PAYLOAD_VERIFICATION verification;
47
48
LPWSTR sczSourcePath;
49
BURN_CONTAINER* pContainer;
src/burn/engine/pseudobundle.cpp
+5
@@ -69,6 +69,11 @@ extern "C" HRESULT PseudoBundleInitialize(
69
memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
70
}
71
72
+ if (BOOTSTRAPPER_RELATION_UPDATE == relationType)
73
+ {
74
+ pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE;
75
+ }
76
+
77
pPackage->Exe.fPseudoBundle = TRUE;
78
79
pPackage->type = BURN_PACKAGE_TYPE_EXE;
src/burn/test/BurnUnitTest/CacheTest.cpp
+2
@@ -71,6 +71,8 @@ namespace Bootstrapper
71
payload.sczFilePath = L"CacheSignatureTest.File";
72
payload.pbHash = pb;
73
payload.cbHash = cb;
74
+ payload.qwFileSize = 27;
75
+ payload.verification = BURN_PAYLOAD_VERIFICATION_HASH;
76
77
hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
78
Assert::Equal(S_OK, hr);
src/burn/test/BurnUnitTest/PlanTest.cpp
+1
-1
@@ -71,7 +71,7 @@ namespace Bootstrapper
71
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
72
73
Assert::Equal(107082ull, pPlan->qwEstimatedSize);
74
- Assert::Equal(506145ull, pPlan->qwCacheSizeTotal);
74
+ Assert::Equal(522548ull, pPlan->qwCacheSizeTotal);
75
76
fRollback = FALSE;
77
dwIndex = 0;