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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: notfywin.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // NotfyWin.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include <winsvc.h> // PnP awareness
  14. #include <dbt.h> // " "
  15. #include <mmsystem.h>
  16. #include <scEvents.h>
  17. #include "notfywin.h"
  18. #include "SCAlert.h"
  19. #include "miscdef.h"
  20. #include "cmnstat.h"
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. /////////////////////////////////////////////////////////////////////////////
  27. //
  28. // CNotifyWin Window
  29. //
  30. BEGIN_MESSAGE_MAP(CNotifyWin, CWnd)
  31. //{{AFX_MSG_MAP(CNotifyWin)
  32. ON_MESSAGE( WM_DEVICECHANGE, OnDeviceChange )
  33. ON_MESSAGE( WM_SCARD_NOTIFY, OnSCardNotify )
  34. ON_MESSAGE( WM_SCARD_STATUS_DLG_EXITED, OnSCardStatusDlgExit )
  35. ON_MESSAGE( WM_SCARD_RESMGR_EXIT, OnResMgrExit )
  36. ON_MESSAGE( WM_SCARD_RESMGR_STATUS, OnResMgrStatus )
  37. ON_MESSAGE( WM_SCARD_NEWREADER, OnNewReader )
  38. ON_MESSAGE( WM_SCARD_NEWREADER_EXIT, OnNewReaderExit )
  39. ON_MESSAGE( WM_SCARD_CARDSTATUS, OnCardStatus )
  40. ON_MESSAGE( WM_SCARD_CARDSTATUS_EXIT, OnCardStatusExit )
  41. ON_MESSAGE( WM_SCARD_REMOPT_CHNG, OnRemovalOptionsChange )
  42. ON_MESSAGE( WM_SCARD_REMOPT_EXIT, OnRemovalOptionsExit )
  43. ON_COMMAND( IDM_CLOSE, OnContextClose )
  44. ON_COMMAND( IDM_STATUS, OnContextStatus)
  45. ON_WM_CREATE()
  46. //}}AFX_MSG_MAP
  47. END_MESSAGE_MAP()
  48. ////////////////////////////////////////////////////////////////////////////////////
  49. //
  50. // CNotifyWin Class
  51. //
  52. /*++
  53. FinalConstruct:
  54. This method implements the constructor for this window
  55. Arguments:
  56. None.
  57. Return Value:
  58. None
  59. Author:
  60. Chris Dudley 7/30/1997
  61. Note:
  62. --*/
  63. BOOL CNotifyWin::FinalConstruct(void)
  64. {
  65. BOOL fResult = FALSE;
  66. // Initialize
  67. m_fCalaisUp = FALSE;
  68. // Register a new class for this window
  69. m_sClassName = AfxRegisterWndClass(CS_NOCLOSE);
  70. // Load the context menu resource
  71. fResult = m_ContextMenu.LoadMenu((UINT)IDR_STATUS_MENU);
  72. return fResult;
  73. }
  74. /*++
  75. FinalRelease:
  76. This method implements the final destructor for this window
  77. Arguments:
  78. None.
  79. Return Value:
  80. None
  81. Author:
  82. Chris Dudley 7/30/1997
  83. Note:
  84. --*/
  85. void CNotifyWin::FinalRelease( void )
  86. {
  87. //
  88. // Clean up anything init'd in the FinalContruct(or)
  89. //
  90. m_ContextMenu.DestroyMenu();
  91. }
  92. /////////////////////////////////////////////////////////////////////////////
  93. //
  94. // CNotifyWin message handlers
  95. //
  96. /*++
  97. void OnCreate:
  98. Called after windows is created but before it is shown. Used here
  99. to set task bar icon.
  100. Arguments:
  101. None.
  102. Return Value:
  103. None
  104. Author:
  105. Chris Dudley 7/30/1997
  106. Note:
  107. --*/
  108. int CNotifyWin::OnCreate(LPCREATESTRUCT lpCreateStruct)
  109. {
  110. BOOL fReturn = TRUE;
  111. int nReturn = 0;
  112. CString strStatusText;
  113. try
  114. {
  115. if (CWnd::OnCreate(lpCreateStruct) == -1)
  116. throw (int)-1;
  117. // Set the menu
  118. if (!SetMenu(&m_ContextMenu))
  119. {
  120. throw (long)GetLastError();
  121. }
  122. // Set the task bar icon
  123. m_pApp = (CSCStatusApp*)AfxGetApp();
  124. ASSERT(NULL != m_pApp);
  125. // Setup notify struct
  126. ZeroMemory((PVOID)&m_nidIconData, sizeof(NOTIFYICONDATA));
  127. m_nidIconData.cbSize = sizeof(NOTIFYICONDATA);
  128. m_nidIconData.hWnd = m_hWnd;
  129. m_nidIconData.uID = 1; // this is our #1 (only) icon
  130. m_nidIconData.uFlags = 0
  131. | NIF_ICON // The hIcon member is valid
  132. | NIF_MESSAGE // The uCallbackMessage message is valid
  133. | NIF_TIP; // The szTip member is valid
  134. m_nidIconData.uCallbackMessage = WM_SCARD_NOTIFY;
  135. m_nidIconData.hIcon = m_pApp->m_hIconCard; // this will be set later
  136. strStatusText.LoadString(IDS_SYSTEM_UP);
  137. lstrcpy(m_nidIconData.szTip, strStatusText);
  138. if (!Shell_NotifyIcon(NIM_ADD, &m_nidIconData))
  139. {
  140. _ASSERTE(FALSE); // Why can't we modify the taskbar icon???
  141. }
  142. // Determine Smart Card service status (sets task bar icon & threads)
  143. CheckSystemStatus(TRUE);
  144. }
  145. catch(long lErr)
  146. {
  147. nReturn = 0;
  148. TRACE_CATCH_UNKNOWN(_T("OnCreate"));
  149. }
  150. catch(int nErr)
  151. {
  152. nReturn = nErr;
  153. TRACE_CATCH_UNKNOWN(_T("OnCreate"));
  154. }
  155. return nReturn;
  156. }
  157. /*++
  158. void OnContextClose:
  159. This message handler is when the popup menu's Close is called
  160. Arguments:
  161. None.
  162. Return Value:
  163. None
  164. Author:
  165. Chris Dudley 7/30/1997
  166. Note:
  167. --*/
  168. void CNotifyWin::OnContextClose( void )
  169. {
  170. //
  171. // Remove task bar notification area icon first
  172. //
  173. if (!Shell_NotifyIcon(NIM_DELETE, &m_nidIconData))
  174. {
  175. _ASSERTE(FALSE); // the icon will be cleaned up when app exits, anyway
  176. }
  177. //
  178. // Note that we're shutting down, so CheckSystemStatus will do no work.
  179. //
  180. m_fShutDown = TRUE;
  181. //
  182. // Shut down threads one at a time
  183. //
  184. m_ThreadLock.Lock();
  185. if (NULL != m_lpStatusDlgThrd)
  186. {
  187. m_lpStatusDlgThrd->Close();
  188. DWORD dwRet = WaitForSingleObject(m_lpStatusDlgThrd->m_hThread, INFINITE);
  189. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  190. delete m_lpStatusDlgThrd;
  191. m_lpStatusDlgThrd = NULL;
  192. }
  193. if (NULL != m_lpCardStatusThrd)
  194. {
  195. m_lpCardStatusThrd->Close();
  196. DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
  197. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  198. delete m_lpCardStatusThrd;
  199. m_lpCardStatusThrd = NULL;
  200. }
  201. if (NULL != m_lpNewReaderThrd)
  202. {
  203. // signal m_lpNewReaderThrd to close
  204. SetEvent(m_hKillNewReaderThrd);
  205. DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
  206. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  207. delete m_lpNewReaderThrd;
  208. m_lpNewReaderThrd = NULL;
  209. CloseHandle(m_hKillNewReaderThrd);
  210. m_hKillNewReaderThrd = NULL;
  211. }
  212. if (NULL != m_lpRemOptThrd)
  213. {
  214. // signal m_lpRemOptThrd to close
  215. SetEvent(m_hKillRemOptThrd);
  216. DWORD dwRet = WaitForSingleObject(m_lpRemOptThrd->m_hThread, INFINITE);
  217. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  218. delete m_lpRemOptThrd;
  219. m_lpRemOptThrd = NULL;
  220. CloseHandle(m_hKillRemOptThrd);
  221. m_hKillRemOptThrd = NULL;
  222. }
  223. if (NULL != m_lpResMgrStsThrd)
  224. {
  225. // signal m_lpNewReaderThrd to close
  226. SetEvent(m_hKillResMgrStatusThrd);
  227. DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
  228. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  229. delete m_lpResMgrStsThrd;
  230. m_lpResMgrStsThrd = NULL;
  231. CloseHandle(m_hKillResMgrStatusThrd);
  232. m_hKillResMgrStatusThrd = NULL;
  233. }
  234. m_ThreadLock.Unlock();
  235. // Post the quit message for this thread
  236. ::PostQuitMessage(0);
  237. }
  238. /*++
  239. void OnContextStatus:
  240. This message handler is when the popup menu's Status is called.
  241. Thie displays the dialog.
  242. Arguments:
  243. None.
  244. Return Value:
  245. None
  246. Author:
  247. Chris Dudley 7/30/1997
  248. Note:
  249. --*/
  250. void CNotifyWin::OnContextStatus( void )
  251. {
  252. if (!m_fCalaisUp)
  253. {
  254. // The user should not have been able to request "Status"
  255. // when the system is down. Toss up an error...
  256. AfxMessageBox(IDS_NO_SYSTEM_STATUS);
  257. return;
  258. }
  259. //
  260. // Start a thread for the status dialog if needed
  261. //
  262. m_ThreadLock.Lock();
  263. if (NULL != m_lpCardStatusThrd)
  264. {
  265. m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
  266. }
  267. if (m_lpStatusDlgThrd == NULL)
  268. {
  269. m_lpStatusDlgThrd = (CSCStatusDlgThrd*)AfxBeginThread(
  270. RUNTIME_CLASS(CSCStatusDlgThrd),
  271. THREAD_PRIORITY_NORMAL,
  272. 0,
  273. CREATE_SUSPENDED);
  274. if (NULL != m_lpStatusDlgThrd)
  275. {
  276. m_lpStatusDlgThrd->m_hCallbackWnd = m_hWnd;
  277. m_lpStatusDlgThrd->ResumeThread();
  278. m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
  279. }
  280. }
  281. else
  282. {
  283. // ShowDialog should start the dialog if it's not currently open...
  284. m_lpStatusDlgThrd->ShowDialog(SW_SHOWNORMAL, &m_aIdleList);
  285. }
  286. m_ThreadLock.Unlock();
  287. }
  288. /*++
  289. void OnSCardNotify:
  290. This message handler is called when action is taken on the task bar icon.
  291. Arguments:
  292. wParam - wparam of message
  293. lParam - lparam of message.
  294. Return Value:
  295. None
  296. Author:
  297. Chris Dudley 7/30/1997
  298. Note:
  299. --*/
  300. LONG CNotifyWin::OnSCardNotify( UINT wParam, LONG lParam)
  301. {
  302. // Locals
  303. BOOL fResult = FALSE;
  304. CMenu *pMenu = NULL;
  305. POINT point;
  306. try
  307. {
  308. // Switch on mouse button notification types.
  309. switch ((UINT) lParam)
  310. {
  311. case WM_LBUTTONUP:
  312. // same thing as if user selected context menu:Status
  313. OnContextStatus();
  314. break;
  315. case WM_RBUTTONUP:
  316. //
  317. // Display context menu where user clicked
  318. //
  319. // Set the foregrouond window to fix menu track problem.
  320. SetForegroundWindow();
  321. fResult = GetCursorPos(&point);
  322. if (fResult)
  323. {
  324. // Display the pop-up menu
  325. pMenu = m_ContextMenu.GetSubMenu(0);
  326. ASSERT(NULL != pMenu);
  327. if (NULL != pMenu)
  328. {
  329. fResult = pMenu->TrackPopupMenu( TPM_RIGHTALIGN |
  330. TPM_BOTTOMALIGN |
  331. TPM_LEFTBUTTON |
  332. TPM_RIGHTBUTTON,
  333. point.x,
  334. point.y,
  335. this,
  336. NULL);
  337. }
  338. }
  339. if (!fResult)
  340. {
  341. throw (fResult);
  342. }
  343. // Force a task switch by sending message to fix menu track problem
  344. PostMessage(WM_NULL);
  345. break;
  346. default:
  347. break;
  348. }
  349. }
  350. catch(LONG err)
  351. {
  352. TRACE_CATCH(_T("OnSCardNotify"),err);
  353. }
  354. catch(...)
  355. {
  356. TRACE_CATCH_UNKNOWN(_T("OnSCardNotify"));
  357. }
  358. return 0;
  359. }
  360. /*++
  361. void OnSCardStatusDlgExit:
  362. This message handler is called when the status dialog is closed.
  363. Arguments:
  364. wParam - wparam of message
  365. lParam - lparam of message.
  366. Return Value:
  367. None
  368. Author:
  369. Chris Dudley 7/30/1997
  370. Note:
  371. --*/
  372. LONG CNotifyWin::OnSCardStatusDlgExit( UINT, LONG )
  373. {
  374. m_ThreadLock.Lock();
  375. // Clear for creation of another dialog
  376. if (NULL != m_lpStatusDlgThrd)
  377. {
  378. DWORD dwRet = WaitForSingleObject(m_lpStatusDlgThrd->m_hThread, INFINITE);
  379. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  380. delete m_lpStatusDlgThrd;
  381. m_lpStatusDlgThrd = NULL;
  382. }
  383. m_ThreadLock.Unlock();
  384. // Did the resource manager go down?
  385. CheckSystemStatus();
  386. return 0;
  387. }
  388. /*++
  389. void OnResMgrExit:
  390. This message handler signals "resmgr thread gone" & calls CheckSystemStatus
  391. Arguments:
  392. Not Used
  393. Return Value:
  394. None
  395. Author:
  396. Amanda Matlosz 4/28/98
  397. Note:
  398. --*/
  399. LONG CNotifyWin::OnResMgrExit( UINT, LONG )
  400. {
  401. m_ThreadLock.Lock();
  402. // close the killthread event handle
  403. if (NULL != m_hKillResMgrStatusThrd)
  404. {
  405. CloseHandle(m_hKillResMgrStatusThrd);
  406. m_hKillResMgrStatusThrd = NULL;
  407. }
  408. // delete the old (dead) thread
  409. if (NULL != m_lpResMgrStsThrd)
  410. {
  411. DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
  412. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  413. delete m_lpResMgrStsThrd;
  414. m_lpResMgrStsThrd = NULL;
  415. }
  416. m_ThreadLock.Unlock();
  417. // What is the status of the RM now?
  418. CheckSystemStatus();
  419. return 0;
  420. }
  421. /*++
  422. void OnNewReaderExit:
  423. This message handler signals "resmgr thread gone" & calls CheckSystemStatus
  424. Arguments:
  425. Not Used
  426. Return Value:
  427. None
  428. Author:
  429. Amanda Matlosz 4/28/98
  430. Note:
  431. --*/
  432. LONG CNotifyWin::OnNewReaderExit( UINT, LONG )
  433. {
  434. m_ThreadLock.Lock();
  435. // close the killthread event handle
  436. if (NULL != m_hKillNewReaderThrd)
  437. {
  438. CloseHandle(m_hKillNewReaderThrd);
  439. m_hKillNewReaderThrd = NULL;
  440. }
  441. // delete the old (dead) thread
  442. if (NULL != m_lpNewReaderThrd)
  443. {
  444. DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
  445. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  446. delete m_lpNewReaderThrd;
  447. m_lpNewReaderThrd = NULL;
  448. }
  449. m_ThreadLock.Unlock();
  450. // What is the status of the RM now?
  451. CheckSystemStatus();
  452. return 0;
  453. }
  454. /*++
  455. void OnCardStatusExit:
  456. This message handler signals "cardstatus thread gone" & calls CheckSystemStatus
  457. Arguments:
  458. Not Used
  459. Return Value:
  460. None
  461. Author:
  462. Amanda Matlosz 4/28/98
  463. Note:
  464. --*/
  465. LONG CNotifyWin::OnCardStatusExit( UINT, LONG )
  466. {
  467. m_ThreadLock.Lock();
  468. // Clear for creation of another CardStatusThrd
  469. if (NULL != m_lpCardStatusThrd)
  470. {
  471. DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
  472. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  473. delete m_lpCardStatusThrd;
  474. m_lpCardStatusThrd = NULL;
  475. }
  476. m_ThreadLock.Unlock();
  477. // What is the status of the RM now?
  478. CheckSystemStatus();
  479. return 0;
  480. }
  481. /*++
  482. void OnResMgrStatus:
  483. This message handler catches RM system status updates from the
  484. ResMGrThread, and calls SetSystemStatus accordingly
  485. Arguments:
  486. ui - WPARAM (BOOL - true if calais is running)
  487. l - not used.
  488. Return Value:
  489. None
  490. Author:
  491. Amanda Matlosz 4/28/98
  492. Note:
  493. --*/
  494. LONG CNotifyWin::OnResMgrStatus( UINT ui, LONG l)
  495. {
  496. // Is the resource manager back?
  497. BOOL fCalaisUp = (ui != 0);
  498. SetSystemStatus(fCalaisUp);
  499. return 0;
  500. }
  501. /*++
  502. void OnNewReader:
  503. This message handler tells the two threads that use reader lists to
  504. update those lists.
  505. Arguments:
  506. Not Used
  507. Return Value:
  508. None
  509. Author:
  510. Amanda Matlosz 4/28/98
  511. Note:
  512. --*/
  513. LONG CNotifyWin::OnNewReader( UINT, LONG )
  514. {
  515. m_ThreadLock.Lock();
  516. if (NULL != m_lpStatusDlgThrd)
  517. {
  518. m_lpStatusDlgThrd->Update();
  519. }
  520. m_ThreadLock.Unlock();
  521. return 0;
  522. }
  523. /*++
  524. void OnCardStatus:
  525. This message handler tells the two threads that use reader lists to
  526. update those lists.
  527. Arguments:
  528. Not Used
  529. Return Value:
  530. None
  531. Author:
  532. Amanda Matlosz 4/28/98
  533. Note:
  534. --*/
  535. LONG CNotifyWin::OnCardStatus( UINT uStatus, LONG )
  536. {
  537. bool fNotify = false;
  538. //
  539. // Need to notify user at end of OnCardStatus if a new card has gone IDLE
  540. //
  541. if (k_State_CardIdle == uStatus)
  542. {
  543. if (k_State_CardIdle != m_pApp->m_dwState)
  544. {
  545. fNotify = true;
  546. }
  547. else
  548. {
  549. CStringArray astrTemp;
  550. m_ThreadLock.Lock();
  551. {
  552. if (NULL != m_lpCardStatusThrd)
  553. {
  554. m_lpCardStatusThrd->CopyIdleList(&astrTemp);
  555. }
  556. }
  557. m_ThreadLock.Unlock();
  558. // compare new list of idle cards w/ current list
  559. for (int n1=(int)astrTemp.GetUpperBound(); n1>=0; n1--)
  560. {
  561. for (int n2=(int)m_aIdleList.GetUpperBound(); n2>=0; n2--)
  562. {
  563. if (m_aIdleList[n2] == astrTemp[n1]) break;
  564. }
  565. if (n2<0) // a match was not found!
  566. {
  567. fNotify = true;
  568. }
  569. }
  570. }
  571. }
  572. //
  573. // At least, update the status dialog with the new idle list
  574. //
  575. m_ThreadLock.Lock();
  576. {
  577. if (NULL != m_lpCardStatusThrd)
  578. {
  579. m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
  580. if (NULL != m_lpStatusDlgThrd)
  581. {
  582. m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
  583. }
  584. }
  585. }
  586. m_ThreadLock.Unlock();
  587. //
  588. // Set the new status
  589. //
  590. SetSystemStatus(true, false, (DWORD)uStatus);
  591. //
  592. // If there is a newly idle card, notify user according to alert options
  593. //
  594. if(fNotify)
  595. {
  596. switch(m_pApp->m_dwAlertOption)
  597. {
  598. case k_AlertOption_IconOnly:
  599. // Do nothing
  600. break;
  601. case k_AlertOption_IconSound:
  602. // MessageBeep(MB_ICONINFORMATION);
  603. PlaySound( TEXT("SmartcardIdle"), NULL, SND_ASYNC | SND_ALIAS | SND_NODEFAULT );
  604. break;
  605. case k_AlertOption_IconSoundMsg:
  606. // MessageBeep(MB_ICONINFORMATION);
  607. PlaySound( TEXT("SmartcardIdle"), NULL, SND_ASYNC | SND_ALIAS | SND_NODEFAULT );
  608. case k_AlertOption_IconMsg:
  609. OnContextStatus(); // raise status dialog
  610. break;
  611. default:
  612. MessageBeep(MB_ICONQUESTION);
  613. break;
  614. }
  615. }
  616. return 0;
  617. }
  618. /*++
  619. void OnRemovalOptionsChange:
  620. This message handler tells the status dialog to update its
  621. logon/lock reader designation
  622. Arguments:
  623. Not Used
  624. Return Value:
  625. None
  626. Author:
  627. Amanda Matlosz 4/28/98
  628. Note:
  629. --*/
  630. LONG CNotifyWin::OnRemovalOptionsChange( UINT, LONG )
  631. {
  632. ASSERT(NULL != m_pApp);
  633. //
  634. // Need to update RemovalOptions
  635. //
  636. m_pApp->SetRemovalOptions();
  637. //
  638. // Tell stat dialog to update status if neccessary
  639. //
  640. m_ThreadLock.Lock();
  641. {
  642. if (NULL != m_lpCardStatusThrd)
  643. {
  644. m_lpCardStatusThrd->CopyIdleList(&m_aIdleList);
  645. if (NULL != m_lpStatusDlgThrd)
  646. {
  647. m_lpStatusDlgThrd->UpdateStatus(&m_aIdleList);
  648. }
  649. }
  650. }
  651. m_ThreadLock.Unlock();
  652. return 0;
  653. }
  654. /*++
  655. void OnRemovalOptionsExit:
  656. This message handler signals "remoptions thread gone" & calls CheckSystemStatus
  657. Arguments:
  658. Not Used
  659. Return Value:
  660. None
  661. Author:
  662. Amanda Matlosz 4/28/98
  663. Note:
  664. --*/
  665. LONG CNotifyWin::OnRemovalOptionsExit( UINT, LONG )
  666. {
  667. m_ThreadLock.Lock();
  668. // close the killthread event handle
  669. if (NULL != m_hKillRemOptThrd)
  670. {
  671. CloseHandle(m_hKillRemOptThrd);
  672. m_hKillRemOptThrd = NULL;
  673. }
  674. // delete the old (dead) thread
  675. if (NULL != m_lpRemOptThrd)
  676. {
  677. DWORD dwRet = WaitForSingleObject(m_lpRemOptThrd->m_hThread, INFINITE);
  678. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  679. delete m_lpRemOptThrd;
  680. m_lpRemOptThrd = NULL;
  681. }
  682. m_ThreadLock.Unlock();
  683. // What is the status of the RM now?
  684. CheckSystemStatus();
  685. return 0;
  686. }
  687. /*++
  688. void SetSystemStatus:
  689. This is called to set UI & behavior according to RM status.
  690. Arguments:
  691. fCalaisUp -- TRUE if the RM is running
  692. Return Value:
  693. None
  694. Author:
  695. Amanda Matlosz 5/28/98
  696. Note:
  697. --*/
  698. void CNotifyWin::SetSystemStatus(BOOL fCalaisUp, BOOL fForceUpdate, DWORD dwState)
  699. {
  700. ASSERT(NULL != m_pApp);
  701. //
  702. // Update UI & behavior & threads only if there has actually been a change
  703. //
  704. if (!fForceUpdate && fCalaisUp == m_fCalaisUp && m_pApp->m_dwState == dwState)
  705. {
  706. return;
  707. }
  708. m_fCalaisUp = fCalaisUp;
  709. if (dwState != k_State_Unknown)
  710. {
  711. m_pApp->m_dwState = dwState;
  712. }
  713. //
  714. // Set appearance of taskbar icon
  715. //
  716. CString strStatusText;
  717. if (!m_fCalaisUp)
  718. {
  719. // Get new icon & tooltip for taskbar
  720. strStatusText.LoadString(IDS_SYSTEM_DOWN);
  721. m_nidIconData.hIcon = m_pApp->m_hIconCalaisDown;
  722. // disable "Status" Context menuitem
  723. m_ContextMenu.EnableMenuItem(IDM_STATUS, MF_DISABLED | MF_GRAYED);
  724. m_pApp->m_dwState = k_State_Unknown;
  725. }
  726. else
  727. {
  728. // Get new icon & tooltip for taskbar
  729. strStatusText.LoadString(IDS_SYSTEM_UP);
  730. switch(m_pApp->m_dwState)
  731. {
  732. case k_State_CardAvailable:
  733. m_nidIconData.hIcon = m_pApp->m_hIconCard;
  734. break;
  735. case k_State_CardIdle:
  736. m_nidIconData.hIcon = m_pApp->m_hIconCardInfo;
  737. break;
  738. default:
  739. case k_State_NoCard:
  740. m_nidIconData.hIcon = m_pApp->m_hIconRdrEmpty;
  741. break;
  742. }
  743. // enable "Status" Context menuitem
  744. m_ContextMenu.EnableMenuItem(IDM_STATUS, MF_ENABLED);
  745. }
  746. lstrcpy(m_nidIconData.szTip, strStatusText);
  747. if (!Shell_NotifyIcon(NIM_MODIFY, &m_nidIconData))
  748. {
  749. _ASSERTE(FALSE); // Why can't we modify the taskbar icon???
  750. // Ultimately, though, we don't care about this error.
  751. }
  752. //
  753. // Start or stop threads as appropriate
  754. //
  755. m_ThreadLock.Lock();
  756. // the RemoveOptionsChange thread should always be running
  757. if (NULL == m_lpRemOptThrd)
  758. {
  759. // reset the KillThread event if possible; if not, recreate it.
  760. if (NULL != m_hKillRemOptThrd)
  761. {
  762. // reset event to non-signalled
  763. if (!ResetEvent(m_hKillRemOptThrd))
  764. {
  765. CloseHandle(m_hKillRemOptThrd);
  766. m_hKillRemOptThrd = NULL;
  767. }
  768. }
  769. if (NULL == m_hKillRemOptThrd)
  770. {
  771. m_hKillRemOptThrd = CreateEvent(
  772. NULL,
  773. TRUE, // must call ResetEvent() to set non-signaled
  774. FALSE, // not signaled when it starts
  775. NULL);
  776. }
  777. m_lpRemOptThrd = (CRemovalOptionsThrd*)AfxBeginThread(
  778. RUNTIME_CLASS(CRemovalOptionsThrd),
  779. THREAD_PRIORITY_NORMAL,
  780. 0,
  781. CREATE_SUSPENDED);
  782. if (NULL != m_lpRemOptThrd)
  783. {
  784. m_lpRemOptThrd->m_hCallbackWnd = m_hWnd;
  785. m_lpRemOptThrd->m_hKillThrd = m_hKillRemOptThrd;
  786. m_lpRemOptThrd->ResumeThread();
  787. }
  788. }
  789. if (!m_fCalaisUp)
  790. {
  791. if (NULL != m_lpNewReaderThrd)
  792. {
  793. // signal m_lpNewReaderThrd to close
  794. SetEvent(m_hKillNewReaderThrd);
  795. DWORD dwRet = WaitForSingleObject(m_lpNewReaderThrd->m_hThread, INFINITE);
  796. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  797. delete m_lpNewReaderThrd;
  798. m_lpNewReaderThrd = NULL;
  799. CloseHandle(m_hKillNewReaderThrd);
  800. m_hKillNewReaderThrd = NULL;
  801. }
  802. if (NULL != m_lpCardStatusThrd)
  803. {
  804. // close down m_lpCardStatusThrd
  805. m_lpCardStatusThrd->Close();
  806. DWORD dwRet = WaitForSingleObject(m_lpCardStatusThrd->m_hThread, INFINITE);
  807. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  808. delete m_lpCardStatusThrd;
  809. m_lpCardStatusThrd = NULL;
  810. }
  811. // Start ResMgrSts to poll/wait for RM startup
  812. if (NULL == m_lpResMgrStsThrd)
  813. {
  814. // reset the KillThread event if possible; if not, recreate it.
  815. if (NULL != m_hKillResMgrStatusThrd)
  816. {
  817. // reset event to non-signalled
  818. if (!ResetEvent(m_hKillResMgrStatusThrd))
  819. {
  820. CloseHandle(m_hKillResMgrStatusThrd);
  821. m_hKillResMgrStatusThrd = NULL;
  822. }
  823. }
  824. if (NULL == m_hKillResMgrStatusThrd)
  825. {
  826. m_hKillResMgrStatusThrd = CreateEvent(
  827. NULL,
  828. TRUE, // must call ResetEvent() to set non-signaled
  829. FALSE, // not signaled when it starts
  830. NULL);
  831. }
  832. m_lpResMgrStsThrd = (CResMgrStatusThrd*)AfxBeginThread(
  833. RUNTIME_CLASS(CResMgrStatusThrd),
  834. THREAD_PRIORITY_NORMAL,
  835. 0,
  836. CREATE_SUSPENDED);
  837. if (NULL != m_lpResMgrStsThrd)
  838. {
  839. m_lpResMgrStsThrd->m_hCallbackWnd = m_hWnd;
  840. m_lpResMgrStsThrd->m_hKillThrd = m_hKillResMgrStatusThrd;
  841. m_lpResMgrStsThrd->ResumeThread();
  842. }
  843. }
  844. }
  845. else
  846. {
  847. // shut down res mgr status thread
  848. if (NULL != m_lpResMgrStsThrd)
  849. {
  850. // signal m_lpResMgrStsThrd to close
  851. SetEvent(m_hKillResMgrStatusThrd);
  852. DWORD dwRet = WaitForSingleObject(m_lpResMgrStsThrd->m_hThread, INFINITE);
  853. _ASSERTE(WAIT_OBJECT_0 == dwRet);
  854. delete m_lpResMgrStsThrd;
  855. m_lpResMgrStsThrd = NULL;
  856. CloseHandle(m_hKillResMgrStatusThrd);
  857. m_hKillResMgrStatusThrd = NULL;
  858. }
  859. // start newreader thread
  860. if (NULL == m_lpNewReaderThrd)
  861. {
  862. // reset the KillThread event if possible; if not, recreate it.
  863. if (NULL != m_hKillNewReaderThrd)
  864. {
  865. // reset event to non-signalled
  866. if (!ResetEvent(m_hKillNewReaderThrd))
  867. {
  868. CloseHandle(m_hKillNewReaderThrd);
  869. m_hKillNewReaderThrd = NULL;
  870. }
  871. }
  872. if (NULL == m_hKillNewReaderThrd)
  873. {
  874. m_hKillNewReaderThrd = CreateEvent(
  875. NULL,
  876. TRUE, // must call ResetEvent() to set non-signaled
  877. FALSE, // not signaled when it starts
  878. NULL);
  879. }
  880. if (NULL != m_hKillNewReaderThrd)
  881. {
  882. m_lpNewReaderThrd = (CNewReaderThrd*)AfxBeginThread(
  883. RUNTIME_CLASS(CNewReaderThrd),
  884. THREAD_PRIORITY_NORMAL,
  885. 0,
  886. CREATE_SUSPENDED);
  887. }
  888. if (NULL != m_lpNewReaderThrd)
  889. {
  890. m_lpNewReaderThrd->m_hCallbackWnd = m_hWnd;
  891. m_lpNewReaderThrd->m_hKillThrd = m_hKillNewReaderThrd;
  892. m_lpNewReaderThrd->ResumeThread();
  893. }
  894. }
  895. // start CardStatus thread
  896. if (NULL == m_lpCardStatusThrd)
  897. {
  898. m_lpCardStatusThrd = (CCardStatusThrd*)AfxBeginThread(
  899. RUNTIME_CLASS(CCardStatusThrd),
  900. THREAD_PRIORITY_NORMAL,
  901. 0,
  902. CREATE_SUSPENDED);
  903. if (NULL != m_lpCardStatusThrd)
  904. {
  905. m_lpCardStatusThrd->m_hCallbackWnd = m_hWnd;
  906. m_lpCardStatusThrd->m_paIdleList = &m_aIdleList;
  907. m_lpCardStatusThrd->m_pstrLogonReader = &(((CSCStatusApp*)AfxGetApp())->m_strLogonReader);
  908. m_lpCardStatusThrd->ResumeThread();
  909. }
  910. }
  911. else // better be NULL!
  912. {
  913. _ASSERTE(FALSE);
  914. }
  915. // StatDlg may need to be updated
  916. if (NULL != m_lpStatusDlgThrd)
  917. {
  918. m_lpStatusDlgThrd->Update();
  919. }
  920. }
  921. m_ThreadLock.Unlock();
  922. }
  923. /*++
  924. void CheckSystemStatus:
  925. This is called as a result of a thread exiting. Check to see whether the
  926. MS Smart Card Resource Manager (Calais) is running or not, and set
  927. UI & behavior accordingly.
  928. Arguments:
  929. None
  930. Return Value:
  931. None
  932. Author:
  933. Amanda Matlosz 3/18/98
  934. Note:
  935. --*/
  936. void CNotifyWin::CheckSystemStatus(BOOL fForceUpdate)
  937. {
  938. //
  939. // We only care about this status if we're
  940. // NOT in the middle of shutting down
  941. //
  942. if (m_fShutDown)
  943. {
  944. return;
  945. }
  946. //
  947. // Query the service manager for the RM's status
  948. //
  949. DWORD dwReturn = ERROR_SUCCESS;
  950. SC_HANDLE schService = NULL;
  951. SC_HANDLE schSCManager = NULL;
  952. SERVICE_STATUS ssStatus; // current status of the service
  953. ZeroMemory((PVOID)&ssStatus, sizeof(ssStatus));
  954. schSCManager = OpenSCManager(
  955. NULL, // machine (NULL == local)
  956. NULL, // database (NULL == default)
  957. SC_MANAGER_CONNECT); // access required
  958. if (NULL == schSCManager)
  959. {
  960. dwReturn = (DWORD)GetLastError();
  961. }
  962. if (ERROR_SUCCESS == dwReturn)
  963. {
  964. schService = OpenService(
  965. schSCManager,
  966. TEXT("SCardSvr"),
  967. SERVICE_QUERY_STATUS);
  968. if (NULL == schService)
  969. {
  970. dwReturn = (DWORD)GetLastError();
  971. }
  972. else if (!QueryServiceStatus(schService, &ssStatus))
  973. {
  974. dwReturn = (DWORD)GetLastError();
  975. }
  976. }
  977. // if the service is running, say it's up
  978. // if the service is stopped, paused, or pending action,
  979. // say it's down. NOTE: may want to consider graying out
  980. // the taskbar icon to indicate paused, or some other err.
  981. if (ERROR_SUCCESS == dwReturn)
  982. {
  983. if (SERVICE_RUNNING == ssStatus.dwCurrentState)
  984. {
  985. dwReturn = SCARD_S_SUCCESS;
  986. }
  987. else
  988. {
  989. dwReturn = SCARD_E_NO_SERVICE;
  990. }
  991. }
  992. if (NULL != schService)
  993. {
  994. CloseServiceHandle(schService);
  995. schService = NULL;
  996. }
  997. if (NULL != schSCManager)
  998. {
  999. CloseServiceHandle(schSCManager);
  1000. schSCManager = NULL;
  1001. }
  1002. CalaisReleaseStartedEvent();
  1003. //
  1004. // Change state, log event as necessary,
  1005. // and kick off appropriate threads
  1006. //
  1007. SetSystemStatus((SCARD_S_SUCCESS == dwReturn), fForceUpdate);
  1008. }