diff --git a/src/DTF/Tools/SfxCA/SfxUtil.cpp b/src/DTF/Tools/SfxCA/SfxUtil.cpp index 1bf2c5b28..32dc6e04a 100644 --- a/src/DTF/Tools/SfxCA/SfxUtil.cpp +++ b/src/DTF/Tools/SfxCA/SfxUtil.cpp @@ -93,7 +93,9 @@ bool DeleteDirectory(const wchar_t* szDir) StringCchCopy(szPath + cchDir + 1, cchPathBuf - (cchDir + 1), fd.cFileName); if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - if (wcscmp(fd.cFileName, L".") != 0 && wcscmp(fd.cFileName, L"..") != 0) + if (wcscmp(fd.cFileName, L".") != 0 + && wcscmp(fd.cFileName, L"..") != 0 + && ((fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0)) { DeleteDirectory(szPath); } @@ -162,38 +164,18 @@ bool ExtractToTempDirectory(__in MSIHANDLE hSession, __in HMODULE hModule, StringCchCopy(szTempDir, cchTempDirBuf, szModule); StringCchCat(szTempDir, cchTempDirBuf, L"-"); + BOOL fCreatedDirectory = FALSE; DWORD cchTempDir = (DWORD) wcslen(szTempDir); - for (int i = 0; DirectoryExists(szTempDir); i++) + for (int i = 0; i < 10000 && !fCreatedDirectory; i++) { swprintf_s(szTempDir + cchTempDir, cchTempDirBuf - cchTempDir, L"%d", i); + fCreatedDirectory = ::CreateDirectory(szTempDir, NULL); } - if (!CreateDirectory(szTempDir, NULL)) + if (!fCreatedDirectory) { - cchCopied = GetTempPath(cchTempDirBuf, szTempDir); - if (cchCopied == 0 || cchCopied >= cchTempDirBuf) - { - Log(hSession, L"Failed to get temp directory. Error code %d", GetLastError()); - return false; - } - - wchar_t* szModuleName = wcsrchr(szModule, L'\\'); - if (szModuleName == NULL) szModuleName = szModule; - else szModuleName = szModuleName + 1; - StringCchCat(szTempDir, cchTempDirBuf, szModuleName); - StringCchCat(szTempDir, cchTempDirBuf, L"-"); - - cchTempDir = (DWORD) wcslen(szTempDir); - for (int i = 0; DirectoryExists(szTempDir); i++) - { - swprintf_s(szTempDir + cchTempDir, cchTempDirBuf - cchTempDir, L"%d", i); - } - - if (!CreateDirectory(szTempDir, NULL)) - { - Log(hSession, L"Failed to create temp directory. Error code %d", GetLastError()); - return false; - } + Log(hSession, L"Failed to create temp directory. Error code %d", ::GetLastError()); + return false; } Log(hSession, L"Extracting custom action to temporary directory: %s\\", szTempDir); diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 72a44cf23..4d4a09be8 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp @@ -14,6 +14,7 @@ static BOOL vfInitializedCache = FALSE; static BOOL vfRunningFromCache = FALSE; static LPWSTR vsczSourceProcessPath = NULL; static LPWSTR vsczWorkingFolder = NULL; +static BOOL vfWorkingFolderElevated = FALSE; static LPWSTR vsczDefaultUserPackageCache = NULL; static LPWSTR vsczDefaultMachinePackageCache = NULL; static LPWSTR vsczCurrentMachinePackageCache = NULL; @@ -21,7 +22,8 @@ static LPWSTR vsczRegistrationId = NULL; static HRESULT CalculateWorkingFolder( __in_z LPCWSTR wzBundleId, - __deref_out_z LPWSTR* psczWorkingFolder + __deref_out_z LPWSTR* psczWorkingFolder, + __out_opt BOOL* pfWorkingFolderElevated ); static HRESULT GetLastUsedSourceFolder( __in BURN_VARIABLES* pVariables, @@ -217,11 +219,29 @@ extern "C" HRESULT CacheEnsureWorkingFolder( { HRESULT hr = S_OK; LPWSTR sczWorkingFolder = NULL; + BOOL fElevatedWorkingFolder = FALSE; + PSECURITY_DESCRIPTOR psd = NULL; + LPSECURITY_ATTRIBUTES pWorkingFolderAcl = NULL; - hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder); + hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder, &fElevatedWorkingFolder); ExitOnFailure(hr, "Failed to calculate working folder to ensure it exists."); - hr = DirEnsureExists(sczWorkingFolder, NULL); + // If elevated, allocate the pWorkingFolderAcl to protect the working folder to only Admins and SYSTEM. + if (fElevatedWorkingFolder) + { + LPCWSTR wzSddl = L"D:PAI(A;;FA;;;BA)(A;OICIIO;GA;;;BA)(A;;FA;;;SY)(A;OICIIO;GA;;;SY)"; + if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(wzSddl, SDDL_REVISION_1, &psd, NULL)) + { + ExitWithLastError(hr, "Failed to create the security descriptor for the working folder."); + } + + pWorkingFolderAcl = reinterpret_cast(MemAlloc(sizeof(SECURITY_ATTRIBUTES), TRUE)); + pWorkingFolderAcl->nLength = sizeof(SECURITY_ATTRIBUTES); + pWorkingFolderAcl->lpSecurityDescriptor = psd; + pWorkingFolderAcl->bInheritHandle = FALSE; + } + + hr = DirEnsureExists(sczWorkingFolder, pWorkingFolderAcl); ExitOnFailure(hr, "Failed create working folder."); // Best effort to ensure our working folder is not encrypted. @@ -234,6 +254,11 @@ extern "C" HRESULT CacheEnsureWorkingFolder( } LExit: + ReleaseMem(pWorkingFolderAcl); + if (psd) + { + ::LocalFree(psd); + } ReleaseStr(sczWorkingFolder); return hr; @@ -259,7 +284,7 @@ extern "C" HRESULT CacheCalculateBundleWorkingPath( } else // Otherwise, use the real working folder. { - hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder); + hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder, NULL); ExitOnFailure(hr, "Failed to get working folder for bundle."); hr = StrAllocFormatted(psczWorkingPath, L"%ls%ls\\%ls", sczWorkingFolder, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName); @@ -280,7 +305,7 @@ extern "C" HRESULT CacheCalculateBundleLayoutWorkingPath( HRESULT hr = S_OK; LPWSTR sczWorkingFolder = NULL; - hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath); + hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath, NULL); ExitOnFailure(hr, "Failed to get working folder for bundle layout."); hr = StrAllocConcat(psczWorkingPath, wzBundleId, 0); @@ -300,7 +325,7 @@ extern "C" HRESULT CacheCalculatePayloadWorkingPath( { HRESULT hr = S_OK; - hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath); + hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath, NULL); ExitOnFailure(hr, "Failed to get working folder for payload."); hr = StrAllocConcat(psczWorkingPath, pPayload->sczKey, 0); @@ -318,7 +343,7 @@ extern "C" HRESULT CacheCalculateContainerWorkingPath( { HRESULT hr = S_OK; - hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath); + hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath, NULL); ExitOnFailure(hr, "Failed to get working folder for container."); hr = StrAllocConcat(psczWorkingPath, pContainer->sczHash, 0); @@ -943,7 +968,7 @@ extern "C" HRESULT CacheRemoveWorkingFolder( if (vfInitializedCache) { - hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder); + hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder, NULL); ExitOnFailure(hr, "Failed to calculate the working folder to remove it."); // Try to clean out everything in the working folder. @@ -1057,7 +1082,7 @@ extern "C" void CacheCleanup( if (!fPerMachine) { - hr = CalculateWorkingFolder(wzBundleId, &sczFolder); + hr = CalculateWorkingFolder(wzBundleId, &sczFolder, NULL); if (SUCCEEDED(hr)) { hr = PathConcat(sczFolder, L"*.*", &sczFiles); @@ -1122,7 +1147,8 @@ extern "C" void CacheUninitialize() static HRESULT CalculateWorkingFolder( __in_z LPCWSTR /*wzBundleId*/, - __deref_out_z LPWSTR* psczWorkingFolder + __deref_out_z LPWSTR* psczWorkingFolder, + __out_opt BOOL* pfWorkingFolderElevated ) { HRESULT hr = S_OK; @@ -1166,11 +1192,18 @@ static HRESULT CalculateWorkingFolder( hr = StrAllocFormatted(&vsczWorkingFolder, L"%ls%ls\\", wzTempPath, wzGuid); ExitOnFailure(hr, "Failed to append bundle id on to temp path for working folder."); + + vfWorkingFolderElevated = fElevated; } hr = StrAllocString(psczWorkingFolder, vsczWorkingFolder, 0); ExitOnFailure(hr, "Failed to copy working folder path."); + if (pfWorkingFolderElevated) + { + *pfWorkingFolderElevated = vfWorkingFolderElevated; + } + LExit: return hr; } diff --git a/src/tools/light/mergemod.cub b/src/tools/light/mergemod.cub index def6dd1af..2042a99e4 100644 Binary files a/src/tools/light/mergemod.cub and b/src/tools/light/mergemod.cub differ