aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine')
-rw-r--r--src/burn/engine/approvedexe.cpp107
-rw-r--r--src/burn/engine/approvedexe.h4
-rw-r--r--src/burn/engine/bundlepackageengine.cpp14
-rw-r--r--src/burn/engine/burnextension.cpp2
-rw-r--r--src/burn/engine/burnpipe.cpp2
-rw-r--r--src/burn/engine/cache.cpp16
-rw-r--r--src/burn/engine/condition.cpp16
-rw-r--r--src/burn/engine/container.cpp2
-rw-r--r--src/burn/engine/core.cpp98
-rw-r--r--src/burn/engine/core.h2
-rw-r--r--src/burn/engine/dependency.cpp24
-rw-r--r--src/burn/engine/detect.cpp2
-rw-r--r--src/burn/engine/elevation.cpp6
-rw-r--r--src/burn/engine/engine.mc6
-rw-r--r--src/burn/engine/engine.vcxproj2
-rw-r--r--src/burn/engine/exeengine.cpp41
-rw-r--r--src/burn/engine/logging.cpp2
-rw-r--r--src/burn/engine/manifest.cpp2
-rw-r--r--src/burn/engine/msiengine.cpp69
-rw-r--r--src/burn/engine/mspengine.cpp6
-rw-r--r--src/burn/engine/package.cpp28
-rw-r--r--src/burn/engine/payload.cpp4
-rw-r--r--src/burn/engine/registration.cpp22
-rw-r--r--src/burn/engine/relatedbundle.cpp8
-rw-r--r--src/burn/engine/search.cpp80
-rw-r--r--src/burn/engine/search.h1
-rw-r--r--src/burn/engine/splashscreen.cpp1
-rw-r--r--src/burn/engine/variable.cpp14
28 files changed, 394 insertions, 187 deletions
diff --git a/src/burn/engine/approvedexe.cpp b/src/burn/engine/approvedexe.cpp
index 28b26d6d..27ec2adc 100644
--- a/src/burn/engine/approvedexe.cpp
+++ b/src/burn/engine/approvedexe.cpp
@@ -3,6 +3,13 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6// internal function declarations
7
8static HRESULT IsRunDll32(
9 __in BURN_VARIABLES* pVariables,
10 __in LPCWSTR wzExecutablePath
11 );
12
6// function definitions 13// function definitions
7 14
8extern "C" HRESULT ApprovedExesParseFromXml( 15extern "C" HRESULT ApprovedExesParseFromXml(
@@ -122,7 +129,7 @@ extern "C" HRESULT ApprovedExesFindById(
122 { 129 {
123 pApprovedExe = &pApprovedExes->rgApprovedExes[i]; 130 pApprovedExe = &pApprovedExes->rgApprovedExes[i];
124 131
125 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pApprovedExe->sczId, -1, wzId, -1)) 132 if (CSTR_EQUAL == ::CompareStringOrdinal(pApprovedExe->sczId, -1, wzId, -1, FALSE))
126 { 133 {
127 *ppApprovedExe = pApprovedExe; 134 *ppApprovedExe = pApprovedExe;
128 ExitFunction1(hr = S_OK); 135 ExitFunction1(hr = S_OK);
@@ -221,12 +228,15 @@ LExit:
221extern "C" HRESULT ApprovedExesVerifySecureLocation( 228extern "C" HRESULT ApprovedExesVerifySecureLocation(
222 __in BURN_CACHE* pCache, 229 __in BURN_CACHE* pCache,
223 __in BURN_VARIABLES* pVariables, 230 __in BURN_VARIABLES* pVariables,
224 __in LPCWSTR wzExecutablePath 231 __in LPCWSTR wzExecutablePath,
232 __in int argc,
233 __in LPCWSTR* argv
225 ) 234 )
226{ 235{
227 HRESULT hr = S_OK; 236 HRESULT hr = S_OK;
228 LPWSTR scz = NULL; 237 LPWSTR scz = NULL;
229 LPWSTR sczSecondary = NULL; 238 LPWSTR sczSecondary = NULL;
239 LPWSTR sczRunDll32Param = NULL;
230 240
231 const LPCWSTR vrgSecureFolderVariables[] = { 241 const LPCWSTR vrgSecureFolderVariables[] = {
232 L"ProgramFiles64Folder", 242 L"ProgramFiles64Folder",
@@ -273,11 +283,104 @@ extern "C" HRESULT ApprovedExesVerifySecureLocation(
273 ExitFunction(); 283 ExitFunction();
274 } 284 }
275 285
286 // Test if executable is rundll32.exe, and it's target is in a secure location
287 // Example for CUDA UninstallString: "C:\WINDOWS\SysWOW64\RunDll32.EXE" "C:\Program Files\NVIDIA Corporation\Installer2\InstallerCore\NVI2.DLL",UninstallPackage CUDAToolkit_12.8
288 if (argc && argv && argv[0] && *argv[0])
289 {
290 hr = IsRunDll32(pVariables, wzExecutablePath);
291 ExitOnFailure(hr, "Failed to test whether executable is rundll32");
292
293 if (hr == S_OK)
294 {
295 LPCWSTR szComma = wcschr(argv[0], L',');
296 if (szComma && *szComma)
297 {
298 hr = StrAllocString(&sczRunDll32Param, argv[0], szComma - argv[0]);
299 ExitOnFailure(hr, "Failed to allocate string");
300 }
301 else
302 {
303 hr = StrAllocString(&sczRunDll32Param, argv[0], 0);
304 ExitOnFailure(hr, "Failed to allocate string");
305 }
306
307 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczRunDll32Param, 0, NULL);
308 ExitOnFailure(hr, "Failed to test whether rundll32's parameter, '%ls', is in a secure location", sczRunDll32Param);
309 if (hr == S_OK)
310 {
311 ExitFunction();
312 }
313 }
314 }
315
276 hr = S_FALSE; 316 hr = S_FALSE;
277 317
278LExit: 318LExit:
279 ReleaseStr(scz); 319 ReleaseStr(scz);
280 ReleaseStr(sczSecondary); 320 ReleaseStr(sczSecondary);
321 ReleaseStr(sczRunDll32Param);
322
323 return hr;
324}
325
326static HRESULT IsRunDll32(
327 __in BURN_VARIABLES* pVariables,
328 __in LPCWSTR wzExecutablePath
329 )
330{
331 HRESULT hr = S_OK;
332 LPWSTR sczFolder = NULL;
333 LPWSTR sczFullPath = NULL;
334 BOOL fEqual = FALSE;
335
336 hr = VariableGetString(pVariables, L"SystemFolder", &sczFolder);
337 ExitOnFailure(hr, "Failed to get the variable: SystemFolder");
338
339 hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath);
340 ExitOnFailure(hr, "Failed to combine paths");
341
342 hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual);
343 ExitOnFailure(hr, "Failed to compare paths");
344 if (fEqual)
345 {
346 hr = S_OK;
347 ExitFunction();
348 }
349
350 hr = VariableGetString(pVariables, L"System64Folder", &sczFolder);
351 ExitOnFailure(hr, "Failed to get the variable: System64Folder");
352
353 hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath);
354 ExitOnFailure(hr, "Failed to combine paths");
355
356 hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual);
357 ExitOnFailure(hr, "Failed to compare paths");
358 if (fEqual)
359 {
360 hr = S_OK;
361 ExitFunction();
362 }
363
364 // Sysnative
365 hr = PathSystemWindowsSubdirectory(L"SysNative\\", &sczFolder);
366 ExitOnFailure(hr, "Failed to append SysNative directory.");
367
368 hr = PathConcat(sczFolder, L"rundll32.exe", &sczFullPath);
369 ExitOnFailure(hr, "Failed to combine paths");
370
371 hr = PathCompareCanonicalized(wzExecutablePath, sczFullPath, &fEqual);
372 ExitOnFailure(hr, "Failed to compare paths");
373 if (fEqual)
374 {
375 hr = S_OK;
376 ExitFunction();
377 }
378
379 hr = S_FALSE;
380
381LExit:
382 ReleaseStr(sczFolder);
383 ReleaseStr(sczFullPath);
281 384
282 return hr; 385 return hr;
283} 386}
diff --git a/src/burn/engine/approvedexe.h b/src/burn/engine/approvedexe.h
index 7a68c174..0f441485 100644
--- a/src/burn/engine/approvedexe.h
+++ b/src/burn/engine/approvedexe.h
@@ -58,7 +58,9 @@ HRESULT ApprovedExesLaunch(
58HRESULT ApprovedExesVerifySecureLocation( 58HRESULT ApprovedExesVerifySecureLocation(
59 __in BURN_CACHE* pCache, 59 __in BURN_CACHE* pCache,
60 __in BURN_VARIABLES* pVariables, 60 __in BURN_VARIABLES* pVariables,
61 __in LPCWSTR wzExecutablePath 61 __in LPCWSTR wzExecutablePath,
62 __in int argc,
63 __in LPCWSTR* argv
62 ); 64 );
63 65
64 66
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index 612da389..7ada5f6a 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -146,7 +146,7 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
146 hr = XmlGetAttributeEx(pixnElement, L"Code", &sczCode); 146 hr = XmlGetAttributeEx(pixnElement, L"Code", &sczCode);
147 ExitOnFailure(hr, "Failed to get @Code."); 147 ExitOnFailure(hr, "Failed to get @Code.");
148 148
149 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Detect", -1)) 149 if (CSTR_EQUAL == ::CompareStringOrdinal(sczAction, -1, L"Detect", -1, FALSE))
150 { 150 {
151 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczDetectCodes), *pcDetectCodes, 1, sizeof(LPWSTR), 5); 151 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczDetectCodes), *pcDetectCodes, 1, sizeof(LPWSTR), 5);
152 ExitOnFailure(hr, "Failed to resize Detect code array"); 152 ExitOnFailure(hr, "Failed to resize Detect code array");
@@ -155,7 +155,7 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
155 sczCode = NULL; 155 sczCode = NULL;
156 *pcDetectCodes += 1; 156 *pcDetectCodes += 1;
157 } 157 }
158 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Upgrade", -1)) 158 else if (CSTR_EQUAL == ::CompareStringOrdinal(sczAction, -1, L"Upgrade", -1, FALSE))
159 { 159 {
160 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczUpgradeCodes), *pcUpgradeCodes, 1, sizeof(LPWSTR), 5); 160 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczUpgradeCodes), *pcUpgradeCodes, 1, sizeof(LPWSTR), 5);
161 ExitOnFailure(hr, "Failed to resize Upgrade code array"); 161 ExitOnFailure(hr, "Failed to resize Upgrade code array");
@@ -164,7 +164,7 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
164 sczCode = NULL; 164 sczCode = NULL;
165 *pcUpgradeCodes += 1; 165 *pcUpgradeCodes += 1;
166 } 166 }
167 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Addon", -1)) 167 else if (CSTR_EQUAL == ::CompareStringOrdinal(sczAction, -1, L"Addon", -1, FALSE))
168 { 168 {
169 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczAddonCodes), *pcAddonCodes, 1, sizeof(LPWSTR), 5); 169 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczAddonCodes), *pcAddonCodes, 1, sizeof(LPWSTR), 5);
170 ExitOnFailure(hr, "Failed to resize Addon code array"); 170 ExitOnFailure(hr, "Failed to resize Addon code array");
@@ -173,7 +173,7 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
173 sczCode = NULL; 173 sczCode = NULL;
174 *pcAddonCodes += 1; 174 *pcAddonCodes += 1;
175 } 175 }
176 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczAction, -1, L"Patch", -1)) 176 else if (CSTR_EQUAL == ::CompareStringOrdinal(sczAction, -1, L"Patch", -1, FALSE))
177 { 177 {
178 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczPatchCodes), *pcPatchCodes, 1, sizeof(LPWSTR), 5); 178 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczPatchCodes), *pcPatchCodes, 1, sizeof(LPWSTR), 5);
179 ExitOnFailure(hr, "Failed to resize Patch code array"); 179 ExitOnFailure(hr, "Failed to resize Patch code array");
@@ -686,7 +686,7 @@ static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback(
686 BOOTSTRAPPER_RELATION_TYPE relationType = RelatedBundleConvertRelationType(pBundle->relationType); 686 BOOTSTRAPPER_RELATION_TYPE relationType = RelatedBundleConvertRelationType(pBundle->relationType);
687 BOOL fPerMachine = BUNDLE_INSTALL_CONTEXT_MACHINE == pBundle->installContext; 687 BOOL fPerMachine = BUNDLE_INSTALL_CONTEXT_MACHINE == pBundle->installContext;
688 688
689 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pBundle->wzBundleCode, -1, pPackage->Bundle.sczBundleCode, -1) && 689 if (CSTR_EQUAL == ::CompareStringOrdinal(pBundle->wzBundleCode, -1, pPackage->Bundle.sczBundleCode, -1, TRUE) &&
690 pPackage->Bundle.fWin64 == (REG_KEY_64BIT == pBundle->regBitness)) 690 pPackage->Bundle.fWin64 == (REG_KEY_64BIT == pBundle->regBitness))
691 { 691 {
692 Assert(BOOTSTRAPPER_RELATION_UPGRADE == relationType); 692 Assert(BOOTSTRAPPER_RELATION_UPGRADE == relationType);
@@ -817,7 +817,7 @@ static HRESULT ExecuteBundle(
817 817
818 if (pPackage->fPerMachine) 818 if (pPackage->fPerMachine)
819 { 819 {
820 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath); 820 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath, argcArp - 1, (argcArp > 1) ? const_cast<LPCWSTR*>(argvArp + 1) : NULL);
821 ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath); 821 ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath);
822 if (S_FALSE == hr) 822 if (S_FALSE == hr)
823 { 823 {
@@ -940,7 +940,7 @@ static HRESULT ExecuteBundle(
940 940
941 if (wzRelationTypeCommandLine) 941 if (wzRelationTypeCommandLine)
942 { 942 {
943 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", wzRelationTypeCommandLine); 943 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -quiet -%ls", wzRelationTypeCommandLine);
944 ExitOnFailure(hr, "Failed to append relation type argument."); 944 ExitOnFailure(hr, "Failed to append relation type argument.");
945 } 945 }
946 946
diff --git a/src/burn/engine/burnextension.cpp b/src/burn/engine/burnextension.cpp
index 536dbcc9..50657f32 100644
--- a/src/burn/engine/burnextension.cpp
+++ b/src/burn/engine/burnextension.cpp
@@ -214,7 +214,7 @@ EXTERN_C HRESULT BurnExtensionFindById(
214 { 214 {
215 pExtension = &pBurnExtensions->rgExtensions[i]; 215 pExtension = &pBurnExtensions->rgExtensions[i];
216 216
217 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pExtension->sczId, -1, wzId, -1)) 217 if (CSTR_EQUAL == ::CompareStringOrdinal(pExtension->sczId, -1, wzId, -1, FALSE))
218 { 218 {
219 *ppExtension = pExtension; 219 *ppExtension = pExtension;
220 ExitFunction1(hr = S_OK); 220 ExitFunction1(hr = S_OK);
diff --git a/src/burn/engine/burnpipe.cpp b/src/burn/engine/burnpipe.cpp
index 25d602b1..ec85822e 100644
--- a/src/burn/engine/burnpipe.cpp
+++ b/src/burn/engine/burnpipe.cpp
@@ -515,7 +515,7 @@ static HRESULT ChildPipeConnected(
515 ExitOnFailure(hr, "Failed to read verification secret from parent pipe."); 515 ExitOnFailure(hr, "Failed to read verification secret from parent pipe.");
516 516
517 // Verify the secrets match. 517 // Verify the secrets match.
518 if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, 0, sczVerificationSecret, -1, wzSecret, -1)) 518 if (CSTR_EQUAL != ::CompareStringOrdinal(sczVerificationSecret, -1, wzSecret, -1, FALSE))
519 { 519 {
520 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 520 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
521 ExitOnRootFailure(hr, "Verification secret from parent does not match."); 521 ExitOnRootFailure(hr, "Verification secret from parent does not match.");
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index 16db4a81..f5df6500 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -260,6 +260,9 @@ extern "C" HRESULT CacheInitializeSources(
260 hr = PathForCurrentProcess(&sczCurrentPath, NULL); 260 hr = PathForCurrentProcess(&sczCurrentPath, NULL);
261 ExitOnFailure(hr, "Failed to get current process path."); 261 ExitOnFailure(hr, "Failed to get current process path.");
262 262
263 hr = VariableSetString(pVariables, BURN_BUNDLE_SOURCE_PROCESS_PATH, sczCurrentPath, FALSE, FALSE);
264 ExitOnFailure(hr, "Failed to set %ls variable.", BURN_BUNDLE_SOURCE_PROCESS_PATH);
265
263 // Determine if we are running from the package cache or not. 266 // Determine if we are running from the package cache or not.
264 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczCode, &sczCompletedFolder); 267 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczCode, &sczCompletedFolder);
265 ExitOnFailure(hr, "Failed to get completed path for bundle."); 268 ExitOnFailure(hr, "Failed to get completed path for bundle.");
@@ -275,6 +278,9 @@ extern "C" HRESULT CacheInitializeSources(
275 hr = PathGetDirectory(sczCurrentPath, &pCache->sczSourceProcessFolder); 278 hr = PathGetDirectory(sczCurrentPath, &pCache->sczSourceProcessFolder);
276 ExitOnFailure(hr, "Failed to initialize cache source folder."); 279 ExitOnFailure(hr, "Failed to initialize cache source folder.");
277 280
281 hr = VariableSetString(pVariables, BURN_BUNDLE_SOURCE_PROCESS_FOLDER, pCache->sczSourceProcessFolder, FALSE, FALSE);
282 ExitOnFailure(hr, "Failed to set %ls variable.", BURN_BUNDLE_SOURCE_PROCESS_FOLDER);
283
278 // If we're not running from the cache, ensure the original source is set. 284 // If we're not running from the cache, ensure the original source is set.
279 if (!pCache->fRunningFromCache) 285 if (!pCache->fRunningFromCache)
280 { 286 {
@@ -613,8 +619,8 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
613 619
614 hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder); 620 hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder);
615 fPreferSourcePathLocation = !pCache->fRunningFromCache || FAILED(hr); 621 fPreferSourcePathLocation = !pCache->fRunningFromCache || FAILED(hr);
616 fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCache->sczSourceProcessFolder, -1, sczLastSourceFolder, -1); 622 fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringOrdinal(pCache->sczSourceProcessFolder, -1, sczLastSourceFolder, -1, TRUE);
617 fTryRelativePath = CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzSourcePath, -1, wzRelativePath, -1); 623 fTryRelativePath = CSTR_EQUAL != ::CompareStringOrdinal(wzSourcePath, -1, wzRelativePath, -1, TRUE);
618 fSourceIsAbsolute = PathIsRooted(wzSourcePath); 624 fSourceIsAbsolute = PathIsRooted(wzSourcePath);
619 625
620 // If the source path provided is a full path, try that first. 626 // If the source path provided is a full path, try that first.
@@ -791,7 +797,7 @@ extern "C" HRESULT CacheSetLastUsedSource(
791 797
792 // If the source path ends with the relative path then this source could be a new path. 798 // If the source path ends with the relative path then this source could be a new path.
793 iSourceRelativePath = cchSourcePath - cchRelativePath; 799 iSourceRelativePath = cchSourcePath - cchRelativePath;
794 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzSourcePath + iSourceRelativePath, -1, wzRelativePath, -1)) 800 if (CSTR_EQUAL == ::CompareStringOrdinal(wzSourcePath + iSourceRelativePath, -1, wzRelativePath, -1, TRUE))
795 { 801 {
796 hr = StrAllocString(&sczSourceFolder, wzSourcePath, iSourceRelativePath); 802 hr = StrAllocString(&sczSourceFolder, wzSourcePath, iSourceRelativePath);
797 ExitOnFailure(hr, "Failed to trim source folder."); 803 ExitOnFailure(hr, "Failed to trim source folder.");
@@ -799,7 +805,7 @@ extern "C" HRESULT CacheSetLastUsedSource(
799 hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, &sczLastSourceFolder); 805 hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, &sczLastSourceFolder);
800 if (SUCCEEDED(hr)) 806 if (SUCCEEDED(hr))
801 { 807 {
802 nCompare = ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, sczSourceFolder, -1, sczLastSourceFolder, -1); 808 nCompare = ::CompareStringOrdinal(sczSourceFolder, -1, sczLastSourceFolder, -1, TRUE);
803 } 809 }
804 else if (E_NOTFOUND == hr) 810 else if (E_NOTFOUND == hr)
805 { 811 {
@@ -1025,7 +1031,7 @@ extern "C" HRESULT CacheCompleteBundle(
1025 ExitOnFailure(hr, "Failed to combine completed path with engine file name."); 1031 ExitOnFailure(hr, "Failed to combine completed path with engine file name.");
1026 1032
1027 // We can't just use wzExecutablePath because we needed to call CreateCompletedPath to ensure that the destination was secured. 1033 // We can't just use wzExecutablePath because we needed to call CreateCompletedPath to ensure that the destination was secured.
1028 Assert(CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzExecutablePath, -1, sczTargetPath, -1)); 1034 Assert(CSTR_EQUAL == ::CompareStringOrdinal(wzExecutablePath, -1, sczTargetPath, -1, TRUE));
1029 1035
1030 // If the bundle is running out of the package cache then we don't need to copy it there 1036 // If the bundle is running out of the package cache then we don't need to copy it there
1031 // (and don't want to since it'll be in use) so bail. 1037 // (and don't want to since it'll be in use) so bail.
diff --git a/src/burn/engine/condition.cpp b/src/burn/engine/condition.cpp
index 8fa62f16..3719ce79 100644
--- a/src/burn/engine/condition.cpp
+++ b/src/burn/engine/condition.cpp
@@ -740,17 +740,17 @@ static HRESULT NextSymbol(
740 ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType); 740 ::GetStringTypeW(CT_CTYPE1, &pContext->wzRead[n], 1, &charType);
741 } while (C1_ALPHA & charType || C1_DIGIT & charType || L'_' == pContext->wzRead[n]); 741 } while (C1_ALPHA & charType || C1_DIGIT & charType || L'_' == pContext->wzRead[n]);
742 742
743 if (2 == n && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pContext->wzRead, 2, L"OR", 2)) 743 if (2 == n && CSTR_EQUAL == ::CompareStringOrdinal(pContext->wzRead, 2, L"OR", 2, TRUE))
744 { 744 {
745 // OR 745 // OR
746 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_OR; 746 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_OR;
747 } 747 }
748 else if (3 == n && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pContext->wzRead, 3, L"AND", 3)) 748 else if (3 == n && CSTR_EQUAL == ::CompareStringOrdinal(pContext->wzRead, 3, L"AND", 3, TRUE))
749 { 749 {
750 // AND 750 // AND
751 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_AND; 751 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_AND;
752 } 752 }
753 else if (3 == n && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pContext->wzRead, 3, L"NOT", 3)) 753 else if (3 == n && CSTR_EQUAL == ::CompareStringOrdinal(pContext->wzRead, 3, L"NOT", 3, TRUE))
754 { 754 {
755 // NOT 755 // NOT
756 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_NOT; 756 pContext->NextSymbol.Type = BURN_SYMBOL_TYPE_NOT;
@@ -928,7 +928,7 @@ static HRESULT CompareStringValues(
928 ) 928 )
929{ 929{
930 HRESULT hr = S_OK; 930 HRESULT hr = S_OK;
931 DWORD dwCompareString = (comparison & INSENSITIVE) ? NORM_IGNORECASE : 0; 931 BOOL fIgnoreCase = (comparison & INSENSITIVE) ? TRUE : FALSE;
932 size_t cchLeftSize = 0; 932 size_t cchLeftSize = 0;
933 size_t cchRightSize = 0; 933 size_t cchRightSize = 0;
934 int cchLeft = 0; 934 int cchLeft = 0;
@@ -958,7 +958,7 @@ static HRESULT CompareStringValues(
958 case BURN_SYMBOL_TYPE_EQ_I: 958 case BURN_SYMBOL_TYPE_EQ_I:
959 case BURN_SYMBOL_TYPE_NE_I: 959 case BURN_SYMBOL_TYPE_NE_I:
960 { 960 {
961 int i = ::CompareStringW(LOCALE_INVARIANT, dwCompareString, wzLeftOperand, cchLeft, wzRightOperand, cchRight); 961 int i = ::CompareStringOrdinal(wzLeftOperand, cchLeft, wzRightOperand, cchRight, fIgnoreCase);
962 hr = CompareIntegerValues(comparison, i, CSTR_EQUAL, pfResult); 962 hr = CompareIntegerValues(comparison, i, CSTR_EQUAL, pfResult);
963 } 963 }
964 break; 964 break;
@@ -967,7 +967,7 @@ static HRESULT CompareStringValues(
967 // test if left string contains right string 967 // test if left string contains right string
968 for (int i = 0; (i + cchRight) <= cchLeft; ++i) 968 for (int i = 0; (i + cchRight) <= cchLeft; ++i)
969 { 969 {
970 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, dwCompareString, wzLeftOperand + i, cchRight, wzRightOperand, cchRight)) 970 if (CSTR_EQUAL == ::CompareStringOrdinal(wzLeftOperand + i, cchRight, wzRightOperand, cchRight, fIgnoreCase))
971 { 971 {
972 *pfResult = TRUE; 972 *pfResult = TRUE;
973 ExitFunction(); 973 ExitFunction();
@@ -978,12 +978,12 @@ static HRESULT CompareStringValues(
978 case BURN_SYMBOL_TYPE_HIEQ: 978 case BURN_SYMBOL_TYPE_HIEQ:
979 case BURN_SYMBOL_TYPE_HIEQ_I: 979 case BURN_SYMBOL_TYPE_HIEQ_I:
980 // test if left string starts with right string 980 // test if left string starts with right string
981 *pfResult = cchLeft >= cchRight && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, dwCompareString, wzLeftOperand, cchRight, wzRightOperand, cchRight); 981 *pfResult = cchLeft >= cchRight && CSTR_EQUAL == ::CompareStringOrdinal(wzLeftOperand, cchRight, wzRightOperand, cchRight, fIgnoreCase);
982 break; 982 break;
983 case BURN_SYMBOL_TYPE_LOEQ: 983 case BURN_SYMBOL_TYPE_LOEQ:
984 case BURN_SYMBOL_TYPE_LOEQ_I: 984 case BURN_SYMBOL_TYPE_LOEQ_I:
985 // test if left string ends with right string 985 // test if left string ends with right string
986 *pfResult = cchLeft >= cchRight && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, dwCompareString, wzLeftOperand + (cchLeft - cchRight), cchRight, wzRightOperand, cchRight); 986 *pfResult = cchLeft >= cchRight && CSTR_EQUAL == ::CompareStringOrdinal(wzLeftOperand + (cchLeft - cchRight), cchRight, wzRightOperand, cchRight, fIgnoreCase);
987 break; 987 break;
988 default: 988 default:
989 ExitFunction1(hr = E_INVALIDARG); 989 ExitFunction1(hr = E_INVALIDARG);
diff --git a/src/burn/engine/container.cpp b/src/burn/engine/container.cpp
index fad010cf..41ab0919 100644
--- a/src/burn/engine/container.cpp
+++ b/src/burn/engine/container.cpp
@@ -400,7 +400,7 @@ extern "C" HRESULT ContainerFindById(
400 { 400 {
401 pContainer = &pContainers->rgContainers[i]; 401 pContainer = &pContainers->rgContainers[i];
402 402
403 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pContainer->sczId, -1, wzId, -1)) 403 if (CSTR_EQUAL == ::CompareStringOrdinal(pContainer->sczId, -1, wzId, -1, FALSE))
404 { 404 {
405 *ppContainer = pContainer; 405 *ppContainer = pContainer;
406 ExitFunction1(hr = S_OK); 406 ExitFunction1(hr = S_OK);
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index b20f7f0c..de202321 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -1215,8 +1215,8 @@ HRESULT CoreAppendLogToCommandLine(
1215 if (rgszArgs[i][0] == L'-' || rgszArgs[i][0] == L'/') 1215 if (rgszArgs[i][0] == L'-' || rgszArgs[i][0] == L'/')
1216 { 1216 {
1217 // Now looking for 'log' or 'l' 1217 // Now looking for 'log' or 'l'
1218 if ((CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &rgszArgs[i][1], -1, L"log", -1)) 1218 if ((CSTR_EQUAL == ::CompareStringOrdinal(&rgszArgs[i][1], -1, L"log", -1, TRUE))
1219 || (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &rgszArgs[i][1], -1, L"l", -1))) 1219 || (CSTR_EQUAL == ::CompareStringOrdinal(&rgszArgs[i][1], -1, L"l", -1, TRUE)))
1220 { 1220 {
1221 ExitFunction1(hr = S_FALSE); 1221 ExitFunction1(hr = S_FALSE);
1222 } 1222 }
@@ -1360,13 +1360,13 @@ extern "C" HRESULT CoreParseCommandLine(
1360 1360
1361 if (argv[i][0] == L'-' || argv[i][0] == L'/') 1361 if (argv[i][0] == L'-' || argv[i][0] == L'/')
1362 { 1362 {
1363 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"l", -1) || 1363 if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"l", -1, TRUE) ||
1364 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"log", -1) || 1364 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"log", -1, TRUE) ||
1365 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"xlog", -1)) 1365 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"xlog", -1, TRUE))
1366 { 1366 {
1367 pInternalCommand->dwLoggingAttributes &= ~BURN_LOGGING_ATTRIBUTE_APPEND; 1367 pInternalCommand->dwLoggingAttributes &= ~BURN_LOGGING_ATTRIBUTE_APPEND;
1368 1368
1369 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], 1, L"x", 1)) 1369 if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], 1, L"x", 1, TRUE))
1370 { 1370 {
1371 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_VERBOSE | BURN_LOGGING_ATTRIBUTE_EXTRADEBUG; 1371 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_VERBOSE | BURN_LOGGING_ATTRIBUTE_EXTRADEBUG;
1372 } 1372 }
@@ -1382,24 +1382,24 @@ extern "C" HRESULT CoreParseCommandLine(
1382 hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH); 1382 hr = PathExpand(&pInternalCommand->sczLogFile, argv[i], PATH_EXPAND_FULLPATH);
1383 ExitOnFailure(hr, "Failed to copy log file path."); 1383 ExitOnFailure(hr, "Failed to copy log file path.");
1384 } 1384 }
1385 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"?", -1) || 1385 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"?", -1, TRUE) ||
1386 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"h", -1) || 1386 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"h", -1, TRUE) ||
1387 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"help", -1)) 1387 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"help", -1, TRUE))
1388 { 1388 {
1389 pCommand->action = BOOTSTRAPPER_ACTION_HELP; 1389 pCommand->action = BOOTSTRAPPER_ACTION_HELP;
1390 } 1390 }
1391 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"q", -1) || 1391 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"q", -1, TRUE) ||
1392 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"quiet", -1) || 1392 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"quiet", -1, TRUE) ||
1393 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"s", -1) || 1393 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"s", -1, TRUE) ||
1394 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"silent", -1)) 1394 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"silent", -1, TRUE))
1395 { 1395 {
1396 pCommand->display = BOOTSTRAPPER_DISPLAY_NONE; 1396 pCommand->display = BOOTSTRAPPER_DISPLAY_NONE;
1397 } 1397 }
1398 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"passive", -1)) 1398 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"passive", -1, TRUE))
1399 { 1399 {
1400 pCommand->display = BOOTSTRAPPER_DISPLAY_PASSIVE; 1400 pCommand->display = BOOTSTRAPPER_DISPLAY_PASSIVE;
1401 } 1401 }
1402 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"layout", -1)) 1402 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"layout", -1, TRUE))
1403 { 1403 {
1404 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) 1404 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action)
1405 { 1405 {
@@ -1415,47 +1415,47 @@ extern "C" HRESULT CoreParseCommandLine(
1415 ExitOnFailure(hr, "Failed to copy path for layout directory."); 1415 ExitOnFailure(hr, "Failed to copy path for layout directory.");
1416 } 1416 }
1417 } 1417 }
1418 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"unsafeuninstall", -1)) 1418 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"unsafeuninstall", -1, TRUE))
1419 { 1419 {
1420 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) 1420 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action)
1421 { 1421 {
1422 pCommand->action = BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL; 1422 pCommand->action = BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL;
1423 } 1423 }
1424 } 1424 }
1425 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"uninstall", -1)) 1425 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"uninstall", -1, TRUE))
1426 { 1426 {
1427 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) 1427 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action)
1428 { 1428 {
1429 pCommand->action = BOOTSTRAPPER_ACTION_UNINSTALL; 1429 pCommand->action = BOOTSTRAPPER_ACTION_UNINSTALL;
1430 } 1430 }
1431 } 1431 }
1432 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"repair", -1)) 1432 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"repair", -1, TRUE))
1433 { 1433 {
1434 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) 1434 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action)
1435 { 1435 {
1436 pCommand->action = BOOTSTRAPPER_ACTION_REPAIR; 1436 pCommand->action = BOOTSTRAPPER_ACTION_REPAIR;
1437 } 1437 }
1438 } 1438 }
1439 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"modify", -1)) 1439 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"modify", -1, TRUE))
1440 { 1440 {
1441 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) 1441 if (BOOTSTRAPPER_ACTION_HELP != pCommand->action)
1442 { 1442 {
1443 pCommand->action = BOOTSTRAPPER_ACTION_MODIFY; 1443 pCommand->action = BOOTSTRAPPER_ACTION_MODIFY;
1444 } 1444 }
1445 } 1445 }
1446 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"package", -1) || 1446 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"package", -1, TRUE) ||
1447 CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"update", -1)) 1447 CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"update", -1, TRUE))
1448 { 1448 {
1449 if (BOOTSTRAPPER_ACTION_UNKNOWN == pCommand->action) 1449 if (BOOTSTRAPPER_ACTION_UNKNOWN == pCommand->action)
1450 { 1450 {
1451 pCommand->action = BOOTSTRAPPER_ACTION_INSTALL; 1451 pCommand->action = BOOTSTRAPPER_ACTION_INSTALL;
1452 } 1452 }
1453 } 1453 }
1454 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"noaupause", -1)) 1454 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"noaupause", -1, TRUE))
1455 { 1455 {
1456 pInternalCommand->automaticUpdates = BURN_AU_PAUSE_ACTION_NONE; 1456 pInternalCommand->automaticUpdates = BURN_AU_PAUSE_ACTION_NONE;
1457 } 1457 }
1458 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"keepaupaused", -1)) 1458 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"keepaupaused", -1, TRUE))
1459 { 1459 {
1460 // Switch /noaupause takes precedence. 1460 // Switch /noaupause takes precedence.
1461 if (BURN_AU_PAUSE_ACTION_NONE != pInternalCommand->automaticUpdates) 1461 if (BURN_AU_PAUSE_ACTION_NONE != pInternalCommand->automaticUpdates)
@@ -1463,11 +1463,11 @@ extern "C" HRESULT CoreParseCommandLine(
1463 pInternalCommand->automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED_NORESUME; 1463 pInternalCommand->automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED_NORESUME;
1464 } 1464 }
1465 } 1465 }
1466 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"disablesystemrestore", -1)) 1466 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"disablesystemrestore", -1, TRUE))
1467 { 1467 {
1468 pInternalCommand->fDisableSystemRestore = TRUE; 1468 pInternalCommand->fDisableSystemRestore = TRUE;
1469 } 1469 }
1470 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"originalsource", -1)) 1470 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"originalsource", -1, TRUE))
1471 { 1471 {
1472 if (i + 1 >= argc) 1472 if (i + 1 >= argc)
1473 { 1473 {
@@ -1479,7 +1479,7 @@ extern "C" HRESULT CoreParseCommandLine(
1479 hr = PathExpand(&pInternalCommand->sczOriginalSource, argv[i], PATH_EXPAND_FULLPATH); 1479 hr = PathExpand(&pInternalCommand->sczOriginalSource, argv[i], PATH_EXPAND_FULLPATH);
1480 ExitOnFailure(hr, "Failed to copy last used source."); 1480 ExitOnFailure(hr, "Failed to copy last used source.");
1481 } 1481 }
1482 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT, -1)) 1482 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT, -1, TRUE))
1483 { 1483 {
1484 if (i + 1 >= argc) 1484 if (i + 1 >= argc)
1485 { 1485 {
@@ -1492,12 +1492,12 @@ extern "C" HRESULT CoreParseCommandLine(
1492 hr = StrAllocString(&pInternalCommand->sczActiveParent, argv[i], 0); 1492 hr = StrAllocString(&pInternalCommand->sczActiveParent, argv[i], 0);
1493 ExitOnFailure(hr, "Failed to copy parent."); 1493 ExitOnFailure(hr, "Failed to copy parent.");
1494 } 1494 }
1495 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT_NONE, -1)) 1495 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PARENT_NONE, -1, TRUE))
1496 { 1496 {
1497 hr = StrAllocString(&pInternalCommand->sczActiveParent, L"", 0); 1497 hr = StrAllocString(&pInternalCommand->sczActiveParent, L"", 0);
1498 ExitOnFailure(hr, "Failed to initialize parent to none."); 1498 ExitOnFailure(hr, "Failed to initialize parent to none.");
1499 } 1499 }
1500 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_LOG_APPEND, -1)) 1500 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_LOG_APPEND, -1, TRUE))
1501 { 1501 {
1502 if (i + 1 >= argc) 1502 if (i + 1 >= argc)
1503 { 1503 {
@@ -1512,7 +1512,7 @@ extern "C" HRESULT CoreParseCommandLine(
1512 1512
1513 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND; 1513 pInternalCommand->dwLoggingAttributes |= BURN_LOGGING_ATTRIBUTE_APPEND;
1514 } 1514 }
1515 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_LOG_MODE), BURN_COMMANDLINE_SWITCH_LOG_MODE, -1)) 1515 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_LOG_MODE), BURN_COMMANDLINE_SWITCH_LOG_MODE, -1, TRUE))
1516 { 1516 {
1517 // Get a pointer to the next character after the switch. 1517 // Get a pointer to the next character after the switch.
1518 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_LOG_MODE)]; 1518 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_LOG_MODE)];
@@ -1541,7 +1541,7 @@ extern "C" HRESULT CoreParseCommandLine(
1541 } 1541 }
1542 } 1542 }
1543 } 1543 }
1544 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_ELEVATED, -1)) 1544 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_ELEVATED, -1, TRUE))
1545 { 1545 {
1546 if (i + 3 >= argc) 1546 if (i + 3 >= argc)
1547 { 1547 {
@@ -1579,7 +1579,7 @@ extern "C" HRESULT CoreParseCommandLine(
1579 1579
1580 i += 2; 1580 i += 2;
1581 } 1581 }
1582 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT), BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT, lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT))) 1582 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT), BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT, lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT), TRUE))
1583 { 1583 {
1584 // Get a pointer to the next character after the switch. 1584 // Get a pointer to the next character after the switch.
1585 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT)]; 1585 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT)];
@@ -1602,7 +1602,7 @@ extern "C" HRESULT CoreParseCommandLine(
1602 pInternalCommand->fArpSystemComponent = TRUE; 1602 pInternalCommand->fArpSystemComponent = TRUE;
1603 } 1603 }
1604 } 1604 }
1605 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED, -1)) 1605 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED, -1, TRUE))
1606 { 1606 {
1607 if (i + 3 >= argc) 1607 if (i + 3 >= argc)
1608 { 1608 {
@@ -1633,59 +1633,59 @@ extern "C" HRESULT CoreParseCommandLine(
1633 1633
1634 i += 2; 1634 i += 2;
1635 } 1635 }
1636 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DETECT, -1)) 1636 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DETECT, -1, TRUE))
1637 { 1637 {
1638 pCommand->relationType = BOOTSTRAPPER_RELATION_DETECT; 1638 pCommand->relationType = BOOTSTRAPPER_RELATION_DETECT;
1639 1639
1640 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1640 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1641 } 1641 }
1642 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UPGRADE, -1)) 1642 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UPGRADE, -1, TRUE))
1643 { 1643 {
1644 pCommand->relationType = BOOTSTRAPPER_RELATION_UPGRADE; 1644 pCommand->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1645 1645
1646 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1646 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1647 } 1647 }
1648 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_ADDON, -1)) 1648 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_ADDON, -1, TRUE))
1649 { 1649 {
1650 pCommand->relationType = BOOTSTRAPPER_RELATION_ADDON; 1650 pCommand->relationType = BOOTSTRAPPER_RELATION_ADDON;
1651 1651
1652 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1652 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1653 } 1653 }
1654 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_ADDON, -1)) 1654 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_ADDON, -1, TRUE))
1655 { 1655 {
1656 pCommand->relationType = BOOTSTRAPPER_RELATION_DEPENDENT_ADDON; 1656 pCommand->relationType = BOOTSTRAPPER_RELATION_DEPENDENT_ADDON;
1657 1657
1658 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1658 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1659 } 1659 }
1660 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_PATCH, -1)) 1660 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_PATCH, -1, TRUE))
1661 { 1661 {
1662 pCommand->relationType = BOOTSTRAPPER_RELATION_PATCH; 1662 pCommand->relationType = BOOTSTRAPPER_RELATION_PATCH;
1663 1663
1664 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1664 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1665 } 1665 }
1666 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH, -1)) 1666 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH, -1, TRUE))
1667 { 1667 {
1668 pCommand->relationType = BOOTSTRAPPER_RELATION_DEPENDENT_PATCH; 1668 pCommand->relationType = BOOTSTRAPPER_RELATION_DEPENDENT_PATCH;
1669 1669
1670 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1670 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1671 } 1671 }
1672 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UPDATE, -1)) 1672 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UPDATE, -1, TRUE))
1673 { 1673 {
1674 pCommand->relationType = BOOTSTRAPPER_RELATION_UPDATE; 1674 pCommand->relationType = BOOTSTRAPPER_RELATION_UPDATE;
1675 1675
1676 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1676 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1677 } 1677 }
1678 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE, -1)) 1678 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE, -1, TRUE))
1679 { 1679 {
1680 pCommand->relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE; 1680 pCommand->relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE;
1681 1681
1682 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType)); 1682 LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1683 } 1683 }
1684 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PASSTHROUGH, -1)) 1684 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_PASSTHROUGH, -1, TRUE))
1685 { 1685 {
1686 pCommand->fPassthrough = TRUE; 1686 pCommand->fPassthrough = TRUE;
1687 } 1687 }
1688 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RUNONCE, -1)) 1688 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RUNONCE, -1, TRUE))
1689 { 1689 {
1690 switch (pInternalCommand->mode) 1690 switch (pInternalCommand->mode)
1691 { 1691 {
@@ -1698,7 +1698,7 @@ extern "C" HRESULT CoreParseCommandLine(
1698 TraceLog(E_INVALIDARG, "Multiple mode command-line switches were provided."); 1698 TraceLog(E_INVALIDARG, "Multiple mode command-line switches were provided.");
1699 } 1699 }
1700 } 1700 }
1701 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES), BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES))) 1701 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES), BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES), TRUE))
1702 { 1702 {
1703 // Get a pointer to the next character after the switch. 1703 // Get a pointer to the next character after the switch.
1704 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES)]; 1704 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES)];
@@ -1713,7 +1713,7 @@ extern "C" HRESULT CoreParseCommandLine(
1713 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); 1713 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
1714 } 1714 }
1715 } 1715 }
1716 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS), BURN_COMMANDLINE_SWITCH_ANCESTORS, lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS))) 1716 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS), BURN_COMMANDLINE_SWITCH_ANCESTORS, lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS), TRUE))
1717 { 1717 {
1718 // Get a pointer to the next character after the switch. 1718 // Get a pointer to the next character after the switch.
1719 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS)]; 1719 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_ANCESTORS)];
@@ -1728,7 +1728,7 @@ extern "C" HRESULT CoreParseCommandLine(
1728 ExitOnFailure(hr, "Failed to allocate the list of ancestors."); 1728 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
1729 } 1729 }
1730 } 1730 }
1731 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY), BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY, lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY))) 1731 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY), BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY, lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY), TRUE))
1732 { 1732 {
1733 // Get a pointer to the next character after the switch. 1733 // Get a pointer to the next character after the switch.
1734 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY)]; 1734 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_WORKING_DIRECTORY)];
@@ -1743,7 +1743,7 @@ extern "C" HRESULT CoreParseCommandLine(
1743 ExitOnFailure(hr, "Failed to store the custom working directory."); 1743 ExitOnFailure(hr, "Failed to store the custom working directory.");
1744 } 1744 }
1745 } 1745 }
1746 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED))) 1746 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED), TRUE))
1747 { 1747 {
1748 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED)]; 1748 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED)];
1749 if (L'=' != wzParam[-1] || L'\0' == wzParam[0]) 1749 if (L'=' != wzParam[-1] || L'\0' == wzParam[0])
@@ -1765,7 +1765,7 @@ extern "C" HRESULT CoreParseCommandLine(
1765 } 1765 }
1766 } 1766 }
1767 } 1767 }
1768 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF), BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF))) 1768 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF), BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF, lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF), TRUE))
1769 { 1769 {
1770 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF)]; 1770 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF)];
1771 if (L'=' != wzParam[-1] || L'\0' == wzParam[0]) 1771 if (L'=' != wzParam[-1] || L'\0' == wzParam[0])
@@ -1787,7 +1787,7 @@ extern "C" HRESULT CoreParseCommandLine(
1787 } 1787 }
1788 } 1788 }
1789 } 1789 }
1790 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN), BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN, lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN))) 1790 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN), BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN, lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN), TRUE))
1791 { 1791 {
1792 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN)]; 1792 LPCWSTR wzParam = &argv[i][2 + lstrlenW(BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN)];
1793 if (L'=' != wzParam[-1] || L'\0' == wzParam[0]) 1793 if (L'=' != wzParam[-1] || L'\0' == wzParam[0])
@@ -1809,7 +1809,7 @@ extern "C" HRESULT CoreParseCommandLine(
1809 } 1809 }
1810 } 1810 }
1811 } 1811 }
1812 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX), BURN_COMMANDLINE_SWITCH_PREFIX, lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX))) 1812 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX), BURN_COMMANDLINE_SWITCH_PREFIX, lstrlenW(BURN_COMMANDLINE_SWITCH_PREFIX), TRUE))
1813 { 1813 {
1814 // Skip (but log) any other private burn switches we don't recognize, so that 1814 // Skip (but log) any other private burn switches we don't recognize, so that
1815 // adding future private variables doesn't break old bundles 1815 // adding future private variables doesn't break old bundles
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index c5d0a370..cf615e35 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -46,6 +46,8 @@ const LPCWSTR BURN_BUNDLE_FORCED_RESTART_PACKAGE = L"WixBundleForcedRestartPacka
46const LPCWSTR BURN_BUNDLE_INSTALLED = L"WixBundleInstalled"; 46const LPCWSTR BURN_BUNDLE_INSTALLED = L"WixBundleInstalled";
47const LPCWSTR BURN_BUNDLE_ELEVATED = L"WixBundleElevated"; 47const LPCWSTR BURN_BUNDLE_ELEVATED = L"WixBundleElevated";
48const LPCWSTR BURN_BUNDLE_PROVIDER_KEY = L"WixBundleProviderKey"; 48const LPCWSTR BURN_BUNDLE_PROVIDER_KEY = L"WixBundleProviderKey";
49const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_PATH = L"WixBundleSourceProcessPath";
50const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_FOLDER = L"WixBundleSourceProcessFolder";
49const LPCWSTR BURN_BUNDLE_TAG = L"WixBundleTag"; 51const LPCWSTR BURN_BUNDLE_TAG = L"WixBundleTag";
50const LPCWSTR BURN_BUNDLE_UILEVEL = L"WixBundleUILevel"; 52const LPCWSTR BURN_BUNDLE_UILEVEL = L"WixBundleUILevel";
51const LPCWSTR BURN_BUNDLE_VERSION = L"WixBundleVersion"; 53const LPCWSTR BURN_BUNDLE_VERSION = L"WixBundleVersion";
diff --git a/src/burn/engine/dependency.cpp b/src/burn/engine/dependency.cpp
index f398a070..6f80c21b 100644
--- a/src/burn/engine/dependency.cpp
+++ b/src/burn/engine/dependency.cpp
@@ -263,7 +263,7 @@ extern "C" HRESULT DependencyDetectProviderKeyBundleCode(
263 hr = StrAllocString(&pRegistration->sczDetectedProviderKeyBundleCode, pRegistration->sczProviderKey, 0); 263 hr = StrAllocString(&pRegistration->sczDetectedProviderKeyBundleCode, pRegistration->sczProviderKey, 0);
264 ExitOnFailure(hr, "Failed to initialize provider key bundle code."); 264 ExitOnFailure(hr, "Failed to initialize provider key bundle code.");
265 } 265 }
266 else if (CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczCode, -1, pRegistration->sczDetectedProviderKeyBundleCode, -1)) 266 else if (CSTR_EQUAL != ::CompareStringOrdinal(pRegistration->sczCode, -1, pRegistration->sczDetectedProviderKeyBundleCode, -1, TRUE))
267 { 267 {
268 pRegistration->fDetectedForeignProviderKeyBundleCode = TRUE; 268 pRegistration->fDetectedForeignProviderKeyBundleCode = TRUE;
269 LogId(REPORT_STANDARD, MSG_DETECTED_FOREIGN_BUNDLE_PROVIDER_REGISTRATION, pRegistration->sczProviderKey, pRegistration->sczDetectedProviderKeyBundleCode); 269 LogId(REPORT_STANDARD, MSG_DETECTED_FOREIGN_BUNDLE_PROVIDER_REGISTRATION, pRegistration->sczProviderKey, pRegistration->sczDetectedProviderKeyBundleCode);
@@ -293,12 +293,12 @@ extern "C" HRESULT DependencyDetectBundle(
293 { 293 {
294 DEPENDENCY* pDependent = pRegistration->rgDependents + i; 294 DEPENDENCY* pDependent = pRegistration->rgDependents + i;
295 295
296 if (pDependencies->fActiveParent && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pDependencies->wzActiveParent, -1, pDependent->sczKey, -1)) 296 if (pDependencies->fActiveParent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzActiveParent, -1, pDependent->sczKey, -1, TRUE))
297 { 297 {
298 pRegistration->fParentRegisteredAsDependent = TRUE; 298 pRegistration->fParentRegisteredAsDependent = TRUE;
299 } 299 }
300 300
301 if (pDependencies->fSelfDependent && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pDependencies->wzSelfDependent, -1, pDependent->sczKey, -1)) 301 if (pDependencies->fSelfDependent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzSelfDependent, -1, pDependent->sczKey, -1, TRUE))
302 { 302 {
303 pRegistration->fSelfRegisteredAsDependent = TRUE; 303 pRegistration->fSelfRegisteredAsDependent = TRUE;
304 } 304 }
@@ -419,6 +419,7 @@ extern "C" HRESULT DependencyPlanPackageBegin(
419 STRINGDICT_HANDLE sdIgnoredDependents = NULL; 419 STRINGDICT_HANDLE sdIgnoredDependents = NULL;
420 BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE; 420 BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE;
421 BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE; 421 BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE;
422 BOOL fDependenciesForcedAbsent = FALSE;
422 BOOL fDependentBlocksUninstall = FALSE; 423 BOOL fDependentBlocksUninstall = FALSE;
423 BOOL fAttemptingUninstall = BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute || pPackage->compatiblePackage.fRemove; 424 BOOL fAttemptingUninstall = BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute || pPackage->compatiblePackage.fRemove;
424 425
@@ -467,7 +468,16 @@ extern "C" HRESULT DependencyPlanPackageBegin(
467 { 468 {
468 hr = S_OK; 469 hr = S_OK;
469 470
470 if (!fDependentBlocksUninstall) 471 if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested)
472 {
473 if (!fDependenciesForcedAbsent)
474 {
475 fDependenciesForcedAbsent = TRUE;
476
477 LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_DEPENDENTS_OVERRIDDEN, pPackage->sczId);
478 }
479 }
480 else if (!fDependentBlocksUninstall)
471 { 481 {
472 fDependentBlocksUninstall = TRUE; 482 fDependentBlocksUninstall = TRUE;
473 483
@@ -905,7 +915,7 @@ extern "C" HRESULT DependencyDetectCompatibleEntry(
905 continue; 915 continue;
906 } 916 }
907 } 917 }
908 else if (sczId && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzPackageProviderId, -1, sczId, -1)) 918 else if (sczId && CSTR_EQUAL == ::CompareStringOrdinal(wzPackageProviderId, -1, sczId, -1, TRUE))
909 { 919 {
910 continue; 920 continue;
911 } 921 }
@@ -969,7 +979,7 @@ static HRESULT DetectPackageDependents(
969 { 979 {
970 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent; 980 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent;
971 981
972 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczCode, -1, pDependent->sczKey, -1)) 982 if (CSTR_EQUAL == ::CompareStringOrdinal(pRegistration->sczCode, -1, pDependent->sczKey, -1, TRUE))
973 { 983 {
974 pProvider->fBundleRegisteredAsDependent = TRUE; 984 pProvider->fBundleRegisteredAsDependent = TRUE;
975 fBundleRegisteredAsDependent = TRUE; 985 fBundleRegisteredAsDependent = TRUE;
@@ -1043,7 +1053,7 @@ static HRESULT SplitIgnoreDependencies(
1043 hr = DictAddKey(sdIgnoreDependencies, wzToken); 1053 hr = DictAddKey(sdIgnoreDependencies, wzToken);
1044 ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", wzToken); 1054 ExitOnFailure(hr, "Failed to add \"%ls\" to the string dictionary.", wzToken);
1045 1055
1046 if (!*pfIgnoreAll && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, L"ALL", -1, wzToken, -1)) 1056 if (!*pfIgnoreAll && CSTR_EQUAL == ::CompareStringOrdinal(L"ALL", -1, wzToken, -1, TRUE))
1047 { 1057 {
1048 *pfIgnoreAll = TRUE; 1058 *pfIgnoreAll = TRUE;
1049 } 1059 }
diff --git a/src/burn/engine/detect.cpp b/src/burn/engine/detect.cpp
index 08f6b57c..c19d382c 100644
--- a/src/burn/engine/detect.cpp
+++ b/src/burn/engine/detect.cpp
@@ -130,7 +130,7 @@ extern "C" HRESULT DetectForwardCompatibleBundles(
130 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; 130 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
131 131
132 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->detectRelationType && 132 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->detectRelationType &&
133 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleCode, -1, pRelatedBundle->package.sczId, -1)) 133 CSTR_EQUAL == ::CompareStringOrdinal(pRegistration->sczDetectedProviderKeyBundleCode, -1, pRelatedBundle->package.sczId, -1, TRUE))
134 { 134 {
135 hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult); 135 hr = VerCompareParsedVersions(pRegistration->pVersion, pRelatedBundle->pVersion, &nCompareResult);
136 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion->sczVersion, pRelatedBundle->pVersion->sczVersion); 136 ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistration->pVersion->sczVersion, pRelatedBundle->pVersion->sczVersion);
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 90e9db01..aff05ae3 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -3380,7 +3380,7 @@ static HRESULT OnUninstallMsiCompatiblePackage(
3380 } 3380 }
3381 3381
3382 if (!sczCompatiblePackageId || !*sczCompatiblePackageId || 3382 if (!sczCompatiblePackageId || !*sczCompatiblePackageId ||
3383 CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1)) 3383 CSTR_EQUAL != ::CompareStringOrdinal(pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1, TRUE))
3384 { 3384 {
3385 ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId); 3385 ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId);
3386 } 3386 }
@@ -3792,7 +3792,7 @@ static HRESULT OnCleanCompatiblePackage(
3792 } 3792 }
3793 3793
3794 if (!sczCompatiblePackageId || !*sczCompatiblePackageId || 3794 if (!sczCompatiblePackageId || !*sczCompatiblePackageId ||
3795 CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1)) 3795 CSTR_EQUAL != ::CompareStringOrdinal(pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1, TRUE))
3796 { 3796 {
3797 ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId); 3797 ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId);
3798 } 3798 }
@@ -3876,7 +3876,7 @@ static HRESULT OnLaunchApprovedExe(
3876 hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); 3876 hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath);
3877 ExitOnFailure(hr, "Failed to read the value for the approved exe path."); 3877 ExitOnFailure(hr, "Failed to read the value for the approved exe path.");
3878 3878
3879 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath); 3879 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath, 0, NULL);
3880 ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); 3880 ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath);
3881 if (S_FALSE == hr) 3881 if (S_FALSE == hr)
3882 { 3882 {
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index c7a07385..776f7832 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -1282,3 +1282,9 @@ Language=English
1282Skipping MSI property '%1!ls!' because condition '%2!ls!' evaluates to %3!hs!. 1282Skipping MSI property '%1!ls!' because condition '%2!ls!' evaluates to %3!hs!.
1283. 1283.
1284 1284
1285MessageId=701
1286Severity=Warning
1287SymbolicName=MSG_DEPENDENCY_PACKAGE_DEPENDENTS_OVERRIDDEN
1288Language=English
1289BA requested to uninstall package: %1!ls!, despite dependents:
1290.
diff --git a/src/burn/engine/engine.vcxproj b/src/burn/engine/engine.vcxproj
index 249f8eef..98556ea6 100644
--- a/src/burn/engine/engine.vcxproj
+++ b/src/burn/engine/engine.vcxproj
@@ -1,7 +1,7 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 4<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <ItemGroup Label="ProjectConfigurations"> 5 <ItemGroup Label="ProjectConfigurations">
6 <ProjectConfiguration Include="Debug|Win32"> 6 <ProjectConfiguration Include="Debug|Win32">
7 <Configuration>Debug</Configuration> 7 <Configuration>Debug</Configuration>
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index 85168943..4df762da 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -25,15 +25,15 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
25 hr = XmlGetAttributeEx(pixnExePackage, L"DetectionType", &scz); 25 hr = XmlGetAttributeEx(pixnExePackage, L"DetectionType", &scz);
26 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @DetectionType."); 26 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @DetectionType.");
27 27
28 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"condition", -1)) 28 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"condition", -1, FALSE))
29 { 29 {
30 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_CONDITION; 30 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_CONDITION;
31 } 31 }
32 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"arp", -1)) 32 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"arp", -1, FALSE))
33 { 33 {
34 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_ARP; 34 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_ARP;
35 } 35 }
36 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"none", -1)) 36 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"none", -1, FALSE))
37 { 37 {
38 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_NONE; 38 pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_NONE;
39 } 39 }
@@ -114,15 +114,15 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
114 114
115 if (fFoundXml) 115 if (fFoundXml)
116 { 116 {
117 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"burn", -1)) 117 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"burn", -1, FALSE))
118 { 118 {
119 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; 119 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
120 } 120 }
121 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"netfx4", -1)) 121 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"netfx4", -1, FALSE))
122 { 122 {
123 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NETFX4; 123 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NETFX4;
124 } 124 }
125 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"none", -1)) 125 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"none", -1, FALSE))
126 { 126 {
127 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NONE; 127 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NONE;
128 } 128 }
@@ -489,29 +489,30 @@ extern "C" HRESULT ExeEngineExecutePackage(
489 } 489 }
490 else if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType && BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action) 490 else if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType && BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action)
491 { 491 {
492 ExitOnNull(sczArpUninstallString, hr, E_INVALIDARG, "%hs is null.", pPackage->Exe.fArpUseUninstallString ? "UninstallString" : "QuietUninstallString"); 492 LPCWSTR szRegName = pPackage->Exe.fArpUseUninstallString ? L"UninstallString" : L"QuietUninstallString";
493 ExitOnNull(sczArpUninstallString, hr, E_INVALIDARG, "%ls is null.", szRegName);
493 494
494 hr = AppParseCommandLine(sczArpUninstallString, &argcArp, &argvArp); 495 hr = AppParseCommandLine(sczArpUninstallString, &argcArp, &argvArp);
495 ExitOnFailure(hr, "Failed to parse QuietUninstallString: %ls.", sczArpUninstallString); 496 ExitOnFailure(hr, "Failed to parse %ls: %ls.", szRegName, sczArpUninstallString);
496 497
497 ExitOnNull(argcArp, hr, E_INVALIDARG, "QuietUninstallString must contain an executable path."); 498 ExitOnNull(argcArp, hr, E_INVALIDARG, "%ls must contain an executable path.", szRegName);
498 499
499 hr = StrAllocString(&sczExecutablePath, argvArp[0], 0); 500 hr = StrAllocString(&sczExecutablePath, argvArp[0], 0);
500 ExitOnFailure(hr, "Failed to copy executable path."); 501 ExitOnFailure(hr, "Failed to copy executable path.");
501 502
502 if (pPackage->fPerMachine) 503 if (pPackage->fPerMachine)
503 { 504 {
504 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath); 505 hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath, argcArp - 1, (argcArp > 1) ? const_cast<LPCWSTR*>(argvArp + 1) : NULL);
505 ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath); 506 ExitOnFailure(hr, "Failed to verify the %ls executable path is in a secure location: %ls", szRegName, sczExecutablePath);
506 if (S_FALSE == hr) 507 if (S_FALSE == hr)
507 { 508 {
508 LogStringLine(REPORT_STANDARD, "The QuietUninstallString executable path is not in a secure location: %ls", sczExecutablePath); 509 LogStringLine(REPORT_STANDARD, "The %ls executable path is not in a secure location: %ls", szRegName, sczExecutablePath);
509 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); 510 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED));
510 } 511 }
511 } 512 }
512 513
513 hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory); 514 hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory);
514 ExitOnFailure(hr, "Failed to get parent directory for QuietUninstallString executable path: %ls", sczExecutablePath); 515 ExitOnFailure(hr, "Failed to get parent directory for %ls executable path: %ls", szRegName, sczExecutablePath);
515 } 516 }
516 else 517 else
517 { 518 {
@@ -587,13 +588,15 @@ extern "C" HRESULT ExeEngineExecutePackage(
587 } 588 }
588 589
589 // build base command 590 // build base command
590 hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath); 591 if (sczArpUninstallString && *sczArpUninstallString)
591 ExitOnFailure(hr, "Failed to allocate base command."); 592 {
592 593 hr = StrAllocString(&sczBaseCommand, sczArpUninstallString, 0);
593 for (int i = 1; i < argcArp; ++i) 594 ExitOnFailure(hr, "Failed to allocate base command.");
595 }
596 else
594 { 597 {
595 hr = AppAppendCommandLineArgument(&sczBaseCommand, argvArp[i]); 598 hr = StrAllocFormatted(&sczBaseCommand, L"\"%ls\"", sczExecutablePath);
596 ExitOnFailure(hr, "Failed to append argument from ARP."); 599 ExitOnFailure(hr, "Failed to allocate base command.");
597 } 600 }
598 601
599 if (pPackage->Exe.fBundle) 602 if (pPackage->Exe.fBundle)
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 60c16c01..51b546ad 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -1052,7 +1052,7 @@ static HRESULT GetNonSessionSpecificTempFolder(
1052 hr = ::StringCchLengthW(sczSessionId, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cchSessionId)); 1052 hr = ::StringCchLengthW(sczSessionId, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cchSessionId));
1053 ExitOnFailure(hr, "Failed to get length of session id string."); 1053 ExitOnFailure(hr, "Failed to get length of session id string.");
1054 1054
1055 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczTempFolder + cchTempFolder - cchSessionId, static_cast<DWORD>(cchSessionId), sczSessionId, static_cast<DWORD>(cchSessionId))) 1055 if (CSTR_EQUAL == ::CompareStringOrdinal(sczTempFolder + cchTempFolder - cchSessionId, static_cast<DWORD>(cchSessionId), sczSessionId, static_cast<DWORD>(cchSessionId), FALSE))
1056 { 1056 {
1057 cchTempFolder -= cchSessionId; 1057 cchTempFolder -= cchSessionId;
1058 } 1058 }
diff --git a/src/burn/engine/manifest.cpp b/src/burn/engine/manifest.cpp
index 266d1987..b2680387 100644
--- a/src/burn/engine/manifest.cpp
+++ b/src/burn/engine/manifest.cpp
@@ -177,7 +177,7 @@ static void ValidateHarvestingAttributes(
177 hr = XmlGetYesNoAttribute(pixeBundle, L"Win64", &fWin64); 177 hr = XmlGetYesNoAttribute(pixeBundle, L"Win64", &fWin64);
178 ExitOnRequiredXmlQueryFailure(hr, "Failed to get BurnManifest/@Win64 attribute."); 178 ExitOnRequiredXmlQueryFailure(hr, "Failed to get BurnManifest/@Win64 attribute.");
179 179
180 Assert(CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczEngineVersion, -1, wzVerMajorMinorBuild, -1)); 180 Assert(CSTR_EQUAL == ::CompareStringOrdinal(sczEngineVersion, -1, wzVerMajorMinorBuild, -1, FALSE));
181 181
182 Assert(BURN_PROTOCOL_VERSION == dwProtocolVersion); 182 Assert(BURN_PROTOCOL_VERSION == dwProtocolVersion);
183 183
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index d5268b17..48ec0c81 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -50,7 +50,9 @@ static void RegisterSourceDirectory(
50 __in BURN_PACKAGE* pPackage, 50 __in BURN_PACKAGE* pPackage,
51 __in_z LPCWSTR wzCacheDirectory 51 __in_z LPCWSTR wzCacheDirectory
52 ); 52 );
53 53static BOOL PackageHasAppliedPatch(
54 __in BURN_PACKAGE* pPackage
55 );
54 56
55// function definitions 57// function definitions
56 58
@@ -523,7 +525,7 @@ extern "C" HRESULT MsiEngineDetectPackage(
523 ExitOnFailure(hr, "Failed to enum related products."); 525 ExitOnFailure(hr, "Failed to enum related products.");
524 526
525 // If we found ourselves, skip because saying that a package is related to itself is nonsensical. 527 // If we found ourselves, skip because saying that a package is related to itself is nonsensical.
526 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pPackage->Msi.sczProductCode, -1, wzProductCode, -1)) 528 if (CSTR_EQUAL == ::CompareStringOrdinal(pPackage->Msi.sczProductCode, -1, wzProductCode, -1, TRUE))
527 { 529 {
528 continue; 530 continue;
529 } 531 }
@@ -631,7 +633,7 @@ extern "C" HRESULT MsiEngineDetectPackage(
631 } 633 }
632 // It can't be a downgrade if the upgrade codes aren't the same. 634 // It can't be a downgrade if the upgrade codes aren't the same.
633 else if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT == pPackage->currentState && 635 else if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT == pPackage->currentState &&
634 pPackage->Msi.sczUpgradeCode && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pPackage->Msi.sczUpgradeCode, -1, pRelatedMsi->sczUpgradeCode, -1)) 636 pPackage->Msi.sczUpgradeCode && CSTR_EQUAL == ::CompareStringOrdinal(pPackage->Msi.sczUpgradeCode, -1, pRelatedMsi->sczUpgradeCode, -1, TRUE))
635 { 637 {
636 relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; 638 relatedMsiOperation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
637 pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE; 639 pPackage->Msi.operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
@@ -904,7 +906,22 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
904 else if ((BOOTSTRAPPER_REQUEST_STATE_ABSENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested) && 906 else if ((BOOTSTRAPPER_REQUEST_STATE_ABSENT == pPackage->requested || BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested) &&
905 !pPackage->fPermanent) // removing a package that should be removed. 907 !pPackage->fPermanent) // removing a package that should be removed.
906 { 908 {
907 execute = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == pPackage->currentState ? BOOTSTRAPPER_ACTION_STATE_NONE : BOOTSTRAPPER_ACTION_STATE_UNINSTALL; 909 if (BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED == pPackage->currentState)
910 {
911 // If the package is superseded, check to see if there's a patch installed.
912 // A minor upgrade patch could be (usually is) the cause of the
913 // supersedence. In that case, we should ignore the supersedence that would
914 // normally prevent the uninstall. There is a gap in this logic: If a minor
915 // upgrade package were installed without a bundle, then a small update patch
916 // (which by definition doesn't change the version number) were installed,
917 // this check would allow the uninstall. If the minor upgrade were installed
918 // by a bundle, dependencies would keep the package installed.
919 execute = PackageHasAppliedPatch(pPackage) ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
920 }
921 else
922 {
923 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
924 }
908 } 925 }
909 else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested) 926 else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT == pPackage->requested)
910 { 927 {
@@ -2265,6 +2282,7 @@ LExit:
2265 ReleaseStr(sczMspPath); 2282 ReleaseStr(sczMspPath);
2266 ReleaseStr(sczCachedDirectory); 2283 ReleaseStr(sczCachedDirectory);
2267 ReleaseStr(sczPatches); 2284 ReleaseStr(sczPatches);
2285
2268 return hr; 2286 return hr;
2269} 2287}
2270 2288
@@ -2289,6 +2307,47 @@ static void RegisterSourceDirectory(
2289 2307
2290LExit: 2308LExit:
2291 ReleaseStr(sczMsiDirectory); 2309 ReleaseStr(sczMsiDirectory);
2310}
2311
2312static BOOL PackageHasAppliedPatch(
2313 __in BURN_PACKAGE* pPackage
2314)
2315{
2316 HRESULT hr = S_OK;
2317 BOOL fPatched = FALSE;
2318 UINT er = ERROR_SUCCESS;
2319 DWORD iPatch = 0;
2320 WCHAR wzPatchCode[MAX_GUID_CHARS + 1] = {};
2321 WCHAR wzTransforms[MAX_PATH] = {};
2322 DWORD cchTransforms = countof(wzTransforms);
2323 WCHAR wzPatchState[2] = {};
2324 DWORD cchPatchState = countof(wzPatchState);
2325
2326 for (;;)
2327 {
2328 er = ::MsiEnumPatchesW(pPackage->Msi.sczProductCode, iPatch, wzPatchCode, wzTransforms, &cchTransforms);
2329
2330 if (ERROR_NO_MORE_ITEMS == er)
2331 {
2332 ExitFunction();
2333 }
2334 ExitOnWin32Error(er, hr, "Failed to enumerate patches for package %ls, product code %ls.", pPackage->sczId, pPackage->Msi.sczProductCode);
2335
2336 er = ::MsiGetPatchInfoExW(wzPatchCode, pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED
2337 , INSTALLPROPERTY_PATCHSTATE, wzPatchState, &cchPatchState);
2338 ExitOnWin32Error(er, hr, "Failed to get patch info for patch %ls.", wzPatchCode);
2339
2340 if ('1' == wzPatchState[0])
2341 {
2342 fPatched = TRUE;
2343
2344 ExitFunction();
2345 }
2346
2347 ++iPatch;
2348 }
2349
2350LExit:
2351 return fPatched;
2292 2352
2293 return;
2294} 2353}
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index c057c06d..e8ef7fcb 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -771,7 +771,7 @@ extern "C" void MspEngineUpdateInstallRegistrationState(
771 { 771 {
772 pTargetProduct = pPackage->Msp.rgTargetProducts + j; 772 pTargetProduct = pPackage->Msp.rgTargetProducts + j;
773 if (pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) && 773 if (pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) &&
774 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1)) 774 CSTR_EQUAL == ::CompareStringOrdinal(pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1, FALSE))
775 { 775 {
776 break; 776 break;
777 } 777 }
@@ -1069,7 +1069,7 @@ static HRESULT DeterminePatchChainedTarget(
1069 { 1069 {
1070 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage; 1070 BURN_PACKAGE* pPackage = pPackages->rgPackages + iPackage;
1071 1071
1072 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzTargetProductCode, -1, pPackage->Msi.sczProductCode, -1)) 1072 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && CSTR_EQUAL == ::CompareStringOrdinal(wzTargetProductCode, -1, pPackage->Msi.sczProductCode, -1, FALSE))
1073 { 1073 {
1074 pTargetProduct->pChainedTargetPackage = pPackage; 1074 pTargetProduct->pChainedTargetPackage = pPackage;
1075 1075
@@ -1123,7 +1123,7 @@ static HRESULT PlanTargetProduct(
1123 if (BURN_EXECUTE_ACTION_TYPE_MSP_TARGET == pAction->type && 1123 if (BURN_EXECUTE_ACTION_TYPE_MSP_TARGET == pAction->type &&
1124 pAction->mspTarget.action == actionState && 1124 pAction->mspTarget.action == actionState &&
1125 pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) && 1125 pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) &&
1126 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1)) 1126 CSTR_EQUAL == ::CompareStringOrdinal(pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1, FALSE))
1127 { 1127 {
1128 dwInsertSequence = i; 1128 dwInsertSequence = i;
1129 break; 1129 break;
diff --git a/src/burn/engine/package.cpp b/src/burn/engine/package.cpp
index fe8af497..3bf676ba 100644
--- a/src/burn/engine/package.cpp
+++ b/src/burn/engine/package.cpp
@@ -123,15 +123,15 @@ extern "C" HRESULT PackagesParseFromXml(
123 123
124 if (fFoundXml) 124 if (fFoundXml)
125 { 125 {
126 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"remove", -1)) 126 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"remove", -1, FALSE))
127 { 127 {
128 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_REMOVE; 128 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_REMOVE;
129 } 129 }
130 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"keep", -1)) 130 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"keep", -1, FALSE))
131 { 131 {
132 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_KEEP; 132 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_KEEP;
133 } 133 }
134 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"force", -1)) 134 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"force", -1, FALSE))
135 { 135 {
136 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_FORCE; 136 pPackage->authoredCacheType = BOOTSTRAPPER_CACHE_TYPE_FORCE;
137 } 137 }
@@ -210,28 +210,28 @@ extern "C" HRESULT PackagesParseFromXml(
210 } 210 }
211 211
212 // read type specific attributes 212 // read type specific attributes
213 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"BundlePackage", -1)) 213 if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"BundlePackage", -1, FALSE))
214 { 214 {
215 pPackage->type = BURN_PACKAGE_TYPE_BUNDLE; 215 pPackage->type = BURN_PACKAGE_TYPE_BUNDLE;
216 216
217 hr = BundlePackageEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization 217 hr = BundlePackageEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization
218 ExitOnFailure(hr, "Failed to parse BUNDLE package."); 218 ExitOnFailure(hr, "Failed to parse BUNDLE package.");
219 } 219 }
220 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExePackage", -1)) 220 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"ExePackage", -1, FALSE))
221 { 221 {
222 pPackage->type = BURN_PACKAGE_TYPE_EXE; 222 pPackage->type = BURN_PACKAGE_TYPE_EXE;
223 223
224 hr = ExeEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization 224 hr = ExeEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization
225 ExitOnFailure(hr, "Failed to parse EXE package."); 225 ExitOnFailure(hr, "Failed to parse EXE package.");
226 } 226 }
227 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiPackage", -1)) 227 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"MsiPackage", -1, FALSE))
228 { 228 {
229 pPackage->type = BURN_PACKAGE_TYPE_MSI; 229 pPackage->type = BURN_PACKAGE_TYPE_MSI;
230 230
231 hr = MsiEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization 231 hr = MsiEngineParsePackageFromXml(pixnNode, pPackage); // TODO: Modularization
232 ExitOnFailure(hr, "Failed to parse MSI package."); 232 ExitOnFailure(hr, "Failed to parse MSI package.");
233 } 233 }
234 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MspPackage", -1)) 234 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"MspPackage", -1, FALSE))
235 { 235 {
236 pPackage->type = BURN_PACKAGE_TYPE_MSP; 236 pPackage->type = BURN_PACKAGE_TYPE_MSP;
237 237
@@ -240,7 +240,7 @@ extern "C" HRESULT PackagesParseFromXml(
240 240
241 ++cMspPackages; 241 ++cMspPackages;
242 } 242 }
243 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsuPackage", -1)) 243 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"MsuPackage", -1, FALSE))
244 { 244 {
245 pPackage->type = BURN_PACKAGE_TYPE_MSU; 245 pPackage->type = BURN_PACKAGE_TYPE_MSU;
246 246
@@ -315,7 +315,7 @@ extern "C" HRESULT PackagesParseFromXml(
315 { 315 {
316 for (DWORD k = 0; k < pMsiPackage->Msi.cSlipstreamMspPackages; ++k) 316 for (DWORD k = 0; k < pMsiPackage->Msi.cSlipstreamMspPackages; ++k)
317 { 317 {
318 if (pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k] && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k], -1)) 318 if (pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k] && CSTR_EQUAL == ::CompareStringOrdinal(pPackage->sczId, -1, pMsiPackage->Msi.rgsczSlipstreamMspPackageIds[k], -1, FALSE))
319 { 319 {
320 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pMsiPackage->Msi.rgSlipstreamMsps + k; 320 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pMsiPackage->Msi.rgSlipstreamMsps + k;
321 pSlipstreamMsp->pMspPackage = pPackage; 321 pSlipstreamMsp->pMspPackage = pPackage;
@@ -486,7 +486,7 @@ extern "C" HRESULT PackageFindById(
486 { 486 {
487 pPackage = &pPackages->rgPackages[i]; 487 pPackage = &pPackages->rgPackages[i];
488 488
489 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1)) 489 if (CSTR_EQUAL == ::CompareStringOrdinal(pPackage->sczId, -1, wzId, -1, FALSE))
490 { 490 {
491 *ppPackage = pPackage; 491 *ppPackage = pPackage;
492 ExitFunction1(hr = S_OK); 492 ExitFunction1(hr = S_OK);
@@ -508,7 +508,7 @@ extern "C" HRESULT PackageFindRelatedById(
508{ 508{
509 HRESULT hr = S_OK; 509 HRESULT hr = S_OK;
510 BURN_RELATED_BUNDLE* pRelatedBundle = NULL; 510 BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
511 511
512 hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle); 512 hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle);
513 *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package; 513 *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package;
514 514
@@ -551,7 +551,7 @@ extern "C" HRESULT PackageGetProperty(
551 { 551 {
552 const BURN_MSIPROPERTY* pProperty = &rgProperties[i]; 552 const BURN_MSIPROPERTY* pProperty = &rgProperties[i];
553 553
554 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pProperty->sczId, -1, wzProperty, -1)) 554 if (CSTR_EQUAL == ::CompareStringOrdinal(pProperty->sczId, -1, wzProperty, -1, FALSE))
555 { 555 {
556 if (psczValue) 556 if (psczValue)
557 { 557 {
@@ -580,7 +580,7 @@ extern "C" HRESULT PackageFindRollbackBoundaryById(
580 { 580 {
581 pRollbackBoundary = &pPackages->rgRollbackBoundaries[i]; 581 pRollbackBoundary = &pPackages->rgRollbackBoundaries[i];
582 582
583 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pRollbackBoundary->sczId, -1, wzId, -1)) 583 if (CSTR_EQUAL == ::CompareStringOrdinal(pRollbackBoundary->sczId, -1, wzId, -1, FALSE))
584 { 584 {
585 *ppRollbackBoundary = pRollbackBoundary; 585 *ppRollbackBoundary = pRollbackBoundary;
586 ExitFunction1(hr = S_OK); 586 ExitFunction1(hr = S_OK);
@@ -730,7 +730,7 @@ static HRESULT FindRollbackBoundaryById(
730 { 730 {
731 pRollbackBoundary = &pPackages->rgRollbackBoundaries[i]; 731 pRollbackBoundary = &pPackages->rgRollbackBoundaries[i];
732 732
733 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pRollbackBoundary->sczId, -1, wzId, -1)) 733 if (CSTR_EQUAL == ::CompareStringOrdinal(pRollbackBoundary->sczId, -1, wzId, -1, FALSE))
734 { 734 {
735 *ppRollbackBoundary = pRollbackBoundary; 735 *ppRollbackBoundary = pRollbackBoundary;
736 ExitFunction1(hr = S_OK); 736 ExitFunction1(hr = S_OK);
diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp
index 270da6aa..a2649f97 100644
--- a/src/burn/engine/payload.cpp
+++ b/src/burn/engine/payload.cpp
@@ -80,11 +80,11 @@ extern "C" HRESULT PayloadsParseFromXml(
80 hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz); 80 hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz);
81 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Packaging."); 81 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Packaging.");
82 82
83 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1)) 83 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"embedded", -1, FALSE))
84 { 84 {
85 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED; 85 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED;
86 } 86 }
87 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1)) 87 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"external", -1, FALSE))
88 { 88 {
89 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; 89 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
90 } 90 }
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 85c006f7..9733e92c 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -223,15 +223,15 @@ extern "C" HRESULT RegistrationParseFromXml(
223 223
224 if (fFoundXml) 224 if (fFoundXml)
225 { 225 {
226 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"button", -1)) 226 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"button", -1, FALSE))
227 { 227 {
228 pRegistration->modify = BURN_REGISTRATION_MODIFY_DISABLE_BUTTON; 228 pRegistration->modify = BURN_REGISTRATION_MODIFY_DISABLE_BUTTON;
229 } 229 }
230 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"yes", -1)) 230 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"yes", -1, FALSE))
231 { 231 {
232 pRegistration->modify = BURN_REGISTRATION_MODIFY_DISABLE; 232 pRegistration->modify = BURN_REGISTRATION_MODIFY_DISABLE;
233 } 233 }
234 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"no", -1)) 234 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"no", -1, FALSE))
235 { 235 {
236 pRegistration->modify = BURN_REGISTRATION_MODIFY_ENABLED; 236 pRegistration->modify = BURN_REGISTRATION_MODIFY_ENABLED;
237 } 237 }
@@ -808,13 +808,6 @@ extern "C" HRESULT RegistrationSessionBegin(
808 ExitOnFailure(hr, "Failed to write software tags."); 808 ExitOnFailure(hr, "Failed to write software tags.");
809 } 809 }
810 810
811 // Update registration.
812 if (pRegistration->update.fRegisterUpdate)
813 {
814 hr = WriteUpdateRegistration(pRegistration, pVariables);
815 ExitOnFailure(hr, "Failed to write update registration.");
816 }
817
818 // Only set install date and initial estimated size here for the first time. 811 // Only set install date and initial estimated size here for the first time.
819 // Estimated size will always get updated at the end of the session. 812 // Estimated size will always get updated at the end of the session.
820 if (fCreated) 813 if (fCreated)
@@ -904,6 +897,13 @@ extern "C" HRESULT RegistrationSessionEnd(
904 897
905 hr = UpdateEstimatedSize(hkRegistration, qwEstimatedSize); 898 hr = UpdateEstimatedSize(hkRegistration, qwEstimatedSize);
906 ExitOnFailure(hr, "Failed to update estimated size."); 899 ExitOnFailure(hr, "Failed to update estimated size.");
900
901 // Update registration.
902 if (pRegistration->update.fRegisterUpdate)
903 {
904 hr = WriteUpdateRegistration(pRegistration, pVariables);
905 ExitOnFailure(hr, "Failed to write update registration.");
906 }
907 } 907 }
908 908
909 // Update resume mode. 909 // Update resume mode.
@@ -1512,7 +1512,7 @@ static HRESULT RemoveUpdateRegistration(
1512 hr = RegReadString(hkKey, L"PackageVersion", &sczPackageVersion); 1512 hr = RegReadString(hkKey, L"PackageVersion", &sczPackageVersion);
1513 if (SUCCEEDED(hr)) 1513 if (SUCCEEDED(hr))
1514 { 1514 {
1515 if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, 0, sczPackageVersion, -1, pRegistration->sczDisplayVersion, -1)) 1515 if (CSTR_EQUAL != ::CompareStringOrdinal(sczPackageVersion, -1, pRegistration->sczDisplayVersion, -1, FALSE))
1516 { 1516 {
1517 fDeleteRegKey = FALSE; 1517 fDeleteRegKey = FALSE;
1518 } 1518 }
diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp
index 938b24d7..c9aa7170 100644
--- a/src/burn/engine/relatedbundle.cpp
+++ b/src/burn/engine/relatedbundle.cpp
@@ -116,7 +116,7 @@ extern "C" HRESULT RelatedBundleFindById(
116 pRelatedBundle = pRelatedBundles->rgRelatedBundles + i; 116 pRelatedBundle = pRelatedBundles->rgRelatedBundles + i;
117 pPackage = &pRelatedBundle->package; 117 pPackage = &pRelatedBundle->package;
118 118
119 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1)) 119 if (CSTR_EQUAL == ::CompareStringOrdinal(pPackage->sczId, -1, wzId, -1, FALSE))
120 { 120 {
121 *ppRelatedBundle = pRelatedBundle; 121 *ppRelatedBundle = pRelatedBundle;
122 ExitFunction1(hr = S_OK); 122 ExitFunction1(hr = S_OK);
@@ -206,7 +206,7 @@ static __callback int __cdecl CompareRelatedBundlesDetect(
206 VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret); 206 VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret);
207 if (0 == ret) 207 if (0 == ret)
208 { 208 {
209 ret = ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1) - 2; 209 ret = ::CompareStringOrdinal(pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1, TRUE) - 2;
210 } 210 }
211 } 211 }
212 212
@@ -249,7 +249,7 @@ static __callback int __cdecl CompareRelatedBundlesPlan(
249 VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret); 249 VerCompareParsedVersions(pBundleLeft->pVersion, pBundleRight->pVersion, &ret);
250 if (0 == ret) 250 if (0 == ret)
251 { 251 {
252 ret = ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1) - 2; 252 ret = ::CompareStringOrdinal(pBundleLeft->package.sczId, -1, pBundleRight->package.sczId, -1, TRUE) - 2;
253 } 253 }
254 } 254 }
255 255
@@ -284,7 +284,7 @@ static HRESULT LoadIfRelatedBundle(
284 BURN_RELATED_BUNDLE* pRelatedBundle = NULL; 284 BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
285 285
286 // If we found our bundle code, it's not a related bundle. 286 // If we found our bundle code, it's not a related bundle.
287 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pBundle->wzBundleCode, -1, pRegistration->sczCode, -1)) 287 if (CSTR_EQUAL == ::CompareStringOrdinal(pBundle->wzBundleCode, -1, pRegistration->sczCode, -1, TRUE))
288 { 288 {
289 ExitFunction1(hr = S_FALSE); 289 ExitFunction1(hr = S_FALSE);
290 } 290 }
diff --git a/src/burn/engine/search.cpp b/src/burn/engine/search.cpp
index a1b6b74a..1f128e95 100644
--- a/src/burn/engine/search.cpp
+++ b/src/burn/engine/search.cpp
@@ -106,7 +106,7 @@ extern "C" HRESULT SearchesParseFromXml(
106 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @Condition."); 106 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get @Condition.");
107 107
108 // read type specific attributes 108 // read type specific attributes
109 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"DirectorySearch", -1)) 109 if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"DirectorySearch", -1, FALSE))
110 { 110 {
111 pSearch->Type = BURN_SEARCH_TYPE_DIRECTORY; 111 pSearch->Type = BURN_SEARCH_TYPE_DIRECTORY;
112 112
@@ -118,11 +118,11 @@ extern "C" HRESULT SearchesParseFromXml(
118 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 118 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
119 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 119 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
120 120
121 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) 121 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"exists", -1, FALSE))
122 { 122 {
123 pSearch->DirectorySearch.Type = BURN_DIRECTORY_SEARCH_TYPE_EXISTS; 123 pSearch->DirectorySearch.Type = BURN_DIRECTORY_SEARCH_TYPE_EXISTS;
124 } 124 }
125 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"path", -1)) 125 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"path", -1, FALSE))
126 { 126 {
127 pSearch->DirectorySearch.Type = BURN_DIRECTORY_SEARCH_TYPE_PATH; 127 pSearch->DirectorySearch.Type = BURN_DIRECTORY_SEARCH_TYPE_PATH;
128 } 128 }
@@ -131,7 +131,7 @@ extern "C" HRESULT SearchesParseFromXml(
131 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); 131 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz);
132 } 132 }
133 } 133 }
134 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"FileSearch", -1)) 134 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"FileSearch", -1, FALSE))
135 { 135 {
136 pSearch->Type = BURN_SEARCH_TYPE_FILE; 136 pSearch->Type = BURN_SEARCH_TYPE_FILE;
137 137
@@ -147,15 +147,15 @@ extern "C" HRESULT SearchesParseFromXml(
147 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 147 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
148 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 148 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
149 149
150 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) 150 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"exists", -1, FALSE))
151 { 151 {
152 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_EXISTS; 152 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_EXISTS;
153 } 153 }
154 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) 154 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"version", -1, FALSE))
155 { 155 {
156 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_VERSION; 156 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_VERSION;
157 } 157 }
158 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"path", -1)) 158 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"path", -1, FALSE))
159 { 159 {
160 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_PATH; 160 pSearch->FileSearch.Type = BURN_FILE_SEARCH_TYPE_PATH;
161 } 161 }
@@ -164,7 +164,7 @@ extern "C" HRESULT SearchesParseFromXml(
164 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); 164 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz);
165 } 165 }
166 } 166 }
167 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"RegistrySearch", -1)) 167 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"RegistrySearch", -1, FALSE))
168 { 168 {
169 pSearch->Type = BURN_SEARCH_TYPE_REGISTRY; 169 pSearch->Type = BURN_SEARCH_TYPE_REGISTRY;
170 170
@@ -172,19 +172,19 @@ extern "C" HRESULT SearchesParseFromXml(
172 hr = XmlGetAttributeEx(pixnNode, L"Root", &scz); 172 hr = XmlGetAttributeEx(pixnNode, L"Root", &scz);
173 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Root."); 173 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Root.");
174 174
175 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKCR", -1)) 175 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"HKCR", -1, FALSE))
176 { 176 {
177 pSearch->RegistrySearch.hRoot = HKEY_CLASSES_ROOT; 177 pSearch->RegistrySearch.hRoot = HKEY_CLASSES_ROOT;
178 } 178 }
179 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKCU", -1)) 179 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"HKCU", -1, FALSE))
180 { 180 {
181 pSearch->RegistrySearch.hRoot = HKEY_CURRENT_USER; 181 pSearch->RegistrySearch.hRoot = HKEY_CURRENT_USER;
182 } 182 }
183 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKLM", -1)) 183 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"HKLM", -1, FALSE))
184 { 184 {
185 pSearch->RegistrySearch.hRoot = HKEY_LOCAL_MACHINE; 185 pSearch->RegistrySearch.hRoot = HKEY_LOCAL_MACHINE;
186 } 186 }
187 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"HKU", -1)) 187 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"HKU", -1, FALSE))
188 { 188 {
189 pSearch->RegistrySearch.hRoot = HKEY_USERS; 189 pSearch->RegistrySearch.hRoot = HKEY_USERS;
190 } 190 }
@@ -208,11 +208,11 @@ extern "C" HRESULT SearchesParseFromXml(
208 hr = XmlGetYesNoAttribute(pixnNode, L"Win64", &pSearch->RegistrySearch.fWin64); 208 hr = XmlGetYesNoAttribute(pixnNode, L"Win64", &pSearch->RegistrySearch.fWin64);
209 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get Win64 attribute."); 209 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get Win64 attribute.");
210 210
211 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1)) 211 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"exists", -1, FALSE))
212 { 212 {
213 pSearch->RegistrySearch.Type = BURN_REGISTRY_SEARCH_TYPE_EXISTS; 213 pSearch->RegistrySearch.Type = BURN_REGISTRY_SEARCH_TYPE_EXISTS;
214 } 214 }
215 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"value", -1)) 215 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"value", -1, FALSE))
216 { 216 {
217 pSearch->RegistrySearch.Type = BURN_REGISTRY_SEARCH_TYPE_VALUE; 217 pSearch->RegistrySearch.Type = BURN_REGISTRY_SEARCH_TYPE_VALUE;
218 218
@@ -224,19 +224,19 @@ extern "C" HRESULT SearchesParseFromXml(
224 hr = XmlGetAttributeEx(pixnNode, L"VariableType", &scz); 224 hr = XmlGetAttributeEx(pixnNode, L"VariableType", &scz);
225 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @VariableType."); 225 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @VariableType.");
226 226
227 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) 227 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"formatted", -1, FALSE))
228 { 228 {
229 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_FORMATTED; 229 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_FORMATTED;
230 } 230 }
231 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"numeric", -1)) 231 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"numeric", -1, FALSE))
232 { 232 {
233 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_NUMERIC; 233 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_NUMERIC;
234 } 234 }
235 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"string", -1)) 235 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"string", -1, FALSE))
236 { 236 {
237 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_STRING; 237 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_STRING;
238 } 238 }
239 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) 239 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"version", -1, FALSE))
240 { 240 {
241 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_VERSION; 241 pSearch->RegistrySearch.VariableType = BURN_VARIANT_TYPE_VERSION;
242 } 242 }
@@ -250,7 +250,7 @@ extern "C" HRESULT SearchesParseFromXml(
250 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); 250 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz);
251 } 251 }
252 } 252 }
253 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiComponentSearch", -1)) 253 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"MsiComponentSearch", -1, FALSE))
254 { 254 {
255 pSearch->Type = BURN_SEARCH_TYPE_MSI_COMPONENT; 255 pSearch->Type = BURN_SEARCH_TYPE_MSI_COMPONENT;
256 256
@@ -266,15 +266,15 @@ extern "C" HRESULT SearchesParseFromXml(
266 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 266 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
267 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 267 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
268 268
269 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"keyPath", -1)) 269 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"keyPath", -1, FALSE))
270 { 270 {
271 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_KEYPATH; 271 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_KEYPATH;
272 } 272 }
273 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"state", -1)) 273 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"state", -1, FALSE))
274 { 274 {
275 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_STATE; 275 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_STATE;
276 } 276 }
277 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"directory", -1)) 277 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"directory", -1, FALSE))
278 { 278 {
279 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_DIRECTORY; 279 pSearch->MsiComponentSearch.Type = BURN_MSI_COMPONENT_SEARCH_TYPE_DIRECTORY;
280 } 280 }
@@ -283,7 +283,7 @@ extern "C" HRESULT SearchesParseFromXml(
283 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); 283 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz);
284 } 284 }
285 } 285 }
286 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"MsiProductSearch", -1)) 286 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"MsiProductSearch", -1, FALSE))
287 { 287 {
288 pSearch->Type = BURN_SEARCH_TYPE_MSI_PRODUCT; 288 pSearch->Type = BURN_SEARCH_TYPE_MSI_PRODUCT;
289 pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_NONE; 289 pSearch->MsiProductSearch.GuidType = BURN_MSI_PRODUCT_SEARCH_GUID_TYPE_NONE;
@@ -318,28 +318,32 @@ extern "C" HRESULT SearchesParseFromXml(
318 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 318 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
319 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 319 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
320 320
321 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) 321 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"version", -1, FALSE))
322 { 322 {
323 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_VERSION; 323 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_VERSION;
324 } 324 }
325 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"language", -1)) 325 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"language", -1, FALSE))
326 { 326 {
327 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE; 327 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE;
328 } 328 }
329 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"state", -1)) 329 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"state", -1, FALSE))
330 { 330 {
331 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_STATE; 331 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_STATE;
332 } 332 }
333 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"assignment", -1)) 333 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"assignment", -1, FALSE))
334 { 334 {
335 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT; 335 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT;
336 } 336 }
337 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"exists", -1))
338 {
339 pSearch->MsiProductSearch.Type = BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS;
340 }
337 else 341 else
338 { 342 {
339 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz); 343 ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for @Type: %ls", scz);
340 } 344 }
341 } 345 }
342 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"ExtensionSearch", -1)) 346 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"ExtensionSearch", -1, FALSE))
343 { 347 {
344 pSearch->Type = BURN_SEARCH_TYPE_EXTENSION; 348 pSearch->Type = BURN_SEARCH_TYPE_EXTENSION;
345 349
@@ -350,7 +354,7 @@ extern "C" HRESULT SearchesParseFromXml(
350 hr = BurnExtensionFindById(pBurnExtensions, scz, &pSearch->ExtensionSearch.pExtension); 354 hr = BurnExtensionFindById(pBurnExtensions, scz, &pSearch->ExtensionSearch.pExtension);
351 ExitOnRootFailure(hr, "Failed to find extension '%ls' for search '%ls'", scz, pSearch->sczKey); 355 ExitOnRootFailure(hr, "Failed to find extension '%ls' for search '%ls'", scz, pSearch->sczKey);
352 } 356 }
353 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"SetVariable", -1)) 357 else if (CSTR_EQUAL == ::CompareStringOrdinal(bstrNodeName, -1, L"SetVariable", -1, FALSE))
354 { 358 {
355 pSearch->Type = BURN_SEARCH_TYPE_SET_VARIABLE; 359 pSearch->Type = BURN_SEARCH_TYPE_SET_VARIABLE;
356 360
@@ -367,19 +371,19 @@ extern "C" HRESULT SearchesParseFromXml(
367 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 371 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
368 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 372 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
369 373
370 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) 374 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"formatted", -1, FALSE))
371 { 375 {
372 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_FORMATTED; 376 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_FORMATTED;
373 } 377 }
374 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"numeric", -1)) 378 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"numeric", -1, FALSE))
375 { 379 {
376 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_NUMERIC; 380 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_NUMERIC;
377 } 381 }
378 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"string", -1)) 382 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"string", -1, FALSE))
379 { 383 {
380 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_STRING; 384 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_STRING;
381 } 385 }
382 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) 386 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"version", -1, FALSE))
383 { 387 {
384 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_VERSION; 388 pSearch->SetVariable.targetType = BURN_VARIANT_TYPE_VERSION;
385 } 389 }
@@ -1144,6 +1148,7 @@ static HRESULT MsiProductSearch(
1144 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE: 1148 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
1145 wzProperty = INSTALLPROPERTY_LANGUAGE; 1149 wzProperty = INSTALLPROPERTY_LANGUAGE;
1146 break; 1150 break;
1151 case BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS: __fallthrough;
1147 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE: 1152 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE:
1148 wzProperty = INSTALLPROPERTY_PRODUCTSTATE; 1153 wzProperty = INSTALLPROPERTY_PRODUCTSTATE;
1149 break; 1154 break;
@@ -1218,6 +1223,7 @@ static HRESULT MsiProductSearch(
1218 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE: 1223 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
1219 // is supposed to remain empty 1224 // is supposed to remain empty
1220 break; 1225 break;
1226 case BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS: __fallthrough;
1221 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE: 1227 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE:
1222 value.Type = BURN_VARIANT_TYPE_NUMERIC; 1228 value.Type = BURN_VARIANT_TYPE_NUMERIC;
1223 value.llValue = INSTALLSTATE_ABSENT; 1229 value.llValue = INSTALLSTATE_ABSENT;
@@ -1237,6 +1243,7 @@ static HRESULT MsiProductSearch(
1237 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE: 1243 case BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE:
1238 type = BURN_VARIANT_TYPE_STRING; 1244 type = BURN_VARIANT_TYPE_STRING;
1239 break; 1245 break;
1246 case BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS: __fallthrough;
1240 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE: __fallthrough; 1247 case BURN_MSI_PRODUCT_SEARCH_TYPE_STATE: __fallthrough;
1241 case BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT: 1248 case BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT:
1242 type = BURN_VARIANT_TYPE_NUMERIC; 1249 type = BURN_VARIANT_TYPE_NUMERIC;
@@ -1245,6 +1252,13 @@ static HRESULT MsiProductSearch(
1245 hr = BVariantChangeType(&value, type); 1252 hr = BVariantChangeType(&value, type);
1246 ExitOnFailure(hr, "Failed to change value type."); 1253 ExitOnFailure(hr, "Failed to change value type.");
1247 1254
1255 // When testing if a product exists, replace the value with a numeric "true" or "false"
1256 // based on the calculated install state.
1257 if (BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS == pSearch->MsiProductSearch.Type)
1258 {
1259 value.llValue = (value.llValue == INSTALLSTATE_ABSENT) ? 0 : 1;
1260 }
1261
1248 // Set variable. 1262 // Set variable.
1249 hr = VariableSetVariant(pVariables, pSearch->sczVariable, &value); 1263 hr = VariableSetVariant(pVariables, pSearch->sczVariable, &value);
1250 ExitOnFailure(hr, "Failed to set variable."); 1264 ExitOnFailure(hr, "Failed to set variable.");
diff --git a/src/burn/engine/search.h b/src/burn/engine/search.h
index 341fe1aa..e70645c5 100644
--- a/src/burn/engine/search.h
+++ b/src/burn/engine/search.h
@@ -58,6 +58,7 @@ enum BURN_MSI_PRODUCT_SEARCH_TYPE
58 BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE, 58 BURN_MSI_PRODUCT_SEARCH_TYPE_LANGUAGE,
59 BURN_MSI_PRODUCT_SEARCH_TYPE_STATE, 59 BURN_MSI_PRODUCT_SEARCH_TYPE_STATE,
60 BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT, 60 BURN_MSI_PRODUCT_SEARCH_TYPE_ASSIGNMENT,
61 BURN_MSI_PRODUCT_SEARCH_TYPE_EXISTS,
61}; 62};
62 63
63enum BURN_MSI_PRODUCT_SEARCH_GUID_TYPE 64enum BURN_MSI_PRODUCT_SEARCH_GUID_TYPE
diff --git a/src/burn/engine/splashscreen.cpp b/src/burn/engine/splashscreen.cpp
index 0bfa00aa..21ddfa98 100644
--- a/src/burn/engine/splashscreen.cpp
+++ b/src/burn/engine/splashscreen.cpp
@@ -371,6 +371,7 @@ static void OnEraseBkgnd(
371 HDC hdc = reinterpret_cast<HDC>(wParam); 371 HDC hdc = reinterpret_cast<HDC>(wParam);
372 HDC hdcMem = ::CreateCompatibleDC(hdc); 372 HDC hdcMem = ::CreateCompatibleDC(hdc);
373 HBITMAP hDefaultBitmap = static_cast<HBITMAP>(::SelectObject(hdcMem, pSplashScreen->hBitmap)); 373 HBITMAP hDefaultBitmap = static_cast<HBITMAP>(::SelectObject(hdcMem, pSplashScreen->hBitmap));
374 ::SetStretchBltMode(hdc, HALFTONE);
374 ::StretchBlt(hdc, 0, 0, pSplashScreen->size.cx, pSplashScreen->size.cy, hdcMem, 0, 0, pSplashScreen->defaultDpiSize.cx, pSplashScreen->defaultDpiSize.cy, SRCCOPY); 375 ::StretchBlt(hdc, 0, 0, pSplashScreen->size.cx, pSplashScreen->size.cy, hdcMem, 0, 0, pSplashScreen->defaultDpiSize.cx, pSplashScreen->defaultDpiSize.cy, SRCCOPY);
375 ::SelectObject(hdcMem, hDefaultBitmap); 376 ::SelectObject(hdcMem, hDefaultBitmap);
376 ::DeleteDC(hdcMem); 377 ::DeleteDC(hdcMem);
diff --git a/src/burn/engine/variable.cpp b/src/burn/engine/variable.cpp
index 9d0aec52..a795d76c 100644
--- a/src/burn/engine/variable.cpp
+++ b/src/burn/engine/variable.cpp
@@ -397,7 +397,7 @@ extern "C" HRESULT VariablesParseFromXml(
397 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz); 397 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
398 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type."); 398 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
399 399
400 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"formatted", -1)) 400 if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"formatted", -1, FALSE))
401 { 401 {
402 if (!fHidden) 402 if (!fHidden)
403 { 403 {
@@ -405,7 +405,7 @@ extern "C" HRESULT VariablesParseFromXml(
405 } 405 }
406 valueType = BURN_VARIANT_TYPE_FORMATTED; 406 valueType = BURN_VARIANT_TYPE_FORMATTED;
407 } 407 }
408 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"numeric", -1)) 408 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"numeric", -1, FALSE))
409 { 409 {
410 if (!fHidden) 410 if (!fHidden)
411 { 411 {
@@ -413,7 +413,7 @@ extern "C" HRESULT VariablesParseFromXml(
413 } 413 }
414 valueType = BURN_VARIANT_TYPE_NUMERIC; 414 valueType = BURN_VARIANT_TYPE_NUMERIC;
415 } 415 }
416 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"string", -1)) 416 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"string", -1, FALSE))
417 { 417 {
418 if (!fHidden) 418 if (!fHidden)
419 { 419 {
@@ -421,7 +421,7 @@ extern "C" HRESULT VariablesParseFromXml(
421 } 421 }
422 valueType = BURN_VARIANT_TYPE_STRING; 422 valueType = BURN_VARIANT_TYPE_STRING;
423 } 423 }
424 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"version", -1)) 424 else if (CSTR_EQUAL == ::CompareStringOrdinal(scz, -1, L"version", -1, FALSE))
425 { 425 {
426 if (!fHidden) 426 if (!fHidden)
427 { 427 {
@@ -1144,7 +1144,7 @@ extern "C" BOOL VariableIsHiddenCommandLine(
1144 { 1144 {
1145 pVariable = pVariables->rgVariables + i; 1145 pVariable = pVariables->rgVariables + i;
1146 1146
1147 if (pVariable->fHidden && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pVariable->sczName, -1, wzVariable, -1)) 1147 if (pVariable->fHidden && CSTR_EQUAL == ::CompareStringOrdinal(pVariable->sczName, -1, wzVariable, -1, TRUE))
1148 { 1148 {
1149 fHidden = TRUE; 1149 fHidden = TRUE;
1150 break; 1150 break;
@@ -1556,7 +1556,7 @@ static HRESULT FindVariableIndexByName(
1556 DWORD iPosition = cRangeLength / 2; 1556 DWORD iPosition = cRangeLength / 2;
1557 BURN_VARIABLE* pVariable = &pVariables->rgVariables[iRangeFirst + iPosition]; 1557 BURN_VARIABLE* pVariable = &pVariables->rgVariables[iRangeFirst + iPosition];
1558 1558
1559 switch (::CompareStringW(LOCALE_INVARIANT, SORT_STRINGSORT, wzVariable, -1, pVariable->sczName, -1)) 1559 switch (::CompareStringOrdinal(wzVariable, -1, pVariable->sczName, -1, FALSE))
1560 { 1560 {
1561 case CSTR_LESS_THAN: 1561 case CSTR_LESS_THAN:
1562 // restrict range to elements before the current 1562 // restrict range to elements before the current
@@ -1591,7 +1591,7 @@ static HRESULT InsertUserVariable(
1591{ 1591{
1592 HRESULT hr = S_OK; 1592 HRESULT hr = S_OK;
1593 1593
1594 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, wzVariable, 3, L"Wix", 3)) 1594 if (CSTR_EQUAL == ::CompareStringOrdinal(wzVariable, 3, L"Wix", 3, FALSE))
1595 { 1595 {
1596 ExitWithRootFailure(hr, E_INVALIDARG, "Attempted to insert variable with reserved prefix: %ls", wzVariable); 1596 ExitWithRootFailure(hr, E_INVALIDARG, "Attempted to insert variable with reserved prefix: %ls", wzVariable);
1597 } 1597 }