/********************************************************************
Created: 27/3/2004, 14:36
File name: D:\Projects\Exile\Exile\ExileDlg.cpp
File path: D:\Projects\Exile\Exile
File base: ExileDlg
File ext: cpp
Author: Gogolev Anton
*********************************************************************/
// ExileDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Exile.h"
#include "ExileDlg.h"
#include "menuflags.h"
#include "NewDialog.h"
#include "InsertCategoryDialog.h"
#include "InsertElementDialog.h"
#include "EnterPasswordDialog.h"
#include "PasswordGeneratorDialog.h"
#include "MD5HashGeneratorDialog.h"
#include "EditCategoryDialog.h"
#include "EditElementDialog.h"
#include "StoragePropertiesDialog.h"
#include "OptionsDialog.h"
#include <WindowsX.h>
#include <shlwapi.h>
#include "security.h"
#include "registry.h"
#include "messagebox.h"
#include "hotkey.h"
#include "instance.h"
#include "sort.h"
#include "ExportToXmlDialog.h"
#include "AdvancedDialog.h"
#include "xmlexportflags.h"
#include "OpenFileDialog.h"
#include "modulepath.h"
#include "shellfolder.h"
#include "../mdx/mdx.h"
#include "../Icons/Icons.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_TRAYCALLBACK (WM_USER + 100)
UINT CExileDlg::m_suMessage = RegisterWindowMessage(BROADCASTMESSAGE);
const UINT_PTR g_uTimerID = 1;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CExileDlg dialog
CExileDlg::CExileDlg(CWnd* pParent /*=NULL*/)
: CDialog(CExileDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CExileDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pimgList = 0;
m_pimgListSmall = 0;
// Set up Title font
NONCLIENTMETRICS ncm = {0};
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
LOGFONT lfTitle = ncm.lfMessageFont;
lfTitle.lfWeight = FW_BOLD;
lstrcpy(lfTitle.lfFaceName, _T("Verdana Bold"));
HDC hDC = ::GetDC(NULL); // Gets the screen DC
int FontSize = 12;
lfTitle.lfHeight = 0 - GetDeviceCaps(hDC, LOGPIXELSY) * FontSize / 72;
m_hFont = CreateFontIndirect(&lfTitle);
::ReleaseDC(NULL, hDC);
//
// Default Settings
//
m_nExportFlags = 0;
m_strExportFileName.Empty();
m_nHashOptions = 0;
m_nPasswordLength = 0;
m_bUppercase = m_bSpecial = m_bPunctuation = m_bLowercase = m_bDecimalDigits = FALSE;
m_bShowPassword = FALSE;
m_bMinimizeToTray = TRUE;
m_bHotKeys = TRUE;
m_bReloadLastStorage = TRUE;
m_bAutosave = FALSE;
m_bAutosort = FALSE;
m_nSortOrder = 1;
m_bSmartType = FALSE;
m_wKeyCode = 0;
m_wModifiers = 0;
m_bBackup = FALSE;
m_bMaintain = TRUE;
m_bReloadReadonly = FALSE;
m_bShellOpenReadonly = FALSE;
m_strLastStorage.Empty();
m_bClipboardErasing = FALSE;
m_nErasingTimeout = 0;
}
void CExileDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CExileDlg)
DDX_Control(pDX, IDC_RATINGICON, m_ctrlRatingIcon);
DDX_Control(pDX, IDC_TREE, m_ctrlTree);
DDX_Control(pDX, IDC_ADDRESS, m_ctrlAddress);
DDX_Control(pDX, IDC_PASSWORD, m_ctrlPassword);
DDX_Control(pDX, IDC_NOTES, m_ctrlNotes);
DDX_Control(pDX, IDC_LOGIN, m_ctrlLogin);
DDX_Control(pDX, IDC_ITEMICON, m_ctrlItemIcon);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CExileDlg, CDialog)
//{{AFX_MSG_MAP(CExileDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
ON_COMMAND(ID_FILE_SAVEAS, OnFileSaveas)
ON_WM_DESTROY()
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelchangedTree)
ON_COMMAND(ID_EDIT_INSERTCATEGORY, OnEditInsertcategory)
ON_COMMAND(ID_EDIT_INSERTELEMENT, OnEditInsertelement)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_WM_CLOSE()
ON_COMMAND(ID_TOOLS_MD5HASHGENERATOR, OnToolsMd5hashgenerator)
ON_COMMAND(ID_TOOLS_PASSWORDGENERATOR, OnToolsPasswordgenerator)
ON_BN_CLICKED(IDC_PASSWORD_TITLE, OnPasswordTitle)
ON_COMMAND(ID_EDIT_DELETE, OnEditDelete)
ON_COMMAND(ID_EDIT_EDIT, OnEditEdit)
ON_COMMAND(ID_EDIT_STORAGEPROPERTIES, OnEditStorageproperties)
ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRclickTree)
ON_COMMAND(ID_TRAYMENU_RESTORE, OnTraymenuRestore)
ON_COMMAND(ID_TRAYMENU_ENABLEHOTKEYS, OnTraymenuEnablehotkeys)
ON_COMMAND(ID_EDIT_OPTIONS, OnEditOptions)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_NAMEASCENDING, OnCategorycontextSortNameascending)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_NAMEDESCENDING, OnCategorycontextSortNamedescending)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_USERNAMEASCENDING, OnCategorycontextSortUsernameascending)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_USERNAMEDESCENDING, OnCategorycontextSortUsernamedescending)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_RATINGASCENDING, OnCategorycontextSortRatingascending)
ON_COMMAND(ID_CATEGORYCONTEXT_SORT_RATINGDESCENDING, OnCategorycontextSortRatingdescending)
ON_COMMAND(ID_FILE_EXPORT_EXPORTTOXML, OnFileExportExporttoxml)
ON_COMMAND(ID_EDIT_ADVANCED, OnEditAdvanced)
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(m_suMessage, OnActivateApp)
ON_MESSAGE(TCEX_ITEMDRAGGED, OnTcexItemdragged)
ON_MESSAGE(SHLE_RBUTTONDOWN, OnShleRButtondown)
ON_COMMAND(ID_COPY, OnCopy)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CExileDlg message handlers
BOOL CExileDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
::MdxInitialize();
m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
//
// Loading settings
//
LoadSettings();
// SmartType
if(m_bSmartType)
{
::RegisterHotKey(*this, 0, MapModifiers(m_wModifiers), m_wKeyCode);
} // if
if(m_bMaintain)
MaintainFileAssociations();
// Icons
m_pimgList = new CImageList();
m_pimgList->Create(32, 32, ILC_COLOR8 | ILC_MASK, 15, 5);
// Small ones
m_pimgListSmall = new CImageList();
m_pimgListSmall->Create(16, 16, ILC_COLOR8 | ILC_MASK, 15, 5);
HINSTANCE hIcons = (HINSTANCE)::GetModuleHandle(_T("icons.dll"));
for(UINT uIcon = IconsGetIconIndex(); uIcon < IconsGetIconIndex() + IconsGetIconCount(); ++uIcon)
{
m_pimgList->Add(::LoadIcon(hIcons, MAKEINTRESOURCE(uIcon)));
m_pimgListSmall->Add(::LoadIcon(hIcons, MAKEINTRESOURCE(uIcon)));
} // for
// Rating icons
m_pimgRating = new CImageList();
m_pimgRating->Create(16, 16, ILC_COLOR8 | ILC_MASK, 11, 1);
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_COLD),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BELOWINSIGNIFICANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_INSIGNIFICANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_UNIMPORTANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BELOWNORMAL),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_NORMAL),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_IMPORTANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ABOVEIMPORTANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_VERYIMPORTANT),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BELOWCRITICAL),
IMAGE_ICON, 16, 16, 0));
m_pimgRating->Add((HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_CRITICAL),
IMAGE_ICON, 16, 16, 0));
// Setting up title font
GetDlgItem(IDC_TITLE_TITLE)->ModifyStyle(0, SS_ENDELLIPSIS, 0); // If title doesn't fit
SetWindowFont(GetDlgItem(IDC_TITLE_TITLE)->GetSafeHwnd(), m_hFont, TRUE);
// Grouping controls
m_gcControls.AddControl(TITLE, GetDlgItem(IDC_TITLE_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(CATEGORY, GetDlgItem(IDC_TITLE_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(CATEGORY, GetDlgItem(IDC_DESCRIPTION_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_LOGIN_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_PASSWORD_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_LOGIN)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_PASSWORD)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_ADDRESS_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_NOTES_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_ADDRESS)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_NOTES)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_MODESWITCH)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_INFO_TITLE)->GetSafeHwnd());
m_gcControls.AddControl(ELEMENT_INDETAIL, GetDlgItem(IDC_RATINGICON)->GetSafeHwnd());
// Cosmetic stuff
m_ctrlTree.SetImageList(m_pimgListSmall, TVSIL_NORMAL);
m_ctrlDescription.SubclassDlgItem(IDC_DESCRIPTION_TITLE, this);
m_ctrlPasswordLink.SubclassDlgItem(IDC_PASSWORD_TITLE, this);
m_ctrlPasswordLink.SetTextColor(RGB(0, 0, 192));
m_ctrlKeyInfo.SubclassDlgItem(IDC_KEYINFO_TITLE, this);
m_ctrlInfo.SubclassDlgItem(IDC_INFO_TITLE, this);
AddTrayIcon(IDR_MAINFRAME);
CBitmap bmSwitch;
bmSwitch.LoadBitmap(IDB_SWITCH);
m_pimgSwitch = new CImageList();
m_pimgSwitch->Create(186, 21, ILC_COLOR16 | ILC_MASK, 4, 1);
m_pimgSwitch->Add(&bmSwitch, RGB(255, 0, 255));
// By default
m_gcControls.SwitchControls(TITLE, CGroupedControls::SWS_SHOW, CGroupedControls::SWS_HIDE);
SwitchMenu(MF_EDIT_ALL | MF_FILE_SAVE | MF_FILE_SAVEAS | MF_FILE_CLOSE | MF_FILE_EXPORT_XML, FALSE);
m_bDirty = FALSE;
m_kiKeyInfo.nKeySize = 0;
m_kiKeyInfo.pbKey = 0;
m_hRc5 = 0;
m_nSelection = EF_CATEGORY;
CCommandLineInfo &rcmdInfo = ((CExileApp *)AfxGetApp())->GetCommandLineInfo();
//
// Command line
//
if(!rcmdInfo.m_strFileName.IsEmpty())
{
m_strStorageName = rcmdInfo.m_strFileName;
m_bReadOnly = m_bShellOpenReadonly;
LoadStorage(FALSE);
} // if
else
{
if(m_bReloadLastStorage)
{
m_bReadOnly = m_bReloadReadonly;
m_strStorageName = m_strLastStorage;
if(!m_strStorageName.IsEmpty())
LoadStorage(FALSE);
} // if
} // else
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CExileDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CExileDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CExileDlg::SwitchMenu(long lItems, BOOL bSwitchOn)
{
CMenu *pMenu = AfxGetApp()->GetMainWnd()->GetMenu();
// File
if(lItems & MF_FILE_NEW)
pMenu->EnableMenuItem(ID_FILE_NEW, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_FILE_OPEN)
pMenu->EnableMenuItem(ID_FILE_OPEN, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_FILE_CLOSE)
pMenu->EnableMenuItem(ID_FILE_CLOSE, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_FILE_SAVE)
pMenu->EnableMenuItem(ID_FILE_SAVE, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_FILE_SAVEAS)
pMenu->EnableMenuItem(ID_FILE_SAVEAS, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_FILE_EXPORT_XML)
pMenu->EnableMenuItem(ID_FILE_EXPORT_EXPORTTOXML, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
// Edit
if(lItems & MF_EDIT_INSERTCATEGORY)
pMenu->EnableMenuItem(ID_EDIT_INSERTCATEGORY, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_EDIT_INSERTELEMENT)
pMenu->EnableMenuItem(ID_EDIT_INSERTELEMENT, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_EDIT_EDIT)
pMenu->EnableMenuItem(ID_EDIT_EDIT, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_EDIT_DELETE)
pMenu->EnableMenuItem(ID_EDIT_DELETE, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_EDIT_STORAGEPROPERTIES)
pMenu->EnableMenuItem(ID_EDIT_STORAGEPROPERTIES, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
if(lItems & MF_EDIT_ADVANCED)
pMenu->EnableMenuItem(ID_EDIT_ADVANCED, MF_BYCOMMAND | (bSwitchOn ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
}
void CExileDlg::OnFileNew()
{
CreateStorage();
}
void CExileDlg::OnFileOpen()
{
LoadStorage(TRUE);
}
void CExileDlg::OnFileClose()
{
CloseStorage();
}
void CExileDlg::OnFileSave()
{
SaveStorage(FALSE);
}
void CExileDlg::OnFileSaveas()
{
SaveStorage(TRUE);
}
void CExileDlg::CreateStorage()
{
CNewDialog dlgNew;
ProcessDirtyStorage();
//
// Settings
//
dlgNew.m_bDecimalDigits = m_bDecimalDigits;
dlgNew.m_bLowercase = m_bLowercase;
dlgNew.m_bPunctuation = m_bPunctuation;
dlgNew.m_bSpecial = m_bSpecial;
dlgNew.m_bUppercase = m_bUppercase;
dlgNew.m_nPasswordLength = m_nPasswordLength;
if(IDOK == dlgNew.DoModal())
{
BeginWaitCursor();
CloseStorage();
m_lIndex = 0;
m_strStorageName.Empty();
GeneratePrivateKey(dlgNew.m_strUserName, dlgNew.m_strMasterPassword, dlgNew.m_nKeySize, m_kiKeyInfo);
m_kiKeyInfo.nRounds = dlgNew.m_nRounds;
// Acquiring new crypting context and setting a new key
if(::Rc5ValidContext(m_hRc5))
::Rc5ReleaseContext(m_hRc5);
if(!::Rc5AcquireContext(m_hRc5, m_kiKeyInfo.nKeySize / 8, m_kiKeyInfo.nRounds))
{
MessageBoxEx(*this, IDS_RC5ACQUIRECONTEXTFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
if(!::Rc5SetBinaryPrivateKey(m_hRc5, m_kiKeyInfo.pbKey))
{
MessageBoxEx(*this, IDS_RC5SETBINARYPRIVATEKEYFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
// So now we can delete key buffer in order not
// to expose it anymore
FreeBuffer(m_kiKeyInfo.pbKey, m_kiKeyInfo.nKeySize / 8);
//////////////////////////////////////////////////////////////////////////
// Now adding to tree and to map
m_ctrlTree.DeleteAllItems();
TV_INSERTSTRUCT tvi;
tvi.hParent = 0; // Root item
tvi.hInsertAfter = TVI_ROOT;
tvi.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.item.cchTextMax = dlgNew.m_strUserName.GetLength() + 1;
tvi.item.pszText = dlgNew.m_strUserName.LockBuffer();
tvi.item.lParam = SetDropTarget(m_lIndex);
tvi.item.iImage = 11; // Keys
tvi.item.iSelectedImage = 11;
m_ctrlTree.InsertItem(&tvi);
// Adding to map
ENTRY eItem;
CString strDescription;
strDescription.LoadString(IDS_ROOTDESCRIPTION);
eItem.nFlags = EF_CATEGORY | EF_ROOTCATEGORY;
eItem.lID = m_lIndex;
eItem.lIconID = 11;
eItem.lReserved = 0;
memset(&(eItem.pePrivate.abReserved), 0, sizeof(eItem.pePrivate.abReserved));
#ifdef _UNICODE
wcscpy(eItem.pePrivate.szName, dlgNew.m_strUserName.LockBuffer());
wcscpy(eItem.pePrivate.szNotes, strDescription.LockBuffer());
wcscpy(eItem.pePrivate.szAddress, _T(""));
wcscpy(eItem.pePrivate.szLogin, _T(""));
wcscpy(eItem.pePrivate.szPassword, _T(""));
#else
strcpy(eItem.pePrivate.szName, dlgNew.m_strUserName.LockBuffer());
strcpy(eItem.pePrivate.szNotes, strDescription.LockBuffer());
strcpy(eItem.pePrivate.szAddress, _T(""));
strcpy(eItem.pePrivate.szLogin, _T(""));
strcpy(eItem.pePrivate.szPassword, _T(""));
#endif // _UNICODE
// Yep!
EncryptPrivateEntry(eItem.pePrivate, m_hRc5);
m_mEntries[m_lIndex++] = eItem;
dlgNew.m_strUserName.UnlockBuffer();
CleanString(dlgNew.m_strMasterPassword);
CleanString(dlgNew.m_strUserName);
SwitchMenu(MF_FILE_ALL, TRUE);
SetKeyInfo(m_kiKeyInfo.nKeySize);
ProcessSortOrder();
SetDirty(TRUE);
EndWaitCursor();
//
// Settings
//
m_bDecimalDigits = dlgNew.m_bDecimalDigits;
m_bLowercase = dlgNew.m_bLowercase;
m_bPunctuation = dlgNew.m_bPunctuation;
m_bSpecial = dlgNew.m_bSpecial;
m_bUppercase = dlgNew.m_bUppercase;
m_nPasswordLength = dlgNew.m_nPasswordLength;
} // if
}
void CExileDlg::ProcessDirtyStorage()
{
if(m_bDirty)
{
CString strTitle, strText;
strTitle.LoadString(IDS_TITLE);
strText.Format(IDS_SAVEDIRTYSTORAGE, m_strStorageName.IsEmpty() ? "<Untitled Storage>" : m_strStorageName);
if(IDYES == ::MessageBox(*this, strText, strTitle, MB_YESNO | MB_ICONQUESTION))
SaveStorage(m_bReadOnly);
} // if
}
void CExileDlg::CloseStorage()
{
if(m_mEntries.empty())
return;
BeginWaitCursor();
// Unregistering hot keys and clearing entries contents
UnregisterHotKeys();
MENTRY::iterator emi = m_mEntries.begin();
while(m_mEntries.end() != emi)
{
CleanBuffer(&(emi->second), sizeof(ENTRY));
++emi;
} // while
m_strLastStorage = m_strStorageName;
m_strStorageName.Empty();
m_ctrlTree.DeleteAllItems();
m_mEntries.clear();
SwitchMenu(MF_EDIT_ALL, FALSE);
SwitchMenu(MF_FILE_SAVE | MF_FILE_CLOSE | MF_FILE_SAVEAS | MF_FILE_EXPORT_XML, FALSE);
m_gcControls.SwitchControls(TITLE, CGroupedControls::SWS_SHOW, CGroupedControls::SWS_HIDE);
SetTitle();
SetKeyInfo(0);
SetDirty(FALSE);
CString strTitle;
strTitle.LoadString(IDS_TITLE);
m_ctrlItemIcon.SetIcon(m_hIcon);
SetTitle(strTitle.LockBuffer());
EndWaitCursor();
}
void CExileDlg::SaveStorage(BOOL bSaveAs)
{
// If no name has been specified
if((m_strStorageName.IsEmpty()) || bSaveAs)
{
CString strFilter, strExt;
strFilter.LoadString(IDS_FILTER);
strExt.LoadString(IDS_EXTENSION);
CFileDialog dlgSave(FALSE, strExt, 0, OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_OVERWRITEPROMPT,
strFilter, this);
if(IDCANCEL == dlgSave.DoModal())
return;
if((m_bReadOnly) && (dlgSave.GetPathName() == m_strStorageName))
{
MessageBoxEx(*this, IDS_CANTSAVETOREADONLY, IDS_TITLE);
return;
} // if
m_strStorageName = dlgSave.GetPathName();
} // if
CString strExt = m_strStorageName.Right(3); // Extension
strExt.MakeUpper();
if(_T("XML") == strExt)
{
SaveStorageXml();
} // if
else
{
SaveStorageSerial();
} // else
SetTitle();
}
void CExileDlg::LoadStorage(BOOL bShowDialog)
{
if(bShowDialog)
{
CString strFilter, strExt;
strFilter.LoadString(IDS_FILTER);
strExt.LoadString(IDS_EXTENSION);
CFileDialog dlgOpen(TRUE, strExt, 0, OFN_NONETWORKBUTTON, strFilter, this);
// COpenFileDialog dlgOpen(TRUE, strExt, 0, OFN_HIDEREADONLY | OFN_NONETWORKBUTTON, strFilter, this);
if(IDCANCEL == dlgOpen.DoModal())
return;
ProcessDirtyStorage();
CloseStorage();
m_strStorageName = dlgOpen.GetPathName();
m_bReadOnly = dlgOpen.m_ofn.Flags & OFN_READONLY;
// m_bReadOnly = dlgOpen.m_bReadOnly;
} // if
CString strExt = m_strStorageName.Right(3);
strExt.MakeUpper();
if(_T("XML") == strExt)
{
LoadStorageXml();
} // if
else
{
LoadStorageSerial();
} // else
}
void CExileDlg::CleanPrivateData()
{
if(m_kiKeyInfo.nKeySize)
{
FreeBuffer(m_kiKeyInfo.pbKey, m_kiKeyInfo.nKeySize / 8);
m_kiKeyInfo.nKeySize = 0;
} // if
}
void CExileDlg::OnDestroy()
{
// Saving settings
BeginWaitCursor();
SaveSettings();
if(m_bMaintain)
MaintainFileAssociations();
//
// Uninitializing
//
RemoveTrayIcon(IDR_MAINFRAME);
// SmartType
if(m_bSmartType)
{
::UnregisterHotKey(*this, 0);
} // if
EndWaitCursor();
CDialog::OnDestroy();
DestroyAcceleratorTable(m_hAccel);
// Image lists
m_pimgList->DeleteImageList();
delete m_pimgList;
m_pimgListSmall->DeleteImageList();
delete m_pimgListSmall;
m_pimgSwitch->DeleteImageList();
delete m_pimgSwitch;
m_pimgRating->DeleteImageList();
delete m_pimgRating;
::MdxUninitialize();
}
void CExileDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
ShowEntry(pNMTreeView->itemNew.hItem);
*pResult = 0; // Ignored
}
void CExileDlg::ShowEntry(HTREEITEM hItem)
{
// Find an item
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
// Look up in a map
MENTRY::iterator ei = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != ei)
{
// Now determine its type
if(ei->second.nFlags & EF_CATEGORY)
{
// Controls
m_gcControls.HideControls(ELEMENT_INDETAIL);
m_gcControls.DisableControls(ELEMENT_INDETAIL);
m_gcControls.ShowControls(CATEGORY);
SwitchMenu(MF_EDIT_ALL & (~MF_EDIT_ADVANCED), TRUE);
if(0 == ei->second.lID)
SwitchMenu(MF_EDIT_DELETE, FALSE); // Can't delete Root item
DecryptPrivateEntry(ei->second.pePrivate, m_hRc5);
// Show information
SetTitle(ei->second.pePrivate.szName);
SetDescription(ei->second.pePrivate.szNotes);
// Icons
m_ctrlItemIcon.SetIcon(m_pimgList->ExtractIcon(ei->second.lIconID));
m_ctrlRatingIcon.SetIcon(m_pimgRating->ExtractIcon(ei->second.pePrivate.exData.cRating));
EncryptPrivateEntry(ei->second.pePrivate, m_hRc5);
m_nSelection = EF_CATEGORY;
} // if
else if(ei->second.nFlags & EF_ELEMENT)
{
// Controls
m_gcControls.HideControls(CATEGORY);
m_gcControls.ShowControls(TITLE);
m_gcControls.EnableControls(ELEMENT_INDETAIL);
m_gcControls.ShowControls(ELEMENT_INDETAIL);
SwitchMenu(MF_EDIT_ALL, FALSE);
SwitchMenu(MF_EDIT_EDIT | MF_EDIT_DELETE | MF_EDIT_STORAGEPROPERTIES | MF_EDIT_ADVANCED, TRUE);
DecryptPrivateEntry(ei->second.pePrivate, m_hRc5);
// Show information
SetTitle(ei->second.pePrivate.szName);
SetLogin(ei->second.pePrivate.szLogin);
SetPassword(ei->second.pePrivate.szPassword);
SetAddress(ei->second.pePrivate.szAddress);
SetNotes(ei->second.pePrivate.szNotes);
CString strInfo;
if((ei->second.pePrivate.exData.wModifiers) && (ei->second.pePrivate.exData.wVKCode))
{
if(m_bHotKeys)
{
strInfo.Format(IDS_HOTKEYINFO, GetModifiersString(MapModifiers(ei->second.pePrivate.exData.wModifiers)),
(TCHAR)ei->second.pePrivate.exData.wVKCode);
} // if
else
{
strInfo.Format(IDS_INACTIVEHOTKEYINFO, GetModifiersString(MapModifiers(ei->second.pePrivate.exData.wModifiers)),
(TCHAR)ei->second.pePrivate.exData.wVKCode);
} // else
} // if
else
{
strInfo.LoadString(IDS_NOHOTKEYINFO);
} // else
SetInfo(strInfo.LockBuffer());
// Icons
m_ctrlItemIcon.SetIcon(m_pimgList->ExtractIcon(ei->second.lIconID));
m_ctrlRatingIcon.SetIcon(m_pimgRating->ExtractIcon(ei->second.pePrivate.exData.cRating));
m_nSelection = EF_ELEMENT;
EncryptPrivateEntry(ei->second.pePrivate, m_hRc5);
} // if
} // if
} // if
else
{
// Controls, etc.
m_gcControls.HideControls(ELEMENT_INDETAIL);
m_gcControls.HideControls(CATEGORY);
m_gcControls.ShowControls(TITLE);
// Menu
SwitchMenu(MF_EDIT_ALL, FALSE);
CString strTitle;
strTitle.LoadString(IDS_TITLE);
SetTitle(strTitle.LockBuffer());
m_ctrlItemIcon.SetIcon(m_hIcon);
} // else
}
void CExileDlg::SetDescription(TCHAR *pszDescription)
{
SetDlgItemText(IDC_DESCRIPTION_TITLE, pszDescription);
}
void CExileDlg::EncryptPrivateEntry(PRIVATEENTRY &rpePrivate, HRC5CONTEXT hRc5)
{
// Both ANSI and Unicode
::Rc5EncryptBlock(hRc5, (RC5_WORD *)&rpePrivate, (RC5_WORD *)&rpePrivate, sizeof(PRIVATEENTRY) / 8);
}
void CExileDlg::DecryptPrivateEntry(PRIVATEENTRY &rpePrivate, HRC5CONTEXT hRc5)
{
// Both ANSI and Unicode
::Rc5DecryptBlock(hRc5, (RC5_WORD *)&rpePrivate, (RC5_WORD *)&rpePrivate, sizeof(PRIVATEENTRY) / 8);
}
void CExileDlg::InsertCategory()
{
// Have to be sure that user has selected Category
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.hItem = m_ctrlTree.GetSelectedItem();
if(!m_ctrlTree.GetItem(&tvi))
return;
// Look up in a map
MENTRY::iterator ei = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() == ei)
return;
// Now determine its type
if(!(ei->second.nFlags & EF_CATEGORY))
return;
CInsertCategoryDialog dlgIns;
dlgIns.SetImageList(m_pimgList);
if(IDOK == dlgIns.DoModal())
{
BeginWaitCursor();
TV_INSERTSTRUCT tvi;
HTREEITEM hRoot;
tvi.hParent = hRoot = m_ctrlTree.GetSelectedItem();
tvi.hInsertAfter = TVI_LAST;
tvi.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.item.cchTextMax = dlgIns.m_strCategoryName.GetLength() + 1;
tvi.item.pszText = dlgIns.m_strCategoryName.LockBuffer();
tvi.item.lParam = SetDropTarget(m_lIndex);
tvi.item.iImage = dlgIns.GetIconID();
tvi.item.iSelectedImage = dlgIns.GetIconID();
m_ctrlTree.InsertItem(&tvi);
// Adding to map
ENTRY eItem;
eItem.nFlags = EF_CATEGORY;
eItem.lID = m_lIndex;
eItem.lIconID = dlgIns.GetIconID();
eItem.lReserved = 0;
memset(&(eItem.pePrivate.abReserved), 0, sizeof(eItem.pePrivate.abReserved));
#ifdef _UNICODE
wcscpy(eItem.pePrivate.szName, dlgIns.m_strCategoryName.LockBuffer());
wcscpy(eItem.pePrivate.szNotes, dlgIns.m_strDescription.LockBuffer());
wcscpy(eItem.pePrivate.szAddress, _T(""));
wcscpy(eItem.pePrivate.szLogin, _T(""));
wcscpy(eItem.pePrivate.szPassword, _T(""));
#else
strcpy(eItem.pePrivate.szName, dlgIns.m_strCategoryName.LockBuffer());
strcpy(eItem.pePrivate.szNotes, dlgIns.m_strDescription.LockBuffer());
strcpy(eItem.pePrivate.szAddress, _T(""));
strcpy(eItem.pePrivate.szLogin, _T(""));
strcpy(eItem.pePrivate.szPassword, _T(""));
#endif // _UNICODE
// Yep!
EncryptPrivateEntry(eItem.pePrivate, m_hRc5);
m_mEntries[m_lIndex++] = eItem;
CleanString(dlgIns.m_strCategoryName);
CleanString(dlgIns.m_strDescription);
SetDirty(TRUE);
SortItems(hRoot);
EndWaitCursor();
} // if
}
void CExileDlg::OnEditInsertcategory()
{
InsertCategory();
}
void CExileDlg::InsertElement()
{
// Have to be sure that user has selected Category
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.hItem = m_ctrlTree.GetSelectedItem();
if(!m_ctrlTree.GetItem(&tvi))
return;
// Look up in a map
MENTRY::iterator ei = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() == ei)
return;
// Now determine its type
if(!(ei->second.nFlags & EF_CATEGORY))
return;
CInsertElementDialog dlgIns;
dlgIns.SetImageList(m_pimgList);
//
// Settings
//
dlgIns.m_bDecimalDigits = m_bDecimalDigits;
dlgIns.m_bLowercase = m_bLowercase;
dlgIns.m_bPunctuation = m_bPunctuation;
dlgIns.m_bSpecial = m_bSpecial;
dlgIns.m_bUppercase = m_bUppercase;
dlgIns.m_nPasswordLength = m_nPasswordLength;
if(IDOK == dlgIns.DoModal())
{
BeginWaitCursor();
TV_INSERTSTRUCT tvi;
HTREEITEM hRoot;
tvi.hParent = hRoot = m_ctrlTree.GetSelectedItem();
tvi.hInsertAfter = TVI_LAST;
tvi.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.item.cchTextMax = dlgIns.m_strElementName.GetLength() + 1;
tvi.item.pszText = dlgIns.m_strElementName.LockBuffer();
tvi.item.lParam = m_lIndex; // Element is not a drop target obviously
tvi.item.iImage = dlgIns.GetIconID();
tvi.item.iSelectedImage = dlgIns.GetIconID();
m_ctrlTree.InsertItem(&tvi);
// Adding to map
ENTRY eItem;
eItem.nFlags = EF_ELEMENT;
eItem.lID = m_lIndex;
eItem.lIconID = dlgIns.GetIconID();
eItem.lReserved = 0;
// Hot key
eItem.pePrivate.exData.wVKCode = dlgIns.m_wVKCode;
eItem.pePrivate.exData.wModifiers = dlgIns.m_wModifiers;
if((eItem.pePrivate.exData.wVKCode) && (eItem.pePrivate.exData.wModifiers) && m_bHotKeys)
{
// m_lIndex is guaranteed to be uinque within a particular session
::RegisterHotKey(GetSafeHwnd(), (int)m_lIndex, MapModifiers(eItem.pePrivate.exData.wModifiers),
eItem.pePrivate.exData.wVKCode);
} // if
#ifdef _UNICODE
wcscpy(eItem.pePrivate.szName, dlgIns.m_strElementName.LockBuffer());
wcscpy(eItem.pePrivate.szNotes, dlgIns.m_strNotes.LockBuffer());
wcscpy(eItem.pePrivate.szAddress, dlgIns.m_strAddress.LockBuffer());
wcscpy(eItem.pePrivate.szLogin, dlgIns.m_strLogin.LockBuffer());
wcscpy(eItem.pePrivate.szPassword, dlgIns.m_strPassword.LockBuffer());
#else
strcpy(eItem.pePrivate.szName, dlgIns.m_strElementName.LockBuffer());
strcpy(eItem.pePrivate.szNotes, dlgIns.m_strNotes.LockBuffer());
strcpy(eItem.pePrivate.szAddress, dlgIns.m_strAddress.LockBuffer());
strcpy(eItem.pePrivate.szLogin, dlgIns.m_strLogin.LockBuffer());
strcpy(eItem.pePrivate.szPassword, dlgIns.m_strPassword.LockBuffer());
#endif // _UNICODE
// Yep!
EncryptPrivateEntry(eItem.pePrivate, m_hRc5);
m_mEntries[m_lIndex++] = eItem;
CleanString(dlgIns.m_strElementName);
CleanString(dlgIns.m_strLogin);
CleanString(dlgIns.m_strPassword);
CleanString(dlgIns.m_strAddress);
CleanString(dlgIns.m_strNotes);
SetDirty(TRUE);
SortItems(hRoot);
EndWaitCursor();
//
// Settings
//
m_bDecimalDigits = dlgIns.m_bDecimalDigits;
m_bLowercase = dlgIns.m_bLowercase;
m_bPunctuation = dlgIns.m_bPunctuation;
m_bSpecial = dlgIns.m_bSpecial;
m_bUppercase = dlgIns.m_bUppercase;
m_nPasswordLength = dlgIns.m_nPasswordLength;
} // if
}
void CExileDlg::OnEditInsertelement()
{
InsertElement();
}
void CExileDlg::SetTitle()
{
CString strTitle;
strTitle.LoadString(IDS_TITLE);
if(!m_strStorageName.IsEmpty())
{
TCHAR szPath[MAX_PATH], szResult[MAX_PATH];
#ifdef _UNICODE
wcscpy(szPath, m_strStorageName.LockBuffer());
#else
strcpy(szPath, m_strStorageName.LockBuffer());
#endif // _UNICODE
m_strStorageName.UnlockBuffer();
PathCompactPathEx(szResult, szPath, 46, 0);
strTitle += _T(" - ") + CString(szResult);
if(m_bDirty)
strTitle += _T(" *");
if(m_bReadOnly)
strTitle += _T(" - Read Only");
} // else
AfxGetMainWnd()->SetWindowText(strTitle);
}
void CExileDlg::SetTitle(TCHAR *pszTitle)
{
CDC *pDC = GetDlgItem(IDC_TITLE_TITLE)->GetDC();
if(pDC)
{
} // if
ReleaseDC(pDC);
SetDlgItemText(IDC_TITLE_TITLE, pszTitle);
}
void CExileDlg::SaveTree(VTREE &rvTree, HTREEITEM hRoot)
{
TV_ITEM tvi;
HTREEITEM hItem = hRoot;
do
{
// Save current item
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
rvTree.push_back(GetItemParam(tvi.lParam)); // Raw value
// If this item has chilren, save them too
if(m_ctrlTree.ItemHasChildren(hItem))
{
// Insert proper tokens
rvTree.push_back(TST_LEFTBRACKET);
SaveTree(rvTree, m_ctrlTree.GetChildItem(hItem));
rvTree.push_back(TST_RIGHTBRACKET);
} // if
} // if
// Proceed with siblings
hItem = m_ctrlTree.GetNextSiblingItem(hItem);
}
while(0 != hItem);
}
void CExileDlg::OnAppAbout()
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
void CExileDlg::LoadTree(VTREE &rvTree, HTREEITEM hRoot)
{
if(rvTree.empty())
return;
// Starting from the beginning of the vector
VTREE::iterator ti = rvTree.begin();
MENTRY::iterator emi;
HTREEITEM hItem = hRoot;
do
{
// If item we found is a token
if(TST_LEFTBRACKET == *ti)
{
ti = rvTree.erase(ti);
LoadTree(rvTree, hItem);
} // if
else if(TST_RIGHTBRACKET == *ti)
{
ti = rvTree.erase(ti);
return;
} // else if
else if(m_mEntries.end() != (emi = m_mEntries.find(*ti))) // Otherwise
{
// We have to decrypt an entry, add an item to the tree and encrypt the item again
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// Adding
TV_INSERTSTRUCT tvIns;
tvIns.hParent = hRoot;
tvIns.hInsertAfter = 0;
tvIns.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE;
tvIns.item.hItem = 0;
tvIns.item.state = 0;
tvIns.item.cchTextMax = nNameLength;
tvIns.item.pszText = emi->second.pePrivate.szName;
tvIns.item.lParam = (emi->second.nFlags & EF_CATEGORY ? SetDropTarget(emi->second.lID) : emi->second.lID);
tvIns.item.iImage = emi->second.lIconID;
tvIns.item.iSelectedImage = emi->second.lIconID;
hItem = m_ctrlTree.InsertItem(&tvIns);
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
if(!rvTree.empty())
ti = rvTree.erase(ti);
} // else if
}
while(!rvTree.empty());
}
void CExileDlg::SetLogin(TCHAR *pszLogin)
{
SetDlgItemText(IDC_LOGIN, pszLogin);
}
void CExileDlg::SetPassword(TCHAR *pszPassword)
{
if(m_bShowPassword)
SetDlgItemText(IDC_PASSWORD, pszPassword);
else
SetDlgItemText(IDC_PASSWORD, _T("**********")); // Not using SetPasswordChar() or whatever...
}
void CExileDlg::CompactString(CDC *pDC, TCHAR *pszString, int nWidth)
{
#ifdef _UNICODE
#else
#endif // _UNICODE
}
void CExileDlg::OnClose()
{
if(m_bAutosave && (!m_mEntries.empty()) && m_bDirty)
{
SaveStorage(FALSE);
} // if
else
ProcessDirtyStorage();
CloseStorage();
CDialog::OnClose();
}
void CExileDlg::OnToolsMd5hashgenerator()
{
CMD5HashGeneratorDialog dlgMdx;
//
// Setings
//
dlgMdx.m_nHashOptions = m_nHashOptions;
dlgMdx.DoModal();
//
// Back
//
m_nHashOptions = dlgMdx.m_nHashOptions;
}
void CExileDlg::OnToolsPasswordgenerator()
{
CPasswordGeneratorDialog dlgPassword;
//
// Transferring settings
//
dlgPassword.m_bDecimalDigits = m_bDecimalDigits;
dlgPassword.m_bLowercase = m_bLowercase;
dlgPassword.m_bPunctuation = m_bPunctuation;
dlgPassword.m_bSpecial = m_bSpecial;
dlgPassword.m_bUppercase = m_bUppercase;
dlgPassword.m_nPasswordLength = m_nPasswordLength;
dlgPassword.DoModal();
//
// And back
//
m_bDecimalDigits = dlgPassword.m_bDecimalDigits;
m_bLowercase = dlgPassword.m_bLowercase;
m_bPunctuation = dlgPassword.m_bPunctuation;
m_bSpecial = dlgPassword.m_bSpecial;
m_bUppercase = dlgPassword.m_bUppercase;
m_nPasswordLength = dlgPassword.m_nPasswordLength;
}
void CExileDlg::OnPasswordTitle()
{
m_bShowPassword = !m_bShowPassword;
ShowEntry(m_ctrlTree.GetSelectedItem());
}
void CExileDlg::OnEditDelete()
{
DeleteItem(m_ctrlTree.GetSelectedItem());
}
void CExileDlg::OnEditEdit()
{
// See what we have to edit
if(m_ctrlTree.GetSelectedItem())
{
TV_ITEM tvi;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = m_ctrlTree.GetSelectedItem();
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
// If it is a category, edit one
if(emi->second.nFlags & EF_CATEGORY)
{
EditCategory(m_ctrlTree.GetSelectedItem());
} // if
else if(emi->second.nFlags & EF_ELEMENT)
{
EditElement(m_ctrlTree.GetSelectedItem());
} // else
} // if
} // if
} // if
}
void CExileDlg::OnEditStorageproperties()
{
CStoragePropertiesDialog dlgProps;
dlgProps.m_nKeySize = m_kiKeyInfo.nKeySize;
dlgProps.m_nRounds = m_kiKeyInfo.nRounds;
if(IDOK == dlgProps.DoModal())
{
// Need to recrypt from old context to a newly acquired one
BeginWaitCursor();
HRC5CONTEXT hRc5 = 0;
GeneratePrivateKey(dlgProps.m_strUserName, dlgProps.m_strMasterPassword, dlgProps.m_nKeySize, m_kiKeyInfo);
m_kiKeyInfo.nRounds = dlgProps.m_nRounds;
// Acquiring new crypting context and setting a new key
if(!::Rc5AcquireContext(hRc5, m_kiKeyInfo.nKeySize / 8, m_kiKeyInfo.nRounds))
{
MessageBoxEx(*this, IDS_RC5ACQUIRECONTEXTFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
if(!::Rc5SetBinaryPrivateKey(hRc5, m_kiKeyInfo.pbKey))
{
MessageBoxEx(*this, IDS_RC5SETBINARYPRIVATEKEYFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
// So now we can delete key buffer in order not
// to expose it anymore
FreeBuffer(m_kiKeyInfo.pbKey, m_kiKeyInfo.nKeySize / 8);
// Recrypting entries
MENTRY::iterator emi = m_mEntries.begin();
for( ; m_mEntries.end() != emi; ++emi)
{
::Rc5RecryptBlock(m_hRc5, hRc5, (RC5_WORD *)&(emi->second.pePrivate),
(RC5_WORD *)&(emi->second.pePrivate), sizeof(PRIVATEENTRY) / 8);
} // for
// Freeing old context
::Rc5ReleaseContext(m_hRc5);
m_hRc5 = hRc5;
ProcessSortOrder();
SetDirty(TRUE);
EndWaitCursor();
} // if
}
void CExileDlg::DeleteItem(HTREEITEM hItem)
{
if(hItem)
{
TV_ITEM tvi;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
// If it is a category, ask if we really want to delete
if(emi->second.nFlags & EF_CATEGORY)
{
CString strTitle, strText;
strTitle.LoadString(IDS_TITLE);
strText.LoadString(IDS_CONFIRMDELETECATEGORY);
if(IDNO == ::MessageBox(*this, strText, strTitle, MB_YESNO | MB_ICONQUESTION))
return;
} // if
else if(emi->second.nFlags & EF_ELEMENT)
{
if(IDNO == MessageBoxEx(*this, IDS_CONFIRMDELETEELEMENT, IDS_TITLE, MB_YESNO | MB_ICONQUESTION))
return;
} // else if
DeleteItems(hItem, TRUE);
} // if
} // if
} // if
}
void CExileDlg::DeleteItems(HTREEITEM hRoot, BOOL bFirstCall)
{
if(!hRoot)
return;
HTREEITEM hItem = hRoot;
MENTRY::iterator emi;
TV_ITEM tvi;
do
{
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
if(m_ctrlTree.ItemHasChildren(hItem))
DeleteItems(m_ctrlTree.GetChildItem(hItem), FALSE);
// Deleting this item
if(m_mEntries.end() != (emi = m_mEntries.find(GetItemParam(tvi.lParam))))
{
HTREEITEM hCurrent = hItem;
// When DeleteItems() is called for the first time,
// delete only this particular items without siblings.
if(!bFirstCall)
hItem = m_ctrlTree.GetNextSiblingItem(hItem);
else
hItem = 0;
CleanBuffer(&emi->second, sizeof(ENTRY));
m_mEntries.erase(emi);
m_ctrlTree.DeleteItem(hCurrent);
SetDirty(TRUE);
} // if
} // if
}
while(hItem);
}
void CExileDlg::EditElement(HTREEITEM hItem)
{
TV_ITEM tvi;
HTREEITEM hRoot;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hRoot = m_ctrlTree.GetSelectedItem();
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
if(!(emi->second.nFlags & EF_ELEMENT))
return;
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
CEditElementDialog dlgEdit;
dlgEdit.SetImageList(m_pimgList);
dlgEdit.m_strElementName = emi->second.pePrivate.szName;
dlgEdit.m_strLogin = emi->second.pePrivate.szLogin;
dlgEdit.m_strPassword = emi->second.pePrivate.szPassword;
dlgEdit.m_strAddress = emi->second.pePrivate.szAddress;
dlgEdit.m_strNotes = emi->second.pePrivate.szNotes;
dlgEdit.m_wModifiers = emi->second.pePrivate.exData.wModifiers;
dlgEdit.m_wVKCode = emi->second.pePrivate.exData.wVKCode;
dlgEdit.SetIconID(emi->second.lIconID);
dlgEdit.SetRating(emi->second.pePrivate.exData.cRating);
//
// Password Generator
//
dlgEdit.m_bDecimalDigits = m_bDecimalDigits;
dlgEdit.m_bLowercase = m_bLowercase;
dlgEdit.m_bPunctuation = m_bPunctuation;
dlgEdit.m_bSpecial = m_bSpecial;
dlgEdit.m_bUppercase = m_bUppercase;
dlgEdit.m_nPasswordLength = m_nPasswordLength;
if((emi->second.pePrivate.exData.wModifiers) && (emi->second.pePrivate.exData.wVKCode))
{
// Unregister hot key in case something happens
::UnregisterHotKey(GetSafeHwnd(), emi->second.lID);
} // if
if(IDOK == dlgEdit.DoModal())
{
// Changing map info
emi->second.lIconID = dlgEdit.GetIconID();
emi->second.pePrivate.exData.wModifiers = dlgEdit.m_wModifiers;
emi->second.pePrivate.exData.wVKCode = dlgEdit.m_wVKCode;
emi->second.pePrivate.exData.cRating = dlgEdit.GetRating();
#ifdef _UNICODE
wcscpy(emi->second.pePrivate.szName, dlgEdit.m_strElementName.LockBuffer());
wcscpy(emi->second.pePrivate.szNotes, dlgEdit.m_strNotes.LockBuffer());
wcscpy(emi->second.pePrivate.szAddress, dlgEdit.m_strAddress.LockBuffer());
wcscpy(emi->second.pePrivate.szLogin, dlgEdit.m_strLogin.LockBuffer());
wcscpy(emi->second.pePrivate.szPassword, dlgEdit.m_strPassword.LockBuffer());
#else
strcpy(emi->second.pePrivate.szName, dlgEdit.m_strElementName.LockBuffer());
strcpy(emi->second.pePrivate.szNotes, dlgEdit.m_strNotes.LockBuffer());
strcpy(emi->second.pePrivate.szAddress, dlgEdit.m_strAddress.LockBuffer());
strcpy(emi->second.pePrivate.szLogin, dlgEdit.m_strLogin.LockBuffer());
strcpy(emi->second.pePrivate.szPassword, dlgEdit.m_strPassword.LockBuffer());
#endif // _UNICODE
// Hot key
if((emi->second.pePrivate.exData.wModifiers) && (emi->second.pePrivate.exData.wVKCode) && m_bHotKeys)
{
if(!::RegisterHotKey(GetSafeHwnd(), emi->second.lID,
MapModifiers(emi->second.pePrivate.exData.wModifiers),
emi->second.pePrivate.exData.wVKCode))
TRACE("Failed to register hot key for %s\n", emi->second.pePrivate.szName);
} // if
// Renaming tree item
tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.cchTextMax = dlgEdit.m_strElementName.GetLength() + 1;
tvi.pszText = dlgEdit.m_strElementName.LockBuffer();
tvi.iImage = dlgEdit.GetIconID();
tvi.iSelectedImage = dlgEdit.GetIconID();
tvi.hItem = m_ctrlTree.GetSelectedItem();
m_ctrlTree.SetItem(&tvi);
SetDirty(TRUE);
SortItems(hRoot);
//
// Password Generator
//
m_bDecimalDigits = dlgEdit.m_bDecimalDigits;
m_bLowercase = dlgEdit.m_bLowercase;
m_bPunctuation = dlgEdit.m_bPunctuation;
m_bSpecial = dlgEdit.m_bSpecial;
m_bUppercase = dlgEdit.m_bUppercase;
m_nPasswordLength = dlgEdit.m_nPasswordLength;
} // if
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// After it was encrypted back
ShowEntry(m_ctrlTree.GetSelectedItem());
} // if
} // if
}
void CExileDlg::EditCategory(HTREEITEM hItem)
{
TV_ITEM tvi;
HTREEITEM hRoot;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hRoot = m_ctrlTree.GetSelectedItem();
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
if(!(emi->second.nFlags & EF_CATEGORY))
return;
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
CEditCategoryDialog dlgEdit;
dlgEdit.SetImageList(m_pimgList);
dlgEdit.m_strCategoryName = emi->second.pePrivate.szName;
dlgEdit.m_strDescription = emi->second.pePrivate.szNotes;
dlgEdit.SetIconID(emi->second.lIconID);
dlgEdit.SetRating(emi->second.pePrivate.exData.cRating);
if(IDOK == dlgEdit.DoModal())
{
// Changing map info
emi->second.lIconID = dlgEdit.GetIconID();
emi->second.pePrivate.exData.cRating = dlgEdit.GetRating();
#ifdef _UNICODE
wcscpy(emi->second.pePrivate.szName, dlgEdit.m_strCategoryName.LockBuffer());
wcscpy(emi->second.pePrivate.szNotes, dlgEdit.m_strDescription.LockBuffer());
#else
strcpy(emi->second.pePrivate.szName, dlgEdit.m_strCategoryName.LockBuffer());
strcpy(emi->second.pePrivate.szNotes, dlgEdit.m_strDescription.LockBuffer());
#endif // _UNICODE
// Renaming tree item
tvi.mask = TVIF_TEXT | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.cchTextMax = dlgEdit.m_strCategoryName.GetLength() + 1;
tvi.pszText = dlgEdit.m_strCategoryName.LockBuffer();
tvi.iImage = dlgEdit.GetIconID();
tvi.iSelectedImage = dlgEdit.GetIconID();
tvi.hItem = m_ctrlTree.GetSelectedItem();
m_ctrlTree.SetItem(&tvi);
SetDirty(TRUE);
SortItems(hRoot);
} // if
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// After it was encrypted back
ShowEntry(m_ctrlTree.GetSelectedItem());
} // if
} // if
}
void CExileDlg::SetDirty(BOOL bDirty)
{
m_bDirty = bDirty;
SetTitle();
}
void CExileDlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult)
{
// Sort of "IntelliMenu" - depends on the item selected
HTREEITEM hItem;
CPoint ptCur;
CMenu mCtx, *pmCtx = 0;
::GetCursorPos(&ptCur);
m_ctrlTree.ScreenToClient(&ptCur);
hItem = m_ctrlTree.HitTest(ptCur, 0);
if(hItem)
{
TV_ITEM tvi;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
m_ctrlTree.SelectItem(hItem);
if(emi->second.nFlags & EF_ROOTCATEGORY)
{
mCtx.LoadMenu(IDR_ROOT_CONTEXT);
pmCtx = mCtx.GetSubMenu(0);
} // if
else if(emi->second.nFlags & EF_CATEGORY)
{
mCtx.LoadMenu(IDR_CATEGORY_CONTEXT);
pmCtx = mCtx.GetSubMenu(0);
} // else if
else if(emi->second.nFlags & EF_ELEMENT)
{
mCtx.LoadMenu(IDR_ELEMENT_CONTEXT);
pmCtx = mCtx.GetSubMenu(0);
} // else if
m_ctrlTree.ClientToScreen(&ptCur);
if(0 != pmCtx)
{
pmCtx->TrackPopupMenu(TPM_LEFTALIGN, ptCur.x, ptCur.y, this);
} // if
} // if
} // if
} // if
*pResult = 0;
}
void CExileDlg::SetAddress(TCHAR *pszAddress)
{
SetDlgItemText(IDC_ADDRESS, pszAddress);
}
void CExileDlg::SetNotes(TCHAR *pszNotes)
{
SetDlgItemText(IDC_NOTES, pszNotes);
}
BOOL CExileDlg::PreTranslateMessage(MSG* pMsg)
{
if(TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
return TRUE;
return CDialog::PreTranslateMessage(pMsg);
}
void CExileDlg::SetKeyInfo(int nKeySize)
{
CString strKI;
switch(nKeySize)
{
case 1024:
strKI.LoadString(IDS_KEY1024);
break;
case 512:
strKI.LoadString(IDS_KEY512);
break;
case 256:
strKI.LoadString(IDS_KEY256);
break;
case 128:
strKI.LoadString(IDS_KEY128);
break;
default:
break;
} // switch
// TODO: Remove if want to see this
// SetDlgItemText(IDC_KEYINFO_TITLE, strKI);
}
LRESULT CExileDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
MENTRY::iterator emi;
HWND hForeground = 0;
HWND hFocused = 0;
DWORD dwForegroungThreadID = 0;
DWORD dwCurrentTreadID = 0;
TCHAR szWindowTitle[nWindowTitleLength];
switch(message)
{
case WM_TIMER:
if(g_uTimerID == wParam)
PerformAutoCleanClipboard();
return 0; // Processed
case WM_SIZE:
if((SIZE_MINIMIZED == wParam) && m_bMinimizeToTray) // Minimizing to tray
TrayWindow(TRUE);
else
return CDialog::WindowProc(message, wParam, lParam);
return 0; // Processed.
case WM_TRAYCALLBACK:
if(IDR_MAINFRAME != wParam)
break;
if(WM_LBUTTONDBLCLK == lParam)
TrayWindow(FALSE); // Restoring
if(WM_RBUTTONDOWN == lParam)
ShowTrayMenu();
return 0; // Processed
case WM_HOTKEY:
// wParam contains hotkey identifier, which is actually element index,
// so we have to decrypt appropriate entry and send message to
// focused window to set window text with a password.
// wParam == 0 is a SmartType hot key
if((0 == wParam) && (m_bSmartType))
{
// Invoking SmartType. Retrieving target window title
hForeground = ::GetForegroundWindow();
if(!hForeground)
return 0;
if(!(::GetWindowText(::GetAncestor(hForeground, GA_ROOT), szWindowTitle, nWindowTitleLength)))
return 0;
TRACE("Activating SmartType for %s\n", szWindowTitle);
// Searching through Advanced items
MADVANCED::iterator ami = m_mAdvanced.begin();
for( ; m_mAdvanced.end() != ami; ++ami)
{
#ifdef _UNICODE
if((!wcscmp(szWindowTitle, ami->second.sti.szWindowTitle)) && (ami->second.sti.bEnabled))
#else
if((!strcmp(szWindowTitle, ami->second.sti.szWindowTitle)) && (ami->second.sti.bEnabled))
#endif // _UNICODE
{
dwForegroungThreadID = ::GetWindowThreadProcessId(hForeground, NULL);
dwCurrentTreadID = ::GetCurrentThreadId();
// Sharing input focus
if(::AttachThreadInput(dwCurrentTreadID, dwForegroungThreadID, TRUE))
{
MENTRY::iterator emi = m_mEntries.find(ami->second.lID);
if(m_mEntries.end() != emi)
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
hFocused = ::GetDlgItem(hForeground, ami->second.sti.nLoginCtrlID);
::SendMessage(hFocused, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)emi->second.pePrivate.szLogin);
hFocused = ::GetDlgItem(hForeground, ami->second.sti.nPasswordCtrlID);
::SendMessage(hFocused, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)emi->second.pePrivate.szPassword);
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // if
::AttachThreadInput(dwCurrentTreadID, dwForegroungThreadID, FALSE);
} // if
return 0;
} // if
} // for
// If we got here than nothing suitable is found
::MessageBeep(MB_ICONEXCLAMATION);
return 0;
} // if
// Otherwise we send a password to a
// focused window
if(m_mEntries.end() == (emi = m_mEntries.find((long)wParam)))
break;
// We need to attach that thread to our process
hForeground = ::GetForegroundWindow();
dwForegroungThreadID = ::GetWindowThreadProcessId(hForeground, NULL);
dwCurrentTreadID = ::GetCurrentThreadId();
// Sharing input focus
if(::AttachThreadInput(dwCurrentTreadID, dwForegroungThreadID, TRUE))
{
hFocused = ::GetFocus();
// Sending password
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
::SendMessage(hFocused, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)emi->second.pePrivate.szPassword);
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
::AttachThreadInput(dwCurrentTreadID, dwForegroungThreadID, FALSE);
} // if
return 0;
default:
break;
} // switch
return CDialog::WindowProc(message, wParam, lParam);
}
void CExileDlg::TrayWindow(BOOL bMode)
{
if(bMode)
{
ShowWindow(SW_MINIMIZE);
ShowWindow(SW_HIDE);
m_bMaximized = FALSE;
} // if
else
{
ShowWindow(SW_SHOW);
ShowWindow(SW_RESTORE);
m_bMaximized = TRUE;
} // else
}
void CExileDlg::AddTrayIcon(UINT nIconID)
{
NOTIFYICONDATA nid = { 0 };
CString str;
str.LoadString(IDS_TITLE);
nid.cbSize = sizeof(nid);
nid.hIcon = AfxGetApp()->LoadIcon(nIconID);
nid.hWnd = GetSafeHwnd();
lstrcpyn(nid.szTip, str.LockBuffer(), sizeof(nid.szTip) / sizeof(nid.szTip[0]));
nid.uCallbackMessage = WM_TRAYCALLBACK;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uID = nIconID; // Icon ID to operate with
Shell_NotifyIcon(NIM_ADD, &nid);
}
void CExileDlg::ShowTrayMenu()
{
CMenu mCtx;
mCtx.LoadMenu(IDR_TRAYMENU);
CMenu *pmCtx = mCtx.GetSubMenu(0);
CPoint pt;
::GetCursorPos(&pt);
::SetForegroundWindow(GetSafeHwnd());
pmCtx->EnableMenuItem(ID_TRAYMENU_RESTORE, MF_BYCOMMAND | (m_bMaximized ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
pmCtx->EnableMenuItem(ID_FILE_CLOSE, MF_BYCOMMAND | (m_mEntries.empty() ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
pmCtx->CheckMenuItem(ID_TRAYMENU_ENABLEHOTKEYS, MF_BYCOMMAND | (m_bHotKeys ? MF_CHECKED : MF_UNCHECKED));
pmCtx->TrackPopupMenu(TPM_RIGHTALIGN, pt.x, pt.y, this);
}
void CExileDlg::OnTraymenuRestore()
{
TrayWindow(FALSE);
}
void CExileDlg::RemoveTrayIcon(UINT nIconID)
{
NOTIFYICONDATA nid;
nid.cbSize = sizeof(nid);
nid.hWnd = GetSafeHwnd();
nid.uID = nIconID;
Shell_NotifyIcon(NIM_DELETE, &nid);
}
void CExileDlg::ConvertStorage(long lVersion)
{
TRACE("Converting from version %d.%d to %d.%d\n", HIWORD(lVersion), LOWORD(lVersion),
HIWORD(STORAGEVERSION), LOWORD(STORAGEVERSION));
MENTRY::iterator ei = m_mEntries.begin();
switch(lVersion)
{
case MAKELONG(0, 1): // From 1.0
// This for this version we had 48 bytes reserved in abReserved and
// they must be set to zero to avoid problems
for(; ei != m_mEntries.end(); ++ei)
{
DecryptPrivateEntry(ei->second.pePrivate, m_hRc5);
memset((void *)&(ei->second.pePrivate.abReserved), 0, sizeof(ei->second.pePrivate.abReserved));
ei->second.lReserved = 0;
ei->second.pePrivate.exData.cRating = 5;
EncryptPrivateEntry(ei->second.pePrivate, m_hRc5);
} // for
break;
case MAKELONG(1, 1): // From 1.1
// Set Rating to Medium for all items
for(; ei != m_mEntries.end(); ++ei)
{
DecryptPrivateEntry(ei->second.pePrivate, m_hRc5);
ei->second.pePrivate.exData.cRating = 5;
ei->second.lReserved = 0;
EncryptPrivateEntry(ei->second.pePrivate, m_hRc5);
} // for
break;
case MAKELONG(4, 1): // From 1.4
// For the time being no conversion is required
break;
default:
break;
} // switch
}
void CExileDlg::RegisterHotKeys()
{
// Unregistering hot keys
MENTRY::iterator emi = m_mEntries.begin();
while(m_mEntries.end() != emi)
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
if((emi->second.pePrivate.exData.wModifiers) && (emi->second.pePrivate.exData.wVKCode))
{
if(!::RegisterHotKey(GetSafeHwnd(), emi->second.lID, MapModifiers(emi->second.pePrivate.exData.wModifiers),
emi->second.pePrivate.exData.wVKCode))
TRACE("Failed to register hot key for %s\n", emi->second.pePrivate.szName);
else
TRACE("Successfully registered hot key for %s\n", emi->second.pePrivate.szName);
} // if
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
++emi;
} // while
}
void CExileDlg::UnregisterHotKeys()
{
// Unregistering hot keys
MENTRY::iterator emi = m_mEntries.begin();
while(m_mEntries.end() != emi)
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
if((emi->second.pePrivate.exData.wModifiers) && (emi->second.pePrivate.exData.wVKCode))
{
::UnregisterHotKey(GetSafeHwnd(), emi->second.lID);
} // if
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
++emi;
} // while
}
void CExileDlg::OnTraymenuEnablehotkeys()
{
m_bHotKeys = !m_bHotKeys;
if(m_bHotKeys)
{
RegisterHotKeys();
} // if
else
{
UnregisterHotKeys();
} // else
// To update information
ShowEntry(m_ctrlTree.GetSelectedItem());
}
void CExileDlg::OnEditOptions()
{
COptionsDialog dlgOpt;
dlgOpt.m_bMinimizeToTray = m_bMinimizeToTray;
dlgOpt.m_bReloadLastStorage = m_bReloadLastStorage;
dlgOpt.m_bAutosave = m_bAutosave;
dlgOpt.m_bAutosort = m_bAutosort;
dlgOpt.m_bSmartType = m_bSmartType;
dlgOpt.SetHotKey(m_wModifiers, m_wKeyCode);
dlgOpt.SetSortOrder(m_nSortOrder);
dlgOpt.m_bBackup = m_bBackup;
dlgOpt.m_bMaintainFileAssociations = m_bMaintain;
dlgOpt.m_strStorageName = m_strStorageName;
dlgOpt.m_bReloadReadonly = m_bReloadReadonly;
dlgOpt.m_bShellOpenReadOnly = m_bShellOpenReadonly;
dlgOpt.m_bClipboardErasing = m_bClipboardErasing;
dlgOpt.m_nErasingTimeout = m_nErasingTimeout;
// Unregistering SmartType hot key
if(m_bSmartType)
{
::UnregisterHotKey(*this, 0);
} // if
if(IDOK == dlgOpt.DoModal())
{
m_nErasingTimeout = dlgOpt.m_nErasingTimeout;
m_bClipboardErasing = dlgOpt.m_bClipboardErasing;
m_bShellOpenReadonly = dlgOpt.m_bShellOpenReadOnly;
m_bMinimizeToTray = dlgOpt.m_bMinimizeToTray;
m_bReloadLastStorage = dlgOpt.m_bReloadLastStorage;
m_bAutosave = dlgOpt.m_bAutosave;
m_bAutosort = dlgOpt.m_bAutosort;
m_bSmartType = dlgOpt.m_bSmartType;
dlgOpt.GetHotKey(m_wModifiers, m_wKeyCode);
m_nSortOrder = dlgOpt.GetSortOrder();
m_bBackup = dlgOpt.m_bBackup;
m_bReloadReadonly = dlgOpt.m_bReloadReadonly;
if(m_bMaintain = dlgOpt.m_bMaintainFileAssociations)
MaintainFileAssociations();
// Registering hot key
if(m_bSmartType)
{
::RegisterHotKey(*this, 0, MapModifiers(m_wModifiers), m_wKeyCode);
} // if
ProcessSortOrder();
} // if
}
LRESULT CExileDlg::OnActivateApp(WPARAM wParam, LPARAM lParam)
{
// Bring from tray
if(!m_bMaximized)
TrayWindow(FALSE);
if(!IsWindowVisible())
ShowWindow(SW_SHOW);
if(IsIconic())
ShowWindow(SW_RESTORE);
SetForegroundWindow();
return 1;
}
void CExileDlg::SetInfo(TCHAR *pszInfo)
{
SetDlgItemText(IDC_INFO_TITLE, pszInfo);
}
LRESULT CExileDlg::OnTcexItemdragged(WPARAM wParam, LPARAM lParam)
{
SetDirty(TRUE);
return 0; // Ignored
}
void CExileDlg::OnCategorycontextSortNameascending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetAscending(0) };
TV_SORTCB cbSort = { hParent, CompareNames, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
void CExileDlg::OnCategorycontextSortNamedescending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetDescending(0) };
TV_SORTCB cbSort = { hParent, CompareNames, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
void CExileDlg::OnCategorycontextSortUsernameascending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetAscending(0) };
TV_SORTCB cbSort = { hParent, CompareUsernames, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
void CExileDlg::OnCategorycontextSortUsernamedescending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetDescending(0) };
TV_SORTCB cbSort = { hParent, CompareUsernames, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
void CExileDlg::OnCategorycontextSortRatingascending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetAscending(0) };
TV_SORTCB cbSort = { hParent, CompareRatings, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
void CExileDlg::OnCategorycontextSortRatingdescending()
{
HTREEITEM hParent = m_ctrlTree.GetSelectedItem();
if(!hParent)
return;
BeginWaitCursor();
// Some information on how to sort stuff we have
SORTPARAMETERS spSort = { &m_mEntries, m_hRc5, SetDescending(0) };
TV_SORTCB cbSort = { hParent, CompareRatings, (LPARAM)&spSort };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
SetDirty(TRUE);
EndWaitCursor();
}
int CExileDlg::CompareNames(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
LPSORTPARAMETERS lpSort = (LPSORTPARAMETERS)lParamSort;
int nOrder = 0;
MENTRY::iterator emi1 = lpSort->lpmEntries->find(GetItemParam(lParam1)),
emi2 = lpSort->lpmEntries->find(GetItemParam(lParam2));
if((lpSort->lpmEntries->end() == emi1) || (lpSort->lpmEntries->end() == emi2))
return 0;
// Analyzing names
DecryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
DecryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
if(IsAscending(lpSort->lParam))
{
#ifdef _UNICODE
nOrder = wcscmp(emi1->second.pePrivate.szName, emi2->second.pePrivate.szName);
#else
nOrder = strcmp(emi1->second.pePrivate.szName, emi2->second.pePrivate.szName);
#endif // _UNICODE
} // if
else
{
#ifdef _UNICODE
nOrder = wcscmp(emi2->second.pePrivate.szName, emi1->second.pePrivate.szName);
#else
nOrder = strcmp(emi2->second.pePrivate.szName, emi1->second.pePrivate.szName);
#endif // _UNICODE
} // else
EncryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
EncryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
return nOrder;
}
int CExileDlg::CompareUsernames(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
LPSORTPARAMETERS lpSort = (LPSORTPARAMETERS)lParamSort;
int nOrder = 0;
MENTRY::iterator emi1 = lpSort->lpmEntries->find(GetItemParam(lParam1)),
emi2 = lpSort->lpmEntries->find(GetItemParam(lParam2));
if((lpSort->lpmEntries->end() == emi1) || (lpSort->lpmEntries->end() == emi2))
return 0;
// Analyzing user names (logins)
DecryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
DecryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
if(IsAscending(lpSort->lParam))
{
#ifdef _UNICODE
nOrder = wcscmp(emi1->second.pePrivate.szLogin, emi2->second.pePrivate.szLogin);
#else
nOrder = strcmp(emi1->second.pePrivate.szLogin, emi2->second.pePrivate.szLogin);
#endif // _UNICODE
} // if
else
{
#ifdef _UNICODE
nOrder = wcscmp(emi2->second.pePrivate.szLogin, emi1->second.pePrivate.szLogin);
#else
nOrder = strcmp(emi2->second.pePrivate.szLogin, emi1->second.pePrivate.szLogin);
#endif // _UNICODE
} // else
EncryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
EncryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
return nOrder;
}
int CALLBACK CExileDlg::CompareRatings(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
LPSORTPARAMETERS lpSort = (LPSORTPARAMETERS)lParamSort;
int nOrder = 0;
MENTRY::iterator emi1 = lpSort->lpmEntries->find(GetItemParam(lParam1)),
emi2 = lpSort->lpmEntries->find(GetItemParam(lParam2));
if((lpSort->lpmEntries->end() == emi1) || (lpSort->lpmEntries->end() == emi2))
return 0;
// Analyzing ratings
DecryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
DecryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
if(IsAscending(lpSort->lParam))
{
nOrder = (int)(emi1->second.pePrivate.exData.cRating - emi2->second.pePrivate.exData.cRating);
} // if
else
{
nOrder = (int)(emi2->second.pePrivate.exData.cRating - emi1->second.pePrivate.exData.cRating);
} // else
EncryptPrivateEntry(emi1->second.pePrivate, lpSort->hRc5);
EncryptPrivateEntry(emi2->second.pePrivate, lpSort->hRc5);
return nOrder;
}
void CExileDlg::SortItems(HTREEITEM hRoot)
{
if(!m_bAutosort)
return;
BeginWaitCursor();
TV_SORTCB cbSort = { hRoot, m_soSortOrder.pfnCompare, (LPARAM)&(m_soSortOrder.spSort) };
m_ctrlTree.SortChildrenCB((LPTVSORTCB)&cbSort);
EndWaitCursor();
}
void CExileDlg::ProcessSortOrder()
{
// Setting up SORTORDER
if((m_nSortOrder < 0) || (m_nSortOrder > sizeof(g_aSortOrder) / sizeof(g_aSortOrder[0])))
return;
m_soSortOrder = g_aSortOrder[m_nSortOrder];
m_soSortOrder.spSort.hRc5 = m_hRc5;
m_soSortOrder.spSort.lpmEntries = &m_mEntries;
switch(m_nSortOrder)
{
case 0:
case 1:
m_soSortOrder.pfnCompare = CompareNames;
break;
case 2:
case 3:
m_soSortOrder.pfnCompare = CompareUsernames;
break;
case 4:
case 5:
m_soSortOrder.pfnCompare = CompareRatings;
break;
default:
break;
} // switch
}
LRESULT CExileDlg::OnShleRButtondown(WPARAM wParam, LPARAM lParam)
{
if(IDC_PASSWORD_TITLE == wParam)
{
TRACE("RClick on Password Title\n");
// Copying password to clipboard
HTREEITEM hItem = m_ctrlTree.GetSelectedItem();
if(!hItem)
return 0;
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
tvi.hItem = hItem;
if(!m_ctrlTree.GetItem(&tvi))
return 0;
MENTRY::iterator emi = m_mEntries.find(tvi.lParam);
if(m_mEntries.end() == emi)
return 0;
// Opening clipboard
if(!::OpenClipboard(GetSafeHwnd()))
{
return 0;
} // if
::EmptyClipboard();
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// Copying password to shared memory...
HGLOBAL hPassword;
LPTSTR lpszPassword;
#ifdef _UNICODE
hPassword = ::GlobalAlloc(GMEM_MOVEABLE, (wcslen(emi->second.pePrivate.szPassword) + 1) * sizeof(TCHAR));
lpszPassword = (LPTSTR)::GlobalLock(hPassword);
wcscpy(lpszPassword, emi->second.pePrivate.szPassword);
::GlobalUnlock(hPassword);
#else
hPassword = ::GlobalAlloc(GMEM_MOVEABLE, (strlen(emi->second.pePrivate.szPassword) + 1) * sizeof(TCHAR));
lpszPassword = (LPTSTR)::GlobalLock(hPassword);
strcpy(lpszPassword, emi->second.pePrivate.szPassword);
::GlobalUnlock(hPassword);
#endif // _UNICODE
::SetClipboardData(CF_TEXT, hPassword);
::CloseClipboard();
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // if
return 0;
}
void CExileDlg::SaveStorageXml()
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
MSXML2::IXMLDOMNodePtr pXMLNode;
MSXML2::IXMLDOMProcessingInstructionPtr pXMLPI;
MSXML2::IXMLDOMCommentPtr pXMLC;
if(FAILED(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30))))
{
// TODO: Message
return;
} // if
pXMLPI = pXMLDoc->createProcessingInstruction("xml", "version='1.0'");
if(0 != pXMLPI)
pXMLDoc->appendChild(pXMLPI);
// Adding comments
pXMLC = pXMLDoc->createComment("octalforty Exile XML Password Storage.");
if(0 != pXMLC)
pXMLDoc->appendChild(pXMLC);
pXMLC = pXMLDoc->createComment("Copyright (C) 2004 octalforty studios. All rights reserved.");
if(0 != pXMLC)
pXMLDoc->appendChild(pXMLC);
// Creating root item with attributes which hold key-related information
MSXML2::IXMLDOMElementPtr pXMLE = pXMLDoc->createElement("password-storage");
if(0 != pXMLE)
{
// Storage version
MSXML2::IXMLDOMAttributePtr pXMLA = pXMLDoc->createAttribute("version");
if(0 != pXMLA)
{
pXMLA->value = STORAGEVERSION; // In decimal, not <major>.<minor>
pXMLE->setAttributeNode(pXMLA);
} // if
// Storage flags
pXMLA = pXMLDoc->createAttribute("flags");
if(0 != pXMLA)
{
#ifdef _UNICODE
pXMLA->value = SF_UNICODE_VERSION;
#else
pXMLA->value = SF_ANSI_VERSION;
#endif // _UNICODE
pXMLE->setAttributeNode(pXMLA);
} // if
// Key size (in bits)
pXMLA = pXMLDoc->createAttribute("keysize");
if(0 != pXMLA)
{
pXMLA->value = (long)m_kiKeyInfo.nKeySize;
pXMLE->setAttributeNode(pXMLA);
} // if
// Encryption rounds
pXMLA = pXMLDoc->createAttribute("rounds");
if(0 != pXMLA)
{
pXMLA->value = (long)m_kiKeyInfo.nRounds;
pXMLE->setAttributeNode(pXMLA);
} // if
// <User Name> + <Master Password> hash
pXMLA = pXMLDoc->createAttribute("passwordhash");
if(0 != pXMLA)
{
TCHAR szHash[64];
#ifdef _UNICODE
swprintf(szHash, _T("%08x%08x%08x%08x"), m_kiKeyInfo.hsPassword.wA,
m_kiKeyInfo.hsPassword.wB, m_kiKeyInfo.hsPassword.wC, m_kiKeyInfo.hsPassword.wD);
#else
sprintf(szHash, _T("%08x%08x%08x%08x"), m_kiKeyInfo.hsPassword.wA,
m_kiKeyInfo.hsPassword.wB, m_kiKeyInfo.hsPassword.wC, m_kiKeyInfo.hsPassword.wD);
#endif // _UNICODE
pXMLA->value = szHash;
pXMLE->setAttributeNode(pXMLA);
} // if
// Index
pXMLA = pXMLDoc->createAttribute("index");
if(0 != pXMLA)
{
pXMLA->value = m_lIndex;
pXMLE->setAttributeNode(pXMLA);
} // if
// Structured view
SaveTreeXml(pXMLDoc, pXMLE, m_ctrlTree.GetRootItem(), 1);
pXMLE->appendChild(pXMLDoc->createTextNode("\n"));
pXMLDoc->appendChild(pXMLE);
} // if
if(FAILED(pXMLDoc->save(m_strStorageName.LockBuffer())))
{
} // if
m_strStorageName.UnlockBuffer();
}
MSXML2::IXMLDOMElementPtr CExileDlg::SaveTreeXml(MSXML2::IXMLDOMDocument2Ptr pXMLDoc, MSXML2::IXMLDOMElementPtr pXMLElement,
HTREEITEM hRoot, int nIndent)
{
TV_ITEM tvi;
HTREEITEM hItem = hRoot;
MSXML2::IXMLDOMElementPtr pXE;
MSXML2::IXMLDOMAttributePtr pXA;
do
{
// Save current item
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() == emi)
return 0;
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// Adding information about this particular item
if(emi->second.nFlags & EF_CATEGORY)
{
pXMLElement->appendChild(pXMLDoc->createTextNode("\n"));
pXE = pXMLDoc->createElement("category");
// Writing attributes
// Item ID
pXA = pXMLDoc->createAttribute("id");
if(0 != pXA)
{
pXA->value = emi->second.lID;
pXE->setAttributeNode(pXA);
} // if
// Item flags
pXA = pXMLDoc->createAttribute("flags");
if(0 != pXA)
{
pXA->value = (long)emi->second.nFlags;
pXE->setAttributeNode(pXA);
} // if
// Entry icon
pXA = pXMLDoc->createAttribute("icon");
if(0 != pXA)
{
pXA->value = emi->second.lIconID;
pXE->setAttributeNode(pXA);
} // if
pXE->appendChild(pXMLDoc->createTextNode(emi->second.pePrivate.szName));
// If this item has chilren, save them too
if(m_ctrlTree.ItemHasChildren(hItem))
{
SaveTreeXml(pXMLDoc, pXE, m_ctrlTree.GetChildItem(hItem), nIndent + 1);
pXE->appendChild(pXMLDoc->createTextNode("\n"));
pXE->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
} // if
pXMLElement->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
pXMLElement->appendChild(pXE);
} // if
else if(emi->second.nFlags & EF_ELEMENT)
{
pXMLElement->appendChild(pXMLDoc->createTextNode("\n"));
pXMLElement->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
pXE = pXMLDoc->createElement("element");
// Writing attributes
// Item ID
pXA = pXMLDoc->createAttribute("id");
if(0 != pXA)
{
pXA->value = emi->second.lID;
pXE->setAttributeNode(pXA);
} // if
// Item flags
pXA = pXMLDoc->createAttribute("flags");
if(0 != pXA)
{
pXA->value = (long)emi->second.nFlags;
pXE->setAttributeNode(pXA);
} // if
// Entry icon
pXA = pXMLDoc->createAttribute("icon");
if(0 != pXA)
{
pXA->value = emi->second.lIconID;
pXE->setAttributeNode(pXA);
} // if
pXE->appendChild(pXMLDoc->createTextNode(emi->second.pePrivate.szName));
pXMLElement->appendChild(pXE);
} // else if
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // if
// Proceed with siblings
hItem = m_ctrlTree.GetNextSiblingItem(hItem);
}
while(0 != hItem);
return pXMLElement;
}
CString CExileDlg::Indent(int nIndent)
{
CString s;
for( ; nIndent; --nIndent)
s += '\t';
return s;
}
void CExileDlg::OnFileExportExporttoxml()
{
CExportToXmlDialog dlgExport;
dlgExport.SetExportFlags(m_nExportFlags);
dlgExport.m_strFileName = m_strExportFileName;
if(IDOK == dlgExport.DoModal())
{
ExportXml(dlgExport.m_strFileName, dlgExport.GetExportFlags());
} // if
m_nExportFlags = dlgExport.GetExportFlags();
m_strExportFileName = dlgExport.m_strFileName;
}
void CExileDlg::ExportXml(CString strFileName, unsigned int nExportFlags)
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
MSXML2::IXMLDOMNodePtr pXMLNode;
MSXML2::IXMLDOMProcessingInstructionPtr pXMLPI;
MSXML2::IXMLDOMCommentPtr pXMLC;
if(FAILED(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30))))
{
// TODO: Message
return;
} // if
pXMLPI = pXMLDoc->createProcessingInstruction("xml", "version='1.0'");
if(0 != pXMLPI)
pXMLDoc->appendChild(pXMLPI);
// Adding comments
pXMLC = pXMLDoc->createComment("Copyright (C) 2004 octalforty studios. All rights reserved.");
if(0 != pXMLC)
pXMLDoc->appendChild(pXMLC);
// Creating root item
MSXML2::IXMLDOMElementPtr pXMLE = pXMLDoc->createElement("passwordStorage");
if(0 != pXMLE)
{
// Structured view
ExportTreeXml(pXMLDoc, pXMLE, m_ctrlTree.GetRootItem(), 1, nExportFlags);
pXMLE->appendChild(pXMLDoc->createTextNode("\n"));
pXMLDoc->appendChild(pXMLE);
} // if
if(FAILED(pXMLDoc->save(strFileName.LockBuffer())))
{
} // if
strFileName.UnlockBuffer();
}
MSXML2::IXMLDOMElementPtr CExileDlg::ExportTreeXml(MSXML2::IXMLDOMDocument2Ptr pXMLDoc, MSXML2::IXMLDOMElementPtr pXMLElement,
HTREEITEM hRoot, int nIndent, unsigned int nExportFlags)
{
TV_ITEM tvi;
HTREEITEM hItem = hRoot;
MSXML2::IXMLDOMElementPtr pXE;
MSXML2::IXMLDOMAttributePtr pXA;
do
{
// Save current item
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hItem;
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() == emi)
return 0;
// Adding information about this particular item
if(emi->second.nFlags & EF_CATEGORY)
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
pXMLElement->appendChild(pXMLDoc->createTextNode("\n"));
pXE = pXMLDoc->createElement("category");
// Writing attributes necessary
// Category Name
if(ExportCategoryName(nExportFlags))
{
pXA = pXMLDoc->createAttribute("categoryName");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szName;
pXE->setAttributeNode(pXA);
} // if
} // if
// Category Description
if(ExportCategoryDescription(nExportFlags))
{
pXA = pXMLDoc->createAttribute("categoryDescription");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szNotes;
pXE->setAttributeNode(pXA);
} // if
} // if
// Category Icon
if(ExportCategoryDescription(nExportFlags))
{
pXA = pXMLDoc->createAttribute("categoryIcon");
if(0 != pXA)
{
pXA->value = emi->second.lIconID;
pXE->setAttributeNode(pXA);
} // if
} // if
// Category Rating
if(ExportCategoryDescription(nExportFlags))
{
pXA = pXMLDoc->createAttribute("categoryRating");
if(0 != pXA)
{
pXA->value = g_aRatings[emi->second.pePrivate.exData.cRating].szName;
pXE->setAttributeNode(pXA);
} // if
} // if
//pXE->appendChild(pXMLDoc->createTextNode(emi->second.pePrivate.szName));
// Before any recursive calls
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
// If this item has chilren, save them too
if(m_ctrlTree.ItemHasChildren(hItem))
{
ExportTreeXml(pXMLDoc, pXE, m_ctrlTree.GetChildItem(hItem), nIndent + 1, nExportFlags);
pXE->appendChild(pXMLDoc->createTextNode("\n"));
pXE->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
} // if
pXMLElement->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
pXMLElement->appendChild(pXE);
} // if
else if(emi->second.nFlags & EF_ELEMENT)
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
MADVANCED::iterator ami = m_mAdvanced.find(emi->second.lID);
pXMLElement->appendChild(pXMLDoc->createTextNode("\n"));
pXMLElement->appendChild(pXMLDoc->createTextNode(Indent(nIndent).LockBuffer()));
pXE = pXMLDoc->createElement("element");
// Writing attributes
// Element Name
if(ExportElementName(nExportFlags))
{
pXA = pXMLDoc->createAttribute("elementName");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szName;
pXE->setAttributeNode(pXA);
} // if
} // if
// Login
if(ExportLogin(nExportFlags))
{
pXA = pXMLDoc->createAttribute("login");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szLogin;
pXE->setAttributeNode(pXA);
} // if
} // if
// Password
if(ExportPassword(nExportFlags))
{
pXA = pXMLDoc->createAttribute("password");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szPassword;
pXE->setAttributeNode(pXA);
} // if
} // if
// Address
if(ExportAddress(nExportFlags))
{
pXA = pXMLDoc->createAttribute("address");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szAddress;
pXE->setAttributeNode(pXA);
} // if
} // if
// Notes
if(ExportNotes(nExportFlags))
{
pXA = pXMLDoc->createAttribute("notes");
if(0 != pXA)
{
pXA->value = emi->second.pePrivate.szNotes;
pXE->setAttributeNode(pXA);
} // if
} // if
// Element Rating
if(ExportElementRating(nExportFlags))
{
pXA = pXMLDoc->createAttribute("elementRating");
if(0 != pXA)
{
pXA->value = g_aRatings[emi->second.pePrivate.exData.cRating].szName;
pXE->setAttributeNode(pXA);
} // if
} // if
// Element Icon
if(ExportElementIcon(nExportFlags))
{
pXA = pXMLDoc->createAttribute("elementIcon");
if(0 != pXA)
{
pXA->value = emi->second.lIconID;
pXE->setAttributeNode(pXA);
} // if
} // if
// SmartType
if((ExportSmartType(nExportFlags)) && (m_mAdvanced.end() != ami))
{
pXA = pXMLDoc->createAttribute("SmartType");
if(0 != pXA)
{
pXA->value = (long)ami->second.sti.bEnabled;
pXE->setAttributeNode(pXA);
} // if
} // if
// Target Window Title
if((ExportTargetWindowTitle(nExportFlags)) && (m_mAdvanced.end() != ami))
{
pXA = pXMLDoc->createAttribute("targetWindowTitle");
if(0 != pXA)
{
pXA->value = ami->second.sti.szWindowTitle;
pXE->setAttributeNode(pXA);
} // if
} // if
// Login Control ID
if((ExportLoginControlID(nExportFlags)) && (m_mAdvanced.end() != ami))
{
pXA = pXMLDoc->createAttribute("loginControlID");
if(0 != pXA)
{
pXA->value = (long)ami->second.sti.nLoginCtrlID;
pXE->setAttributeNode(pXA);
} // if
} // if
// Password Control ID
if((ExportLoginControlID(nExportFlags)) && (m_mAdvanced.end() != ami))
{
pXA = pXMLDoc->createAttribute("passwordControlID");
if(0 != pXA)
{
pXA->value = (long)ami->second.sti.nPasswordCtrlID;
pXE->setAttributeNode(pXA);
} // if
} // if
//pXE->appendChild(pXMLDoc->createTextNode(emi->second.pePrivate.szName));
pXMLElement->appendChild(pXE);
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // else if
} // if
// Proceed with siblings
hItem = m_ctrlTree.GetNextSiblingItem(hItem);
}
while(0 != hItem);
return pXMLElement;
}
void CExileDlg::SaveStorageSerial()
{
// Now freely saving
CFile fStg;
CFileException eFe;
// Creating backup of a storage
if(m_bBackup)
{
CString strDest = m_strStorageName.Left(m_strStorageName.Find(_T('.'))) + CString("_backup.pws");
if(!::CopyFile(m_strStorageName, strDest, FALSE))
{
MessageBoxEx(*this, IDS_BACKUPSTORAGEFAILED, IDS_TITLE);
} // if
} // if
if(!fStg.Open(m_strStorageName, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive, &eFe))
{
MessageBoxEx(*this, IDS_CREATESTORAGEFAILED, IDS_TITLE);
return;
} // if
BeginWaitCursor();
// Traversing tree
VTREE vTree;
SaveTree(vTree, m_ctrlTree.GetRootItem());
// Writing header
STORAGEHEADER sth;
// See typedefs.h
sth.lTag = STORAGETAG;
sth.lVersion = STORAGEVERSION;
sth.lAdvanced = m_mAdvanced.size();
#ifdef _UNICODE
sth.lFlags = SF_UNICODE_VERSION;
#else
sth.lFlags = SF_ANSI_VERSION;
#endif // _UNICODE
sth.nKeySize = m_kiKeyInfo.nKeySize;
sth.nRounds = m_kiKeyInfo.nRounds;
sth.hsPassword = m_kiKeyInfo.hsPassword;
sth.lIndex = m_lIndex;
sth.lElements = m_mEntries.size();
sth.lNodes = vTree.size();
fStg.Write((void *)&sth, sizeof(STORAGEHEADER));
// Now writing tree structure information
LONG *plTree = new LONG[vTree.size()];
for(size_t s = 0; s < vTree.size(); ++s)
{
plTree[s] = vTree[s];
} // for
fStg.Write((void *)plTree, sizeof(LONG) * vTree.size());
FreeBuffer(plTree, sizeof(LONG) * vTree.size());
// And Private entries...
MENTRY::iterator emi = m_mEntries.begin();
while(m_mEntries.end() != emi)
{
fStg.Write((void *)&emi->second, sizeof(ENTRY));
++emi;
} // while
// Advanced stuff
MADVANCED::iterator ami = m_mAdvanced.begin();
while(m_mAdvanced.end() != ami)
{
fStg.Write((void *)&(ami->second), sizeof(ADVANCED));
++ami;
} // while
// Done
fStg.Close();
SetDirty(FALSE);
EndWaitCursor();
}
void CExileDlg::LoadStorageSerial()
{
// Loading Storage
CFile fStg;
CFileException eFe;
if(!fStg.Open(m_strStorageName, CFile::modeRead | CFile::shareExclusive, &eFe))
{
MessageBoxEx(*this, IDS_STORAGEOPENFAILED, IDS_TITLE);
m_strStorageName.Empty();
return;
} // if
// Reading header and asking for a password
STORAGEHEADER sth;
fStg.Read((void *)&sth, sizeof(STORAGEHEADER));
// This section is common for all versions of storage files
if(STORAGETAG == sth.lTag)
{
#ifdef _UNICODE
if(!(SF_UNICODE_VERSION & sth.lFlags))
{
MessageBoxEx(*this, IDS_NOTAUNICODEVERSION, IDS_TITLE);
return;
} // if
#else
if(!(SF_ANSI_VERSION & sth.lFlags))
{
MessageBoxEx(*this, IDS_NOTANANSIVERSION, IDS_TITLE);
return;
} // if
#endif // _UNICODE
MDXHASH hsPassword;
CEnterPasswordDialog dlgPassword;
do
{
CleanString(dlgPassword.m_strUserName);
CleanString(dlgPassword.m_strMasterPassword);
dlgPassword.m_strMasterPassword.Empty();
dlgPassword.m_strUserName.Empty();
if(IDOK == dlgPassword.DoModal())
{
GeneratePasswordHash(dlgPassword.m_strUserName, dlgPassword.m_strMasterPassword, hsPassword);
} // if
else
return;
}
while(!::MdxEqualHashes(sth.hsPassword, hsPassword));
BeginWaitCursor();
// Key info
m_kiKeyInfo.nKeySize = sth.nKeySize;
m_kiKeyInfo.nRounds = sth.nRounds;
m_kiKeyInfo.pbKey = 0;
GeneratePrivateKey(dlgPassword.m_strUserName, dlgPassword.m_strMasterPassword, sth.nKeySize, m_kiKeyInfo);
// Acquiring new context
if(::Rc5ValidContext(m_hRc5))
::Rc5ReleaseContext(m_hRc5);
if(!::Rc5AcquireContext(m_hRc5, m_kiKeyInfo.nKeySize / 8, m_kiKeyInfo.nRounds))
{
MessageBoxEx(*this, IDS_RC5ACQUIRECONTEXTFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
if(!::Rc5SetBinaryPrivateKey(m_hRc5, m_kiKeyInfo.pbKey))
{
MessageBoxEx(*this, IDS_RC5SETBINARYPRIVATEKEYFAILED, IDS_TITLE);
CleanPrivateData();
EndWaitCursor();
return;
} // if
// So now we can delete key buffer in order not
// to expose it anymore
FreeBuffer(m_kiKeyInfo.pbKey, m_kiKeyInfo.nKeySize / 8);
CleanString(dlgPassword.m_strMasterPassword);
CleanString(dlgPassword.m_strUserName);
// Now reading items
m_ctrlTree.DeleteAllItems();
m_mEntries.clear();
m_lIndex = sth.lIndex;
// Tree structure
size_t sBuffer = sizeof(LONG) * sth.lNodes;
LONG *plBuffer = new LONG[sth.lNodes];
VTREE vTree;
fStg.Read((void *)plBuffer, sBuffer);
for(long l = 0; l < sth.lNodes; ++l)
vTree.push_back(plBuffer[l]);
FreeBuffer(plBuffer, sBuffer);
// Items
sBuffer = sizeof(ENTRY) * sth.lElements;
ENTRY *pBufer = new ENTRY[sth.lElements];
fStg.Read((void *)pBufer, sBuffer);
for(l = 0; l < sth.lElements; ++l)
m_mEntries[pBufer[l].lID] = pBufer[l];
FreeBuffer(pBufer, sBuffer);
// If the storage we're opening has version 1.5 and above, read
// required number of ADVANCED structures
if((sth.lVersion >= MAKELONG(5, 1)) && (sth.lAdvanced > 0))
{
sBuffer = sizeof(ADVANCED) * sth.lAdvanced;
ADVANCED *paBuffer = new ADVANCED[sth.lAdvanced];
fStg.Read((void *)paBuffer, sBuffer);
for(l = 0; l < sth.lAdvanced; ++l)
m_mAdvanced[paBuffer[l].lID] = paBuffer[l];
FreeBuffer(paBuffer, sBuffer);
} // if
// Convert items to our version if required
if(STORAGEVERSION > sth.lVersion) // Converting from older versions
{
ConvertStorage(sth.lVersion);
} // if
if(m_bHotKeys)
RegisterHotKeys();
// Restoring tree structure
LoadTree(vTree, 0);
SwitchMenu(MF_FILE_ALL, TRUE);
SwitchMenu(MF_FILE_SAVE, !m_bReadOnly);
SetTitle();
SetKeyInfo(m_kiKeyInfo.nKeySize);
ProcessSortOrder();
EndWaitCursor();
} // if
else
MessageBoxEx(*this, IDS_WRONGFORMAT, IDS_TITLE);
}
void CExileDlg::LoadStorageXml()
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
if(FAILED(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30))))
{
// TODO: Message
return;
} // if
if(VARIANT_FALSE == pXMLDoc->load(m_strStorageName.LockBuffer()))
{
m_strStorageName.UnlockBuffer();
return;
} // if
m_strStorageName.UnlockBuffer();
// Root element
MSXML2::IXMLDOMElementPtr pXMLElem = pXMLDoc->documentElement;
if(0 == pXMLElem)
{
// TODO: Message
return;
} // if
if(_bstr_t("password-storage") != pXMLElem->tagName)
{
MessageBoxEx(*this, IDS_XMLOPENFAILED, IDS_TITLE);
return;
} // if
MSXML2::IXMLDOMNamedNodeMapPtr pXMLNNM;
MSXML2::IXMLDOMNodePtr pXMLN;
pXMLElem->get_attributes(&pXMLNNM);
// Setting up key info
if(0 != (pXMLN = pXMLNNM->getNamedItem("version")))
{
long lVersion = atol(pXMLN->text);
} // if
}
void CExileDlg::OnEditAdvanced()
{
// See what we have to edit
if(m_ctrlTree.GetSelectedItem())
{
TV_ITEM tvi;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = m_ctrlTree.GetSelectedItem();
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
if(emi->second.nFlags & EF_ELEMENT)
{
EditElementAdvanced(m_ctrlTree.GetSelectedItem());
} // else
} // if
} // if
} // if
}
void CExileDlg::EditElementAdvanced(HTREEITEM hItem)
{
TV_ITEM tvi;
HTREEITEM hRoot;
tvi.mask = TVIF_PARAM | TVIF_HANDLE;
tvi.hItem = hRoot = m_ctrlTree.GetSelectedItem();
if(m_ctrlTree.GetItem(&tvi))
{
MENTRY::iterator emi = m_mEntries.find(GetItemParam(tvi.lParam));
if(m_mEntries.end() != emi)
{
if(!(emi->second.nFlags & EF_ELEMENT))
return;
CAdvancedDialog dlgAdv;
// Loading Advanced settings for this item
MADVANCED::iterator ami = m_mAdvanced.find(emi->second.lID);
if(m_mAdvanced.end() != ami)
{
dlgAdv.m_bEnable = ami->second.sti.bEnabled;
dlgAdv.m_nLogin = ami->second.sti.nLoginCtrlID;
dlgAdv.m_nPassword = ami->second.sti.nPasswordCtrlID;
dlgAdv.m_strWindowTitle = ami->second.sti.szWindowTitle;
} // if
else
{
dlgAdv.m_bEnable = FALSE;
dlgAdv.m_nLogin = 0;
dlgAdv.m_nPassword = 0;
dlgAdv.m_strWindowTitle.Empty();
// Inserting new ADVANCED thing
ADVANCED adv;
memset(&adv, 0, sizeof(ADVANCED));
adv.lID = emi->second.lID;
m_mAdvanced[emi->second.lID] = adv;
} // else
if(IDOK == dlgAdv.DoModal())
{
// Creating new STI
SMARTTYPEINFO sti;
sti.bEnabled = dlgAdv.m_bEnable;
sti.nLoginCtrlID = dlgAdv.m_nLogin;
sti.nPasswordCtrlID = dlgAdv.m_nPassword;
#ifdef _UNICODE
wcscpy(sti.szWindowTitle, dlgAdv.m_strWindowTitle.LockBuffer());
#else
strcpy(sti.szWindowTitle, dlgAdv.m_strWindowTitle.LockBuffer());
#endif // _UNICODE
m_mAdvanced[emi->second.lID].sti = sti;
SetDirty(TRUE);
} // if
} // if
} // if
}
void CExileDlg::MaintainFileAssociations()
{
TCHAR szModule[MAX_PATH];
if(!GetModuleFileName(0, szModule, MAX_PATH)) // Failure
return;
BeginWaitCursor();
CRegistry reg;
CString strCmd;
reg.SetRootKey(HKEY_CLASSES_ROOT);
// Add entry in HKEY_CLASSES_ROOT about
// .pws file type...
reg.CreateKey(".pws");
reg.WriteString("", "octalforty.Exile.PasswordStorage");
reg.CreateKey("octalforty.Exile.PasswordStorage");
reg.WriteString("", "octalforty Exile Password Storage"); // Document type name
reg.CreateKey("octalforty.Exile.PasswordStorage\\Shell");
reg.WriteString("", "Open"); // Default action
strCmd.Format("\"%s\", 0", szModule);
reg.CreateKey("octalforty.Exile.PasswordStorage\\DefaultIcon");
reg.WriteString("", strCmd); // Default icon
reg.CreateKey("octalforty.Exile.PasswordStorage\\Shell\\Open");
reg.WriteString("", "&Open"); // Command string
strCmd.Format("\"%s\" \"%%1\"", szModule);
reg.CreateKey("octalforty.Exile.PasswordStorage\\Shell\\Open\\Command");
reg.WriteString("", strCmd); // Command itself
EndWaitCursor();
}
void CExileDlg::OnCopy()
{
// What exactly do we have to copy
CWnd* pWnd = GetFocus();
if(!pWnd)
return;
CString strCopy;
//
// Searching for required item
//
HTREEITEM hItem = m_ctrlTree.GetSelectedItem();
if(!hItem)
return;
TV_ITEM tvi;
tvi.mask = TVIF_HANDLE | TVIF_PARAM;
tvi.hItem = hItem;
if(!m_ctrlTree.GetItem(&tvi))
return;
MENTRY::iterator emi = m_mEntries.find(tvi.lParam);
if(m_mEntries.end() == emi)
return;
if(*pWnd == *GetDlgItem(IDC_LOGIN))
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
strCopy = emi->second.pePrivate.szLogin;
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // if
else if(*pWnd == *GetDlgItem(IDC_PASSWORD))
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
strCopy = emi->second.pePrivate.szPassword;
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // else if
else if(*pWnd == *GetDlgItem(IDC_ADDRESS))
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
strCopy = emi->second.pePrivate.szAddress;
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // else if
else if(*pWnd == *GetDlgItem(IDC_NOTES))
{
DecryptPrivateEntry(emi->second.pePrivate, m_hRc5);
strCopy = emi->second.pePrivate.szNotes;
EncryptPrivateEntry(emi->second.pePrivate, m_hRc5);
} // else if
else
return;
//
// If we got here we have something to send to Clipboard
//
CopyToClipboard(strCopy);
CleanString(strCopy);
}
void CExileDlg::SaveSettings()
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
MSXML2::IXMLDOMNodePtr pXMLNode;
MSXML2::IXMLDOMProcessingInstructionPtr pXMLPI;
MSXML2::IXMLDOMCommentPtr pXMLC;
if(FAILED(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30))))
{
// TODO: Message
return;
} // if
pXMLPI = pXMLDoc->createProcessingInstruction(_T("xml"), _T("version='1.0' encoding='UTF-8'"));
if(0 != pXMLPI)
pXMLDoc->appendChild(pXMLPI);
// Adding comments
pXMLC = pXMLDoc->createComment("Generated by octalforty Exile 1.7");
if(0 != pXMLC)
pXMLDoc->appendChild(pXMLC);
pXMLC = pXMLDoc->createComment("Copyright (C) 2004 octalforty studios. All rights reserved.");
if(0 != pXMLC)
pXMLDoc->appendChild(pXMLC);
// Creating root item
MSXML2::IXMLDOMElementPtr pXMLE = pXMLDoc->createElement("configuration");
if(0 != pXMLE)
{
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n\t")));
//
// General Settings
//
MSXML2::IXMLDOMElementPtr pElement = pXMLDoc->createElement("configurationGeneral");
if(pElement)
{
pElement->setAttribute(_T("showPassword"), _variant_t((short)m_bShowPassword, VT_I2));
pElement->setAttribute(_T("maintainFileAssociations"), _variant_t((short)m_bMaintain, VT_I2));
pElement->setAttribute(_T("enableHotKeys"), _variant_t((short)m_bHotKeys, VT_I2));
pElement->setAttribute(_T("minimizeToTray"), _variant_t((short)m_bMinimizeToTray, VT_I2));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// Storage Settings
//
pElement = pXMLDoc->createElement("configurationStorage");
if(pElement)
{
pElement->setAttribute(_T("createBackup"), _variant_t((short)m_bBackup, VT_I2));
pElement->setAttribute(_T("autoSave"), _variant_t((short)m_bAutosave, VT_I2));
pElement->setAttribute(_T("shellOpenReadOnly"), _variant_t((short)m_bShellOpenReadonly, VT_I2));
pElement->setAttribute(_T("reloadLastStorage"), _variant_t((short)m_bReloadLastStorage, VT_I2));
pElement->setAttribute(_T("lastStorage"), _T(m_strLastStorage.LockBuffer()));
pElement->setAttribute(_T("reloadReadOnly"), _variant_t((short)m_bReloadReadonly, VT_I2));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// SmartType Settings
//
pElement = pXMLDoc->createElement("configurationSmartType");
if(pElement)
{
pElement->setAttribute(_T("smartType"), _variant_t((short)m_bSmartType, VT_I2));
pElement->setAttribute(_T("smartTypeModifier"), _variant_t((long)m_wModifiers, VT_I4));
pElement->setAttribute(_T("smartTypeVKey"), _variant_t((long)m_wKeyCode, VT_I4));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
// Sorting Settings
pElement = pXMLDoc->createElement("configurationSorting");
if(pElement)
{
pElement->setAttribute(_T("autoSort"), _variant_t((short)m_bAutosort, VT_I2));
pElement->setAttribute(_T("autoSortOrder"), _variant_t((long)m_nSortOrder, VT_I4));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// Clipboard Settings
//
pElement = pXMLDoc->createElement("configurationClipboard");
if(pElement)
{
pElement->setAttribute(_T("eraseClipboard"), _variant_t((short)m_bClipboardErasing, VT_I2));
pElement->setAttribute(_T("eraseClipboardTimeout"), _variant_t((long)m_nErasingTimeout, VT_I4));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// Password Generator
//
pElement = pXMLDoc->createElement("configurationPasswordGenerator");
if(pElement)
{
pElement->setAttribute(_T("decimalDigits"), _variant_t((short)m_bDecimalDigits, VT_I2));
pElement->setAttribute(_T("lowercaseCharacters"), _variant_t((short)m_bLowercase, VT_I2));
pElement->setAttribute(_T("punctuationMarks"), _variant_t((short)m_bPunctuation, VT_I2));
pElement->setAttribute(_T("specialCharacters"), _variant_t((short)m_bSpecial, VT_I2));
pElement->setAttribute(_T("uppercaseCharacters"), _variant_t((short)m_bUppercase, VT_I2));
pElement->setAttribute(_T("passwordLength"), _variant_t((long)m_nPasswordLength, VT_I4));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// Hash Generator
//
pElement = pXMLDoc->createElement("configurationHashGenerator");
if(pElement)
{
pElement->setAttribute(_T("hashOptions"), _variant_t((long)m_nHashOptions, VT_I4));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\t")));
//
// Export To Xml
//
pElement = pXMLDoc->createElement("configurationExportToXml");
if(pElement)
{
pElement->setAttribute(_T("exportFlags"), _variant_t((long)m_nExportFlags, VT_I4));
pElement->setAttribute(_T("exportFileName"), _variant_t(m_strExportFileName.LockBuffer()));
pXMLE->appendChild(pElement);
pXMLE->appendChild(pXMLDoc->createTextNode(_T("\n")));
} // if
pXMLDoc->appendChild(pXMLE);
} // if
if(FAILED(pXMLDoc->save(_variant_t(CombinePathName(GetShellFolder(CSIDL_PERSONAL), _T("exile.xml"))))))
{
// TODO : Message
} // if
}
void CExileDlg::CopyToClipboard(CString &rString)
{
//
// Opening clipboard
//
if(!::OpenClipboard(GetSafeHwnd()))
return;
::EmptyClipboard();
//
// Copying to shared memory...
//
HGLOBAL hData;
LPTSTR lpszData;
#ifdef _UNICODE
hData = ::GlobalAlloc(GMEM_MOVEABLE, (rString.GetLength() + 1) * sizeof(TCHAR));
lpszData = (LPTSTR)::GlobalLock(hData);
wcscpy(lpszData, rString.LockBuffer());
::GlobalUnlock(hData);
#else
hData = ::GlobalAlloc(GMEM_MOVEABLE, (rString.GetLength() + 1) * sizeof(TCHAR));
lpszData = (LPTSTR)::GlobalLock(hData);
strcpy(lpszData, rString.LockBuffer());
::GlobalUnlock(hData);
#endif // _UNICODE
::SetClipboardData(CF_TEXT, hData);
::CloseClipboard();
//
// Auto clean
//
AutoCleanClipboard();
}
void CExileDlg::LoadSettings()
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
MSXML2::IXMLDOMNodePtr pNode;
MSXML2::IXMLDOMNodeListPtr pNodes;
MSXML2::IXMLDOMProcessingInstructionPtr pXMLPI;
MSXML2::IXMLDOMCommentPtr pXMLC;
if(FAILED(pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30))))
{
// TODO: Message
return;
} // if
if(VARIANT_FALSE == pXMLDoc->load(_variant_t(CombinePathName(GetShellFolder(CSIDL_PERSONAL), _T("exile.xml")))))
{
// TODO: Message
return;
} // if
if(0 == (pNodes = pXMLDoc->documentElement->childNodes))
{
// TODO: Message
return;
} // if
//
// Loading General Settings
//
if(FAILED(pNodes->get_item(0, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationGeneral")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bShowPassword = XmlReadBool(pNode, _T("showPassword"));
m_bMaintain = XmlReadBool(pNode, _T("maintainFileAssociations"));
m_bHotKeys = XmlReadBool(pNode, _T("enableHotKeys"));
m_bMinimizeToTray = XmlReadBool(pNode, _T("minimizeToTray"));
//
// Storage Settings
//
if(FAILED(pNodes->get_item(1, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationStorage")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bBackup = XmlReadBool(pNode, _T("createBackup"));
m_bAutosave = XmlReadBool(pNode, _T("autoSave"));
m_bShellOpenReadonly = XmlReadBool(pNode, _T("shellOpenReadOnly"));
m_bReloadLastStorage = XmlReadBool(pNode, _T("reloadLastStorage"));
m_bReloadReadonly = XmlReadBool(pNode, _T("reloadReadOnly"));
m_strStorageName = m_strLastStorage = XmlReadString(pNode, _T("lastStorage"));
//
// SmartType Settings
//
if(FAILED(pNodes->get_item(2, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationSmartType")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bSmartType = XmlReadBool(pNode, _T("smartType"));
m_wModifiers = (WORD)XmlReadLong(pNode, _T("smartTypeModifier"));
m_wKeyCode = (WORD)XmlReadLong(pNode, _T("smartTypeVKey"));
//
// Sorting Settings
//
if(FAILED(pNodes->get_item(3, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationSorting")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bAutosort = XmlReadBool(pNode, _T("autoSort"));
m_nSortOrder = (int)XmlReadLong(pNode, _T("autoSortOrder"));
//
// Clipboard Settings
//
if(FAILED(pNodes->get_item(4, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationClipboard")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bClipboardErasing = XmlReadBool(pNode, _T("eraseClipboard"));
m_nErasingTimeout = (int)XmlReadLong(pNode, _T("eraseClipboardTimeout"));
//
// Password Generator Settings
//
if(FAILED(pNodes->get_item(5, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationPasswordGenerator")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_bDecimalDigits = XmlReadBool(pNode, _T("decimalDigits"));
m_bLowercase = XmlReadBool(pNode, _T("lowercaseCharacters"));
m_bPunctuation = XmlReadBool(pNode, _T("punctuationMarks"));
m_bSpecial = XmlReadBool(pNode, _T("specialCharacters"));
m_bUppercase = XmlReadBool(pNode, _T("uppercaseCharacters"));
m_nPasswordLength = (int)XmlReadLong(pNode, _T("passwordLength"));
//
// Hash Generator Settings
//
if(FAILED(pNodes->get_item(6, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationHashGenerator")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_nHashOptions = (int)XmlReadLong(pNode, _T("hashOptions"));
//
// Export To Xml Settings
//
if(FAILED(pNodes->get_item(7, &pNode)))
{
// TODO: Message
return;
} // if
if(_bstr_t(_T("configurationExportToXml")) != pNode->nodeName)
{
// TODO : Message
return;
} // if
m_nExportFlags = (int)XmlReadLong(pNode, _T("exportFlags"));
m_strExportFileName = XmlReadString(pNode, _T("exportFileName"));
}
BOOL CExileDlg::XmlReadBool(MSXML2::IXMLDOMNodePtr pNode, LPCTSTR pszAttribute, BOOL bDefault)
{
MSXML2::IXMLDOMNamedNodeMapPtr pNodes;
MSXML2::IXMLDOMNodePtr pAttribute;
if(0 == (pNodes = pNode->attributes))
return bDefault;
//
// Reading attribute required
//
_variant_t vt;
if(0 == (pAttribute = pNodes->getNamedItem(_bstr_t(pszAttribute))))
return bDefault;
if(FAILED(pAttribute->get_nodeValue(&vt)))
return bDefault;
vt.ChangeType(VT_I2);
return vt.boolVal;
}
CString CExileDlg::XmlReadString(MSXML2::IXMLDOMNodePtr pNode, LPCTSTR pszAttribute, CString strDefault)
{
MSXML2::IXMLDOMNamedNodeMapPtr pNodes;
MSXML2::IXMLDOMNodePtr pAttribute;
if(0 == (pNodes = pNode->attributes))
return strDefault;
//
// Reading attribute required
//
_variant_t vt;
if(0 == (pAttribute = pNodes->getNamedItem(_bstr_t(pszAttribute))))
return strDefault;
if(FAILED(pAttribute->get_nodeValue(&vt)))
return strDefault;
return CString(vt.bstrVal);
}
LONG CExileDlg::XmlReadLong(MSXML2::IXMLDOMNodePtr pNode, LPCTSTR pszAttribute, LONG lDefault)
{
MSXML2::IXMLDOMNamedNodeMapPtr pNodes;
MSXML2::IXMLDOMNodePtr pAttribute;
if(0 == (pNodes = pNode->attributes))
return lDefault;
//
// Reading attribute required
//
_variant_t vt;
if(0 == (pAttribute = pNodes->getNamedItem(_bstr_t(pszAttribute))))
return lDefault;
if(FAILED(pAttribute->get_nodeValue(&vt)))
return lDefault;
vt.ChangeType(VT_I4);
return LONG(vt.lVal);
}
void CExileDlg::AutoCleanClipboard()
{
if((!m_bClipboardErasing) || (0 == m_nErasingTimeout ))
return;
//
// Setting up timer
//
::SetTimer(*this, g_uTimerID, m_nErasingTimeout * 1000, 0);
}
void CExileDlg::PerformAutoCleanClipboard()
{
//
// Removing timer and erasing clipboard
//
::KillTimer(*this, g_uTimerID);
if(!::OpenClipboard(GetSafeHwnd()))
return;
::EmptyClipboard();
::CloseClipboard();
}