Fix session.xml emptying by forced Windows update restart
This fixes both the long standing problem with the emptying of the session.xml file by forced Windows Update restart/shutdown and some potential Notepad++ crashes caused by possible main Notepad++ window blocking at exit. Two main changes to the original design: - WM_QUERYENDSESSION is not used anymore for the tidy-up ops and it always quickly returns TRUE/FALSE to the system as it should. - there is now a safe-guard flag for the session.xml saving at N++ exit, which prevents otherwise possible incorrect overwriting in case of multiple "endsession" messages. Fix #9850, fix #12389, close #12388
This commit is contained in:
parent
ed3189e00b
commit
6000f3bb21
|
@ -39,7 +39,7 @@ Win32_IO_File::Win32_IO_File(const wchar_t *fname)
|
||||||
_hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, _dispParam, _attribParam, NULL);
|
_hFile = ::CreateFileW(fname, _accessParam, _shareParam, NULL, _dispParam, _attribParam, NULL);
|
||||||
|
|
||||||
NppParameters& nppParam = NppParameters::getInstance();
|
NppParameters& nppParam = NppParameters::getInstance();
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
|
@ -69,7 +69,7 @@ void Win32_IO_File::close()
|
||||||
|
|
||||||
|
|
||||||
NppParameters& nppParam = NppParameters::getInstance();
|
NppParameters& nppParam = NppParameters::getInstance();
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
|
@ -132,7 +132,7 @@ bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
|
||||||
NppParameters& nppParam = NppParameters::getInstance();
|
NppParameters& nppParam = NppParameters::getInstance();
|
||||||
if (::WriteFile(_hFile, wbuf, buf_size, &bytes_written, NULL) == FALSE)
|
if (::WriteFile(_hFile, wbuf, buf_size, &bytes_written, NULL) == FALSE)
|
||||||
{
|
{
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
|
@ -151,7 +151,7 @@ bool Win32_IO_File::write(const void *wbuf, unsigned long buf_size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
|
|
|
@ -2057,6 +2057,9 @@ void Notepad_plus::filePrint(bool showDialog)
|
||||||
|
|
||||||
int Notepad_plus::doSaveOrNot(const TCHAR* fn, bool isMulti)
|
int Notepad_plus::doSaveOrNot(const TCHAR* fn, bool isMulti)
|
||||||
{
|
{
|
||||||
|
if ((NppParameters::getInstance()).isEndSessionCritical())
|
||||||
|
return IDCANCEL; // simulate Esc-key or Cancel-button as there should not be any big delay / code-flow block
|
||||||
|
|
||||||
// In case Notepad++ is iconized into notification zone
|
// In case Notepad++ is iconized into notification zone
|
||||||
if (!::IsWindowVisible(_pPublicInterface->getHSelf()))
|
if (!::IsWindowVisible(_pPublicInterface->getHSelf()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -383,11 +383,8 @@ private:
|
||||||
bool _isFileOpening = false;
|
bool _isFileOpening = false;
|
||||||
bool _isAdministrator = false;
|
bool _isAdministrator = false;
|
||||||
|
|
||||||
bool _isEndingSessionButNotReady = false; // If Windows 10 update needs to restart
|
bool _isNppSessionSavedAtExit = false; // guard flag, it prevents emptying of the N++ session.xml in case of multiple WM_ENDSESSION or WM_CLOSE messages
|
||||||
// and Notepad++ has one (some) dirty document(s)
|
|
||||||
// and "Enable session snapshot and periodic backup" is not enabled
|
|
||||||
// then WM_ENDSESSION is send with wParam == FALSE
|
|
||||||
// in this case this boolean is set true, so Notepad++ will quit and its current session will be saved
|
|
||||||
ScintillaCtrls _scintillaCtrls4Plugins;
|
ScintillaCtrls _scintillaCtrls4Plugins;
|
||||||
|
|
||||||
std::vector<std::pair<int, int> > _hideLinesMarks;
|
std::vector<std::pair<int, int> > _hideLinesMarks;
|
||||||
|
|
|
@ -2059,14 +2059,29 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_QUERYENDSESSION:
|
case WM_QUERYENDSESSION:
|
||||||
case WM_CLOSE:
|
|
||||||
{
|
{
|
||||||
if (message == WM_QUERYENDSESSION)
|
// app should return TRUE or FALSE immediately upon receiving this message,
|
||||||
{
|
// and defer any cleanup operations until it receives WM_ENDSESSION (with WPARAM TRUE)
|
||||||
nppParam.queryEndSessionStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
// for a bigger tidy-up/save operations we can kick off a background thread here to prepare for shutdown
|
||||||
|
// and when we get the WM_ENDSESSION TRUE, we wait there until that background operation completes
|
||||||
|
// before telling the system, "ok, you can shut down now...", i.e. returning 0 there
|
||||||
|
|
||||||
|
// whatever we do from here - make sure that it is ok for the operation to occur even if the shutdown
|
||||||
|
// is then subsequently canceled
|
||||||
|
|
||||||
|
// here we could also display a prompt to ask the users whether they want to save their unsaved changes etc.,
|
||||||
|
// but in practice, this is usually not a good idea because if we do not respond to this message
|
||||||
|
// after a few seconds (e.g. user is away from PC...), the system will shut down without us
|
||||||
|
|
||||||
|
bool isFirstQueryEndSession = !nppParam.isEndSessionStarted();
|
||||||
|
bool isForcedShuttingDown = (lParam & ENDSESSION_CRITICAL);
|
||||||
|
|
||||||
|
nppParam.endSessionStart();
|
||||||
|
if (isForcedShuttingDown)
|
||||||
|
nppParam.makeEndSessionCritical();
|
||||||
|
|
||||||
|
if (nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
|
@ -2074,7 +2089,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
pathAppend(nppIssueLog, issueFn);
|
pathAppend(nppIssueLog, issueFn);
|
||||||
|
|
||||||
string wmqesType = std::to_string(lParam);
|
string wmqesType = std::to_string(lParam);
|
||||||
if (0 == lParam)
|
if (lParam == 0)
|
||||||
{
|
{
|
||||||
wmqesType += " - ordinary system shutdown/restart";
|
wmqesType += " - ordinary system shutdown/restart";
|
||||||
}
|
}
|
||||||
|
@ -2088,11 +2103,173 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
if (lParam & ENDSESSION_LOGOFF)
|
if (lParam & ENDSESSION_LOGOFF)
|
||||||
wmqesType += " - ENDSESSION_LOGOFF";
|
wmqesType += " - ENDSESSION_LOGOFF";
|
||||||
}
|
}
|
||||||
string queryEndSession = "WM_QUERYENDSESSION (lParam: " + wmqesType + ") =====================================";
|
string msg = "WM_QUERYENDSESSION (lParam: " + wmqesType + ") =====================================";
|
||||||
if (WM_QUERYENDSESSION == message)
|
writeLog(nppIssueLog.c_str(), msg.c_str());
|
||||||
writeLog(nppIssueLog.c_str(), queryEndSession.c_str());
|
}
|
||||||
|
|
||||||
|
if (::IsWindowEnabled(hwnd))
|
||||||
|
{
|
||||||
|
if (MainFileManager.getNbDirtyBuffers() > 0)
|
||||||
|
{
|
||||||
|
// we have unsaved filebuffer(s), give the user a chance to respond (non-critical shutdown only)
|
||||||
|
if (!isForcedShuttingDown && isFirstQueryEndSession)
|
||||||
|
{
|
||||||
|
// if N++ has been minimized or invisible, we need to show it 1st
|
||||||
|
if (::IsIconic(hwnd))
|
||||||
|
{
|
||||||
|
::ShowWindow(hwnd, SW_RESTORE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
writeLog(nppIssueLog.c_str(), "WM_CLOSE (isQueryEndSessionStarted == true)");
|
{
|
||||||
|
if (!::IsWindowVisible(hwnd))
|
||||||
|
{
|
||||||
|
// systray etc...
|
||||||
|
::ShowWindow(hwnd, SW_SHOW);
|
||||||
|
::SendMessage(hwnd, WM_SIZE, 0, 0); // to make window fit (specially to show tool bar.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::PostMessage(hwnd, WM_COMMAND, IDM_FILE_SAVEALL, 0); // posting will not block us here
|
||||||
|
return FALSE; // request abort of the shutdown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we probably have a blocking modal-window like MessageBox (e.g. the "Reload" or "Keep non existing file")
|
||||||
|
if (!isForcedShuttingDown && isFirstQueryEndSession)
|
||||||
|
return FALSE; // request abort of the shutdown (for a non-critical one we can give the user a chance to solve whatever is needed)
|
||||||
|
|
||||||
|
// here is the right place to unblock the modal-dlg blocking the main N++ wnd, because then it will be too late
|
||||||
|
// to do so at the WM_ENDSESSION time (for that we need this thread message queue...)
|
||||||
|
|
||||||
|
// in most cases we will need to take care and programmatically close such dialogs in order to exit gracefully,
|
||||||
|
// otherwise the N++ most probably crashes itself without any tidy-up
|
||||||
|
|
||||||
|
string strLog = "Main N++ wnd is disabled by (an active modal-dlg?): ";
|
||||||
|
char szBuf[MAX_PATH + 128] = { 0 };
|
||||||
|
|
||||||
|
HWND hActiveWnd = ::GetActiveWindow();
|
||||||
|
if (hActiveWnd)
|
||||||
|
{
|
||||||
|
if (::GetWindowTextA(hActiveWnd, szBuf, _countof(szBuf)))
|
||||||
|
strLog += szBuf;
|
||||||
|
::SendMessage(hActiveWnd, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no active child window, so it is most probably the system dialog box class #32770 (used e.g. by the MessageBox WINAPI)
|
||||||
|
// - so our main hwnd here is not the PARENT but OWNER of that top-level window
|
||||||
|
hActiveWnd = ::GetLastActivePopup(hwnd);
|
||||||
|
if (hActiveWnd)
|
||||||
|
{
|
||||||
|
if (::GetWindowTextA(hActiveWnd, szBuf, _countof(szBuf)))
|
||||||
|
strLog += szBuf;
|
||||||
|
::GetClassNameA(hActiveWnd, szBuf, _countof(szBuf));
|
||||||
|
if (lstrcmpiA("#32770", szBuf) == 0)
|
||||||
|
strLog += " (MessageBox)";
|
||||||
|
// we cannot use here the usual sending of the WM_CLOSE as it will not always work (e.g. for a MB_YESNO MessageBox)
|
||||||
|
if (!::EndDialog(hActiveWnd, 0))
|
||||||
|
{
|
||||||
|
strLog += " -> EndDialog failed with ErrorCode: ";
|
||||||
|
strLog += std::to_string(::GetLastError());
|
||||||
|
// last attempt
|
||||||
|
::SendMessage(hActiveWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strLog += "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-test
|
||||||
|
if (::IsWindowEnabled(hwnd))
|
||||||
|
strLog += " -> Main N++ wnd has been successfully reenabled.";
|
||||||
|
|
||||||
|
if (nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
|
{
|
||||||
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
|
issueFn += TEXT(".log");
|
||||||
|
generic_string nppIssueLog = nppParam.getUserPath();
|
||||||
|
pathAppend(nppIssueLog, issueFn);
|
||||||
|
writeLog(nppIssueLog.c_str(), strLog.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: here is the last opportunity to call the following WINAPI in a possible future version of the N++
|
||||||
|
//
|
||||||
|
// flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we should be restarted if terminated by an update or restart
|
||||||
|
//::RegisterApplicationRestart(restartCommandLine.c_str(), RESTART_NO_CRASH | RESTART_NO_HANG);
|
||||||
|
|
||||||
|
return TRUE; // nowadays, with the monstrous Win10+ Windows Update behind, is futile to try to interrupt the shutdown by returning FALSE here
|
||||||
|
// (if one really needs so, there is the ShutdownBlockReasonCreate WINAPI for the rescue ...)
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_ENDSESSION:
|
||||||
|
{
|
||||||
|
// this message informs our app whether the session is really ending
|
||||||
|
|
||||||
|
if (nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
|
{
|
||||||
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
|
issueFn += TEXT(".log");
|
||||||
|
generic_string nppIssueLog = nppParam.getUserPath();
|
||||||
|
pathAppend(nppIssueLog, issueFn);
|
||||||
|
|
||||||
|
string wmesType = std::to_string(lParam);
|
||||||
|
if (lParam == 0)
|
||||||
|
{
|
||||||
|
wmesType += " - ordinary system shutdown/restart";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the lParam here is a bit mask, it can be one or more of the following values
|
||||||
|
if (lParam & ENDSESSION_CLOSEAPP)
|
||||||
|
wmesType += " - ENDSESSION_CLOSEAPP";
|
||||||
|
if (lParam & ENDSESSION_CRITICAL)
|
||||||
|
wmesType += " - ENDSESSION_CRITICAL";
|
||||||
|
if (lParam & ENDSESSION_LOGOFF)
|
||||||
|
wmesType += " - ENDSESSION_LOGOFF";
|
||||||
|
}
|
||||||
|
string msg = "WM_ENDSESSION (wParam: ";
|
||||||
|
if (wParam)
|
||||||
|
msg += "TRUE, lParam: ";
|
||||||
|
else
|
||||||
|
msg += "FALSE, lParam: ";
|
||||||
|
msg += wmesType + ")";
|
||||||
|
|
||||||
|
writeLog(nppIssueLog.c_str(), msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wParam == FALSE)
|
||||||
|
{
|
||||||
|
// the session is not being ended after all
|
||||||
|
// - it happens when either the N++ returns FALSE to non-critical WM_QUERYENDSESSION or any other app with higher shutdown level
|
||||||
|
// than N++ (app shuttdown order can be checked by the GetProcessShutdownParameters WINAPI)
|
||||||
|
// - we will not try to reset back our nppParam _isEndSessionStarted flag somehow, because of we should now that there was already
|
||||||
|
// a previous shutdown attempt, otherwise we could stubbornly repeat returning FALSE for the next WM_QUERYENDSESSION and
|
||||||
|
// the system will terminate us
|
||||||
|
return 0; // return here and do not continue to the WM_CLOSE part
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the session is being ended, it can end ANY TIME after all apps running have returned from processing this message,
|
||||||
|
// so DO NOT e.g. Send/Post any message from here onwards!!!
|
||||||
|
nppParam.endSessionStart(); // ensure
|
||||||
|
nppParam.makeEndSessionCritical(); // set our exit-flag to critical even if the bitmask has not the ENDSESSION_CRITICAL set
|
||||||
|
// do not return 0 here and continue to the N++ standard WM_CLOSE code-part (no verbose GUI there this time!!!)
|
||||||
|
}
|
||||||
|
} // case WM_ENDSESSION:
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
{
|
||||||
|
if (nppParam.doNppLogNulContentCorruptionIssue() && nppParam.isEndSessionStarted() && (message == WM_CLOSE))
|
||||||
|
{
|
||||||
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
|
issueFn += TEXT(".log");
|
||||||
|
generic_string nppIssueLog = nppParam.getUserPath();
|
||||||
|
pathAppend(nppIssueLog, issueFn);
|
||||||
|
writeLog(nppIssueLog.c_str(), "WM_CLOSE (isEndSessionStarted == true)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pPublicInterface->isPrelaunch())
|
if (_pPublicInterface->isPrelaunch())
|
||||||
|
@ -2102,9 +2279,9 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SCNotification scnN{};
|
SCNotification scnN{};
|
||||||
scnN.nmhdr.code = NPPN_BEFORESHUTDOWN;
|
|
||||||
scnN.nmhdr.hwndFrom = hwnd;
|
scnN.nmhdr.hwndFrom = hwnd;
|
||||||
scnN.nmhdr.idFrom = 0;
|
scnN.nmhdr.idFrom = 0;
|
||||||
|
scnN.nmhdr.code = NPPN_BEFORESHUTDOWN;
|
||||||
_pluginsManager.notify(&scnN);
|
_pluginsManager.notify(&scnN);
|
||||||
|
|
||||||
if (_pTrayIco)
|
if (_pTrayIco)
|
||||||
|
@ -2141,15 +2318,14 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
saveFileBrowserParam();
|
saveFileBrowserParam();
|
||||||
saveColumnEditorParams();
|
saveColumnEditorParams();
|
||||||
|
|
||||||
if (!allClosed)
|
if (!allClosed && !nppParam.isEndSessionCritical())
|
||||||
{
|
{
|
||||||
//User cancelled the shutdown
|
// cancelled by user
|
||||||
scnN.nmhdr.code = NPPN_CANCELSHUTDOWN;
|
scnN.nmhdr.code = NPPN_CANCELSHUTDOWN;
|
||||||
_pluginsManager.notify(&scnN);
|
_pluginsManager.notify(&scnN);
|
||||||
|
|
||||||
if (isSnapshotMode)
|
if (isSnapshotMode)
|
||||||
::LockWindowUpdate(NULL);
|
::LockWindowUpdate(NULL);
|
||||||
return FALSE;
|
return 0; // abort quitting
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_beforeSpecialView._isFullScreen) //closing, return to windowed mode
|
if (_beforeSpecialView._isFullScreen) //closing, return to windowed mode
|
||||||
|
@ -2163,7 +2339,6 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
scnN.nmhdr.code = NPPN_SHUTDOWN;
|
scnN.nmhdr.code = NPPN_SHUTDOWN;
|
||||||
_pluginsManager.notify(&scnN);
|
_pluginsManager.notify(&scnN);
|
||||||
|
|
||||||
|
|
||||||
saveScintillasZoom();
|
saveScintillasZoom();
|
||||||
saveGUIParams(); //writeGUIParams writeScintillaParams
|
saveGUIParams(); //writeGUIParams writeScintillaParams
|
||||||
saveFindHistory(); //writeFindHistory
|
saveFindHistory(); //writeFindHistory
|
||||||
|
@ -2183,6 +2358,10 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
//
|
//
|
||||||
saveShortcuts();
|
saveShortcuts();
|
||||||
|
|
||||||
|
if (!_isNppSessionSavedAtExit)
|
||||||
|
{
|
||||||
|
_isNppSessionSavedAtExit = true; // prevents emptying of the session.xml file on another WM_ENDSESSION or WM_CLOSE
|
||||||
|
|
||||||
//
|
//
|
||||||
// saving session.xml
|
// saving session.xml
|
||||||
//
|
//
|
||||||
|
@ -2195,6 +2374,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
generic_string loadedSessionFilePath = nppParam.getLoadedSessionFilePath();
|
generic_string loadedSessionFilePath = nppParam.getLoadedSessionFilePath();
|
||||||
if (!loadedSessionFilePath.empty() && PathFileExists(loadedSessionFilePath.c_str()))
|
if (!loadedSessionFilePath.empty() && PathFileExists(loadedSessionFilePath.c_str()))
|
||||||
nppParam.writeSession(currentSession, loadedSessionFilePath.c_str());
|
nppParam.writeSession(currentSession, loadedSessionFilePath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// write settings on cloud if enabled, if the settings files don't exist
|
// write settings on cloud if enabled, if the settings files don't exist
|
||||||
if (nppgui._cloudPath != TEXT("") && nppParam.isCloudPathChanged())
|
if (nppgui._cloudPath != TEXT("") && nppParam.isCloudPathChanged())
|
||||||
|
@ -2215,9 +2395,10 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
::LockWindowUpdate(NULL);
|
::LockWindowUpdate(NULL);
|
||||||
|
|
||||||
//Sends WM_DESTROY, Notepad++ will end
|
//Sends WM_DESTROY, Notepad++ will end
|
||||||
if (message == WM_CLOSE)
|
|
||||||
::DestroyWindow(hwnd);
|
::DestroyWindow(hwnd);
|
||||||
|
|
||||||
|
if (!nppParam.isEndSessionCritical())
|
||||||
|
{
|
||||||
generic_string updaterFullPath = nppParam.getWingupFullPath();
|
generic_string updaterFullPath = nppParam.getWingupFullPath();
|
||||||
if (!updaterFullPath.empty())
|
if (!updaterFullPath.empty())
|
||||||
{
|
{
|
||||||
|
@ -2225,73 +2406,20 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
||||||
updater.run(nppParam.shouldDoUAC());
|
updater.run(nppParam.shouldDoUAC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _isEndingSessionButNotReady is true means WM_QUERYENDSESSION is sent but no time to finish saving data
|
|
||||||
// then WM_ENDSESSION is sent with wParam == FALSE - Notepad++ should exit in this case
|
|
||||||
if (_isEndingSessionButNotReady)
|
|
||||||
::DestroyWindow(hwnd);
|
|
||||||
|
|
||||||
if (message == WM_CLOSE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_ENDSESSION:
|
return 0; // both WM_CLOSE and a possible WM_ENDSESSION should return 0
|
||||||
{
|
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
|
||||||
{
|
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
|
||||||
issueFn += TEXT(".log");
|
|
||||||
generic_string nppIssueLog = nppParam.getUserPath();
|
|
||||||
pathAppend(nppIssueLog, issueFn);
|
|
||||||
|
|
||||||
string wmesType = std::to_string(lParam);
|
|
||||||
if (0 == lParam)
|
|
||||||
{
|
|
||||||
wmesType += " - ordinary system shutdown/restart";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the lParam here is a bit mask, it can be one or more of the following values
|
|
||||||
if (lParam & ENDSESSION_CLOSEAPP)
|
|
||||||
wmesType += " - ENDSESSION_CLOSEAPP";
|
|
||||||
if (lParam & ENDSESSION_CRITICAL)
|
|
||||||
wmesType += " - ENDSESSION_CRITICAL";
|
|
||||||
if (lParam & ENDSESSION_LOGOFF)
|
|
||||||
wmesType += " - ENDSESSION_LOGOFF";
|
|
||||||
}
|
|
||||||
string endSession = "WM_ENDSESSION (wParam: ";
|
|
||||||
if (wParam)
|
|
||||||
endSession += "TRUE, lParam: ";
|
|
||||||
else
|
|
||||||
endSession += "FALSE, lParam: ";
|
|
||||||
endSession += wmesType + ")";
|
|
||||||
|
|
||||||
writeLog(nppIssueLog.c_str(), endSession.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wParam == TRUE)
|
|
||||||
{
|
|
||||||
::DestroyWindow(hwnd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_isEndingSessionButNotReady = true;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
{
|
{
|
||||||
if (nppParam.isQueryEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
if (nppParam.isEndSessionStarted() && nppParam.doNppLogNulContentCorruptionIssue())
|
||||||
{
|
{
|
||||||
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
generic_string issueFn = nppLogNulContentCorruptionIssue;
|
||||||
issueFn += TEXT(".log");
|
issueFn += TEXT(".log");
|
||||||
generic_string nppIssueLog = nppParam.getUserPath();
|
generic_string nppIssueLog = nppParam.getUserPath();
|
||||||
pathAppend(nppIssueLog, issueFn);
|
pathAppend(nppIssueLog, issueFn);
|
||||||
|
writeLog(nppIssueLog.c_str(), "WM_DESTROY (isEndSessionStarted == true)");
|
||||||
writeLog(nppIssueLog.c_str(), "WM_DESTROY");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
killAllChildren();
|
killAllChildren();
|
||||||
|
|
|
@ -1874,7 +1874,8 @@ private:
|
||||||
bool _doNppLogNetworkDriveIssue = false;
|
bool _doNppLogNetworkDriveIssue = false;
|
||||||
|
|
||||||
bool _doNppLogNulContentCorruptionIssue = false;
|
bool _doNppLogNulContentCorruptionIssue = false;
|
||||||
bool _isQueryEndSessionStarted = false;
|
bool _isEndSessionStarted = false;
|
||||||
|
bool _isEndSessionCritical = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generic_string getWingupFullPath() const { return _wingupFullPath; };
|
generic_string getWingupFullPath() const { return _wingupFullPath; };
|
||||||
|
@ -1888,8 +1889,10 @@ public:
|
||||||
|
|
||||||
bool doNppLogNetworkDriveIssue() { return _doNppLogNetworkDriveIssue; };
|
bool doNppLogNetworkDriveIssue() { return _doNppLogNetworkDriveIssue; };
|
||||||
bool doNppLogNulContentCorruptionIssue() { return _doNppLogNulContentCorruptionIssue; };
|
bool doNppLogNulContentCorruptionIssue() { return _doNppLogNulContentCorruptionIssue; };
|
||||||
void queryEndSessionStart() { _isQueryEndSessionStarted = true; };
|
void endSessionStart() { _isEndSessionStarted = true; };
|
||||||
bool isQueryEndSessionStarted() { return _isQueryEndSessionStarted; };
|
bool isEndSessionStarted() { return _isEndSessionStarted; };
|
||||||
|
void makeEndSessionCritical() { _isEndSessionCritical = true; };
|
||||||
|
bool isEndSessionCritical() { return _isEndSessionCritical; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void getLangKeywordsFromXmlTree();
|
void getLangKeywordsFromXmlTree();
|
||||||
|
|
|
@ -1365,6 +1365,9 @@ generic_string NativeLangSpeaker::getAttrNameStr(const TCHAR *defaultStr, const
|
||||||
|
|
||||||
int NativeLangSpeaker::messageBox(const char *msgBoxTagName, HWND hWnd, const TCHAR *defaultMessage, const TCHAR *defaultTitle, int msgBoxType, int intInfo, const TCHAR *strInfo)
|
int NativeLangSpeaker::messageBox(const char *msgBoxTagName, HWND hWnd, const TCHAR *defaultMessage, const TCHAR *defaultTitle, int msgBoxType, int intInfo, const TCHAR *strInfo)
|
||||||
{
|
{
|
||||||
|
if ((NppParameters::getInstance()).isEndSessionCritical())
|
||||||
|
return IDCANCEL; // simulate Esc-key or Cancel-button as there should not be any big delay / code-flow block
|
||||||
|
|
||||||
generic_string msg, title;
|
generic_string msg, title;
|
||||||
if (!getMsgBoxLang(msgBoxTagName, title, msg))
|
if (!getMsgBoxLang(msgBoxTagName, title, msg))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue