| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | |
| 3 | #include "precomp.h" |
| 4 | |
| 5 | |
| 6 | extern "C" HRESULT PseudoBundleInitializeRelated( |
| 7 | __in BURN_PACKAGE* pPackage, |
| 8 | __in BOOL fSupportsBurnProtocol, |
| 9 | __in BOOL fPerMachine, |
| 10 | __in_z LPCWSTR wzId, |
| 11 | #ifdef DEBUG |
| 12 | __in BOOTSTRAPPER_RELATION_TYPE relationType, |
| 13 | #endif |
| 14 | __in BOOL fCached, |
| 15 | __in_z LPCWSTR wzFilePath, |
| 16 | __in DWORD64 qwSize, |
| 17 | __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider |
| 18 | ) |
| 19 | { |
| 20 | HRESULT hr = S_OK; |
| 21 | BURN_PAYLOAD* pPayload = NULL; |
| 22 | |
| 23 | AssertSz(BOOTSTRAPPER_RELATION_UPDATE != relationType, "Update pseudo bundles must use PseudoBundleInitializeUpdateBundle instead."); |
| 24 | |
| 25 | // Initialize the single payload, and fill out all the necessary fields |
| 26 | pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE); |
| 27 | ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct"); |
| 28 | pPackage->payloads.cItems = 1; |
| 29 | |
| 30 | pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE); |
| 31 | ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct"); |
| 32 | pPackage->payloads.rgItems[0].pPayload = pPayload; |
| 33 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; |
| 34 | pPayload->qwFileSize = qwSize; |
| 35 | |
| 36 | hr = StrAllocString(&pPayload->sczKey, wzId, 0); |
| 37 | ExitOnFailure(hr, "Failed to copy key for pseudo bundle payload."); |
| 38 | |
| 39 | hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0); |
| 40 | ExitOnFailure(hr, "Failed to copy filename for pseudo bundle."); |
| 41 | |
| 42 | hr = StrAllocString(&pPayload->sczSourcePath, wzFilePath, 0); |
| 43 | ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle."); |
| 44 | |
| 45 | pPackage->type = BURN_PACKAGE_TYPE_BUNDLE; |
| 46 | pPackage->fPerMachine = fPerMachine; |
| 47 | pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; |
| 48 | pPackage->fCached = fCached; |
| 49 | pPackage->qwInstallSize = qwSize; |
| 50 | pPackage->qwSize = qwSize; |
| 51 | pPackage->fVital = FALSE; |
| 52 | |
| 53 | pPackage->fPermanent = FALSE; |
| 54 | pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol; |
| 55 | |
| 56 | hr = StrAllocString(&pPackage->sczId, wzId, 0); |
| 57 | ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); |
| 58 | |
| 59 | hr = StrAllocString(&pPackage->sczCacheId, wzId, 0); |
| 60 | ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle."); |
| 61 | |
| 62 | // Log variables - best effort |
| 63 | StrAllocFormatted(&pPackage->sczLogPathVariable, L"WixBundleLog_%ls", pPackage->sczId); |
| 64 | StrAllocFormatted(&pPackage->sczRollbackLogPathVariable, L"WixBundleRollbackLog_%ls", pPackage->sczId); |
| 65 | |
| 66 | if (pDependencyProvider) |
| 67 | { |
| 68 | pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE); |
| 69 | ExitOnNull(pPackage->rgDependencyProviders, hr, E_OUTOFMEMORY, "Failed to allocate memory for dependency providers."); |
| 70 | pPackage->cDependencyProviders = 1; |
| 71 | |
| 72 | pPackage->rgDependencyProviders[0].fImported = pDependencyProvider->fImported; |
| 73 | |
| 74 | hr = StrAllocString(&pPackage->rgDependencyProviders[0].sczKey, pDependencyProvider->sczKey, 0); |
| 75 | ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); |
| 76 | |
| 77 | hr = StrAllocString(&pPackage->rgDependencyProviders[0].sczVersion, pDependencyProvider->sczVersion, 0); |
| 78 | ExitOnFailure(hr, "Failed to copy version for pseudo bundle."); |
| 79 | |
| 80 | hr = StrAllocString(&pPackage->rgDependencyProviders[0].sczDisplayName, pDependencyProvider->sczDisplayName, 0); |
| 81 | ExitOnFailure(hr, "Failed to copy display name for pseudo bundle."); |
| 82 | } |
| 83 | |
| 84 | LExit: |
| 85 | return hr; |
| 86 | } |
| 87 | |
| 88 | extern "C" HRESULT PseudoBundleInitializePassthrough( |
| 89 | __in BURN_PACKAGE* pPassthroughPackage, |
| 90 | __in BURN_ENGINE_COMMAND* pInternalCommand, |
| 91 | __in BOOTSTRAPPER_COMMAND* pCommand, |
| 92 | __in BURN_PACKAGE* pPackage |
| 93 | ) |
| 94 | { |
| 95 | Assert(BURN_PACKAGE_TYPE_BUNDLE == pPackage->type); |
| 96 | |
| 97 | HRESULT hr = S_OK; |
| 98 | LPWSTR sczArguments = NULL; |
| 99 | |
| 100 | // Initialize the payloads, and copy the necessary fields. |
| 101 | pPassthroughPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM) * pPackage->payloads.cItems, TRUE); |
| 102 | ExitOnNull(pPassthroughPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle."); |
| 103 | pPassthroughPackage->payloads.cItems = pPackage->payloads.cItems; |
| 104 | |
| 105 | for (DWORD iPayload = 0; iPayload < pPackage->payloads.cItems; ++iPayload) |
| 106 | { |
| 107 | pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload; |
| 108 | } |
| 109 | |
| 110 | pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user. |
| 111 | pPassthroughPackage->type = BURN_PACKAGE_TYPE_EXE; |
| 112 | pPassthroughPackage->currentState = pPackage->currentState; |
| 113 | pPassthroughPackage->fCached = pPackage->fCached; |
| 114 | pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize; |
| 115 | pPassthroughPackage->qwSize = pPackage->qwSize; |
| 116 | pPassthroughPackage->fVital = pPackage->fVital; |
| 117 | pPassthroughPackage->fPermanent = TRUE; |
| 118 | |
| 119 | pPassthroughPackage->Exe.fPseudoPackage = TRUE; |
| 120 | pPassthroughPackage->Exe.fUninstallable = FALSE; |
| 121 | pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; |
| 122 | |
| 123 | hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0); |
| 124 | ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle."); |
| 125 | |
| 126 | hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0); |
| 127 | ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle."); |
| 128 | |
| 129 | // Log variables - best effort |
| 130 | StrAllocFormatted(&pPackage->sczLogPathVariable, L"WixBundleLog_%ls", pPackage->sczId); |
| 131 | StrAllocFormatted(&pPackage->sczRollbackLogPathVariable, L"WixBundleRollbackLog_%ls", pPackage->sczId); |
| 132 | |
| 133 | hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand); |
| 134 | ExitOnFailure(hr, "Failed to create command-line arguments."); |
| 135 | |
| 136 | hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0); |
| 137 | ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package"); |
| 138 | |
| 139 | LExit: |
| 140 | ReleaseStr(sczArguments); |
| 141 | return hr; |
| 142 | } |
| 143 | |
| 144 | extern "C" HRESULT PseudoBundleInitializeUpdateBundle( |
| 145 | __in BURN_PACKAGE* pPackage, |
| 146 | __in_z LPCWSTR wzId, |
| 147 | __in_z LPCWSTR wzCacheId, |
| 148 | __in_z LPCWSTR wzFilePath, |
| 149 | __in_z LPCWSTR wzLocalSource, |
| 150 | __in_z_opt LPCWSTR wzDownloadSource, |
| 151 | __in DWORD64 qwSize, |
| 152 | __in_z LPCWSTR wzInstallArguments, |
| 153 | __in_opt LPCWSTR wzHash |
| 154 | ) |
| 155 | { |
| 156 | HRESULT hr = S_OK; |
| 157 | BURN_PAYLOAD* pPayload = NULL; |
| 158 | |
| 159 | // Initialize the single payload, and fill out all the necessary fields |
| 160 | pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE); |
| 161 | ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of update bundle struct"); |
| 162 | pPackage->payloads.cItems = 1; |
| 163 | |
| 164 | pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE); |
| 165 | ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of update bundle struct"); |
| 166 | pPackage->payloads.rgItems[0].pPayload = pPayload; |
| 167 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; |
| 168 | pPayload->qwFileSize = qwSize; |
| 169 | pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE; |
| 170 | |
| 171 | hr = StrAllocString(&pPayload->sczKey, wzId, 0); |
| 172 | ExitOnFailure(hr, "Failed to copy key for pseudo bundle payload."); |
| 173 | |
| 174 | hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0); |
| 175 | ExitOnFailure(hr, "Failed to copy filename for pseudo bundle."); |
| 176 | |
| 177 | hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0); |
| 178 | ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle."); |
| 179 | |
| 180 | if (wzDownloadSource && *wzDownloadSource) |
| 181 | { |
| 182 | hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0); |
| 183 | ExitOnFailure(hr, "Failed to copy download source for pseudo bundle."); |
| 184 | } |
| 185 | |
| 186 | if (wzHash && *wzHash) |
| 187 | { |
| 188 | BYTE* rgbHash = NULL; |
| 189 | DWORD cbHash = 0; |
| 190 | |
| 191 | hr = StrAllocHexDecode(wzHash, &rgbHash, &cbHash); |
| 192 | ExitOnFailure(hr, "Failed to decode hash string: %ls.", wzHash); |
| 193 | |
| 194 | pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE)); |
| 195 | ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for update bundle payload hash."); |
| 196 | |
| 197 | pPayload->cbHash = cbHash; |
| 198 | |
| 199 | memcpy_s(pPayload->pbHash, pPayload->cbHash, rgbHash, cbHash); |
| 200 | } |
| 201 | |
| 202 | pPackage->type = BURN_PACKAGE_TYPE_EXE; |
| 203 | pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; |
| 204 | pPackage->qwInstallSize = qwSize; |
| 205 | pPackage->qwSize = qwSize; |
| 206 | pPackage->fVital = TRUE; |
| 207 | |
| 208 | // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate. |
| 209 | pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; |
| 210 | pPackage->Exe.fPseudoPackage = TRUE; |
| 211 | |
| 212 | hr = StrAllocString(&pPackage->sczId, wzId, 0); |
| 213 | ExitOnFailure(hr, "Failed to copy id for update bundle."); |
| 214 | |
| 215 | hr = StrAllocString(&pPackage->sczCacheId, wzCacheId, 0); |
| 216 | ExitOnFailure(hr, "Failed to copy cache id for update bundle."); |
| 217 | |
| 218 | // Log variables - best effort |
| 219 | StrAllocFormatted(&pPackage->sczLogPathVariable, L"WixBundleLog_%ls", pPackage->sczId); |
| 220 | StrAllocFormatted(&pPackage->sczRollbackLogPathVariable, L"WixBundleRollbackLog_%ls", pPackage->sczId); |
| 221 | |
| 222 | hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0); |
| 223 | ExitOnFailure(hr, "Failed to copy install arguments for update bundle package"); |
| 224 | |
| 225 | LExit: |
| 226 | return hr; |
| 227 | } |