diff options
| -rw-r--r-- | src/ca/RemoveFoldersEx.cpp | 62 | ||||
| -rw-r--r-- | src/test/WixToolsetTest.Util/UtilExtensionFixture.cs | 4 | ||||
| -rw-r--r-- | src/wixext/Symbols/WixRemoveFolderExSymbol.cs | 21 | ||||
| -rw-r--r-- | src/wixext/UtilCompiler.cs | 28 | ||||
| -rw-r--r-- | src/wixext/UtilTableDefinitions.cs | 1 |
5 files changed, 87 insertions, 29 deletions
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 @@ | |||
| 2 | 2 | ||
| 3 | #include "precomp.h" | 3 | #include "precomp.h" |
| 4 | 4 | ||
| 5 | LPCWSTR vcsRemoveFolderExQuery = L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode` FROM `Wix4RemoveFolderEx`"; | 5 | LPCWSTR vcsRemoveFolderExQuery = |
| 6 | enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, feqMode }; | 6 | L"SELECT `Wix4RemoveFolderEx`, `Component_`, `Property`, `InstallMode`, `WixRemoveFolderEx`.`Condition`, `Component`.`Attributes`" |
| 7 | L"FROM `Wix4RemoveFolderEx``,`Component` " | ||
| 8 | L"WHERE `Wix4RemoveFolderEx`.`Component_`=`Component`.`Component`"; | ||
| 9 | enum eRemoveFolderExQuery { rfqId = 1, rfqComponent, rfqProperty, rfqMode, rfqCondition, rfqComponentAttributes }; | ||
| 7 | 10 | ||
| 8 | static HRESULT RecursePath( | 11 | static HRESULT RecursePath( |
| 9 | __in_z LPCWSTR wzPath, | 12 | __in_z LPCWSTR wzPath, |
| @@ -11,6 +14,7 @@ static HRESULT RecursePath( | |||
| 11 | __in_z LPCWSTR wzComponent, | 14 | __in_z LPCWSTR wzComponent, |
| 12 | __in_z LPCWSTR wzProperty, | 15 | __in_z LPCWSTR wzProperty, |
| 13 | __in int iMode, | 16 | __in int iMode, |
| 17 | __in BOOL fDisableWow64Redirection, | ||
| 14 | __inout DWORD* pdwCounter, | 18 | __inout DWORD* pdwCounter, |
| 15 | __inout MSIHANDLE* phTable, | 19 | __inout MSIHANDLE* phTable, |
| 16 | __inout MSIHANDLE* phColumns | 20 | __inout MSIHANDLE* phColumns |
| @@ -24,6 +28,12 @@ static HRESULT RecursePath( | |||
| 24 | WIN32_FIND_DATAW wfd; | 28 | WIN32_FIND_DATAW wfd; |
| 25 | LPWSTR sczNext = NULL; | 29 | LPWSTR sczNext = NULL; |
| 26 | 30 | ||
| 31 | if (fDisableWow64Redirection) | ||
| 32 | { | ||
| 33 | hr = WcaDisableWow64FSRedirection(); | ||
| 34 | ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API."); | ||
| 35 | } | ||
| 36 | |||
| 27 | // First recurse down to all the child directories. | 37 | // First recurse down to all the child directories. |
| 28 | hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); | 38 | hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); |
| 29 | ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath); | 39 | ExitOnFailure(hr, "Failed to allocate file search string in path: %S", wzPath); |
| @@ -34,7 +44,7 @@ static HRESULT RecursePath( | |||
| 34 | er = ::GetLastError(); | 44 | er = ::GetLastError(); |
| 35 | if (ERROR_PATH_NOT_FOUND == er) | 45 | if (ERROR_PATH_NOT_FOUND == er) |
| 36 | { | 46 | { |
| 37 | WcaLog(LOGMSG_STANDARD, "Search path not found: %ls", sczSearch); | 47 | WcaLog(LOGMSG_STANDARD, "Search path not found: %ls; skipping", sczSearch); |
| 38 | ExitFunction1(hr = S_FALSE); | 48 | ExitFunction1(hr = S_FALSE); |
| 39 | } | 49 | } |
| 40 | else | 50 | else |
| @@ -55,7 +65,8 @@ static HRESULT RecursePath( | |||
| 55 | hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); | 65 | hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); |
| 56 | ExitOnFailure(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); | 66 | ExitOnFailure(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); |
| 57 | 67 | ||
| 58 | hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, pdwCounter, phTable, phColumns); | 68 | // Don't re-disable redirection; if it was necessary, we've already done it. |
| 69 | hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, FALSE, pdwCounter, phTable, phColumns); | ||
| 59 | ExitOnFailure(hr, "Failed to recurse path: %S", sczNext); | 70 | ExitOnFailure(hr, "Failed to recurse path: %S", sczNext); |
| 60 | } while (::FindNextFileW(hFind, &wfd)); | 71 | } while (::FindNextFileW(hFind, &wfd)); |
| 61 | 72 | ||
| @@ -81,10 +92,10 @@ static HRESULT RecursePath( | |||
| 81 | 92 | ||
| 82 | // Add the row to remove any files and another row to remove the folder. | 93 | // Add the row to remove any files and another row to remove the folder. |
| 83 | hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); | 94 | hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); |
| 84 | ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %S under path:", wzId, wzPath); | 95 | ExitOnFailure(hr, "Failed to add row to remove all files for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); |
| 85 | 96 | ||
| 86 | hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); | 97 | hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); |
| 87 | ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %S under path: %S", wzId, wzPath); | 98 | ExitOnFailure(hr, "Failed to add row to remove folder for Wix4RemoveFolderEx row: %ls under path: %ls", wzId, wzPath); |
| 88 | 99 | ||
| 89 | LExit: | 100 | LExit: |
| 90 | if (INVALID_HANDLE_VALUE != hFind) | 101 | if (INVALID_HANDLE_VALUE != hFind) |
| @@ -92,6 +103,11 @@ LExit: | |||
| 92 | ::FindClose(hFind); | 103 | ::FindClose(hFind); |
| 93 | } | 104 | } |
| 94 | 105 | ||
| 106 | if (fDisableWow64Redirection) | ||
| 107 | { | ||
| 108 | WcaRevertWow64FSRedirection(); | ||
| 109 | } | ||
| 110 | |||
| 95 | ReleaseStr(sczNext); | 111 | ReleaseStr(sczNext); |
| 96 | ReleaseStr(sczProperty); | 112 | ReleaseStr(sczProperty); |
| 97 | ReleaseStr(sczSearch); | 113 | ReleaseStr(sczSearch); |
| @@ -110,9 +126,12 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( | |||
| 110 | LPWSTR sczId = NULL; | 126 | LPWSTR sczId = NULL; |
| 111 | LPWSTR sczComponent = NULL; | 127 | LPWSTR sczComponent = NULL; |
| 112 | LPWSTR sczProperty = NULL; | 128 | LPWSTR sczProperty = NULL; |
| 129 | LPWSTR sczCondition = NULL; | ||
| 113 | LPWSTR sczPath = NULL; | 130 | LPWSTR sczPath = NULL; |
| 114 | LPWSTR sczExpandedPath = NULL; | 131 | LPWSTR sczExpandedPath = NULL; |
| 115 | int iMode = 0; | 132 | int iMode = 0; |
| 133 | int iComponentAttributes; | ||
| 134 | BOOL f64BitComponent = FALSE; | ||
| 116 | DWORD dwCounter = 0; | 135 | DWORD dwCounter = 0; |
| 117 | DWORD_PTR cchLen = 0; | 136 | DWORD_PTR cchLen = 0; |
| 118 | MSIHANDLE hTable = NULL; | 137 | MSIHANDLE hTable = NULL; |
| @@ -121,6 +140,8 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( | |||
| 121 | hr = WcaInitialize(hInstall, "WixRemoveFoldersEx"); | 140 | hr = WcaInitialize(hInstall, "WixRemoveFoldersEx"); |
| 122 | ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx."); | 141 | ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx."); |
| 123 | 142 | ||
| 143 | WcaInitializeWow64(); | ||
| 144 | |||
| 124 | // anything to do? | 145 | // anything to do? |
| 125 | if (S_OK != WcaTableExists(L"Wix4RemoveFolderEx")) | 146 | if (S_OK != WcaTableExists(L"Wix4RemoveFolderEx")) |
| 126 | { | 147 | { |
| @@ -137,18 +158,40 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( | |||
| 137 | hr = WcaGetRecordString(hRec, rfqId, &sczId); | 158 | hr = WcaGetRecordString(hRec, rfqId, &sczId); |
| 138 | ExitOnFailure(hr, "Failed to get remove folder identity."); | 159 | ExitOnFailure(hr, "Failed to get remove folder identity."); |
| 139 | 160 | ||
| 161 | hr = WcaGetRecordString(hRec, rfqCondition, &sczCondition); | ||
| 162 | ExitOnFailure(hr, "Failed to get remove folder condition."); | ||
| 163 | |||
| 164 | if (sczCondition && *sczCondition) | ||
| 165 | { | ||
| 166 | MSICONDITION condition = ::MsiEvaluateConditionW(hInstall, sczCondition); | ||
| 167 | if (MSICONDITION_TRUE == condition) | ||
| 168 | { | ||
| 169 | WcaLog(LOGMSG_STANDARD, "True condition for row %S: %S; processing.", sczId, sczCondition); | ||
| 170 | } | ||
| 171 | else | ||
| 172 | { | ||
| 173 | WcaLog(LOGMSG_STANDARD, "False or invalid condition for row %S: %S; skipping.", sczId, sczCondition); | ||
| 174 | continue; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 140 | hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent); | 178 | hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent); |
| 141 | ExitOnFailure(hr, "Failed to get remove folder component."); | 179 | ExitOnFailure(hr, "Failed to get remove folder component."); |
| 142 | 180 | ||
| 143 | hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty); | 181 | hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty); |
| 144 | ExitOnFailure(hr, "Failed to get remove folder property."); | 182 | ExitOnFailure(hr, "Failed to get remove folder property."); |
| 145 | 183 | ||
| 146 | hr = WcaGetRecordInteger(hRec, feqMode, &iMode); | 184 | hr = WcaGetRecordInteger(hRec, rfqMode, &iMode); |
| 147 | ExitOnFailure(hr, "Failed to get remove folder mode"); | 185 | ExitOnFailure(hr, "Failed to get remove folder mode"); |
| 148 | 186 | ||
| 149 | hr = WcaGetProperty(sczProperty, &sczPath); | 187 | hr = WcaGetProperty(sczProperty, &sczPath); |
| 150 | ExitOnFailure(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId); | 188 | ExitOnFailure(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId); |
| 151 | 189 | ||
| 190 | hr = WcaGetRecordInteger(hRec, rfqComponentAttributes, &iComponentAttributes); | ||
| 191 | ExitOnFailure(hr, "failed to get component attributes for row: %ls", sczId); | ||
| 192 | |||
| 193 | f64BitComponent = iComponentAttributes & msidbComponentAttributes64bit; | ||
| 194 | |||
| 152 | // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder | 195 | // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder |
| 153 | // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null | 196 | // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null |
| 154 | hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast<UINT_PTR*>(&cchLen)); | 197 | hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast<UINT_PTR*>(&cchLen)); |
| @@ -164,7 +207,7 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( | |||
| 164 | ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath); | 207 | ExitOnFailure(hr, "Failed to backslash-terminate path: %S", sczExpandedPath); |
| 165 | 208 | ||
| 166 | WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId); | 209 | WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId); |
| 167 | hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, &dwCounter, &hTable, &hColumns); | 210 | hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, f64BitComponent, &dwCounter, &hTable, &hColumns); |
| 168 | ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId); | 211 | ExitOnFailure(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId); |
| 169 | } | 212 | } |
| 170 | 213 | ||
| @@ -176,6 +219,8 @@ extern "C" UINT WINAPI WixRemoveFoldersEx( | |||
| 176 | ExitOnFailure(hr, "Failure occured while processing Wix4RemoveFolderEx table"); | 219 | ExitOnFailure(hr, "Failure occured while processing Wix4RemoveFolderEx table"); |
| 177 | 220 | ||
| 178 | LExit: | 221 | LExit: |
| 222 | WcaFinalizeWow64(); | ||
| 223 | |||
| 179 | if (hColumns) | 224 | if (hColumns) |
| 180 | { | 225 | { |
| 181 | ::MsiCloseHandle(hColumns); | 226 | ::MsiCloseHandle(hColumns); |
| @@ -190,6 +235,7 @@ LExit: | |||
| 190 | ReleaseStr(sczPath); | 235 | ReleaseStr(sczPath); |
| 191 | ReleaseStr(sczProperty); | 236 | ReleaseStr(sczProperty); |
| 192 | ReleaseStr(sczComponent); | 237 | ReleaseStr(sczComponent); |
| 238 | ReleaseStr(sczCondition); | ||
| 193 | ReleaseStr(sczId); | 239 | ReleaseStr(sczId); |
| 194 | 240 | ||
| 195 | DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | 241 | DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; |
diff --git a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs index b2af91b3..9c32ebc2 100644 --- a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs +++ b/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs | |||
| @@ -139,8 +139,8 @@ namespace WixToolsetTest.Util | |||
| 139 | WixAssert.CompareLineByLine(new[] | 139 | WixAssert.CompareLineByLine(new[] |
| 140 | { | 140 | { |
| 141 | "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", | 141 | "Binary:Wix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t[Binary data]", |
| 142 | "CustomAction:Wix4RemoveFoldersEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A WixRemoveFoldersEx\t", | 142 | "CustomAction:Wix4RemoveFoldersEx_X64.047730A5_30FE_4A62_A520_DA9381B8226A\t65\tWix4UtilCA_X64.047730A5_30FE_4A62_A520_DA9381B8226A\tWixRemoveFoldersEx\t", |
| 143 | "Wix4RemoveFolderEx:wrfB3e9CDihkNwm06LohylbJcjZ91w.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\tRemoveProp.047730A5_30FE_4A62_A520_DA9381B8226A\t3", | 143 | "Wix4RemoveFolderEx:wrf5qCm1SE.zp8djrlk78l1IYFXsEw.047730A5_30FE_4A62_A520_DA9381B8226A\tfilh4juyUVjoUcWWtcQmd5L07FoON4.047730A5_30FE_4A62_A520_DA9381B8226A\tRemoveProp.047730A5_30FE_4A62_A520_DA9381B8226A\t3\t", |
| 144 | }, results.OrderBy(s => s).ToArray()); | 144 | }, results.OrderBy(s => s).ToArray()); |
| 145 | } | 145 | } |
| 146 | 146 | ||
diff --git a/src/wixext/Symbols/WixRemoveFolderExSymbol.cs b/src/wixext/Symbols/WixRemoveFolderExSymbol.cs index 0c50ab8e..86352b6c 100644 --- a/src/wixext/Symbols/WixRemoveFolderExSymbol.cs +++ b/src/wixext/Symbols/WixRemoveFolderExSymbol.cs | |||
| @@ -14,6 +14,7 @@ namespace WixToolset.Util | |||
| 14 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.ComponentRef), IntermediateFieldType.String), | 14 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.ComponentRef), IntermediateFieldType.String), |
| 15 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Property), IntermediateFieldType.String), | 15 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Property), IntermediateFieldType.String), |
| 16 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.InstallMode), IntermediateFieldType.Number), | 16 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.InstallMode), IntermediateFieldType.Number), |
| 17 | new IntermediateFieldDefinition(nameof(WixRemoveFolderExSymbolFields.Condition), IntermediateFieldType.String), | ||
| 17 | }, | 18 | }, |
| 18 | typeof(WixRemoveFolderExSymbol)); | 19 | typeof(WixRemoveFolderExSymbol)); |
| 19 | } | 20 | } |
| @@ -28,6 +29,14 @@ namespace WixToolset.Util.Symbols | |||
| 28 | ComponentRef, | 29 | ComponentRef, |
| 29 | Property, | 30 | Property, |
| 30 | InstallMode, | 31 | InstallMode, |
| 32 | Condition, | ||
| 33 | } | ||
| 34 | |||
| 35 | public enum WixRemoveFolderExInstallMode | ||
| 36 | { | ||
| 37 | Install = 1, | ||
| 38 | Uninstall = 2, | ||
| 39 | Both = 3, | ||
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | public class WixRemoveFolderExSymbol : IntermediateSymbol | 42 | public class WixRemoveFolderExSymbol : IntermediateSymbol |
| @@ -54,10 +63,16 @@ namespace WixToolset.Util.Symbols | |||
| 54 | set => this.Set((int)WixRemoveFolderExSymbolFields.Property, value); | 63 | set => this.Set((int)WixRemoveFolderExSymbolFields.Property, value); |
| 55 | } | 64 | } |
| 56 | 65 | ||
| 57 | public int InstallMode | 66 | public WixRemoveFolderExInstallMode InstallMode |
| 67 | { | ||
| 68 | get => (WixRemoveFolderExInstallMode)this.Fields[(int)WixRemoveFolderExSymbolFields.InstallMode].AsNumber(); | ||
| 69 | set => this.Set((int)WixRemoveFolderExSymbolFields.InstallMode, (int)value); | ||
| 70 | } | ||
| 71 | |||
| 72 | public string Condition | ||
| 58 | { | 73 | { |
| 59 | get => this.Fields[(int)WixRemoveFolderExSymbolFields.InstallMode].AsNumber(); | 74 | get => this.Fields[(int)WixRemoveFolderExSymbolFields.Condition].AsString(); |
| 60 | set => this.Set((int)WixRemoveFolderExSymbolFields.InstallMode, value); | 75 | set => this.Set((int)WixRemoveFolderExSymbolFields.Condition, value); |
| 61 | } | 76 | } |
| 62 | } | 77 | } |
| 63 | } \ No newline at end of file | 78 | } \ No newline at end of file |
diff --git a/src/wixext/UtilCompiler.cs b/src/wixext/UtilCompiler.cs index 12213e63..63f2b469 100644 --- a/src/wixext/UtilCompiler.cs +++ b/src/wixext/UtilCompiler.cs | |||
| @@ -41,13 +41,6 @@ namespace WixToolset.Util | |||
| 41 | Compatible, | 41 | Compatible, |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | internal enum WixRemoveFolderExOn | ||
| 45 | { | ||
| 46 | Install = 1, | ||
| 47 | Uninstall = 2, | ||
| 48 | Both = 3, | ||
| 49 | } | ||
| 50 | |||
| 51 | private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled); | 44 | private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled); |
| 52 | 45 | ||
| 53 | public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/util"; | 46 | public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/util"; |
| @@ -2812,8 +2805,9 @@ namespace WixToolset.Util | |||
| 2812 | { | 2805 | { |
| 2813 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | 2806 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); |
| 2814 | Identifier id = null; | 2807 | Identifier id = null; |
| 2815 | var on = (int)WixRemoveFolderExOn.Uninstall; | 2808 | var mode = WixRemoveFolderExInstallMode.Uninstall; |
| 2816 | string property = null; | 2809 | string property = null; |
| 2810 | string condition = null; | ||
| 2817 | 2811 | ||
| 2818 | foreach (var attrib in element.Attributes()) | 2812 | foreach (var attrib in element.Attributes()) |
| 2819 | { | 2813 | { |
| @@ -2821,6 +2815,9 @@ namespace WixToolset.Util | |||
| 2821 | { | 2815 | { |
| 2822 | switch (attrib.Name.LocalName) | 2816 | switch (attrib.Name.LocalName) |
| 2823 | { | 2817 | { |
| 2818 | case "Condition": | ||
| 2819 | condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2820 | break; | ||
| 2824 | case "Id": | 2821 | case "Id": |
| 2825 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); | 2822 | id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); |
| 2826 | break; | 2823 | break; |
| @@ -2828,24 +2825,22 @@ namespace WixToolset.Util | |||
| 2828 | var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); | 2825 | var onValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); |
| 2829 | if (onValue.Length == 0) | 2826 | if (onValue.Length == 0) |
| 2830 | { | 2827 | { |
| 2831 | on = CompilerConstants.IllegalInteger; | ||
| 2832 | } | 2828 | } |
| 2833 | else | 2829 | else |
| 2834 | { | 2830 | { |
| 2835 | switch (onValue) | 2831 | switch (onValue) |
| 2836 | { | 2832 | { |
| 2837 | case "install": | 2833 | case "install": |
| 2838 | on = (int)WixRemoveFolderExOn.Install; | 2834 | mode = WixRemoveFolderExInstallMode.Install; |
| 2839 | break; | 2835 | break; |
| 2840 | case "uninstall": | 2836 | case "uninstall": |
| 2841 | on = (int)WixRemoveFolderExOn.Uninstall; | 2837 | mode = WixRemoveFolderExInstallMode.Uninstall; |
| 2842 | break; | 2838 | break; |
| 2843 | case "both": | 2839 | case "both": |
| 2844 | on = (int)WixRemoveFolderExOn.Both; | 2840 | mode = WixRemoveFolderExInstallMode.Both; |
| 2845 | break; | 2841 | break; |
| 2846 | default: | 2842 | default: |
| 2847 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", onValue, "install", "uninstall", "both")); | 2843 | this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "On", onValue, "install", "uninstall", "both")); |
| 2848 | on = CompilerConstants.IllegalInteger; | ||
| 2849 | break; | 2844 | break; |
| 2850 | } | 2845 | } |
| 2851 | } | 2846 | } |
| @@ -2869,9 +2864,9 @@ namespace WixToolset.Util | |||
| 2869 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property")); | 2864 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Property")); |
| 2870 | } | 2865 | } |
| 2871 | 2866 | ||
| 2872 | if (null == id) | 2867 | if (id == null) |
| 2873 | { | 2868 | { |
| 2874 | id = this.ParseHelper.CreateIdentifier("wrf", componentId, property, on.ToString(CultureInfo.InvariantCulture.NumberFormat)); | 2869 | id = this.ParseHelper.CreateIdentifier("wrf", componentId, property, mode.ToString()); |
| 2875 | } | 2870 | } |
| 2876 | 2871 | ||
| 2877 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | 2872 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); |
| @@ -2884,7 +2879,8 @@ namespace WixToolset.Util | |||
| 2884 | { | 2879 | { |
| 2885 | ComponentRef = componentId, | 2880 | ComponentRef = componentId, |
| 2886 | Property = property, | 2881 | Property = property, |
| 2887 | InstallMode = on, | 2882 | InstallMode = mode, |
| 2883 | Condition = condition | ||
| 2888 | }); | 2884 | }); |
| 2889 | 2885 | ||
| 2890 | this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveFile"); | 2886 | this.ParseHelper.EnsureTable(section, sourceLineNumbers, "RemoveFile"); |
diff --git a/src/wixext/UtilTableDefinitions.cs b/src/wixext/UtilTableDefinitions.cs index eff5aaf6..fd09367a 100644 --- a/src/wixext/UtilTableDefinitions.cs +++ b/src/wixext/UtilTableDefinitions.cs | |||
| @@ -33,6 +33,7 @@ namespace WixToolset.Util | |||
| 33 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), | 33 | new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table used to determine install state", modularizeType: ColumnModularizeType.Column), |
| 34 | new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of Property that contains the root of the directory tree to remove.", modularizeType: ColumnModularizeType.Column), | 34 | new ColumnDefinition("Property", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, description: "Name of Property that contains the root of the directory tree to remove.", modularizeType: ColumnModularizeType.Column), |
| 35 | new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), | 35 | new ColumnDefinition("InstallMode", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, minValue: 1, maxValue: 3, description: "1 == Remove only when the associated component is being installed (msiInstallStateLocal or msiInstallStateSource), 2 == Remove only when the associated component is being removed (msiInstallStateAbsent), 3 = Remove in either of the above cases."), |
| 36 | new ColumnDefinition("Condition", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Condition, description: "Optional expression which skips the removing of folders.", modularizeType: ColumnModularizeType.Condition, forceLocalizable: true), | ||
| 36 | }, | 37 | }, |
| 37 | symbolIdIsPrimaryKey: true | 38 | symbolIdIsPrimaryKey: true |
| 38 | ); | 39 | ); |
