aboutsummaryrefslogtreecommitdiff
path: root/src/api/burn/balutil/balcondition.cpp
blob: 00a46e055611fa88036af795dbb301610c4283b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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.

#include "precomp.h"

// prototypes


DAPI_(HRESULT) BalConditionsParseFromXml(
    __in BAL_CONDITIONS* pConditions,
    __in IXMLDOMDocument* pixdManifest,
    __in_opt WIX_LOCALIZATION* pWixLoc
    )
{
    HRESULT hr = S_OK;
    IXMLDOMNodeList* pNodeList = NULL;
    IXMLDOMNode* pNode = NULL;
    BAL_CONDITION* prgConditions = NULL;
    DWORD cConditions = 0;

    hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixBalCondition", &pNodeList);
    ExitOnFailure(hr, "Failed to select all conditions.");

    hr = pNodeList->get_length(reinterpret_cast<long*>(&cConditions));
    ExitOnFailure(hr, "Failed to get the condition count.");

    if (!cConditions)
    {
        ExitFunction();
    }

    prgConditions = static_cast<BAL_CONDITION*>(MemAlloc(sizeof(BAL_CONDITION) * cConditions, TRUE));
    ExitOnNull(prgConditions, hr, E_OUTOFMEMORY, "Failed to allocate memory for conditions.");

    DWORD iCondition = 0;
    while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL)))
    {
        hr = XmlGetAttributeEx(pNode, L"Condition", &prgConditions[iCondition].sczCondition);
        ExitOnRequiredXmlQueryFailure(hr, "Failed to get condition for condition.");

        hr = XmlGetAttributeEx(pNode, L"Message", &prgConditions[iCondition].sczMessage);
        ExitOnRequiredXmlQueryFailure(hr, "Failed to get message for condition.");

        if (pWixLoc && prgConditions[iCondition].sczMessage && *prgConditions[iCondition].sczMessage)
        {
            hr = LocLocalizeString(pWixLoc, &prgConditions[iCondition].sczMessage);
            ExitOnFailure(hr, "Failed to localize condition message.");
        }

        ++iCondition;
        ReleaseNullObject(pNode);
    }
    ExitOnFailure(hr, "Failed to parse all condition elements.");

    if (S_FALSE == hr)
    {
        hr = S_OK;
    }

    pConditions->cConditions = cConditions;
    pConditions->rgConditions = prgConditions;
    prgConditions = NULL;

LExit:
    ReleaseMem(prgConditions);
    ReleaseObject(pNode);
    ReleaseObject(pNodeList);

    return hr;
}


//the contents of psczMessage may be sensitive, should keep encrypted and SecureZeroFree
DAPI_(HRESULT) BalConditionEvaluate(
    __in BAL_CONDITION* pCondition,
    __in IBootstrapperEngine* pEngine,
    __out BOOL* pfResult,
    __out_z_opt LPWSTR* psczMessage
    )
{
    HRESULT hr = S_OK;
    SIZE_T cchMessage = 0;

    hr = pEngine->EvaluateCondition(pCondition->sczCondition, pfResult);
    ExitOnFailure(hr, "Failed to evaluate condition with bootstrapper engine.");

    if (psczMessage)
    {
        if (*psczMessage)
        {
            hr = StrMaxLength(*psczMessage, &cchMessage);
            ExitOnFailure(hr, "Failed to get length of message.");
        }

        hr = pEngine->FormatString(pCondition->sczMessage, *psczMessage, &cchMessage);
        if (E_MOREDATA == hr)
        {
            ++cchMessage;

            hr = StrAllocSecure(psczMessage, cchMessage);
            ExitOnFailure(hr, "Failed to allocate string for condition's formatted message.");

            hr = pEngine->FormatString(pCondition->sczMessage, *psczMessage, &cchMessage);
        }
        ExitOnFailure(hr, "Failed to format condition's message.");
    }

LExit:
    return hr;
}


DAPI_(void) BalConditionsUninitialize(
    __in BAL_CONDITIONS* pConditions
    )
{
    for (DWORD i = 0; i < pConditions->cConditions; ++i)
    {
        ReleaseStr(pConditions->rgConditions[i].sczMessage);
        ReleaseStr(pConditions->rgConditions[i].sczCondition);
    }

    ReleaseMem(pConditions->rgConditions);
    memset(pConditions, 0, sizeof(BAL_CONDITIONS));
}