| 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 | // prototypes |
| 6 | |
| 7 | |
| 8 | DAPI_(HRESULT) BalConditionsParseFromXml( |
| 9 | __in BAL_CONDITIONS* pConditions, |
| 10 | __in IXMLDOMDocument* pixdManifest, |
| 11 | __in_opt WIX_LOCALIZATION* pWixLoc |
| 12 | ) |
| 13 | { |
| 14 | HRESULT hr = S_OK; |
| 15 | IXMLDOMNodeList* pNodeList = NULL; |
| 16 | IXMLDOMNode* pNode = NULL; |
| 17 | BAL_CONDITION* prgConditions = NULL; |
| 18 | DWORD cConditions = 0; |
| 19 | |
| 20 | hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixBalCondition", &pNodeList); |
| 21 | ExitOnFailure(hr, "Failed to select all conditions."); |
| 22 | |
| 23 | hr = pNodeList->get_length(reinterpret_cast<long*>(&cConditions)); |
| 24 | ExitOnFailure(hr, "Failed to get the condition count."); |
| 25 | |
| 26 | if (!cConditions) |
| 27 | { |
| 28 | ExitFunction(); |
| 29 | } |
| 30 | |
| 31 | prgConditions = static_cast<BAL_CONDITION*>(MemAlloc(sizeof(BAL_CONDITION) * cConditions, TRUE)); |
| 32 | ExitOnNull(prgConditions, hr, E_OUTOFMEMORY, "Failed to allocate memory for conditions."); |
| 33 | |
| 34 | DWORD iCondition = 0; |
| 35 | while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL))) |
| 36 | { |
| 37 | hr = XmlGetAttributeEx(pNode, L"Condition", &prgConditions[iCondition].sczCondition); |
| 38 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get condition for condition."); |
| 39 | |
| 40 | hr = XmlGetAttributeEx(pNode, L"Message", &prgConditions[iCondition].sczMessage); |
| 41 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get message for condition."); |
| 42 | |
| 43 | if (pWixLoc && prgConditions[iCondition].sczMessage && *prgConditions[iCondition].sczMessage) |
| 44 | { |
| 45 | hr = LocLocalizeString(pWixLoc, &prgConditions[iCondition].sczMessage); |
| 46 | ExitOnFailure(hr, "Failed to localize condition message."); |
| 47 | } |
| 48 | |
| 49 | ++iCondition; |
| 50 | ReleaseNullObject(pNode); |
| 51 | } |
| 52 | ExitOnFailure(hr, "Failed to parse all condition elements."); |
| 53 | |
| 54 | if (S_FALSE == hr) |
| 55 | { |
| 56 | hr = S_OK; |
| 57 | } |
| 58 | |
| 59 | pConditions->cConditions = cConditions; |
| 60 | pConditions->rgConditions = prgConditions; |
| 61 | prgConditions = NULL; |
| 62 | |
| 63 | LExit: |
| 64 | ReleaseMem(prgConditions); |
| 65 | ReleaseObject(pNode); |
| 66 | ReleaseObject(pNodeList); |
| 67 | |
| 68 | return hr; |
| 69 | } |
| 70 | |
| 71 | |
| 72 | //the contents of psczMessage may be sensitive, should keep encrypted and SecureZeroFree |
| 73 | DAPI_(HRESULT) BalConditionEvaluate( |
| 74 | __in BAL_CONDITION* pCondition, |
| 75 | __in IBootstrapperEngine* pEngine, |
| 76 | __out BOOL* pfResult, |
| 77 | __out_z_opt LPWSTR* psczMessage |
| 78 | ) |
| 79 | { |
| 80 | HRESULT hr = S_OK; |
| 81 | SIZE_T cchMessage = 0; |
| 82 | |
| 83 | hr = pEngine->EvaluateCondition(pCondition->sczCondition, pfResult); |
| 84 | ExitOnFailure(hr, "Failed to evaluate condition with bootstrapper engine."); |
| 85 | |
| 86 | if (psczMessage) |
| 87 | { |
| 88 | if (*psczMessage) |
| 89 | { |
| 90 | hr = StrMaxLength(*psczMessage, &cchMessage); |
| 91 | ExitOnFailure(hr, "Failed to get length of message."); |
| 92 | } |
| 93 | |
| 94 | hr = pEngine->FormatString(pCondition->sczMessage, *psczMessage, &cchMessage); |
| 95 | if (E_MOREDATA == hr) |
| 96 | { |
| 97 | ++cchMessage; |
| 98 | |
| 99 | hr = StrAllocSecure(psczMessage, cchMessage); |
| 100 | ExitOnFailure(hr, "Failed to allocate string for condition's formatted message."); |
| 101 | |
| 102 | hr = pEngine->FormatString(pCondition->sczMessage, *psczMessage, &cchMessage); |
| 103 | } |
| 104 | ExitOnFailure(hr, "Failed to format condition's message."); |
| 105 | } |
| 106 | |
| 107 | LExit: |
| 108 | return hr; |
| 109 | } |
| 110 | |
| 111 | |
| 112 | DAPI_(void) BalConditionsUninitialize( |
| 113 | __in BAL_CONDITIONS* pConditions |
| 114 | ) |
| 115 | { |
| 116 | for (DWORD i = 0; i < pConditions->cConditions; ++i) |
| 117 | { |
| 118 | ReleaseStr(pConditions->rgConditions[i].sczMessage); |
| 119 | ReleaseStr(pConditions->rgConditions[i].sczCondition); |
| 120 | } |
| 121 | |
| 122 | ReleaseMem(pConditions->rgConditions); |
| 123 | memset(pConditions, 0, sizeof(BAL_CONDITIONS)); |
| 124 | } |