aboutsummaryrefslogtreecommitdiff
path: root/src/api/burn/balutil/balutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/burn/balutil/balutil.cpp')
-rw-r--r--src/api/burn/balutil/balutil.cpp425
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
5const DWORD VARIABLE_GROW_FACTOR = 80;
6static IBootstrapperEngine* vpEngine = NULL;
7
8// prototypes
9
10DAPI_(void) BalInitialize(
11 __in IBootstrapperEngine* pEngine
12 )
13{
14 pEngine->AddRef();
15
16 ReleaseObject(vpEngine);
17 vpEngine = pEngine;
18}
19
20DAPI_(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
39LExit:
40 ReleaseObject(pEngine);
41
42 return hr;
43}
44
45
46DAPI_(void) BalUninitialize()
47{
48 ReleaseNullObject(vpEngine);
49}
50
51
52DAPI_(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
66LExit:
67 ReleaseStr(sczPath);
68 return hr;
69}
70
71
72DAPI_(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
87LExit:
88 return hr;
89}
90
91
92// The contents of psczOut may be sensitive, should keep encrypted and SecureZeroFree.
93DAPI_(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
124LExit:
125 return hr;
126}
127
128
129// The contents of pllValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroMemory.
130DAPI_(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
145LExit:
146 return hr;
147}
148
149
150DAPI_(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
165LExit:
166 return hr;
167}
168
169
170DAPI_(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
185LExit:
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.
191DAPI_(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
222LExit:
223 return hr;
224}
225
226DAPI_(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
242LExit:
243 return hr;
244}
245
246
247DAPIV_(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
266LExit:
267 return hr;
268}
269
270
271DAPI_(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
295LExit:
296 ReleaseStr(sczMessage);
297 ReleaseStr(sczFormattedAnsi);
298 return hr;
299}
300
301
302DAPIV_(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
321LExit:
322 return hr;
323}
324
325
326DAPI_(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
350LExit:
351 ReleaseStr(sczMessage);
352 ReleaseStr(sczFormattedAnsi);
353 return hr;
354}
355
356DAPIV_(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
376LExit:
377 return hr;
378}
379
380DAPI_(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
418LExit:
419 if (pwz)
420 {
421 ::LocalFree(pwz);
422 }
423
424 return hr;
425}