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.

1189 lines
31 KiB

  1. // File: popupmsg.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "PopupMsg.h"
  5. #include "conf.h"
  6. #include "call.h"
  7. #include "certui.h"
  8. const int POPUPMSG_LEFT_MARGIN = 2;
  9. const int POPUPMSG_TOP_MARGIN = 2;
  10. const int POPUPMSG_CLIENT_MARGIN = 5;
  11. const int POPUPMSG_ICON_GAP = 3;
  12. const int POPUPMSG_WIDTH = 350;
  13. const int POPUPMSG_HEIGHT = 32;
  14. const int POPUPMSG_DLG_DEF_TEXT_WIDTH = 100;
  15. const TCHAR g_cszTrayWndClass[] = _TEXT("Shell_TrayWnd");
  16. const TCHAR g_cszTrayNotifyWndClass[] = _TEXT("TrayNotifyWnd");
  17. extern GUID g_csguidSecurity;
  18. ///////////////////////////////////////////////////////////////////////////
  19. UINT CPopupMsg::m_uVisiblePixels = 0;
  20. /*static*/ CSimpleArray<CPopupMsg*>* CPopupMsg::m_splstPopupMsgs = NULL;
  21. CPopupMsg::CPopupMsg(PMCALLBACKPROC pcp, LPVOID pContext):
  22. m_pCallbackProc (pcp),
  23. m_pContext (pContext),
  24. m_fRing (FALSE),
  25. m_hwnd (NULL),
  26. m_hIcon (NULL),
  27. m_fAutoSize (FALSE),
  28. m_hInstance (NULL),
  29. m_nWidth (0),
  30. m_nHeight (0),
  31. m_nTextWidth (POPUPMSG_DLG_DEF_TEXT_WIDTH)
  32. {
  33. TRACE_OUT(("Constructing CPopupMsg"));
  34. if (NULL != m_splstPopupMsgs)
  35. {
  36. CPopupMsg* p = const_cast<CPopupMsg*>(this);
  37. m_splstPopupMsgs->Add(p);
  38. }
  39. }
  40. CPopupMsg::~CPopupMsg()
  41. {
  42. TRACE_OUT(("Destructing CPopupMsg"));
  43. if (NULL != m_hIcon)
  44. {
  45. DestroyIcon(m_hIcon);
  46. }
  47. if (NULL != m_hwnd)
  48. {
  49. KillTimer(m_hwnd, POPUPMSG_TIMER);
  50. KillTimer(m_hwnd, POPUPMSG_RING_TIMER);
  51. DestroyWindow(m_hwnd);
  52. if (m_fAutoSize)
  53. {
  54. m_uVisiblePixels -= m_nHeight;
  55. }
  56. }
  57. if (NULL != m_splstPopupMsgs)
  58. {
  59. CPopupMsg* p = const_cast<CPopupMsg*>(this);
  60. if( !m_splstPopupMsgs->Remove(p) )
  61. {
  62. TRACE_OUT(("CPopupMsg object is not in the list"));
  63. }
  64. }
  65. }
  66. /****************************************************************************
  67. *
  68. * CLASS: CPopupMsg
  69. *
  70. * MEMBER: PlaySound()
  71. *
  72. * PURPOSE: Plays the sound or beeps the system speaker
  73. *
  74. ****************************************************************************/
  75. VOID CPopupMsg::PlaySound()
  76. {
  77. if (FALSE == ::PlaySound(m_szSound, NULL,
  78. SND_APPLICATION | SND_ALIAS | SND_ASYNC | SND_NOWAIT))
  79. {
  80. // Use the computer speaker to beep:
  81. TRACE_OUT(("PlaySound() failed, trying MessageBeep()"));
  82. ::MessageBeep(0xFFFFFFFF);
  83. }
  84. }
  85. /****************************************************************************
  86. *
  87. * CLASS: CPopupMsg
  88. *
  89. * MEMBER: Change(LPCTSTR)
  90. *
  91. * PURPOSE: Changes the text on an existing popup message
  92. *
  93. ****************************************************************************/
  94. BOOL CPopupMsg::Change(LPCTSTR pcszText)
  95. {
  96. BOOL bRet = FALSE;
  97. // BUGBUG: doesn't handle dialog message
  98. if (NULL != m_hwnd)
  99. {
  100. bRet = ::SetWindowText(m_hwnd, pcszText);
  101. }
  102. return bRet;
  103. }
  104. /****************************************************************************
  105. *
  106. * CLASS: CPopupMsg
  107. *
  108. * MEMBER: Init()
  109. *
  110. * PURPOSE: Allocates a static list of these objects
  111. *
  112. ****************************************************************************/
  113. BOOL CPopupMsg::Init()
  114. {
  115. ASSERT(NULL == m_splstPopupMsgs);
  116. return (NULL != (m_splstPopupMsgs = new CSimpleArray<CPopupMsg*>));
  117. }
  118. /****************************************************************************
  119. *
  120. * CLASS: CPopupMsg
  121. *
  122. * MEMBER: Cleanup()
  123. *
  124. * PURPOSE: Removes all of the objects of this type
  125. *
  126. ****************************************************************************/
  127. VOID CPopupMsg::Cleanup()
  128. {
  129. if (NULL != m_splstPopupMsgs)
  130. {
  131. for( int i = 0; i < m_splstPopupMsgs->GetSize(); ++i )
  132. {
  133. ASSERT( (*m_splstPopupMsgs)[i] != NULL);
  134. CPopupMsg *pThis = (*m_splstPopupMsgs)[i];
  135. delete pThis;
  136. }
  137. delete m_splstPopupMsgs;
  138. m_splstPopupMsgs = NULL;
  139. }
  140. }
  141. /****************************************************************************
  142. *
  143. * CLASS: CPopupMsg
  144. *
  145. * MEMBER: PMWndProc(HWND, unsigned, WORD, LONG)
  146. *
  147. * PURPOSE:
  148. *
  149. ****************************************************************************/
  150. LRESULT CALLBACK CPopupMsg::PMWndProc(
  151. HWND hWnd, /* window handle */
  152. UINT message, /* type of message */
  153. WPARAM wParam, /* additional information */
  154. LPARAM lParam) /* additional information */
  155. {
  156. CPopupMsg* ppm;
  157. LPCREATESTRUCT lpcs;
  158. switch (message)
  159. {
  160. case WM_CREATE:
  161. {
  162. TRACE_OUT(("PopupMsg Window created"));
  163. lpcs = (LPCREATESTRUCT) lParam;
  164. ppm = (CPopupMsg*) lpcs->lpCreateParams;
  165. ASSERT(ppm && "NULL object passed in WM_CREATE!");
  166. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) ppm);
  167. // Create a timer to make the window time-out and disappear:
  168. ::SetTimer(hWnd, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
  169. // For now, if you pass a callback, you get ringing.
  170. // If not, there is no ring
  171. if (NULL != ppm->m_fPlaySound)
  172. {
  173. ppm->PlaySound();
  174. if (NULL != ppm->m_fRing)
  175. {
  176. // Create a timer to make the ringer start:
  177. ::SetTimer(hWnd, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
  178. }
  179. }
  180. break;
  181. }
  182. case WM_TIMER:
  183. {
  184. ppm = (CPopupMsg*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  185. if (POPUPMSG_TIMER == wParam)
  186. {
  187. // Message timed out:
  188. if (NULL != ppm)
  189. {
  190. PMCALLBACKPROC pCallback;
  191. if (NULL != (pCallback = ppm->m_pCallbackProc))
  192. {
  193. ppm->m_pCallbackProc = NULL;
  194. pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
  195. }
  196. // Self-destruct:
  197. if (NULL != ppm->m_hwnd)
  198. {
  199. // NULL out the object pointer:
  200. SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
  201. delete ppm;
  202. }
  203. }
  204. }
  205. else if (POPUPMSG_RING_TIMER == wParam)
  206. {
  207. if (NULL != ppm)
  208. {
  209. ppm->PlaySound();
  210. }
  211. // Create a timer to make it ring again:
  212. ::SetTimer( hWnd,
  213. POPUPMSG_RING_TIMER,
  214. POPUPMSG_RING_INTERVAL,
  215. NULL);
  216. }
  217. break;
  218. }
  219. case WM_LBUTTONUP:
  220. {
  221. // Clicked on the message:
  222. ppm = (CPopupMsg*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  223. if (NULL != ppm)
  224. {
  225. ::PlaySound(NULL, NULL, 0); // stop playing the ring sound
  226. ::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
  227. ::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
  228. PMCALLBACKPROC pCallback;
  229. if (NULL != (pCallback = ppm->m_pCallbackProc))
  230. {
  231. ppm->m_pCallbackProc = NULL;
  232. pCallback(ppm->m_pContext, PMF_OK);
  233. }
  234. // Self-destruct:
  235. if (NULL != ppm->m_hwnd)
  236. {
  237. // NULL out the object pointer:
  238. SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
  239. delete ppm;
  240. }
  241. }
  242. break;
  243. }
  244. case WM_PAINT:
  245. {
  246. // Handle painting:
  247. PAINTSTRUCT ps;
  248. HDC hdc;
  249. int nHorizTextOffset = POPUPMSG_LEFT_MARGIN;
  250. if (hdc = ::BeginPaint(hWnd, &ps))
  251. {
  252. // Start by painting the icon (if needed)
  253. ppm = (CPopupMsg*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
  254. if ((NULL != ppm) &&
  255. (NULL != ppm->m_hIcon))
  256. {
  257. if (::DrawIconEx( hdc,
  258. POPUPMSG_LEFT_MARGIN,
  259. POPUPMSG_TOP_MARGIN,
  260. ppm->m_hIcon,
  261. POPUPMSG_ICON_WIDTH,
  262. POPUPMSG_ICON_HEIGHT,
  263. 0,
  264. NULL,
  265. DI_NORMAL))
  266. {
  267. // We painted an icon, so make sure the text is shifted
  268. // to the right by the right amount:
  269. nHorizTextOffset += (POPUPMSG_ICON_WIDTH + POPUPMSG_ICON_GAP);
  270. }
  271. }
  272. // Draw the text with a transparent background:
  273. int bkOld = ::SetBkMode(hdc, TRANSPARENT);
  274. COLORREF crOld = ::SetTextColor(hdc, ::GetSysColor(COLOR_WINDOWTEXT));
  275. HFONT hFontOld = (HFONT) ::SelectObject(hdc, g_hfontDlg);
  276. TCHAR szWinText[POPUPMSG_MAX_LENGTH];
  277. szWinText[0] = _T('\0');
  278. ::GetWindowText(hWnd, szWinText, sizeof(szWinText));
  279. RECT rctClient;
  280. if (::GetClientRect(hWnd, &rctClient))
  281. {
  282. rctClient.left += nHorizTextOffset;
  283. ::DrawText( hdc, szWinText, -1, &rctClient,
  284. DT_SINGLELINE | DT_NOCLIP | DT_VCENTER | DT_NOPREFIX);
  285. }
  286. ::SetBkMode(hdc, bkOld);
  287. ::SetTextColor(hdc, crOld);
  288. ::SelectObject(hdc, hFontOld);
  289. ::EndPaint(hWnd, &ps);
  290. }
  291. break;
  292. }
  293. default:
  294. {
  295. return DefWindowProc(hWnd, message, wParam, lParam);
  296. }
  297. }
  298. return(FALSE);
  299. }
  300. /****************************************************************************
  301. *
  302. * CLASS: CPopupMsg
  303. *
  304. * MEMBER: PMDlgProc(HWND, UINT, WPARAM, LPARAM)
  305. *
  306. * PURPOSE: Handles messages associated with the incoming call dialog
  307. *
  308. ****************************************************************************/
  309. INT_PTR CALLBACK CPopupMsg::PMDlgProc( HWND hDlg,
  310. UINT uMsg,
  311. WPARAM wParam,
  312. LPARAM lParam)
  313. {
  314. CPopupMsg* ppm;
  315. switch (uMsg)
  316. {
  317. case WM_INITDIALOG:
  318. {
  319. TRACE_OUT(("PopupMsg Window created"));
  320. AddModelessDlg(hDlg);
  321. ppm = (CPopupMsg*) lParam;
  322. ASSERT(ppm && "NULL object passed in WM_INITDIALOG!");
  323. ::SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) ppm);
  324. TRACE_OUT(("CPopupMsg m_nTextWidth=%d in WM_INITDIALOG", ppm->m_nTextWidth));
  325. // If the dialog is too big, then resize the text width.
  326. RECT rctDlg;
  327. RECT rctDesk;
  328. HWND hwndDesk;
  329. if (::GetWindowRect(hDlg, &rctDlg) &&
  330. (hwndDesk = ::GetDesktopWindow()) &&
  331. ::GetWindowRect(hwndDesk, &rctDesk))
  332. {
  333. int nDlgWidth = rctDlg.right - rctDlg.left;
  334. ppm->m_nTextWidth -= max( 0,
  335. nDlgWidth + ppm->m_nTextWidth -
  336. (rctDesk.right - rctDesk.left));
  337. }
  338. RECT rctCtrl;
  339. // Move the "Authenticate" button, if it's there
  340. HWND hwndAuth = ::GetDlgItem(hDlg, IDB_AUTH);
  341. if ((NULL != hwndAuth) && ::GetWindowRect(hwndAuth, &rctCtrl)) {
  342. // Turn rctCtrl's top and left into client coords:
  343. ::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
  344. ::SetWindowPos( hwndAuth,
  345. NULL,
  346. rctCtrl.left + ppm->m_nTextWidth,
  347. rctCtrl.top,
  348. 0, 0,
  349. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
  350. }
  351. // Move the "Accept" button (IDOK)
  352. HWND hwndOK = ::GetDlgItem(hDlg, IDOK);
  353. if ((NULL != hwndOK) && ::GetWindowRect(hwndOK, &rctCtrl))
  354. {
  355. // Turn rctCtrl's top and left into client coords:
  356. ::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
  357. ::SetWindowPos( hwndOK,
  358. NULL,
  359. rctCtrl.left + ppm->m_nTextWidth,
  360. rctCtrl.top,
  361. 0, 0,
  362. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
  363. }
  364. // Move the "Ignore" button (IDCANCEL)
  365. HWND hwndCancel = ::GetDlgItem(hDlg, IDCANCEL);
  366. if ((NULL != hwndCancel) && ::GetWindowRect(hwndCancel, &rctCtrl))
  367. {
  368. // Turn rctCtrl's top and left into client coords:
  369. ::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
  370. ::SetWindowPos( hwndCancel,
  371. NULL,
  372. rctCtrl.left + ppm->m_nTextWidth,
  373. rctCtrl.top,
  374. 0, 0,
  375. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
  376. }
  377. // Stretch the text field:
  378. HWND hwndText = ::GetDlgItem(hDlg, IDC_MSG_STATIC);
  379. if ((NULL != hwndText) && ::GetWindowRect(hwndText, &rctCtrl))
  380. {
  381. ::SetWindowPos( hwndText,
  382. NULL,
  383. 0, 0,
  384. ppm->m_nTextWidth,
  385. rctCtrl.bottom - rctCtrl.top,
  386. SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
  387. // and set the font
  388. ::SendMessage(hwndText, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
  389. }
  390. // Create a timer to make the window time-out and disappear:
  391. ::SetTimer(hDlg, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
  392. // For now, if you pass a callback, you get ringing.
  393. // If not, there is no ring
  394. if (NULL != ppm->m_fPlaySound)
  395. {
  396. ppm->PlaySound();
  397. if (NULL != ppm->m_fRing)
  398. {
  399. // Create a timer to make the ringer start:
  400. ::SetTimer(hDlg, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
  401. }
  402. }
  403. return TRUE;
  404. }
  405. case WM_TIMER:
  406. {
  407. ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  408. if (POPUPMSG_TIMER == wParam)
  409. {
  410. // Message timed out:
  411. if (NULL != ppm)
  412. {
  413. PMCALLBACKPROC pCallback;
  414. if (NULL != (pCallback = ppm->m_pCallbackProc))
  415. {
  416. ppm->m_pCallbackProc = NULL;
  417. // hide the dialog in case the callback doesn't
  418. // return immediately
  419. ::ShowWindow(ppm->m_hwnd, SW_HIDE);
  420. pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
  421. }
  422. // Self-destruct:
  423. if (NULL != ppm->m_hwnd)
  424. {
  425. // NULL out the object pointer:
  426. SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
  427. delete ppm;
  428. }
  429. }
  430. }
  431. else if (POPUPMSG_RING_TIMER == wParam)
  432. {
  433. if (NULL != ppm)
  434. {
  435. ppm->PlaySound();
  436. }
  437. // Create a timer to make it ring again:
  438. ::SetTimer( hDlg,
  439. POPUPMSG_RING_TIMER,
  440. POPUPMSG_RING_INTERVAL,
  441. NULL);
  442. }
  443. return TRUE;
  444. }
  445. case WM_COMMAND:
  446. {
  447. // Clicked on one of the buttons:
  448. ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  449. if (NULL != ppm)
  450. {
  451. // stop playing the ring sound
  452. ::PlaySound(NULL, NULL, 0);
  453. ::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
  454. ::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
  455. PMCALLBACKPROC pCallback;
  456. if (NULL != (pCallback = ppm->m_pCallbackProc))
  457. {
  458. ppm->m_pCallbackProc = NULL; // prevent this from firing twice
  459. // hide the dialog in case the callback doesn't
  460. // return immediately
  461. ::ShowWindow(ppm->m_hwnd, SW_HIDE);
  462. pCallback(ppm->m_pContext,
  463. (IDB_AUTH == LOWORD(wParam)) ? PMF_AUTH : (IDOK == LOWORD(wParam)) ? PMF_OK : PMF_CANCEL);
  464. }
  465. // Self-destruct:
  466. if (NULL != ppm->m_hwnd)
  467. {
  468. // NULL out the object pointer:
  469. SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
  470. delete ppm;
  471. }
  472. }
  473. return TRUE;
  474. }
  475. case WM_DESTROY:
  476. {
  477. ::RemoveModelessDlg(hDlg);
  478. break;
  479. }
  480. default:
  481. break;
  482. } /* switch (uMsg) */
  483. return FALSE;
  484. }
  485. /****************************************************************************
  486. *
  487. * CLASS: CPopupMsg
  488. *
  489. * MEMBER: SecurePMDlgProc(HWND, UINT, WPARAM, LPARAM)
  490. *
  491. * PURPOSE: Handles messages associated with the incoming call dialog
  492. *
  493. ****************************************************************************/
  494. INT_PTR CALLBACK CPopupMsg::SecurePMDlgProc( HWND hDlg,
  495. UINT uMsg,
  496. WPARAM wParam,
  497. LPARAM lParam)
  498. {
  499. CPopupMsg* ppm;
  500. switch (uMsg)
  501. {
  502. case WM_INITDIALOG:
  503. {
  504. TRACE_OUT(("PopupMsg Window created"));
  505. AddModelessDlg(hDlg);
  506. ppm = (CPopupMsg*) lParam;
  507. ASSERT(ppm && "NULL object passed in WM_INITDIALOG!");
  508. ::SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) ppm);
  509. TRACE_OUT(("CPopupMsg m_nTextWidth=%d in WM_INITDIALOG", ppm->m_nTextWidth));
  510. RegEntry re(UI_KEY, HKEY_CURRENT_USER);
  511. if (1 == re.GetNumber(REGVAL_SHOW_SECUREDETAILS, DEFAULT_SHOW_SECUREDETAILS)) {
  512. ExpandSecureDialog(hDlg,ppm);
  513. }
  514. // Create a timer to make the window time-out and disappear:
  515. ::SetTimer(hDlg, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
  516. // For now, if you pass a callback, you get ringing.
  517. // If not, there is no ring
  518. if (NULL != ppm->m_fPlaySound)
  519. {
  520. ppm->PlaySound();
  521. if (NULL != ppm->m_fRing)
  522. {
  523. // Create a timer to make the ringer start:
  524. ::SetTimer(hDlg, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
  525. }
  526. }
  527. return TRUE;
  528. }
  529. case WM_TIMER:
  530. {
  531. ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  532. if (POPUPMSG_TIMER == wParam)
  533. {
  534. // Message timed out:
  535. if (NULL != ppm)
  536. {
  537. PMCALLBACKPROC pCallback;
  538. if (NULL != (pCallback = ppm->m_pCallbackProc))
  539. {
  540. ppm->m_pCallbackProc = NULL;
  541. // hide the dialog in case the callback doesn't
  542. // return immediately
  543. ::ShowWindow(ppm->m_hwnd, SW_HIDE);
  544. pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
  545. }
  546. // Self-destruct:
  547. if (NULL != ppm->m_hwnd)
  548. {
  549. // NULL out the object pointer:
  550. SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
  551. delete ppm;
  552. }
  553. }
  554. }
  555. else if (POPUPMSG_RING_TIMER == wParam)
  556. {
  557. if (NULL != ppm)
  558. {
  559. ppm->PlaySound();
  560. }
  561. // Create a timer to make it ring again:
  562. ::SetTimer( hDlg,
  563. POPUPMSG_RING_TIMER,
  564. POPUPMSG_RING_INTERVAL,
  565. NULL);
  566. }
  567. return TRUE;
  568. }
  569. case WM_COMMAND:
  570. {
  571. ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  572. switch (LOWORD(wParam)) {
  573. case IDOK:
  574. case IDCANCEL:
  575. // Clicked on one of the buttons:
  576. if (NULL != ppm)
  577. {
  578. // stop playing the ring sound
  579. ::PlaySound(NULL, NULL, 0);
  580. ::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
  581. ::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
  582. PMCALLBACKPROC pCallback;
  583. if (NULL != (pCallback = ppm->m_pCallbackProc))
  584. {
  585. ppm->m_pCallbackProc = NULL; // prevent this from firing twice
  586. // hide the dialog in case the callback doesn't
  587. // return immediately
  588. ::ShowWindow(ppm->m_hwnd, SW_HIDE);
  589. pCallback(ppm->m_pContext, (IDOK == LOWORD(wParam)) ? PMF_OK : PMF_CANCEL);
  590. }
  591. // Self-destruct:
  592. if (NULL != ppm->m_hwnd)
  593. {
  594. // NULL out the object pointer:
  595. SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
  596. delete ppm;
  597. }
  598. }
  599. break;
  600. case IDB_DETAILS:
  601. RegEntry re(UI_KEY, HKEY_CURRENT_USER);
  602. if (1 == re.GetNumber(REGVAL_SHOW_SECUREDETAILS,DEFAULT_SHOW_SECUREDETAILS)) {
  603. // Currently expanded, so shrink
  604. re.SetValue(REGVAL_SHOW_SECUREDETAILS,(DWORD)0);
  605. ShrinkSecureDialog(hDlg);
  606. }
  607. else {
  608. // Currently shrunk, so expand
  609. re.SetValue(REGVAL_SHOW_SECUREDETAILS,1);
  610. ExpandSecureDialog(hDlg,ppm);
  611. }
  612. break;
  613. }
  614. return TRUE;
  615. }
  616. case WM_DESTROY:
  617. {
  618. ::RemoveModelessDlg(hDlg);
  619. break;
  620. }
  621. default:
  622. break;
  623. } /* switch (uMsg) */
  624. return FALSE;
  625. }
  626. /****************************************************************************
  627. *
  628. * CLASS: CPopupMsg
  629. *
  630. * MEMBER: Create()
  631. *
  632. * PURPOSE: Creates a popup message window
  633. *
  634. ****************************************************************************/
  635. HWND CPopupMsg::Create( LPCTSTR pcszText, BOOL fRing, LPCTSTR pcszIconName,
  636. HINSTANCE hInstance, UINT uIDSoundEvent,
  637. UINT uTimeout, int xCoord, int yCoord)
  638. {
  639. ASSERT(pcszText);
  640. m_fRing = fRing;
  641. m_fPlaySound = (BOOL) uIDSoundEvent;
  642. m_uTimeout = uTimeout;
  643. // First try to load the icon:
  644. m_hInstance = hInstance;
  645. if ((NULL != m_hInstance) && (NULL != pcszIconName))
  646. {
  647. m_hIcon = (HICON) LoadImage(m_hInstance,
  648. pcszIconName,
  649. IMAGE_ICON,
  650. POPUPMSG_ICON_WIDTH,
  651. POPUPMSG_ICON_HEIGHT,
  652. LR_DEFAULTCOLOR);
  653. }
  654. else
  655. {
  656. m_hIcon = NULL;
  657. }
  658. if ((NULL == m_hInstance) ||
  659. (!::LoadString( m_hInstance,
  660. uIDSoundEvent,
  661. m_szSound,
  662. CCHMAX(m_szSound))))
  663. {
  664. m_szSound[0] = _T('\0');
  665. }
  666. // initialize window size with default values:
  667. m_nWidth = POPUPMSG_WIDTH;
  668. m_nHeight = POPUPMSG_HEIGHT;
  669. HWND hwndDesktop = GetDesktopWindow();
  670. if (NULL != hwndDesktop)
  671. {
  672. RECT rctDesktop;
  673. ::GetWindowRect(hwndDesktop, &rctDesktop);
  674. HDC hdc = GetDC(hwndDesktop);
  675. if (NULL != hdc)
  676. {
  677. HFONT hFontOld = (HFONT) SelectObject(hdc, g_hfontDlg);
  678. SIZE size;
  679. if (GetTextExtentPoint32(hdc, pcszText, lstrlen(pcszText), &size))
  680. {
  681. // don't make it wider than the desktop
  682. m_nWidth = min( rctDesktop.right - rctDesktop.left,
  683. size.cx + (2 * POPUPMSG_CLIENT_MARGIN));
  684. m_nHeight = size.cy + (2 * POPUPMSG_CLIENT_MARGIN);
  685. // If we have succesfully loaded an icon, make size
  686. // adjustments:
  687. if (NULL != m_hIcon)
  688. {
  689. m_nWidth += POPUPMSG_ICON_WIDTH + POPUPMSG_ICON_GAP;
  690. if (size.cy < POPUPMSG_ICON_HEIGHT)
  691. {
  692. m_nHeight = POPUPMSG_ICON_HEIGHT +
  693. (2 * POPUPMSG_CLIENT_MARGIN);
  694. }
  695. }
  696. }
  697. // Reselect old font
  698. SelectObject(hdc, hFontOld);
  699. ReleaseDC(hwndDesktop, hdc);
  700. }
  701. POINT pt;
  702. GetIdealPosition(&pt, xCoord, yCoord);
  703. m_hwnd = CreateWindowEx(WS_EX_PALETTEWINDOW,
  704. g_szPopupMsgWndClass,
  705. pcszText,
  706. WS_POPUP | /* WS_VISIBLE |*/ WS_DLGFRAME,
  707. pt.x, pt.y,
  708. m_nWidth, m_nHeight,
  709. NULL,
  710. NULL,
  711. ::GetInstanceHandle(),
  712. (LPVOID) this);
  713. if (m_fAutoSize)
  714. {
  715. m_uVisiblePixels += m_nHeight;
  716. }
  717. // Show, but don't activate
  718. ::ShowWindow(m_hwnd, SW_SHOWNA);
  719. // Repaint
  720. ::UpdateWindow(m_hwnd);
  721. return m_hwnd;
  722. }
  723. // Something went wrong
  724. return NULL;
  725. }
  726. /****************************************************************************
  727. *
  728. * CLASS: CPopupMsg
  729. *
  730. * MEMBER: CreateDlg()
  731. *
  732. * PURPOSE: Creates a popup dialog message window
  733. *
  734. ****************************************************************************/
  735. HWND CPopupMsg::CreateDlg( LPCTSTR pcszText, BOOL fRing, LPCTSTR pcszIconName,
  736. HINSTANCE hInstance, UINT uIDSoundEvent,
  737. UINT uTimeout, int xCoord, int yCoord)
  738. {
  739. ASSERT(pcszText);
  740. m_fRing = fRing;
  741. m_fPlaySound = (BOOL) uIDSoundEvent;
  742. m_uTimeout = uTimeout;
  743. // First try to load the icon:
  744. m_hInstance = hInstance;
  745. if ((NULL != m_hInstance) && (NULL != pcszIconName))
  746. {
  747. m_hIcon = (HICON) LoadImage(m_hInstance,
  748. pcszIconName,
  749. IMAGE_ICON,
  750. POPUPMSG_ICON_WIDTH,
  751. POPUPMSG_ICON_HEIGHT,
  752. LR_DEFAULTCOLOR);
  753. }
  754. else
  755. {
  756. m_hIcon = NULL;
  757. }
  758. if ((NULL == m_hInstance) ||
  759. (!::LoadString( m_hInstance,
  760. uIDSoundEvent,
  761. m_szSound,
  762. sizeof(m_szSound))))
  763. {
  764. m_szSound[0] = _T('\0');
  765. }
  766. // init with large defaults in case getwindowrect fails
  767. RECT rctDesktop = { 0x0000, 0x0000, 0xFFFF, 0xFFFF };
  768. HWND hwndDesktop = GetDesktopWindow();
  769. if (NULL != hwndDesktop)
  770. {
  771. ::GetWindowRect(hwndDesktop, &rctDesktop);
  772. HDC hdc = GetDC(hwndDesktop);
  773. if (NULL != hdc)
  774. {
  775. HFONT hFontOld = (HFONT) SelectObject(hdc, g_hfontDlg);
  776. SIZE size;
  777. if (::GetTextExtentPoint32(hdc, pcszText, lstrlen(pcszText), &size))
  778. {
  779. m_nTextWidth = size.cx;
  780. }
  781. ::SelectObject(hdc, hFontOld);
  782. ::ReleaseDC(hwndDesktop, hdc);
  783. }
  784. }
  785. KillScrnSaver();
  786. INmCall * pCall = NULL;
  787. PBYTE pb = NULL;
  788. ULONG cb = 0;
  789. int id;
  790. if (m_pContext != NULL) {
  791. pCall = ((CCall *)m_pContext)->GetINmCall();
  792. }
  793. if (NULL != pCall && S_OK == pCall->GetUserData(g_csguidSecurity,&pb,&cb)) {
  794. // This is an encrypted call
  795. CoTaskMemFree(pb);
  796. id = IDD_SECURE_INCOMING_CALL;
  797. m_hwnd = ::CreateDialogParam(m_hInstance, MAKEINTRESOURCE(id),
  798. ::GetMainWindow(),CPopupMsg::SecurePMDlgProc,(LPARAM) this);
  799. }
  800. else {
  801. id = IDD_INCOMING_CALL;
  802. m_hwnd = ::CreateDialogParam(m_hInstance, MAKEINTRESOURCE(id),
  803. ::GetMainWindow(),CPopupMsg::PMDlgProc,(LPARAM) this);
  804. }
  805. if (NULL != m_hwnd)
  806. {
  807. ::SetDlgItemText(m_hwnd, IDC_MSG_STATIC, pcszText);
  808. RECT rctDlg;
  809. ::GetWindowRect(m_hwnd, &rctDlg);
  810. // Stretch the width to fit the person's name,
  811. // but not wider than the desktop.
  812. // int nDeskWidth = rctDesktop.right - rctDesktop.left;
  813. // Resize the non-secure dialog
  814. m_nWidth = (rctDlg.right - rctDlg.left) + ((IDD_INCOMING_CALL == id) ? m_nTextWidth : 0);
  815. // if (m_nWidth > nDeskWidth)
  816. // {
  817. // m_nTextWidth -= (m_nWidth - nDeskWidth);
  818. // m_nWidth = nDeskWidth;
  819. // }
  820. m_nHeight = rctDlg.bottom - rctDlg.top;
  821. POINT pt;
  822. GetIdealPosition(&pt, xCoord, yCoord);
  823. // Show, move, make topmost, but don't activate
  824. ::SetWindowPos( m_hwnd,
  825. HWND_TOPMOST,
  826. pt.x,
  827. pt.y,
  828. m_nWidth,
  829. m_nHeight,
  830. SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_DRAWFRAME);
  831. if (m_fAutoSize)
  832. {
  833. m_uVisiblePixels += m_nHeight;
  834. }
  835. }
  836. return m_hwnd;
  837. }
  838. BOOL CPopupMsg::GetIdealPosition(LPPOINT ppt, int xCoord, int yCoord)
  839. {
  840. ASSERT(ppt);
  841. BOOL bRet = FALSE;
  842. HWND hwndDesktop = GetDesktopWindow();
  843. RECT rctDesktop;
  844. if (NULL != hwndDesktop)
  845. {
  846. int yBottomofTrayRect = 0;
  847. if ((-1 == xCoord) && (-1 == yCoord))
  848. {
  849. m_fAutoSize = TRUE;
  850. // BUGBUG: We search for the tray notification window by looking for
  851. // hard coded window class names. This is safe if we're running
  852. // Win 95 build 950.6, but maybe not otherwise...
  853. HWND hwndTray = FindWindowEx(NULL, NULL, g_cszTrayWndClass, NULL);
  854. if (NULL != hwndTray)
  855. {
  856. HWND hwndTrayNotify = FindWindowEx(hwndTray, NULL, g_cszTrayNotifyWndClass, NULL);
  857. if (NULL != hwndTrayNotify)
  858. {
  859. RECT rctTrayNotify;
  860. if (GetWindowRect(hwndTrayNotify, &rctTrayNotify))
  861. {
  862. xCoord = rctTrayNotify.right;
  863. yCoord = rctTrayNotify.top;
  864. yBottomofTrayRect = rctTrayNotify.bottom;
  865. }
  866. }
  867. }
  868. }
  869. if (GetWindowRect(hwndDesktop, &rctDesktop))
  870. {
  871. // Make sure that xCoord and yCoord are on the screen (bugs 1817,1819):
  872. xCoord = min(rctDesktop.right, xCoord);
  873. xCoord = max(rctDesktop.left, xCoord);
  874. yCoord = min(rctDesktop.bottom, yCoord);
  875. yCoord = max(rctDesktop.top, yCoord);
  876. // First attempt will be to center the toolbar horizontally
  877. // with respect to the mouse position and place it directly
  878. // above vertically.
  879. ppt->x = xCoord - (m_nWidth / 2);
  880. // Make the window higher if there are exisiting visible messages
  881. ppt->y = yCoord - m_uVisiblePixels - m_nHeight;
  882. // If we are too high on the screen (the taskbar is probably
  883. // docked on top), then use the click position as the top of
  884. // where the toolbar will appear.
  885. if (ppt->y < 0)
  886. {
  887. ppt->y = yCoord;
  888. // Even better, if we have found the tray rect and we know that
  889. // we have docked on top, then use the bottom of the rect instead
  890. // of the top
  891. if (0 != yBottomofTrayRect)
  892. {
  893. ppt->y = yBottomofTrayRect;
  894. // Make the window lower if there are
  895. // exisiting visible messages
  896. ppt->y += m_uVisiblePixels;
  897. }
  898. }
  899. // Repeat the same logic for the horizontal position
  900. if (ppt->x < 0)
  901. {
  902. ppt->x = xCoord;
  903. }
  904. // If the toolbar if off the screen to the right, then right-justify it
  905. if (ppt->x > (rctDesktop.right - m_nWidth))
  906. {
  907. ppt->x = max(0, xCoord - m_nWidth);
  908. }
  909. bRet = TRUE;
  910. }
  911. }
  912. return bRet;
  913. }
  914. VOID CPopupMsg::ExpandSecureDialog(HWND hDlg,CPopupMsg * ppm)
  915. {
  916. RECT rect, editrect;
  917. // Change the dialog to the expanded version.
  918. if (GetWindowRect(hDlg,&rect) &&
  919. GetWindowRect(GetDlgItem(hDlg,IDC_SECURE_CALL_EDIT),&editrect)) {
  920. int nHeight = rect.bottom - rect.top;
  921. int nWidth = rect.right - rect.left;
  922. //
  923. // Grow by height of edit control plus 7 dialog unit margin as
  924. // given by edit control offset within control:
  925. //
  926. int deltaHeight = ( editrect.bottom - editrect.top ) +
  927. ( editrect.left - rect.left );
  928. SetWindowPos(hDlg,NULL,
  929. rect.left,(rect.top - deltaHeight > 0 ? rect.top - deltaHeight : 0),
  930. nWidth,nHeight + deltaHeight, SWP_NOZORDER);
  931. // Make the edit box visible.
  932. HWND hEditBox = GetDlgItem(hDlg, IDC_SECURE_CALL_EDIT);
  933. if (hEditBox != NULL) {
  934. ShowWindow(hEditBox,SW_SHOW);
  935. EnableWindow(hEditBox, TRUE);
  936. // Get security information, if any.
  937. if (NULL != ppm) {
  938. INmCall * pCall = NULL;
  939. PBYTE pb = NULL;
  940. ULONG cb = 0;
  941. if (NULL != ppm->m_pContext) {
  942. pCall = ((CCall *)ppm->m_pContext)->GetINmCall();
  943. }
  944. if (NULL != pCall && S_OK == pCall->GetUserData(g_csguidSecurity,&pb,&cb)) {
  945. ASSERT(pb);
  946. ASSERT(cb);
  947. if ( TCHAR * pCertText = FormatCert( pb, cb )) {
  948. SetDlgItemText(hDlg,IDC_SECURE_CALL_EDIT,pCertText);
  949. delete pCertText;
  950. }
  951. else {
  952. ERROR_OUT(("FormatCert failed"));
  953. }
  954. CoTaskMemFree(pb);
  955. }
  956. }
  957. }
  958. // Move the buttons southward.
  959. HWND hButton = GetDlgItem(hDlg, IDOK);
  960. if (hButton && GetWindowRect(hButton,&rect)) {
  961. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  962. SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
  963. SWP_NOZORDER | SWP_NOSIZE);
  964. }
  965. hButton = GetDlgItem(hDlg, IDCANCEL);
  966. if (hButton && GetWindowRect(hButton,&rect)) {
  967. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  968. SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
  969. SWP_NOZORDER | SWP_NOSIZE);
  970. }
  971. hButton = GetDlgItem(hDlg, IDB_DETAILS);
  972. if (hButton && GetWindowRect(hButton,&rect)) {
  973. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  974. SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
  975. SWP_NOZORDER | SWP_NOSIZE);
  976. // Change text on Details button
  977. TCHAR lpButtonString[MAX_PATH];
  978. ::FLoadString(IDS_SECURITY_NODETAILS, lpButtonString, MAX_PATH);
  979. SetDlgItemText(hDlg,IDB_DETAILS,lpButtonString);
  980. }
  981. }
  982. }
  983. VOID CPopupMsg::ShrinkSecureDialog(HWND hDlg)
  984. {
  985. RECT rect,editrect;
  986. // Change the dialog to the normal version.
  987. if (GetWindowRect(hDlg,&rect) &&
  988. GetWindowRect(GetDlgItem(hDlg,IDC_SECURE_CALL_EDIT),&editrect)) {
  989. int nHeight = rect.bottom - rect.top;
  990. int nWidth = rect.right - rect.left;
  991. //
  992. // Grow by height of edit control plus 7 dialog unit margin as
  993. // given by edit control offset within control:
  994. //
  995. int deltaHeight = ( editrect.bottom - editrect.top ) +
  996. ( editrect.left - rect.left );
  997. SetWindowPos(hDlg,NULL,
  998. rect.left,(rect.top - deltaHeight > 0 ? rect.top + deltaHeight : 0),
  999. nWidth,nHeight - deltaHeight,SWP_NOZORDER);
  1000. // Make the edit box invisible.
  1001. HWND hEditBox = GetDlgItem(hDlg, IDC_SECURE_CALL_EDIT);
  1002. if (hEditBox != NULL) {
  1003. ShowWindow(hEditBox,SW_HIDE);
  1004. EnableWindow(hEditBox,FALSE);
  1005. }
  1006. // Move the buttons northward.
  1007. HWND hButton = GetDlgItem(hDlg, IDOK);
  1008. if (hButton && GetWindowRect(hButton,&rect)) {
  1009. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  1010. SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
  1011. SWP_NOZORDER | SWP_NOSIZE);
  1012. }
  1013. hButton = GetDlgItem(hDlg, IDCANCEL);
  1014. if (hButton && GetWindowRect(hButton,&rect)) {
  1015. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  1016. SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
  1017. SWP_NOZORDER | SWP_NOSIZE);
  1018. }
  1019. hButton = GetDlgItem(hDlg, IDB_DETAILS);
  1020. if (hButton && GetWindowRect(hButton,&rect)) {
  1021. MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
  1022. SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
  1023. SWP_NOZORDER | SWP_NOSIZE);
  1024. TCHAR lpButtonString[MAX_PATH];
  1025. ::FLoadString(IDS_SECURITY_DETAILS, lpButtonString, MAX_PATH);
  1026. SetDlgItemText(hDlg,IDB_DETAILS,lpButtonString);
  1027. }
  1028. }
  1029. }