diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2021-06-29 19:14:02 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2021-07-02 12:50:09 -0500 |
| commit | 8cbfc326cccf8d9b3b63cb6f752fc770f7dee0fc (patch) | |
| tree | 639f70e7327cdfade62271da04aaaaae2e85cc05 /src/api/burn/balutil/balinfo.cpp | |
| parent | e844f12f7d7247a1e9ba4eef2a388e614001bb24 (diff) | |
| download | wix-8cbfc326cccf8d9b3b63cb6f752fc770f7dee0fc.tar.gz wix-8cbfc326cccf8d9b3b63cb6f752fc770f7dee0fc.tar.bz2 wix-8cbfc326cccf8d9b3b63cb6f752fc770f7dee0fc.zip | |
Expose overridable variable APIs in balutil and Mba.Core.
Fixes #4777
Diffstat (limited to 'src/api/burn/balutil/balinfo.cpp')
| -rw-r--r-- | src/api/burn/balutil/balinfo.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp index 3abb9286..5927ef72 100644 --- a/src/api/burn/balutil/balinfo.cpp +++ b/src/api/burn/balutil/balinfo.cpp | |||
| @@ -11,7 +11,88 @@ static HRESULT ParseBalPackageInfoFromXml( | |||
| 11 | __in BAL_INFO_PACKAGES* pPackages, | 11 | __in BAL_INFO_PACKAGES* pPackages, |
| 12 | __in IXMLDOMDocument* pixdManifest | 12 | __in IXMLDOMDocument* pixdManifest |
| 13 | ); | 13 | ); |
| 14 | static HRESULT ParseOverridableVariablesFromXml( | ||
| 15 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
| 16 | __in IXMLDOMDocument* pixdManifest | ||
| 17 | ); | ||
| 18 | |||
| 19 | |||
| 20 | DAPI_(HRESULT) BalInfoParseCommandLine( | ||
| 21 | __in BAL_INFO_COMMAND* pCommand, | ||
| 22 | __in LPCWSTR wzCommandLine | ||
| 23 | ) | ||
| 24 | { | ||
| 25 | HRESULT hr = S_OK; | ||
| 26 | int argc = 0; | ||
| 27 | LPWSTR* argv = NULL; | ||
| 28 | BOOL fUnknownArg = FALSE; | ||
| 29 | |||
| 30 | BalInfoUninitializeCommandLine(pCommand); | ||
| 31 | |||
| 32 | if (!wzCommandLine || !*wzCommandLine) | ||
| 33 | { | ||
| 34 | ExitFunction(); | ||
| 35 | } | ||
| 36 | |||
| 37 | hr = AppParseCommandLine(wzCommandLine, &argc, &argv); | ||
| 38 | ExitOnFailure(hr, "Failed to parse command line."); | ||
| 14 | 39 | ||
| 40 | for (int i = 0; i < argc; ++i) | ||
| 41 | { | ||
| 42 | fUnknownArg = FALSE; | ||
| 43 | |||
| 44 | if (argv[i][0] == L'-' || argv[i][0] == L'/') | ||
| 45 | { | ||
| 46 | fUnknownArg = TRUE; | ||
| 47 | } | ||
| 48 | else | ||
| 49 | { | ||
| 50 | const wchar_t* pwc = wcschr(argv[i], L'='); | ||
| 51 | if (!pwc) | ||
| 52 | { | ||
| 53 | fUnknownArg = TRUE; | ||
| 54 | } | ||
| 55 | else | ||
| 56 | { | ||
| 57 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgVariableNames), pCommand->cVariables, 1, sizeof(LPWSTR), 5); | ||
| 58 | ExitOnFailure(hr, "Failed to ensure size for variable names."); | ||
| 59 | |||
| 60 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgVariableValues), pCommand->cVariables, 1, sizeof(LPWSTR), 5); | ||
| 61 | ExitOnFailure(hr, "Failed to ensure size for variable values."); | ||
| 62 | |||
| 63 | LPWSTR* psczVariableName = pCommand->rgVariableNames + pCommand->cVariables; | ||
| 64 | LPWSTR* psczVariableValue = pCommand->rgVariableValues + pCommand->cVariables; | ||
| 65 | pCommand->cVariables += 1; | ||
| 66 | |||
| 67 | hr = StrAllocString(psczVariableName, argv[i], pwc - argv[i]); | ||
| 68 | BalExitOnFailure(hr, "Failed to copy variable name."); | ||
| 69 | |||
| 70 | hr = StrAllocString(psczVariableValue, ++pwc, 0); | ||
| 71 | BalExitOnFailure(hr, "Failed to copy variable value."); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | if (fUnknownArg) | ||
| 76 | { | ||
| 77 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pCommand->rgUnknownArgs), pCommand->cUnknownArgs, 1, sizeof(LPWSTR), 5); | ||
| 78 | BalExitOnFailure(hr, "Failed to ensure size for unknown args."); | ||
| 79 | |||
| 80 | LPWSTR* psczArg = pCommand->rgUnknownArgs + pCommand->cUnknownArgs; | ||
| 81 | pCommand->cUnknownArgs += 1; | ||
| 82 | |||
| 83 | StrAllocString(psczArg, argv[i], 0); | ||
| 84 | BalExitOnFailure(hr, "Failed to copy unknown arg."); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | LExit: | ||
| 89 | if (argv) | ||
| 90 | { | ||
| 91 | AppFreeCommandLineArgs(argv); | ||
| 92 | } | ||
| 93 | |||
| 94 | return hr; | ||
| 95 | } | ||
| 15 | 96 | ||
| 16 | DAPI_(HRESULT) BalInfoParseFromXml( | 97 | DAPI_(HRESULT) BalInfoParseFromXml( |
| 17 | __in BAL_INFO_BUNDLE* pBundle, | 98 | __in BAL_INFO_BUNDLE* pBundle, |
| @@ -45,6 +126,9 @@ DAPI_(HRESULT) BalInfoParseFromXml( | |||
| 45 | } | 126 | } |
| 46 | } | 127 | } |
| 47 | 128 | ||
| 129 | hr = ParseOverridableVariablesFromXml(&pBundle->overridableVariables, pixdManifest); | ||
| 130 | BalExitOnFailure(hr, "Failed to parse overridable variables from bootstrapper application data."); | ||
| 131 | |||
| 48 | hr = ParsePackagesFromXml(&pBundle->packages, pixdManifest); | 132 | hr = ParsePackagesFromXml(&pBundle->packages, pixdManifest); |
| 49 | BalExitOnFailure(hr, "Failed to parse package information from bootstrapper application data."); | 133 | BalExitOnFailure(hr, "Failed to parse package information from bootstrapper application data."); |
| 50 | 134 | ||
| @@ -163,12 +247,76 @@ DAPI_(void) BalInfoUninitialize( | |||
| 163 | 247 | ||
| 164 | ReleaseMem(pBundle->packages.rgPackages); | 248 | ReleaseMem(pBundle->packages.rgPackages); |
| 165 | 249 | ||
| 250 | for (DWORD i = 0; i < pBundle->overridableVariables.cVariables; ++i) | ||
| 251 | { | ||
| 252 | ReleaseStr(pBundle->overridableVariables.rgVariables[i].sczName); | ||
| 253 | } | ||
| 254 | |||
| 255 | ReleaseMem(pBundle->overridableVariables.rgVariables); | ||
| 256 | ReleaseDict(pBundle->overridableVariables.sdVariables); | ||
| 257 | |||
| 166 | ReleaseStr(pBundle->sczName); | 258 | ReleaseStr(pBundle->sczName); |
| 167 | ReleaseStr(pBundle->sczLogVariable); | 259 | ReleaseStr(pBundle->sczLogVariable); |
| 168 | memset(pBundle, 0, sizeof(BAL_INFO_BUNDLE)); | 260 | memset(pBundle, 0, sizeof(BAL_INFO_BUNDLE)); |
| 169 | } | 261 | } |
| 170 | 262 | ||
| 171 | 263 | ||
| 264 | DAPI_(void) BalInfoUninitializeCommandLine( | ||
| 265 | __in BAL_INFO_COMMAND* pCommand | ||
| 266 | ) | ||
| 267 | { | ||
| 268 | for (DWORD i = 0; i < pCommand->cUnknownArgs; ++i) | ||
| 269 | { | ||
| 270 | ReleaseNullStrSecure(pCommand->rgUnknownArgs[i]); | ||
| 271 | } | ||
| 272 | |||
| 273 | ReleaseMem(pCommand->rgUnknownArgs); | ||
| 274 | |||
| 275 | for (DWORD i = 0; i < pCommand->cVariables; ++i) | ||
| 276 | { | ||
| 277 | ReleaseNullStrSecure(pCommand->rgVariableNames[i]); | ||
| 278 | ReleaseNullStrSecure(pCommand->rgVariableValues[i]); | ||
| 279 | } | ||
| 280 | |||
| 281 | ReleaseMem(pCommand->rgVariableNames); | ||
| 282 | ReleaseMem(pCommand->rgVariableValues); | ||
| 283 | |||
| 284 | memset(pCommand, 0, sizeof(BAL_INFO_COMMAND)); | ||
| 285 | } | ||
| 286 | |||
| 287 | |||
| 288 | DAPI_(HRESULT) BalSetOverridableVariablesFromEngine( | ||
| 289 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
| 290 | __in BAL_INFO_COMMAND* pCommand, | ||
| 291 | __in IBootstrapperEngine* pEngine | ||
| 292 | ) | ||
| 293 | { | ||
| 294 | HRESULT hr = S_OK; | ||
| 295 | BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; | ||
| 296 | |||
| 297 | for (DWORD i = 0; i < pCommand->cVariables; ++i) | ||
| 298 | { | ||
| 299 | LPCWSTR wzVariableName = pCommand->rgVariableNames[i]; | ||
| 300 | LPCWSTR wzVariableValue = pCommand->rgVariableValues[i]; | ||
| 301 | |||
| 302 | hr = DictGetValue(pOverridableVariables->sdVariables, wzVariableName, reinterpret_cast<void**>(&pOverridableVariable)); | ||
| 303 | if (E_NOTFOUND == hr) | ||
| 304 | { | ||
| 305 | BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", wzVariableName); | ||
| 306 | hr = S_OK; | ||
| 307 | continue; | ||
| 308 | } | ||
| 309 | BalExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); | ||
| 310 | |||
| 311 | hr = pEngine->SetVariableString(pOverridableVariable->sczName, wzVariableValue, FALSE); | ||
| 312 | BalExitOnFailure(hr, "Failed to set variable: '%ls'.", pOverridableVariable->sczName); | ||
| 313 | } | ||
| 314 | |||
| 315 | LExit: | ||
| 316 | return hr; | ||
| 317 | } | ||
| 318 | |||
| 319 | |||
| 172 | static HRESULT ParsePackagesFromXml( | 320 | static HRESULT ParsePackagesFromXml( |
| 173 | __in BAL_INFO_PACKAGES* pPackages, | 321 | __in BAL_INFO_PACKAGES* pPackages, |
| 174 | __in IXMLDOMDocument* pixdManifest | 322 | __in IXMLDOMDocument* pixdManifest |
| @@ -371,3 +519,58 @@ LExit: | |||
| 371 | 519 | ||
| 372 | return hr; | 520 | return hr; |
| 373 | } | 521 | } |
| 522 | |||
| 523 | |||
| 524 | static HRESULT ParseOverridableVariablesFromXml( | ||
| 525 | __in BAL_INFO_OVERRIDABLE_VARIABLES* pOverridableVariables, | ||
| 526 | __in IXMLDOMDocument* pixdManifest | ||
| 527 | ) | ||
| 528 | { | ||
| 529 | HRESULT hr = S_OK; | ||
| 530 | IXMLDOMNode* pNode = NULL; | ||
| 531 | IXMLDOMNodeList* pNodes = NULL; | ||
| 532 | BAL_INFO_OVERRIDABLE_VARIABLE* pOverridableVariable = NULL; | ||
| 533 | |||
| 534 | // Get the list of variables users can override on the command line. | ||
| 535 | hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); | ||
| 536 | if (S_FALSE == hr) | ||
| 537 | { | ||
| 538 | ExitFunction1(hr = S_OK); | ||
| 539 | } | ||
| 540 | ExitOnFailure(hr, "Failed to select overridable variable nodes."); | ||
| 541 | |||
| 542 | hr = pNodes->get_length(reinterpret_cast<long*>(&pOverridableVariables->cVariables)); | ||
| 543 | ExitOnFailure(hr, "Failed to get overridable variable node count."); | ||
| 544 | |||
| 545 | if (pOverridableVariables->cVariables) | ||
| 546 | { | ||
| 547 | hr = DictCreateWithEmbeddedKey(&pOverridableVariables->sdVariables, pOverridableVariables->cVariables, reinterpret_cast<void**>(&pOverridableVariables->rgVariables), offsetof(BAL_INFO_OVERRIDABLE_VARIABLE, sczName), DICT_FLAG_NONE); | ||
| 548 | ExitOnFailure(hr, "Failed to create the overridable variables string dictionary."); | ||
| 549 | |||
| 550 | hr = MemAllocArray(reinterpret_cast<LPVOID*>(&pOverridableVariables->rgVariables), sizeof(pOverridableVariable), pOverridableVariables->cVariables); | ||
| 551 | ExitOnFailure(hr, "Failed to create the overridable variables array."); | ||
| 552 | |||
| 553 | for (DWORD i = 0; i < pOverridableVariables->cVariables; ++i) | ||
| 554 | { | ||
| 555 | pOverridableVariable = pOverridableVariables->rgVariables + i; | ||
| 556 | |||
| 557 | hr = XmlNextElement(pNodes, &pNode, NULL); | ||
| 558 | ExitOnFailure(hr, "Failed to get next node."); | ||
| 559 | |||
| 560 | // @Name | ||
| 561 | hr = XmlGetAttributeEx(pNode, L"Name", &pOverridableVariable->sczName); | ||
| 562 | ExitOnFailure(hr, "Failed to get name for overridable variable."); | ||
| 563 | |||
| 564 | hr = DictAddValue(pOverridableVariables->sdVariables, pOverridableVariable); | ||
| 565 | ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", pOverridableVariable->sczName); | ||
| 566 | |||
| 567 | // prepare next iteration | ||
| 568 | ReleaseNullObject(pNode); | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | LExit: | ||
| 573 | ReleaseObject(pNode); | ||
| 574 | ReleaseObject(pNodes); | ||
| 575 | return hr; | ||
| 576 | } | ||
