//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1999 - 1999 // // File: notfywin.cpp // //-------------------------------------------------------------------------- // NotfyWin.cpp : implementation file // #include "stdafx.h" #include // PnP awareness #include // " " #include #include #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); }