Unsupported SetRegView mode must fail all registry operations

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6865 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2017-06-04 22:48:13 +00:00
parent a2aa3ed305
commit b558dea54d
12 changed files with 186 additions and 154 deletions

View file

@ -28,9 +28,7 @@
#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
#endif
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#endif
#ifndef SHTDN_REASON_FLAG_PLANNED
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
@ -63,6 +61,8 @@ TCHAR g_caption[NSIS_MAX_STRLEN*2]; // Why does this have to be NSIS_MAX_STRLEN*
HWND g_hwnd;
HANDLE g_hInstance;
#endif
void *g_SHGetFolderPath;
DWORD g_WinVer;
void NSISCALL CleanUp();
@ -77,14 +77,12 @@ TCHAR *ValidateTempDir()
return my_GetTempFileName(state_language, state_temp_dir);
}
void *g_SHGetFolderPath;
NSIS_ENTRYPOINT_GUINOCRT
EXTERN_C void NSISWinMainNOCRT()
{
int ret = 0;
const TCHAR *m_Err = _LANG_ERRORWRITINGTEMP;
int cl_flags = 0;
TCHAR *realcmds;
@ -92,13 +90,14 @@ EXTERN_C void NSISWinMainNOCRT()
TCHAR *cmdline;
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
g_WinVer = GetVersion() & ~(NSIS_WINVER_WOW64FLAG); // We store a private flag in the build number bits
{
// bug #1125: Don't load modules from the application nor current directory.
// SetDefaultDllDirectories() allows us to restrict implicitly loaded and
// dynamically loaded modules to just %windir%\System32 and directories
// added with AddDllDirectory(). This prevents DLL search order attacks (CAPEC-471).
DWORD winver = GetVersion();
DWORD winver = g_WinVer;
// CoCreateInstance(CLSID_ShellLink, ...) fails on Vista if SetDefaultDllDirectories is called
BOOL avoidwinbug = LOWORD(winver) == MAKEWORD(6, 0);
if (!avoidwinbug)
@ -145,6 +144,16 @@ EXTERN_C void NSISWinMainNOCRT()
#endif
g_SHGetFolderPath = myGetProcAddress(MGA_SHGetFolderPath); // and SHFOLDER
#ifndef _WIN64
{
// KEY_WOW64_xxKEY causes registry functions to fail on WinNT4 & Win2000.
// We don't filter them out because all registry instructions are supposed to fail when
// accessing a unsupported view and RegKey* takes care of that by looking at the WOW64 flag.
FARPROC fp = myGetProcAddress(MGA_IsOS);
enum { os_wow6432 = 30 };
if (fp && ((BOOL(WINAPI*)(UINT))fp)(os_wow6432)) g_WinVer |= NSIS_WINVER_WOW64FLAG;
}
#endif
InitCommonControls();

View file

@ -41,20 +41,19 @@ typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
typedef struct
{
int autoclose;
int all_user_var;
int exec_error;
int abort;
int all_user_var; // SetShellVarContext: User context = 0, Machine context = 1
int exec_error; // IfErrors
int abort; // IfAbort
int exec_reboot; // NSIS_SUPPORT_REBOOT
int reboot_called; // NSIS_SUPPORT_REBOOT
int XXX_cur_insttype; // Deprecated
int plugin_api_version; // see NSISPIAPIVER_CURR
// used to be XXX_insttype_changed
int plugin_api_version; // See NSISPIAPIVER_CURR (Note: used to be XXX_insttype_changed)
int silent; // NSIS_CONFIG_SILENT_SUPPORT
int instdir_error;
int rtl;
int errlvl;
int alter_reg_view;
int status_update;
int errlvl; // SetErrorLevel
int alter_reg_view; // SetRegView: Default View = 0, Alternative View = (sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY)
int status_update; // SetDetailsPrint
} exec_flags_t;
#ifndef NSISCALL

View file

@ -156,30 +156,41 @@ static TCHAR * NSISCALL GetStringFromParm(int id_)
}
#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
#define AlterRegistrySAM(sam) (sam | g_exec_flags.alter_reg_view)
// based loosely on code from Tim Kosse
// in win9x this isn't necessary (RegDeleteKey() can delete a tree of keys),
// but in win2k you need to do this manually.
static LONG NSISCALL myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey, int onlyifempty)
static HKEY NSISCALL GetRegRootKey(int RootKey)
{
HKEY key;
int retval=RegOpenKeyEx(thiskey,lpSubKey,0,AlterRegistrySAM(KEY_ENUMERATE_SUB_KEYS),&key);
if (retval==ERROR_SUCCESS)
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
}
static HKEY NSISCALL RegOpenScriptKey(REGSAM RS)
{
HKEY hKey;
return RegKeyOpen(GetRegRootKey(g_parms[1]), GetStringFromParm(0x22), RS|KEY_FROMSCRIPT, &hKey) ? NULL : hKey;
}
static HKEY NSISCALL RegCreateScriptKey(int RootKey, LPCTSTR SubKey, REGSAM RS)
{
HKEY hKey;
return RegKeyCreate(GetRegRootKey(RootKey), SubKey, RS|KEY_FROMSCRIPT, &hKey) ? NULL : hKey;
}
// 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)
{
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);
if (retval == ERROR_SUCCESS)
{
// NB - don't change this to static (recursive function)
TCHAR buffer[MAX_PATH+1];
while (RegEnumKey(key,0,buffer,MAX_PATH+1)==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)
{
RegCloseKey(key);
return !ERROR_SUCCESS;
}
if ((retval=myRegDeleteKeyEx(key,buffer,0)) != ERROR_SUCCESS) break;
if (onlyifempty) return (RegCloseKey(hKey), !ERROR_SUCCESS);
if ((retval = RegDeleteScriptKeyWorker(hKey, child, Flags)) != ERROR_SUCCESS) break;
}
RegCloseKey(key);
RegCloseKey(hKey);
{
typedef LONG (WINAPI * RegDeleteKeyExPtr)(HKEY, LPCTSTR, REGSAM, DWORD);
RegDeleteKeyExPtr RDKE = (RegDeleteKeyExPtr)
@ -189,32 +200,13 @@ static LONG NSISCALL myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey, int onlyif
myGetProcAddress(MGA_RegDeleteKeyEx);
#endif
if (RDKE)
retval=RDKE(thiskey,lpSubKey,AlterRegistrySAM(0),0);
retval = RDKE(hThisKey, SubKey, viewsam, 0);
else
retval=g_exec_flags.alter_reg_view||RegDeleteKey(thiskey,lpSubKey);
retval = RegDeleteKey(hThisKey, SubKey);
}
}
return retval;
}
static HKEY NSISCALL GetRegRootKey(int hRootKey)
{
if (hRootKey)
return (HKEY) (UINT_PTR) hRootKey;
// HKEY_LOCAL_MACHINE - HKEY_CURRENT_USER == 1
return (HKEY) ((UINT_PTR) HKEY_CURRENT_USER + g_exec_flags.all_user_var);
}
static HKEY NSISCALL myRegOpenKey(REGSAM samDesired)
{
HKEY hKey;
if (RegOpenKeyEx(GetRegRootKey(g_parms[1]), GetStringFromParm(0x22), 0, AlterRegistrySAM(samDesired), &hKey) == ERROR_SUCCESS)
{
return hKey;
}
return NULL;
}
#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS
// returns EXEC_ERROR on error
@ -1212,11 +1204,11 @@ static int NSISCALL ExecuteEntry(entry *entry_)
#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
case EW_DELREG:
{
long res=!ERROR_SUCCESS;
const TCHAR *rkn UNUSED=RegKeyHandleToName((HKEY)parm1);
if (!parm4)
long res=!ERROR_SUCCESS, rootkey=parm1;
const TCHAR *rkn UNUSED=RegKeyHandleToName((HKEY)rootkey);
if (!parm4) // TOK_DELETEREGVALUE
{
HKEY hKey=myRegOpenKey(KEY_SET_VALUE);
HKEY hKey=RegOpenScriptKey(KEY_SET_VALUE);
if (hKey)
{
TCHAR *buf3=GetStringFromParm(0x33);
@ -1225,11 +1217,11 @@ static int NSISCALL ExecuteEntry(entry *entry_)
RegCloseKey(hKey);
}
}
else
else // TOK_DELETEREGKEY
{
TCHAR *buf2=GetStringFromParm(0x22);
log_printf3(_T("DeleteRegKey: \"%s\\%s\""),rkn,buf2);
res = myRegDeleteKeyEx(GetRegRootKey(parm1),buf2,parm4&2);
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")
}
if (res != ERROR_SUCCESS)
exec_error++;
@ -1237,16 +1229,14 @@ static int NSISCALL ExecuteEntry(entry *entry_)
break;
case EW_WRITEREG: // write registry value
{
int rootkey=parm0, type=parm4, rtype=parm5;
const TCHAR *rkn UNUSED=RegKeyHandleToName((HKEY)rootkey);
HKEY hKey;
HKEY rootkey=GetRegRootKey(parm0);
int type=parm4;
int rtype=parm5;
TCHAR *buf0=GetStringFromParm(0x02);
TCHAR *buf1=GetStringFromParm(0x11);
const TCHAR *rkn UNUSED=RegKeyHandleToName(rootkey);
exec_error++;
if (RegCreateKeyEx(rootkey,buf1,0,0,0,AlterRegistrySAM(KEY_SET_VALUE),0,&hKey,0) == ERROR_SUCCESS)
if ((hKey = RegCreateScriptKey(rootkey, buf1, KEY_SET_VALUE)))
{
LPBYTE data = (LPBYTE) buf2;
DWORD size = 0;
@ -1297,7 +1287,7 @@ static int NSISCALL ExecuteEntry(entry *entry_)
break;
case EW_READREGSTR: // read registry string
{
HKEY hKey=myRegOpenKey(KEY_READ);
HKEY hKey=RegOpenScriptKey(KEY_READ);
TCHAR *p=var0;
TCHAR *buf3=GetStringFromParm(0x33); // buf3 == key name
p[0]=0;
@ -1333,21 +1323,19 @@ static int NSISCALL ExecuteEntry(entry *entry_)
break;
case EW_REGENUM:
{
HKEY key=myRegOpenKey(KEY_READ);
HKEY hKey=RegOpenScriptKey(KEY_READ);
TCHAR *p=var0;
int b=GetIntFromParm(3);
p[0]=0;
if (key)
p[0]=0; // "" on error. This assumes that RegEnumKey and RegEnumValue do not party on our buffer!
if (hKey)
{
DWORD d=NSIS_MAX_STRLEN-1;
if (parm4) RegEnumKey(key,b,p,d);
else if (RegEnumValue(key,b,p,&d,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
{
DWORD d=NSIS_MAX_STRLEN-1; // -1 is not required here?
if (parm4)
RegEnumKey(hKey,b,p,d);
else if (RegEnumValue(hKey,b,p,&d,NULL,NULL,NULL,NULL) != ERROR_SUCCESS)
exec_error++;
break;
}
p[NSIS_MAX_STRLEN-1]=0;
RegCloseKey(key);
p[NSIS_MAX_STRLEN-1]=0; // Not required?
RegCloseKey(hKey);
}
else exec_error++;
}

View file

@ -155,7 +155,7 @@ enum
#endif
#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key
EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, ActionAndFlags]
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]
@ -510,6 +510,8 @@ typedef struct {
#define DEL_REBOOT 4
#define DEL_SIMPLE 8
#define HKSHCTX ( (HKEY) 0 ) // Converted to HKCU or HKLM by GetRegRootKey
#ifdef NSIS_SUPPORT_CREATESHORTCUT
#define CS_HK_MASK 0xffff0000 // HotKey
#define CS_HK_SHIFT 16

View file

@ -539,7 +539,7 @@ void RenameViaWininit(const TCHAR* prevName, const TCHAR* newName)
int spn; // length of the short path name in TCHARs.
lstrcpy(tmpbuf, _T("NUL"));
mystrcpy(tmpbuf, _T("NUL"));
if (newName) {
// create the file if it's not already there to prevent GetShortPathName from failing
@ -643,22 +643,38 @@ void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew)
}
#endif
// 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 altview)
#define GetAltViewREGSAM() ( sizeof(void*) > 4 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY )
static HKEY 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;
*pRS = sam & ~(NSIS_REGSAM_PRIVATEMASK); // Filter away internal flags
return (incompatsam & sam) ? NULL : hKey; // Fail if the requested view is not supported
}
LONG NSISCALL RegKeyOpen(HKEY hBase, LPCTSTR SubKey, REGSAM RS, HKEY*phKey)
{
if (!(hBase = GetRegKeyAndSAM(hBase, &RS))) return ERROR_INVALID_HANDLE; // ERROR_CANTOPEN?
return RegOpenKeyEx(hBase, SubKey, 0, RS, phKey);
}
LONG NSISCALL RegKeyCreate(HKEY hBase, LPCTSTR SubKey, REGSAM RS, HKEY*phKey)
{
if (!(hBase = GetRegKeyAndSAM(hBase, &RS))) return ERROR_INVALID_HANDLE; // ERROR_CANTOPEN?
return RegCreateKeyEx(hBase, SubKey, 0, 0, 0, RS, 0, phKey, 0);
}
void NSISCALL myRegGetStr(HKEY root, const TCHAR *sub, const TCHAR *name, TCHAR *out, UINT 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|wowsam,&hKey) == ERROR_SUCCESS)
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)
{
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;
out[NSIS_MAX_STRLEN-1]=0;
ec = RegQueryValueEx(hKey, name, NULL, &rt, (LPBYTE)out, &cb);
RegCloseKey(hKey);
out[NSIS_MAX_STRLEN-1] = 0; // Make sure the string is terminated. This could potentially truncate a long string by 1 character!
}
if (ec != ERROR_SUCCESS || (rt != REG_SZ && rt != REG_EXPAND_SZ)) *out = 0; // Empty string on failure
}
void NSISCALL iptrtostr(TCHAR *s, INT_PTR d)
@ -764,8 +780,10 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
int fldrs[4];
if (nVarIdx < NS_SKIP_CODE)
{
// the next 2 BYTEs in the string might be coding either a value 0..MAX_CODED (nData), or 2 CSIDL of Special folders (for NS_SHELL_CODE)
// The next 2 BYTEs in the string might be coding either a value 0..MAX_CODED (nData), or 2 CSIDL of Special folders (for NS_SHELL_CODE)
nData = DECODE_SHORT(in);
// There are 2 CSIDL parameters for each context and query must be used before create
// because of bug #820 (CSIDL_FLAG_CREATE failures on root paths are cached in Vista).
#ifdef _UNICODE
fldrs[1] = LOBYTE(*in); // current user
fldrs[0] = fldrs[1] | CSIDL_FLAG_CREATE;
@ -777,7 +795,6 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
fldrs[2] = in[1] | CSIDL_FLAG_CREATE; // all users
fldrs[3] = in[1];
#endif
//TODO: are fldrs[1] and fldrs[3] really useful? why not force folder creation directly?
in += sizeof(SHORT)/sizeof(TCHAR);
if (nVarIdx == NS_SHELL_CODE)
@ -785,10 +802,8 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
LPITEMIDLIST idl;
int x = 2;
DWORD ver = GetVersion();
DWORD ver = sizeof(void*) > 4 ? MAKEWORD(5, 2) : g_WinVer; // We only care about 95/98 vs ME/NT4+
/*
SHGetFolderPath as provided by shfolder.dll is used to get special folders
unless the installer is running on Windows 95/98. For 95/98 shfolder.dll is
only used for the Application Data and Documents folder (if the DLL exists).
@ -802,9 +817,7 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
SHGetFolderPath in shell32.dll could be called directly for Windows versions
later than 95/98 but there is no need to do so, because shfolder.dll is still
provided and calls shell32.dll.
*/
BOOL use_shfolder =
// Use shfolder if not on 95/98
!((ver & 0x80000000) && (LOWORD(ver) != 0x5A04)) ||
@ -819,7 +832,7 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
if (g_exec_flags.all_user_var)
{
x = 4;
x = 4; // Get common folder > Create common folder > Get user folder > Create user folder
}
if (fldrs[1] & 0x80)
@ -829,12 +842,12 @@ TCHAR * NSISCALL GetNSISString(TCHAR *outbuf, int strtab)
GetNSISString(out, fldrs[3]);
x = 0;
}
else if (fldrs[1] == CSIDL_SYSTEM)
else if (fldrs[1] == CSIDL_SYSTEM) // Does not work on 95, 98 nor NT4. Works on ME and 2000+.
{
GetSystemDirectory(out, NSIS_MAX_STRLEN);
x = 0;
}
else if (fldrs[1] == CSIDL_WINDOWS)
else if (fldrs[1] == CSIDL_WINDOWS) // Does not work on 95, 98 nor NT4. Works on ME and 2000+.
{
GetWindowsDirectory(out, NSIS_MAX_STRLEN);
x = 0;
@ -982,22 +995,14 @@ void NSISCALL log_write(int close)
const TCHAR * _RegKeyHandleToName(HKEY hKey)
{
if (hKey == HKEY_CLASSES_ROOT)
return _T("HKEY_CLASSES_ROOT");
else if (hKey == HKEY_CURRENT_USER)
return _T("HKEY_CURRENT_USER");
else if (hKey == HKEY_LOCAL_MACHINE)
return _T("HKEY_LOCAL_MACHINE");
else if (hKey == HKEY_USERS)
return _T("HKEY_USERS");
else if (hKey == HKEY_PERFORMANCE_DATA)
return _T("HKEY_PERFORMANCE_DATA");
else if (hKey == HKEY_CURRENT_CONFIG)
return _T("HKEY_CURRENT_CONFIG");
else if (hKey == HKEY_DYN_DATA)
return _T("HKEY_DYN_DATA");
else
return _T("invalid registry key");
if (hKey == HKEY_CLASSES_ROOT) return _T("HKEY_CLASSES_ROOT");
if (hKey == HKEY_CURRENT_USER) return _T("HKEY_CURRENT_USER");
if (hKey == HKEY_LOCAL_MACHINE) return _T("HKEY_LOCAL_MACHINE");
if (hKey == HKEY_USERS) return _T("HKEY_USERS");
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");
return _T("HK??");
}
void _LogData2Hex(TCHAR *buf, size_t cchbuf, BYTE *data, size_t cbdata)
@ -1103,6 +1108,9 @@ struct MGA_FUNC MGA_FUNCS[] = {
#endif
{"ADVAPI32", "InitiateShutdownW"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS
#endif
{"SHLWAPI", "SHAutoComplete"},
{"SHFOLDER", "SHGetFolderPathW"},
#ifdef NSIS_SUPPORT_GETDLLVERSION
@ -1118,6 +1126,9 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"ADVAPI32", "RegDeleteKeyExA"},
{"ADVAPI32", "InitiateShutdownA"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS
#endif
{"SHLWAPI", "SHAutoComplete"},
{"SHFOLDER", "SHGetFolderPathA"},
#ifdef NSIS_SUPPORT_GETDLLVERSION

View file

@ -32,7 +32,6 @@ 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 altview);
#define myatoi(s) ( (int)strtoiptr(s) )
INT_PTR NSISCALL strtoiptr(const TCHAR *s);
#define myitoa iptrtostr
@ -41,6 +40,22 @@ TCHAR * NSISCALL mystrcpy(TCHAR *out, const TCHAR *in);
int NSISCALL mystrlen(const TCHAR *in);
TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat);
TCHAR * NSISCALL mystrstr(TCHAR *a, TCHAR *b);
#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)
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);
extern DWORD g_WinVer; // GetVersion()
#define NSIS_WINVER_WOW64FLAG ( sizeof(void*) > 4 ? ( 0 ) : ( 0x40000000 ) )
#define IsWow64() ( sizeof(void*) > 4 ? ( FALSE ) : ( g_WinVer & NSIS_WINVER_WOW64FLAG ) )
#define SystemSupportsAltRegView() ( sizeof(void*) > 4 ? ( TRUE ) : ( IsWow64() ) )
WIN32_FIND_DATA * NSISCALL file_exists(TCHAR *buf);
TCHAR * NSISCALL my_GetTempFileName(TCHAR *buf, const TCHAR *dir);
BOOL NSISCALL myReadFile(HANDLE h, LPVOID buf, DWORD cb);
@ -134,6 +149,9 @@ enum myGetProcAddressFunctions {
#endif
MGA_InitiateShutdown,
MGA_IsUserAnAdmin,
#ifndef _WIN64
MGA_IsOS,
#endif
MGA_SHAutoComplete, // x64 can link to shlwapi directly but as long as MGA_SHGetFolderPath is used we can stick with myGetProcAddress
MGA_SHGetFolderPath, // TODO: This can probably call something else directly on x64
#ifdef NSIS_SUPPORT_GETDLLVERSION