Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

808 lines
20 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: ScInsDlg.cpp
//
//--------------------------------------------------------------------------
// ScInsDlg.cpp : implementation file
//
#include "stdafx.h"
#include <atlconv.h>
#include "resource.h"
#include "scdlg.h"
#include "ScSearch.h"
#include "ScInsDlg.h"
#include "statmon.h"
#include "scHlpArr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CScInsertDlg dialog
CScInsertDlg::CScInsertDlg(CWnd* pParent/*=NULL*/)
: CDialog(CScInsertDlg::IDD, pParent)
{
// Member Initialization
m_lLastError = SCARD_S_SUCCESS;
m_ParentHwnd = pParent;
m_pOCNW = NULL;
m_pOCNA = NULL;
m_pSelectedReader = NULL;
m_pSubDlg = NULL;
m_strTitle.Empty();
m_strPrompt.Empty();
m_mstrAllCards = "";
//{{AFX_DATA_INIT(CScInsertDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CScInsertDlg::~CScInsertDlg()
{
// Stop status monitor
m_monitor.Stop();
// Clean up status list!
if (0 != m_aReaderState.GetSize())
{
for (int i = (int)m_aReaderState.GetUpperBound(); i>=0; i--)
{
delete m_aReaderState[i];
}
m_aReaderState.RemoveAll();
}
}
void CScInsertDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CScInsertDlg)
DDX_Control(pDX, IDC_DETAILS, m_btnDetails);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CScInsertDlg, CDialog)
//{{AFX_MSG_MAP(CScInsertDlg)
ON_MESSAGE( WM_READERSTATUSCHANGE, OnReaderStatusChange )
ON_BN_CLICKED(IDC_DETAILS, OnDetails)
ON_WM_HELPINFO()
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CScInsertDlg data methods
/*++
LONG Initialize:
Stores the open card name pointer in the proper internal struct.
Determines whether to show the dialog in details or brief mode.
Arguments:
pOCN(x) - pointer to an open card name ex struct
Return Value:
A LONG value indicating the status of the requested action. Please
see the Smartcard header files for additional information.
Author:
Amanda Matlosz 07/09/1998
--*/
// ANSI
LONG CScInsertDlg::Initialize(LPOPENCARDNAMEA_EX pOCNA, DWORD dwNumOKCards, LPCSTR mszOKCards)
{
_ASSERTE(NULL != pOCNA);
if (NULL == pOCNA)
{
return SCARD_F_UNKNOWN_ERROR;
}
m_pOCNA = pOCNA;
m_strTitle = m_pOCNA->lpstrTitle;
m_strPrompt = m_pOCNA->lpstrSearchDesc;
m_mstrAllCards = mszOKCards;
m_hIcon = pOCNA->hIcon;
// hide details if no suitable cards available, else show details
m_fDetailsShown = (0==dwNumOKCards) ? FALSE : TRUE;
// prepare critical section for UI routines
m_pCritSec = new CCriticalSection();
if (NULL == m_pCritSec)
{
return ERROR_OUTOFMEMORY; // TODO: is another errorcode more appropriate?
}
// put dialog on top
SetForegroundWindow();
return SCARD_S_SUCCESS;
}
//UNICODE
HRESULT CScInsertDlg::Initialize(LPOPENCARDNAMEW_EX pOCNW, DWORD dwNumOKCards, LPCWSTR mszOKCards)
{
_ASSERTE(NULL != pOCNW);
if (NULL == pOCNW)
{
return SCARD_F_UNKNOWN_ERROR;
}
m_pOCNW = pOCNW;
m_strTitle = m_pOCNW->lpstrTitle;
m_strPrompt = m_pOCNW->lpstrSearchDesc;
m_mstrAllCards = mszOKCards;
m_hIcon = pOCNW->hIcon;
// hide details if no suitable cards available, else show details
m_fDetailsShown = (0==dwNumOKCards) ? FALSE : TRUE;
// prepare critical section for UI routines
m_pCritSec = new CCriticalSection();
if (NULL == m_pCritSec)
{
return ERROR_OUTOFMEMORY; // TODO: is another errorcode more appropriate?
}
// put dialog on top
SetForegroundWindow();
return SCARD_S_SUCCESS;
}
void CScInsertDlg::EnableOK(BOOL fEnabled)
{
CButton* pBtn = (CButton*)GetDlgItem(IDOK);
_ASSERTE(NULL != pBtn);
pBtn->EnableWindow(fEnabled);
//
// Change prompt text accordingly and set the OK button
// to be default if it's enabled
//
CString strPrompt;
if (fEnabled)
{
strPrompt.LoadString(IDS_SC_FOUND);
// set <OK> default, remove <Cancel> default
pBtn->SetButtonStyle(BS_DEFPUSHBUTTON);
pBtn = (CButton*)GetDlgItem(IDCANCEL);
_ASSERTE(NULL != pBtn);
pBtn->SetButtonStyle(BS_PUSHBUTTON);
pBtn = (CButton*)GetDlgItem(IDC_DETAILS); // details can sometimes get set to default
_ASSERTE(NULL != pBtn);
pBtn->SetButtonStyle(BS_PUSHBUTTON);
}
else
{
_ASSERTE(!m_strPrompt.IsEmpty());
strPrompt = m_strPrompt;
// remove <OK> default, set <Cancel> default
pBtn->SetButtonStyle(BS_PUSHBUTTON);
pBtn = (CButton*)GetDlgItem(IDCANCEL);
_ASSERTE(NULL != pBtn);
pBtn->SetButtonStyle(BS_DEFPUSHBUTTON);
pBtn = (CButton*)GetDlgItem(IDC_DETAILS); // details can sometimes get set to default
_ASSERTE(NULL != pBtn);
pBtn->SetButtonStyle(BS_PUSHBUTTON);
}
CWnd* pDlgItem = GetDlgItem(IDC_PROMPT);
_ASSERTE(NULL != pDlgItem);
pDlgItem->SetWindowText(strPrompt);
}
void CScInsertDlg::DisplayError(UINT uiErrorMsg)
{
CString strTitle, strMsg;
strTitle.LoadString(IDS_SC_TITLE_ERROR);
strMsg.LoadString(uiErrorMsg);
MessageBox(strMsg, strTitle, MB_OK | MB_ICONEXCLAMATION);
}
void CScInsertDlg::SetSelection(CSCardReaderState* pRdrSt)
{
m_pSelectedReader = pRdrSt;
EnableOK(IsSelectionOK());
}
BOOL CScInsertDlg::SameCard(CSCardReaderState* p1, CSCardReaderState* p2)
{
_ASSERTE(NULL != p1);
_ASSERTE(NULL != p2);
if ((NULL == p1) && (NULL == p2))
{
return TRUE;
}
if ((NULL == p1) || (NULL == p2))
{
return FALSE;
}
// same reader & card?
if ((0 == p1->strReader.Compare(p2->strReader)) &&
(0 == p1->strCard.Compare(p2->strCard)))
{
// no drastic state change?
if(p1->dwState == p2->dwState)
{
return TRUE;
}
if(((p1->dwState == SC_SATATUS_AVAILABLE) ||
(p1->dwState == SC_STATUS_SHARED) ||
(p1->dwState == SC_STATUS_EXCLUSIVE)) &&
((p2->dwState == SC_SATATUS_AVAILABLE) ||
(p2->dwState == SC_STATUS_SHARED) ||
(p2->dwState == SC_STATUS_EXCLUSIVE)) )
{
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CScInsertDlg message handlers
/*++
void ShowHelp:
Helper function for OnHelpInfo and OnContextMenu.
BOOL OnHelpInfo:
Called by the MFC framework when the user hits F1.
void OnContextMenu
Called by the MFC framework when the user right-clicks.
Author:
Amanda Matlosz 03/04/1999
Note:
These three functions work together to provide context-sensitive
help for the insertdlg. Similar functions are declared for
CScInsertBar
--*/
void CScInsertDlg::ShowHelp(HWND hWnd, UINT nCommand)
{
::WinHelp(hWnd, _T("SCardDlg.hlp"), nCommand, (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_SCARDDLG1);
}
afx_msg BOOL CScInsertDlg::OnHelpInfo(LPHELPINFO lpHelpInfo)
{
_ASSERTE(NULL != lpHelpInfo);
ShowHelp((HWND)lpHelpInfo->hItemHandle, HELP_WM_HELP);
return TRUE;
}
afx_msg void CScInsertDlg::OnContextMenu(CWnd* pWnd, CPoint pt)
{
_ASSERTE(NULL != pWnd);
ShowHelp(pWnd->m_hWnd, HELP_CONTEXTMENU);
}
/*++
void OnReaderStatusChange:
This message handler is called by the status thread when smartcard status
has changed.
Arguments:
None.
Return Value:
IGNORED BY CALLER. Long indicating status of ResMgr calls.
Author:
Amanda Matlosz 07/09/1998
Note:
No formal parameters are declared. These are not used and
will stop compiler warnings from being generated.
The long param takes the result of no_service or stopped
--*/
LONG CScInsertDlg::OnReaderStatusChange(UINT uint, LONG lParam)
{
// Is monitor still alive?
CScStatusMonitor::status status = m_monitor.GetStatus();
if (CScStatusMonitor::running != status)
{
m_pSubDlg->EnableStatusList(FALSE);
SetSelection(NULL); // JIC
// display appropriate error & set m_lLastError
switch(status)
{
case CScStatusMonitor::no_service:
case CScStatusMonitor::stopped:
m_lLastError = lParam;
DisplayError(IDS_SC_RM_ERR);
break;
case CScStatusMonitor::no_readers:
m_lLastError = SCARD_E_NO_READERS_AVAILABLE;
DisplayError(IDS_SC_NO_READERS);
break;
default:
m_lLastError = SCARD_F_UNKNOWN_ERROR;
DisplayError(IDS_UNKNOWN_ERROR);
break;
}
}
else
{
// crit section around member reader/card status array
_ASSERTE(m_pCritSec);
if (m_pCritSec)
{
m_pCritSec->Lock();
}
// make local copy of recent reader state array,
// so we know which cards have already been checked
CSCardReaderStateArray aPreviousReaderState;
aPreviousReaderState.RemoveAll();
for (int nCopy = (int)m_aReaderState.GetUpperBound(); nCopy>=0; nCopy--)
{
CSCardReaderState* pReader = NULL;
pReader = new CSCardReaderState(m_aReaderState[nCopy]);
if (NULL != pReader)
{
aPreviousReaderState.Add(pReader);
}
}
// udpate array from CStatusMonitor
// check cards that have not been previously checked,
// & update UI
m_monitor.GetReaderStatus(m_aReaderState);
for (int n = (int)m_aReaderState.GetUpperBound(); n>=0; n--)
{
CSCardReaderState* pReader = m_aReaderState[n];
BOOL fAlreadyChecked = FALSE;
// have we checked this card before?
for (int nPrev = (int)aPreviousReaderState.GetUpperBound();
(nPrev>=0 && !fAlreadyChecked);
nPrev--)
{
if (SameCard(pReader, aPreviousReaderState[nPrev]))
{
pReader->fOK = (aPreviousReaderState[nPrev])->fOK;
fAlreadyChecked = TRUE;
}
}
// if this is a new card, or if the card's status has changed
// drastically since we last looked at it, check it again
if (!fAlreadyChecked)
{
if (NULL != m_pOCNW)
{
m_aReaderState[n]->fOK = CheckCardAll(
m_aReaderState[n],
m_pOCNW,
(LPCWSTR)m_mstrAllCards);
}
else
{
_ASSERTE(NULL != m_pOCNA);
m_aReaderState[n]->fOK = CheckCardAll(
m_aReaderState[n],
m_pOCNA,
(LPCWSTR)m_mstrAllCards);
}
}
}
// the subdialog will handle automatic reader selection
m_pSubDlg->UpdateStatusList(&m_aReaderState);
// clean up
for (int nX = (int)aPreviousReaderState.GetUpperBound(); nX>=0; nX--)
{
delete aPreviousReaderState[nX];
}
aPreviousReaderState.RemoveAll();
// end crit section
if (m_pCritSec)
{
m_pCritSec->Unlock();
}
}
return (long)SCARD_S_SUCCESS; // there's no one to receive this.
}
void CScInsertDlg::OnDetails()
{
//
// If the details are currently shown, hide them...
// otherwise, show them.
//
CRect rectWin;
GetWindowRect(&rectWin);
CRect rectButtonBottom;
CString strDetailsCaption;
//
// Determine the new height of the dialog & resize
//
int nNewHeight = 0;
if (m_fDetailsShown)
{
nNewHeight = m_SmallHeight;
strDetailsCaption.LoadString(IDS_DETAILS_SHOW);
}
else
{
nNewHeight = m_BigHeight;
strDetailsCaption.LoadString(IDS_DETAILS_HIDE);
}
ScreenToClient(&rectButtonBottom);
rectWin.bottom = rectWin.top + nNewHeight;
SetWindowPos(NULL,
rectWin.left,
rectWin.top,
rectWin.Width(),
rectWin.Height(),
SWP_NOMOVE | SWP_NOZORDER);
//
// change captions, move buttons, show or hide the details section
//
m_btnDetails.SetWindowText(strDetailsCaption);
MoveButton(IDC_DETAILS, nNewHeight - m_yMargin);
MoveButton(IDOK, nNewHeight - m_yMargin);
MoveButton(IDCANCEL, nNewHeight - m_yMargin);
ToggleSubDialog();
//
// remember our new state
//
m_fDetailsShown = !m_fDetailsShown;
}
BOOL CScInsertDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//
// Initialize bits to query RM; if these fail, there's no point to go on
// but the user should see an error message.
//
// kick off CSCStatusMonitor
m_lLastError = m_monitor.Start(m_hWnd, WM_READERSTATUSCHANGE);
// if not running or no readers available
CScStatusMonitor::status status = m_monitor.GetStatus();
if (SCARD_S_SUCCESS != m_lLastError)
{
switch(status)
{
case CScStatusMonitor::no_service:
DisplayError(IDS_SC_RM_ERR);
break;
case CScStatusMonitor::no_readers:
// DisplayError(IDS_SC_NO_READERS); // Bug 15742 -> will die quietly (no UI)
break;
case CScStatusMonitor::running:
_ASSERTE(FALSE); // How can this be running if an error was returned??????
// no break; go ahead an report an 'unknown error'
default:
DisplayError(IDS_UNKNOWN_ERROR);
break;
}
PostMessage(WM_CLOSE, 0, 0);
return TRUE;
}
_ASSERTE(status == CScStatusMonitor::running);
//
// Determine constant offsets for resizing window (on details)
//
CRect rectWin, rectDlgItem;
GetWindowRect(&rectWin);
m_SmallHeight = rectWin.Height();
CWnd* pDlgItem = GetDlgItem(IDOK);
_ASSERTE(NULL != pDlgItem);
pDlgItem->GetWindowRect(&rectDlgItem);
ScreenToClient(rectDlgItem);
m_yMargin = m_SmallHeight - rectDlgItem.bottom;
pDlgItem = GetDlgItem(IDC_BUTTON_BOTTOM);
_ASSERTE(NULL != pDlgItem);
pDlgItem->GetWindowRect(&rectDlgItem);
ScreenToClient(rectDlgItem);
m_BigHeight = rectDlgItem.bottom + m_yMargin;
//
// Add user-provided or ReaderLoaded icon
//
if (NULL == m_hIcon)
{
m_hIcon = AfxGetApp()->LoadIcon(IDI_SC_READERLOADED_V2);
}
_ASSERTE(NULL != m_hIcon);
pDlgItem = GetDlgItem(IDC_USERICON);
_ASSERTE(NULL != pDlgItem);
pDlgItem->SetIcon(m_hIcon, TRUE); // TRUE: 32x32 icon
//
// Add other User-Customization bits
//
if (!m_strTitle.IsEmpty())
{
SetWindowText(m_strTitle);
}
if (m_strPrompt.IsEmpty())
{
// Use the default prompt text.
m_strPrompt.LoadString(IDS_SC_PROMPT_ANYCARD);
}
pDlgItem = GetDlgItem(IDC_PROMPT);
_ASSERTE(NULL != pDlgItem);
pDlgItem->SetWindowText(m_strPrompt);
// by default, <OK> is not enabled (subdlg's OnInitDlg might change that)
EnableOK(FALSE);
//
// Set HELP ID(s) for context help
//
pDlgItem = GetDlgItem(IDC_DETAILS);
_ASSERTE(NULL != pDlgItem);
pDlgItem->SetWindowContextHelpId(IDH_DLG1_DETAILS_BTN);
//
// Add CScInsertBar (actually, a CDialog-derivative) to our dialog
//
pDlgItem = GetDlgItem(IDC_DLGBAR);
_ASSERTE(NULL != pDlgItem);
pDlgItem->GetWindowRect(&rectDlgItem);
ScreenToClient(rectDlgItem);
m_pSubDlg = new CScInsertBar(this);
_ASSERTE(NULL != m_pSubDlg);
if (NULL == m_pSubDlg)
{
m_lLastError = ERROR_OUTOFMEMORY;
PostMessage(WM_CLOSE, 0, 0);
return TRUE;
}
m_pSubDlg->Create(IDD_SCARDDLG_BAR, this);
m_pSubDlg->SetWindowPos(NULL,
rectDlgItem.left,
rectDlgItem.top,
0,
0,
SWP_NOSIZE | SWP_NOACTIVATE); // TODO: SWP_NOZORDER ??
//
// Set the dialog to alter itself to match how it was called
//
m_fDetailsShown = !m_fDetailsShown;
OnDetails();
if (m_fDetailsShown)
{
return FALSE; // focus should be set to list control
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CScInsertDlg::MoveButton(UINT nID, int newBottom)
{
CWnd* pBtn = GetDlgItem(nID);
_ASSERTE(NULL != pBtn);
CRect rect;
pBtn->GetWindowRect(&rect);
ScreenToClient(&rect);
rect.top = newBottom - rect.Height();
pBtn->SetWindowPos(NULL,
rect.left,
rect.top,
0,
0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
}
void CScInsertDlg::ToggleSubDialog()
{
//
// All you need to do to toggle the sub dialog's accessibility
// is to hide&disable or show&enable the window.
//
if (m_fDetailsShown)
{
m_pSubDlg->ShowWindow(SW_HIDE);
m_pSubDlg->EnableWindow(FALSE);
}
else
{
m_pSubDlg->ShowWindow(SW_SHOW);
m_pSubDlg->EnableWindow(TRUE);
}
}
BOOL CScInsertDlg::DestroyWindow()
{
if (NULL != m_pSubDlg)
{
m_pSubDlg->DestroyWindow();
delete m_pSubDlg;
}
return CDialog::DestroyWindow();
}
/*++
void OnOK:
Handle user's <OK>, error if can't complete
Arguments:
None.
Return Value:
None
Author:
Amanda Matlosz 4/28/98
--*/
void CScInsertDlg::OnOK()
{
USES_CONVERSION;
// Must have something selected to exit
if (NULL == m_pSelectedReader || m_pSelectedReader->strCard.IsEmpty())
{
DisplayError(IDS_SC_SELECT);
return;
}
// Must have selected something we're looking for...
if (!(m_pSelectedReader->fOK))
{
DisplayError(IDS_SC_NOMATCH);
return;
}
// Call the correct method to set the *real* card selection
if(NULL != m_pOCNA)
{
LPSTR szCard = W2A(m_pSelectedReader->strCard);
LPSTR szReader = W2A(m_pSelectedReader->strReader);
m_lLastError = SetFinalCardSelection(szReader, szCard, m_pOCNA);
}
else
{
_ASSERTE(NULL != m_pOCNW);
LPWSTR szCard = m_pSelectedReader->strCard.GetBuffer(1);
LPWSTR szReader = m_pSelectedReader->strReader.GetBuffer(1);
m_lLastError = SetFinalCardSelection(szReader, szCard, m_pOCNW);
m_pSelectedReader->strCard.ReleaseBuffer();
m_pSelectedReader->strReader.ReleaseBuffer();
}
if (SCARD_S_SUCCESS != m_lLastError)
{
DisplayError(IDS_SC_CONNECT_FAILED); // Either connect failed or out of memory - close enough.
return;
}
CDialog::OnOK();
}