summaryrefslogtreecommitdiff
path: root/src/burn/engine/logging.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-04-22 17:06:54 -0700
committerRob Mensching <rob@firegiant.com>2021-04-29 16:36:06 -0700
commitaf10c45d7b3a44af0b461a557847fe03263dcc10 (patch)
tree6a5c1532304782c36ffe4200b38f3afb76789a43 /src/burn/engine/logging.cpp
parent9c2aed97299fb96aeee3f1471ce40225437aaecf (diff)
downloadwix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.gz
wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.bz2
wix-af10c45d7b3a44af0b461a557847fe03263dcc10.zip
Move burn into burn
Diffstat (limited to 'src/burn/engine/logging.cpp')
-rw-r--r--src/burn/engine/logging.cpp754
1 files changed, 754 insertions, 0 deletions
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
new file mode 100644
index 00000000..065ef907
--- /dev/null
+++ b/src/burn/engine/logging.cpp
@@ -0,0 +1,754 @@
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
6static DWORD vdwPackageSequence = 0;
7static const DWORD LOG_OPEN_RETRY_COUNT = 3;
8static const DWORD LOG_OPEN_RETRY_WAIT = 2000;
9static CONST LPWSTR LOG_FAILED_EVENT_LOG_MESSAGE = L"Burn Engine Fatal Error: failed to open log file.";
10
11// structs
12
13
14
15// internal function declarations
16
17static void CheckLoggingPolicy(
18 __out DWORD *pdwAttributes
19 );
20static HRESULT GetNonSessionSpecificTempFolder(
21 __deref_out_z LPWSTR* psczNonSessionTempFolder
22 );
23
24
25// function definitions
26
27extern "C" HRESULT LoggingOpen(
28 __in BURN_LOGGING* pLog,
29 __in BURN_VARIABLES* pVariables,
30 __in BOOTSTRAPPER_DISPLAY display,
31 __in_z LPCWSTR wzBundleName
32 )
33{
34 HRESULT hr = S_OK;
35 LPWSTR sczLoggingBaseFolder = NULL;
36 LPWSTR sczPrefixFormatted = NULL;
37
38 // Check if the logging policy is set and configure the logging appropriately.
39 CheckLoggingPolicy(&pLog->dwAttributes);
40
41 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_VERBOSE || pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_EXTRADEBUG)
42 {
43 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_EXTRADEBUG)
44 {
45 LogSetLevel(REPORT_DEBUG, FALSE);
46 }
47 else if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_VERBOSE)
48 {
49 LogSetLevel(REPORT_VERBOSE, FALSE);
50 }
51
52 if ((!pLog->sczPath || !*pLog->sczPath) && (!pLog->sczPrefix || !*pLog->sczPrefix))
53 {
54 PathCreateTimeBasedTempFile(NULL, L"Setup", NULL, L"log", &pLog->sczPath, NULL);
55 }
56 }
57
58 // Open the log approriately.
59 if (pLog->sczPath && *pLog->sczPath)
60 {
61 DWORD cRetry = 0;
62
63 hr = DirGetCurrent(&sczLoggingBaseFolder);
64 ExitOnFailure(hr, "Failed to get current directory.");
65
66 // Try pretty hard to open the log file when appending.
67 do
68 {
69 if (0 < cRetry)
70 {
71 ::Sleep(LOG_OPEN_RETRY_WAIT);
72 }
73
74 hr = LogOpen(sczLoggingBaseFolder, pLog->sczPath, NULL, NULL, pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND, FALSE, &pLog->sczPath);
75 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND && HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == hr)
76 {
77 ++cRetry;
78 }
79 } while (cRetry > 0 && cRetry <= LOG_OPEN_RETRY_COUNT);
80
81 if (FAILED(hr))
82 {
83 // Log is not open, so note that.
84 LogDisable();
85 pLog->state = BURN_LOGGING_STATE_DISABLED;
86
87 if (pLog->dwAttributes & BURN_LOGGING_ATTRIBUTE_APPEND)
88 {
89 // If appending, ignore the failure and continue.
90 hr = S_OK;
91 }
92 else // specifically tried to create a log file so show an error if appropriate and bail.
93 {
94 HRESULT hrOriginal = hr;
95
96 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_LOG_FAILURE);
97 SplashScreenDisplayError(display, wzBundleName, hr);
98
99 ExitOnFailure(hrOriginal, "Failed to open log: %ls", pLog->sczPath);
100 }
101 }
102 else
103 {
104 pLog->state = BURN_LOGGING_STATE_OPEN;
105 }
106 }
107 else
108 {
109 if (pLog->sczPrefix && *pLog->sczPrefix)
110 {
111 hr = VariableFormatString(pVariables, pLog->sczPrefix, &sczPrefixFormatted, NULL);
112 }
113
114 if (sczPrefixFormatted && *sczPrefixFormatted)
115 {
116 LPCWSTR wzPrefix = sczPrefixFormatted;
117
118 // Best effort to open default logging.
119 if (PathIsAbsolute(sczPrefixFormatted))
120 {
121 hr = PathGetDirectory(sczPrefixFormatted, &sczLoggingBaseFolder);
122 ExitOnFailure(hr, "Failed to get parent directory from '%ls'.", sczPrefixFormatted);
123
124 wzPrefix = PathFile(sczPrefixFormatted);
125 }
126 else
127 {
128 hr = GetNonSessionSpecificTempFolder(&sczLoggingBaseFolder);
129 ExitOnFailure(hr, "Failed to get non-session specific TEMP folder.");
130 }
131
132 hr = LogOpen(sczLoggingBaseFolder, wzPrefix, NULL, pLog->sczExtension, FALSE, FALSE, &pLog->sczPath);
133 if (FAILED(hr))
134 {
135 LogDisable();
136 pLog->state = BURN_LOGGING_STATE_DISABLED;
137
138 hr = S_OK;
139 }
140 else
141 {
142 pLog->state = BURN_LOGGING_STATE_OPEN;
143 }
144 }
145 else // no logging enabled.
146 {
147 LogDisable();
148 pLog->state = BURN_LOGGING_STATE_DISABLED;
149 }
150 }
151
152 // If the log was opened, write the header info and update the prefix and extension to match
153 // the log name so future logs are opened with the same pattern.
154 if (BURN_LOGGING_STATE_OPEN == pLog->state)
155 {
156 LPCWSTR wzExtension = PathExtension(pLog->sczPath);
157 if (wzExtension && *wzExtension)
158 {
159 hr = StrAllocString(&pLog->sczPrefix, pLog->sczPath, wzExtension - pLog->sczPath);
160 ExitOnFailure(hr, "Failed to copy log path to prefix.");
161
162 hr = StrAllocString(&pLog->sczExtension, wzExtension + 1, 0);
163 ExitOnFailure(hr, "Failed to copy log extension to extension.");
164 }
165 else
166 {
167 hr = StrAllocString(&pLog->sczPrefix, pLog->sczPath, 0);
168 ExitOnFailure(hr, "Failed to copy full log path to prefix.");
169 }
170
171 if (pLog->sczPathVariable && *pLog->sczPathVariable)
172 {
173 VariableSetString(pVariables, pLog->sczPathVariable, pLog->sczPath, FALSE, FALSE); // Ignore failure.
174 }
175 }
176
177LExit:
178 ReleaseStr(sczLoggingBaseFolder);
179 StrSecureZeroFreeString(sczPrefixFormatted);
180
181 return hr;
182}
183
184extern "C" void LoggingOpenFailed()
185{
186 HRESULT hr = S_OK;
187 HANDLE hEventLog = NULL;
188 LPCWSTR* lpStrings = const_cast<LPCWSTR*>(&LOG_FAILED_EVENT_LOG_MESSAGE);
189 WORD wNumStrings = 1;
190
191 hr = LogOpen(NULL, L"Setup", L"_Failed", L"txt", FALSE, FALSE, NULL);
192 if (SUCCEEDED(hr))
193 {
194 ExitFunction();
195 }
196
197 // If opening the "failure" log failed, then attempt to record that in the Application event log.
198 hEventLog = ::OpenEventLogW(NULL, L"Application");
199 ExitOnNullWithLastError(hEventLog, hr, "Failed to open Application event log");
200
201 hr = ::ReportEventW(hEventLog, EVENTLOG_ERROR_TYPE, 1, 1, NULL, wNumStrings, 0, lpStrings, NULL);
202 ExitOnNullWithLastError(hEventLog, hr, "Failed to write event log entry");
203
204LExit:
205 if (hEventLog)
206 {
207 ::CloseEventLog(hEventLog);
208 }
209}
210
211extern "C" void LoggingIncrementPackageSequence()
212{
213 ++vdwPackageSequence;
214}
215
216extern "C" HRESULT LoggingSetPackageVariable(
217 __in BURN_PACKAGE* pPackage,
218 __in_z_opt LPCWSTR wzSuffix,
219 __in BOOL fRollback,
220 __in BURN_LOGGING* pLog,
221 __in BURN_VARIABLES* pVariables,
222 __out_opt LPWSTR* psczLogPath
223 )
224{
225 HRESULT hr = S_OK;
226 LPWSTR sczLogPath = NULL;
227
228 // Make sure that no package log files are created when logging has been disabled via Log element.
229 if (BURN_LOGGING_STATE_DISABLED == pLog->state)
230 {
231 if (psczLogPath)
232 {
233 *psczLogPath = NULL;
234 }
235
236 ExitFunction();
237 }
238
239 if ((!fRollback && pPackage->sczLogPathVariable && *pPackage->sczLogPathVariable) ||
240 (fRollback && pPackage->sczRollbackLogPathVariable && *pPackage->sczRollbackLogPathVariable))
241 {
242 hr = StrAllocFormatted(&sczLogPath, L"%ls%hs%ls_%03u_%ls%ls.%ls", pLog->sczPrefix, wzSuffix && *wzSuffix ? "_" : "", wzSuffix && *wzSuffix ? wzSuffix : L"", vdwPackageSequence, pPackage->sczId, fRollback ? L"_rollback" : L"", pLog->sczExtension);
243 ExitOnFailure(hr, "Failed to allocate path for package log.");
244
245 hr = VariableSetString(pVariables, fRollback ? pPackage->sczRollbackLogPathVariable : pPackage->sczLogPathVariable, sczLogPath, FALSE, FALSE);
246 ExitOnFailure(hr, "Failed to set log path into variable.");
247
248 if (psczLogPath)
249 {
250 hr = StrAllocString(psczLogPath, sczLogPath, 0);
251 ExitOnFailure(hr, "Failed to copy package log path.");
252 }
253 }
254
255LExit:
256 ReleaseStr(sczLogPath);
257
258 return hr;
259}
260
261extern "C" LPCSTR LoggingBurnActionToString(
262 __in BOOTSTRAPPER_ACTION action
263 )
264{
265 switch (action)
266 {
267 case BOOTSTRAPPER_ACTION_UNKNOWN:
268 return "Unknown";
269 case BOOTSTRAPPER_ACTION_HELP:
270 return "Help";
271 case BOOTSTRAPPER_ACTION_LAYOUT:
272 return "Layout";
273 case BOOTSTRAPPER_ACTION_CACHE:
274 return "Cache";
275 case BOOTSTRAPPER_ACTION_UNINSTALL:
276 return "Uninstall";
277 case BOOTSTRAPPER_ACTION_INSTALL:
278 return "Install";
279 case BOOTSTRAPPER_ACTION_MODIFY:
280 return "Modify";
281 case BOOTSTRAPPER_ACTION_REPAIR:
282 return "Repair";
283 case BOOTSTRAPPER_ACTION_UPDATE_REPLACE:
284 return "UpdateReplace";
285 case BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED:
286 return "UpdateReplaceEmbedded";
287 default:
288 return "Invalid";
289 }
290}
291
292LPCSTR LoggingBurnMessageToString(
293 __in UINT message
294 )
295{
296 switch (message)
297 {
298 case WM_BURN_APPLY:
299 return "Apply";
300 case WM_BURN_DETECT:
301 return "Detect";
302 case WM_BURN_ELEVATE:
303 return "Elevate";
304 case WM_BURN_LAUNCH_APPROVED_EXE:
305 return "LaunchApprovedExe";
306 case WM_BURN_PLAN:
307 return "Plan";
308 case WM_BURN_QUIT:
309 return "Quit";
310 default:
311 return "Invalid";
312 }
313}
314
315extern "C" LPCSTR LoggingActionStateToString(
316 __in BOOTSTRAPPER_ACTION_STATE actionState
317 )
318{
319 switch (actionState)
320 {
321 case BOOTSTRAPPER_ACTION_STATE_NONE:
322 return "None";
323 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
324 return "Uninstall";
325 case BOOTSTRAPPER_ACTION_STATE_INSTALL:
326 return "Install";
327 case BOOTSTRAPPER_ACTION_STATE_MODIFY:
328 return "Modify";
329 case BOOTSTRAPPER_ACTION_STATE_MEND:
330 return "Mend";
331 case BOOTSTRAPPER_ACTION_STATE_REPAIR:
332 return "Repair";
333 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE:
334 return "MinorUpgrade";
335 default:
336 return "Invalid";
337 }
338}
339
340extern "C" LPCSTR LoggingDependencyActionToString(
341 BURN_DEPENDENCY_ACTION action
342 )
343{
344 switch (action)
345 {
346 case BURN_DEPENDENCY_ACTION_NONE:
347 return "None";
348 case BURN_DEPENDENCY_ACTION_REGISTER:
349 return "Register";
350 case BURN_DEPENDENCY_ACTION_UNREGISTER:
351 return "Unregister";
352 default:
353 return "Invalid";
354 }
355}
356
357extern "C" LPCSTR LoggingBoolToString(
358 __in BOOL f
359 )
360{
361 if (f)
362 {
363 return "Yes";
364 }
365
366 return "No";
367}
368
369extern "C" LPCSTR LoggingTrueFalseToString(
370 __in BOOL f
371 )
372{
373 if (f)
374 {
375 return "true";
376 }
377
378 return "false";
379}
380
381extern "C" LPCSTR LoggingPackageStateToString(
382 __in BOOTSTRAPPER_PACKAGE_STATE packageState
383 )
384{
385 switch (packageState)
386 {
387 case BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN:
388 return "Unknown";
389 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE:
390 return "Obsolete";
391 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
392 return "Absent";
393 case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
394 return "Present";
395 case BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED:
396 return "Superseded";
397 default:
398 return "Invalid";
399 }
400}
401
402extern "C" LPCSTR LoggingPackageRegistrationStateToString(
403 __in BOOL fCanAffectRegistration,
404 __in BURN_PACKAGE_REGISTRATION_STATE registrationState
405 )
406{
407 if (!fCanAffectRegistration)
408 {
409 return "(permanent)";
410 }
411
412 switch (registrationState)
413 {
414 case BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN:
415 return "Unknown";
416 case BURN_PACKAGE_REGISTRATION_STATE_IGNORED:
417 return "Ignored";
418 case BURN_PACKAGE_REGISTRATION_STATE_ABSENT:
419 return "Absent";
420 case BURN_PACKAGE_REGISTRATION_STATE_PRESENT:
421 return "Present";
422 default:
423 return "Invalid";
424 }
425}
426
427extern "C" LPCSTR LoggingMsiFeatureStateToString(
428 __in BOOTSTRAPPER_FEATURE_STATE featureState
429 )
430{
431 switch (featureState)
432 {
433 case BOOTSTRAPPER_FEATURE_STATE_UNKNOWN:
434 return "Unknown";
435 case BOOTSTRAPPER_FEATURE_STATE_ABSENT:
436 return "Absent";
437 case BOOTSTRAPPER_FEATURE_STATE_ADVERTISED:
438 return "Advertised";
439 case BOOTSTRAPPER_FEATURE_STATE_LOCAL:
440 return "Local";
441 case BOOTSTRAPPER_FEATURE_STATE_SOURCE:
442 return "Source";
443 default:
444 return "Invalid";
445 }
446}
447
448extern "C" LPCSTR LoggingMsiFeatureActionToString(
449 __in BOOTSTRAPPER_FEATURE_ACTION featureAction
450 )
451{
452 switch (featureAction)
453 {
454 case BOOTSTRAPPER_FEATURE_ACTION_NONE:
455 return "None";
456 case BOOTSTRAPPER_FEATURE_ACTION_ADDLOCAL:
457 return "AddLocal";
458 case BOOTSTRAPPER_FEATURE_ACTION_ADDSOURCE:
459 return "AddSource";
460 case BOOTSTRAPPER_FEATURE_ACTION_ADDDEFAULT:
461 return "AddDefault";
462 case BOOTSTRAPPER_FEATURE_ACTION_REINSTALL:
463 return "Reinstall";
464 case BOOTSTRAPPER_FEATURE_ACTION_ADVERTISE:
465 return "Advertise";
466 case BOOTSTRAPPER_FEATURE_ACTION_REMOVE:
467 return "Remove";
468 default:
469 return "Invalid";
470 }
471}
472
473extern "C" LPCSTR LoggingMsiInstallContext(
474 __in MSIINSTALLCONTEXT context
475 )
476{
477 switch (context)
478 {
479 case MSIINSTALLCONTEXT_ALL:
480 return "All";
481 case MSIINSTALLCONTEXT_ALLUSERMANAGED:
482 return "AllUserManaged";
483 case MSIINSTALLCONTEXT_MACHINE:
484 return "Machine";
485 case MSIINSTALLCONTEXT_NONE:
486 return "None";
487 case MSIINSTALLCONTEXT_USERMANAGED:
488 return "UserManaged";
489 case MSIINSTALLCONTEXT_USERUNMANAGED:
490 return "UserUnmanaged";
491 default:
492 return "Invalid";
493 }
494}
495
496extern "C" LPCWSTR LoggingBurnMsiPropertyToString(
497 __in BURN_MSI_PROPERTY burnMsiProperty
498 )
499{
500 switch (burnMsiProperty)
501 {
502 case BURN_MSI_PROPERTY_INSTALL:
503 return BURNMSIINSTALL_PROPERTY_NAME;
504 case BURN_MSI_PROPERTY_MODIFY:
505 return BURNMSIMODIFY_PROPERTY_NAME;
506 case BURN_MSI_PROPERTY_NONE:
507 return L"(none)";
508 case BURN_MSI_PROPERTY_REPAIR:
509 return BURNMSIREPAIR_PROPERTY_NAME;
510 case BURN_MSI_PROPERTY_UNINSTALL:
511 return BURNMSIUNINSTALL_PROPERTY_NAME;
512 default:
513 return L"Invalid";
514 }
515}
516
517extern "C" LPCSTR LoggingMspTargetActionToString(
518 __in BOOTSTRAPPER_ACTION_STATE action,
519 __in BURN_PATCH_SKIP_STATE skipState
520 )
521{
522 switch (skipState)
523 {
524 case BURN_PATCH_SKIP_STATE_NONE:
525 return LoggingActionStateToString(action);
526 case BURN_PATCH_SKIP_STATE_TARGET_UNINSTALL:
527 return "Skipped (target uninstall)";
528 case BURN_PATCH_SKIP_STATE_SLIPSTREAM:
529 return "Skipped (slipstream)";
530 default:
531 return "Invalid";
532 }
533}
534
535extern "C" LPCSTR LoggingPerMachineToString(
536 __in BOOL fPerMachine
537 )
538{
539 if (fPerMachine)
540 {
541 return "PerMachine";
542 }
543
544 return "PerUser";
545}
546
547extern "C" LPCSTR LoggingRestartToString(
548 __in BOOTSTRAPPER_APPLY_RESTART restart
549 )
550{
551 switch (restart)
552 {
553 case BOOTSTRAPPER_APPLY_RESTART_NONE:
554 return "None";
555 case BOOTSTRAPPER_APPLY_RESTART_REQUIRED:
556 return "Required";
557 case BOOTSTRAPPER_APPLY_RESTART_INITIATED:
558 return "Initiated";
559 default:
560 return "Invalid";
561 }
562}
563
564extern "C" LPCSTR LoggingResumeModeToString(
565 __in BURN_RESUME_MODE resumeMode
566 )
567{
568 switch (resumeMode)
569 {
570 case BURN_RESUME_MODE_NONE:
571 return "None";
572 case BURN_RESUME_MODE_ACTIVE:
573 return "Active";
574 case BURN_RESUME_MODE_SUSPEND:
575 return "Suspend";
576 case BURN_RESUME_MODE_ARP:
577 return "ARP";
578 case BURN_RESUME_MODE_REBOOT_PENDING:
579 return "Reboot Pending";
580 default:
581 return "Invalid";
582 }
583}
584
585extern "C" LPCSTR LoggingRelationTypeToString(
586 __in BOOTSTRAPPER_RELATION_TYPE type
587 )
588{
589 switch (type)
590 {
591 case BOOTSTRAPPER_RELATION_NONE:
592 return "None";
593 case BOOTSTRAPPER_RELATION_DETECT:
594 return "Detect";
595 case BOOTSTRAPPER_RELATION_UPGRADE:
596 return "Upgrade";
597 case BOOTSTRAPPER_RELATION_ADDON:
598 return "Addon";
599 case BOOTSTRAPPER_RELATION_PATCH:
600 return "Patch";
601 case BOOTSTRAPPER_RELATION_DEPENDENT:
602 return "Dependent";
603 case BOOTSTRAPPER_RELATION_UPDATE:
604 return "Update";
605 default:
606 return "Invalid";
607 }
608}
609
610extern "C" LPCSTR LoggingRelatedOperationToString(
611 __in BOOTSTRAPPER_RELATED_OPERATION operation
612 )
613{
614 switch (operation)
615 {
616 case BOOTSTRAPPER_RELATED_OPERATION_NONE:
617 return "None";
618 case BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE:
619 return "Downgrade";
620 case BOOTSTRAPPER_RELATED_OPERATION_MINOR_UPDATE:
621 return "MinorUpdate";
622 case BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE:
623 return "MajorUpgrade";
624 case BOOTSTRAPPER_RELATED_OPERATION_REMOVE:
625 return "Remove";
626 case BOOTSTRAPPER_RELATED_OPERATION_INSTALL:
627 return "Install";
628 case BOOTSTRAPPER_RELATED_OPERATION_REPAIR:
629 return "Repair";
630 default:
631 return "Invalid";
632 }
633}
634
635extern "C" LPCSTR LoggingRequestStateToString(
636 __in BOOTSTRAPPER_REQUEST_STATE requestState
637 )
638{
639 switch (requestState)
640 {
641 case BOOTSTRAPPER_REQUEST_STATE_NONE:
642 return "None";
643 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
644 return "ForceAbsent";
645 case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
646 return "Absent";
647 case BOOTSTRAPPER_REQUEST_STATE_CACHE:
648 return "Cache";
649 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
650 return "Present";
651 case BOOTSTRAPPER_REQUEST_STATE_MEND:
652 return "Mend";
653 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
654 return "Repair";
655 default:
656 return "Invalid";
657 }
658}
659
660extern "C" LPCSTR LoggingRollbackOrExecute(
661 __in BOOL fRollback
662 )
663{
664 return fRollback ? "rollback" : "execute";
665}
666
667extern "C" LPWSTR LoggingStringOrUnknownIfNull(
668 __in LPCWSTR wz
669 )
670{
671 return wz ? wz : L"Unknown";
672}
673
674
675// internal function declarations
676
677static void CheckLoggingPolicy(
678 __out DWORD *pdwAttributes
679 )
680{
681 HRESULT hr = S_OK;
682 HKEY hk = NULL;
683 LPWSTR sczLoggingPolicy = NULL;
684
685 hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer", KEY_READ, &hk);
686 if (SUCCEEDED(hr))
687 {
688 hr = RegReadString(hk, L"Logging", &sczLoggingPolicy);
689 if (SUCCEEDED(hr))
690 {
691 LPCWSTR wz = sczLoggingPolicy;
692 while (*wz)
693 {
694 if (L'v' == *wz || L'V' == *wz)
695 {
696 *pdwAttributes |= BURN_LOGGING_ATTRIBUTE_VERBOSE;
697 }
698 else if (L'x' == *wz || L'X' == *wz)
699 {
700 *pdwAttributes |= BURN_LOGGING_ATTRIBUTE_EXTRADEBUG;
701 }
702
703 ++wz;
704 }
705 }
706 }
707
708 ReleaseStr(sczLoggingPolicy);
709 ReleaseRegKey(hk);
710}
711
712static HRESULT GetNonSessionSpecificTempFolder(
713 __deref_out_z LPWSTR* psczNonSessionTempFolder
714 )
715{
716 HRESULT hr = S_OK;
717 WCHAR wzTempFolder[MAX_PATH] = { };
718 SIZE_T cchTempFolder = 0;
719 DWORD dwSessionId = 0;
720 LPWSTR sczSessionId = 0;
721 SIZE_T cchSessionId = 0;
722
723 if (!::GetTempPathW(countof(wzTempFolder), wzTempFolder))
724 {
725 ExitWithLastError(hr, "Failed to get temp folder.");
726 }
727
728 hr = ::StringCchLengthW(wzTempFolder, countof(wzTempFolder), reinterpret_cast<size_t*>(&cchTempFolder));
729 ExitOnFailure(hr, "Failed to get length of temp folder.");
730
731 // If our session id is in the TEMP path then remove that part so we get the non-session
732 // specific temporary folder.
733 if (::ProcessIdToSessionId(::GetCurrentProcessId(), &dwSessionId))
734 {
735 hr = StrAllocFormatted(&sczSessionId, L"%u\\", dwSessionId);
736 ExitOnFailure(hr, "Failed to format session id as a string.");
737
738 hr = ::StringCchLengthW(sczSessionId, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cchSessionId));
739 ExitOnFailure(hr, "Failed to get length of session id string.");
740
741 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzTempFolder + cchTempFolder - cchSessionId, static_cast<DWORD>(cchSessionId), sczSessionId, static_cast<DWORD>(cchSessionId)))
742 {
743 cchTempFolder -= cchSessionId;
744 }
745 }
746
747 hr = StrAllocString(psczNonSessionTempFolder, wzTempFolder, cchTempFolder);
748 ExitOnFailure(hr, "Failed to copy temp folder.");
749
750LExit:
751 ReleaseStr(sczSessionId);
752
753 return hr;
754}