diff options
Diffstat (limited to 'src/api/burn/balutil/balutil.cpp')
-rw-r--r-- | src/api/burn/balutil/balutil.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/src/api/burn/balutil/balutil.cpp b/src/api/burn/balutil/balutil.cpp new file mode 100644 index 00000000..7a638219 --- /dev/null +++ b/src/api/burn/balutil/balutil.cpp | |||
@@ -0,0 +1,425 @@ | |||
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 | const DWORD VARIABLE_GROW_FACTOR = 80; | ||
6 | static IBootstrapperEngine* vpEngine = NULL; | ||
7 | |||
8 | // prototypes | ||
9 | |||
10 | DAPI_(void) BalInitialize( | ||
11 | __in IBootstrapperEngine* pEngine | ||
12 | ) | ||
13 | { | ||
14 | pEngine->AddRef(); | ||
15 | |||
16 | ReleaseObject(vpEngine); | ||
17 | vpEngine = pEngine; | ||
18 | } | ||
19 | |||
20 | DAPI_(HRESULT) BalInitializeFromCreateArgs( | ||
21 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
22 | __out_opt IBootstrapperEngine** ppEngine | ||
23 | ) | ||
24 | { | ||
25 | HRESULT hr = S_OK; | ||
26 | IBootstrapperEngine* pEngine = NULL; | ||
27 | |||
28 | hr = BalBootstrapperEngineCreate(pArgs->pfnBootstrapperEngineProc, pArgs->pvBootstrapperEngineProcContext, &pEngine); | ||
29 | ExitOnFailure(hr, "Failed to create BalBootstrapperEngine."); | ||
30 | |||
31 | BalInitialize(pEngine); | ||
32 | |||
33 | if (ppEngine) | ||
34 | { | ||
35 | *ppEngine = pEngine; | ||
36 | } | ||
37 | pEngine = NULL; | ||
38 | |||
39 | LExit: | ||
40 | ReleaseObject(pEngine); | ||
41 | |||
42 | return hr; | ||
43 | } | ||
44 | |||
45 | |||
46 | DAPI_(void) BalUninitialize() | ||
47 | { | ||
48 | ReleaseNullObject(vpEngine); | ||
49 | } | ||
50 | |||
51 | |||
52 | DAPI_(HRESULT) BalManifestLoad( | ||
53 | __in HMODULE hBootstrapperApplicationModule, | ||
54 | __out IXMLDOMDocument** ppixdManifest | ||
55 | ) | ||
56 | { | ||
57 | HRESULT hr = S_OK; | ||
58 | LPWSTR sczPath = NULL; | ||
59 | |||
60 | hr = PathRelativeToModule(&sczPath, BAL_MANIFEST_FILENAME, hBootstrapperApplicationModule); | ||
61 | ExitOnFailure(hr, "Failed to get path to bootstrapper application manifest: %ls", BAL_MANIFEST_FILENAME); | ||
62 | |||
63 | hr = XmlLoadDocumentFromFile(sczPath, ppixdManifest); | ||
64 | ExitOnFailure(hr, "Failed to load bootstrapper application manifest '%ls' from path: %ls", BAL_MANIFEST_FILENAME, sczPath); | ||
65 | |||
66 | LExit: | ||
67 | ReleaseStr(sczPath); | ||
68 | return hr; | ||
69 | } | ||
70 | |||
71 | |||
72 | DAPI_(HRESULT) BalEvaluateCondition( | ||
73 | __in_z LPCWSTR wzCondition, | ||
74 | __out BOOL* pf | ||
75 | ) | ||
76 | { | ||
77 | HRESULT hr = S_OK; | ||
78 | |||
79 | if (!vpEngine) | ||
80 | { | ||
81 | hr = E_POINTER; | ||
82 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
83 | } | ||
84 | |||
85 | hr = vpEngine->EvaluateCondition(wzCondition, pf); | ||
86 | |||
87 | LExit: | ||
88 | return hr; | ||
89 | } | ||
90 | |||
91 | |||
92 | // The contents of psczOut may be sensitive, should keep encrypted and SecureZeroFree. | ||
93 | DAPI_(HRESULT) BalFormatString( | ||
94 | __in_z LPCWSTR wzFormat, | ||
95 | __inout LPWSTR* psczOut | ||
96 | ) | ||
97 | { | ||
98 | HRESULT hr = S_OK; | ||
99 | SIZE_T cch = 0; | ||
100 | |||
101 | if (!vpEngine) | ||
102 | { | ||
103 | hr = E_POINTER; | ||
104 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
105 | } | ||
106 | |||
107 | if (*psczOut) | ||
108 | { | ||
109 | hr = StrMaxLength(*psczOut, &cch); | ||
110 | ExitOnFailure(hr, "Failed to determine length of value."); | ||
111 | } | ||
112 | |||
113 | hr = vpEngine->FormatString(wzFormat, *psczOut, &cch); | ||
114 | if (E_MOREDATA == hr) | ||
115 | { | ||
116 | ++cch; | ||
117 | |||
118 | hr = StrAllocSecure(psczOut, cch); | ||
119 | ExitOnFailure(hr, "Failed to allocate value."); | ||
120 | |||
121 | hr = vpEngine->FormatString(wzFormat, *psczOut, &cch); | ||
122 | } | ||
123 | |||
124 | LExit: | ||
125 | return hr; | ||
126 | } | ||
127 | |||
128 | |||
129 | // The contents of pllValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroMemory. | ||
130 | DAPI_(HRESULT) BalGetNumericVariable( | ||
131 | __in_z LPCWSTR wzVariable, | ||
132 | __out LONGLONG* pllValue | ||
133 | ) | ||
134 | { | ||
135 | HRESULT hr = S_OK; | ||
136 | |||
137 | if (!vpEngine) | ||
138 | { | ||
139 | hr = E_POINTER; | ||
140 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
141 | } | ||
142 | |||
143 | hr = vpEngine->GetVariableNumeric(wzVariable, pllValue); | ||
144 | |||
145 | LExit: | ||
146 | return hr; | ||
147 | } | ||
148 | |||
149 | |||
150 | DAPI_(HRESULT) BalSetNumericVariable( | ||
151 | __in_z LPCWSTR wzVariable, | ||
152 | __in LONGLONG llValue | ||
153 | ) | ||
154 | { | ||
155 | HRESULT hr = S_OK; | ||
156 | |||
157 | if (!vpEngine) | ||
158 | { | ||
159 | hr = E_POINTER; | ||
160 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
161 | } | ||
162 | |||
163 | hr = vpEngine->SetVariableNumeric(wzVariable, llValue); | ||
164 | |||
165 | LExit: | ||
166 | return hr; | ||
167 | } | ||
168 | |||
169 | |||
170 | DAPI_(BOOL) BalVariableExists( | ||
171 | __in_z LPCWSTR wzVariable | ||
172 | ) | ||
173 | { | ||
174 | HRESULT hr = S_OK; | ||
175 | SIZE_T cch = 0; | ||
176 | |||
177 | if (!vpEngine) | ||
178 | { | ||
179 | hr = E_POINTER; | ||
180 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
181 | } | ||
182 | |||
183 | hr = vpEngine->GetVariableString(wzVariable, NULL, &cch); | ||
184 | |||
185 | LExit: | ||
186 | return E_NOTFOUND != hr; | ||
187 | } | ||
188 | |||
189 | |||
190 | // The contents of psczValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroFree. | ||
191 | DAPI_(HRESULT) BalGetStringVariable( | ||
192 | __in_z LPCWSTR wzVariable, | ||
193 | __inout LPWSTR* psczValue | ||
194 | ) | ||
195 | { | ||
196 | HRESULT hr = S_OK; | ||
197 | SIZE_T cch = 0; | ||
198 | |||
199 | if (!vpEngine) | ||
200 | { | ||
201 | hr = E_POINTER; | ||
202 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
203 | } | ||
204 | |||
205 | if (*psczValue) | ||
206 | { | ||
207 | hr = StrMaxLength(*psczValue, &cch); | ||
208 | ExitOnFailure(hr, "Failed to determine length of value."); | ||
209 | } | ||
210 | |||
211 | hr = vpEngine->GetVariableString(wzVariable, *psczValue, &cch); | ||
212 | if (E_MOREDATA == hr) | ||
213 | { | ||
214 | ++cch; | ||
215 | |||
216 | hr = StrAllocSecure(psczValue, cch); | ||
217 | ExitOnFailure(hr, "Failed to allocate value."); | ||
218 | |||
219 | hr = vpEngine->GetVariableString(wzVariable, *psczValue, &cch); | ||
220 | } | ||
221 | |||
222 | LExit: | ||
223 | return hr; | ||
224 | } | ||
225 | |||
226 | DAPI_(HRESULT) BalSetStringVariable( | ||
227 | __in_z LPCWSTR wzVariable, | ||
228 | __in_z_opt LPCWSTR wzValue, | ||
229 | __in BOOL fFormatted | ||
230 | ) | ||
231 | { | ||
232 | HRESULT hr = S_OK; | ||
233 | |||
234 | if (!vpEngine) | ||
235 | { | ||
236 | hr = E_POINTER; | ||
237 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
238 | } | ||
239 | |||
240 | hr = vpEngine->SetVariableString(wzVariable, wzValue, fFormatted); | ||
241 | |||
242 | LExit: | ||
243 | return hr; | ||
244 | } | ||
245 | |||
246 | |||
247 | DAPIV_(HRESULT) BalLog( | ||
248 | __in BOOTSTRAPPER_LOG_LEVEL level, | ||
249 | __in_z __format_string LPCSTR szFormat, | ||
250 | ... | ||
251 | ) | ||
252 | { | ||
253 | HRESULT hr = S_OK; | ||
254 | va_list args; | ||
255 | |||
256 | if (!vpEngine) | ||
257 | { | ||
258 | hr = E_POINTER; | ||
259 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
260 | } | ||
261 | |||
262 | va_start(args, szFormat); | ||
263 | hr = BalLogArgs(level, szFormat, args); | ||
264 | va_end(args); | ||
265 | |||
266 | LExit: | ||
267 | return hr; | ||
268 | } | ||
269 | |||
270 | |||
271 | DAPI_(HRESULT) BalLogArgs( | ||
272 | __in BOOTSTRAPPER_LOG_LEVEL level, | ||
273 | __in_z __format_string LPCSTR szFormat, | ||
274 | __in va_list args | ||
275 | ) | ||
276 | { | ||
277 | HRESULT hr = S_OK; | ||
278 | LPSTR sczFormattedAnsi = NULL; | ||
279 | LPWSTR sczMessage = NULL; | ||
280 | |||
281 | if (!vpEngine) | ||
282 | { | ||
283 | hr = E_POINTER; | ||
284 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
285 | } | ||
286 | |||
287 | hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args); | ||
288 | ExitOnFailure(hr, "Failed to format log string."); | ||
289 | |||
290 | hr = StrAllocStringAnsi(&sczMessage, sczFormattedAnsi, 0, CP_UTF8); | ||
291 | ExitOnFailure(hr, "Failed to convert log string to Unicode."); | ||
292 | |||
293 | hr = vpEngine->Log(level, sczMessage); | ||
294 | |||
295 | LExit: | ||
296 | ReleaseStr(sczMessage); | ||
297 | ReleaseStr(sczFormattedAnsi); | ||
298 | return hr; | ||
299 | } | ||
300 | |||
301 | |||
302 | DAPIV_(HRESULT) BalLogError( | ||
303 | __in HRESULT hrError, | ||
304 | __in_z __format_string LPCSTR szFormat, | ||
305 | ... | ||
306 | ) | ||
307 | { | ||
308 | HRESULT hr = S_OK; | ||
309 | va_list args; | ||
310 | |||
311 | if (!vpEngine) | ||
312 | { | ||
313 | hr = E_POINTER; | ||
314 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
315 | } | ||
316 | |||
317 | va_start(args, szFormat); | ||
318 | hr = BalLogErrorArgs(hrError, szFormat, args); | ||
319 | va_end(args); | ||
320 | |||
321 | LExit: | ||
322 | return hr; | ||
323 | } | ||
324 | |||
325 | |||
326 | DAPI_(HRESULT) BalLogErrorArgs( | ||
327 | __in HRESULT hrError, | ||
328 | __in_z __format_string LPCSTR szFormat, | ||
329 | __in va_list args | ||
330 | ) | ||
331 | { | ||
332 | HRESULT hr = S_OK; | ||
333 | LPSTR sczFormattedAnsi = NULL; | ||
334 | LPWSTR sczMessage = NULL; | ||
335 | |||
336 | if (!vpEngine) | ||
337 | { | ||
338 | hr = E_POINTER; | ||
339 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
340 | } | ||
341 | |||
342 | hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args); | ||
343 | ExitOnFailure(hr, "Failed to format error log string."); | ||
344 | |||
345 | hr = StrAllocFormatted(&sczMessage, L"Error 0x%08x: %S", hrError, sczFormattedAnsi); | ||
346 | ExitOnFailure(hr, "Failed to prepend error number to error log string."); | ||
347 | |||
348 | hr = vpEngine->Log(BOOTSTRAPPER_LOG_LEVEL_ERROR, sczMessage); | ||
349 | |||
350 | LExit: | ||
351 | ReleaseStr(sczMessage); | ||
352 | ReleaseStr(sczFormattedAnsi); | ||
353 | return hr; | ||
354 | } | ||
355 | |||
356 | DAPIV_(HRESULT) BalLogId( | ||
357 | __in BOOTSTRAPPER_LOG_LEVEL level, | ||
358 | __in DWORD dwLogId, | ||
359 | __in HMODULE hModule, | ||
360 | ... | ||
361 | ) | ||
362 | { | ||
363 | HRESULT hr = S_OK; | ||
364 | va_list args; | ||
365 | |||
366 | if (!vpEngine) | ||
367 | { | ||
368 | hr = E_POINTER; | ||
369 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
370 | } | ||
371 | |||
372 | va_start(args, hModule); | ||
373 | hr = BalLogIdArgs(level, dwLogId, hModule, args); | ||
374 | va_end(args); | ||
375 | |||
376 | LExit: | ||
377 | return hr; | ||
378 | } | ||
379 | |||
380 | DAPI_(HRESULT) BalLogIdArgs( | ||
381 | __in BOOTSTRAPPER_LOG_LEVEL level, | ||
382 | __in DWORD dwLogId, | ||
383 | __in HMODULE hModule, | ||
384 | __in va_list args | ||
385 | ) | ||
386 | { | ||
387 | |||
388 | HRESULT hr = S_OK; | ||
389 | LPWSTR pwz = NULL; | ||
390 | DWORD cch = 0; | ||
391 | |||
392 | if (!vpEngine) | ||
393 | { | ||
394 | hr = E_POINTER; | ||
395 | ExitOnRootFailure(hr, "BalInitialize() must be called first."); | ||
396 | } | ||
397 | |||
398 | // Get the string for the id. | ||
399 | #pragma prefast(push) | ||
400 | #pragma prefast(disable:25028) | ||
401 | #pragma prefast(disable:25068) | ||
402 | cch = ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, | ||
403 | static_cast<LPCVOID>(hModule), dwLogId, 0, reinterpret_cast<LPWSTR>(&pwz), 0, &args); | ||
404 | #pragma prefast(pop) | ||
405 | |||
406 | if (0 == cch) | ||
407 | { | ||
408 | ExitOnLastError(hr, "Failed to log id: %d", dwLogId); | ||
409 | } | ||
410 | |||
411 | if (2 <= cch && L'\r' == pwz[cch - 2] && L'\n' == pwz[cch - 1]) | ||
412 | { | ||
413 | pwz[cch - 2] = L'\0'; // remove newline from message table. | ||
414 | } | ||
415 | |||
416 | hr = vpEngine->Log(level, pwz); | ||
417 | |||
418 | LExit: | ||
419 | if (pwz) | ||
420 | { | ||
421 | ::LocalFree(pwz); | ||
422 | } | ||
423 | |||
424 | return hr; | ||
425 | } | ||