From 94dd438510be96ef920370972c6adc3408a7920f Mon Sep 17 00:00:00 2001 From: anders_k Date: Tue, 6 Jun 2017 19:51:43 +0000 Subject: [PATCH] Added the HKCR32, HKCR64, HKCU32, HKCU64, HKLM32 and HKLM64 root keys and the experimental HK*ANY root keys. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6871 212acab6-be3b-0410-9dea-997c60f758d6 --- Contrib/System/Source/System.c | 2 +- Docs/src/history.but | 6 ++++-- Docs/src/registry.but | 25 ++++++++++++++++------ Source/exehead/exec.c | 27 ++++++++++++++--------- Source/exehead/fileform.h | 27 ++++++++++++++++++++++- Source/exehead/util.c | 39 ++++++++++++++++++++++++++++------ Source/exehead/util.h | 9 ++++++-- Source/script.cpp | 14 ++++++------ Source/tokens.cpp | 22 +++++++++---------- 9 files changed, 125 insertions(+), 46 deletions(-) diff --git a/Contrib/System/Source/System.c b/Contrib/System/Source/System.c index a1153416..dbe8cf45 100644 --- a/Contrib/System/Source/System.c +++ b/Contrib/System/Source/System.c @@ -971,7 +971,7 @@ void ParamsIn(SystemProc *proc) #endif case PAT_CALLBACK: // Generate new or use old callback - if (lstrlen(realbuf) > 0) + if (realbuf[0]) par->Value = (INT_PTR) CreateCallback((SystemProc*) StrToIntPtr(realbuf)); break; case PAT_REGMEM: diff --git a/Docs/src/history.but b/Docs/src/history.but index 514422f7..af12ecbc 100644 --- a/Docs/src/history.but +++ b/Docs/src/history.but @@ -8,9 +8,11 @@ Released on ? ?th, 2017 \S2{} Major Changes -\b Fixed RegTool Win9x bug +\b Fixed NSIS3 RegTool Win9x bug -\b Unsupported SetRegView mode fails all registry operations +\b Added the HKCR32, HKCR64, HKCU32, HKCU64, HKLM32 and HKLM64 root keys + +\b Unsupported SetRegView mode now fails all registry operations \b Added \R{execshellwait}{ExecShellWait} diff --git a/Docs/src/registry.but b/Docs/src/registry.but index 2d3ae9cc..cb442f53 100644 --- a/Docs/src/registry.but +++ b/Docs/src/registry.but @@ -182,6 +182,12 @@ Write a string to the registry. \e{root_key} must be one of: \b \e{SHCTX} or \e{SHELL_CONTEXT} +\b \e{HKCR32} or \e{HKCR64} + +\b \e{HKCU32} or \e{HKCU64} + +\b \e{HKLM32} or \e{HKLM64} + If \e{root_key} is \e{SHCTX} or \e{SHELL_CONTEXT}, it will be replaced with \e{HKLM} if \R{setshellvarcontext}{SetShellVarContext} is set to \e{all} and with \e{HKCU} if \R{setshellvarcontext}{SetShellVarContext} is set to \e{current}. The error flag is set if the string could not be written to the registry. The type of the string will be REG_SZ for \R{writeregstr}{WriteRegStr}, or REG_EXPAND_STR for \R{writeregexpandstr}{WriteRegExpandStr}. If the registry key doesn't exist it will be created. @@ -200,7 +206,7 @@ Writes a multi-string value. The /REGEDIT5 switch must be used and specifies tha \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. +Sets the registry view affected by \R{registry}{registry commands} (root keys with a 32/64 suffix are not affected). 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. Registry operations will fail if the selected view is not supported by Windows. Affects \R{deleteregkey}{DeleteRegKey}, \R{deleteregvalue}{DeleteRegValue}, \R{enumregkey}{EnumRegKey}, \R{enumregvalue}{EnumRegValue}, \R{readregdword}{ReadRegDWORD}, \R{readregstr}{ReadRegStr}, \R{writeregbin}{WriteRegBin}, \R{writeregdword}{WriteRegDWORD}, \R{writeregstr}{WriteRegStr} and \R{writeregexpandstr}{WriteRegExpandStr}. @@ -209,12 +215,17 @@ Does not affect \R{ainstalldirregkey}{InstallDirRegKey}. Instead, the registry m \c SetRegView 32 \c ReadRegStr $0 HKLM Software\Microsoft\Windows\CurrentVersion ProgramFilesDir \c DetailPrint $0 # prints C:\Program Files (x86) -\c SetRegView 64 -\c ReadRegStr $0 HKLM Software\Microsoft\Windows\CurrentVersion ProgramFilesDir -\c DetailPrint $0 # prints C:\Program Files +\c !include x64.nsh +\c ${If} ${RunningX64} +\c SetRegView 64 +\c ReadRegStr $0 HKLM Software\Microsoft\Windows\CurrentVersion ProgramFilesDir +\c DetailPrint $0 # prints C:\Program Files +\c ${EndIf} \c Function .onInit -\c SetRegView 64 -\c ReadRegStr $INSTDIR HKLM Software\NSIS "" -\c SetRegView 32 +\c ${If} ${RunningX64} +\c SetRegView 64 +\c ReadRegStr $INSTDIR HKLM Software\NSIS "" +\c SetRegView Default +\c ${EndIf} \c FunctionEnd diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 210cd6cb..1a5bb895 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -158,8 +158,8 @@ static TCHAR * NSISCALL GetStringFromParm(int id_) #ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS static HKEY NSISCALL GetRegRootKey(int RootKey) { - if (RootKey != (int) HKSHCTX) return (HKEY) (UINT_PTR) RootKey; - return (HKEY) ((UINT_PTR) HKEY_CURRENT_USER + g_exec_flags.all_user_var); // SHCTX: HKEY_CURRENT_USER + 1 == HKEY_LOCAL_MACHINE + if (RootKey < 0) return (HKEY) (UINT_PTR) RootKey; + return (HKEY) ((UINT_PTR) HKEY_CURRENT_USER + RootKey + g_exec_flags.all_user_var); // SHCTX[32|64|ANY]: HKEY_CURRENT_USER + 1 == HKEY_LOCAL_MACHINE } static HKEY NSISCALL RegOpenScriptKey(REGSAM RS) { @@ -175,20 +175,20 @@ static HKEY NSISCALL RegCreateScriptKey(int RootKey, LPCTSTR SubKey, REGSAM RS) // RegDeleteKey on Win9x will delete a tree of keys, WinNT will only delete a key without subkeys. // RegDeleteKeyEx on 32-bit Windows accepts but ignores the KEY_WOW64_xxKEY flags and always uses the // one and only native key. Our RegKeyOpen will intentionally fail if a incompatible WoW64 flag is used. -#define RegDeleteScriptKey(RootKey, SubKey, Flags) RegDeleteScriptKeyWorker(GetRegRootKey(RootKey), (SubKey), (Flags)) -static LONG NSISCALL RegDeleteScriptKeyWorker(HKEY hThisKey, LPCTSTR SubKey, UINT Flags) +#define DRTF_ONLYIFNOSUBKEYS DELREGKEY_ONLYIFNOSUBKEYS +static LONG NSISCALL DeleteRegTree(HKEY hThisKey, LPCTSTR SubKey, REGSAM SamviewAndFlags) { HKEY hKey; - UINT onlyifempty = Flags; - REGSAM viewsam = g_exec_flags.alter_reg_view; // Not using KEY_ALTERVIEW here because viewsam is also passed to RegDeleteKeyEx. - LONG retval = RegKeyOpen(hThisKey, SubKey, KEY_ENUMERATE_SUB_KEYS|viewsam, &hKey); + UINT onlyifempty = SamviewAndFlags & DRTF_ONLYIFNOSUBKEYS; + REGSAM samview = SamviewAndFlags & (KEY_WOW64_32KEY|KEY_WOW64_64KEY); + LONG retval = RegKeyOpen(hThisKey, SubKey, KEY_ENUMERATE_SUB_KEYS|samview, &hKey); if (retval == ERROR_SUCCESS) { TCHAR child[MAX_PATH+1]; // NB - don't change this to static (recursive function) while (RegEnumKey(hKey, 0, child, COUNTOF(child)) == ERROR_SUCCESS) { if (onlyifempty) return (RegCloseKey(hKey), !ERROR_SUCCESS); - if ((retval = RegDeleteScriptKeyWorker(hKey, child, Flags)) != ERROR_SUCCESS) break; + if ((retval = DeleteRegTree(hKey, child, SamviewAndFlags)) != ERROR_SUCCESS) break; } RegCloseKey(hKey); { @@ -200,13 +200,20 @@ static LONG NSISCALL RegDeleteScriptKeyWorker(HKEY hThisKey, LPCTSTR SubKey, UIN myGetProcAddress(MGA_RegDeleteKeyEx); #endif if (RDKE) - retval = RDKE(hThisKey, SubKey, viewsam, 0); + retval = RDKE(hThisKey, SubKey, samview, 0); else retval = RegDeleteKey(hThisKey, SubKey); } } return retval; } +static LONG NSISCALL RegDeleteScriptKey(int RootKey, LPCTSTR SubKey, REGSAM SamviewAndFlags) +{ + HKEY hKey; + SamviewAndFlags |= KEY_FROMSCRIPT; + hKey = GetRegKeyAndSAM(GetRegRootKey(RootKey), &SamviewAndFlags); + return hKey ? DeleteRegTree(hKey, SubKey, SamviewAndFlags) : ERROR_INVALID_HANDLE; // ERROR_CANTOPEN? +} #endif//NSIS_SUPPORT_REGISTRYFUNCTIONS // returns EXEC_ERROR on error @@ -1219,7 +1226,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) { TCHAR *buf2=GetStringFromParm(0x22); log_printf3(_T("DeleteRegKey: \"%s\\%s\""),rkn,buf2); - res = RegDeleteScriptKey(rootkey,buf2,parm4 >> 1); // Shifting away the TOK_DELETEREGKEY bit, onlyifempty is now the bottom bit (">> 1" is 1 byte smaller than "& 2") + res = RegDeleteScriptKey(rootkey,buf2,parm4 >> DELREGKEYFLAGSSHIFT); // SHR is 1 byte smaller than AND } if (res != ERROR_SUCCESS) exec_error++; diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index d35652ea..87105a3c 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -155,7 +155,7 @@ enum #endif #ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS - EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, ActionAndFlags] + EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, ActionAndFlags(DELREG*)] EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen] // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str] @@ -504,13 +504,37 @@ typedef struct { # define ctlcolors ctlcolors32 #endif + // constants for myDelete (util.c) #define DEL_DIR 1 #define DEL_RECURSE 2 #define DEL_REBOOT 4 #define DEL_SIMPLE 8 + +#define REGROOTVIEW32 0x40000000 +#define REGROOTVIEW64 0x20000000 +#define REGROOTVIEWTOSAMVIEW(rv) ( ((UINT_PTR)(rv)&(REGROOTVIEW32|REGROOTVIEW64)) >> 21 ) // REGROOTVIEWxx to KEY_WOW64_xxKEY +#define IsRegRootkeyForcedView(hKey) ( ((UINT_PTR) (hKey) & (REGROOTVIEW32|REGROOTVIEW64)) ) +#define MAKEREGROOTVIEW(r, fv) ( (HKEY) ((UINT_PTR)(r) | (fv)) ) #define HKSHCTX ( (HKEY) 0 ) // Converted to HKCU or HKLM by GetRegRootKey +#define HKSHCTX32 MAKEREGROOTVIEW(HKSHCTX, REGROOTVIEW32) +#define HKSHCTX64 MAKEREGROOTVIEW(HKSHCTX, REGROOTVIEW64) +#define HKCR32 MAKEREGROOTVIEW(HKEY_CLASSES_ROOT, REGROOTVIEW32) +#define HKCR64 MAKEREGROOTVIEW(HKEY_CLASSES_ROOT, REGROOTVIEW64) +#define HKCU32 MAKEREGROOTVIEW(HKEY_CURRENT_USER, REGROOTVIEW32) +#define HKCU64 MAKEREGROOTVIEW(HKEY_CURRENT_USER, REGROOTVIEW64) +#define HKLM32 MAKEREGROOTVIEW(HKEY_LOCAL_MACHINE, REGROOTVIEW32) +#define HKLM64 MAKEREGROOTVIEW(HKEY_LOCAL_MACHINE, REGROOTVIEW64) +#define HKSHCTXANY MAKEREGROOTVIEW(HKSHCTX, REGROOTVIEW32|REGROOTVIEW64) +#define HKCRANY MAKEREGROOTVIEW(HKEY_CLASSES_ROOT, REGROOTVIEW32|REGROOTVIEW64) +#define HKCUANY MAKEREGROOTVIEW(HKEY_CURRENT_USER, REGROOTVIEW32|REGROOTVIEW64) +#define HKLMANY MAKEREGROOTVIEW(HKEY_LOCAL_MACHINE, REGROOTVIEW32|REGROOTVIEW64) +#define DELREG_VALUE 0 // TOK_DELETEREGVALUE +#define DELREG_KEY 1 // TOK_DELETEREGKEY +#define DELREGKEY_ONLYIFNOSUBKEYS 1 // Shifted and stored as 2 in the binary for compatibility with <= 3.1 +#define DELREGKEYFLAGSSHIFT 1 // parm4 is shifted so exehead can remove the DELREG_KEY bit + #ifdef NSIS_SUPPORT_CREATESHORTCUT #define CS_HK_MASK 0xffff0000 // HotKey @@ -523,6 +547,7 @@ typedef struct { #define CS_II_MAX (CS_II_MASK >> CS_II_SHIFT) #endif + // special escape characters used in strings: (we use control codes in order to minimize conflicts with normal characters) #define NS_LANG_CODE _T('\x01') // for a langstring #define NS_SHELL_CODE _T('\x02') // for a shell folder path diff --git a/Source/exehead/util.c b/Source/exehead/util.c index 138b9f68..d72a12cd 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -655,11 +655,25 @@ void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) #endif #define GetAltViewREGSAM() ( sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY ) -static HKEY GetRegKeyAndSAM(HKEY hKey, REGSAM*pRS) +HKEY NSISCALL GetRegKeyAndSAM(HKEY hKey, REGSAM*pRS) { - REGSAM sam = *pRS, otherview = GetAltViewREGSAM(); - REGSAM incompatsam = SystemSupportsAltRegView() ? 0 : otherview; - if (sam & KEY_ALTERVIEW) sam |= g_exec_flags.alter_reg_view; + const REGSAM samviewmask = (KEY_WOW64_32KEY|KEY_WOW64_64KEY); + const REGSAM incompatsamview = SystemSupportsAltRegView() ? 0 : GetAltViewREGSAM(); + REGSAM sam = *pRS, incompatsam = incompatsamview; +#ifdef C_ASSERT + {C_ASSERT(REGROOTVIEWTOSAMVIEW(REGROOTVIEW32|REGROOTVIEW64) == (KEY_WOW64_32KEY|KEY_WOW64_64KEY));} +#endif + if ((sam & KEY_FORCEVIEW) && IsRegRootkeyForcedView(hKey)) + { + REGSAM keysamview = REGROOTVIEWTOSAMVIEW(hKey); + if (keysamview == samviewmask) keysamview = (g_exec_flags.alter_reg_view & ~incompatsamview); // HKxxANY tries to honor SetRegView + sam &= ~samviewmask, sam |= (keysamview & ~(sizeof(void*) > 4 ? 0 : KEY_WOW64_32KEY)); // HKxx32 has the *_32KEY bit set but WinNT4&2000 cannot handle any KEY_WOW64_xxKEY flags. + hKey = (HKEY) ( (UINT_PTR) hKey & ~(REGROOTVIEW32|REGROOTVIEW64) ); + } + else if (sam & KEY_ALTERVIEW) + { + sam |= g_exec_flags.alter_reg_view; // We don't mask away the incompatsamview bits because the operation is supposed to fail if the view is not supported. + } *pRS = sam & ~(NSIS_REGSAM_PRIVATEMASK); // Filter away internal flags return (incompatsam & sam) ? NULL : hKey; // Fail if the requested view is not supported } @@ -678,8 +692,8 @@ void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR { HKEY hKey; DWORD cb = NSIS_MAX_STRLEN*sizeof(TCHAR), rt, ec; - REGSAM viewsam = altview ? GetAltViewREGSAM() : 0; - if ((ec = RegKeyOpen(root, sub, KEY_READ|viewsam, &hKey)) == ERROR_SUCCESS) + REGSAM samview = altview ? GetAltViewREGSAM() : 0; + if ((ec = RegKeyOpen(root, sub, KEY_READ|samview, &hKey)) == ERROR_SUCCESS) { ec = RegQueryValueEx(hKey, name, NULL, &rt, (LPBYTE)out, &cb); RegCloseKey(hKey); @@ -1013,6 +1027,19 @@ const TCHAR * _RegKeyHandleToName(HKEY hKey) if (hKey == HKEY_PERFORMANCE_DATA) return _T("HKEY_PERFORMANCE_DATA"); if (hKey == HKEY_CURRENT_CONFIG) return _T("HKEY_CURRENT_CONFIG"); if (hKey == HKEY_DYN_DATA) return _T("HKEY_DYN_DATA"); + if (hKey == HKSHCTX) return _T("HKSHCTX"); + if (hKey == HKSHCTX32) return _T("HKSHCTX32"); + if (hKey == HKSHCTX64) return _T("HKSHCTX64"); + if (hKey == HKCR32) return _T("HKCR32"); + if (hKey == HKCR64) return _T("HKCR64"); + if (hKey == HKCU32) return _T("HKCU32"); + if (hKey == HKCU64) return _T("HKCU64"); + if (hKey == HKLM32) return _T("HKLM32"); + if (hKey == HKLM64) return _T("HKLM64"); + if (hKey == HKSHCTXANY) return _T("HKSHCTXANY"); + if (hKey == HKCRANY) return _T("HKCRANY"); + if (hKey == HKCUANY) return _T("HKCUANY"); + if (hKey == HKLMANY) return _T("HKLMANY"); return _T("HK??"); } diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 087eee52..08b06d5c 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -42,9 +42,14 @@ TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat); TCHAR * NSISCALL mystrstr(TCHAR *a, TCHAR *b); +#ifndef KEY_CREATE_LINK +#define KEY_CREATE_LINK 0x0020 +#endif +#define KEY_FORCEVIEW KEY_CREATE_LINK // Our private flag used by RegKey* to indicate that we want it to handle HKLM[32|64] style root keys. Cannot be set if the HKEY is a real handle! #define KEY_ALTERVIEW SYNCHRONIZE // Our private flag used by RegKey* to indicate that we want it to apply g_exec_flags.alter_reg_view. (MSDN:"Registry keys do not support the SYNCHRONIZE standard access right") -#define KEY_FROMSCRIPT (KEY_ALTERVIEW) // Use this flag for registry operations from a .nsi script -#define NSIS_REGSAM_PRIVATEMASK (KEY_FROMSCRIPT|KEY_ALTERVIEW) +#define KEY_FROMSCRIPT (KEY_FORCEVIEW|KEY_ALTERVIEW) // Use this flag for registry operations from a .nsi script +#define NSIS_REGSAM_PRIVATEMASK (KEY_FROMSCRIPT|KEY_FORCEVIEW|KEY_ALTERVIEW) +HKEY NSISCALL GetRegKeyAndSAM(HKEY hKey, REGSAM*pRS); LONG NSISCALL RegKeyOpen(HKEY hBase, LPCTSTR SubKey, REGSAM RS, HKEY*phKey); LONG NSISCALL RegKeyCreate(HKEY hBase, LPCTSTR SubKey, REGSAM RS, HKEY*phKey); void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, UINT altview); diff --git a/Source/script.cpp b/Source/script.cpp index 8a0fa442..ae0efff3 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -47,6 +47,7 @@ using namespace std; #endif #define REGROOTKEYTOINT(hk) ( (INT) (((INT_PTR)(hk)) & 0xffffffff) ) // Masking off non-existing top bits to make GCC happy +#define REGROOTKEYTOINTEX(hk, removeviewbits) ( REGROOTKEYTOINT(hk) & ~(removeviewbits ? (REGROOTVIEW32|REGROOTVIEW64) : 0) ) #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT static bool LookupWinSysColorId(const TCHAR*Str, UINT&Clr) @@ -849,11 +850,11 @@ int CEXEBuild::process_jump(LineParser &line, int wt, int *offs) static HKEY ParseRegRootKey(LineParser &line, int tok) { static const TCHAR *rootkeys[2] = { - _T("HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0SHCTX\0"), + _T("HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0SHCTX\0HKCR32\0HKCR64\0HKCU32\0HKCU64\0HKLM32\0HKLM64\0HKCRANY\0HKCUANY\0HKLMANY\0SHCTX32\0SHCTX64\0SHCTXANY\0"), _T("HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0SHELL_CONTEXT\0") }; static const HKEY rootkey_tab[] = { - HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA,HKSHCTX + HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA,HKSHCTX,HKCR32,HKCR64,HKCU32,HKCU64,HKLM32,HKLM64,HKCRANY,HKCUANY,HKLMANY,HKSHCTX32,HKSHCTX64,HKSHCTXANY }; int k = line.gettoken_enum(tok, rootkeys[0]); if (k == -1) k = line.gettoken_enum(tok, rootkeys[1]); @@ -1690,6 +1691,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) HKEY hRK = ParseRegRootKey(line,1); if (INVALIDREGROOT == hRK) PRINTHELP() if (HKSHCTX == hRK) PRINTHELP() // SHCTX is invalid here + if (IsRegRootkeyForcedView(hRK)) PRINTHELP() // 32|64 views are also invalid build_header.install_reg_rootkey=REGROOTKEYTOINT(hRK); build_header.install_reg_key_ptr = add_string(line.gettoken_str(2),0); if (line.gettoken_str(2)[0] == _T('\\')) @@ -4186,24 +4188,24 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) case TOK_DELETEREGVALUE: case TOK_DELETEREGKEY: { - int a=1, iskeyop, delkeyflag=1, onlyifemptyflag=2; + int a=1, iskeyop; if ((iskeyop = which_token == TOK_DELETEREGKEY)) { - ent.offsets[4]=(delkeyflag); TCHAR *s=line.gettoken_str(a); if (s[0] == _T('/')) { if (_tcsicmp(s,_T("/ifempty"))) PRINTHELP() - a++, ent.offsets[4]=(delkeyflag|onlyifemptyflag); + a++, ent.offsets[4]|=(DELREGKEY_ONLYIFNOSUBKEYS<