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