made the Reboot command first quit and then reboot

- fixed bug #989690
 - the installer now denies reboots while running
 - the Reboot instruction no longer returns or sets the error flag
 - added .onRebootFailed which is called when Reboot fails
 - installer should now always clean-up when rebooting


git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3729 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2004-10-14 13:56:02 +00:00
parent b5cab9b25f
commit 335fd47066
10 changed files with 100 additions and 58 deletions

View file

@ -327,7 +327,7 @@ You can also set a subcaption (or override the default) using \R{acaption}{Capti
\c text
Changes the text of the button that by default says "Uninstall" in the uninstaller. If no parameter is specified, the default text is used. See also \R{WriteUninstaller}{WriteUninstaller} (replaces UninstallEXEName).
Changes the text of the button that by default says "Uninstall" in the uninstaller. If no parameter is specified, the default text is used. See also \R{writeuninstaller}{WriteUninstaller} (replaces UninstallEXEName).
\S2{auninstallcaption} UninstallCaption

View file

@ -86,6 +86,16 @@ Example:
\c SendMessage $R0 ${WM_SETTEXT} 0 "second section description"
\c FunctionEnd
\S3{onrebootfailed} .onRebootFailed
This callback is called if \R{reboot}{Reboot} fails. \R{writeuninstaller}{WriteUninstaller}, \R{plugindlls}{plug-ins}, \R{file}{File} and \R{writeregbin}{WriteRegBin} should not be used in this callback.
Example:
\c Function .onRebootFailed
\c MessageBox MB_OK|MB_ICONSTOP "Reboot failed. Please reboot manually." /SD IDOK
\c FunctionEnd
\S3{onselchange} .onSelChange
Called when the selection changes on the \R{pages}{component page}. Useful for using with \R{sectionsetflags}{SectionSetFlags} and \R{sectiongetflags}{SectionGetFlags}.
@ -167,6 +177,16 @@ Example:
This callback is called right after the uninstaller window closes. Use it to free any user interface related plug-ins if needed.
\S3{unonrebootfailed} un.onRebootFailed
This callback is called if \R{reboot}{Reboot} fails. \R{writeuninstaller}{WriteUninstaller}, \R{plugindlls}{plug-ins}, \R{file}{File} and \R{writeregbin}{WriteRegBin} should not be used in this callback.
Example:
\c Function un.onRebootFailed
\c MessageBox MB_OK|MB_ICONSTOP "Reboot failed. Please reboot manually." /SD IDOK
\c FunctionEnd
\S3{unonuserabort} un.onUserAbort
This callback is called when the user hits the 'cancel' button and the uninstall hasn't already failed. If this function calls Abort, the install will not be aborted.

View file

@ -2,7 +2,7 @@
\S2{reboot} Reboot
Reboots the computer. Be careful with this one. If there is an error rebooting, this function sets the error flag and continues. If the reboot is successful, this instruction does not return.
Reboots the computer. Be careful with this one. If it fails, \R{onrebootfailed}{.onRebootFailed} is called. In any case, this instruction never returns, just like \R{quit}{Quit}.
\c MessageBox MB_YESNO|MB_ICONQUESTION "Do you wish to reboot the system?" IDNO +2
\c Reboot

View file

@ -1,6 +1,6 @@
\S1{uninst} Uninstaller Instructions
\S2{WriteUninstaller} WriteUninstaller
\S2{writeuninstaller} WriteUninstaller
\c [Path\]exename.exe

View file

@ -1537,10 +1537,13 @@ int CEXEBuild::resolve_coderefs(const char *str)
{"%s.onGUIInit", &cur_header->code_onGUIInit},
{"%s.onGUIEnd", &cur_header->code_onGUIEnd},
{"%s.onMouseOverSection", &cur_header->code_onMouseOverSection},
#endif
#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
#ifdef NSIS_CONFIG_COMPONENTPAGE
{"%s.onSelChange", &cur_header->code_onSelChange},
#endif
#endif//NSIS_CONFIG_COMPONENTPAGE
#ifdef NSIS_SUPPORT_REBOOT
{"%s.onRebootFailed", &cur_header->code_onRebootFailed},
#endif//NSIS_SUPPORT_REBOOT
{0, 0}
};

View file

@ -245,8 +245,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam,
g_exec_flags.errlvl = -1;
ret = ui_doinstall();
if (g_exec_flags.errlvl != -1)
ret = g_exec_flags.errlvl;
#ifdef NSIS_CONFIG_LOG
#ifndef NSIS_CONFIG_LOG_ODS
@ -257,17 +255,53 @@ end:
CleanUp();
if (m_Err)
{
my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 20));
ret = 2;
}
#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
OleUninitialize();
#endif
if (m_Err)
{
my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 20));
ExitProcess(2);
return 0;
}
#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;
ExitProcess(ret);
return 0;
}
void NSISCALL CleanUp()

View file

@ -577,7 +577,12 @@ skipPage:
m_curwnd = (HWND)wParam;
goto skipPage;
}
if (uMsg == WM_QUERYENDSESSION || (uMsg == WM_CLOSE && m_page == g_blocks[NB_PAGES].num - 1))
if (uMsg == WM_QUERYENDSESSION)
{
SetWindowLong(hwndDlg, DWL_MSGRESULT, FALSE);
return TRUE;
}
if (uMsg == WM_CLOSE && m_page == g_blocks[NB_PAGES].num - 1)
{
if (!IsWindowEnabled(m_hwndCancel))
{

View file

@ -1056,39 +1056,10 @@ static int NSISCALL ExecuteEntry(entry *entry_)
my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<20));
return EXEC_ERROR;
}
g_exec_flags.exec_error++;
{
HANDLE h=LoadLibrary("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);
}
}
FreeLibrary(h);
}
if (ExitWindowsEx(EWX_REBOOT,0))
{
g_quit_flag++;
PostQuitMessage(0);
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

View file

@ -291,14 +291,15 @@ typedef struct
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
int code_onGUIInit;
int code_onGUIEnd;
#endif
int code_onVerifyInstDir;
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
int code_onMouseOverSection;
#endif
#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
int code_onVerifyInstDir;
#ifdef NSIS_CONFIG_COMPONENTPAGE
int code_onSelChange;
#endif//NSIS_CONFIG_COMPONENTPAGE
#ifdef NSIS_SUPPORT_REBOOT
int code_onRebootFailed;
#endif//NSIS_SUPPORT_REBOOT
#endif//NSIS_SUPPORT_CODECALLBACKS
#ifdef NSIS_CONFIG_COMPONENTPAGE
@ -320,14 +321,15 @@ enum
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
CB_ONGUIINIT,
CB_ONGUIEND,
#endif
CB_ONVERIFYINSTDIR,
#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
CB_ONMOUSEOVERSECTION,
#endif
#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
CB_ONVERIFYINSTDIR,
#ifdef NSIS_CONFIG_COMPONENTPAGE
CB_ONSELCHANGE
CB_ONSELCHANGE,
#endif//NSIS_CONFIG_COMPONENTPAGE
#ifdef NSIS_SUPPORT_REBOOT
CB_ONREBOOTFAILED
#endif//NSIS_SUPPORT_REBOOT
};
#endif//NSIS_SUPPORT_CODECALLBACKS
@ -459,6 +461,7 @@ typedef struct
int abort;
#ifdef NSIS_SUPPORT_REBOOT
int exec_reboot;
int reboot_called;
#endif
int cur_insttype;
int insttype_changed;

View file

@ -5078,12 +5078,18 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
#endif//!NSIS_SUPPORT_FILEFUNCTIONS
#ifdef NSIS_SUPPORT_REBOOT
case TOK_REBOOT:
ent.which=EW_REBOOT;
ent.offsets[0]=0xbadf00d;
{
int ret = add_entry_direct(EW_REBOOT, 0xbadf00d);
if (ret != PS_OK) return ret;
ret = add_entry_direct(EW_QUIT);
if (ret != PS_OK) return ret;
SCRIPT_MSG("Reboot! (WOW)\n");
DefineInnerLangString(NLF_INST_CORRUPTED);
return add_entry(&ent);
}
return PS_OK;
case TOK_IFREBOOTFLAG:
ent.which=EW_IFFLAG;
if (process_jump(line,1,&ent.offsets[0]) ||