summaryrefslogtreecommitdiff
path: root/Shutdown/LogDlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Shutdown/LogDlg.cpp')
-rw-r--r--Shutdown/LogDlg.cpp502
1 files changed, 502 insertions, 0 deletions
diff --git a/Shutdown/LogDlg.cpp b/Shutdown/LogDlg.cpp
new file mode 100644
index 0000000..3d94bc9
--- /dev/null
+++ b/Shutdown/LogDlg.cpp
@@ -0,0 +1,502 @@
+// LogDlg.cpp : Implementation of CShutdownApp and DLL registration.
+
+#include "stdafx.h"
+#include "LogDlg.h"
+
+#include <algorithm>
+using std::replace;
+
+_COM_SMARTPTR_TYPEDEF(INightSecErrorFix, __uuidof(INightSecErrorFix));
+
+#include <appmisc.h>
+#include <shlobj.h>
+
+#define IMAGE_OKAY 0
+#define IMAGE_ERROR 1
+
+/////////////////////////////////////////////////////////////////////////////
+//
+LRESULT CLogDlg::OnHide(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // We use this event to keep the program open
+ // when the user is looking at the log
+ if(m_hEvent)
+ SetEvent(m_hEvent);
+
+ ShowWindow(SW_HIDE);
+ return 0;
+}
+
+LRESULT CLogDlg::OnSave(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // I think this is good enough. ie: saving on the desktop.
+ if(IDYES == MessageBox(_T("The log will be saved on your desktop. Continue?"), _T("Save Log"), MB_YESNO | MB_ICONQUESTION))
+ SaveLog();
+
+ return 0;
+}
+
+LRESULT CLogDlg::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ OnHide(0, 0, NULL, bHandled);
+ return 0;
+}
+
+/*LRESULT CLogDlg::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ return 0;
+}
+*/
+//////////////////////////////////////////////////////////////////
+// InitDialog (what more can I say)
+
+LRESULT CLogDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ m_hIcon = ::LoadIcon(_Module.m_hInst, MAKEINTRESOURCE(IDI_ERR));
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ // Create the small icon image list.
+ m_ImageListSmall.Create(IDB_ERRORS,
+ 16,
+ 0, // list won't grow
+ RGB(255, 0, 255));
+
+ // Set Mask color for Image Lists
+ m_ImageListSmall.SetBkColor(CLR_NONE);
+
+ m_ctlErrors = GetDlgItem(IDC_ERROR_LOG);
+
+ // Associate the image lists with the list view control.
+ m_ctlErrors.SetImageList(m_ImageListSmall, LVSIL_SMALL);
+
+ // This sets the sizing of the dialog
+ SetMin(IDC_MINSIZE);
+ SetControlSizing(ID_SAVE, SD_HORZ | SD_MOVING);
+ SetControlSizing(ID_HIDE, SD_HORZ | SD_MOVING);
+ SetControlSizing(IDC_ERROR_LOG, SD_HORZ | SD_VERT | SD_SIZING);
+
+ // We need at least one bogus column since we're using
+ // report view
+ LV_COLUMN lvC; // list view column structure
+
+ // Now initialize the columns you will need.
+ // Initialize the LV_COLUMN structure.
+ // The mask specifies that the fmt, width, pszText, and subitem members
+ // of the structure are valid.
+ lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvC.fmt = LVCFMT_LEFT; // left-align column
+ lvC.cx = 200; // width of column in pixels
+ lvC.iSubItem = 0;
+ lvC.pszText = _T("Errors");
+
+ if (m_ctlErrors.InsertColumn(0, &lvC) == -1)
+ return true;
+
+ // Make sure the column is the width of control
+ RECT rect;
+ m_ctlErrors.GetClientRect(&rect);
+ m_ctlErrors.SetColumnWidth(0, rect.right);
+
+ // Move Window to previous position
+ if(!LoadPosition(_Module.m_settings))
+ // If fails then Center it on the desktop
+ CenterWindow(GetDesktopWindow());
+
+ // This event gets set when we're hidden
+ m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+LRESULT CLogDlg::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ // Clear All Items (which also releases the COM Objects)
+ while(m_ctlErrors.GetItemCount())
+ RemoveItem(0);
+
+ // Just in case set the event
+ if(m_hEvent)
+ SetEvent(m_hEvent);
+
+ // Put window position in registry for next time
+ SavePosition(_Module.m_settings);
+
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////
+// Gives the item a tick or cross image depending on bState
+
+bool CLogDlg::AddItem(INightSecError* pError)
+{
+ USES_CONVERSION;
+
+ if(!pError)
+ return false;
+
+ // Get the Description of the Error
+ BSTR bsTemp;
+ HRESULT hr = pError->get_Description(&bsTemp);
+
+ if(FAILED(hr))
+ return false;
+
+ // Clean up any new lines
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\n', L' ');
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\r', L' ');
+
+ // Make sure object stays around
+ pError->AddRef();
+
+ // Create or Show the Log Window
+ ShowLog();
+
+ // Setup Structures
+ LV_ITEM lv;
+ lv.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
+ lv.iSubItem = 0;
+ lv.iItem = m_ctlErrors.GetItemCount();
+ lv.iImage = 1;
+ lv.lParam = (LPARAM)pError;
+ lv.pszText = OLE2T(bsTemp);
+
+ // Set right image for item
+ return m_ctlErrors.InsertItem(&lv) ? true : false;
+}
+
+void CLogDlg::ShowLog()
+{
+ // If not created then Create
+ if(!IsWindow())
+ Create(m_hWndParent, NULL);
+
+ // Make sure it's Visible
+ if(!IsWindowVisible())
+ ShowWindow(SW_SHOW);
+
+ // Make sure event is not signalled so we don't just close by self
+ ResetEvent(m_hEvent);
+}
+
+void CLogDlg::WaitLog()
+{
+ // Prompt the user
+ UINT nRet = MessageBoxTimeout(g_site.m_log, _T("There were errors during Secure Shutdown. \n\nWould you like to pause a moment before continuing?"), _T("Secure Shutdown"), MB_YESNO | MB_ICONQUESTION, 10000, 5000);
+
+ if(nRet == IDYES)
+ {
+ // Display the Log Window
+ ShowLog();
+
+ // Wait for the Event
+ if(m_hEvent)
+ WaitForAndIdle(1, &m_hEvent, INFINITE);
+ }
+
+ // If we time out then save the log on the desktop
+ else if(nRet == IDTIMEOUT)
+ if(!_Module.m_settings.GetInt(NO_LOG_KEY, false))
+ SaveLog();
+}
+
+HRESULT CLogDlg::SaveLog(/*const string& sFile*/)
+{
+ string sFile;
+ LPITEMIDLIST pidl;
+ HRESULT hr;
+
+ // Get Desktop PIDL
+ hr = SHGetSpecialFolderLocation(*this, CSIDL_DESKTOPDIRECTORY, &pidl);
+
+ if(FAILED(hr))
+ return 0;
+
+ // Get the Folder from That
+ if(!SHGetPathFromIDList(pidl, sFile.get_buffer(MAX_PATH)))
+ return 0;
+
+ sFile.release_buffer();
+
+ // This is the file name
+ // LIMITATION: Can't be changed
+ sFile += _T("\\Secure Shutdown Log.txt");
+
+ // Open the File
+ HANDLE hFile = NULL;
+ if((hFile = CreateFile(sFile, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL)) == INVALID_HANDLE_VALUE)
+ return HRESULT_FROM_WIN32(::GetLastError());
+
+ int nPos = -1;
+ DWORD dwWritten;
+
+ // Always use ANSI here
+ // LIMITATION: Only errors up to 1K in length
+ char* szText = new char[1024];
+
+ // Write Header
+ char* szTemp = "SECURE SHUTDOWN ERROR LOG\r\n\r\n";
+ WriteFile(hFile, szTemp, strlen(szTemp), &dwWritten, NULL);
+
+ LVITEMA lvi;
+ memset(&lvi, 0, sizeof(LVITEMA));
+
+ while((nPos = m_ctlErrors.GetNextItem(nPos, 0)) != -1)
+ {
+ // We need all this crazy code here to make sure
+ // We get ANSI text in UNICODE Builds.
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE;
+ lvi.iItem = nPos;
+ lvi.iSubItem = 0;
+ lvi.cchTextMax = 1024;
+ lvi.pszText = szText;
+ lvi.iImage = 0;
+
+ ::SendMessageA(m_ctlErrors, LVM_GETITEMA, 0, (LPARAM)&lvi);
+
+ // Only write errors (No Fixed)
+ if(lvi.iImage != IMAGE_OKAY)
+ {
+ // Write it to the file
+ WriteFile(hFile, szText, strlen(szText), &dwWritten, NULL);
+ WriteFile(hFile, "\r\n", 2, &dwWritten, NULL);
+ }
+ }
+
+ // Close the File
+ CloseHandle(hFile);
+
+ return S_OK;
+}
+
+bool CLogDlg::HasErrors()
+{
+ if(!IsWindow())
+ return false;
+
+ // If we're created then we've got errors
+ int nPos = -1;
+ LV_ITEM lv;
+ while((nPos = m_ctlErrors.GetNextItem(nPos, LVNI_ALL)) != -1)
+ {
+ lv.mask = LVIF_IMAGE;
+ lv.iItem = nPos;
+ lv.iSubItem = 0;
+ m_ctlErrors.GetItem(&lv);
+
+ if(lv.iImage == IMAGE_ERROR)
+ return true;
+ }
+
+ return false;
+}
+
+LRESULT CLogDlg::OnListRClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
+{
+ // First of all get the mouse incase we move (unlikely)
+ POINT ptMouse;
+ ::GetCursorPos(&ptMouse);
+
+ LVHITTESTINFO lvHit;
+ lvHit.pt = ptMouse;
+ lvHit.flags = LVHT_ONITEM;
+
+ m_ctlErrors.ScreenToClient(&lvHit.pt);
+ int nIndex = m_ctlErrors.HitTest(&lvHit);
+
+ // If we didn't click on an item then...
+ if(nIndex == -1)
+ {
+ // ...Deselect All
+ for(int nCnt = 0; nCnt < m_ctlErrors.GetItemCount(); nCnt ++)
+ // Set right state for item
+ ListView_SetItemState(m_ctlErrors, nCnt, 0, (UINT)-1);
+
+ return 0;
+ }
+
+ // Focus on Current Item
+ ListView_SetItemState(m_ctlErrors, nIndex, LVIS_SELECTED | LVIS_FOCUSED,
+ LVIS_STATEIMAGEMASK);
+
+ // Load the Menu
+ HMENU hMenu = ::LoadMenu(_Module.m_hInstResource, MAKEINTRESOURCE(IDR_ERROR_MENU));
+ if (!hMenu) return 0;
+
+ HMENU hSubMenu = GetSubMenu(hMenu, 0);
+ if (!hSubMenu)
+ {
+ DestroyMenu(hMenu);
+ return 0;
+ }
+
+ // Get a COM Pointer to the current Error
+ INightSecErrorFixPtr pFix = (INightSecError*)m_ctlErrors.GetItemData(nIndex);
+
+ if(pFix)
+ {
+ // Check if Fixable
+ BOOL bFixable = FALSE;
+ if(SUCCEEDED(pFix->get_Fixable(&bFixable)) && bFixable)
+ ::EnableMenuItem(hSubMenu, ID_ERROR_FIX, MF_BYCOMMAND | MF_ENABLED);
+
+ // Check if Retryable
+ BOOL bRetryable = FALSE;
+ if(SUCCEEDED(pFix->get_Retryable(&bRetryable)) && bRetryable)
+ ::EnableMenuItem(hSubMenu, ID_ERROR_RETRY, MF_BYCOMMAND | MF_ENABLED);
+ }
+
+ // Make the default (same as double-click) Retry
+ SetMenuDefaultItem(hSubMenu, ID_ERROR_RETRY, FALSE);
+
+ // Show the Menu
+ ::TrackPopupMenu(hSubMenu, 0, ptMouse.x, ptMouse.y, 0, m_hWnd, NULL);
+ ::PostMessage(m_hWnd, WM_USER, 0, 0);
+ return 0;
+}
+
+LRESULT CLogDlg::OnErrorFix(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // Fix all selected items
+ int nPos = -1;
+ while((nPos = m_ctlErrors.GetNextItem(nPos, LVIS_SELECTED)) != -1)
+ FixItem(nPos);
+
+ return 0;
+}
+
+LRESULT CLogDlg::OnErrorRetry(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // Retry all selected Items
+ int nPos = -1;
+ while((nPos = m_ctlErrors.GetNextItem(nPos, LVIS_SELECTED)) != -1)
+ RetryItem(nPos);
+
+ return 0;
+}
+
+LRESULT CLogDlg::OnErrorDelete(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // Delete all selected items
+ int nPos = -1;
+ while((nPos = m_ctlErrors.GetNextItem(nPos, LVIS_SELECTED)) != -1)
+ RemoveItem(nPos);
+
+ return 0;
+}
+
+HRESULT CLogDlg::FixItem(int nIndex)
+{
+ USES_CONVERSION;
+
+ // Extract COM Pointer from ListCtrl
+ INightSecErrorFixPtr pFix = (INightSecError*)m_ctlErrors.GetItemData(nIndex);
+
+ if(pFix == NULL)
+ return 0;
+
+ // Check if actually fixable
+ BOOL bFixable = FALSE;
+ if(FAILED(pFix->get_Fixable(&bFixable)) || !bFixable)
+ return 0;
+
+ // Fix it
+ HCURSOR hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
+
+ HRESULT hr = pFix->Fix();
+
+ ::SetCursor(hOldCursor);
+
+ INightSecErrorPtr pError = pFix;
+
+ if(pError == NULL)
+ return 0;
+
+ // Get New Error Messages
+ BSTR bsTemp;
+ pError->get_Description(&bsTemp);
+
+ // Clean up newlines
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\n', L' ');
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\r', L' ');
+
+ // Set Image and Text
+ LV_ITEM lv;
+ lv.mask = LVIF_IMAGE | LVIF_TEXT;
+ lv.iSubItem = 0;
+ lv.iItem = nIndex;
+ lv.pszText = OLE2T(bsTemp);
+ lv.iImage = SUCCEEDED(hr) ? 0 : 1;
+
+ // Set right image and text for item
+ m_ctlErrors.SetItem(&lv);
+
+ return hr;
+}
+
+HRESULT CLogDlg::RetryItem(int nIndex)
+{
+ USES_CONVERSION;
+
+ // Extract COM Pointer from List Ctrl
+ INightSecErrorFixPtr pFix = (INightSecError*)m_ctlErrors.GetItemData(nIndex);
+
+ if(pFix == NULL)
+ return 0;
+
+ // Check if we can actually Retry
+ BOOL bRetryable = FALSE;
+ if(FAILED(pFix->get_Retryable(&bRetryable)) || !bRetryable)
+ return 0;
+
+ // Retry it
+ HCURSOR hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
+
+ HRESULT hr = pFix->Retry();
+
+ ::SetCursor(hOldCursor);
+
+ INightSecErrorPtr pError = pFix;
+
+ if(pError == NULL)
+ return 0;
+
+ // Get new Error Messages
+ BSTR bsTemp;
+ pError->get_Description(&bsTemp);
+
+ // Clean up newlines
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\n', L' ');
+ replace(bsTemp, bsTemp + SysStringLen(bsTemp), L'\r', L' ');
+
+ // Set Image and Text
+ LV_ITEM lv;
+ lv.mask = LVIF_IMAGE | LVIF_TEXT;
+ lv.iSubItem = 0;
+ lv.iItem = nIndex;
+ lv.pszText = OLE2T(bsTemp);
+ lv.iImage = SUCCEEDED(hr) ? IMAGE_OKAY : IMAGE_ERROR;
+
+ // Set right image and text for item
+ m_ctlErrors.SetItem(&lv);
+
+ return hr;
+}
+
+bool CLogDlg::RemoveItem(int nIndex)
+{
+ // Release COM Ptr
+ INightSecError* pError = (INightSecError*)m_ctlErrors.GetItemData(nIndex);
+ if(pError) pError->Release();
+
+ // Remove it
+ return m_ctlErrors.DeleteItem(nIndex) ? true : false;
+}
+
+void CLogDlg::Init(HWND hWndParent)
+{
+ m_hWndParent = hWndParent;
+}