diff options
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 | } | ||