
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6047 212acab6-be3b-0410-9dea-997c60f758d6
1657 lines
44 KiB
C
1657 lines
44 KiB
C
/*
|
|
* exec.c
|
|
*
|
|
* This file is a part of NSIS.
|
|
*
|
|
* Copyright (C) 1999-2009 Nullsoft and Contributors
|
|
*
|
|
* Licensed under the zlib/libpng license (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
*
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty.
|
|
*
|
|
* Unicode support by Jim Park -- 08/13/2007
|
|
*/
|
|
|
|
#include "../Platform.h"
|
|
#include <shlobj.h>
|
|
#include <shellapi.h>
|
|
#include "fileform.h"
|
|
#include "util.h"
|
|
#include "state.h"
|
|
#include "ui.h"
|
|
#include "components.h"
|
|
#include "exec.h"
|
|
#include "plugin.h"
|
|
#include "lang.h"
|
|
#include "resource.h"
|
|
#include "api.h"
|
|
#include "../tchar.h"
|
|
|
|
#define EXEC_ERROR 0x7FFFFFFF
|
|
|
|
#ifdef NSIS_CONFIG_COMPONENTPAGE
|
|
HWND g_SectionHack;
|
|
#endif
|
|
|
|
#ifdef NSIS_SUPPORT_STACK
|
|
typedef struct _stack_t {
|
|
struct _stack_t *next;
|
|
TCHAR text[NSIS_MAX_STRLEN];
|
|
} stack_t;
|
|
|
|
static stack_t *g_st;
|
|
#endif
|
|
|
|
exec_flags_t g_exec_flags;
|
|
exec_flags_t g_exec_flags_last_used;
|
|
|
|
extra_parameters plugin_extra_parameters = {
|
|
&g_exec_flags,
|
|
&ExecuteCodeSegment,
|
|
&validate_filename,
|
|
&RegisterPluginCallback
|
|
};
|
|
|
|
#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
|
|
HRESULT g_hres;
|
|
#endif
|
|
|
|
static int NSISCALL ExecuteEntry(entry *entry_);
|
|
|
|
/**
|
|
* If v is negative, then the address to resolve is actually
|
|
* stored in the global user variables. Convert the value
|
|
* to integer and return.
|
|
*/
|
|
int NSISCALL resolveaddr(int v)
|
|
{
|
|
if (v < 0)
|
|
{
|
|
return myatoi(g_usrvars[-(v+1)]);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
int NSISCALL ExecuteCodeSegment(int pos, HWND hwndProgress)
|
|
{
|
|
while (pos >= 0)
|
|
{
|
|
int rv;
|
|
if (g_entries[pos].which == EW_RET) return 0;
|
|
rv=ExecuteEntry(g_entries + pos);
|
|
if (rv == EXEC_ERROR) return EXEC_ERROR;
|
|
|
|
rv=resolveaddr(rv);
|
|
|
|
if (!rv) { rv++; pos++; }
|
|
else
|
|
{
|
|
int t=pos;
|
|
rv--; // rv is decremented here by 1, since it was +1 on the other end.
|
|
pos=rv; // set new position
|
|
rv-=t; // set rv to delta for progress adjustment
|
|
}
|
|
|
|
if (hwndProgress)
|
|
{
|
|
extern int progress_bar_pos, progress_bar_len;
|
|
progress_bar_pos+=rv;
|
|
SendMessage(hwndProgress,PBM_SETPOS,MulDiv(progress_bar_pos,30000,progress_bar_len),0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef NSIS_SUPPORT_CODECALLBACKS
|
|
|
|
int NSISCALL ExecuteCallbackFunction(int num)
|
|
{
|
|
return ExecuteCodeSegment(*(&g_header->code_onInit + num), NULL);
|
|
}
|
|
|
|
#endif
|
|
|
|
static TCHAR bufs[5][NSIS_MAX_STRLEN];
|
|
static int *parms;
|
|
|
|
void NSISCALL update_status_text_buf1(int strtab)
|
|
{
|
|
update_status_text(strtab, bufs[1]);
|
|
}
|
|
|
|
static int NSISCALL GetIntFromParm(int id_)
|
|
{
|
|
return myatoi(GetNSISStringTT(parms[id_]));
|
|
}
|
|
|
|
// NB - USE CAUTION when rearranging code to make use of the new return value of
|
|
// this function - be sure the parm being accessed is not modified before the call.
|
|
// Use a negative number to get the string validated as a file name
|
|
// Note: Calling GetNSISString has the side effect that the buffer holding
|
|
// the string to expand gets modified.
|
|
// When calling this function with numbers like 0x13, it means create the string
|
|
// from the string ID found in entry.offset[3] and put it into bufs[0].
|
|
static TCHAR * NSISCALL GetStringFromParm(int id_)
|
|
{
|
|
int id = id_ < 0 ? -id_ : id_;
|
|
TCHAR *result = GetNSISString(bufs[id >> 4], parms[id & 0xF]);
|
|
if (id_ < 0) validate_filename(result);
|
|
return result;
|
|
}
|
|
|
|
#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)
|
|
{
|
|
HKEY key;
|
|
int retval=RegOpenKeyEx(thiskey,lpSubKey,0,AlterRegistrySAM(KEY_ENUMERATE_SUB_KEYS),&key);
|
|
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)
|
|
{
|
|
if (onlyifempty)
|
|
{
|
|
RegCloseKey(key);
|
|
return !ERROR_SUCCESS;
|
|
}
|
|
if ((retval=myRegDeleteKeyEx(key,buffer,0)) != ERROR_SUCCESS) break;
|
|
}
|
|
RegCloseKey(key);
|
|
{
|
|
typedef LONG (WINAPI * RegDeleteKeyExPtr)(HKEY, LPCTSTR, REGSAM, DWORD);
|
|
RegDeleteKeyExPtr RDKE = (RegDeleteKeyExPtr)
|
|
myGetProcAddress(MGA_RegDeleteKeyEx);
|
|
|
|
if (RDKE)
|
|
retval=RDKE(thiskey,lpSubKey,AlterRegistrySAM(0),0);
|
|
else
|
|
retval=g_exec_flags.alter_reg_view||RegDeleteKey(thiskey,lpSubKey);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
static HKEY NSISCALL GetRegRootKey(int hRootKey)
|
|
{
|
|
if (hRootKey)
|
|
return (HKEY) hRootKey;
|
|
|
|
// HKEY_LOCAL_MACHINE - HKEY_CURRENT_USER == 1
|
|
return (HKEY) ((int) HKEY_CURRENT_USER + g_exec_flags.all_user_var);
|
|
}
|
|
|
|
static HKEY NSISCALL myRegOpenKey(REGSAM samDesired)
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKeyEx(GetRegRootKey(parms[1]), GetStringFromParm(0x22), 0, AlterRegistrySAM(samDesired), &hKey) == ERROR_SUCCESS)
|
|
{
|
|
return hKey;
|
|
}
|
|
return NULL;
|
|
}
|
|
#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
|
|
// returns EXEC_ERROR on error
|
|
// returns 0, advance position by 1
|
|
// otherwise, returns new_position+1
|
|
static int NSISCALL ExecuteEntry(entry *entry_)
|
|
{
|
|
TCHAR *buf0 = bufs[0];
|
|
TCHAR *buf1 = bufs[1];
|
|
TCHAR *buf2 = bufs[2];
|
|
TCHAR *buf3 = bufs[3];
|
|
//char *buf4 = bufs[4];
|
|
|
|
TCHAR *var0;
|
|
TCHAR *var1;
|
|
//char *var2;
|
|
//char *var3;
|
|
//char *var4;
|
|
//char *var5;
|
|
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
// Saves 8 bytes
|
|
HWND mainHwnd = g_hwnd;
|
|
#define g_hwnd mainHwnd
|
|
#endif
|
|
|
|
int exec_error = 0;
|
|
|
|
entry lent = *entry_;
|
|
|
|
#define which (lent.which)
|
|
#define parm0 (lent.offsets[0])
|
|
#define parm1 (lent.offsets[1])
|
|
#define parm2 (lent.offsets[2])
|
|
#define parm3 (lent.offsets[3])
|
|
#define parm4 (lent.offsets[4])
|
|
#define parm5 (lent.offsets[5])
|
|
|
|
var0 = g_usrvars[parm0];
|
|
var1 = g_usrvars[parm1];
|
|
// not used yet
|
|
//var2 = g_usrvars[parm2];
|
|
//var3 = g_usrvars[parm3];
|
|
//var4 = g_usrvars[parm4];
|
|
//var5 = g_usrvars[parm5];
|
|
|
|
parms = lent.offsets;
|
|
|
|
switch (which)
|
|
{
|
|
case EW_NOP:
|
|
log_printf2(_T("Jump: %d"),parm0);
|
|
return parm0;
|
|
case EW_ABORT:
|
|
{
|
|
log_printf2(_T("Aborting: \"%s\""),GetStringFromParm(0x00));
|
|
update_status_text(parm0,0);
|
|
}
|
|
return EXEC_ERROR;
|
|
case EW_QUIT:
|
|
g_quit_flag++;
|
|
if (g_hwnd) PostQuitMessage(0); // make sure we bail out fast.
|
|
return EXEC_ERROR;
|
|
case EW_CALL:
|
|
{
|
|
int v=resolveaddr(parm0)-1; // address is -1, since we encode it as +1
|
|
log_printf2(_T("Call: %d"),v);
|
|
return ExecuteCodeSegment(v,NULL);
|
|
}
|
|
case EW_UPDATETEXT:
|
|
log_printf2(_T("detailprint: %s"),GetStringFromParm(0x00));
|
|
update_status_text(parm0,0);
|
|
break;
|
|
case EW_SLEEP:
|
|
{
|
|
int x=GetIntFromParm(0);
|
|
log_printf2(_T("Sleep(%d)"),x);
|
|
Sleep(max(x,1));
|
|
}
|
|
break;
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case EW_BRINGTOFRONT:
|
|
log_printf(_T("BringToFront"));
|
|
SetForegroundWindow(g_hwnd);
|
|
break;
|
|
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case EW_SETFLAG:
|
|
if (!parm2)
|
|
{
|
|
FIELDN(g_exec_flags_last_used,parm0)=FIELDN(g_exec_flags,parm0);
|
|
FIELDN(g_exec_flags,parm0)=GetIntFromParm(1);
|
|
}
|
|
else
|
|
{
|
|
FIELDN(g_exec_flags,parm0)=FIELDN(g_exec_flags_last_used,parm0);
|
|
}
|
|
break;
|
|
case EW_IFFLAG:
|
|
{
|
|
int f=lent.offsets[!FIELDN(g_exec_flags,parm2)];
|
|
FIELDN(g_exec_flags,parm2)&=parm3;
|
|
return f;
|
|
}
|
|
case EW_GETFLAG:
|
|
myitoa(var0,FIELDN(g_exec_flags,parm1));
|
|
break;
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case EW_CHDETAILSVIEW:
|
|
if (insthwndbutton) ShowWindow(insthwndbutton,parm1);
|
|
if (insthwnd) ShowWindow(insthwnd,parm0);
|
|
break;
|
|
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
|
|
case EW_SETFILEATTRIBUTES:
|
|
{
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
log_printf3(_T("SetFileAttributes: \"%s\":%08X"),buf1,parm1);
|
|
if (!SetFileAttributes(buf1,parm1))
|
|
{
|
|
exec_error++;
|
|
log_printf(_T("SetFileAttributes failed."));
|
|
}
|
|
}
|
|
break;
|
|
case EW_CREATEDIR: {
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
log_printf3(_T("CreateDirectory: \"%s\" (%d)"),buf1,parm1);
|
|
{
|
|
TCHAR *p = skip_root(buf1);
|
|
TCHAR c = _T('c');
|
|
if (p)
|
|
{
|
|
while (c)
|
|
{
|
|
p = findchar(p, _T('\\'));
|
|
c = *p;
|
|
*p = 0;
|
|
if (!CreateDirectory(buf1, NULL))
|
|
{
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS)
|
|
{
|
|
log_printf3(_T("CreateDirectory: can't create \"%s\" (err=%d)"),buf1,GetLastError());
|
|
exec_error++;
|
|
}
|
|
else if ((GetFileAttributes(buf1) & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
|
{
|
|
log_printf2(_T("CreateDirectory: can't create \"%s\" - a file already exists"),buf1);
|
|
exec_error++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log_printf2(_T("CreateDirectory: \"%s\" created"),buf1);
|
|
}
|
|
*p++ = c;
|
|
}
|
|
}
|
|
}
|
|
if (parm1)
|
|
{
|
|
update_status_text_buf1(LANG_OUTPUTDIR);
|
|
mystrcpy(state_output_directory,buf1);
|
|
if (!SetCurrentDirectory(buf1))
|
|
{
|
|
log_printf3("SetCurrentDirectory(%s) failed (%d)",buf1,GetLastError());
|
|
exec_error++;
|
|
}
|
|
}
|
|
else update_status_text_buf1(LANG_CREATEDIR);
|
|
}
|
|
break;
|
|
case EW_IFFILEEXISTS:
|
|
{
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
if (file_exists(buf0))
|
|
{
|
|
log_printf3(_T("IfFileExists: file \"%s\" exists, jumping %d"),buf0,parm1);
|
|
return parm1;
|
|
}
|
|
log_printf3(_T("IfFileExists: file \"%s\" does not exist, jumping %d"),buf0,parm2);
|
|
}
|
|
return parm2;
|
|
#ifdef NSIS_SUPPORT_RENAME
|
|
case EW_RENAME:
|
|
{
|
|
TCHAR *buf3=GetStringFromParm(-0x30);
|
|
TCHAR *buf2=GetStringFromParm(-0x21);
|
|
TCHAR *buf1=GetStringFromParm(0x13);
|
|
log_printf2(_T("Rename: %s"),buf1);
|
|
if (MoveFile(buf3,buf2))
|
|
{
|
|
update_status_text_buf1(LANG_RENAME);
|
|
}
|
|
else
|
|
{
|
|
#ifdef NSIS_SUPPORT_MOVEONREBOOT
|
|
if (parm2 && file_exists(buf3))
|
|
{
|
|
MoveFileOnReboot(buf3,buf2);
|
|
update_status_text_buf1(LANG_RENAMEONREBOOT);
|
|
log_printf2(_T("Rename on reboot: %s"),buf1);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
exec_error++;
|
|
log_printf2(_T("Rename failed: %s"),buf1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_RENAME
|
|
#ifdef NSIS_SUPPORT_FNUTIL
|
|
case EW_GETFULLPATHNAME:
|
|
{
|
|
TCHAR *fp;
|
|
TCHAR *p=var1;
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
if (!GetFullPathName(buf0,NSIS_MAX_STRLEN,p,&fp))
|
|
{
|
|
exec_error++;
|
|
*p=0;
|
|
}
|
|
else if (fp>buf0 && *fp)
|
|
{
|
|
WIN32_FIND_DATA *fd=file_exists(buf0);
|
|
if (fd)
|
|
{
|
|
mystrcpy(fp,fd->cFileName);
|
|
}
|
|
else
|
|
{
|
|
exec_error++;
|
|
*p=0;
|
|
}
|
|
}
|
|
if (!parm2) GetShortPathName(p,p,NSIS_MAX_STRLEN);
|
|
}
|
|
break;
|
|
case EW_SEARCHPATH:
|
|
{
|
|
TCHAR *fp;
|
|
TCHAR *p=var0;
|
|
TCHAR *buf0=GetStringFromParm(-0x01);
|
|
if (!SearchPath(NULL,buf0,NULL,NSIS_MAX_STRLEN,p,&fp))
|
|
{
|
|
exec_error++;
|
|
p[0]=0;
|
|
}
|
|
}
|
|
break;
|
|
case EW_GETTEMPFILENAME:
|
|
{
|
|
TCHAR *textout=var0;
|
|
if (!my_GetTempFileName(textout, GetStringFromParm(-0x11)))
|
|
exec_error++;
|
|
}
|
|
break;
|
|
#endif
|
|
#ifdef NSIS_SUPPORT_FILE
|
|
case EW_EXTRACTFILE:
|
|
{
|
|
HANDLE hOut;
|
|
int ret;
|
|
TCHAR *buf3 = GetStringFromParm(0x31);
|
|
int overwriteflag = parm0 & 7;
|
|
|
|
log_printf4(_T("File: overwriteflag=%d, allowskipfilesflag=%d, name=\"%s\""),overwriteflag,(parm0>>3)&MB_ABORTRETRYIGNORE,buf3);
|
|
if (validpathspec(buf3))
|
|
{
|
|
mystrcpy(buf0,buf3);
|
|
}
|
|
else mystrcat(addtrailingslash(mystrcpy(buf0,state_output_directory)),buf3);
|
|
validate_filename(buf0);
|
|
_tryagain:
|
|
if (overwriteflag >= 3) // check date and time
|
|
{
|
|
WIN32_FIND_DATA *ffd=file_exists(buf0);
|
|
// if it doesn't exist, overwrite flag will be off (though it doesn't really matter)
|
|
int cmp=0;
|
|
if (ffd)
|
|
{
|
|
cmp=CompareFileTime(&ffd->ftLastWriteTime, (FILETIME*)(lent.offsets + 3));
|
|
}
|
|
overwriteflag=!(cmp & (0x80000000 | (overwriteflag - 3)));
|
|
}
|
|
// remove read only flag if overwrite mode is on
|
|
if (!overwriteflag)
|
|
{
|
|
remove_ro_attr(buf0);
|
|
}
|
|
hOut=myOpenFile(buf0,GENERIC_WRITE,(overwriteflag==1)?CREATE_NEW:CREATE_ALWAYS);
|
|
if (hOut == INVALID_HANDLE_VALUE)
|
|
{
|
|
if (overwriteflag)
|
|
{
|
|
update_status_text(LANG_SKIPPED,buf3);
|
|
if (overwriteflag==2) exec_error++;
|
|
log_printf3(_T("File: skipped: \"%s\" (overwriteflag=%d)"),buf0,overwriteflag);
|
|
break;
|
|
}
|
|
log_printf2(_T("File: error creating \"%s\""),buf0);
|
|
|
|
mystrcpy(buf2,g_usrvars[0]); // save $0
|
|
mystrcpy(g_usrvars[0],buf0); // copy file name to $0
|
|
GetNSISString(buf1,parm5); // use $0
|
|
mystrcpy(g_usrvars[0],buf2); // restore $0
|
|
|
|
// Modified by ramon 23 May 2003
|
|
switch (my_MessageBox(buf1, parm0>>3))
|
|
{
|
|
case IDRETRY:
|
|
log_printf(_T("File: error, user retry"));
|
|
goto _tryagain;
|
|
case IDIGNORE:
|
|
log_printf(_T("File: error, user cancel"));
|
|
g_exec_flags.exec_error++;
|
|
return 0;
|
|
default:
|
|
log_printf(_T("File: error, user abort"));
|
|
update_status_text(LANG_CANTWRITE,buf0);
|
|
return EXEC_ERROR;
|
|
}
|
|
}
|
|
|
|
update_status_text(LANG_EXTRACT,buf3);
|
|
{
|
|
g_exec_flags.status_update++;
|
|
ret=GetCompressedDataFromDataBlock(parm2,hOut);
|
|
g_exec_flags.status_update--;
|
|
}
|
|
|
|
log_printf3(_T("File: wrote %d to \"%s\""),ret,buf0);
|
|
|
|
if (parm3 != 0xffffffff || parm4 != 0xffffffff)
|
|
SetFileTime(hOut,(FILETIME*)(lent.offsets+3),NULL,(FILETIME*)(lent.offsets+3));
|
|
|
|
CloseHandle(hOut);
|
|
|
|
if (ret < 0)
|
|
{
|
|
if (ret == -2)
|
|
{
|
|
GetNSISString(buf0,LANG_ERRORWRITING);
|
|
mystrcat(buf0,buf3);
|
|
}
|
|
else
|
|
{
|
|
GetNSISString(buf0,LANG_ERRORDECOMPRESSING);
|
|
}
|
|
log_printf2(_T("%s"),buf0);
|
|
my_MessageBox(buf0,MB_OK|MB_ICONSTOP|(IDOK<<21));
|
|
return EXEC_ERROR;
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_FILE
|
|
#ifdef NSIS_SUPPORT_DELETE
|
|
case EW_DELETEFILE:
|
|
{
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
log_printf2(_T("Delete: \"%s\""),buf0);
|
|
myDelete(buf0,parm1);
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_DELETE
|
|
#ifdef NSIS_SUPPORT_MESSAGEBOX
|
|
case EW_MESSAGEBOX: // MessageBox
|
|
{
|
|
int v;
|
|
TCHAR *buf3=GetStringFromParm(0x31);
|
|
log_printf3(_T("MessageBox: %d,\"%s\""),parm0,buf3);
|
|
v=my_MessageBox(buf3,parm0);
|
|
if (v)
|
|
{
|
|
if (v==parm2)
|
|
{
|
|
return parm3;
|
|
}
|
|
if (v==parm4)
|
|
{
|
|
return parm5;
|
|
}
|
|
}
|
|
else exec_error++;
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_MESSAGEBOX
|
|
#ifdef NSIS_SUPPORT_RMDIR
|
|
case EW_RMDIR:
|
|
{
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
log_printf2(_T("RMDir: \"%s\""),buf1);
|
|
|
|
myDelete(buf1,parm1);
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_RMDIR
|
|
#ifdef NSIS_SUPPORT_STROPTS
|
|
case EW_STRLEN:
|
|
{
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
myitoa(var0,mystrlen(buf0));
|
|
}
|
|
break;
|
|
case EW_ASSIGNVAR:
|
|
{
|
|
int newlen=GetIntFromParm(2);
|
|
int start=GetIntFromParm(3);
|
|
int l;
|
|
TCHAR *p=var0;
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
*p=0;
|
|
if (!parm2 || newlen)
|
|
{
|
|
l=mystrlen(buf0);
|
|
|
|
if (start<0) start=l+start;
|
|
if (start>=0)
|
|
{
|
|
if (start>l) start=l;
|
|
mystrcpy(p,buf0+start);
|
|
if (newlen)
|
|
{
|
|
if (newlen<0) newlen=mystrlen(p)+newlen;
|
|
if (newlen<0) newlen=0;
|
|
if (newlen < NSIS_MAX_STRLEN) p[newlen]=0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EW_STRCMP:
|
|
{
|
|
TCHAR *buf2=GetStringFromParm(0x20);
|
|
TCHAR *buf3=GetStringFromParm(0x31);
|
|
if (!parm4) {
|
|
// case insensitive
|
|
if (!lstrcmpi(buf2,buf3)) return parm2;
|
|
}
|
|
else {
|
|
// case sensitive
|
|
if (!lstrcmp(buf2,buf3)) return parm2;
|
|
}
|
|
}
|
|
return parm3;
|
|
#endif//NSIS_SUPPORT_STROPTS
|
|
#ifdef NSIS_SUPPORT_ENVIRONMENT
|
|
case EW_READENVSTR:
|
|
{
|
|
TCHAR *p=var0;
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
if (!ExpandEnvironmentStrings(buf0,p,NSIS_MAX_STRLEN)
|
|
|| (parm2 && !lstrcmp(buf0, p)))
|
|
{
|
|
exec_error++;
|
|
*p=0;
|
|
}
|
|
p[NSIS_MAX_STRLEN-1]=0;
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_ENVIRONMENT
|
|
#ifdef NSIS_SUPPORT_INTOPTS
|
|
case EW_INTCMP:
|
|
{
|
|
int v,v2;
|
|
v=GetIntFromParm(0);
|
|
v2=GetIntFromParm(1);
|
|
if (!parm5) {
|
|
// signed
|
|
if (v<v2) return parm3;
|
|
if (v>v2) return parm4;
|
|
}
|
|
else {
|
|
// unsigned
|
|
if ((unsigned int)v<(unsigned int)v2) return parm3;
|
|
if ((unsigned int)v>(unsigned int)v2) return parm4;
|
|
}
|
|
}
|
|
return parm2;
|
|
case EW_INTOP:
|
|
{
|
|
int v,v2;
|
|
TCHAR *p=var0;
|
|
v=GetIntFromParm(1);
|
|
v2=GetIntFromParm(2);
|
|
switch (parm3)
|
|
{
|
|
case 0: v+=v2; break;
|
|
case 1: v-=v2; break;
|
|
case 2: v*=v2; break;
|
|
case 3: if (v2) v/=v2; else { v=0; exec_error++; } break;
|
|
case 4: v|=v2; break;
|
|
case 5: v&=v2; break;
|
|
case 6: v^=v2; break;
|
|
case 7: v=!v; break;
|
|
case 8: v=v||v2; break;
|
|
case 9: v=v&&v2; break;
|
|
case 10: if (v2) v%=v2; else { v=0; exec_error++; } break;
|
|
case 11: v=v<<v2; break;
|
|
case 12: v=v>>v2; break;
|
|
}
|
|
myitoa(p,v);
|
|
}
|
|
break;
|
|
case EW_INTFMT: {
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
wsprintf(var0,
|
|
buf0,
|
|
GetIntFromParm(2));
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_INTOPTS
|
|
#ifdef NSIS_SUPPORT_STACK
|
|
case EW_PUSHPOP:
|
|
{
|
|
stack_t *s=g_st;
|
|
int cnt=parm2;
|
|
if (cnt) //Exch contributed by Fritz Elfert
|
|
{
|
|
while (cnt--&&s) s=s->next;
|
|
if (!s)
|
|
{
|
|
log_printf2(_T("Exch: stack < %d elements"),parm2);
|
|
my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21));
|
|
return EXEC_ERROR;
|
|
}
|
|
mystrcpy(buf0,s->text);
|
|
mystrcpy(s->text,g_st->text);
|
|
mystrcpy(g_st->text,buf0);
|
|
}
|
|
else if (parm1)
|
|
{
|
|
if (!s)
|
|
{
|
|
log_printf(_T("Pop: stack empty"));
|
|
exec_error++;
|
|
break;
|
|
}
|
|
mystrcpy(var0,s->text);
|
|
g_st=s->next;
|
|
GlobalFree((HGLOBAL)s);
|
|
}
|
|
else
|
|
{
|
|
s=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t));
|
|
GetNSISString(s->text,parm0);
|
|
s->next=g_st;
|
|
g_st=s;
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_STACK
|
|
#ifdef NSIS_SUPPORT_HWNDS
|
|
case EW_FINDWINDOW:
|
|
case EW_SENDMESSAGE:
|
|
{
|
|
int v;
|
|
int b3=GetIntFromParm(3);
|
|
int b4=GetIntFromParm(4);
|
|
if (parm5&1) b3=(int)GetStringFromParm(0x33);
|
|
if (parm5&2) b4=(int)GetStringFromParm(0x44);
|
|
|
|
if (which == EW_SENDMESSAGE)
|
|
{
|
|
HWND hwnd=(HWND)GetIntFromParm(1);
|
|
int msg=GetIntFromParm(2);
|
|
|
|
if (parm5>>2) exec_error += !SendMessageTimeout(hwnd,msg,b3,b4,SMTO_NORMAL,parm5>>2,(LPDWORD)&v);
|
|
// Jim Park: This sends script messages. Some messages require
|
|
// settings for Unicode. This means the user's script may need
|
|
// to change for Unicode NSIS.
|
|
else v=SendMessage(hwnd,msg,b3,b4);
|
|
}
|
|
else
|
|
{
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
TCHAR *buf1=GetStringFromParm(0x12);
|
|
v=(int)FindWindowEx((HWND)b3,(HWND)b4,buf0[0]?buf0:NULL,buf1[0]?buf1:NULL);
|
|
}
|
|
|
|
if (parm0>=0)
|
|
myitoa(var0,v);
|
|
}
|
|
break;
|
|
case EW_ISWINDOW:
|
|
if (IsWindow((HWND)GetIntFromParm(0))) return parm1;
|
|
return parm2;
|
|
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
case EW_GETDLGITEM:
|
|
myitoa(
|
|
var0,
|
|
(int)GetDlgItem(
|
|
(HWND)GetIntFromParm(1),
|
|
GetIntFromParm(2)
|
|
)
|
|
);
|
|
break;
|
|
case EW_SETCTLCOLORS:
|
|
{
|
|
ctlcolors *c = (ctlcolors *)(g_blocks[NB_CTLCOLORS].offset + parm1);
|
|
SetWindowLong((HWND) GetIntFromParm(0), GWL_USERDATA, (long) c);
|
|
}
|
|
break;
|
|
case EW_SETBRANDINGIMAGE:
|
|
{
|
|
RECT r;
|
|
HANDLE hImage;
|
|
HWND hwImage=GetDlgItem(g_hwnd, parm1);
|
|
GetClientRect(hwImage, &r);
|
|
hImage=LoadImage(
|
|
0,
|
|
GetStringFromParm(0x00),
|
|
IMAGE_BITMAP,
|
|
parm2*r.right,
|
|
parm2*r.bottom,
|
|
LR_LOADFROMFILE
|
|
);
|
|
hImage = (HANDLE)SendMessage(
|
|
hwImage,
|
|
STM_SETIMAGE,
|
|
IMAGE_BITMAP,
|
|
(LPARAM)hImage
|
|
);
|
|
// delete old image
|
|
if (hImage) DeleteObject(hImage);
|
|
}
|
|
break;
|
|
case EW_CREATEFONT:
|
|
{
|
|
static LOGFONT f;
|
|
f.lfHeight=-MulDiv(GetIntFromParm(2),GetDeviceCaps(GetDC(g_hwnd),LOGPIXELSY),72);
|
|
f.lfWeight=GetIntFromParm(3);
|
|
f.lfItalic=parm4&1;
|
|
f.lfUnderline=parm4&2;
|
|
f.lfStrikeOut=parm4&4;
|
|
f.lfCharSet=DEFAULT_CHARSET;
|
|
GetNSISString(f.lfFaceName,parm1);
|
|
myitoa(var0,(int)CreateFontIndirect(&f));
|
|
}
|
|
break;
|
|
case EW_SHOWWINDOW:
|
|
{
|
|
HWND hw=(HWND)GetIntFromParm(0);
|
|
int a=GetIntFromParm(1);
|
|
if (parm2) log_printf(_T("HideWindow"));
|
|
if (!parm3)
|
|
ShowWindow(hw,a);
|
|
else
|
|
EnableWindow(hw,a);
|
|
}
|
|
break;
|
|
#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
|
|
#endif//NSIS_SUPPORT_HWNDS
|
|
#ifdef NSIS_SUPPORT_SHELLEXECUTE
|
|
case EW_SHELLEXEC: // this uses improvements of Andras Varga
|
|
{
|
|
int x;
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
TCHAR *buf3=GetStringFromParm(0x31);
|
|
TCHAR *buf2=GetStringFromParm(0x22);
|
|
TCHAR *buf1=GetStringFromParm(0x15);
|
|
update_status_text_buf1(LANG_EXECSHELL);
|
|
x=(int)ShellExecute(g_hwnd,buf0[0]?buf0:NULL,buf3,buf2[0]?buf2:NULL,state_output_directory,parm3);
|
|
if (x < 33)
|
|
{
|
|
log_printf5(_T("ExecShell: warning: error (\"%s\": file:\"%s\" params:\"%s\")=%d"),buf0,buf3,buf2,x);
|
|
exec_error++;
|
|
}
|
|
else
|
|
{
|
|
log_printf4(_T("ExecShell: success (\"%s\": file:\"%s\" params:\"%s\")"),buf0,buf3,buf2);
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_SHELLEXECUTE
|
|
#ifdef NSIS_SUPPORT_EXECUTE
|
|
case EW_EXECUTE:
|
|
{
|
|
HANDLE hProc;
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
log_printf2(_T("Exec: command=\"%s\""),buf0);
|
|
update_status_text(LANG_EXECUTE,buf0);
|
|
|
|
hProc=myCreateProcess(buf0);
|
|
|
|
if (hProc)
|
|
{
|
|
log_printf2(_T("Exec: success (\"%s\")"),buf0);
|
|
if (parm2)
|
|
{
|
|
DWORD lExitCode;
|
|
while (WaitForSingleObject(hProc,100) == WAIT_TIMEOUT)
|
|
{
|
|
MessageLoop(WM_PAINT);
|
|
}
|
|
GetExitCodeProcess(hProc, &lExitCode);
|
|
|
|
if (parm1>=0) myitoa(var1,lExitCode);
|
|
else if (lExitCode) exec_error++;
|
|
}
|
|
CloseHandle( hProc );
|
|
}
|
|
else
|
|
{
|
|
exec_error++;
|
|
log_printf2(_T("Exec: failed createprocess (\"%s\")"),buf0);
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_EXECUTE
|
|
#ifdef NSIS_SUPPORT_GETFILETIME
|
|
case EW_GETFILETIME:
|
|
// this new implementation based on one by Dave Bau
|
|
// used FindFirstFile instead of GetFileTime to better handle files that are locked.
|
|
// also allows GetFileTime to be passed a wildcard.
|
|
{
|
|
WIN32_FIND_DATA *ffd;
|
|
TCHAR *highout=var0;
|
|
TCHAR *lowout=var1;
|
|
TCHAR *buf0=GetStringFromParm(0x02);
|
|
|
|
ffd=file_exists(buf0);
|
|
if (ffd)
|
|
{
|
|
myitoa(lowout,ffd->ftLastWriteTime.dwLowDateTime);
|
|
myitoa(highout,ffd->ftLastWriteTime.dwHighDateTime);
|
|
}
|
|
else
|
|
{
|
|
*lowout=*highout=0;
|
|
exec_error++;
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_GETFILETIME
|
|
#ifdef NSIS_SUPPORT_GETDLLVERSION
|
|
case EW_GETDLLVERSION:
|
|
{
|
|
TCHAR *highout=var0;
|
|
TCHAR *lowout=var1;
|
|
DWORD s1;
|
|
VS_FIXEDFILEINFO *pvsf1;
|
|
DWORD d;
|
|
TCHAR *buf1=GetStringFromParm(-0x12);
|
|
s1=GetFileVersionInfoSize(buf1,&d);
|
|
*lowout=*highout=0;
|
|
exec_error++;
|
|
if (s1)
|
|
{
|
|
void *b1;
|
|
b1=GlobalAlloc(GPTR,s1);
|
|
if (b1)
|
|
{
|
|
UINT uLen;
|
|
if (GetFileVersionInfo(buf1,0,s1,b1) && VerQueryValue(b1,_T("\\"),(void*)&pvsf1,&uLen))
|
|
{
|
|
myitoa(highout,pvsf1->dwFileVersionMS);
|
|
myitoa(lowout,pvsf1->dwFileVersionLS);
|
|
|
|
exec_error--;
|
|
}
|
|
GlobalFree(b1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_GETDLLVERSION
|
|
#ifdef NSIS_SUPPORT_ACTIVEXREG
|
|
case EW_REGISTERDLL:
|
|
{
|
|
exec_error++;
|
|
if (SUCCEEDED(g_hres))
|
|
{
|
|
HANDLE h=NULL;
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
|
|
if (parm4)
|
|
h=GetModuleHandle(buf1);
|
|
if (!h)
|
|
h=LoadLibraryEx(buf1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
if (h)
|
|
{
|
|
FARPROC funke = GetProcAddress(h,buf0);
|
|
if (funke)
|
|
{
|
|
exec_error--;
|
|
if (parm2)
|
|
{
|
|
update_status_text_buf1(parm2);
|
|
if (funke()) exec_error++;
|
|
}
|
|
else
|
|
{
|
|
void (*func)(HWND,int,TCHAR*,void*,void*);
|
|
func=(void*)funke;
|
|
func(
|
|
g_hwnd,
|
|
NSIS_MAX_STRLEN,
|
|
(TCHAR*)g_usrvars,
|
|
#ifdef NSIS_SUPPORT_STACK
|
|
(void*)&g_st,
|
|
#else
|
|
NULL,
|
|
#endif//NSIS_SUPPORT_STACK
|
|
&plugin_extra_parameters
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
update_status_text(LANG_CANNOTFINDSYMBOL,buf0);
|
|
log_printf3(_T("Error registering DLL: %s not found in %s"),buf0,buf1);
|
|
}
|
|
if (!parm3 && Plugins_CanUnload(h)) FreeLibrary(h);
|
|
}
|
|
else
|
|
{
|
|
update_status_text_buf1(LANG_COULDNOTLOAD);
|
|
log_printf2(_T("Error registering DLL: Could not load %s"),buf1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
update_status_text_buf1(LANG_NOOLE);
|
|
log_printf(_T("Error registering DLL: Could not initialize OLE"));
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
#ifdef NSIS_SUPPORT_CREATESHORTCUT
|
|
case EW_CREATESHORTCUT:
|
|
{
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
TCHAR *buf2=GetStringFromParm(-0x21);
|
|
TCHAR *buf0=GetStringFromParm(0x02);
|
|
TCHAR *buf3=GetStringFromParm(-0x33);
|
|
TCHAR *buf4=GetStringFromParm(0x45);
|
|
|
|
HRESULT hres;
|
|
IShellLink* psl;
|
|
|
|
if (!validpathspec(buf2))
|
|
GetStringFromParm(0x21);
|
|
|
|
log_printf8(_T("CreateShortCut: out: \"%s\", in: \"%s %s\", icon: %s,%d, sw=%d, hk=%d"),
|
|
buf1,buf2,buf0,buf3,parm4&0xff,(parm4&0xff00)>>8,parm4>>16);
|
|
|
|
hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IShellLink, (void **) &psl);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
IPersistFile* ppf;
|
|
|
|
hres = psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile, (void **) &ppf);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = psl->lpVtbl->SetPath(psl,buf2);
|
|
psl->lpVtbl->SetWorkingDirectory(psl,state_output_directory);
|
|
if ((parm4&0xff00)>>8) psl->lpVtbl->SetShowCmd(psl,(parm4&0xff00)>>8);
|
|
psl->lpVtbl->SetHotkey(psl,(unsigned short)(parm4>>16));
|
|
if (buf3[0]) psl->lpVtbl->SetIconLocation(psl,buf3,parm4&0xff);
|
|
psl->lpVtbl->SetArguments(psl,buf0);
|
|
psl->lpVtbl->SetDescription(psl,buf4);
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
#ifdef _UNICODE
|
|
hres=ppf->lpVtbl->Save(ppf,(const WCHAR*)buf1,TRUE);
|
|
#else
|
|
static WCHAR wsz[1024];
|
|
hres=E_FAIL;
|
|
if (MultiByteToWideChar(CP_ACP, 0, buf1, -1, wsz, 1024))
|
|
hres=ppf->lpVtbl->Save(ppf,(const WCHAR*)wsz,TRUE);
|
|
#endif
|
|
}
|
|
ppf->lpVtbl->Release(ppf);
|
|
}
|
|
psl->lpVtbl->Release(psl);
|
|
}
|
|
|
|
if (FAILED(hres))
|
|
{
|
|
exec_error++;
|
|
update_status_text_buf1(LANG_ERRORCREATINGSHORTCUT);
|
|
}
|
|
else
|
|
{
|
|
update_status_text_buf1(LANG_CREATESHORTCUT);
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_CREATESHORTCUT
|
|
#ifdef NSIS_SUPPORT_COPYFILES
|
|
case EW_COPYFILES: // CopyFile (added by NOP)
|
|
{
|
|
int res;
|
|
SHFILEOPSTRUCT op;
|
|
TCHAR *buf0=GetStringFromParm(0x00);
|
|
TCHAR *buf1=GetStringFromParm(0x11);
|
|
TCHAR *buf2=GetStringFromParm(0x23); // LANG_COPYTO + buf1
|
|
log_printf3(_T("CopyFiles \"%s\"->\"%s\""),buf0,buf1);
|
|
|
|
if (!file_exists(buf0))
|
|
{
|
|
// workaround for bug #774966
|
|
//
|
|
// on nt4, SHFileOperation silently fails if the source
|
|
// file doesn't exist. do a manual check instead.
|
|
|
|
update_status_text(LANG_COPYFAILED,0);
|
|
exec_error++;
|
|
break;
|
|
}
|
|
|
|
op.hwnd=g_hwnd;
|
|
op.wFunc=FO_COPY;
|
|
buf0[mystrlen(buf0)+1]=0;
|
|
buf1[mystrlen(buf1)+1]=0;
|
|
|
|
op.pFrom=buf0;
|
|
op.pTo=buf1;
|
|
op.lpszProgressTitle=buf2;
|
|
op.fFlags=parm2;
|
|
update_status_text(0,buf2);
|
|
res=SHFileOperation(&op);
|
|
if (res)
|
|
{ // some of these changes were from Edgewise (wiked_edge@yahoo.com)
|
|
update_status_text(LANG_COPYFAILED,0);
|
|
exec_error++;
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_COPYFILES
|
|
#ifdef NSIS_SUPPORT_REBOOT
|
|
case EW_REBOOT:
|
|
if (parm0!=0xbadf00d)
|
|
{
|
|
my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21));
|
|
return EXEC_ERROR;
|
|
}
|
|
|
|
g_exec_flags.reboot_called++;
|
|
// a following EW_QUIT will make sure the installer quits right away
|
|
|
|
break;
|
|
#endif//NSIS_SUPPORT_REBOOT
|
|
#ifdef NSIS_SUPPORT_INIFILES
|
|
case EW_WRITEINI:
|
|
{
|
|
TCHAR *sec=0, *key=0, *str=0;
|
|
#ifdef NSIS_CONFIG_LOG
|
|
mystrcpy(buf1,_T("<RM>"));
|
|
mystrcpy(buf2,buf1);
|
|
#endif
|
|
if (parm0)
|
|
{
|
|
sec=GetStringFromParm(0x00);
|
|
}
|
|
if (parm1)
|
|
{
|
|
key=GetStringFromParm(0x11);
|
|
}
|
|
if (parm4)
|
|
{
|
|
str=GetStringFromParm(0x22);
|
|
}
|
|
buf3=GetStringFromParm(-0x33);
|
|
log_printf5(_T("WriteINIStr: wrote [%s] %s=%s in %s"),buf0,buf1,buf2,buf3);
|
|
if (!WritePrivateProfileString(sec,key,str,buf3)) exec_error++;
|
|
}
|
|
break;
|
|
case EW_READINISTR:
|
|
{
|
|
TCHAR errstr[] = _T("!N~");
|
|
TCHAR *p=var0;
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
TCHAR *buf1=GetStringFromParm(0x12);
|
|
TCHAR *buf2=GetStringFromParm(-0x23);
|
|
GetPrivateProfileString(buf0,buf1,errstr,p,NSIS_MAX_STRLEN-1,buf2);
|
|
if (lstrcmp(p, errstr) == 0)
|
|
{
|
|
exec_error++;
|
|
p[0]=0;
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_INIFILES
|
|
#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
case EW_DELREG:
|
|
{
|
|
long res=!ERROR_SUCCESS;
|
|
const TCHAR *rkn UNUSED=RegKeyHandleToName((HKEY)parm1);
|
|
if (!parm4)
|
|
{
|
|
HKEY hKey=myRegOpenKey(KEY_SET_VALUE);
|
|
if (hKey)
|
|
{
|
|
TCHAR *buf3=GetStringFromParm(0x33);
|
|
res = RegDeleteValue(hKey,buf3);
|
|
log_printf4(_T("DeleteRegValue: \"%s\\%s\" \"%s\""),rkn,buf2,buf3);
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCHAR *buf2=GetStringFromParm(0x22);
|
|
log_printf3(_T("DeleteRegKey: \"%s\\%s\""),rkn,buf2);
|
|
res = myRegDeleteKeyEx(GetRegRootKey(parm1),buf2,parm4&2);
|
|
}
|
|
if (res != ERROR_SUCCESS)
|
|
exec_error++;
|
|
}
|
|
break;
|
|
case EW_WRITEREG: // write registry value
|
|
{
|
|
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)
|
|
{
|
|
LPBYTE data = (LPBYTE) buf2;
|
|
DWORD size = 0;
|
|
if (type == REG_SZ)
|
|
{
|
|
GetStringFromParm(0x23);
|
|
size = (mystrlen((TCHAR *) data) + 1)*sizeof(TCHAR);
|
|
if (rtype == REG_SZ)
|
|
{
|
|
log_printf5(_T("WriteRegStr: \"%s\\%s\" \"%s\"=\"%s\""),rkn,buf1,buf0,data);
|
|
}
|
|
else
|
|
{
|
|
log_printf5(_T("WriteRegExpandStr: \"%s\\%s\" \"%s\"=\"%s\""),rkn,buf1,buf0,data);
|
|
}
|
|
}
|
|
if (type == REG_DWORD)
|
|
{
|
|
*(LPDWORD) data = GetIntFromParm(3);
|
|
size = sizeof(DWORD);
|
|
log_printf5(_T("WriteRegDWORD: \"%s\\%s\" \"%s\"=\"0x%08x\""),rkn,buf1,buf0,*(LPDWORD) data);
|
|
}
|
|
if (type == REG_BINARY)
|
|
{
|
|
#ifdef NSIS_CONFIG_LOG
|
|
TCHAR binbuf[128];
|
|
#endif
|
|
// use buf2, buf3 and buf4
|
|
size = GetCompressedDataFromDataBlockToMemory(parm3, data, (3 * NSIS_MAX_STRLEN)*sizeof(TCHAR));
|
|
LogData2Hex(binbuf, sizeof(binbuf), data, size);
|
|
log_printf5(_T("WriteRegBin: \"%s\\%s\" \"%s\"=\"%s\""),rkn,buf1,buf0,binbuf);
|
|
}
|
|
|
|
if (size >= 0 && RegSetValueEx(hKey,buf0,0,rtype,data,size) == ERROR_SUCCESS)
|
|
{
|
|
exec_error--;
|
|
}
|
|
else
|
|
{
|
|
log_printf4(_T("WriteReg: error writing into \"%s\\%s\" \"%s\""),rkn,buf1,buf0);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else { log_printf3(_T("WriteReg: error creating key \"%s\\%s\""),rkn,buf1); }
|
|
}
|
|
break;
|
|
case EW_READREGSTR: // read registry string
|
|
{
|
|
HKEY hKey=myRegOpenKey(KEY_READ);
|
|
TCHAR *p=var0;
|
|
TCHAR *buf3=GetStringFromParm(0x33); // buf3 == key name
|
|
p[0]=0;
|
|
if (hKey)
|
|
{
|
|
DWORD l = NSIS_MAX_STRLEN - 1;
|
|
DWORD t;
|
|
|
|
if (RegQueryValueEx(hKey,buf3,NULL,&t,p,&l) != ERROR_SUCCESS ||
|
|
(t != REG_DWORD && t != REG_SZ && t != REG_EXPAND_SZ))
|
|
{
|
|
p[0]=0;
|
|
exec_error++;
|
|
}
|
|
else
|
|
{
|
|
if (t==REG_DWORD)
|
|
{
|
|
exec_error += !parm4;
|
|
myitoa(p,*((DWORD*)p));
|
|
}
|
|
else
|
|
{
|
|
exec_error += parm4;
|
|
p[l]=0;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
else exec_error++;
|
|
}
|
|
break;
|
|
case EW_REGENUM:
|
|
{
|
|
HKEY key=myRegOpenKey(KEY_READ);
|
|
TCHAR *p=var0;
|
|
int b=GetIntFromParm(3);
|
|
p[0]=0;
|
|
if (key)
|
|
{
|
|
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)
|
|
{
|
|
exec_error++;
|
|
break;
|
|
}
|
|
p[NSIS_MAX_STRLEN-1]=0;
|
|
RegCloseKey(key);
|
|
}
|
|
else exec_error++;
|
|
}
|
|
|
|
break;
|
|
#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS
|
|
#ifdef NSIS_SUPPORT_FILEFUNCTIONS
|
|
case EW_FCLOSE:
|
|
{
|
|
TCHAR *t=var0;
|
|
if (*t) CloseHandle((HANDLE)myatoi(t));
|
|
}
|
|
break;
|
|
case EW_FOPEN:
|
|
{
|
|
HANDLE h;
|
|
TCHAR *handleout=var0;
|
|
TCHAR *buf1=GetStringFromParm(-0x13);
|
|
h=myOpenFile(buf1,parm1,parm2);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
{
|
|
*handleout=0;
|
|
exec_error++;
|
|
}
|
|
else
|
|
{
|
|
myitoa(handleout,(int)h);
|
|
}
|
|
}
|
|
break;
|
|
case EW_FPUTS:
|
|
{
|
|
DWORD dw;
|
|
int l;
|
|
TCHAR *t=var0;
|
|
if (parm2) // WriteByte
|
|
{
|
|
((unsigned char *)buf1)[0]=GetIntFromParm(1)&0xff;
|
|
l=1;
|
|
}
|
|
else
|
|
{
|
|
l=mystrlen(GetStringFromParm(0x11));
|
|
}
|
|
if (!*t || !WriteFile((HANDLE)myatoi(t),buf1,l,&dw,NULL))
|
|
{
|
|
exec_error++;
|
|
}
|
|
}
|
|
break;
|
|
case EW_FGETS:
|
|
{
|
|
char *textout=var1;
|
|
DWORD dw;
|
|
int rpos=0;
|
|
char *hptr=var0;
|
|
int maxlen=GetIntFromParm(2);
|
|
if (maxlen<1) break;
|
|
if (maxlen > NSIS_MAX_STRLEN-1) maxlen=NSIS_MAX_STRLEN-1;
|
|
if (*hptr)
|
|
{
|
|
char lc=0;
|
|
HANDLE h=(HANDLE)myatoi(hptr);
|
|
while (rpos<maxlen)
|
|
{
|
|
char c;
|
|
if (!ReadFile(h,&c,sizeof(c),&dw,NULL) || dw != sizeof(c)) break;
|
|
if (parm3)
|
|
{
|
|
myitoa(textout,(unsigned int)(unsigned char)c);
|
|
return 0;
|
|
}
|
|
if (lc == '\r' || lc == '\n')
|
|
{
|
|
if (lc == c || (c != '\r' && c != '\n')) SetFilePointer(h,-((int)(sizeof(c))),NULL,FILE_CURRENT);
|
|
else textout[rpos++]=c;
|
|
break;
|
|
}
|
|
textout[rpos++]=c;
|
|
lc=c;
|
|
if (!c) break;
|
|
}
|
|
}
|
|
textout[rpos]=0;
|
|
if (!rpos) exec_error++;
|
|
}
|
|
break;
|
|
case EW_FSEEK:
|
|
{
|
|
TCHAR *t=var0;
|
|
if (*t)
|
|
{
|
|
DWORD v=SetFilePointer((HANDLE)myatoi(t),GetIntFromParm(2),NULL,parm3);
|
|
|
|
if (parm1>=0)
|
|
{
|
|
myitoa(var1,v);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_FILEFUNCTIONS
|
|
#ifdef NSIS_SUPPORT_FINDFIRST
|
|
case EW_FINDCLOSE:
|
|
{
|
|
TCHAR *t=var0;
|
|
if (*t) FindClose((HANDLE)myatoi(t));
|
|
}
|
|
break;
|
|
case EW_FINDNEXT:
|
|
{
|
|
TCHAR *textout=var0;
|
|
TCHAR *t=var1;
|
|
WIN32_FIND_DATA fd;
|
|
if (*t && FindNextFile((HANDLE)myatoi(t),&fd))
|
|
{
|
|
mystrcpy(textout,fd.cFileName);
|
|
}
|
|
else
|
|
{
|
|
exec_error++;
|
|
*textout=0;
|
|
}
|
|
|
|
}
|
|
break;
|
|
case EW_FINDFIRST:
|
|
{
|
|
TCHAR *textout=var0;
|
|
TCHAR *handleout=var1;
|
|
HANDLE h;
|
|
WIN32_FIND_DATA fd;
|
|
TCHAR *buf0=GetStringFromParm(0x02);
|
|
h=FindFirstFile(buf0,&fd);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
{
|
|
*handleout=0;
|
|
*textout=0;
|
|
exec_error++;
|
|
}
|
|
else
|
|
{
|
|
myitoa(handleout,(int)h);
|
|
mystrcpy(textout,fd.cFileName);
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_SUPPORT_FINDFIRST
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
case EW_WRITEUNINSTALLER:
|
|
{
|
|
int ret=-666;
|
|
HANDLE hFile;
|
|
TCHAR *buf1=GetStringFromParm(-0x10);
|
|
|
|
if (!validpathspec(buf1))
|
|
GetStringFromParm(-0x13);
|
|
|
|
remove_ro_attr(buf1);
|
|
hFile=myOpenFile(buf1,GENERIC_WRITE,CREATE_ALWAYS);
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
unsigned char *filebuf;
|
|
int filehdrsize = g_filehdrsize;
|
|
filebuf=(unsigned char *)GlobalAlloc(GPTR,filehdrsize);
|
|
if (filebuf)
|
|
{
|
|
DWORD lout;
|
|
SetSelfFilePointer(0);
|
|
ReadSelfFile((char*)filebuf,filehdrsize);
|
|
{
|
|
// parm1 = uninstdata_offset
|
|
// parm2 = m_unicon_size
|
|
unsigned char* seeker;
|
|
unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2);
|
|
if (unicon_data) {
|
|
GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2);
|
|
while (*seeker) {
|
|
struct icondata {
|
|
DWORD dwSize;
|
|
DWORD dwOffset;
|
|
} id = *(struct icondata *) seeker;
|
|
seeker += sizeof(struct icondata);
|
|
mini_memcpy(filebuf+id.dwOffset, seeker, id.dwSize);
|
|
seeker += id.dwSize;
|
|
}
|
|
GlobalFree(unicon_data);
|
|
}
|
|
}
|
|
WriteFile(hFile,(char*)filebuf,filehdrsize,&lout,NULL);
|
|
GlobalFree(filebuf);
|
|
ret=GetCompressedDataFromDataBlock(-1,hFile);
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
log_printf3(_T("created uninstaller: %d, \"%s\""),ret,buf1);
|
|
{
|
|
int str = LANG_CREATEDUNINST;
|
|
if (ret < 0)
|
|
{
|
|
str = LANG_ERRORCREATING;
|
|
DeleteFile(buf1);
|
|
exec_error++;
|
|
}
|
|
update_status_text_buf1(str);
|
|
}
|
|
}
|
|
break;
|
|
#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
#ifdef NSIS_CONFIG_LOG
|
|
case EW_LOG:
|
|
if (parm0)
|
|
{
|
|
log_printf2(_T("settings logging to %d"),parm1);
|
|
log_dolog=parm1;
|
|
log_printf2(_T("logging set to %d"),parm1);
|
|
#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
|
|
if (parm1)
|
|
build_g_logfile();
|
|
else
|
|
log_write(1);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
TCHAR *buf0=GetStringFromParm(0x01);
|
|
log_printf2(_T("%s"),buf0);
|
|
}
|
|
break;
|
|
#endif//NSIS_CONFIG_LOG
|
|
#ifdef NSIS_CONFIG_COMPONENTPAGE
|
|
case EW_SECTIONSET:
|
|
{
|
|
int x=GetIntFromParm(0);
|
|
if ((unsigned int)x < (unsigned int)num_sections)
|
|
{
|
|
section *sec=g_sections+x;
|
|
if (parm2>=0) // get something
|
|
{
|
|
int res=((int*)sec)[parm2];
|
|
if (!parm2)
|
|
{
|
|
// getting text
|
|
mystrcpy(var1,sec->name);
|
|
}
|
|
else
|
|
{
|
|
// getting number
|
|
myitoa(var1,res);
|
|
}
|
|
}
|
|
else // set something
|
|
{
|
|
parm2=-parm2-1;
|
|
if (parm2)
|
|
{
|
|
// not setting text, get int
|
|
parm1=GetIntFromParm(1);
|
|
}
|
|
else
|
|
{
|
|
// setting text
|
|
GetNSISString(sec->name,parm4);
|
|
sec->flags|=SF_NAMECHG;
|
|
// parm1 is zero so name_ptr will be set to zero
|
|
// if name_ptr is zero, it won't be used after .onInit
|
|
}
|
|
|
|
((int*)sec)[parm2]=parm1;
|
|
|
|
if (parm3) // update flags
|
|
{
|
|
SectionFlagsChanged(x);
|
|
}
|
|
}
|
|
}
|
|
else exec_error++;
|
|
}
|
|
break;
|
|
case EW_INSTTYPESET:
|
|
{
|
|
int x = GetIntFromParm(0);
|
|
|
|
if ((unsigned int)x < (unsigned int)NSIS_MAX_INST_TYPES)
|
|
{
|
|
if (parm3) // current install type
|
|
{
|
|
if (parm2) // set install type
|
|
{
|
|
SetInstType(x);
|
|
RefreshSectionGroups();
|
|
}
|
|
else // get install type
|
|
{
|
|
myitoa(var1, GetInstType(0));
|
|
}
|
|
}
|
|
else // install type text
|
|
{
|
|
if (parm2) // set text
|
|
{
|
|
g_header->install_types[x] = parm1;
|
|
}
|
|
else // get text
|
|
{
|
|
GetNSISString(var1,g_header->install_types[x]);
|
|
}
|
|
}
|
|
}
|
|
else exec_error++;
|
|
}
|
|
break;
|
|
#endif//NSIS_CONFIG_COMPONENTPAGE
|
|
|
|
#ifdef NSIS_LOCKWINDOW_SUPPORT
|
|
case EW_LOCKWINDOW:
|
|
{
|
|
// ui_dlg_visible is 1 or 0, so is parm0
|
|
SendMessage(g_hwnd, WM_SETREDRAW, parm0 & ui_dlg_visible, 0);
|
|
if ( parm0 )
|
|
InvalidateRect(g_hwnd, NULL, FALSE);
|
|
break;
|
|
}
|
|
#endif //NSIS_LOCKWINDOW_SUPPORT
|
|
}
|
|
|
|
g_exec_flags.exec_error += exec_error;
|
|
|
|
return 0;
|
|
}
|