diff options
| -rw-r--r-- | src/burn/engine/search.cpp | 159 | ||||
| -rw-r--r-- | src/burn/engine/search.h | 13 | ||||
| -rw-r--r-- | src/burn/test/BurnUnitTest/SearchTest.cpp | 36 |
3 files changed, 42 insertions, 166 deletions
diff --git a/src/burn/engine/search.cpp b/src/burn/engine/search.cpp index 4505e1a2..46dd2395 100644 --- a/src/burn/engine/search.cpp +++ b/src/burn/engine/search.cpp | |||
| @@ -41,10 +41,6 @@ static HRESULT MsiProductSearch( | |||
| 41 | __in BURN_SEARCH* pSearch, | 41 | __in BURN_SEARCH* pSearch, |
| 42 | __in BURN_VARIABLES* pVariables | 42 | __in BURN_VARIABLES* pVariables |
| 43 | ); | 43 | ); |
| 44 | static HRESULT MsiFeatureSearch( | ||
| 45 | __in BURN_SEARCH* pSearch, | ||
| 46 | __in BURN_VARIABLES* pVariables | ||
| 47 | ); | ||
| 48 | static HRESULT PerformExtensionSearch( | 44 | static HRESULT PerformExtensionSearch( |
| 49 | __in BURN_SEARCH* pSearch | 45 | __in BURN_SEARCH* pSearch |
| 50 | ); | 46 | ); |
| @@ -67,6 +63,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 67 | IXMLDOMNode* pixnNode = NULL; | 63 | IXMLDOMNode* pixnNode = NULL; |
| 68 | DWORD cNodes = 0; | 64 | DWORD cNodes = 0; |
| 69 | BSTR bstrNodeName = NULL; | 65 | BSTR bstrNodeName = NULL; |
| 66 | BOOL fXmlFound = FALSE; | ||
| 70 | LPWSTR scz = NULL; | 67 | LPWSTR scz = NULL; |
| 71 | BURN_VARIANT_TYPE valueType = BURN_VARIANT_TYPE_NONE; | 68 | BURN_VARIANT_TYPE valueType = BURN_VARIANT_TYPE_NONE; |
| 72 | 69 | ||
| @@ -76,7 +73,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 76 | 73 | ||
| 77 | // get search node count | 74 | // get search node count |
| 78 | hr = pixnNodes->get_length((long*)&cNodes); | 75 | hr = pixnNodes->get_length((long*)&cNodes); |
| 79 | ExitOnFailure(hr, "Failed to get search node count."); | 76 | ExitOnRootFailure(hr, "Failed to get search node count."); |
| 80 | 77 | ||
| 81 | if (!cNodes) | 78 | if (!cNodes) |
| 82 | { | 79 | { |
| @@ -99,18 +96,15 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 99 | 96 | ||
| 100 | // @Id | 97 | // @Id |
| 101 | hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczKey); | 98 | hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczKey); |
| 102 | ExitOnFailure(hr, "Failed to get @Id."); | 99 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Id."); |
| 103 | 100 | ||
| 104 | // @Variable | 101 | // @Variable |
| 105 | hr = XmlGetAttributeEx(pixnNode, L"Variable", &pSearch->sczVariable); | 102 | hr = XmlGetAttributeEx(pixnNode, L"Variable", &pSearch->sczVariable); |
| 106 | ExitOnFailure(hr, "Failed to get @Variable."); | 103 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Variable."); |
| 107 | 104 | ||
| 108 | // @Condition | 105 | // @Condition |
| 109 | hr = XmlGetAttributeEx(pixnNode, L"Condition", &pSearch->sczCondition); | 106 | hr = XmlGetAttributeEx(pixnNode, L"Condition", &pSearch->sczCondition); |
| 110 | if (E_NOTFOUND != hr) | 107 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @Condition."); |
| 111 | { | ||
| 112 | ExitOnFailure(hr, "Failed to get @Condition."); | ||
| 113 | } | ||
| 114 | 108 | ||
| 115 | // read type specific attributes | 109 | // read type specific attributes |
| 116 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"DirectorySearch", -1)) | 110 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"DirectorySearch", -1)) |
| @@ -119,11 +113,11 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 119 | 113 | ||
| 120 | // @Path | 114 | // @Path |
| 121 | hr = XmlGetAttributeEx(pixnNode, L"Path", &pSearch->DirectorySearch.sczPath); | 115 | hr = XmlGetAttributeEx(pixnNode, L"Path", &pSearch->DirectorySearch.sczPath); |
| 122 | ExitOnFailure(hr, "Failed to get @Path."); | 116 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Path."); |
| 123 | 117 | ||
| 124 | // @Type | 118 | // @Type |
| 125 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 119 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 126 | ExitOnFailure(hr, "Failed to get @Type."); | 120 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 127 | 121 | ||
| 128 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) | 122 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) |
| 129 | { | 123 | { |
| @@ -135,8 +129,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 135 | } | 129 | } |
| 136 | else | 130 | else |
| 137 | { | 131 | { |
| 138 | hr = E_INVALIDARG; | 132 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 139 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 140 | } | 133 | } |
| 141 | } | 134 | } |
| 142 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"FileSearch", -1)) | 135 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"FileSearch", -1)) |
| @@ -145,11 +138,11 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 145 | 138 | ||
| 146 | // @Path | 139 | // @Path |
| 147 | hr = XmlGetAttributeEx(pixnNode, L"Path", &pSearch->FileSearch.sczPath); | 140 | hr = XmlGetAttributeEx(pixnNode, L"Path", &pSearch->FileSearch.sczPath); |
| 148 | ExitOnFailure(hr, "Failed to get @Path."); | 141 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Path."); |
| 149 | 142 | ||
| 150 | // @Type | 143 | // @Type |
| 151 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 144 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 152 | ExitOnFailure(hr, "Failed to get @Type."); | 145 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 153 | 146 | ||
| 154 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) | 147 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) |
| 155 | { | 148 | { |
| @@ -165,8 +158,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 165 | } | 158 | } |
| 166 | else | 159 | else |
| 167 | { | 160 | { |
| 168 | hr = E_INVALIDARG; | 161 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 169 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 170 | } | 162 | } |
| 171 | } | 163 | } |
| 172 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"RegistrySearch", -1)) | 164 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"RegistrySearch", -1)) |
| @@ -175,7 +167,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 175 | 167 | ||
| 176 | // @Root | 168 | // @Root |
| 177 | hr = XmlGetAttributeEx(pixnNode, L"Root", &scz); | 169 | hr = XmlGetAttributeEx(pixnNode, L"Root", &scz); |
| 178 | ExitOnFailure(hr, "Failed to get @Root."); | 170 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Root."); |
| 179 | 171 | ||
| 180 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKCR", -1)) | 172 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKCR", -1)) |
| 181 | { | 173 | { |
| @@ -195,30 +187,23 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 195 | } | 187 | } |
| 196 | else | 188 | else |
| 197 | { | 189 | { |
| 198 | hr = E_INVALIDARG; | 190 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Root: %ls", scz); |
| 199 | ExitOnFailure(hr, "Invalid value for @Root: %ls", scz); | ||
| 200 | } | 191 | } |
| 201 | 192 | ||
| 202 | // @Key | 193 | // @Key |
| 203 | hr = XmlGetAttributeEx(pixnNode, L"Key", &pSearch->RegistrySearch.sczKey); | 194 | hr = XmlGetAttributeEx(pixnNode, L"Key", &pSearch->RegistrySearch.sczKey); |
| 204 | ExitOnFailure(hr, "Failed to get Key attribute."); | 195 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get Key attribute."); |
| 205 | 196 | ||
| 206 | // @Value | 197 | // @Value |
| 207 | hr = XmlGetAttributeEx(pixnNode, L"Value", &pSearch->RegistrySearch.sczValue); | 198 | hr = XmlGetAttributeEx(pixnNode, L"Value", &pSearch->RegistrySearch.sczValue); |
| 208 | if (E_NOTFOUND != hr) | 199 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get Value attribute."); |
| 209 | { | ||
| 210 | ExitOnFailure(hr, "Failed to get Value attribute."); | ||
| 211 | } | ||
| 212 | 200 | ||
| 213 | // @Type | 201 | // @Type |
| 214 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 202 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 215 | ExitOnFailure(hr, "Failed to get @Type."); | 203 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 216 | 204 | ||
| 217 | hr = XmlGetYesNoAttribute(pixnNode, L"Win64", &pSearch->RegistrySearch.fWin64); | 205 | hr = XmlGetYesNoAttribute(pixnNode, L"Win64", &pSearch->RegistrySearch.fWin64); |
| 218 | if (E_NOTFOUND != hr) | 206 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get Win64 attribute."); |
| 219 | { | ||
| 220 | ExitOnFailure(hr, "Failed to get Win64 attribute."); | ||
| 221 | } | ||
| 222 | 207 | ||
| 223 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) | 208 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) |
| 224 | { | 209 | { |
| @@ -230,14 +215,11 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 230 | 215 | ||
| 231 | // @ExpandEnvironment | 216 | // @ExpandEnvironment |
| 232 | hr = XmlGetYesNoAttribute(pixnNode, L"ExpandEnvironment", &pSearch->RegistrySearch.fExpandEnvironment); | 217 | hr = XmlGetYesNoAttribute(pixnNode, L"ExpandEnvironment", &pSearch->RegistrySearch.fExpandEnvironment); |
| 233 | if (E_NOTFOUND != hr) | 218 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @ExpandEnvironment."); |
| 234 | { | ||
| 235 | ExitOnFailure(hr, "Failed to get @ExpandEnvironment."); | ||
| 236 | } | ||
| 237 | 219 | ||
| 238 | // @VariableType | 220 | // @VariableType |
| 239 | hr = XmlGetAttributeEx(pixnNode, L"VariableType", &scz); | 221 | hr = XmlGetAttributeEx(pixnNode, L"VariableType", &scz); |
| 240 | ExitOnFailure(hr, "Failed to get @VariableType."); | 222 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @VariableType."); |
| 241 | 223 | ||
| 242 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) | 224 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) |
| 243 | { | 225 | { |
| @@ -257,14 +239,12 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 257 | } | 239 | } |
| 258 | else | 240 | else |
| 259 | { | 241 | { |
| 260 | hr = E_INVALIDARG; | 242 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @VariableType: %ls", scz); |
| 261 | ExitOnFailure(hr, "Invalid value for @VariableType: %ls", scz); | ||
| 262 | } | 243 | } |
| 263 | } | 244 | } |
| 264 | else | 245 | else |
| 265 | { | 246 | { |
| 266 | hr = E_INVALIDARG; | 247 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 267 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 268 | } | 248 | } |
| 269 | } | 249 | } |
| 270 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiComponentSearch", -1)) | 250 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiComponentSearch", -1)) |
| @@ -273,18 +253,15 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 273 | 253 | ||
| 274 | // @ProductCode | 254 | // @ProductCode |
| 275 | hr = XmlGetAttributeEx(pixnNode, L"ProductCode", &pSearch->MsiComponentSearch.sczProductCode); | 255 | hr = XmlGetAttributeEx(pixnNode, L"ProductCode", &pSearch->MsiComponentSearch.sczProductCode); |
| 276 | if (E_NOTFOUND != hr) | 256 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @ProductCode."); |
| 277 | { | ||
| 278 | ExitOnFailure(hr, "Failed to get @ProductCode."); | ||
| 279 | } | ||
| 280 | 257 | ||
| 281 | // @ComponentId | 258 | // @ComponentId |
| 282 | hr = XmlGetAttributeEx(pixnNode, L"ComponentId", &pSearch->MsiComponentSearch.sczComponentId); | 259 | hr = XmlGetAttributeEx(pixnNode, L"ComponentId", &pSearch->MsiComponentSearch.sczComponentId); |
| 283 | ExitOnFailure(hr, "Failed to get @ComponentId."); | 260 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ComponentId."); |
| 284 | 261 | ||
| 285 | // @Type | 262 | // @Type |
| 286 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 263 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 287 | ExitOnFailure(hr, "Failed to get @Type."); | 264 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 288 | 265 | ||
| 289 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"keyPath", -1)) | 266 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"keyPath", -1)) |
| 290 | { | 267 | { |
| @@ -300,8 +277,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 300 | } | 277 | } |
| 301 | else | 278 | else |
| 302 | { | 279 | { |
| 303 | hr = E_INVALIDARG; | 280 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 304 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 305 | } | 281 | } |
| 306 | } | 282 | } |
| 307 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiProductSearch", -1)) | 283 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiProductSearch", -1)) |
| @@ -311,18 +287,20 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 311 | 287 | ||
| 312 | // @ProductCode (if we don't find a product code then look for an upgrade code) | 288 | // @ProductCode (if we don't find a product code then look for an upgrade code) |
| 313 | hr = XmlGetAttributeEx(pixnNode, L"ProductCode", &pSearch->MsiProductSearch.sczGuid); | 289 | hr = XmlGetAttributeEx(pixnNode, L"ProductCode", &pSearch->MsiProductSearch.sczGuid); |
| 314 | if (E_NOTFOUND != hr) | 290 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @ProductCode."); |
| 291 | |||
| 292 | if (fXmlFound) | ||
| 315 | { | 293 | { |
| 316 | ExitOnFailure(hr, "Failed to get @ProductCode."); | ||
| 317 | pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_PRODUCTCODE; | 294 | pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_PRODUCTCODE; |
| 318 | } | 295 | } |
| 319 | else | 296 | else |
| 320 | { | 297 | { |
| 321 | // @UpgradeCode | 298 | // @UpgradeCode |
| 322 | hr = XmlGetAttributeEx(pixnNode, L"UpgradeCode", &pSearch->MsiProductSearch.sczGuid); | 299 | hr = XmlGetAttributeEx(pixnNode, L"UpgradeCode", &pSearch->MsiProductSearch.sczGuid); |
| 323 | if (E_NOTFOUND != hr) | 300 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @UpgradeCode."); |
| 301 | |||
| 302 | if (fXmlFound) | ||
| 324 | { | 303 | { |
| 325 | ExitOnFailure(hr, "Failed to get @UpgradeCode."); | ||
| 326 | pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_UPGRADECODE; | 304 | pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_UPGRADECODE; |
| 327 | } | 305 | } |
| 328 | } | 306 | } |
| @@ -330,13 +308,12 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 330 | // make sure we found either a product or upgrade code | 308 | // make sure we found either a product or upgrade code |
| 331 | if (BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_NONE == pSearch->MsiProductSearch.GuidType) | 309 | if (BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_NONE == pSearch->MsiProductSearch.GuidType) |
| 332 | { | 310 | { |
| 333 | hr = E_NOTFOUND; | 311 | ExitWithRootFailure(hr, E_NOTFOUND, "Failed to get @ProductCode or @UpgradeCode."); |
| 334 | ExitOnFailure(hr, "Failed to get @ProductCode or @UpgradeCode."); | ||
| 335 | } | 312 | } |
| 336 | 313 | ||
| 337 | // @Type | 314 | // @Type |
| 338 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 315 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 339 | ExitOnFailure(hr, "Failed to get @Type."); | 316 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 340 | 317 | ||
| 341 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) | 318 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) |
| 342 | { | 319 | { |
| @@ -356,34 +333,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 356 | } | 333 | } |
| 357 | else | 334 | else |
| 358 | { | 335 | { |
| 359 | hr = E_INVALIDARG; | 336 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 360 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiFeatureSearch", -1)) | ||
| 364 | { | ||
| 365 | pSearch->Type = BURN_SEARCH_TYPE_MSI_FEATURE; | ||
| 366 | |||
| 367 | // @ProductCode | ||
| 368 | hr = XmlGetAttributeEx(pixnNode, L"ProductCode", &pSearch->MsiFeatureSearch.sczProductCode); | ||
| 369 | ExitOnFailure(hr, "Failed to get @ProductCode."); | ||
| 370 | |||
| 371 | // @FeatureId | ||
| 372 | hr = XmlGetAttributeEx(pixnNode, L"FeatureId", &pSearch->MsiFeatureSearch.sczFeatureId); | ||
| 373 | ExitOnFailure(hr, "Failed to get @FeatureId."); | ||
| 374 | |||
| 375 | // @Type | ||
| 376 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | ||
| 377 | ExitOnFailure(hr, "Failed to get @Type."); | ||
| 378 | |||
| 379 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"state", -1)) | ||
| 380 | { | ||
| 381 | pSearch->MsiFeatureSearch.Type = BURN_MSI_FEATURE_SEARCH_TYPE_STATE; | ||
| 382 | } | ||
| 383 | else | ||
| 384 | { | ||
| 385 | hr = E_INVALIDARG; | ||
| 386 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 387 | } | 337 | } |
| 388 | } | 338 | } |
| 389 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExtensionSearch", -1)) | 339 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExtensionSearch", -1)) |
| @@ -392,10 +342,10 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 392 | 342 | ||
| 393 | // @ExtensionId | 343 | // @ExtensionId |
| 394 | hr = XmlGetAttributeEx(pixnNode, L"ExtensionId", &scz); | 344 | hr = XmlGetAttributeEx(pixnNode, L"ExtensionId", &scz); |
| 395 | ExitOnFailure(hr, "Failed to get @ExtensionId."); | 345 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ExtensionId."); |
| 396 | 346 | ||
| 397 | hr = BurnExtensionFindById(pBurnExtensions, scz, &pSearch->ExtensionSearch.pExtension); | 347 | hr = BurnExtensionFindById(pBurnExtensions, scz, &pSearch->ExtensionSearch.pExtension); |
| 398 | ExitOnFailure(hr, "Failed to find extension '%ls' for search '%ls'", scz, pSearch->sczKey); | 348 | ExitOnRootFailure(hr, "Failed to find extension '%ls' for search '%ls'", scz, pSearch->sczKey); |
| 399 | } | 349 | } |
| 400 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"SetVariable", -1)) | 350 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"SetVariable", -1)) |
| 401 | { | 351 | { |
| @@ -403,16 +353,16 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 403 | 353 | ||
| 404 | // @Value | 354 | // @Value |
| 405 | hr = XmlGetAttributeEx(pixnNode, L"Value", &scz); | 355 | hr = XmlGetAttributeEx(pixnNode, L"Value", &scz); |
| 406 | if (E_NOTFOUND != hr) | 356 | ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @Value."); |
| 407 | { | ||
| 408 | ExitOnFailure(hr, "Failed to get @Value."); | ||
| 409 | 357 | ||
| 358 | if (fXmlFound) | ||
| 359 | { | ||
| 410 | hr = BVariantSetString(&pSearch->SetVariable.value, scz, 0, FALSE); | 360 | hr = BVariantSetString(&pSearch->SetVariable.value, scz, 0, FALSE); |
| 411 | ExitOnFailure(hr, "Failed to set variant value."); | 361 | ExitOnFailure(hr, "Failed to set variant value."); |
| 412 | 362 | ||
| 413 | // @Type | 363 | // @Type |
| 414 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); | 364 | hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); |
| 415 | ExitOnFailure(hr, "Failed to get @Type."); | 365 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); |
| 416 | 366 | ||
| 417 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) | 367 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) |
| 418 | { | 368 | { |
| @@ -432,8 +382,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 432 | } | 382 | } |
| 433 | else | 383 | else |
| 434 | { | 384 | { |
| 435 | hr = E_INVALIDARG; | 385 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); |
| 436 | ExitOnFailure(hr, "Invalid value for @Type: %ls", scz); | ||
| 437 | } | 386 | } |
| 438 | } | 387 | } |
| 439 | else | 388 | else |
| @@ -447,8 +396,7 @@ extern "C" HRESULT SearchesParseFromXml( | |||
| 447 | } | 396 | } |
| 448 | else | 397 | else |
| 449 | { | 398 | { |
| 450 | hr = E_UNEXPECTED; | 399 | ExitWithRootFailure(hr, E_UNEXPECTED, "Unexpected element name: %ls", bstrNodeName); |
| 451 | ExitOnFailure(hr, "Unexpected element name: %ls", bstrNodeName); | ||
| 452 | } | 400 | } |
| 453 | 401 | ||
| 454 | // prepare next iteration | 402 | // prepare next iteration |
| @@ -546,9 +494,6 @@ extern "C" HRESULT SearchesExecute( | |||
| 546 | case BURN_SEARCH_TYPE_MSI_PRODUCT: | 494 | case BURN_SEARCH_TYPE_MSI_PRODUCT: |
| 547 | hr = MsiProductSearch(pSearch, pVariables); | 495 | hr = MsiProductSearch(pSearch, pVariables); |
| 548 | break; | 496 | break; |
| 549 | case BURN_SEARCH_TYPE_MSI_FEATURE: | ||
| 550 | hr = MsiFeatureSearch(pSearch, pVariables); | ||
| 551 | break; | ||
| 552 | case BURN_SEARCH_TYPE_EXTENSION: | 497 | case BURN_SEARCH_TYPE_EXTENSION: |
| 553 | hr = PerformExtensionSearch(pSearch); | 498 | hr = PerformExtensionSearch(pSearch); |
| 554 | break; | 499 | break; |
| @@ -605,10 +550,6 @@ extern "C" void SearchesUninitialize( | |||
| 605 | case BURN_SEARCH_TYPE_MSI_PRODUCT: | 550 | case BURN_SEARCH_TYPE_MSI_PRODUCT: |
| 606 | ReleaseStr(pSearch->MsiProductSearch.sczGuid); | 551 | ReleaseStr(pSearch->MsiProductSearch.sczGuid); |
| 607 | break; | 552 | break; |
| 608 | case BURN_SEARCH_TYPE_MSI_FEATURE: | ||
| 609 | ReleaseStr(pSearch->MsiFeatureSearch.sczProductCode); | ||
| 610 | ReleaseStr(pSearch->MsiFeatureSearch.sczFeatureId); | ||
| 611 | break; | ||
| 612 | case BURN_SEARCH_TYPE_SET_VARIABLE: | 553 | case BURN_SEARCH_TYPE_SET_VARIABLE: |
| 613 | BVariantUninitialize(&pSearch->SetVariable.value); | 554 | BVariantUninitialize(&pSearch->SetVariable.value); |
| 614 | break; | 555 | break; |
| @@ -1249,22 +1190,6 @@ LExit: | |||
| 1249 | return hr; | 1190 | return hr; |
| 1250 | } | 1191 | } |
| 1251 | 1192 | ||
| 1252 | static HRESULT MsiFeatureSearch( | ||
| 1253 | __in BURN_SEARCH* pSearch, | ||
| 1254 | __in BURN_VARIABLES* /*pVariables*/ | ||
| 1255 | ) | ||
| 1256 | { | ||
| 1257 | HRESULT hr = E_NOTIMPL; | ||
| 1258 | |||
| 1259 | //LExit: | ||
| 1260 | if (FAILED(hr)) | ||
| 1261 | { | ||
| 1262 | LogStringLine(REPORT_STANDARD, "MsiFeatureSearch failed: ID '%ls', HRESULT 0x%x", pSearch->sczKey, hr); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | return hr; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | static HRESULT PerformExtensionSearch( | 1193 | static HRESULT PerformExtensionSearch( |
| 1269 | __in BURN_SEARCH* pSearch | 1194 | __in BURN_SEARCH* pSearch |
| 1270 | ) | 1195 | ) |
diff --git a/src/burn/engine/search.h b/src/burn/engine/search.h index c699c97c..6397d2a3 100644 --- a/src/burn/engine/search.h +++ b/src/burn/engine/search.h | |||
| @@ -17,7 +17,6 @@ enum BURN_SEARCH_TYPE | |||
| 17 | BURN_SEARCH_TYPE_REGISTRY, | 17 | BURN_SEARCH_TYPE_REGISTRY, |
| 18 | BURN_SEARCH_TYPE_MSI_COMPONENT, | 18 | BURN_SEARCH_TYPE_MSI_COMPONENT, |
| 19 | BURN_SEARCH_TYPE_MSI_PRODUCT, | 19 | BURN_SEARCH_TYPE_MSI_PRODUCT, |
| 20 | BURN_SEARCH_TYPE_MSI_FEATURE, | ||
| 21 | BURN_SEARCH_TYPE_EXTENSION, | 20 | BURN_SEARCH_TYPE_EXTENSION, |
| 22 | BURN_SEARCH_TYPE_SET_VARIABLE, | 21 | BURN_SEARCH_TYPE_SET_VARIABLE, |
| 23 | }; | 22 | }; |
| @@ -68,12 +67,6 @@ enum BURN_MSI_PRODUCT_SEARCH_GUID_TYPE | |||
| 68 | BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_UPGRADECODE | 67 | BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_UPGRADECODE |
| 69 | }; | 68 | }; |
| 70 | 69 | ||
| 71 | enum BURN_MSI_FEATURE_SEARCH_TYPE | ||
| 72 | { | ||
| 73 | BURN_MSI_FEATURE_SEARCH_TYPE_NONE, | ||
| 74 | BURN_MSI_FEATURE_SEARCH_TYPE_STATE, | ||
| 75 | }; | ||
| 76 | |||
| 77 | 70 | ||
| 78 | // structs | 71 | // structs |
| 79 | 72 | ||
| @@ -120,12 +113,6 @@ typedef struct _BURN_SEARCH | |||
| 120 | } MsiProductSearch; | 113 | } MsiProductSearch; |
| 121 | struct | 114 | struct |
| 122 | { | 115 | { |
| 123 | BURN_MSI_FEATURE_SEARCH_TYPE Type; | ||
| 124 | LPWSTR sczProductCode; | ||
| 125 | LPWSTR sczFeatureId; | ||
| 126 | } MsiFeatureSearch; | ||
| 127 | struct | ||
| 128 | { | ||
| 129 | BURN_EXTENSION* pExtension; | 116 | BURN_EXTENSION* pExtension; |
| 130 | } ExtensionSearch; | 117 | } ExtensionSearch; |
| 131 | struct | 118 | struct |
diff --git a/src/burn/test/BurnUnitTest/SearchTest.cpp b/src/burn/test/BurnUnitTest/SearchTest.cpp index eca01f5f..de38f2d8 100644 --- a/src/burn/test/BurnUnitTest/SearchTest.cpp +++ b/src/burn/test/BurnUnitTest/SearchTest.cpp | |||
| @@ -427,42 +427,6 @@ namespace Bootstrapper | |||
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | [Fact] | 429 | [Fact] |
| 430 | void MsiFeatureSearchTest() | ||
| 431 | { | ||
| 432 | HRESULT hr = S_OK; | ||
| 433 | IXMLDOMElement* pixeBundle = NULL; | ||
| 434 | BURN_VARIABLES variables = { }; | ||
| 435 | BURN_SEARCHES searches = { }; | ||
| 436 | BURN_EXTENSIONS burnExtensions = { }; | ||
| 437 | try | ||
| 438 | { | ||
| 439 | LPCWSTR wzDocument = | ||
| 440 | L"<Bundle>" | ||
| 441 | L" <MsiFeatureSearch Id='Search1' Type='state' ProductCode='{BAD00000-0000-0000-0000-000000000000}' FeatureId='' Variable='Variable1' />" | ||
| 442 | L"</Bundle>"; | ||
| 443 | |||
| 444 | hr = VariableInitialize(&variables); | ||
| 445 | TestThrowOnFailure(hr, L"Failed to initialize variables."); | ||
| 446 | |||
| 447 | // load XML document | ||
| 448 | LoadBundleXmlHelper(wzDocument, &pixeBundle); | ||
| 449 | |||
| 450 | hr = SearchesParseFromXml(&searches, &burnExtensions, pixeBundle); | ||
| 451 | TestThrowOnFailure(hr, L"Failed to parse searches from XML."); | ||
| 452 | |||
| 453 | // execute searches | ||
| 454 | hr = SearchesExecute(&searches, &variables); | ||
| 455 | TestThrowOnFailure(hr, L"Failed to execute searches."); | ||
| 456 | } | ||
| 457 | finally | ||
| 458 | { | ||
| 459 | ReleaseObject(pixeBundle); | ||
| 460 | VariablesUninitialize(&variables); | ||
| 461 | SearchesUninitialize(&searches); | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | [Fact] | ||
| 466 | void ConditionalSearchTest() | 430 | void ConditionalSearchTest() |
| 467 | { | 431 | { |
| 468 | HRESULT hr = S_OK; | 432 | HRESULT hr = S_OK; |
