DeleteRegKey /ifempty now also checks for values

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7166 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2020-04-12 18:25:21 +00:00
parent 2fa5cd37b8
commit 821b4d6a18
8 changed files with 41 additions and 21 deletions

View file

@ -12,6 +12,8 @@ Released on ? ?th, 2020
\S2{} Major Changes
\b \cw{DeleteRegKey /ifempty} now also checks for values, not just subkeys. Use \cw{/ifnosubkeys} for the old behavior.
\b Added \R{getknownfolderpath}{GetKnownFolderPath}
\S2{} Minor Changes

View file

@ -29,9 +29,9 @@ Deletes the string str_name from section [section_name] from ini_filename. If th
\S2{deleteregkey} DeleteRegKey
\c [/ifempty] root_key subkey
\c [/ifempty | /ifnosubkeys | /ifnovalues] root_key subkey
Deletes a registry key. If /ifempty is specified, the registry key will only be deleted if it has no subkeys (otherwise, the whole registry tree will be removed). Valid values for root_key are listed under \R{writeregstr}{WriteRegStr}. The error flag is set if the key could not be removed from the registry (or if it didn't exist to begin with).
Deletes a registry key. If /ifempty is specified, the registry key will only be deleted if it has no subkeys and no values (otherwise, the whole registry tree will be removed). Valid values for root_key are listed under \R{writeregstr}{WriteRegStr}. The error flag is set if the key could not be removed from the registry (or if it didn't exist to begin with).
\c DeleteRegKey HKLM "Software\My Company\My Software"
\c DeleteRegKey /ifempty HKLM "Software\A key that might have subkeys"

View file

@ -176,33 +176,42 @@ static HKEY NSISCALL RegCreateScriptKey(int RootKey, LPCTSTR SubKey, REGSAM RS)
// 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 DRTF_ONLYIFNOSUBKEYS DELREGKEY_ONLYIFNOSUBKEYS
#define DRTF_ONLYIFNOVALUES DELREGKEY_ONLYIFNOVALUES
static LONG NSISCALL DeleteRegTree(HKEY hThisKey, LPCTSTR SubKey, REGSAM SamviewAndFlags)
{
HKEY hKey;
UINT onlyifempty = SamviewAndFlags & DRTF_ONLYIFNOSUBKEYS;
UINT onlyifnosubkeys = SamviewAndFlags & DRTF_ONLYIFNOSUBKEYS;
UINT onlyifnovalues = SamviewAndFlags & DRTF_ONLYIFNOVALUES, valuesexistcheckinsubkeys = TRUE;
REGSAM samview = SamviewAndFlags & (KEY_WOW64_32KEY|KEY_WOW64_64KEY);
LONG retval = RegKeyOpen(hThisKey, SubKey, KEY_ENUMERATE_SUB_KEYS|samview, &hKey);
LONG retval = RegKeyOpen(hThisKey, SubKey, KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE|samview, &hKey);
if (retval == ERROR_SUCCESS)
{
TCHAR child[MAX_PATH+1]; // NB - don't change this to static (recursive function)
if (onlyifnovalues)
{
DWORD cchName = 0;
retval = RegEnumValue(hKey, 0, child, &cchName, NULL, NULL, NULL, NULL);
if (retval != ERROR_NO_MORE_ITEMS) goto notempty;
if (!valuesexistcheckinsubkeys) SamviewAndFlags &= ~DRTF_ONLYIFNOVALUES;
}
while (RegEnumKey(hKey, 0, child, COUNTOF(child)) == ERROR_SUCCESS)
{
if (onlyifempty) return (RegCloseKey(hKey), ERROR_CAN_NOT_COMPLETE);
if (onlyifnosubkeys) notempty: return (RegCloseKey(hKey), ERROR_CAN_NOT_COMPLETE);
if ((retval = DeleteRegTree(hKey, child, SamviewAndFlags)) != ERROR_SUCCESS) break;
}
RegCloseKey(hKey);
{
typedef LONG (WINAPI * RegDeleteKeyExPtr)(HKEY, LPCTSTR, REGSAM, DWORD);
RegDeleteKeyExPtr RDKE = (RegDeleteKeyExPtr)
#ifdef _WIN64
RegDeleteKeyEx;
#else
typedef LONG (WINAPI * RegDeleteKeyExType)(HKEY, LPCTSTR, REGSAM, DWORD);
RegDeleteKeyExType RDKE = (RegDeleteKeyExType)
#if !defined(_WIN64) || defined(_M_IA64)
myGetProcAddress(MGA_RegDeleteKeyEx);
#endif
if (RDKE)
retval = RDKE(hThisKey, SubKey, samview, 0);
else
if (!RDKE)
retval = RegDeleteKey(hThisKey, SubKey);
else
#else
RegDeleteKeyEx;
#endif
retval = RDKE(hThisKey, SubKey, samview, 0);
}
}
return retval;

View file

@ -550,8 +550,9 @@ typedef struct {
#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
#define DELREGKEY_ONLYIFNOSUBKEYS 0x01 // Note: Shifted (stored as 2 in the binary) for compatibility with <= v3.1
#define DELREGKEY_ONLYIFNOVALUES 0x02
#define DELREGKEYFLAGSSHIFT 1 // exehead removes the DELREG_KEY bit in parm4 by shifting. After shifting the bits are DELREGKEY_*.
#ifdef NSIS_SUPPORT_CREATESHORTCUT

View file

@ -1166,6 +1166,8 @@ struct MGA_FUNC MGA_FUNCS[] = {
#ifndef _WIN64
{"KERNEL32", "GetDiskFreeSpaceExW"},
{"KERNEL32", "GetUserDefaultUILanguage"},
#endif
#if !defined(_WIN64) || defined(_M_IA64)
{"ADVAPI32", "RegDeleteKeyExW"},
#endif
{"ADVAPI32", "InitiateShutdownW"},

View file

@ -164,6 +164,8 @@ enum myGetProcAddressFunctions {
#ifndef _WIN64
MGA_GetDiskFreeSpaceEx,
MGA_GetUserDefaultUILanguage,
#endif
#if !defined(_WIN64) || defined(_M_IA64)
MGA_RegDeleteKeyEx,
#endif
MGA_InitiateShutdown,

View file

@ -4319,11 +4319,15 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
int a=1, iskeyop;
if ((iskeyop = which_token == TOK_DELETEREGKEY))
{
TCHAR *s=line.gettoken_str(a);
if (s[0] == _T('/'))
for (;; ++a)
{
if (_tcsicmp(s,_T("/ifempty"))) PRINTHELP()
a++, ent.offsets[4]|=(DELREGKEY_ONLYIFNOSUBKEYS<<DELREGKEYFLAGSSHIFT);
switch(line.gettoken_enum(a,_T("/ifempty\0/ifnosubkeys\0/ifnovalues\0")))
{
case 0: ent.offsets[4]|=((DELREGKEY_ONLYIFNOSUBKEYS|DELREGKEY_ONLYIFNOVALUES)<<DELREGKEYFLAGSSHIFT); continue;
case 1: ent.offsets[4]|=((DELREGKEY_ONLYIFNOSUBKEYS )<<DELREGKEYFLAGSSHIFT); continue;
case 2: ent.offsets[4]|=(( DELREGKEY_ONLYIFNOVALUES)<<DELREGKEYFLAGSSHIFT); continue;
}
break;
}
if (line.gettoken_str(a+2)[0]) PRINTHELP()
}

View file

@ -62,7 +62,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_DBOPTIMIZE,_T("SetDatablockOptimize"),1,0,_T("(off|on)"),TP_ALL},
{TOK_DELETEINISEC,_T("DeleteINISec"),2,0,_T("ini_file section_name"),TP_CODE},
{TOK_DELETEINISTR,_T("DeleteINIStr"),3,0,_T("ini_file section_name entry_name"),TP_CODE},
{TOK_DELETEREGKEY,_T("DeleteRegKey"),2,1,_T("[/ifempty] root_key subkey\n root_key=(HKCR[32|64]|HKLM[32|64]|HKCU[32|64]|HKU|HKCC|HKDD|HKPD|SHCTX)"),TP_CODE},
{TOK_DELETEREGKEY,_T("DeleteRegKey"),2,-1,_T("[/ifempty | /ifnosubkeys | /ifnovalues] root_key subkey\n root_key=(HKCR[32|64]|HKLM[32|64]|HKCU[32|64]|HKU|HKCC|HKDD|HKPD|SHCTX)"),TP_CODE},
{TOK_DELETEREGVALUE,_T("DeleteRegValue"),3,0,_T("root_key subkey entry_name\n root_key=(HKCR[32|64]|HKLM[32|64]|HKCU[32|64]|HKU|HKCC|HKDD|HKPD|SHCTX)"),TP_CODE},
{TOK_DELETE,_T("Delete"),1,1,_T("[/REBOOTOK] filespec"),TP_CODE},
{TOK_DETAILPRINT,_T("DetailPrint"),1,0,_T("message"),TP_CODE},