diff --git a/Docs/src/attributes.but b/Docs/src/attributes.but
index 5b481443..86a7fa92 100644
--- a/Docs/src/attributes.but
+++ b/Docs/src/attributes.but
@@ -293,6 +293,20 @@ Declare that the installer is DPI-aware. A DPI-aware application is not scaled b
See \W{http://msdn.microsoft.com/en-us/library/dd464660}{MSDN} for more information about DPI-aware applications.
+\S2{amanifestlongpathaware} ManifestLongPathAware
+
+\c \\notset\\|true|false
+
+Declare that the installer can handle paths longer than MAX_PATH. Only supported on Windows 10 Anniversary Update and later.
+
+\NsisWarnBlockContainerBegin
+\\Note: \\ Instructions like CopyFiles and CreateShortcut do not support long paths!
+\NsisWarnBlockContainerEnd
+
+\NsisWarnBlockContainerBegin
+\\Note: \\ Has no effect if the "Enable Win32 long paths" policy is not enabled.
+\NsisWarnBlockContainerEnd
+
\S2{amanifestsupportedos} ManifestSupportedOS
\c none|all|WinVista|\\Win7|Win8|Win8.1|Win10\\|{GUID} [...]
diff --git a/Docs/src/history.but b/Docs/src/history.but
index c4e4f2f9..032250d3 100644
--- a/Docs/src/history.but
+++ b/Docs/src/history.but
@@ -18,6 +18,8 @@ ANSI targets are deprecated, consider moving to Unicode.
\# Undocumented: \b Added ManifestMaxVersionTested
+\b Added experimental \R{amanifestlongpathaware}{ManifestLongPathAware} attribute
+
\b Allow quoted library path in System::Call (\W{http://sf.net/p/nsis/bugs/546}{bug #546} and \W{http://sf.net/p/nsis/bugs/1225}{bug #1225})
\b %1 in !finalize command can be specified multiple times
diff --git a/Docs/style.css b/Docs/style.css
index 40d8363c..aa53721b 100644
--- a/Docs/style.css
+++ b/Docs/style.css
@@ -48,8 +48,8 @@ a:hover {
text-decoration: underline;
}
.wb {
- background-color: #FFFFCC;
+ background-color: #FFFFD8;
color: #000000;
- border: 1px solid #646400;
+ border: 1px solid #CECEAA;
padding: 0.2em;
}
\ No newline at end of file
diff --git a/Source/build.cpp b/Source/build.cpp
index d7707722..710938ca 100644
--- a/Source/build.cpp
+++ b/Source/build.cpp
@@ -283,6 +283,7 @@ CEXEBuild::CEXEBuild(signed char pponly, bool warnaserror) :
manifest_comctl = manifest::comctl_old;
manifest_exec_level = manifest::exec_level_admin;
manifest_dpiaware = manifest::dpiaware_notset;
+ manifest_lpaware = manifest::lpaware_notset;
manifest_sosl.setdefault();
enable_last_page_cancel=0;
@@ -2383,12 +2384,15 @@ int CEXEBuild::SetManifest()
{
try {
init_res_editor();
- manifest::SPECIFICATION spec = { (manifest::flags) manifest_flags, manifest_dpiaware, manifest_dpiawareness.c_str(), manifest_sosl, manifest_maxversiontested.c_str() };
+ manifest::SPECIFICATION spec = { (manifest::flags) manifest_flags, manifest_dpiaware, manifest_dpiawareness.c_str(), manifest_lpaware, manifest_sosl, manifest_maxversiontested.c_str() };
string manifest = manifest::generate(manifest_comctl, manifest_exec_level, spec);
if (manifest == "")
return PS_OK;
+ if (!build_unicode && manifest_lpaware >= manifest::lpaware_true)
+ throw std::runtime_error("Incompatible option");
+
// TODO: Ideally we should allow this but we must be sure that the manifest is custom and not a manifest from the stub
//if (res_editor->ResourceExists(MAKEINTRESOURCE(24), 1, CResourceEditor::ANYLANGID))
// return PS_OK; // Allow user to completely override the manifest with PEAddResource
diff --git a/Source/build.h b/Source/build.h
index ef289ca0..465435a0 100644
--- a/Source/build.h
+++ b/Source/build.h
@@ -683,6 +683,7 @@ class CEXEBuild {
manifest::exec_level manifest_exec_level;
manifest::dpiaware manifest_dpiaware;
tstring manifest_dpiawareness;
+ manifest::longpathaware manifest_lpaware;
manifest::SupportedOSList manifest_sosl;
tstring manifest_maxversiontested;
diff --git a/Source/manifest.cpp b/Source/manifest.cpp
index 344b2d7b..68ed5c8b 100644
--- a/Source/manifest.cpp
+++ b/Source/manifest.cpp
@@ -96,6 +96,7 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const
flags featureflags = spec.Flags;
dpiaware dpia = spec.DPIA;
const TCHAR *dpia2 = spec.DPIA2;
+ longpathaware lpa = spec.lpaware;
SupportedOSList& sosl = spec.SOSL;
const TCHAR *mvt = spec.MaxVersionTested;
@@ -186,6 +187,12 @@ string generate(comctl comctl_selection, exec_level exec_level_selection, const
xml_aws += TtoCString(dpia2);
xml_aws += "";
}
+ if (lpaware_notset != lpa)
+ {
+ xml_aws += "";
+ xml_aws += lpaware_false != lpa ? "true" : "false";
+ xml_aws += "";
+ }
if (!xml_aws.empty())
{
xml += "";
diff --git a/Source/manifest.h b/Source/manifest.h
index 8f98dd18..84cc8d6d 100644
--- a/Source/manifest.h
+++ b/Source/manifest.h
@@ -26,7 +26,7 @@ namespace manifest
{
enum flags
{
- disablewindowfiltering = 0x01, // Win8+
+ disablewindowfiltering = 0x01, // Win8+ (Allow EnumWindows() to return Windows 8 immersive apps)
gdiscaling = 0x02, // Win10FU1703+
flags_default = 0
};
@@ -50,10 +50,17 @@ namespace manifest
dpiaware_notset,
dpiaware_false,
dpiaware_true, // System DPI on Vista+
- dpiaware_permonitor, // System DPI on Vista/7/8, PerMonitor on 8.1+
+ dpiaware_permonitor, // System DPI on Vista/7/8, PerMonitor on 8.1+ (Undocumented because we don't handle WM_DPICHANGED)
dpiaware_explorer // Win8.1+? Undocumented?
};
+ enum longpathaware
+ {
+ lpaware_notset,
+ lpaware_false,
+ lpaware_true // Win10.0.14352+
+ };
+
class SupportedOSList // Win7+
{
StringList m_list;
@@ -91,6 +98,7 @@ namespace manifest
flags Flags;
dpiaware DPIA;
const TCHAR *DPIA2; // Win10FU1607+
+ longpathaware lpaware;
SupportedOSList& SOSL;
const TCHAR *MaxVersionTested; // Win10FU1903+ github.com/microsoft/AppConsult-WinAppsModernizationWorkshop/tree/master/Exercise2
} SPECIFICATION;
diff --git a/Source/script.cpp b/Source/script.cpp
index 0afb0578..e7413425 100644
--- a/Source/script.cpp
+++ b/Source/script.cpp
@@ -2347,6 +2347,17 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
manifest_dpiawareness = line.gettoken_str(1);
return PS_OK;
+ case TOK_MANIFEST_LPAWARE:
+ switch(line.gettoken_enum(1,_T("none\0notset\0true\0false\0")))
+ {
+ case 0: // A lot of attributes use "none" so we support that along with the documented value
+ case 1: manifest_lpaware = manifest::lpaware_notset; break;
+ case 2: manifest_lpaware = manifest::lpaware_true; break;
+ case 3: manifest_lpaware = manifest::lpaware_false; break;
+ default: PRINTHELP();
+ }
+ return PS_OK;
+
case TOK_MANIFEST_SUPPORTEDOS:
{
manifest_sosl.deleteall();
@@ -2374,6 +2385,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
default: PRINTHELP();
}
return PS_OK;
+
case TOK_MANIFEST_GDISCALING:
switch(line.gettoken_enum(1,_T("notset\0false\0true")))
{
diff --git a/Source/tokens.cpp b/Source/tokens.cpp
index 8112b714..582aa183 100644
--- a/Source/tokens.cpp
+++ b/Source/tokens.cpp
@@ -258,6 +258,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_REQEXECLEVEL,_T("RequestExecutionLevel"),1,0,_T("none|user|highest|admin"),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},
{TOK_MANIFEST_SUPPORTEDOS,_T("ManifestSupportedOS"),1,-1,_T("none|all|WinVista|Win7|Win8|Win8.1|Win10|{GUID} [...]"),TP_GLOBAL},
{TOK_MANIFEST_MAXVERSIONTESTED,_T("ManifestMaxVersionTested"),1,0,_T("maj.min.bld.rev"),TP_GLOBAL},
{TOK_MANIFEST_DISABLEWINDOWFILTERING,_T("ManifestDisableWindowFiltering"),1,0,_T("notset|true"),TP_GLOBAL},
diff --git a/Source/tokens.h b/Source/tokens.h
index cdc0fefa..e7964388 100644
--- a/Source/tokens.h
+++ b/Source/tokens.h
@@ -67,6 +67,7 @@ enum
TOK_REQEXECLEVEL,
TOK_MANIFEST_DPIAWARE,
TOK_MANIFEST_DPIAWARENESS,
+ TOK_MANIFEST_LPAWARE,
TOK_MANIFEST_SUPPORTEDOS,
TOK_MANIFEST_MAXVERSIONTESTED,
TOK_MANIFEST_DISABLEWINDOWFILTERING,
diff --git a/Source/util.cpp b/Source/util.cpp
index fed50407..35223e56 100644
--- a/Source/util.cpp
+++ b/Source/util.cpp
@@ -1192,7 +1192,7 @@ bool WINAPI WinStdIO_OStreamWrite(WINSIO_OSDATA&osd, const wchar_t *Str, UINT cc
if ((UINT)-1 == cch) cch = (UINT)_tcslen(Str);
DWORD cbio;
if (WinStdIO_IsConsole(osd))
- return !!WriteConsoleW(osd.hNative, Str, cch, &cbio, 0) || !cch;
+ return WriteConsoleW(osd.hNative, Str, cch, &cbio, 0) || !cch;
NOStream strm(osd.hCRT);
NStreamEncoding &enc = strm.StreamEncoding();
enc.SetCodepage(osd.cp);