Fixed SetRegView and $ProgramFiles[32|64] in 64-bit installers

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6841 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2017-03-22 00:46:25 +00:00
parent a9b56a63fd
commit c1c2ccb4a6
7 changed files with 33 additions and 36 deletions

View file

@ -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 \\<b\\>32\\</b\\>|64|lastused
\c 32|64|\\<b\\>default\\</b\\>|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.

View file

@ -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

View file

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

View file

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

View file

@ -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

View file

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

View file

@ -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},