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.
 
 
 
 
 
 

1351 lines
30 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: notfywin.cpp
//
//--------------------------------------------------------------------------
// NotfyWin.cpp : implementation file
//
#include "stdafx.h"
#include <winsvc.h> // PnP awareness
#include <dbt.h> // " "
#include <mmsystem.h>
#include <scEvents.h>
#include "notfywin.h"
#include "SCAlert.h"
#include "miscdef.h"
#include "cmnstat.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// CNotifyWin Window
//
BEGIN_MESSAGE_MAP(CNotifyWin, CWnd)
//{{AFX_MSG_MAP(CNotifyWin)
ON_MESSAGE( WM_DEVICECHANGE, OnDeviceChange )
ON_MESSAGE( WM_SCARD_NOTIFY, OnSCardNotify )
ON_MESSAGE( WM_SCARD_STATUS_DLG_EXITED, OnSCardStatusDlgExit )
ON_MESSAGE( WM_SCARD_RESMGR_EXIT, OnResMgrExit )
ON_MESSAGE( WM_SCARD_RESMGR_STATUS, OnResMgrStatus )
ON_MESSAGE( WM_SCARD_NEWREADER, OnNewReader )
ON_MESSAGE( WM_SCARD_NEWREADER_EXIT, OnNewReaderExit )
ON_MESSAGE( WM_SCARD_CARDSTATUS, OnCardStatus )
ON_MESSAGE( WM_SCARD_CARDSTATUS_EXIT, OnCardStatusExit )
ON_MESSAGE( WM_SCARD_REMOPT_CHNG, OnRemovalOptionsChange )
ON_MESSAGE( WM_SCARD_REMOPT_EXIT, OnRemovalOptionsExit )
ON_COMMAND( IDM_CLOSE, OnContextClose )
ON_COMMAND( IDM_STATUS, OnContextStatus)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////////
//
// CNotifyWin Class
//
/*++
FinalConstruct:
This method implements the constructor for this window
Arguments:
None.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
BOOL CNotifyWin::FinalConstruct(void)
{
BOOL fResult = FALSE;
// Initialize
m_fCalaisUp = FALSE;
// Register a new class for this window
m_sClassName = AfxRegisterWndClass(CS_NOCLOSE);
// Load the context menu resource
fResult = m_ContextMenu.LoadMenu((UINT)IDR_STATUS_MENU);
return fResult;
}
/*++
FinalRelease:
This method implements the final destructor for this window
Arguments:
None.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
void CNotifyWin::FinalRelease( void )
{
//
// Clean up anything init'd in the FinalContruct(or)
//
m_ContextMenu.DestroyMenu();
}
/////////////////////////////////////////////////////////////////////////////
//
// CNotifyWin message handlers
//
/*++
void OnCreate:
Called after windows is created but before it is shown. Used here
to set task bar icon.
Arguments:
None.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
int CNotifyWin::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
BOOL fReturn = TRUE;
int nReturn = 0;
CString strStatusText;
try
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
throw (int)-1;
// Set the menu
if (!SetMenu(&m_ContextMenu))
{
throw (long)GetLastError();
}
// Set the task bar icon
m_pApp = (CSCStatusApp*)AfxGetApp();
ASSERT(NULL != m_pApp);
// Setup notify struct
ZeroMemory((PVOID)&m_nidIconData, sizeof(NOTIFYICONDATA));
m_nidIconData.cbSize = sizeof(NOTIFYICONDATA);
m_nidIconData.hWnd = m_hWnd;
m_nidIconData.uID = 1; // this is our #1 (only) icon
m_nidIconData.uFlags = 0
| NIF_ICON // The hIcon member is valid
| NIF_MESSAGE // The uCallbackMessage message is valid
| NIF_TIP; // The szTip member is valid
m_nidIconData.uCallbackMessage = WM_SCARD_NOTIFY;
m_nidIconData.hIcon = m_pApp->m_hIconCard; // this will be set later
strStatusText.LoadString(IDS_SYSTEM_UP);
lstrcpy(m_nidIconData.szTip, strStatusText);
if (!Shell_NotifyIcon(NIM_ADD, &m_nidIconData))
{
_ASSERTE(FALSE); // Why can't we modify the taskbar icon???
}
// Determine Smart Card service status (sets task bar icon & threads)
CheckSystemStatus(TRUE);
}
catch(long lErr)
{
nReturn = 0;
TRACE_CATCH_UNKNOWN(_T("OnCreate"));
}
catch(int nErr)
{
nReturn = nErr;
TRACE_CATCH_UNKNOWN(_T("OnCreate"));
}
return nReturn;
}
/*++
void OnContextClose:
This message handler is when the popup menu's Close is called
Arguments:
None.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
void CNotifyWin::OnContextClose( void )
{
//
// Remove task bar notification area icon first
//
if (!Shell_NotifyIcon(NIM_DELETE, &m_nidIconData))
{
_ASSERTE(FALSE); // the icon will be cleaned up when app exits, anyway
}
//
// Note that we're shutting down, so CheckSystemStatus will do no work.
//
m_fShutDown = TRUE;
//
// Shut down threads one at a time
//
m_ThreadLock.Lock();
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->Close();
DWORD dwRet = WaitForSingleObject(m_lpStatusDlgThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpStatusDlgThrd;
m_lpStatusDlgThrd = NULL;
}
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->Close();
DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpCardStatusThrd;
m_lpCardStatusThrd = NULL;
}
if (NULL != m_lpNewReaderThrd)
{
// signal m_lpNewReaderThrd to close
SetEvent(m_hKillNewReaderThrd);
DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpNewReaderThrd;
m_lpNewReaderThrd = NULL;
CloseHandle(m_hKillNewReaderThrd);
m_hKillNewReaderThrd = NULL;
}
if (NULL != m_lpRemOptThrd)
{
// signal m_lpRemOptThrd to close
SetEvent(m_hKillRemOptThrd);
DWORD dwRet = WaitForSingleObject(m_lpRemOptThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpRemOptThrd;
m_lpRemOptThrd = NULL;
CloseHandle(m_hKillRemOptThrd);
m_hKillRemOptThrd = NULL;
}
if (NULL != m_lpResMgrStsThrd)
{
// signal m_lpNewReaderThrd to close
SetEvent(m_hKillResMgrStatusThrd);
DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpResMgrStsThrd;
m_lpResMgrStsThrd = NULL;
CloseHandle(m_hKillResMgrStatusThrd);
m_hKillResMgrStatusThrd = NULL;
}
m_ThreadLock.Unlock();
// Post the quit message for this thread
::PostQuitMessage(0);
}
/*++
void OnContextStatus:
This message handler is when the popup menu's Status is called.
Thie displays the dialog.
Arguments:
None.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
void CNotifyWin::OnContextStatus( void )
{
if (!m_fCalaisUp)
{
// The user should not have been able to request "Status"
// when the system is down. Toss up an error...
AfxMessageBox(IDS_NO_SYSTEM_STATUS);
return;
}
//
// Start a thread for the status dialog if needed
//
m_ThreadLock.Lock();
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
}
if (m_lpStatusDlgThrd == NULL)
{
m_lpStatusDlgThrd = (CSCStatusDlgThrd*)AfxBeginThread(
RUNTIME_CLASS(CSCStatusDlgThrd),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->m_hCallbackWnd = m_hWnd;
m_lpStatusDlgThrd->ResumeThread();
m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
}
}
else
{
// ShowDialog should start the dialog if it's not currently open...
m_lpStatusDlgThrd->ShowDialog(SW_SHOWNORMAL, &m_aIdleList);
}
m_ThreadLock.Unlock();
}
/*++
void OnSCardNotify:
This message handler is called when action is taken on the task bar icon.
Arguments:
wParam - wparam of message
lParam - lparam of message.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
LONG CNotifyWin::OnSCardNotify( UINT wParam, LONG lParam)
{
// Locals
BOOL fResult = FALSE;
CMenu *pMenu = NULL;
POINT point;
try
{
// Switch on mouse button notification types.
switch ((UINT) lParam)
{
case WM_LBUTTONUP:
// same thing as if user selected context menu:Status
OnContextStatus();
break;
case WM_RBUTTONUP:
//
// Display context menu where user clicked
//
// Set the foregrouond window to fix menu track problem.
SetForegroundWindow();
fResult = GetCursorPos(&point);
if (fResult)
{
// Display the pop-up menu
pMenu = m_ContextMenu.GetSubMenu(0);
ASSERT(NULL != pMenu);
if (NULL != pMenu)
{
fResult = pMenu->TrackPopupMenu( TPM_RIGHTALIGN |
TPM_BOTTOMALIGN |
TPM_LEFTBUTTON |
TPM_RIGHTBUTTON,
point.x,
point.y,
this,
NULL);
}
}
if (!fResult)
{
throw (fResult);
}
// Force a task switch by sending message to fix menu track problem
PostMessage(WM_NULL);
break;
default:
break;
}
}
catch(LONG err)
{
TRACE_CATCH(_T("OnSCardNotify"),err);
}
catch(...)
{
TRACE_CATCH_UNKNOWN(_T("OnSCardNotify"));
}
return 0;
}
/*++
void OnSCardStatusDlgExit:
This message handler is called when the status dialog is closed.
Arguments:
wParam - wparam of message
lParam - lparam of message.
Return Value:
None
Author:
Chris Dudley 7/30/1997
Note:
--*/
LONG CNotifyWin::OnSCardStatusDlgExit( UINT, LONG )
{
m_ThreadLock.Lock();
// Clear for creation of another dialog
if (NULL != m_lpStatusDlgThrd)
{
DWORD dwRet = WaitForSingleObject(m_lpStatusDlgThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpStatusDlgThrd;
m_lpStatusDlgThrd = NULL;
}
m_ThreadLock.Unlock();
// Did the resource manager go down?
CheckSystemStatus();
return 0;
}
/*++
void OnResMgrExit:
This message handler signals "resmgr thread gone" & calls CheckSystemStatus
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnResMgrExit( UINT, LONG )
{
m_ThreadLock.Lock();
// close the killthread event handle
if (NULL != m_hKillResMgrStatusThrd)
{
CloseHandle(m_hKillResMgrStatusThrd);
m_hKillResMgrStatusThrd = NULL;
}
// delete the old (dead) thread
if (NULL != m_lpResMgrStsThrd)
{
DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpResMgrStsThrd;
m_lpResMgrStsThrd = NULL;
}
m_ThreadLock.Unlock();
// What is the status of the RM now?
CheckSystemStatus();
return 0;
}
/*++
void OnNewReaderExit:
This message handler signals "resmgr thread gone" & calls CheckSystemStatus
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnNewReaderExit( UINT, LONG )
{
m_ThreadLock.Lock();
// close the killthread event handle
if (NULL != m_hKillNewReaderThrd)
{
CloseHandle(m_hKillNewReaderThrd);
m_hKillNewReaderThrd = NULL;
}
// delete the old (dead) thread
if (NULL != m_lpNewReaderThrd)
{
DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpNewReaderThrd;
m_lpNewReaderThrd = NULL;
}
m_ThreadLock.Unlock();
// What is the status of the RM now?
CheckSystemStatus();
return 0;
}
/*++
void OnCardStatusExit:
This message handler signals "cardstatus thread gone" & calls CheckSystemStatus
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnCardStatusExit( UINT, LONG )
{
m_ThreadLock.Lock();
// Clear for creation of another CardStatusThrd
if (NULL != m_lpCardStatusThrd)
{
DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpCardStatusThrd;
m_lpCardStatusThrd = NULL;
}
m_ThreadLock.Unlock();
// What is the status of the RM now?
CheckSystemStatus();
return 0;
}
/*++
void OnResMgrStatus:
This message handler catches RM system status updates from the
ResMGrThread, and calls SetSystemStatus accordingly
Arguments:
ui - WPARAM (BOOL - true if calais is running)
l - not used.
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnResMgrStatus( UINT ui, LONG l)
{
// Is the resource manager back?
BOOL fCalaisUp = (ui != 0);
SetSystemStatus(fCalaisUp);
return 0;
}
/*++
void OnNewReader:
This message handler tells the two threads that use reader lists to
update those lists.
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnNewReader( UINT, LONG )
{
m_ThreadLock.Lock();
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->Update();
}
m_ThreadLock.Unlock();
return 0;
}
/*++
void OnCardStatus:
This message handler tells the two threads that use reader lists to
update those lists.
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnCardStatus( UINT uStatus, LONG )
{
bool fNotify = false;
//
// Need to notify user at end of OnCardStatus if a new card has gone IDLE
//
if (k_State_CardIdle == uStatus)
{
if (k_State_CardIdle != m_pApp->m_dwState)
{
fNotify = true;
}
else
{
CStringArray astrTemp;
m_ThreadLock.Lock();
{
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->CopyIdleList(&astrTemp);
}
}
m_ThreadLock.Unlock();
// compare new list of idle cards w/ current list
for (int n1=(int)astrTemp.GetUpperBound(); n1>=0; n1--)
{
for (int n2=(int)m_aIdleList.GetUpperBound(); n2>=0; n2--)
{
if (m_aIdleList[n2] == astrTemp[n1]) break;
}
if (n2<0) // a match was not found!
{
fNotify = true;
}
}
}
}
//
// At least, update the status dialog with the new idle list
//
m_ThreadLock.Lock();
{
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
}
}
}
m_ThreadLock.Unlock();
//
// Set the new status
//
SetSystemStatus(true, false, (DWORD)uStatus);
//
// If there is a newly idle card, notify user according to alert options
//
if(fNotify)
{
switch(m_pApp->m_dwAlertOption)
{
case k_AlertOption_IconOnly:
// Do nothing
break;
case k_AlertOption_IconSound:
// MessageBeep(MB_ICONINFORMATION);
PlaySound( TEXT("SmartcardIdle"), NULL, SND_ASYNC | SND_ALIAS | SND_NODEFAULT );
break;
case k_AlertOption_IconSoundMsg:
// MessageBeep(MB_ICONINFORMATION);
PlaySound( TEXT("SmartcardIdle"), NULL, SND_ASYNC | SND_ALIAS | SND_NODEFAULT );
case k_AlertOption_IconMsg:
OnContextStatus(); // raise status dialog
break;
default:
MessageBeep(MB_ICONQUESTION);
break;
}
}
return 0;
}
/*++
void OnRemovalOptionsChange:
This message handler tells the status dialog to update its
logon/lock reader designation
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnRemovalOptionsChange( UINT, LONG )
{
ASSERT(NULL != m_pApp);
//
// Need to update RemovalOptions
//
m_pApp->SetRemovalOptions();
//
// Tell stat dialog to update status if neccessary
//
m_ThreadLock.Lock();
{
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
}
}
}
m_ThreadLock.Unlock();
return 0;
}
/*++
void OnRemovalOptionsExit:
This message handler signals "remoptions thread gone" & calls CheckSystemStatus
Arguments:
Not Used
Return Value:
None
Author:
Amanda Matlosz 4/28/98
Note:
--*/
LONG CNotifyWin::OnRemovalOptionsExit( UINT, LONG )
{
m_ThreadLock.Lock();
// close the killthread event handle
if (NULL != m_hKillRemOptThrd)
{
CloseHandle(m_hKillRemOptThrd);
m_hKillRemOptThrd = NULL;
}
// delete the old (dead) thread
if (NULL != m_lpRemOptThrd)
{
DWORD dwRet = WaitForSingleObject(m_lpRemOptThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpRemOptThrd;
m_lpRemOptThrd = NULL;
}
m_ThreadLock.Unlock();
// What is the status of the RM now?
CheckSystemStatus();
return 0;
}
/*++
void SetSystemStatus:
This is called to set UI & behavior according to RM status.
Arguments:
fCalaisUp -- TRUE if the RM is running
Return Value:
None
Author:
Amanda Matlosz 5/28/98
Note:
--*/
void CNotifyWin::SetSystemStatus(BOOL fCalaisUp, BOOL fForceUpdate, DWORD dwState)
{
ASSERT(NULL != m_pApp);
//
// Update UI & behavior & threads only if there has actually been a change
//
if (!fForceUpdate && fCalaisUp == m_fCalaisUp && m_pApp->m_dwState == dwState)
{
return;
}
m_fCalaisUp = fCalaisUp;
if (dwState != k_State_Unknown)
{
m_pApp->m_dwState = dwState;
}
//
// Set appearance of taskbar icon
//
CString strStatusText;
if (!m_fCalaisUp)
{
// Get new icon & tooltip for taskbar
strStatusText.LoadString(IDS_SYSTEM_DOWN);
m_nidIconData.hIcon = m_pApp->m_hIconCalaisDown;
// disable "Status" Context menuitem
m_ContextMenu.EnableMenuItem(IDM_STATUS, MF_DISABLED | MF_GRAYED);
m_pApp->m_dwState = k_State_Unknown;
}
else
{
// Get new icon & tooltip for taskbar
strStatusText.LoadString(IDS_SYSTEM_UP);
switch(m_pApp->m_dwState)
{
case k_State_CardAvailable:
m_nidIconData.hIcon = m_pApp->m_hIconCard;
break;
case k_State_CardIdle:
m_nidIconData.hIcon = m_pApp->m_hIconCardInfo;
break;
default:
case k_State_NoCard:
m_nidIconData.hIcon = m_pApp->m_hIconRdrEmpty;
break;
}
// enable "Status" Context menuitem
m_ContextMenu.EnableMenuItem(IDM_STATUS, MF_ENABLED);
}
lstrcpy(m_nidIconData.szTip, strStatusText);
if (!Shell_NotifyIcon(NIM_MODIFY, &m_nidIconData))
{
_ASSERTE(FALSE); // Why can't we modify the taskbar icon???
// Ultimately, though, we don't care about this error.
}
//
// Start or stop threads as appropriate
//
m_ThreadLock.Lock();
// the RemoveOptionsChange thread should always be running
if (NULL == m_lpRemOptThrd)
{
// reset the KillThread event if possible; if not, recreate it.
if (NULL != m_hKillRemOptThrd)
{
// reset event to non-signalled
if (!ResetEvent(m_hKillRemOptThrd))
{
CloseHandle(m_hKillRemOptThrd);
m_hKillRemOptThrd = NULL;
}
}
if (NULL == m_hKillRemOptThrd)
{
m_hKillRemOptThrd = CreateEvent(
NULL,
TRUE, // must call ResetEvent() to set non-signaled
FALSE, // not signaled when it starts
NULL);
}
m_lpRemOptThrd = (CRemovalOptionsThrd*)AfxBeginThread(
RUNTIME_CLASS(CRemovalOptionsThrd),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
if (NULL != m_lpRemOptThrd)
{
m_lpRemOptThrd->m_hCallbackWnd = m_hWnd;
m_lpRemOptThrd->m_hKillThrd = m_hKillRemOptThrd;
m_lpRemOptThrd->ResumeThread();
}
}
if (!m_fCalaisUp)
{
if (NULL != m_lpNewReaderThrd)
{
// signal m_lpNewReaderThrd to close
SetEvent(m_hKillNewReaderThrd);
DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpNewReaderThrd;
m_lpNewReaderThrd = NULL;
CloseHandle(m_hKillNewReaderThrd);
m_hKillNewReaderThrd = NULL;
}
if (NULL != m_lpCardStatusThrd)
{
// close down m_lpCardStatusThrd
m_lpCardStatusThrd->Close();
DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpCardStatusThrd;
m_lpCardStatusThrd = NULL;
}
// Start ResMgrSts to poll/wait for RM startup
if (NULL == m_lpResMgrStsThrd)
{
// reset the KillThread event if possible; if not, recreate it.
if (NULL != m_hKillResMgrStatusThrd)
{
// reset event to non-signalled
if (!ResetEvent(m_hKillResMgrStatusThrd))
{
CloseHandle(m_hKillResMgrStatusThrd);
m_hKillResMgrStatusThrd = NULL;
}
}
if (NULL == m_hKillResMgrStatusThrd)
{
m_hKillResMgrStatusThrd = CreateEvent(
NULL,
TRUE, // must call ResetEvent() to set non-signaled
FALSE, // not signaled when it starts
NULL);
}
m_lpResMgrStsThrd = (CResMgrStatusThrd*)AfxBeginThread(
RUNTIME_CLASS(CResMgrStatusThrd),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
if (NULL != m_lpResMgrStsThrd)
{
m_lpResMgrStsThrd->m_hCallbackWnd = m_hWnd;
m_lpResMgrStsThrd->m_hKillThrd = m_hKillResMgrStatusThrd;
m_lpResMgrStsThrd->ResumeThread();
}
}
}
else
{
// shut down res mgr status thread
if (NULL != m_lpResMgrStsThrd)
{
// signal m_lpResMgrStsThrd to close
SetEvent(m_hKillResMgrStatusThrd);
DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
_ASSERTE(WAIT_OBJECT_0 == dwRet);
delete m_lpResMgrStsThrd;
m_lpResMgrStsThrd = NULL;
CloseHandle(m_hKillResMgrStatusThrd);
m_hKillResMgrStatusThrd = NULL;
}
// start newreader thread
if (NULL == m_lpNewReaderThrd)
{
// reset the KillThread event if possible; if not, recreate it.
if (NULL != m_hKillNewReaderThrd)
{
// reset event to non-signalled
if (!ResetEvent(m_hKillNewReaderThrd))
{
CloseHandle(m_hKillNewReaderThrd);
m_hKillNewReaderThrd = NULL;
}
}
if (NULL == m_hKillNewReaderThrd)
{
m_hKillNewReaderThrd = CreateEvent(
NULL,
TRUE, // must call ResetEvent() to set non-signaled
FALSE, // not signaled when it starts
NULL);
}
if (NULL != m_hKillNewReaderThrd)
{
m_lpNewReaderThrd = (CNewReaderThrd*)AfxBeginThread(
RUNTIME_CLASS(CNewReaderThrd),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
}
if (NULL != m_lpNewReaderThrd)
{
m_lpNewReaderThrd->m_hCallbackWnd = m_hWnd;
m_lpNewReaderThrd->m_hKillThrd = m_hKillNewReaderThrd;
m_lpNewReaderThrd->ResumeThread();
}
}
// start CardStatus thread
if (NULL == m_lpCardStatusThrd)
{
m_lpCardStatusThrd = (CCardStatusThrd*)AfxBeginThread(
RUNTIME_CLASS(CCardStatusThrd),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
if (NULL != m_lpCardStatusThrd)
{
m_lpCardStatusThrd->m_hCallbackWnd = m_hWnd;
m_lpCardStatusThrd->m_paIdleList = &m_aIdleList;
m_lpCardStatusThrd->m_pstrLogonReader = &(((CSCStatusApp*)AfxGetApp())->m_strLogonReader);
m_lpCardStatusThrd->ResumeThread();
}
}
else // better be NULL!
{
_ASSERTE(FALSE);
}
// StatDlg may need to be updated
if (NULL != m_lpStatusDlgThrd)
{
m_lpStatusDlgThrd->Update();
}
}
m_ThreadLock.Unlock();
}
/*++
void CheckSystemStatus:
This is called as a result of a thread exiting. Check to see whether the
MS Smart Card Resource Manager (Calais) is running or not, and set
UI & behavior accordingly.
Arguments:
None
Return Value:
None
Author:
Amanda Matlosz 3/18/98
Note:
--*/
void CNotifyWin::CheckSystemStatus(BOOL fForceUpdate)
{
//
// We only care about this status if we're
// NOT in the middle of shutting down
//
if (m_fShutDown)
{
return;
}
//
// Query the service manager for the RM's status
//
DWORD dwReturn = ERROR_SUCCESS;
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
SERVICE_STATUS ssStatus; // current status of the service
ZeroMemory((PVOID)&ssStatus, sizeof(ssStatus));
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_CONNECT); // access required
if (NULL == schSCManager)
{
dwReturn = (DWORD)GetLastError();
}
if (ERROR_SUCCESS == dwReturn)
{
schService = OpenService(
schSCManager,
TEXT("SCardSvr"),
SERVICE_QUERY_STATUS);
if (NULL == schService)
{
dwReturn = (DWORD)GetLastError();
}
else if (!QueryServiceStatus(schService, &ssStatus))
{
dwReturn = (DWORD)GetLastError();
}
}
// if the service is running, say it's up
// if the service is stopped, paused, or pending action,
// say it's down. NOTE: may want to consider graying out
// the taskbar icon to indicate paused, or some other err.
if (ERROR_SUCCESS == dwReturn)
{
if (SERVICE_RUNNING == ssStatus.dwCurrentState)
{
dwReturn = SCARD_S_SUCCESS;
}
else
{
dwReturn = SCARD_E_NO_SERVICE;
}
}
if (NULL != schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
if (NULL != schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
CalaisReleaseStartedEvent();
//
// Change state, log event as necessary,
// and kick off appropriate threads
//
SetSystemStatus((SCARD_S_SUCCESS == dwReturn), fForceUpdate);
}