From 13c4becf524dbd12b92f099320726aa0b59f3bbc Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sun, 11 Apr 2021 12:22:57 -0700 Subject: Add Condition to RemoveFoldersEx --- src/ca/RemoveFoldersEx.cpp | 62 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src/ca') diff --git a/src/ca/RemoveFoldersEx.cpp b/src/ca/RemoveFoldersEx.cpp index ce64c2c2..cbc7f4bb 100644 --- a/src/ca/RemoveFoldersEx.cpp +++ b/src/ca/RemoveFoldersEx.cpp @@ -2,8 +2,11 @@ #include "precomp.h" -LPCWSTR vcsRemoveFolderExQuery = L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode` FROM `Wix4RemoveFolderEx`"; -enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, feqMode }; +LPCWSTR vcsRemoveFolderExQuery = + L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode`, `WixRemoveFolderEx`.`Condition`, `Component`.`Attributes`" + L"FROM `Wix4RemoveFolderEx``,`Component` " + L"WHERE `Wix4RemoveFolderEx`.`Component_`=`Component`.`Component`"; +enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, rfqMode, rfqCondition, rfqComponentAttributes }; static HRESULT RecursePath( __in_z LPCWSTR wzPath, @@ -11,6 +14,7 @@ static HRESULT RecursePath( __in_z LPCWSTR wzComponent, __in_z LPCWSTR wzProperty, __in int iMode, + __in BOOL fDisableWow64Redirection, __inout DWORD* pdwCounter, __inout MSIHANDLE* phTable, __inout MSIHANDLE* phColumns @@ -24,6 +28,12 @@ static HRESULT RecursePath( WIN32_FIND_DATAW wfd; LPWSTR sczNext = NULL; + if (fDisableWow64Redirection) + { + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); + } + // First recurse down to all the child directories. hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath); @@ -34,7 +44,7 @@ static HRESULT RecursePath( er = ::GetLastError(); if (ERROR_PATH_NOT_FOUND == er) { - WcaLog(LOGMSG_STANDARD, "Search path not found: %ls", sczSearch); + WcaLog(LOGMSG_STANDARD, "Search path not found: %ls; skipping", sczSearch); ExitFunction1(hr = S_FALSE); } else @@ -55,7 +65,8 @@ static HRESULT RecursePath( hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); ExitOnFailure(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); - hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, pdwCounter, phTable, phColumns); + // Don't re-disable redirection; if it was necessary, we've already done it. + hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, FALSE, pdwCounter, phTable, phColumns); ExitOnFailure(hr, "Failed to recurse path: %S", sczNext); } while (::FindNextFileW(hFind, &wfd)); @@ -81,10 +92,10 @@ static HRESULT RecursePath( // Add the row to remove any files and another row to remove the folder. hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); - ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %S under path:", wzId, wzPath); + ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); - ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %S under path: %S", wzId, wzPath); + ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); LExit: if (INVALID_HANDLE_VALUE != hFind) @@ -92,6 +103,11 @@ LExit: ::FindClose(hFind); } + if (fDisableWow64Redirection) + { + WcaRevertWow64FSRedirection(); + } + ReleaseStr(sczNext); ReleaseStr(sczProperty); ReleaseStr(sczSearch); @@ -110,9 +126,12 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( LPWSTR sczId = NULL; LPWSTR sczComponent = NULL; LPWSTR sczProperty = NULL; + LPWSTR sczCondition = NULL; LPWSTR sczPath = NULL; LPWSTR sczExpandedPath = NULL; int iMode = 0; + int iComponentAttributes; + BOOL f64BitComponent = FALSE; DWORD dwCounter = 0; DWORD_PTR cchLen = 0; MSIHANDLE hTable = NULL; @@ -121,6 +140,8 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( hr = WcaInitialize(hInstall, "WixRemoveFoldersEx"); ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx."); + WcaInitializeWow64(); + // anything to do? if (S_OK != WcaTableExists(L"Wix4RemoveFolderEx")) { @@ -137,18 +158,40 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( hr = WcaGetRecordString(hRec, rfqId, &sczId); ExitOnFailure(hr, "Failed to get remove folder identity."); + hr = WcaGetRecordString(hRec, rfqCondition, &sczCondition); + ExitOnFailure(hr, "Failed to get remove folder condition."); + + if (sczCondition && *sczCondition) + { + MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); + if (MSICONDITION_TRUE == condition) + { + WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); + } + else + { + WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); + continue; + } + } + hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent); ExitOnFailure(hr, "Failed to get remove folder component."); hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty); ExitOnFailure(hr, "Failed to get remove folder property."); - hr = WcaGetRecordInteger(hRec, feqMode, &iMode); + hr = WcaGetRecordInteger(hRec, rfqMode, &iMode); ExitOnFailure(hr, "Failed to get remove folder mode"); hr = WcaGetProperty(sczProperty, &sczPath); ExitOnFailure(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId); + hr = WcaGetRecordInteger(hRec, rfqComponentAttributes, &iComponentAttributes); + ExitOnFailure(hr, "failed to get component attributes for row: %ls", sczId); + + f64BitComponent = iComponentAttributes & msidbComponentAttributes64bit; + // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast(&cchLen)); @@ -164,7 +207,7 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath); WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId); - hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, &dwCounter, &hTable, &hColumns); + hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, f64BitComponent, &dwCounter, &hTable, &hColumns); ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId); } @@ -176,6 +219,8 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( ExitOnFailure(hr, "Failure occured while processing Wix4RemoveFolderEx table"); LExit: + WcaFinalizeWow64(); + if (hColumns) { ::MsiCloseHandle(hColumns); @@ -190,6 +235,7 @@ LExit: ReleaseStr(sczPath); ReleaseStr(sczProperty); ReleaseStr(sczComponent); + ReleaseStr(sczCondition); ReleaseStr(sczId); DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; -- cgit v1.2.3-55-g6feb