From 3232f84c19b86184cb7c2db137b97ccb9aec20cc Mon Sep 17 00:00:00 2001 From: comicfans Date: Sun, 10 Sep 2017 17:39:04 +0800 Subject: VS: Fix MANIFESTUAC link flag map to .vcxproj elements Add special parsing of the flags given in `/MANIFESTUAC:"..."` in order to map them correctly to `.vcxproj` elements. Keep the old incorrect flag table entries for `uiAccess` and `level` flags for compatibility even though they do not really exist. Fixes: #16563 --- Source/cmVS10LinkFlagTable.h | 13 +++--- Source/cmVS11LinkFlagTable.h | 13 +++--- Source/cmVS12LinkFlagTable.h | 13 +++--- Source/cmVS140LinkFlagTable.h | 13 +++--- Source/cmVS141LinkFlagTable.h | 13 +++--- Source/cmVisualStudio10TargetGenerator.cxx | 1 + Source/cmVisualStudioGeneratorOptions.cxx | 68 ++++++++++++++++++++++++++++++ Source/cmVisualStudioGeneratorOptions.h | 2 + 8 files changed, 111 insertions(+), 25 deletions(-) diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h index c30ea9a..6a0313a 100644 --- a/Source/cmVS10LinkFlagTable.h +++ b/Source/cmVS10LinkFlagTable.h @@ -29,6 +29,8 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] = { { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", "ItaniumImage", 0 }, + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", "HighestAvailable", 0 }, @@ -123,8 +125,12 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] = { { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, { "GenerateManifest", "MANIFEST", "", "true", 0 }, { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "GenerateDebugInformation", "DEBUG", "", "true", cmVS7FlagTable::CaseInsensitive }, { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, @@ -162,11 +168,8 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] = { { "LinkDLL", "DLL", "", "true", 0 }, // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, - { "EnableUAC", "MANIFESTUAC:", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", - cmVS7FlagTable::UserValueRequired }, + { "EnableUAC", "MANIFESTUAC:", "", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, { "GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "MapFileName", "MAP:", "Generate Map File", "", diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h index 1b3a046..24ba8fd 100644 --- a/Source/cmVS11LinkFlagTable.h +++ b/Source/cmVS11LinkFlagTable.h @@ -29,6 +29,8 @@ static cmVS7FlagTable cmVS11LinkFlagTable[] = { { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", "ItaniumImage", 0 }, + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", "HighestAvailable", 0 }, @@ -135,8 +137,12 @@ static cmVS7FlagTable cmVS11LinkFlagTable[] = { { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, { "GenerateManifest", "MANIFEST", "", "true", 0 }, { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "ManifestEmbed", "manifest:embed", "", "true", 0 }, { "GenerateDebugInformation", "DEBUG", "", "true", cmVS7FlagTable::CaseInsensitive }, @@ -179,11 +185,8 @@ static cmVS7FlagTable cmVS11LinkFlagTable[] = { { "LinkDLL", "DLL", "", "true", 0 }, // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, - { "EnableUAC", "MANIFESTUAC:", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", - cmVS7FlagTable::UserValueRequired }, + { "EnableUAC", "MANIFESTUAC:", "", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, { "GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "MapFileName", "MAP:", "Generate Map File", "", diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h index 168c34c..fc667c3 100644 --- a/Source/cmVS12LinkFlagTable.h +++ b/Source/cmVS12LinkFlagTable.h @@ -29,6 +29,8 @@ static cmVS7FlagTable cmVS12LinkFlagTable[] = { { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", "ItaniumImage", 0 }, + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", "HighestAvailable", 0 }, @@ -135,8 +137,12 @@ static cmVS7FlagTable cmVS12LinkFlagTable[] = { { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, { "GenerateManifest", "MANIFEST", "", "true", 0 }, { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "ManifestEmbed", "manifest:embed", "", "true", 0 }, { "GenerateDebugInformation", "DEBUG", "", "true", cmVS7FlagTable::CaseInsensitive }, @@ -179,11 +185,8 @@ static cmVS7FlagTable cmVS12LinkFlagTable[] = { { "LinkDLL", "DLL", "", "true", 0 }, // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, - { "EnableUAC", "MANIFESTUAC:", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", - cmVS7FlagTable::UserValueRequired }, + { "EnableUAC", "MANIFESTUAC:", "", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, { "GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "MapFileName", "MAP:", "Generate Map File", "", diff --git a/Source/cmVS140LinkFlagTable.h b/Source/cmVS140LinkFlagTable.h index b9a4dc3..7c9452a 100644 --- a/Source/cmVS140LinkFlagTable.h +++ b/Source/cmVS140LinkFlagTable.h @@ -29,6 +29,8 @@ static cmVS7FlagTable cmVS140LinkFlagTable[] = { { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", "ItaniumImage", 0 }, + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", "HighestAvailable", 0 }, @@ -148,8 +150,12 @@ static cmVS7FlagTable cmVS140LinkFlagTable[] = { { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, { "GenerateManifest", "MANIFEST", "", "true", 0 }, { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "ManifestEmbed", "manifest:embed", "", "true", 0 }, { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, @@ -190,11 +196,8 @@ static cmVS7FlagTable cmVS140LinkFlagTable[] = { { "LinkDLL", "DLL", "", "true", 0 }, // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, - { "EnableUAC", "MANIFESTUAC:", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", - cmVS7FlagTable::UserValueRequired }, + { "EnableUAC", "MANIFESTUAC:", "", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, { "GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "MapFileName", "MAP:", "Generate Map File", "", diff --git a/Source/cmVS141LinkFlagTable.h b/Source/cmVS141LinkFlagTable.h index 8f0f1f4..d97c00d 100644 --- a/Source/cmVS141LinkFlagTable.h +++ b/Source/cmVS141LinkFlagTable.h @@ -29,6 +29,8 @@ static cmVS7FlagTable cmVS141LinkFlagTable[] = { { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only", "ItaniumImage", 0 }, + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 }, { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable", "HighestAvailable", 0 }, @@ -149,8 +151,12 @@ static cmVS7FlagTable cmVS141LinkFlagTable[] = { { "GenerateManifest", "MANIFEST:NO", "", "false", 0 }, { "GenerateManifest", "MANIFEST", "", "true", 0 }, { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 }, + + // correct flags for uac should be /MANIFESTUAC, but some projects already + // use this bug to access uac field, so keep these for compatibility { "UACUIAccess", "uiAccess='false'", "", "false", 0 }, { "UACUIAccess", "uiAccess='true'", "", "true", 0 }, + { "ManifestEmbed", "manifest:embed", "", "true", 0 }, { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 }, { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 }, @@ -191,11 +197,8 @@ static cmVS7FlagTable cmVS141LinkFlagTable[] = { { "LinkDLL", "DLL", "", "true", 0 }, // Bool Properties With Argument - { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 }, - { "EnableUAC", "MANIFESTUAC:", "", "true", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, - { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "", - cmVS7FlagTable::UserValueRequired }, + { "EnableUAC", "MANIFESTUAC:", "", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SpaceAppendable }, { "GenerateMapFile", "MAP", "", "true", cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, { "MapFileName", "MAP:", "Generate Map File", "", diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 7fe2f2a..b965013 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3261,6 +3261,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( } linkOptions.Parse(flags.c_str()); + linkOptions.FixManifestUACFlags(); if (this->MSTools) { cmGeneratorTarget::ModuleDefinitionInfo const* mdi = diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 51944fa..b1686be 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -256,6 +256,74 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() } } +void cmVisualStudioGeneratorOptions::FixManifestUACFlags() +{ + static const char* ENABLE_UAC = "EnableUAC"; + if (!HasFlag(ENABLE_UAC)) { + return; + } + + const std::string uacFlag = GetFlag(ENABLE_UAC); + std::vector subOptions; + cmsys::SystemTools::Split(uacFlag, subOptions, ' '); + if (subOptions.empty()) { + AddFlag(ENABLE_UAC, "true"); + return; + } + + if (subOptions.size() == 1 && subOptions[0] == "NO") { + AddFlag(ENABLE_UAC, "false"); + return; + } + + std::map uacMap; + uacMap["level"] = "UACExecutionLevel"; + uacMap["uiAccess"] = "UACUIAccess"; + + std::map uacExecuteLevelMap; + uacExecuteLevelMap["asInvoker"] = "AsInvoker"; + uacExecuteLevelMap["highestAvailable"] = "HighestAvailable"; + uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator"; + + for (auto const& subopt : subOptions) { + std::vector keyValue; + cmsys::SystemTools::Split(subopt, keyValue, '='); + if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) { + // ignore none key=value option or unknown flags + continue; + } + + if (keyValue[1].front() == '\'' && keyValue[1].back() == '\'') { + keyValue[1] = + keyValue[1].substr(1, std::max(0, keyValue[1].size() - 2)); + } + + if (keyValue[0] == "level") { + if (uacExecuteLevelMap.find(keyValue[1]) == uacExecuteLevelMap.end()) { + // unknown level value + continue; + } + + AddFlag(uacMap[keyValue[0]].c_str(), + uacExecuteLevelMap[keyValue[1]].c_str()); + continue; + } + + if (keyValue[0] == "uiAccess") { + if (keyValue[1] != "true" && keyValue[1] != "false") { + // unknown uiAccess value + continue; + } + AddFlag(uacMap[keyValue[0]].c_str(), keyValue[1].c_str()); + continue; + } + + // unknwon sub option + } + + AddFlag(ENABLE_UAC, "true"); +} + void cmVisualStudioGeneratorOptions::Parse(const char* flags) { // Parse the input string as a windows command line since the string diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 8d7942b..7c08a2c 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -77,6 +77,8 @@ public: void FixCudaCodeGeneration(); + void FixManifestUACFlags(); + bool IsDebug() const; bool IsWinRt() const; bool IsManaged() const; -- cgit v0.12