// USBFilterEditorDlg.cpp : implementation file
//

#include "StdAfx.h"

#include <cstdio>

#include "sqlite3.h"

#include "AboutDlg.h"
#include "EditDeviceDlg.h"
#include "USBFilterEditor.h"
#include "USBFilterEditorDlg.h"
#include "SearchDeviceDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CUSBFilterEditorDlg dialog

BEGIN_MESSAGE_MAP(CUSBFilterEditorDlg, CDialog)
    ON_WM_CLOSE()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON_ADD, &CUSBFilterEditorDlg::OnBnClickedButtonAdd)
    ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CUSBFilterEditorDlg::OnBnClickedButtonExport)
    ON_BN_CLICKED(IDC_BUTTON_IMPORT, &CUSBFilterEditorDlg::OnBnClickedButtonImport)
    ON_BN_CLICKED(IDC_BUTTON_UP, &CUSBFilterEditorDlg::OnBnClickedButtonUp)
    ON_BN_CLICKED(IDC_BUTTON_DOWN, &CUSBFilterEditorDlg::OnBnClickedButtonDown)
    ON_BN_CLICKED(IDC_BUTTON_EDIT, &CUSBFilterEditorDlg::OnBnClickedButtonEdit)
    ON_BN_CLICKED(IDC_BUTTON_REMOVE, &CUSBFilterEditorDlg::OnBnClickedButtonRemove)
    ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CUSBFilterEditorDlg::OnBnClickedButtonSearch)
    ON_COMMAND(ID_HELP_ABOUT, &CUSBFilterEditorDlg::OnHelpAbout)
    ON_COMMAND(ID_FILE_EXIT, &CUSBFilterEditorDlg::OnFileExit)
    ON_COMMAND(ID_FILE_SAVE, &CUSBFilterEditorDlg::OnFileSave)
    ON_NOTIFY(NM_CLICK, IDC_LIST_CRITERIAS, &CUSBFilterEditorDlg::OnItemActivateListCriterias)
    ON_NOTIFY(NM_RCLICK, IDC_LIST_CRITERIAS, &CUSBFilterEditorDlg::OnNMRclickListCriterias)
END_MESSAGE_MAP()

CUSBFilterEditorDlg::CUSBFilterEditorDlg(CWnd* pParent /*=NULL*/) :
    CDialog(CUSBFilterEditorDlg::IDD, pParent),
    m_hAccelTable(NULL),
    m_bModified(false)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CUSBFilterEditorDlg::DoDataExchange(CDataExchange *pDX)
{
	CDialog::DoDataExchange(pDX);
}

BOOL CUSBFilterEditorDlg::PreTranslateMessage(MSG* pMsg)
{
    if (::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))
    {
        return TRUE;        
    }

    return CDialog::PreTranslateMessage(pMsg);
}

BOOL CUSBFilterEditorDlg::DestroyWindow()
{
    DeleteAllCriterias();

    return CDialog::DestroyWindow();
}

// CUSBFilterEditorDlg message handlers

BOOL CUSBFilterEditorDlg::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

    m_hAccelTable = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDR_ACCELERATORS));
    ASSERT(m_hAccelTable != NULL);

    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    DWORD dwExtStyle = pCriterias->GetExtendedStyle();
    dwExtStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
    pCriterias->SetExtendedStyle(dwExtStyle);

    pCriterias->InsertColumn(0, _T(""), LVCFMT_LEFT, 10);
    pCriterias->InsertColumn(1, _T("Class"), LVCFMT_LEFT, 100);
    pCriterias->InsertColumn(2, _T("Vendor"), LVCFMT_LEFT, 120);
    pCriterias->InsertColumn(3, _T("Product"), LVCFMT_LEFT, 120);
    pCriterias->InsertColumn(4, _T("Revision"), LVCFMT_LEFT, 70);
    pCriterias->InsertColumn(5, _T("Action"), LVCFMT_LEFT, 50);

    LoadCriterias();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CUSBFilterEditorDlg::OnClose()
{
    int nStore = IDNO;

    if (m_bModified == true)
    {
        nStore = MessageBox(_T("The criterias were changed\n\nDo you want to save the changes?"),
            _T("Close Filter Editor"), MB_YESNOCANCEL);
    }

    if (nStore == IDYES)
    {
        StoreCriterias();
    }

    if (nStore != IDCANCEL)
    {
        CDialog::OnClose();
    }
}

// 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 CUSBFilterEditorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CUSBFilterEditorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CUSBFilterEditorDlg::OnBnClickedButtonAdd()
{
    CEditDeviceDlg dlg;

    if (dlg.DoModal() == IDOK)
    {
        CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
        ASSERT(pCriterias != NULL);

        InsertCriteria(pCriterias->GetItemCount(), dlg.m_nClassId,
            dlg.m_nVendorId, dlg.m_nProductId, dlg.m_nRevision,
            dlg.m_nAction);
    }
}

void CUSBFilterEditorDlg::OnBnClickedButtonSearch()
{
    CSearchDeviceDlg dlg;

    if (dlg.DoModal() == IDOK)
    {
        CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
        ASSERT(pCriterias != NULL);

        InsertCriteria(pCriterias->GetItemCount(), dlg.GetClassId(),
            dlg.GetVendorId(), dlg.GetProductId(), dlg.GetRevision(),
            dlg.GetAction());
    }
}

void CUSBFilterEditorDlg::ExportCriterias(const CString& sFileName)
{
    ASSERT(sFileName.IsEmpty() == FALSE);

    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    CString sCriterias;

    for (int nItem = 0; nItem < pCriterias->GetItemCount(); ++nItem)
    {
        CStringA *pData = reinterpret_cast<CStringA *>(pCriterias->GetItemData(nItem));
        ASSERT(pData != NULL);

        CString sData;
        sData.Format(_T("%S"), *pData);

        sCriterias.Append(sData);
        sCriterias.AppendChar('|');
    }

    if (sCriterias.IsEmpty() == FALSE)
    {
        // Remove the last '|' separator.
        sCriterias.Delete(sCriterias.GetLength() - 1);

        CStdioFile file(sFileName, CFile::modeWrite | CFile::modeCreate | CFile::typeText);
        file.WriteString(sCriterias);
    }
}

void CUSBFilterEditorDlg::ImportCriterias(const CString& sFileName)
{
    ASSERT(sFileName.IsEmpty() == FALSE);

    CStdioFile file(sFileName, CFile::modeRead | CFile::typeText);

    CString sCriterias;
    if (file.ReadString(sCriterias) && !sCriterias.IsEmpty())
    {
        CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
        ASSERT(pCriterias != NULL);

        DeleteAllCriterias();

        int i = sCriterias.Find(_T('|'));

        while (i != -1)
        {
            CStringA sCriteria;
            sCriteria.Format("%S", sCriterias.Left(i));

            InsertCriteria(pCriterias->GetItemCount(), sCriteria);

            sCriterias.Delete(0, i + 1);
            i = sCriterias.Find(_T('|'));
        }

        if (!sCriterias.IsEmpty())
        {
            CStringA sCriteria;
            sCriteria.Format("%S", sCriterias);

            InsertCriteria(pCriterias->GetItemCount(), sCriteria);
        }
    }
}

void CUSBFilterEditorDlg::LoadCriterias()
{
    sqlite3 *pDb = ((CUSBFilterEditorApp*)AfxGetApp())->GetEditorDb();
    sqlite3_stmt *pStmt = NULL;

    sqlite3_prepare16_v2(pDb, _T("SELECT C.Class, C.Vendor, C.Product, C.Revision, C.Action, ifnull(Classes.Name, 'ANY'), V.Name, P.Name FROM Criterias AS C LEFT OUTER JOIN Classes ON C.Class = Classes.Class LEFT OUTER JOIN Vendors AS V ON C.Vendor = V.Vendor LEFT OUTER JOIN Products AS P ON C.Vendor = P.Vendor AND C.Product = P.Product;"), -1, &pStmt, NULL);
    if (pStmt != NULL)
    {
        DeleteAllCriterias();

        CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
        ASSERT(pCriterias != NULL);

        int nItem = 0;

        while (sqlite3_step(pStmt) == SQLITE_ROW)
        {
            InsertCriteria(nItem++,
                sqlite3_column_int(pStmt, 0),
                sqlite3_column_int(pStmt, 1), sqlite3_column_int(pStmt, 2),
                sqlite3_column_int(pStmt, 3), sqlite3_column_int(pStmt, 4),
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 5)),
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 6)),
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 7)));
        }

        sqlite3_finalize(pStmt);
    }

    m_bModified = false;
}

void CUSBFilterEditorDlg::StoreCriterias()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    sqlite3 *pDb = ((CUSBFilterEditorApp*)AfxGetApp())->GetEditorDb();
    
    // Delete all criterias.
    sqlite3_exec(pDb, "DELETE FROM Criterias;", NULL, NULL, NULL);
    
    for (int nItem = 0; nItem < pCriterias->GetItemCount(); ++nItem)
    {
        CStringA *pData = reinterpret_cast<CStringA *>(pCriterias->GetItemData(nItem));
        ASSERT(pData != NULL);

        CStringA sInsert;
        sInsert.Format("INSERT INTO Criterias VALUES(%s);", *pData);

        sqlite3_exec(pDb, sInsert, NULL, NULL, NULL);
    }

    m_bModified = false;
}

void CUSBFilterEditorDlg::DeleteCriteria(int nItem)
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    CStringA *pData = reinterpret_cast<CStringA *>(pCriterias->GetItemData(nItem));
    ASSERT(pData != NULL);

    pCriterias->SetItemData(nItem, NULL);

    delete pData;
}

void CUSBFilterEditorDlg::DeleteAllCriterias()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    for (int nItem = 0; nItem < pCriterias->GetItemCount(); ++nItem)
    {
        DeleteCriteria(nItem);
    }

    VERIFY(pCriterias->DeleteAllItems());
}

void CUSBFilterEditorDlg::InsertCriteria(int nItem, LPCSTR szCriteria)
{
    int nClass, nVendor, nProduct, nRevision, nAction;

    if (sscanf_s(szCriteria, "%d,%d,%d,%d,%d", &nClass, &nVendor, &nProduct, &nRevision, &nAction) == 5)
    {
        InsertCriteria(nItem, nClass, nVendor, nProduct, nRevision, nAction);
    }
}

void CUSBFilterEditorDlg::InsertCriteria(int nItem,
                                         int nClass, int nVendor, int nProduct, int nRevision, int nAction)
{
    sqlite3 *pDb = ((CUSBFilterEditorApp*)AfxGetApp())->GetEditorDb();
    sqlite3_stmt *pStmt = NULL;

    CString sResolve;
    sResolve.Format(_T("SELECT DISTINCT ifnull(C.Name, 'ANY'), V.Name, P.Name FROM Criterias LEFT OUTER JOIN Classes AS C ON C.Class = %d LEFT OUTER JOIN Vendors AS V ON V.Vendor = %d LEFT OUTER JOIN Products AS P ON P.Vendor = %d AND P.Product = %d;"),
        nClass, nVendor,nVendor, nProduct);

    sqlite3_prepare16_v2(pDb, sResolve, -1, &pStmt, NULL);
    if (pStmt != NULL)
    {
        CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
        ASSERT(pCriterias != NULL);

        if (sqlite3_step(pStmt) == SQLITE_ROW)
        {
            InsertCriteria(nItem,
                nClass, nVendor, nProduct, nRevision, nAction,
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 0)),
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 1)),
                reinterpret_cast<LPCTSTR>(sqlite3_column_text16(pStmt, 2)));
        }

        sqlite3_finalize(pStmt);
    }
}

void CUSBFilterEditorDlg::InsertCriteria(int nItem,
                                         int nClass, int nVendor, int nProduct, int nRevision, int nAction,
                                         LPCTSTR szClass, LPCTSTR szVendor, LPCTSTR szProduct)
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    pCriterias->InsertItem(nItem, _T(""));

    CStringA *pData = new CStringA();
    pData->Format("%d,%d,%d,%d,%d", nClass, nVendor, nProduct,
        nRevision, nAction);

    pCriterias->SetItemData(nItem, reinterpret_cast<DWORD_PTR>(pData));

    CString sText;

    pCriterias->SetItemText(nItem, 1, szClass);

    if (nVendor == -1)
    {
        sText = _T("ANY");
    }
    else if (szVendor == NULL)
    {
        sText.Format(_T("0x%04x"), nVendor);
    }
    else
    {
        sText = szVendor;
    }
    
    pCriterias->SetItemText(nItem, 2, sText);

    if (nProduct == -1)
    {
        sText = _T("ANY");
    }
    else if (szProduct == NULL)
    {
        sText.Format(_T("0x%04x"), nProduct);
    }
    else
    {
        sText = szProduct;
    }

    pCriterias->SetItemText(nItem, 3, sText);

    if (nRevision == -1)
    {
        sText = _T("ANY");
    }
    else
    {
        sText.Format(_T("0x%04x"), nRevision);
    }
    
    pCriterias->SetItemText(nItem, 4, sText);

    sText = (nAction == 1) ? _T("Allow") : _T("Block");
    pCriterias->SetItemText(nItem, 5, sText);

    m_bModified = true;
}

void CUSBFilterEditorDlg::MoveCriteria(int nItem, int nStep)
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    CStringA *pData = reinterpret_cast<CStringA *>(pCriterias->GetItemData(nItem));
    ASSERT(pData != NULL);

    pCriterias->DeleteItem(nItem);

    int nMovedItem = nItem + nStep;

    InsertCriteria(nMovedItem, *pData);

    pCriterias->SetItemState(nMovedItem, LVIS_SELECTED, LVIS_SELECTED);
    ASSERT(pCriterias->GetItemState(nMovedItem, LVIS_SELECTED) == LVIS_SELECTED);

    delete pData;
}

void CUSBFilterEditorDlg::UpdateButtons(int nItem)
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    CWnd *pRemoveBtn = GetDlgItem(IDC_BUTTON_REMOVE);
    ASSERT(pRemoveBtn != NULL);

    pRemoveBtn->EnableWindow(pCriterias->GetFirstSelectedItemPosition() != NULL);

    CWnd *pUpBtn = GetDlgItem(IDC_BUTTON_UP);
    ASSERT(pUpBtn != NULL);

    pUpBtn->EnableWindow(nItem > 0);

    CWnd *pDownBtn = GetDlgItem(IDC_BUTTON_DOWN);
    ASSERT(pDownBtn != NULL);
    
    if (nItem == -1)
    {
        pDownBtn->EnableWindow(FALSE);
    }
    else
    {
        pDownBtn->EnableWindow(nItem < pCriterias->GetItemCount() - 1);
    }
}

void CUSBFilterEditorDlg::OnBnClickedButtonExport()
{
    CFileDialog dlg(FALSE, _T(".txt"), _T("usbfilter.txt"),
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
        _T("Text Documents (*.txt)|*.txt|All Files (*.*)|*.*||"));

    if (dlg.DoModal() == IDOK)
    {
        ExportCriterias(dlg.GetFileName());
    }
}

void CUSBFilterEditorDlg::OnBnClickedButtonImport()
{
    CFileDialog dlg(TRUE, _T(".txt"), _T("usbfilter.txt"),
        OFN_HIDEREADONLY | OFN_EXPLORER,
        _T("Text Documents (*.txt)|*.txt|All Files (*.*)|*.*||"));

    if (dlg.DoModal() == IDOK)
    {
        ImportCriterias(dlg.GetFileName());
    }
}

void CUSBFilterEditorDlg::OnHelpAbout()
{
    CAboutDlg dlg;
    dlg.DoModal();
}

void CUSBFilterEditorDlg::OnFileExit()
{
    SendMessage(WM_CLOSE);
}

void CUSBFilterEditorDlg::OnFileSave()
{
    StoreCriterias();
}

void CUSBFilterEditorDlg::OnBnClickedButtonUp()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    POSITION pos = pCriterias->GetFirstSelectedItemPosition();
    if (pos != NULL)
    {
        int nItem = pCriterias->GetNextSelectedItem(pos);

        if (nItem > 0)
        {
            MoveCriteria(nItem, -1);
            UpdateButtons(nItem - 1);
        }

        pCriterias->SetFocus();
    }
}

void CUSBFilterEditorDlg::OnBnClickedButtonDown()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    POSITION pos = pCriterias->GetFirstSelectedItemPosition();
    if (pos != NULL)
    {
        int nItem = pCriterias->GetNextSelectedItem(pos);
        
        if (nItem < (pCriterias->GetItemCount() - 1))
        {
            MoveCriteria(nItem, +1);
            UpdateButtons(nItem + 1);
        }

        pCriterias->SetFocus();
    }
}

void CUSBFilterEditorDlg::OnItemActivateListCriterias(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE phdr = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    
    UpdateButtons(phdr->iItem);

    *pResult = 0;
}

void CUSBFilterEditorDlg::OnNMRclickListCriterias(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE phdr = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);
   
    CMenu PopUp;
    VERIFY(PopUp.CreatePopupMenu());

    if (phdr->iItem != -1)
    {
        if (phdr->iItem > 0)
        {
            PopUp.AppendMenu(MF_STRING, IDC_BUTTON_UP, _T("Move Up"));
        }

        if (phdr->iItem < (pCriterias->GetItemCount() - 1))
        {
            PopUp.AppendMenu(MF_STRING, IDC_BUTTON_DOWN, _T("Move Down"));
        }

        PopUp.AppendMenu(MF_STRING, IDC_BUTTON_EDIT, _T("Edit..."));
        PopUp.AppendMenu(MF_STRING, IDC_BUTTON_REMOVE, _T("Remove"));
    }

    pCriterias->ClientToScreen(&phdr->ptAction);
    PopUp.TrackPopupMenu(0, phdr->ptAction.x, phdr->ptAction.y, this);

    *pResult = 0;
}

void CUSBFilterEditorDlg::OnBnClickedButtonEdit()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    POSITION pos = pCriterias->GetFirstSelectedItemPosition();
    if (pos != NULL)
    {
        CEditDeviceDlg dlg;

        int nItem = pCriterias->GetNextSelectedItem(pos);

        CStringA *pData = reinterpret_cast<CStringA *>(pCriterias->GetItemData(nItem));
        ASSERT(pData != NULL);

        sscanf_s(*pData, "%d,%d,%d,%d,%d", &dlg.m_nClassId, &dlg.m_nVendorId,
            &dlg.m_nProductId, &dlg.m_nRevision, &dlg.m_nAction);

        if (dlg.DoModal() == IDOK)
        {
            CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
            ASSERT(pCriterias != NULL);

            DeleteCriteria(nItem);
            pCriterias->DeleteItem(nItem);

            InsertCriteria(nItem, dlg.m_nClassId, dlg.m_nVendorId,
                dlg.m_nProductId, dlg.m_nRevision, dlg.m_nAction);
        }
    }
}

void CUSBFilterEditorDlg::OnBnClickedButtonRemove()
{
    CListCtrl *pCriterias = (CListCtrl *)GetDlgItem(IDC_LIST_CRITERIAS);
    ASSERT(pCriterias != NULL);

    POSITION pos = pCriterias->GetFirstSelectedItemPosition();
    if (pos != NULL)
    {
        int nItem = pCriterias->GetNextSelectedItem(pos);

        CString sConfirm;
        
        sConfirm = _T("Are you sure you want to remove \"");
        sConfirm += pCriterias->GetItemText(nItem, 2);
        sConfirm += _T(" - ");
        sConfirm += pCriterias->GetItemText(nItem, 3);
        sConfirm += _T("\"?");

        if (MessageBox(sConfirm, _T("Remove a Criteria"), MB_YESNO) == IDYES)
        {
            DeleteCriteria(nItem);

            pCriterias->DeleteItem(nItem);

            nItem -= 1;
            if (nItem < 0)
            {
                nItem = 0;
            }

            pCriterias->SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);
            pCriterias->SetFocus();
        }
    }
}
