2004-02-23 18:39:50 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
Nullsoft Scriptable Install System (NSIS)
|
|
|
|
main.c - executable header main code
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2005-01-04 14:54:48 +00:00
|
|
|
Copyright (C) 1999-2005 Nullsoft, Inc.
|
2004-02-23 18:39:50 +00:00
|
|
|
|
|
|
|
This license applies to everything in the NSIS package, except where otherwise noted.
|
2002-08-19 21:24:44 +00:00
|
|
|
|
2002-08-02 10:01:35 +00:00
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
2004-02-23 18:39:50 +00:00
|
|
|
This is the zlib/libpng license, which is approved by opensource.org.
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2004-02-23 18:39:50 +00:00
|
|
|
Portions Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler (zlib).
|
|
|
|
Portions Copyright (C) 1996-2002 Julian R Seward (bzip2).
|
|
|
|
Portions Copyright (C) 1999-2003 Igor Pavlov (lzma).
|
|
|
|
|
|
|
|
*/
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2004-01-30 22:04:10 +00:00
|
|
|
#include "../Platform.h"
|
2003-09-04 18:25:57 +00:00
|
|
|
#include <shlobj.h>
|
2002-08-02 10:01:35 +00:00
|
|
|
#include "resource.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "fileform.h"
|
|
|
|
#include "state.h"
|
|
|
|
#include "ui.h"
|
|
|
|
#include "lang.h"
|
2003-03-18 20:36:52 +00:00
|
|
|
#include "state.h"
|
2004-08-20 14:14:51 +00:00
|
|
|
#include "exec.h"
|
2002-08-02 10:01:35 +00:00
|
|
|
|
|
|
|
#if !defined(NSIS_CONFIG_VISIBLE_SUPPORT) && !defined(NSIS_CONFIG_SILENT_SUPPORT)
|
|
|
|
#error One of NSIS_CONFIG_SILENT_SUPPORT or NSIS_CONFIG_VISIBLE_SUPPORT must be defined.
|
|
|
|
#endif
|
|
|
|
#ifdef NSIS_COMPRESS_WHOLE
|
|
|
|
extern HANDLE dbd_hFile;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
char g_caption[NSIS_MAX_STRLEN*2];
|
2003-09-10 16:39:06 +00:00
|
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
2002-08-02 10:01:35 +00:00
|
|
|
HWND g_hwnd;
|
2003-09-10 16:39:06 +00:00
|
|
|
HANDLE g_hInstance;
|
|
|
|
#endif
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2004-01-29 23:18:32 +00:00
|
|
|
void NSISCALL CleanUp();
|
|
|
|
|
2003-11-14 21:08:51 +00:00
|
|
|
char *ValidateTempDir()
|
|
|
|
{
|
|
|
|
validate_filename(state_temp_dir);
|
2003-11-28 18:52:19 +00:00
|
|
|
if (!validpathspec(state_temp_dir))
|
|
|
|
return NULL;
|
2003-11-28 18:59:51 +00:00
|
|
|
addtrailingslash(state_temp_dir);
|
2003-11-14 21:08:51 +00:00
|
|
|
CreateDirectory(state_temp_dir, NULL);
|
2004-08-20 14:14:51 +00:00
|
|
|
// state_command_line is used as a temp var here
|
|
|
|
return my_GetTempFileName(state_command_line, state_temp_dir);
|
2003-11-14 21:08:51 +00:00
|
|
|
}
|
|
|
|
|
2002-08-02 10:01:35 +00:00
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow)
|
|
|
|
{
|
2004-09-25 14:56:16 +00:00
|
|
|
int ret = 0;
|
2003-11-14 21:08:51 +00:00
|
|
|
const char *m_Err = _LANG_ERRORWRITINGTEMP;
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2003-07-18 14:22:17 +00:00
|
|
|
int cl_flags = 0;
|
|
|
|
|
2002-08-02 10:01:35 +00:00
|
|
|
char *realcmds;
|
|
|
|
char seekchar=' ';
|
2003-06-17 23:59:13 +00:00
|
|
|
char *cmdline;
|
2002-08-02 10:01:35 +00:00
|
|
|
|
|
|
|
InitCommonControls();
|
2002-11-30 13:15:49 +00:00
|
|
|
|
2003-09-04 18:25:57 +00:00
|
|
|
#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
|
|
|
|
{
|
|
|
|
extern HRESULT g_hres;
|
|
|
|
g_hres=OleInitialize(NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-08-20 14:14:51 +00:00
|
|
|
mystrcpy(g_caption,_LANG_GENERIC_ERROR);
|
|
|
|
|
2003-11-14 21:08:51 +00:00
|
|
|
GetTempPath(NSIS_MAX_STRLEN, state_temp_dir);
|
|
|
|
if (!ValidateTempDir())
|
2003-07-08 23:18:47 +00:00
|
|
|
{
|
2003-11-14 21:08:51 +00:00
|
|
|
GetWindowsDirectory(state_temp_dir, NSIS_MAX_STRLEN - 5); // leave space for \Temp
|
2003-09-05 10:40:31 +00:00
|
|
|
lstrcat(state_temp_dir, "\\Temp");
|
2003-11-14 21:08:51 +00:00
|
|
|
if (!ValidateTempDir())
|
2003-07-08 23:18:47 +00:00
|
|
|
{
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
2004-08-20 14:14:51 +00:00
|
|
|
DeleteFile(state_command_line);
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2003-07-18 14:22:17 +00:00
|
|
|
lstrcpyn(state_command_line, GetCommandLine(), NSIS_MAX_STRLEN);
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2003-09-10 16:39:06 +00:00
|
|
|
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
|
2003-07-18 14:22:17 +00:00
|
|
|
g_hInstance = GetModuleHandle(NULL);
|
2003-09-10 16:39:06 +00:00
|
|
|
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
|
2002-08-02 10:01:35 +00:00
|
|
|
|
2003-06-17 23:59:13 +00:00
|
|
|
cmdline = state_command_line;
|
|
|
|
if (*cmdline == '\"') seekchar = *cmdline++;
|
|
|
|
|
2004-02-04 20:03:30 +00:00
|
|
|
cmdline=findchar(cmdline, seekchar);
|
2003-06-17 23:59:13 +00:00
|
|
|
cmdline=CharNext(cmdline);
|
|
|
|
realcmds=cmdline;
|
|
|
|
|
2004-02-04 20:03:30 +00:00
|
|
|
while (*cmdline)
|
2003-06-17 23:59:13 +00:00
|
|
|
{
|
|
|
|
// skip over any spaces
|
2004-02-04 22:40:36 +00:00
|
|
|
while (*cmdline == ' ') cmdline++;
|
2004-02-06 16:31:32 +00:00
|
|
|
|
|
|
|
// get char we should look for to get the next parm
|
|
|
|
seekchar = ' ';
|
2004-02-04 22:40:36 +00:00
|
|
|
if (cmdline[0] == '\"')
|
2004-02-04 20:03:30 +00:00
|
|
|
{
|
|
|
|
cmdline++;
|
|
|
|
seekchar = '\"';
|
|
|
|
}
|
2004-02-06 16:31:32 +00:00
|
|
|
|
|
|
|
// is it a switch?
|
2004-02-04 20:03:30 +00:00
|
|
|
if (cmdline[0] == '/')
|
|
|
|
{
|
|
|
|
cmdline++;
|
2003-06-17 23:59:13 +00:00
|
|
|
|
2003-09-23 19:01:19 +00:00
|
|
|
// this only works with spaces because they have just one bit on
|
2003-06-17 23:59:13 +00:00
|
|
|
#define END_OF_ARG(c) (((c)|' ')==' ')
|
|
|
|
|
|
|
|
#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT)
|
2004-02-04 20:03:30 +00:00
|
|
|
if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1]))
|
|
|
|
cl_flags |= FH_FLAGS_SILENT;
|
2003-06-17 23:59:13 +00:00
|
|
|
#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT
|
|
|
|
#ifdef NSIS_CONFIG_CRC_SUPPORT
|
2004-10-01 21:15:24 +00:00
|
|
|
if (*(LPDWORD)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4]))
|
2004-02-04 20:03:30 +00:00
|
|
|
cl_flags |= FH_FLAGS_NO_CRC;
|
2003-06-17 23:59:13 +00:00
|
|
|
#endif//NSIS_CONFIG_CRC_SUPPORT
|
|
|
|
|
2004-10-01 21:15:24 +00:00
|
|
|
if (*(LPDWORD)(cmdline-2) == CHAR4_TO_DWORD(' ', '/', 'D','='))
|
2004-02-04 20:03:30 +00:00
|
|
|
{
|
2004-10-01 21:15:24 +00:00
|
|
|
cmdline[-2]=0; // keep this from being passed to uninstaller if necessary
|
2004-02-04 20:03:30 +00:00
|
|
|
mystrcpy(state_install_directory,cmdline+2);
|
2004-02-06 16:31:32 +00:00
|
|
|
break; // /D= must always be last
|
2004-02-04 20:03:30 +00:00
|
|
|
}
|
2003-06-17 23:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// skip over our parm
|
2004-02-04 20:03:30 +00:00
|
|
|
cmdline = findchar(cmdline, seekchar);
|
|
|
|
// skip the quote
|
2004-02-04 22:40:36 +00:00
|
|
|
if (*cmdline == '\"')
|
2004-02-04 20:03:30 +00:00
|
|
|
cmdline++;
|
2003-06-17 23:59:13 +00:00
|
|
|
}
|
|
|
|
|
2003-07-18 14:22:17 +00:00
|
|
|
m_Err = loadHeaders(cl_flags);
|
|
|
|
if (m_Err) goto end;
|
|
|
|
|
2002-08-02 10:01:35 +00:00
|
|
|
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
|
|
if (g_is_uninstaller)
|
|
|
|
{
|
2004-02-06 16:31:32 +00:00
|
|
|
char *p = findchar(realcmds, 0);
|
2002-09-13 18:00:11 +00:00
|
|
|
|
2004-10-01 21:15:24 +00:00
|
|
|
// state_command_line has state_install_directory right after it in memory, so reading
|
|
|
|
// a bit over state_command_line won't do any harm
|
|
|
|
while (p >= realcmds && *(LPDWORD)p != CHAR4_TO_DWORD(' ', '_', '?', '=')) p--;
|
2003-09-04 18:25:57 +00:00
|
|
|
|
2003-09-10 16:39:06 +00:00
|
|
|
m_Err = _LANG_UNINSTINITERROR;
|
|
|
|
|
2004-02-04 23:12:54 +00:00
|
|
|
if (p >= realcmds)
|
2002-08-02 10:01:35 +00:00
|
|
|
{
|
2004-10-01 21:15:24 +00:00
|
|
|
*p=0; // terminate before "_?="
|
|
|
|
p+=4; // skip over " _?="
|
2002-09-13 18:00:11 +00:00
|
|
|
if (is_valid_instpath(p))
|
2002-08-02 10:01:35 +00:00
|
|
|
{
|
2003-07-18 14:22:17 +00:00
|
|
|
mystrcpy(state_install_directory, p);
|
|
|
|
mystrcpy(state_output_directory, p);
|
2003-09-10 16:39:06 +00:00
|
|
|
m_Err = 0;
|
2002-08-02 10:01:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-09-10 16:39:06 +00:00
|
|
|
int x;
|
2002-08-02 10:01:35 +00:00
|
|
|
|
|
|
|
for (x = 0; x < 26; x ++)
|
|
|
|
{
|
2003-11-28 19:04:06 +00:00
|
|
|
static char s[]="A~NSISu_.exe";
|
2003-07-19 12:29:36 +00:00
|
|
|
static char buf2[NSIS_MAX_STRLEN*2];
|
2002-08-02 10:01:35 +00:00
|
|
|
static char ibuf[NSIS_MAX_STRLEN];
|
2002-08-19 21:24:44 +00:00
|
|
|
|
2003-07-19 12:29:36 +00:00
|
|
|
buf2[0]='\"';
|
2003-06-23 22:40:11 +00:00
|
|
|
mystrcpy(buf2+1,state_temp_dir);
|
2002-08-02 10:01:35 +00:00
|
|
|
lstrcat(buf2,s);
|
|
|
|
|
|
|
|
DeleteFile(buf2+1); // clean up after all the other ones if they are there
|
2002-08-19 21:24:44 +00:00
|
|
|
|
2003-09-10 16:39:06 +00:00
|
|
|
if (m_Err) // not done yet
|
2002-08-02 10:01:35 +00:00
|
|
|
{
|
|
|
|
// get current name
|
|
|
|
int l=GetModuleFileName(g_hInstance,ibuf,sizeof(ibuf));
|
|
|
|
// check if it is ?~NSISu_.exe - if so, fuck it
|
|
|
|
if (!lstrcmpi(ibuf+l-(sizeof(s)-2),s+1)) break;
|
|
|
|
|
|
|
|
// copy file
|
|
|
|
if (CopyFile(ibuf,buf2+1,FALSE))
|
|
|
|
{
|
|
|
|
HANDLE hProc;
|
|
|
|
#ifdef NSIS_SUPPORT_MOVEONREBOOT
|
|
|
|
MoveFileOnReboot(buf2+1,NULL);
|
|
|
|
#endif
|
2002-08-19 21:24:44 +00:00
|
|
|
if (state_install_directory[0]) mystrcpy(ibuf,state_install_directory);
|
2002-08-02 10:01:35 +00:00
|
|
|
else trimslashtoend(ibuf);
|
|
|
|
lstrcat(buf2,"\" ");
|
|
|
|
lstrcat(buf2,realcmds);
|
2002-09-13 18:00:11 +00:00
|
|
|
lstrcat(buf2," _?=");
|
2002-08-02 10:01:35 +00:00
|
|
|
lstrcat(buf2,ibuf);
|
2003-09-10 16:39:06 +00:00
|
|
|
// add a trailing backslash to make sure is_valid_instpath will not fail when it shouldn't
|
2003-11-14 21:08:51 +00:00
|
|
|
addtrailingslash(buf2);
|
2003-06-23 22:40:11 +00:00
|
|
|
hProc=myCreateProcess(buf2,state_temp_dir);
|
2003-09-10 16:39:06 +00:00
|
|
|
if (hProc)
|
|
|
|
{
|
|
|
|
CloseHandle(hProc);
|
|
|
|
// success
|
|
|
|
m_Err = 0;
|
|
|
|
}
|
2002-08-02 10:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
s[0]++;
|
|
|
|
}
|
2002-08-19 21:24:44 +00:00
|
|
|
goto end;
|
2002-08-02 10:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
|
|
|
|
|
2004-09-25 14:56:16 +00:00
|
|
|
g_exec_flags.errlvl = -1;
|
2003-07-18 14:22:17 +00:00
|
|
|
ret = ui_doinstall();
|
2002-08-02 10:01:35 +00:00
|
|
|
|
|
|
|
#ifdef NSIS_CONFIG_LOG
|
2003-11-24 14:22:50 +00:00
|
|
|
#ifndef NSIS_CONFIG_LOG_ODS
|
2002-08-02 10:01:35 +00:00
|
|
|
log_write(1);
|
2003-11-24 14:22:50 +00:00
|
|
|
#endif//!NSIS_CONFIG_LOG_ODS
|
2002-08-02 10:01:35 +00:00
|
|
|
#endif//NSIS_CONFIG_LOG
|
|
|
|
end:
|
2003-09-04 18:25:57 +00:00
|
|
|
|
2004-01-29 23:18:32 +00:00
|
|
|
CleanUp();
|
2002-08-05 02:05:00 +00:00
|
|
|
|
2004-10-14 13:56:02 +00:00
|
|
|
#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
|
|
|
|
OleUninitialize();
|
|
|
|
#endif
|
|
|
|
|
2004-01-29 23:18:32 +00:00
|
|
|
if (m_Err)
|
2004-09-25 10:49:08 +00:00
|
|
|
{
|
2004-01-29 23:18:32 +00:00
|
|
|
my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 20));
|
2004-10-14 13:56:02 +00:00
|
|
|
ExitProcess(2);
|
|
|
|
return 0;
|
2004-09-25 10:49:08 +00:00
|
|
|
}
|
2002-08-05 02:05:00 +00:00
|
|
|
|
2004-10-14 13:56:02 +00:00
|
|
|
#ifdef NSIS_SUPPORT_REBOOT
|
|
|
|
if (g_exec_flags.reboot_called)
|
|
|
|
{
|
|
|
|
HANDLE h=GetModuleHandle("ADVAPI32.dll");
|
|
|
|
if (h)
|
|
|
|
{
|
|
|
|
BOOL (WINAPI *OPT)(HANDLE, DWORD,PHANDLE);
|
|
|
|
BOOL (WINAPI *LPV)(LPCTSTR,LPCTSTR,PLUID);
|
|
|
|
BOOL (WINAPI *ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
|
|
|
|
OPT=(void*)GetProcAddress(h,"OpenProcessToken");
|
|
|
|
LPV=(void*)GetProcAddress(h,"LookupPrivilegeValueA");
|
|
|
|
ATP=(void*)GetProcAddress(h,"AdjustTokenPrivileges");
|
|
|
|
if (OPT && LPV && ATP)
|
|
|
|
{
|
|
|
|
HANDLE hToken;
|
|
|
|
TOKEN_PRIVILEGES tkp;
|
|
|
|
if (OPT(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
|
|
|
{
|
|
|
|
LPV(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
|
|
|
|
tkp.PrivilegeCount = 1;
|
|
|
|
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
ATP(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ExitWindowsEx(EWX_REBOOT,0))
|
|
|
|
ExecuteCallbackFunction(CB_ONREBOOTFAILED);
|
|
|
|
}
|
|
|
|
#endif//NSIS_SUPPORT_REBOOT
|
|
|
|
|
|
|
|
if (g_exec_flags.errlvl != -1)
|
|
|
|
ret = g_exec_flags.errlvl;
|
2003-09-22 16:06:53 +00:00
|
|
|
|
2004-09-25 14:56:16 +00:00
|
|
|
ExitProcess(ret);
|
2004-10-14 13:56:02 +00:00
|
|
|
return 0;
|
2004-01-29 23:18:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NSISCALL CleanUp()
|
|
|
|
{
|
|
|
|
if (g_db_hFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
CloseHandle(g_db_hFile);
|
|
|
|
g_db_hFile = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
#ifdef NSIS_COMPRESS_WHOLE
|
|
|
|
if (dbd_hFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
CloseHandle(dbd_hFile);
|
|
|
|
dbd_hFile = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
|
|
|
// Clean up after plug-ins
|
2004-08-06 17:03:07 +00:00
|
|
|
myDelete(state_plugins_dir, DEL_DIR | DEL_RECURSE | DEL_REBOOT);
|
2004-01-29 23:18:32 +00:00
|
|
|
#endif // NSIS_CONFIG_PLUGIN_SUPPORT
|
2004-02-05 14:06:05 +00:00
|
|
|
}
|