diff --git a/Docs/src/var.but b/Docs/src/var.but index c89708ba..2f0fb544 100644 --- a/Docs/src/var.but +++ b/Docs/src/var.but @@ -59,13 +59,13 @@ Constants can also be used in the \R{ainstalldir}{InstallDir} attribute. Note that some of the new constants will not work on every OS. For example, $CDBURN_AREA will only work on Windows XP and above. If it's used on Windows 98, it'll be empty. Unless mentioned otherwise, a constant should be available on every OS. -\e{$PROGRAMFILES} +\e{$PROGRAMFILES}, \e{$PROGRAMFILES32}, \e{$PROGRAMFILES64} -The program files directory (usually C:\\Program Files but detected at runtime). +The program files directory (usually C:\\Program Files but detected at runtime). On Windows x64, $PROGRAMFILES and $PROGRAMFILES32 point to \c{C:\\Program Files (x86)} while $PROGRAMFILES64 points to \c{C:\\Program Files}. Use $PROGRAMFILES64 when installing x64 applications. -\e{$COMMONFILES} +\e{$COMMONFILES}, \e{$COMMONFILES32}, \e{$COMMONFILES64} -The common files directory. This is a directory for components that are shared across applications (usually C:\\Program Files\\Common Files but detected at runtime). +The common files directory. This is a directory for components that are shared across applications (usually C:\\Program Files\\Common Files but detected at runtime). On Windows x64, $COMMONFILES and $COMMONFILES32 point to \c{C:\\Program Files (x86)\\Common Files} while $COMMONFILES64 points to \c{C:\\Program Files\\Common Files}. Use $COMMONFILES64 when installing x64 applications. \e{$DESKTOP} diff --git a/Source/build.cpp b/Source/build.cpp index a88df6b2..8005f358 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -309,13 +309,11 @@ CEXEBuild::CEXEBuild() : m_ShellConstants.add("WINDIR",CSIDL_WINDOWS,CSIDL_WINDOWS); m_ShellConstants.add("SYSDIR",CSIDL_SYSTEM,CSIDL_SYSTEM); - m_ShellConstants.add("PROGRAMFILES",CSIDL_PROGRAM_FILES, CSIDL_PROGRAM_FILES); m_ShellConstants.add("SMPROGRAMS",CSIDL_PROGRAMS, CSIDL_COMMON_PROGRAMS); m_ShellConstants.add("SMSTARTUP",CSIDL_STARTUP, CSIDL_COMMON_STARTUP); m_ShellConstants.add("DESKTOP",CSIDL_DESKTOPDIRECTORY, CSIDL_COMMON_DESKTOPDIRECTORY); m_ShellConstants.add("STARTMENU",CSIDL_STARTMENU, CSIDL_COMMON_STARTMENU); m_ShellConstants.add("QUICKLAUNCH", CSIDL_APPDATA, CSIDL_APPDATA); - m_ShellConstants.add("COMMONFILES",CSIDL_PROGRAM_FILES_COMMON, CSIDL_PROGRAM_FILES_COMMON); m_ShellConstants.add("DOCUMENTS",CSIDL_PERSONAL, CSIDL_COMMON_DOCUMENTS); m_ShellConstants.add("SENDTO",CSIDL_SENDTO, CSIDL_SENDTO); m_ShellConstants.add("RECENT",CSIDL_RECENT, CSIDL_RECENT); @@ -339,6 +337,27 @@ CEXEBuild::CEXEBuild() : m_ShellConstants.add("RESOURCES_LOCALIZED", CSIDL_RESOURCES_LOCALIZED, CSIDL_RESOURCES_LOCALIZED); m_ShellConstants.add("CDBURN_AREA", CSIDL_CDBURN_AREA, CSIDL_CDBURN_AREA); + unsigned int program_files = add_string("ProgramFilesDir"); + unsigned int common_files = add_string("CommonFilesDir"); + unsigned int program_files_def = add_string("C:\\Program Files"); + unsigned int common_files_def = add_string("C:\\Program Files\\Common Files"); + + if ((program_files >= 0x40) || (common_files >= 0x40) + || (program_files_def > 0xFF) || (common_files_def > 0xFF)) + { + // see Source\exehead\util.c for implementation details + // basically, it knows it needs to get folders from the registry when the 0x80 is on + ERROR_MSG("Internal compiler error: too many strings added to strings block before adding shell constants!\n"); + throw out_of_range("Internal compiler error: too many strings added to strings block before adding shell constants!"); + } + + m_ShellConstants.add("PROGRAMFILES", 0x80 | program_files, program_files_def); + m_ShellConstants.add("PROGRAMFILES32", 0x80 | program_files, program_files_def); + m_ShellConstants.add("PROGRAMFILES64", 0xC0 | program_files, program_files_def); + m_ShellConstants.add("COMMONFILES", 0x80 | common_files, common_files_def); + m_ShellConstants.add("COMMONFILES32", 0x80 | common_files, common_files_def); + m_ShellConstants.add("COMMONFILES64", 0xC0 | common_files, common_files_def); + set_code_type_predefines(); } diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index 2bf6432e..0170341c 100644 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -250,14 +250,14 @@ FORCE_INLINE int NSISCALL ui_doinstall(void) { // Windows 9x - myRegGetStr(HKEY_CURRENT_USER, reg_9x_locale, NULL, g_tmp); + myRegGetStr(HKEY_CURRENT_USER, reg_9x_locale, NULL, g_tmp, 0); } if (!g_tmp[0]) { // Windows NT // This key exists on 9x as well, so it's only read if ResourceLocale wasn't found - myRegGetStr(HKEY_USERS, reg_nt_locale_key, reg_nt_locale_val, g_tmp); + myRegGetStr(HKEY_USERS, reg_nt_locale_key, reg_nt_locale_val, g_tmp, 0); } mystrcat(state_language, g_tmp); @@ -278,7 +278,8 @@ FORCE_INLINE int NSISCALL ui_doinstall(void) (HKEY)header->install_reg_rootkey, GetNSISStringNP(header->install_reg_key_ptr), GetNSISStringNP(header->install_reg_value_ptr), - ps_tmpbuf + ps_tmpbuf, + 0 ); if (ps_tmpbuf[0]) { diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 35249002..1b6d6d0d 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -515,11 +515,11 @@ void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) } #endif -void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out) +void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64) { HKEY hKey; *out=0; - if (RegOpenKeyEx(root,sub,0,KEY_READ,&hKey) == ERROR_SUCCESS) + if (RegOpenKeyEx(root,sub,0,KEY_READ|(x64?KEY_WOW64_64KEY:0),&hKey) == ERROR_SUCCESS) { DWORD l = NSIS_MAX_STRLEN; DWORD t; @@ -632,6 +632,24 @@ char * NSISCALL GetNSISString(char *outbuf, int strtab) x = 4; } + if (fldrs[0] & 0x80) + { + myRegGetStr(HKEY_LOCAL_MACHINE, SYSREGKEY, GetNSISStringNP(fldrs[0] & 0x3F), out, fldrs[0] & 0x40); + if (!*out) + mystrcpy(out, GetNSISStringNP(fldrs[2])); + x = 0; + } + else if (fldrs[0] == CSIDL_SYSTEM) + { + GetSystemDirectory(out, NSIS_MAX_STRLEN); + x = 0; + } + else if (fldrs[0] == CSIDL_WINDOWS) + { + GetWindowsDirectory(out, NSIS_MAX_STRLEN); + x = 0; + } + while (x--) { if (!SHGetSpecialFolderLocation(g_hwnd, fldrs[x], &idl)) @@ -646,29 +664,6 @@ char * NSISCALL GetNSISString(char *outbuf, int strtab) *out=0; } - // resort to old registry methods, only when CSIDL failed - if (!*out) - { - if (fldrs[0] == CSIDL_PROGRAM_FILES_COMMON) - { - myRegGetStr(HKEY_LOCAL_MACHINE, SYSREGKEY, "CommonFilesDir", out); - } - else if (fldrs[0] == CSIDL_PROGRAM_FILES) - { - myRegGetStr(HKEY_LOCAL_MACHINE, SYSREGKEY, "ProgramFilesDir", out); - if (!*out) - mystrcpy(out, "C:\\Program Files"); - } - else if (fldrs[0] == CSIDL_SYSTEM) - { - GetSystemDirectory(out, NSIS_MAX_STRLEN); - } - else if (fldrs[0] == CSIDL_WINDOWS) - { - GetWindowsDirectory(out, NSIS_MAX_STRLEN); - } - } - if (*out) { // all users' version is CSIDL_APPDATA only for $QUICKLAUNCH diff --git a/Source/exehead/util.h b/Source/exehead/util.h index e3ae6d39..ae6c5cbd 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -23,7 +23,7 @@ char * NSISCALL GetNSISString(char *outbuf, int strtab); #define GetNSISStringTT(strtab) GetNSISString(0, (strtab)) #define GetNSISStringNP(strtab) ((const char *)g_blocks[NB_STRINGS].offset+(strtab)) #define GetNSISTab(strtab) (strtab < 0 ? LANG_STR_TAB(strtab) : strtab) -void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out); +void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64); int NSISCALL myatoi(char *s); void NSISCALL myitoa(char *s, int d); char * NSISCALL mystrcpy(char *out, const char *in);