diff --git a/Docs/src/history.but b/Docs/src/history.but index 4be1a842..dfc1b493 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -24,6 +24,8 @@ Released on ? ?th, 2020 \# Undocumented: \b Added GetShellVarContext, IfAltRegView and GetRegView | Documenting these would require documenting the parameter name to number mapping +\# Undocumented: \b Added ManifestAppendCustomString + \b Added \cw{!define /intfmt} \b Added Date/Time NSD controls and macros diff --git a/Source/manifest.cpp b/Source/manifest.cpp index c4aba72f..bca83eab 100644 --- a/Source/manifest.cpp +++ b/Source/manifest.cpp @@ -21,6 +21,7 @@ #include #include "tstring.h" #include "util.h" // RawTStrToASCII +#include // Jim Park: The manifest must stay UTF-8. Do not convert. @@ -91,6 +92,51 @@ bool SupportedOSList::append(const TCHAR* osid) } +static const TCHAR*g_appendpaths[] = { // Basic simulated XPath support + _T("/"), + _T("/assembly"), + _T("/assembly/dependency"), + _T("/assembly/dependency/dependentAssembly"), + _T("/assembly/compatibility/application"), + _T("/assembly/application/windowsSettings") +}; +std::vector g_appendstrings[COUNTOF(g_appendpaths)]; + +static int isvalidappendpath(const TCHAR*path) +{ + for (int i = 0; i < COUNTOF(g_appendpaths); ++i) + if (!_tcsicmp(path, g_appendpaths[i])) + return i; + return -1; +} + +bool addappendstring(const TCHAR*path, const TCHAR*data) +{ + int i = isvalidappendpath(path); + if (i >= 0) + { + string str = TtoCString(data); + g_appendstrings[i].push_back(str); + return true; + } + return false; +} + +static bool append(string& xml, const TCHAR*path, const char*prefix = 0, const char*suffix = 0) +{ + bool any = false; + int i = isvalidappendpath(path); + if (i >= 0) + for (std::size_t j = 0; j < g_appendstrings[i].size(); ++j) + { + if (!any && prefix) xml += prefix, any = true; + xml += g_appendstrings[i][j]; + } + if (any && suffix) + xml += suffix; + return any; +} + string generate(comctl comctl_selection, exec_level exec_level_selection, const SPECIFICATION&spec) { flags featureflags = spec.Flags; @@ -100,18 +146,28 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const SupportedOSList& sosl = *spec.pSOSL; const TCHAR *mvt = spec.MaxVersionTested; - bool default_or_empty_sosl = sosl.isdefaultlist() || !sosl.getcount(); + bool default_or_empty_sosl = sosl.isdefaultlist() || !sosl.getcount(), any; if (comctl_selection == comctl_old && exec_level_selection == exec_level_none && default_or_empty_sosl && dpiaware_notset == dpia) return ""; + string xmltmp; string xml = "Nullsoft Install System "; xml += TtoCString(NSIS_VERSION); xml += ""; if (comctl_selection == comctl_xp) { - xml += ""; + addappendstring(_T("/assembly/dependency/dependentAssembly"), _T("")); } + xmltmp = ""; + any = append(xmltmp, _T("/assembly/dependency")); + any |= append(xmltmp, _T("/assembly/dependency/dependentAssembly"), "", ""); + if (any) + { + xmltmp += ""; + xml += xmltmp; + } + if (exec_level_selection != exec_level_none) { @@ -142,8 +198,9 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const sosl.deleteall(); } + xmltmp = "", append(xmltmp, _T("/assembly/compatibility/application")); int soslcount = sosl.getcount(); - if (soslcount || *mvt) + if (!xmltmp.empty() || soslcount || *mvt) { char buf[38+1]; xml += ""; @@ -159,6 +216,7 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const xml += TtoCString(mvt); xml += "\"/>"; } + xml += xmltmp; xml += ""; } @@ -193,6 +251,7 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const xml_aws += lpaware_false != lpa ? "true" : "false"; xml_aws += ""; } + append(xml_aws, _T("/assembly/application/windowsSettings")); if (!xml_aws.empty()) { xml += ""; @@ -200,7 +259,9 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const xml += ""; } + append(xml, _T("/assembly")); xml += ""; + append(xml, _T("/")); return xml; } diff --git a/Source/manifest.h b/Source/manifest.h index f68afba1..7c3436a8 100644 --- a/Source/manifest.h +++ b/Source/manifest.h @@ -104,6 +104,7 @@ namespace manifest } SPECIFICATION; std::string generate(comctl, exec_level, const SPECIFICATION&); + bool addappendstring(const TCHAR*path, const TCHAR*data); }; diff --git a/Source/script.cpp b/Source/script.cpp index 8df98a94..92800a03 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -2342,6 +2342,9 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } return PS_OK; + case TOK_MANIFEST_APPENDCUSTOMSTRING: + if (!manifest::addappendstring(line.gettoken_str(1), line.gettoken_str(2))) PRINTHELP(); + return PS_OK; case TOK_MANIFEST_DPIAWARE: switch(line.gettoken_enum(1,_T("none\0notset\0false\0true\0system\0permonitor\0explorer\0"))) { diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 472f3c00..a5d8c1bd 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -263,6 +263,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_PESUBSYSVER,_T("PESubsysVer"),1,0,_T("major.minor"),TP_GLOBAL}, {TOK_XPSTYLE,_T("XPStyle"),1,0,_T("(on|off)"),TP_GLOBAL}, {TOK_REQEXECLEVEL,_T("RequestExecutionLevel"),1,0,_T("none|user|highest|admin"),TP_GLOBAL}, +{TOK_MANIFEST_APPENDCUSTOMSTRING,_T("ManifestAppendCustomString"),2,0,_T("path string"),TP_GLOBAL}, {TOK_MANIFEST_DPIAWARE,_T("ManifestDPIAware"),1,0,_T("notset|true|false"),TP_GLOBAL}, {TOK_MANIFEST_DPIAWARENESS,_T("ManifestDPIAwareness"),1,0,_T("comma_separated_string"),TP_GLOBAL}, {TOK_MANIFEST_LPAWARE,_T("ManifestLongPathAware"),1,0,_T("notset|true|false"),TP_GLOBAL}, diff --git a/Source/tokens.h b/Source/tokens.h index cdc44413..2196506c 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -65,6 +65,7 @@ enum TOK_PESUBSYSVER, TOK_XPSTYLE, TOK_REQEXECLEVEL, + TOK_MANIFEST_APPENDCUSTOMSTRING, TOK_MANIFEST_DPIAWARE, TOK_MANIFEST_DPIAWARENESS, TOK_MANIFEST_LPAWARE,