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