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);