diff options
author | Rob Mensching <rob@firegiant.com> | 2024-03-20 23:51:53 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2024-03-22 14:25:14 -0700 |
commit | 75a8c75d4e02ea219008dc5af7d03869291d61f7 (patch) | |
tree | c51a05a3cb878de83a2043e24a4641bddd181495 | |
parent | 2e5960b575881567a8807e6b8b9c513138b19742 (diff) | |
download | wix-75a8c75d4e02ea219008dc5af7d03869291d61f7.tar.gz wix-75a8c75d4e02ea219008dc5af7d03869291d61f7.tar.bz2 wix-75a8c75d4e02ea219008dc5af7d03869291d61f7.zip |
Protect elevated working folder from malicious data
When running elevated, Burn uses the Windows Temp folder as its working folder
to prevent normal processes from tampering with the files. Windows Temp does
allow non-elevated processes to write to the folder but they cannot see the
files there. Unfortunately, contrary to our belief, non-elevated processes
can read the files in Windows Temp by watching for directory changes. This
allows a malicious process to lie in wait, watching the Windows Temp folder
until a Burn process is launched elevated, then attack the working folder.
Mitigate that attack by protecting the working folder to only elevated users.
Managed custom actions also fall back to using the Windows Temp folder in
some cases and thus can be exposed in a similar fashion as an elevated Burn
process. Remove that possibility.
-rw-r--r-- | src/burn/engine/cache.cpp | 35 | ||||
-rw-r--r-- | src/burn/engine/cache.h | 3 | ||||
-rw-r--r-- | src/burn/engine/core.cpp | 10 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 2 | ||||
-rw-r--r-- | src/burn/engine/userexperience.cpp | 3 | ||||
-rw-r--r-- | src/burn/engine/userexperience.h | 1 | ||||
-rw-r--r-- | src/dtf/SfxCA/SfxUtil.cpp | 32 |
7 files changed, 49 insertions, 37 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 251cd24b..119200ec 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
@@ -107,6 +107,7 @@ static HRESULT SecurePath( | |||
107 | __in LPCWSTR wzPath | 107 | __in LPCWSTR wzPath |
108 | ); | 108 | ); |
109 | static HRESULT CopyEngineToWorkingFolder( | 109 | static HRESULT CopyEngineToWorkingFolder( |
110 | __in BOOL fElevated, | ||
110 | __in BURN_CACHE* pCache, | 111 | __in BURN_CACHE* pCache, |
111 | __in_z LPCWSTR wzSourcePath, | 112 | __in_z LPCWSTR wzSourcePath, |
112 | __in_z LPCWSTR wzWorkingFolderName, | 113 | __in_z LPCWSTR wzWorkingFolderName, |
@@ -342,6 +343,7 @@ LExit: | |||
342 | } | 343 | } |
343 | 344 | ||
344 | extern "C" HRESULT CacheEnsureBaseWorkingFolder( | 345 | extern "C" HRESULT CacheEnsureBaseWorkingFolder( |
346 | __in BOOL fElevated, | ||
345 | __in BURN_CACHE* pCache, | 347 | __in BURN_CACHE* pCache, |
346 | __deref_out_z_opt LPWSTR* psczBaseWorkingFolder | 348 | __deref_out_z_opt LPWSTR* psczBaseWorkingFolder |
347 | ) | 349 | ) |
@@ -350,15 +352,32 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder( | |||
350 | 352 | ||
351 | HRESULT hr = S_OK; | 353 | HRESULT hr = S_OK; |
352 | LPWSTR sczPotential = NULL; | 354 | LPWSTR sczPotential = NULL; |
355 | PSECURITY_DESCRIPTOR psd = NULL; | ||
356 | LPSECURITY_ATTRIBUTES pWorkingFolderAcl = NULL; | ||
353 | 357 | ||
354 | if (!pCache->fInitializedBaseWorkingFolder) | 358 | if (!pCache->fInitializedBaseWorkingFolder) |
355 | { | 359 | { |
360 | // If elevated, allocate the pWorkingFolderAcl to protect the working folder to only SYSTEM and Admins. | ||
361 | if (fElevated) | ||
362 | { | ||
363 | LPCWSTR wzSddl = L"D:PAI(A;;FA;;;BA)(A;OICIIO;GA;;;BA)(A;;FA;;;SY)(A;OICIIO;GA;;;SY)"; | ||
364 | if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSddl, SDDL_REVISION_1, &psd, NULL)) | ||
365 | { | ||
366 | ExitWithLastError(hr, "Failed to create the security descriptor for the working folder."); | ||
367 | } | ||
368 | |||
369 | pWorkingFolderAcl = reinterpret_cast<LPSECURITY_ATTRIBUTES>(MemAlloc(sizeof(SECURITY_ATTRIBUTES), TRUE)); | ||
370 | pWorkingFolderAcl->nLength = sizeof(SECURITY_ATTRIBUTES); | ||
371 | pWorkingFolderAcl->lpSecurityDescriptor = psd; | ||
372 | pWorkingFolderAcl->bInheritHandle = FALSE; | ||
373 | } | ||
374 | |||
356 | for (DWORD i = 0; i < pCache->cPotentialBaseWorkingFolders; ++i) | 375 | for (DWORD i = 0; i < pCache->cPotentialBaseWorkingFolders; ++i) |
357 | { | 376 | { |
358 | hr = PathConcatRelativeToFullyQualifiedBase(pCache->rgsczPotentialBaseWorkingFolders[i], pCache->wzGuid, &sczPotential); | 377 | hr = PathConcatRelativeToFullyQualifiedBase(pCache->rgsczPotentialBaseWorkingFolders[i], pCache->wzGuid, &sczPotential); |
359 | if (SUCCEEDED(hr)) | 378 | if (SUCCEEDED(hr)) |
360 | { | 379 | { |
361 | hr = DirEnsureExists(sczPotential, NULL); | 380 | hr = DirEnsureExists(sczPotential, pWorkingFolderAcl); |
362 | if (SUCCEEDED(hr)) | 381 | if (SUCCEEDED(hr)) |
363 | { | 382 | { |
364 | pCache->sczBaseWorkingFolder = sczPotential; | 383 | pCache->sczBaseWorkingFolder = sczPotential; |
@@ -385,6 +404,11 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder( | |||
385 | } | 404 | } |
386 | 405 | ||
387 | LExit: | 406 | LExit: |
407 | ReleaseMem(pWorkingFolderAcl); | ||
408 | if (psd) | ||
409 | { | ||
410 | ::LocalFree(psd); | ||
411 | } | ||
388 | ReleaseStr(sczPotential); | 412 | ReleaseStr(sczPotential); |
389 | 413 | ||
390 | return hr; | 414 | return hr; |
@@ -900,6 +924,7 @@ extern "C" HRESULT CachePreparePackage( | |||
900 | } | 924 | } |
901 | 925 | ||
902 | extern "C" HRESULT CacheBundleToCleanRoom( | 926 | extern "C" HRESULT CacheBundleToCleanRoom( |
927 | __in BOOL fElevated, | ||
903 | __in BURN_CACHE* pCache, | 928 | __in BURN_CACHE* pCache, |
904 | __in BURN_SECTION* pSection, | 929 | __in BURN_SECTION* pSection, |
905 | __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath | 930 | __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath |
@@ -914,7 +939,7 @@ extern "C" HRESULT CacheBundleToCleanRoom( | |||
914 | 939 | ||
915 | wzExecutableName = PathFile(sczSourcePath); | 940 | wzExecutableName = PathFile(sczSourcePath); |
916 | 941 | ||
917 | hr = CopyEngineToWorkingFolder(pCache, sczSourcePath, BUNDLE_CLEAN_ROOM_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczCleanRoomBundlePath); | 942 | hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_CLEAN_ROOM_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczCleanRoomBundlePath); |
918 | ExitOnFailure(hr, "Failed to cache bundle to clean room."); | 943 | ExitOnFailure(hr, "Failed to cache bundle to clean room."); |
919 | 944 | ||
920 | LExit: | 945 | LExit: |
@@ -924,6 +949,7 @@ LExit: | |||
924 | } | 949 | } |
925 | 950 | ||
926 | extern "C" HRESULT CacheBundleToWorkingDirectory( | 951 | extern "C" HRESULT CacheBundleToWorkingDirectory( |
952 | __in BOOL fElevated, | ||
927 | __in BURN_CACHE* pCache, | 953 | __in BURN_CACHE* pCache, |
928 | __in_z LPCWSTR wzExecutableName, | 954 | __in_z LPCWSTR wzExecutableName, |
929 | __in BURN_SECTION* pSection, | 955 | __in BURN_SECTION* pSection, |
@@ -948,7 +974,7 @@ extern "C" HRESULT CacheBundleToWorkingDirectory( | |||
948 | } | 974 | } |
949 | else // otherwise, carry on putting the bundle in the working folder. | 975 | else // otherwise, carry on putting the bundle in the working folder. |
950 | { | 976 | { |
951 | hr = CopyEngineToWorkingFolder(pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath); | 977 | hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath); |
952 | ExitOnFailure(hr, "Failed to copy engine to working folder."); | 978 | ExitOnFailure(hr, "Failed to copy engine to working folder."); |
953 | } | 979 | } |
954 | 980 | ||
@@ -2099,6 +2125,7 @@ LExit: | |||
2099 | 2125 | ||
2100 | 2126 | ||
2101 | static HRESULT CopyEngineToWorkingFolder( | 2127 | static HRESULT CopyEngineToWorkingFolder( |
2128 | __in BOOL fElevated, | ||
2102 | __in BURN_CACHE* pCache, | 2129 | __in BURN_CACHE* pCache, |
2103 | __in_z LPCWSTR wzSourcePath, | 2130 | __in_z LPCWSTR wzSourcePath, |
2104 | __in_z LPCWSTR wzWorkingFolderName, | 2131 | __in_z LPCWSTR wzWorkingFolderName, |
@@ -2115,7 +2142,7 @@ static HRESULT CopyEngineToWorkingFolder( | |||
2115 | LPWSTR sczPayloadSourcePath = NULL; | 2142 | LPWSTR sczPayloadSourcePath = NULL; |
2116 | LPWSTR sczPayloadTargetPath = NULL; | 2143 | LPWSTR sczPayloadTargetPath = NULL; |
2117 | 2144 | ||
2118 | hr = CacheEnsureBaseWorkingFolder(pCache, &sczWorkingFolder); | 2145 | hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder); |
2119 | ExitOnFailure(hr, "Failed to create working path to copy engine."); | 2146 | ExitOnFailure(hr, "Failed to create working path to copy engine."); |
2120 | 2147 | ||
2121 | hr = PathConcatRelativeToFullyQualifiedBase(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory); | 2148 | hr = PathConcatRelativeToFullyQualifiedBase(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory); |
diff --git a/src/burn/engine/cache.h b/src/burn/engine/cache.h index cc28166e..1ad5d96c 100644 --- a/src/burn/engine/cache.h +++ b/src/burn/engine/cache.h | |||
@@ -97,6 +97,7 @@ HRESULT CacheEnsureAcquisitionFolder( | |||
97 | __in BURN_CACHE* pCache | 97 | __in BURN_CACHE* pCache |
98 | ); | 98 | ); |
99 | HRESULT CacheEnsureBaseWorkingFolder( | 99 | HRESULT CacheEnsureBaseWorkingFolder( |
100 | __in BOOL fElevated, | ||
100 | __in BURN_CACHE* pCache, | 101 | __in BURN_CACHE* pCache, |
101 | __deref_out_z_opt LPWSTR* psczBaseWorkingFolder | 102 | __deref_out_z_opt LPWSTR* psczBaseWorkingFolder |
102 | ); | 103 | ); |
@@ -172,11 +173,13 @@ HRESULT CachePreparePackage( | |||
172 | __in BURN_PACKAGE* pPackage | 173 | __in BURN_PACKAGE* pPackage |
173 | ); | 174 | ); |
174 | HRESULT CacheBundleToCleanRoom( | 175 | HRESULT CacheBundleToCleanRoom( |
176 | __in BOOL fElevated, | ||
175 | __in BURN_CACHE* pCache, | 177 | __in BURN_CACHE* pCache, |
176 | __in BURN_SECTION* pSection, | 178 | __in BURN_SECTION* pSection, |
177 | __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath | 179 | __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath |
178 | ); | 180 | ); |
179 | HRESULT CacheBundleToWorkingDirectory( | 181 | HRESULT CacheBundleToWorkingDirectory( |
182 | __in BOOL fElvated, | ||
180 | __in BURN_CACHE* pCache, | 183 | __in BURN_CACHE* pCache, |
181 | __in_z LPCWSTR wzExecutableName, | 184 | __in_z LPCWSTR wzExecutableName, |
182 | __in BURN_SECTION* pSection, | 185 | __in BURN_SECTION* pSection, |
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 8903b5b2..2d8a76dd 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp | |||
@@ -182,7 +182,7 @@ extern "C" HRESULT CoreInitialize( | |||
182 | if (BURN_MODE_NORMAL == pEngineState->internalCommand.mode || BURN_MODE_EMBEDDED == pEngineState->internalCommand.mode) | 182 | if (BURN_MODE_NORMAL == pEngineState->internalCommand.mode || BURN_MODE_EMBEDDED == pEngineState->internalCommand.mode) |
183 | { | 183 | { |
184 | // Extract all UX payloads to working folder. | 184 | // Extract all UX payloads to working folder. |
185 | hr = UserExperienceEnsureWorkingFolder(&pEngineState->cache, &pEngineState->userExperience.sczTempDirectory); | 185 | hr = UserExperienceEnsureWorkingFolder(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, &pEngineState->userExperience.sczTempDirectory); |
186 | ExitOnFailure(hr, "Failed to get unique temporary folder for bootstrapper application."); | 186 | ExitOnFailure(hr, "Failed to get unique temporary folder for bootstrapper application."); |
187 | 187 | ||
188 | hr = PayloadExtractUXContainer(&pEngineState->userExperience.payloads, &containerContext, pEngineState->userExperience.sczTempDirectory); | 188 | hr = PayloadExtractUXContainer(&pEngineState->userExperience.payloads, &containerContext, pEngineState->userExperience.sczTempDirectory); |
@@ -227,7 +227,7 @@ extern "C" HRESULT CoreInitializeConstants( | |||
227 | hr = StrAllocString(&pRegistration->sczBundlePackageAncestors, pRegistration->sczId, 0); | 227 | hr = StrAllocString(&pRegistration->sczBundlePackageAncestors, pRegistration->sczId, 0); |
228 | ExitOnFailure(hr, "Failed to copy self to bundle package ancestors."); | 228 | ExitOnFailure(hr, "Failed to copy self to bundle package ancestors."); |
229 | } | 229 | } |
230 | 230 | ||
231 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) | 231 | for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) |
232 | { | 232 | { |
233 | BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; | 233 | BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; |
@@ -605,7 +605,7 @@ extern "C" HRESULT CoreElevate( | |||
605 | // If the elevated companion pipe isn't created yet, let's make that happen. | 605 | // If the elevated companion pipe isn't created yet, let's make that happen. |
606 | if (!pEngineState->sczBundleEngineWorkingPath) | 606 | if (!pEngineState->sczBundleEngineWorkingPath) |
607 | { | 607 | { |
608 | hr = CacheBundleToWorkingDirectory(&pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath); | 608 | hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath); |
609 | ExitOnFailure(hr, "Failed to cache engine to working directory."); | 609 | ExitOnFailure(hr, "Failed to cache engine to working directory."); |
610 | } | 610 | } |
611 | 611 | ||
@@ -714,7 +714,7 @@ extern "C" HRESULT CoreApply( | |||
714 | // Ensure the engine is cached to the working path. | 714 | // Ensure the engine is cached to the working path. |
715 | if (!pEngineState->sczBundleEngineWorkingPath) | 715 | if (!pEngineState->sczBundleEngineWorkingPath) |
716 | { | 716 | { |
717 | hr = CacheBundleToWorkingDirectory(&pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath); | 717 | hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath); |
718 | ExitOnFailure(hr, "Failed to cache engine to working directory."); | 718 | ExitOnFailure(hr, "Failed to cache engine to working directory."); |
719 | } | 719 | } |
720 | 720 | ||
@@ -2285,7 +2285,7 @@ static HRESULT DetectPackage( | |||
2285 | { | 2285 | { |
2286 | HRESULT hr = S_OK; | 2286 | HRESULT hr = S_OK; |
2287 | BOOL fBegan = FALSE; | 2287 | BOOL fBegan = FALSE; |
2288 | 2288 | ||
2289 | fBegan = TRUE; | 2289 | fBegan = TRUE; |
2290 | hr = UserExperienceOnDetectPackageBegin(&pEngineState->userExperience, pPackage->sczId); | 2290 | hr = UserExperienceOnDetectPackageBegin(&pEngineState->userExperience, pPackage->sczId); |
2291 | ExitOnRootFailure(hr, "BA aborted detect package begin."); | 2291 | ExitOnRootFailure(hr, "BA aborted detect package begin."); |
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index b093ec9b..79e6aab4 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp | |||
@@ -525,7 +525,7 @@ static HRESULT RunUntrusted( | |||
525 | } | 525 | } |
526 | else | 526 | else |
527 | { | 527 | { |
528 | hr = CacheBundleToCleanRoom(&pEngineState->cache, &pEngineState->section, &sczCachedCleanRoomBundlePath); | 528 | hr = CacheBundleToCleanRoom(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, &pEngineState->section, &sczCachedCleanRoomBundlePath); |
529 | ExitOnFailure(hr, "Failed to cache to clean room."); | 529 | ExitOnFailure(hr, "Failed to cache to clean room."); |
530 | 530 | ||
531 | wzCleanRoomBundlePath = sczCachedCleanRoomBundlePath; | 531 | wzCleanRoomBundlePath = sczCachedCleanRoomBundlePath; |
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 372ca901..65414a92 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp | |||
@@ -169,6 +169,7 @@ extern "C" HRESULT UserExperienceUnload( | |||
169 | } | 169 | } |
170 | 170 | ||
171 | extern "C" HRESULT UserExperienceEnsureWorkingFolder( | 171 | extern "C" HRESULT UserExperienceEnsureWorkingFolder( |
172 | __in BOOL fElevated, | ||
172 | __in BURN_CACHE* pCache, | 173 | __in BURN_CACHE* pCache, |
173 | __deref_out_z LPWSTR* psczUserExperienceWorkingFolder | 174 | __deref_out_z LPWSTR* psczUserExperienceWorkingFolder |
174 | ) | 175 | ) |
@@ -176,7 +177,7 @@ extern "C" HRESULT UserExperienceEnsureWorkingFolder( | |||
176 | HRESULT hr = S_OK; | 177 | HRESULT hr = S_OK; |
177 | LPWSTR sczWorkingFolder = NULL; | 178 | LPWSTR sczWorkingFolder = NULL; |
178 | 179 | ||
179 | hr = CacheEnsureBaseWorkingFolder(pCache, &sczWorkingFolder); | 180 | hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder); |
180 | ExitOnFailure(hr, "Failed to create working folder."); | 181 | ExitOnFailure(hr, "Failed to create working folder."); |
181 | 182 | ||
182 | hr = StrAllocFormatted(psczUserExperienceWorkingFolder, L"%ls%ls\\", sczWorkingFolder, L".ba"); | 183 | hr = StrAllocFormatted(psczUserExperienceWorkingFolder, L"%ls%ls\\", sczWorkingFolder, L".ba"); |
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 4f15c5d7..6256b8be 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h | |||
@@ -64,6 +64,7 @@ HRESULT UserExperienceUnload( | |||
64 | __in BOOL fReload | 64 | __in BOOL fReload |
65 | ); | 65 | ); |
66 | HRESULT UserExperienceEnsureWorkingFolder( | 66 | HRESULT UserExperienceEnsureWorkingFolder( |
67 | __in BOOL fElevated, | ||
67 | __in BURN_CACHE* pCache, | 68 | __in BURN_CACHE* pCache, |
68 | __deref_out_z LPWSTR* psczUserExperienceWorkingFolder | 69 | __deref_out_z LPWSTR* psczUserExperienceWorkingFolder |
69 | ); | 70 | ); |
diff --git a/src/dtf/SfxCA/SfxUtil.cpp b/src/dtf/SfxCA/SfxUtil.cpp index 2e6b0555..32dc6e04 100644 --- a/src/dtf/SfxCA/SfxUtil.cpp +++ b/src/dtf/SfxCA/SfxUtil.cpp | |||
@@ -164,38 +164,18 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule, | |||
164 | StringCchCopy(szTempDir, cchTempDirBuf, szModule); | 164 | StringCchCopy(szTempDir, cchTempDirBuf, szModule); |
165 | StringCchCat(szTempDir, cchTempDirBuf, L"-"); | 165 | StringCchCat(szTempDir, cchTempDirBuf, L"-"); |
166 | 166 | ||
167 | BOOL fCreatedDirectory = FALSE; | ||
167 | DWORD cchTempDir = (DWORD) wcslen(szTempDir); | 168 | DWORD cchTempDir = (DWORD) wcslen(szTempDir); |
168 | for (int i = 0; DirectoryExists(szTempDir); i++) | 169 | for (int i = 0; i < 10000 && !fCreatedDirectory; i++) |
169 | { | 170 | { |
170 | swprintf_s(szTempDir + cchTempDir, cchTempDirBuf - cchTempDir, L"%d", i); | 171 | swprintf_s(szTempDir + cchTempDir, cchTempDirBuf - cchTempDir, L"%d", i); |
172 | fCreatedDirectory = ::CreateDirectory(szTempDir, NULL); | ||
171 | } | 173 | } |
172 | 174 | ||
173 | if (!CreateDirectory(szTempDir, NULL)) | 175 | if (!fCreatedDirectory) |
174 | { | 176 | { |
175 | cchCopied = GetTempPath(cchTempDirBuf, szTempDir); | 177 | Log(hSession, L"Failed to create temp directory. Error code %d", ::GetLastError()); |
176 | if (cchCopied == 0 || cchCopied >= cchTempDirBuf) | 178 | return false; |
177 | { | ||
178 | Log(hSession, L"Failed to get temp directory. Error code %d", GetLastError()); | ||
179 | return false; | ||
180 | } | ||
181 | |||
182 | wchar_t* szModuleName = wcsrchr(szModule, L'\\'); | ||
183 | if (szModuleName == NULL) szModuleName = szModule; | ||
184 | else szModuleName = szModuleName + 1; | ||
185 | StringCchCat(szTempDir, cchTempDirBuf, szModuleName); | ||
186 | StringCchCat(szTempDir, cchTempDirBuf, L"-"); | ||
187 | |||
188 | cchTempDir = (DWORD) wcslen(szTempDir); | ||
189 | for (int i = 0; DirectoryExists(szTempDir); i++) | ||
190 | { | ||
191 | swprintf_s(szTempDir + cchTempDir, cchTempDirBuf - cchTempDir, L"%d", i); | ||
192 | } | ||
193 | |||
194 | if (!CreateDirectory(szTempDir, NULL)) | ||
195 | { | ||
196 | Log(hSession, L"Failed to create temp directory. Error code %d", GetLastError()); | ||
197 | return false; | ||
198 | } | ||
199 | } | 179 | } |
200 | 180 | ||
201 | Log(hSession, L"Extracting custom action to temporary directory: %s\\", szTempDir); | 181 | Log(hSession, L"Extracting custom action to temporary directory: %s\\", szTempDir); |