Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Exile 1.8 - The Password Manager

, 7 Mar 2005
Yet another password manager.
exile_18_setup.zip
exile_1.8_setup.exe
exile_exe.zip
exile.exe
Exile.exe.manifest
icons.dll
md5.dll
mdx.dll
PwsInfo.dll
rc5.dll
exile_exe_staticmfc.zip
exile.exe
icons.dll
md5.dll
mdx.dll
rc5.dll
exile_src.zip
exile
Exile
Exile.exe.manifest
exile.dep
exile.dsp
exile.dsw
res
aboveimportant.ico
advanced.bmp
belowcritical.ico
belowinsignificant.ico
belownormal.ico
changeicon.bmp
cold.ico
collapsed.ico
critical.ico
editcategory.bmp
editelement.bmp
enterpassword.bmp
error.ico
exile.ico
expanded.ico
exporttoxml.bmp
find.ico
found.ico
important.ico
insertcategory.bmp
insertelement.bmp
insignificant.ico
md5hashgenerator.bmp
new.bmp
normal.ico
options.bmp
passwordgenerator.bmp
rsasecurity.bmp
rsasecurity.ico
search.cur
storageproperties.bmp
switch.bmp
unimportant.ico
veryimportant.ico
vssver.scc
Icons
res
icon1.ico
icon10.ico
icon11.ico
icon12.ico
icon13.ico
icon14.ico
icon15.ico
icon16.ico
icon17.ico
icon18.ico
icon19.ico
icon2.ico
icon20.ico
icon21.ico
icon22.ico
icon23.ico
icon24.ico
icon25.ico
icon26.ico
icon27.ico
icon28.ico
icon3.ico
icon4.ico
icon5.ico
icon6.ico
icon7.ico
icon8.ico
icon9.ico
md5
md5.dep
md5.dsp
mdx
pwsinfo
passwordstorageshellext.rgs
pwsinfo.def
pwsinfo.dep
pwsinfo.dsp
pwsinfo.dsw
PwsInfo.tlb
pwsinfops.def
pwsinfops.mk
rc5
rc5.dep
rc5.dsp
xml
exile_src_vs2003.zip
Exile.exe.manifest
Exile.dep
Exile.dsp
Exile.dsw
Exile.suo
msxml3.tlh
msxml3.tli
res
AboveImportant.ico
Advanced.bmp
BelowCritical.ico
BelowInsignificant.ico
BelowNormal.ico
ChangeIcon.bmp
Cold.ico
Critical.ico
EditCategory.bmp
EditElement.bmp
EnterPassword.bmp
Error.ico
Exile.ico
ExportToXML.bmp
Find.ico
Found.ico
Icon1.ico
Icon10.ico
Icon11.ico
Icon12.ico
Icon13.ico
Icon14.ico
icon15.ico
Icon16.ico
Icon17.ico
Icon18.ico
Icon19.ico
Icon2.ico
Icon20.ico
Icon21.ico
Icon22.ico
Icon23.ico
Icon24.ico
Icon25.ico
Icon26.ico
Icon27.ico
Icon28.ico
Icon3.ico
Icon4.ico
Icon5.ico
Icon6.ico
Icon7.ico
Icon8.ico
Icon9.ico
Important.ico
InsertCategory.bmp
InsertElement.bmp
Insignificant.ico
MD5HashGenerator.bmp
New.bmp
Normal.ico
Options.bmp
PasswordGenerator.bmp
RSASecurity.bmp
rsasecurity.ico
Search.cur
StorageProperties.bmp
Switch.bmp
Unimportant.ico
VeryImportant.ico
vssver.scc
MD5
MD5.dep
MD5.dsp
PwsInfo
PasswordStorageShellExt.rgs
PwsInfo.def
PwsInfo.dep
PwsInfo.dsp
PwsInfo.dsw
PwsInfo.tlb
PwsInfops.def
PwsInfops.mk
RC5
RC5.dep
RC5.dsp
/********************************************************************
	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"

#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);

/////////////////////////////////////////////////////////////////////////////
// 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);
}

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_MODESWITCH, m_ctrlModeSwitch);
	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_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	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)
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

	::Md5Initialize();

	m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));

	// Loading settings
	CRegistry reg;
	CString strKey;

	reg.SetRootKey(HKEY_CURRENT_USER);
	strKey.LoadString(IDS_REGKEY);

	BOOL bKey = reg.SetKey(strKey, FALSE);
	
	m_bDetailed = bKey ? reg.ReadBool("Show Detailed Information", TRUE) : TRUE;
	m_bShowPassword = bKey ? reg.ReadBool("Show Password") : FALSE;
	m_bHotKeys = bKey ? reg.ReadBool("Enable Hot Keys") : FALSE;
	m_bReloadLastStorage = bKey ? reg.ReadBool("Reload Last Storage") : FALSE;
	m_bAutosave = bKey ? reg.ReadBool("Auto-Save") : FALSE;
	m_bMinimizeToTray = bKey ? reg.ReadBool("Minimize To Tray", TRUE) : TRUE;
	m_bAutosort = bKey ? reg.ReadBool("Auto-Sort") : FALSE;
	m_bSmartType = bKey ? reg.ReadBool("SmartType") : FALSE;
	m_wModifiers = (WORD)reg.ReadInt("SmartType Hot Key Modifier");
	m_wKeyCode = (WORD)reg.ReadInt("SmartType Kot Key Virtual Key");
	m_nSortOrder = bKey ? reg.ReadInt("Sort Order") : 0;

	// SmartType
	if(m_bSmartType)
	{
		::RegisterHotKey(*this, 0, MapModifiers(m_wModifiers), m_wKeyCode);
	} // if

	// Icons
	m_pimgList = new CImageList();
	m_pimgList->Create(32, 32, ILC_COLOR8 | ILC_MASK, 15, 5);

	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON1));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON2));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON3));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON4));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON5));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON6));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON7));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON8));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON9));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON10));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON11));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON12));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON13));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON14));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON15));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON16));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON17));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON18));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON19));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON20));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON21));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON22));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON23));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON24));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON25));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON26));
	m_pimgList->Add(AfxGetApp()->LoadIcon(IDI_ICON27));

	// Small ones
	m_pimgListSmall = new CImageList();
	m_pimgListSmall->Create(16, 16, ILC_COLOR8 | ILC_MASK, 15, 5);

	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON1));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON2));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON3));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON4));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON5));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON6));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON7));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON8));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON9));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON10));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON11));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON12));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON13));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON14));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON15));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON16));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON17));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON18));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON19));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON20));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON21));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON22));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON23));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON24));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON25));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON26));
	m_pimgListSmall->Add(AfxGetApp()->LoadIcon(IDI_ICON27));

	// Rating icoms
	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_BRIEF, GetDlgItem(IDC_LOGIN_TITLE)->GetSafeHwnd());
	m_gcControls.AddControl(ELEMENT_BRIEF, GetDlgItem(IDC_PASSWORD_TITLE)->GetSafeHwnd());
	m_gcControls.AddControl(ELEMENT_BRIEF, GetDlgItem(IDC_LOGIN)->GetSafeHwnd());
	m_gcControls.AddControl(ELEMENT_BRIEF, GetDlgItem(IDC_PASSWORD)->GetSafeHwnd());
	m_gcControls.AddControl(ELEMENT_BRIEF, GetDlgItem(IDC_MODESWITCH)->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));

	m_ctrlModeSwitch.SetIcon(m_pimgSwitch->ExtractIcon(m_bDetailed ? 0 : 2));

	// 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();

	if(!rcmdInfo.m_strFileName.IsEmpty())
	{
		m_strStorageName = rcmdInfo.m_strFileName;
		LoadStorage(FALSE);
	} // if
	else
	{
		if(m_bReloadLastStorage) 
		{
			m_strStorageName = bKey ? reg.ReadString("Last Storage") : CString("");

			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();

	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();
	} // 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(FALSE);
	} // 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

	// Saving recent storage
	CRegistry reg;
	CString strKey;

	reg.SetRootKey(HKEY_CURRENT_USER);
	strKey.LoadString(IDS_REGKEY);

	if(reg.CreateKey(strKey))
	{
		reg.WriteString("Last Storage", m_strStorageName);
	} // if

	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;

		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_HIDEREADONLY | OFN_NONETWORKBUTTON, strFilter, this);

		if(IDCANCEL == dlgOpen.DoModal()) 
			return;

		ProcessDirtyStorage();
		CloseStorage();	

		m_strStorageName = dlgOpen.GetPathName();
	} // 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();
	
	CRegistry reg;
	CString strKey;

	reg.SetRootKey(HKEY_CURRENT_USER);
	strKey.LoadString(IDS_REGKEY);

	if(reg.CreateKey(strKey))
	{
		reg.WriteBool("Show Detailed Information", m_bDetailed);
		reg.WriteBool("Show Password", m_bShowPassword);
		reg.WriteBool("Enable Hot Keys", m_bHotKeys);
		reg.WriteBool("Reload Last Storage", m_bReloadLastStorage);
		reg.WriteBool("Auto-Save", m_bAutosave);
		reg.WriteBool("Minimize To Tray", m_bMinimizeToTray);
		reg.WriteBool("Auto-Sort", m_bAutosort);
		reg.WriteBool("SmartType", m_bSmartType);
		reg.WriteInt("SmartType Hot Key Modifier", (int)m_wModifiers);
		reg.WriteInt("SmartType Kot Key Virtual Key", (int)m_wKeyCode);
		reg.WriteInt("Sort Order", m_nSortOrder);
	} // if

	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;

	::Md5Uninitialize();	
}

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(m_bDetailed ? ELEMENT_INDETAIL : ELEMENT_BRIEF);

				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);

	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();
	} // 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(" *");
	} // 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 dlgMd5;

	dlgMd5.DoModal();
}

void CExileDlg::OnToolsPasswordgenerator() 
{
	CPasswordGeneratorDialog dlgPassword;

	dlgPassword.DoModal();
}

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::OnMouseMove(UINT nFlags, CPoint point) 
{
	if((m_mEntries.empty()) || (m_nSelection != EF_ELEMENT))
	{
		return;
		CDialog::OnMouseMove(nFlags, point);
	} // if
		
	// Might be a bit slow, but looks fancy, isn't it ;)
	CRect rcSw;

	m_ctrlModeSwitch.GetClientRect(rcSw);
	m_ctrlModeSwitch.MapWindowPoints(this, rcSw);

	if(rcSw.PtInRect(point))
		m_ctrlModeSwitch.SetIcon(m_pimgSwitch->ExtractIcon(m_bDetailed ? 1 : 3));
	else
		m_ctrlModeSwitch.SetIcon(m_pimgSwitch->ExtractIcon(m_bDetailed ? 0 : 2));	
}

void CExileDlg::SwitchMode()
{
	m_bDetailed = !m_bDetailed;

	m_ctrlModeSwitch.SetIcon(m_pimgSwitch->ExtractIcon(m_bDetailed ? 0 : 2));

	// If we show detailed information
	if(m_bDetailed) 
	{
		m_gcControls.SwitchControls(ELEMENT_INDETAIL, CGroupedControls::SWS_SHOW);
	} // if
	else
	{
		m_gcControls.SwitchControls(ELEMENT_INDETAIL, CGroupedControls::SWS_HIDE);
		m_gcControls.SwitchControls(ELEMENT_BRIEF, CGroupedControls::SWS_SHOW);
	} // else
}

void CExileDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if((m_mEntries.empty()) || (m_nSelection != EF_ELEMENT))
	{
		CDialog::OnLButtonDown(nFlags, point);
		return;
	} // if

	CRect rcSw;

	m_ctrlModeSwitch.GetClientRect(rcSw);
	m_ctrlModeSwitch.MapWindowPoints(this, rcSw);

	if(rcSw.PtInRect(point))
		SwitchMode();
	
	CDialog::OnLButtonDown(nFlags, point);
}

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);

			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);
			} // 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_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);

	// Unregistering SmartType hot key
	if(m_bSmartType)
	{
		::UnregisterHotKey(*this, 0);
	} // if

	if(IDOK == dlgOpt.DoModal()) 
	{
		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();

		// 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()
{
	IXMLDOMDocument2Ptr pXMLDoc;
    IXMLDOMNodePtr pXMLNode;
    IXMLDOMProcessingInstructionPtr pXMLPI;
    IXMLDOMCommentPtr pXMLC;

    if(FAILED(pXMLDoc.CreateInstance(__uuidof(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
    IXMLDOMElementPtr pXMLE = pXMLDoc->createElement("password-storage");
    if(0 != pXMLE)
    {        
        // Storage version
        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();
}

IXMLDOMElementPtr CExileDlg::SaveTreeXml(IXMLDOMDocument2Ptr pXMLDoc, IXMLDOMElementPtr pXMLElement, 
										 HTREEITEM hRoot, int nIndent)
{
	TV_ITEM tvi;
	HTREEITEM hItem = hRoot;
	IXMLDOMElementPtr pXE;
	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;

	if(IDOK == dlgExport.DoModal())
	{
		ExportXml(dlgExport.m_strFileName, dlgExport.GetExportFlags());
	} // if
}

void CExileDlg::ExportXml(CString strFileName, unsigned int nExportFlags)
{
	IXMLDOMDocument2Ptr pXMLDoc;
    IXMLDOMNodePtr pXMLNode;
    IXMLDOMProcessingInstructionPtr pXMLPI;
    IXMLDOMCommentPtr pXMLC;

    if(FAILED(pXMLDoc.CreateInstance(__uuidof(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
    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();
}

IXMLDOMElementPtr CExileDlg::ExportTreeXml(IXMLDOMDocument2Ptr pXMLDoc, IXMLDOMElementPtr pXMLElement, 
										   HTREEITEM hRoot, int nIndent, unsigned int nExportFlags)
{
	TV_ITEM tvi;
	HTREEITEM hItem = hRoot;
	IXMLDOMElementPtr pXE;
	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;

	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

		MD5HASH 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(!::Md5EqualHashes(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);
		SetTitle();
		SetKeyInfo(m_kiKeyInfo.nKeySize);

		ProcessSortOrder();

		EndWaitCursor();
	} // if
	else
		MessageBoxEx(*this, IDS_WRONGFORMAT, IDS_TITLE);
}

void CExileDlg::LoadStorageXml()
{
	IXMLDOMDocument2Ptr pXMLDoc;

	if(FAILED(pXMLDoc.CreateInstance(__uuidof(DOMDocument30))))
	{
		// TODO: Message
		return;
	} // if

	if(VARIANT_FALSE == pXMLDoc->load(m_strStorageName.LockBuffer()))
	{
		m_strStorageName.UnlockBuffer();
		return;
	} // if

	m_strStorageName.UnlockBuffer();

	// Root element
	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

	IXMLDOMNamedNodeMapPtr pXMLNNM;
	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	
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

AntonGogolev
Web Developer
Russian Federation Russian Federation
I'll think about it later on...

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 7 Mar 2005
Article Copyright 2004 by AntonGogolev
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid