diff --git a/Docs/src/registry.but b/Docs/src/registry.but index 880827d9..2d3ae9cc 100644 --- a/Docs/src/registry.but +++ b/Docs/src/registry.but @@ -2,7 +2,7 @@ In all of the below registry instructions use an empty string (just two quotes with nothing between them - "") as the key name to specify the default key which is shown as (Default) in regedit.exe. -Use \R{setregview}{SetRegView} on Windows x64 to choose which registry view is used. +Use \R{setregview}{SetRegView} on 64-bit Windows to choose which registry view is used. If a full path is not specified for any of the INI handling instructions, the Windows directory will be used. @@ -198,7 +198,7 @@ Writes a multi-string value. The /REGEDIT5 switch must be used and specifies tha \S2{setregview} SetRegView -\c \\32\\|64|lastused +\c 32|64|\\default\\|lastused Sets the registry view affected by \R{registry}{registry commands}. On 64-bit versions of Windows there are two views; one for 32-bit applications and one for 64-bit applications. By default, 32-bit applications running on 64-bit systems (WOW64) only have access to the 32-bit view. Using \c{SetRegView 64} allows the installer to access keys in the 64-bit view of the registry. diff --git a/Source/Platform.h b/Source/Platform.h index d4c85eca..f9c45d10 100644 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -642,6 +642,9 @@ typedef DWORDLONG ULONGLONG,*PULONGLONG; # define HKEY_DYN_DATA ((HKEY)0x80000006) #endif +#ifndef KEY_WOW64_32KEY +# define KEY_WOW64_32KEY 0x200 +#endif #ifndef KEY_WOW64_64KEY # define KEY_WOW64_64KEY 0x100 #endif diff --git a/Source/build.cpp b/Source/build.cpp index 47bf8888..673262a1 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -426,24 +426,25 @@ void CEXEBuild::init_shellconstantvalues() static bool done = false; if (done) return ; else done = true; - const int orgunmode = uninstall_mode; + const int orgunmode = uninstall_mode, t64 = is_target_64bit(), reg = 0x80, r32 = t64 ? 0xC0 : reg, r64 = r32 ^ 0x40; set_uninstall_mode(0); // Note: The order matters because some of the strings are preprocessed and cf must be <= 0x40 unsigned int pf = add_asciistring(_T("ProgramFilesDir"), 0); unsigned int cf = add_asciistring(_T("CommonFilesDir"), 0); - unsigned int pf_def = add_asciistring(_T("C:\\Program Files")); - m_ShellConstants.set_values(_T("PROGRAMFILES"), 0x80 | pf, pf_def); - unsigned int pf64_def = add_asciistring(_T("$PROGRAMFILES")); - m_ShellConstants.set_values(_T("PROGRAMFILES32"), 0x80 | pf, pf_def); - m_ShellConstants.set_values(_T("PROGRAMFILES64"), 0xC0 | pf, pf64_def); + unsigned int pf_def = add_asciistring(_T("C:\\Program Files")); // Ultimate fallback + // TODO: 64-bit targets could use CSIDL_PROGRAM_FILES+CSIDL_PROGRAM_FILESX86? + m_ShellConstants.set_values(_T("PROGRAMFILES"), reg | pf, pf_def); + unsigned int pf_var = add_asciistring(_T("$PROGRAMFILES")); // Fallback for the 32/64 specific constants if the WOW registry view fails + m_ShellConstants.set_values(_T("PROGRAMFILES32"), r32 | pf, reg != r32 ? pf_var : pf_def); + m_ShellConstants.set_values(_T("PROGRAMFILES64"), r64 | pf, reg != r64 ? pf_var : pf_def); unsigned int cf_def = add_asciistring(_T("$PROGRAMFILES\\Common Files")); - m_ShellConstants.set_values(_T("COMMONFILES"), 0x80 | cf, cf_def); - unsigned int cf64_def = add_asciistring(_T("$COMMONFILES")); - m_ShellConstants.set_values(_T("COMMONFILES32"), 0x80 | cf, cf_def); - m_ShellConstants.set_values(_T("COMMONFILES64"), 0xC0 | cf, cf64_def); + m_ShellConstants.set_values(_T("COMMONFILES"), reg | cf, cf_def); + unsigned int cf_var = add_asciistring(_T("$COMMONFILES")); + m_ShellConstants.set_values(_T("COMMONFILES32"), r32 | cf, reg != r32 ? cf_var : cf_def); + m_ShellConstants.set_values(_T("COMMONFILES64"), r64 | cf, reg != r64 ? cf_var : cf_def); - if ( (pf >= 0x40 || pf_def >= 0xFF || pf64_def > 0xFF) // BUGBUG: pf_def should be ">"? - || (cf > 0x40 || cf_def > 0xFF || cf64_def > 0xFF) ) + if ( (pf >= 0x40 || pf_def >= 0xFF || pf_var > 0xFF) // BUGBUG: pf_def should be ">"? + || (cf > 0x40 || cf_def > 0xFF || cf_var > 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 @@ -456,17 +457,13 @@ void CEXEBuild::init_shellconstantvalues() unsigned int unpf = add_asciistring(_T("ProgramFilesDir"), 0); unsigned int uncf = add_asciistring(_T("CommonFilesDir"), 0); unsigned int unpf_def = add_asciistring(_T("C:\\Program Files")); - unsigned int unpf64_def = add_asciistring(_T("$PROGRAMFILES")); + unsigned int unpf_var = add_asciistring(_T("$PROGRAMFILES")); unsigned int uncf_def = add_asciistring(_T("$PROGRAMFILES\\Common Files")); - unsigned int uncf64_def = add_asciistring(_T("$COMMONFILES")); + unsigned int uncf_var = add_asciistring(_T("$COMMONFILES")); set_uninstall_mode(orgunmode); - if ( unpf != pf - || unpf_def != pf_def - || unpf64_def != pf64_def - || uncf != cf - || uncf_def != cf_def - || uncf64_def != cf64_def) + if ( unpf != pf || unpf_def != pf_def || unpf_var != pf_var + || uncf != cf || uncf_def != cf_def || uncf_var != cf_var ) { const char* msg = "Internal compiler error: installer's shell constants are different than uninstallers!"; ERROR_MSG(_T("%") NPRIns, msg); diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 48aa5936..39e55780 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -645,14 +645,14 @@ void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) // The value of registry->sub->name is stored in out. If failure, then out becomes // an empty string "". -void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, int x64) +void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, int altview) { HKEY hKey; + const REGSAM wowsam = altview ? (sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY) : 0; *out=0; - if (RegOpenKeyEx(root,sub,0,KEY_READ|(x64?KEY_WOW64_64KEY:0),&hKey) == ERROR_SUCCESS) + if (RegOpenKeyEx(root,sub,0,KEY_READ|wowsam,&hKey) == ERROR_SUCCESS) { - DWORD l = NSIS_MAX_STRLEN*sizeof(TCHAR); - DWORD t; + DWORD l = NSIS_MAX_STRLEN*sizeof(TCHAR), t; // Note that RegQueryValueEx returns Unicode strings if _UNICODE is defined for the // REG_SZ type. if (RegQueryValueEx(hKey,name,NULL,&t,(LPBYTE)out,&l ) != ERROR_SUCCESS || (t != REG_SZ && t != REG_EXPAND_SZ)) *out=0; diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 8280e7b0..fc454eee 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -32,7 +32,7 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab); // use the LANG_STR_TAB() macro to decode it. #define GetNSISTab(strtab) (strtab < 0 ? LANG_STR_TAB(strtab) : strtab) -void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, int x64); +void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, int altview); #define myatoi(s) ( (int)strtoiptr(s) ) INT_PTR NSISCALL strtoiptr(const TCHAR *s); #define myitoa iptrtostr diff --git a/Source/script.cpp b/Source/script.cpp index 74429df7..27d65047 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -4023,15 +4023,12 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) { ent.which=EW_SETFLAG; ent.offsets[0]=FLAG_OFFSET(alter_reg_view); - // "64" results in setting the flag to 1 which alters the view - int k=line.gettoken_enum(1,_T("32\0") _T("64\0lastused\0")); + int k=line.gettoken_enum(1,_T("32\0") _T("64\0default\0lastused\0")); // TODO: Can we support "native" without OS sniffing? Must verify on 9x, NT4 and 2000! if (k<0) PRINTHELP() - if (k == 0) // 32 - ent.offsets[1]=add_intstring(0); - else if (k == 1) // 64 - ent.offsets[1]=add_intstring(KEY_WOW64_64KEY); - else if (k == 2) // last used - ent.offsets[2]=1; + if (k == 0) ent.offsets[1]=add_intstring(is_target_64bit() ? KEY_WOW64_32KEY : 0); // 32 + else if (k == 1) ent.offsets[1]=add_intstring(KEY_WOW64_64KEY); // 64 + else if (k == 2) ent.offsets[1]=add_intstring(0); // default + else if (k == 3) ent.offsets[2]=1; // last used SCRIPT_MSG(_T("SetRegView: %") NPRIs _T("\n"),line.gettoken_str(1)); } return add_entry(&ent); diff --git a/Source/tokens.cpp b/Source/tokens.cpp index fb3a8ecc..98514e55 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -203,7 +203,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_SETOVERWRITE,_T("SetOverwrite"),1,0,_T("on|off|try|ifnewer|ifdiff"),TP_ALL}, {TOK_SETPLUGINUNLOAD,_T("SetPluginUnload"),1,0,_T("deprecated - plug-ins should handle this on their own"),TP_ALL}, {TOK_SETREBOOTFLAG,_T("SetRebootFlag"),1,0,_T("true|false"),TP_CODE}, -{TOK_SETREGVIEW,_T("SetRegView"),1,0,_T("32|64|lastused"),TP_CODE}, +{TOK_SETREGVIEW,_T("SetRegView"),1,0,_T("32|64|default|lastused"),TP_CODE}, {TOK_SETSHELLVARCONTEXT,_T("SetShellVarContext"),1,0,_T("all|current"),TP_CODE}, {TOK_SETSILENT,_T("SetSilent"),1,0,_T("silent|normal"),TP_CODE}, {TOK_SHOWDETAILS,_T("ShowInstDetails"),1,0,_T("(hide|show|nevershow)"),TP_GLOBAL},