Source code of Windows XP (NT5)
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.

775 lines
22 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N O T I F Y . C P P
  7. //
  8. // Contents: Implementation of INetConnectionNotifySink
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 21 Aug 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h"
  18. #include "nccom.h"
  19. #include "notify.h"
  20. #include "shutil.h"
  21. #include "smcent.h"
  22. #include "ctrayui.h"
  23. #include "traymsgs.h"
  24. #include "wzcdlg.h"
  25. extern HWND g_hwndTray;
  26. enum EVENT_LEVELS
  27. {
  28. EVT_LVL_DISABLE_ALL = 0,
  29. EVT_LVL_ENABLE_PRIVATE = 1,
  30. EVT_LVL_ENABLE_ALL = 2
  31. };
  32. DWORD g_dwCurrentEventLevel = EVT_LVL_ENABLE_ALL;
  33. //static
  34. HRESULT
  35. CConnectionNotifySink::CreateInstance (
  36. REFIID riid,
  37. VOID** ppv)
  38. {
  39. TraceFileFunc(ttidNotifySink);
  40. HRESULT hr = E_OUTOFMEMORY;
  41. // Initialize the output parameter.
  42. //
  43. *ppv = NULL;
  44. CConnectionNotifySink* pObj;
  45. pObj = new CComObject <CConnectionNotifySink>;
  46. if (pObj)
  47. {
  48. // Do the standard CComCreator::CreateInstance stuff.
  49. //
  50. pObj->SetVoid (NULL);
  51. pObj->InternalFinalConstructAddRef ();
  52. hr = pObj->FinalConstruct ();
  53. pObj->InternalFinalConstructRelease ();
  54. if (SUCCEEDED(hr))
  55. {
  56. // Call the PidlInitialize function to allow the enumeration
  57. // object to copy the list.
  58. //
  59. hr = HrGetConnectionsFolderPidl(pObj->m_pidlFolder);
  60. if (SUCCEEDED(hr))
  61. {
  62. hr = pObj->QueryInterface (riid, ppv);
  63. }
  64. }
  65. if (FAILED(hr))
  66. {
  67. delete pObj;
  68. }
  69. }
  70. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CConnectionNotifySink::CreateInstance");
  71. return hr;
  72. }
  73. //+---------------------------------------------------------------------------
  74. //
  75. // Member: CConnectionNotifySink::~CConnectionNotifySink
  76. //
  77. // Purpose: Clean up the sink object, deleting the folder pidl and any
  78. // alloc'd junk we might add in the future.
  79. //
  80. // Arguments:
  81. // (none)
  82. //
  83. // Returns:
  84. //
  85. // Author: jeffspr 26 Aug 1998
  86. //
  87. // Notes:
  88. //
  89. CConnectionNotifySink::~CConnectionNotifySink()
  90. {
  91. TraceFileFunc(ttidNotifySink);
  92. if (FIsDebugFlagSet (dfidBreakOnNotifySinkRelease))
  93. {
  94. AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag "
  95. "\"BreakOnNotifySinkRelease\" has been set. Set your breakpoints now.");
  96. }
  97. TraceTag(ttidNotifySink, "Connection notify sink destroyed");
  98. }
  99. HRESULT CConnectionNotifySink::HrUpdateIncomingConnection()
  100. {
  101. HRESULT hr = S_OK;
  102. ConnListEntry cle;
  103. hr = g_ccl.HrFindRasServerConnection(cle);
  104. if (S_OK == hr)
  105. {
  106. hr = HrOnNotifyUpdateConnection(
  107. m_pidlFolder,
  108. &(cle.ccfe.GetGuidID()),
  109. cle.ccfe.GetNetConMediaType(),
  110. cle.ccfe.GetNetConSubMediaType(),
  111. cle.ccfe.GetNetConStatus(),
  112. cle.ccfe.GetCharacteristics(),
  113. cle.ccfe.GetName(),
  114. cle.ccfe.GetDeviceName(),
  115. cle.ccfe.GetPhoneOrHostAddress()
  116. );
  117. }
  118. return hr;
  119. }
  120. HRESULT
  121. CConnectionNotifySink::ConnectionAdded (
  122. const NETCON_PROPERTIES_EX* pPropsEx)
  123. {
  124. TraceFileFunc(ttidNotifySink);
  125. #ifdef DBG
  126. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  127. StringFromGUID2(pPropsEx->guidId, szGuidString, MAX_GUID_STRING_LEN);
  128. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionAdded - %S %S [%s:%s:%s:%s]",
  129. szGuidString, pPropsEx->bstrName, DbgNcm(pPropsEx->ncMediaType), DbgNcsm(pPropsEx->ncSubMediaType), DbgNcs(pPropsEx->ncStatus), DbgNccf(pPropsEx->dwCharacter) );
  130. #endif
  131. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  132. {
  133. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  134. return S_FALSE;
  135. }
  136. HRESULT hr = S_OK; // Only used for code paths. We don't return this.
  137. HRESULT hrFind = S_OK; // Only for finding the connection.
  138. PCONFOLDPIDL pidlNew;
  139. ConnListEntry cleDontCare;
  140. hrFind = g_ccl.HrFindConnectionByGuid(&(pPropsEx->guidId), cleDontCare);
  141. if (S_OK == hrFind)
  142. {
  143. // We already know about this connection. Don't bother added it.
  144. TraceTag(ttidShellFolder, "Ignoring known connection on ConnectionAdded notify");
  145. }
  146. else
  147. {
  148. // Create the entry in the connection list and get the returned pidl
  149. //
  150. hr = HrCreateConFoldPidl(
  151. *pPropsEx,
  152. pidlNew);
  153. if (SUCCEEDED(hr) && (!pidlNew.empty()))
  154. {
  155. CONFOLDENTRY cfe;
  156. Assert(!m_pidlFolder.empty());
  157. // Convert to the confoldentry
  158. //
  159. hr = pidlNew.ConvertToConFoldEntry(cfe);
  160. if (SUCCEEDED(hr))
  161. {
  162. // Insert the connection in the connection list
  163. //
  164. hr = g_ccl.HrInsert(cfe);
  165. if (SUCCEEDED(hr))
  166. {
  167. // Notify the shell that we have a new object
  168. //
  169. PCONFOLDPIDL pidlShellNotify;
  170. hr = cfe.ConvertToPidl(pidlShellNotify);
  171. if (SUCCEEDED(hr))
  172. {
  173. GenerateEvent(SHCNE_CREATE, m_pidlFolder, pidlShellNotify, NULL);
  174. }
  175. }
  176. // Don't delete the cfe here because the connection list now owns it.
  177. }
  178. }
  179. }
  180. if (SUCCEEDED(hr) &&
  181. (NCM_NONE != pPropsEx->ncMediaType) &&
  182. (pPropsEx->dwCharacter & NCCF_INCOMING_ONLY) )
  183. {
  184. hr = HrUpdateIncomingConnection();
  185. }
  186. return S_OK;
  187. }
  188. HRESULT
  189. CConnectionNotifySink::ConnectionBandWidthChange (
  190. const GUID* pguidId)
  191. {
  192. TraceFileFunc(ttidNotifySink);
  193. #ifdef DBG
  194. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  195. StringFromGUID2(*pguidId, szGuidString, MAX_GUID_STRING_LEN);
  196. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionBandWidthChange - %S", szGuidString);
  197. #endif
  198. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  199. {
  200. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  201. return S_FALSE;
  202. }
  203. HRESULT hr = S_OK;
  204. CNetStatisticsCentral * pnsc = NULL;
  205. hr = CNetStatisticsCentral::HrGetNetStatisticsCentral(&pnsc, FALSE);
  206. if (SUCCEEDED(hr))
  207. {
  208. pnsc->UpdateRasLinkList(pguidId);
  209. ReleaseObj(pnsc);
  210. }
  211. return S_OK;
  212. }
  213. HRESULT
  214. CConnectionNotifySink::ConnectionDeleted (
  215. const GUID* pguidId)
  216. {
  217. TraceFileFunc(ttidNotifySink);
  218. HRESULT hr = S_OK;
  219. HRESULT hrFind = S_OK;
  220. ConnListEntry cle;
  221. PCONFOLDPIDL pidlFind;
  222. BOOL fFlushPosts = FALSE;
  223. Assert(pguidId);
  224. Assert(!m_pidlFolder.empty());
  225. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  226. {
  227. TraceTag(ttidNotifySink, "CConnectionNotifySink::ConnectionDeleted event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  228. return S_FALSE;
  229. }
  230. // Find the connection using the GUID.
  231. //
  232. hrFind = g_ccl.HrFindConnectionByGuid(pguidId, cle);
  233. if (S_OK == hrFind)
  234. {
  235. #ifdef DBG
  236. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  237. StringFromGUID2(cle.ccfe.GetGuidID(), szGuidString, MAX_GUID_STRING_LEN);
  238. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionDeleted - %S %S [%s:%s:%s:%s]", szGuidString, cle.ccfe.GetName(),
  239. DbgNcm(cle.ccfe.GetNetConMediaType()), DbgNcsm(cle.ccfe.GetNetConSubMediaType()), DbgNcs(cle.ccfe.GetNetConStatus()), DbgNccf(cle.ccfe.GetCharacteristics()));
  240. #endif
  241. // Very important to release the lock before doing any thing which
  242. // calls back into the shell. (e.g. GenerateEvent)
  243. const CONFOLDENTRY &ccfe = cle.ccfe;
  244. // Get the pidl for the connection so we can use it to notify
  245. // the shell further below.
  246. //
  247. ccfe.ConvertToPidl(pidlFind);
  248. // Remove this connection from the global list while we
  249. // have the lock held.
  250. //
  251. hr = g_ccl.HrRemove(cle.ccfe, &fFlushPosts);
  252. }
  253. else
  254. {
  255. TraceTag(ttidShellFolder, "Notify: Delete <item not found in cache>. hr = 0x%08x", hr);
  256. }
  257. // If we need to flush the posts after making tray icon changes, do so
  258. //
  259. if (g_hwndTray && fFlushPosts)
  260. {
  261. FlushTrayPosts(g_hwndTray);
  262. }
  263. if (SUCCEEDED(hr) && (!pidlFind.empty()))
  264. {
  265. GenerateEvent(SHCNE_DELETE, m_pidlFolder, pidlFind, NULL);
  266. }
  267. if (SUCCEEDED(hr))
  268. {
  269. hr = HrUpdateIncomingConnection();
  270. }
  271. // Only return S_OK from here.
  272. //
  273. return S_OK;
  274. }
  275. HRESULT
  276. CConnectionNotifySink::ConnectionModified (
  277. const NETCON_PROPERTIES_EX* pPropsEx)
  278. {
  279. TraceFileFunc(ttidNotifySink);
  280. Assert(pPropsEx);
  281. Assert(!m_pidlFolder.empty());
  282. #ifdef DBG
  283. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  284. StringFromGUID2(pPropsEx->guidId, szGuidString, MAX_GUID_STRING_LEN);
  285. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionModified - %S %S [%s:%s:%s:%s]", szGuidString, pPropsEx->bstrName,
  286. DbgNcm(pPropsEx->ncMediaType), DbgNcsm(pPropsEx->ncSubMediaType), DbgNcs(pPropsEx->ncStatus), DbgNccf(pPropsEx->dwCharacter));
  287. #endif
  288. if (g_dwCurrentEventLevel <= EVT_LVL_ENABLE_PRIVATE)
  289. {
  290. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  291. return S_FALSE;
  292. }
  293. // Get the result for debugging only. We never want to fail this function
  294. //
  295. HRESULT hrTmp = HrOnNotifyUpdateConnection(
  296. m_pidlFolder,
  297. (GUID *)&(pPropsEx->guidId),
  298. pPropsEx->ncMediaType,
  299. pPropsEx->ncSubMediaType,
  300. pPropsEx->ncStatus,
  301. pPropsEx->dwCharacter,
  302. pPropsEx->bstrName,
  303. pPropsEx->bstrDeviceName,
  304. pPropsEx->bstrPhoneOrHostAddress);
  305. return S_OK;
  306. }
  307. HRESULT
  308. CConnectionNotifySink::ConnectionRenamed (
  309. const GUID* pguidId,
  310. PCWSTR pszwNewName)
  311. {
  312. TraceFileFunc(ttidNotifySink);
  313. HRESULT hr = S_OK;
  314. PCONFOLDPIDL pidlNew;
  315. Assert(pguidId);
  316. Assert(pszwNewName);
  317. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  318. {
  319. TraceTag(ttidNotifySink, "CConnectionNotifySink::ConnectionRenamed event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  320. return S_FALSE;
  321. }
  322. // Update the name in the cache
  323. //
  324. // Note: There exists a race condition with shutil.cpp:
  325. // HrRenameConnectionInternal\HrUpdateNameByGuid can also update the cache.
  326. ConnListEntry cle;
  327. hr = g_ccl.HrFindConnectionByGuid(pguidId, cle);
  328. if (FAILED(hr))
  329. {
  330. return E_INVALIDARG;
  331. }
  332. #ifdef DBG
  333. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  334. StringFromGUID2(cle.ccfe.GetGuidID(), szGuidString, MAX_GUID_STRING_LEN);
  335. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionRenamed - %S %S (to %S) [%s:%s:%s:%s]", szGuidString, cle.ccfe.GetName(), pszwNewName,
  336. DbgNcm(cle.ccfe.GetNetConMediaType()), DbgNcsm(cle.ccfe.GetNetConSubMediaType()), DbgNcs(cle.ccfe.GetNetConStatus()), DbgNccf(cle.ccfe.GetCharacteristics()));
  337. #endif
  338. hr = g_ccl.HrUpdateNameByGuid(
  339. (GUID *) pguidId,
  340. (PWSTR) pszwNewName,
  341. pidlNew,
  342. TRUE); // Force the update -- this is a notification, not a request
  343. if (S_OK == hr)
  344. {
  345. PCONFOLDPIDL pidl;
  346. cle.ccfe.ConvertToPidl(pidl);
  347. GenerateEvent(
  348. SHCNE_RENAMEITEM,
  349. m_pidlFolder,
  350. pidl,
  351. pidlNew.GetItemIdList());
  352. // Update status monitor title (RAS case)
  353. CNetStatisticsCentral * pnsc = NULL;
  354. hr = CNetStatisticsCentral::HrGetNetStatisticsCentral(&pnsc, FALSE);
  355. if (SUCCEEDED(hr))
  356. {
  357. pnsc->UpdateTitle(pguidId, pszwNewName);
  358. ReleaseObj(pnsc);
  359. }
  360. }
  361. else
  362. {
  363. // If the connection wasn't found in the cache, then it's likely that
  364. // the notification engine is giving us a notification for a connection
  365. // that hasn't yet been given to us.
  366. //
  367. if (S_FALSE == hr)
  368. {
  369. TraceHr(ttidShellFolder, FAL, hr, FALSE, "Rename notification received on a connection we don't know about");
  370. }
  371. }
  372. return S_OK;
  373. }
  374. HRESULT
  375. CConnectionNotifySink::ConnectionStatusChange (
  376. const GUID* pguidId,
  377. NETCON_STATUS Status)
  378. {
  379. TraceFileFunc(ttidNotifySink);
  380. HRESULT hr = S_OK;
  381. HRESULT hrFind = S_OK;
  382. PCONFOLDPIDL pidlFind;
  383. if (g_dwCurrentEventLevel <= EVT_LVL_ENABLE_PRIVATE)
  384. {
  385. TraceTag(ttidNotifySink, "CConnectionNotifySink::ConnectionStatusChange event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  386. return S_FALSE;
  387. }
  388. // Find the connection using the GUID. Cast the const away from the GUID
  389. //
  390. hrFind = g_ccl.HrFindPidlByGuid((GUID *) pguidId, pidlFind);
  391. if( S_OK != hrFind )
  392. {
  393. GUID guidOwner;
  394. // We did not find the guid in connection folder. Try finding the connection in the
  395. // hidden connectiod list on netmans side.
  396. //
  397. hr = g_ccl.HrMapCMHiddenConnectionToOwner(*pguidId, &guidOwner);
  398. if (S_OK == hr)
  399. {
  400. // The conection has a parent!!!! Use the childs status instead of the parents status.
  401. //
  402. if (Status == NCS_CONNECTED)
  403. {
  404. // This means that the child has connected and the parent still has to connect
  405. // the overall status should stay as connected. This was done to overrule the Multi-link
  406. // hack in HrOnNotifyUpdateStatus. If we did not do this it would say :
  407. // Child( Connecting, Connected) and then Parent(Connecting, Connected)
  408. //
  409. Status = NCS_CONNECTING;
  410. }
  411. // Get the pidl of the parent.
  412. //
  413. hrFind = g_ccl.HrFindPidlByGuid(&guidOwner, pidlFind);
  414. }
  415. }
  416. if (S_OK == hrFind)
  417. {
  418. #ifdef DBG
  419. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  420. StringFromGUID2(pidlFind->guidId, szGuidString, MAX_GUID_STRING_LEN);
  421. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionStatusChange - %S %S [%s:%s:%s:%s]", szGuidString, pidlFind->PszGetNamePointer(),
  422. DbgNcm(pidlFind->ncm), DbgNcsm(pidlFind->ncsm), DbgNcs(Status), DbgNccf(pidlFind->dwCharacteristics));
  423. #endif
  424. hr = HrOnNotifyUpdateStatus(m_pidlFolder, pidlFind, Status);
  425. }
  426. return S_OK;
  427. }
  428. HRESULT
  429. CConnectionNotifySink::RefreshAll ()
  430. {
  431. TraceFileFunc(ttidNotifySink);
  432. #ifdef DBG
  433. TraceTag(ttidNotifySink, "INetConnectionNotifySink::RefreshAll");
  434. #endif
  435. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  436. {
  437. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  438. return S_FALSE;
  439. }
  440. // Refresh the connections folder, without having to hook the shell view.
  441. // In this case, we do a non-flush refresh where we compare the new set
  442. // of items to the cached set and do the merge (with the correct set
  443. // of individual notifications).
  444. //
  445. (VOID) HrForceRefreshNoFlush(m_pidlFolder);
  446. return S_OK;
  447. }
  448. HRESULT CConnectionNotifySink::ConnectionAddressChange (
  449. const GUID* pguidId )
  450. {
  451. // Find the connection using the GUID.
  452. //
  453. PCONFOLDPIDL pidlFind;
  454. HRESULT hr = g_ccl.HrFindPidlByGuid(pguidId, pidlFind);
  455. if (S_OK != hr)
  456. {
  457. return E_INVALIDARG;
  458. }
  459. #ifdef DBG
  460. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  461. StringFromGUID2(pidlFind->guidId, szGuidString, MAX_GUID_STRING_LEN);
  462. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ConnectionAddressChange - %S %S [%s:%s:%s:%s]", szGuidString, pidlFind->PszGetNamePointer(),
  463. DbgNcm(pidlFind->ncm), DbgNcsm(pidlFind->ncsm), DbgNcs(pidlFind->ncs), DbgNccf(pidlFind->dwCharacteristics));
  464. #endif
  465. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  466. {
  467. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  468. return S_FALSE;
  469. }
  470. PCONFOLDPIDLFOLDER pidlFolder;
  471. hr = HrGetConnectionsFolderPidl(pidlFolder);
  472. if (SUCCEEDED(hr))
  473. {
  474. GenerateEvent(SHCNE_UPDATEITEM, pidlFolder, pidlFind, NULL);
  475. }
  476. return hr;
  477. }
  478. DWORD WINAPI OnTaskBarIconBalloonClickThread(LPVOID lpParam);
  479. STDMETHODIMP CConnectionNotifySink::ShowBalloon(
  480. IN const GUID* pguidId,
  481. IN const BSTR szCookie,
  482. IN const BSTR szBalloonText)
  483. {
  484. HRESULT hr;
  485. #ifdef DBG
  486. OLECHAR szGuidString[MAX_GUID_STRING_LEN];
  487. StringFromGUID2(*pguidId, szGuidString, MAX_GUID_STRING_LEN);
  488. TraceTag(ttidNotifySink, "INetConnectionNotifySink::ShowBalloon - %S (%S)", szGuidString, szBalloonText);
  489. #endif
  490. if (g_dwCurrentEventLevel <= EVT_LVL_DISABLE_ALL)
  491. {
  492. TraceTag(ttidNotifySink, "Last event ignored due to g_dwCurrentEventLevel == %d", g_dwCurrentEventLevel);
  493. return S_FALSE;
  494. }
  495. CComBSTR szBalloonTextTmp = szBalloonText;
  496. BSTR szCookieTmp = NULL;
  497. if (szCookie)
  498. {
  499. szCookieTmp = SysAllocStringByteLen(reinterpret_cast<LPCSTR>(szCookie), SysStringByteLen(szCookie));
  500. }
  501. ConnListEntry cleFind;
  502. hr = g_ccl.HrFindConnectionByGuid(pguidId, cleFind);
  503. if (S_OK == hr)
  504. {
  505. hr = WZCCanShowBalloon(pguidId, cleFind.ccfe.GetName(), &szBalloonTextTmp, &szCookieTmp);
  506. if ( (S_OK == hr) || (S_OBJECT_NO_LONGER_VALID == hr) )
  507. {
  508. CTrayBalloon *pTrayBalloon = new CTrayBalloon();
  509. if (!pTrayBalloon)
  510. {
  511. hr = E_OUTOFMEMORY;
  512. }
  513. else
  514. {
  515. pTrayBalloon->m_gdGuid = *pguidId;
  516. pTrayBalloon->m_dwTimeOut = 30 * 1000;
  517. pTrayBalloon->m_szMessage = szBalloonTextTmp;
  518. pTrayBalloon->m_pfnFuncCallback = WZCOnBalloonClick;
  519. pTrayBalloon->m_szCookie = szCookieTmp;
  520. pTrayBalloon->m_szAdapterName = cleFind.ccfe.GetName();
  521. if (S_OK == hr)
  522. {
  523. PostMessage(g_hwndTray, MYWM_SHOWBALLOON,
  524. NULL,
  525. (LPARAM) pTrayBalloon);
  526. }
  527. else // S_OBJECT_NO_LONGER_VALID == hr
  528. {
  529. CreateThread(NULL, STACK_SIZE_SMALL, OnTaskBarIconBalloonClickThread, pTrayBalloon, 0, NULL);
  530. }
  531. }
  532. }
  533. }
  534. if (S_OK != hr)
  535. {
  536. SysFreeString(szCookieTmp);
  537. }
  538. TraceHr(ttidError, FAL, hr, FALSE,
  539. "CConnectionNotifySink::ShowBalloon");
  540. return hr;
  541. }
  542. UINT_PTR uipTimer = NULL;
  543. VOID CALLBACK EventTimerProc(
  544. HWND hwnd, // handle to window
  545. UINT uMsg, // WM_TIMER message
  546. UINT_PTR idEvent, // timer identifier
  547. DWORD dwTime // current system time
  548. )
  549. {
  550. HRESULT hr = S_OK;
  551. TraceTag(ttidNotifySink, "Refreshing the folder due to DisableEvents timeout reached");
  552. g_dwCurrentEventLevel = EVT_LVL_ENABLE_ALL;
  553. if (uipTimer)
  554. {
  555. KillTimer(NULL, uipTimer);
  556. uipTimer = NULL;
  557. }
  558. PCONFOLDPIDLFOLDER pcfpFolder;
  559. hr = HrGetConnectionsFolderPidl(pcfpFolder);
  560. if (SUCCEEDED(hr))
  561. {
  562. HrForceRefreshNoFlush(pcfpFolder);
  563. }
  564. }
  565. STDMETHODIMP CConnectionNotifySink::DisableEvents (
  566. IN const BOOL fDisable,
  567. IN const ULONG ulDisableTimeout)
  568. {
  569. #ifdef DBG
  570. TraceTag(ttidNotifySink, "INetConnectionNotifySink::DisableEvents - %s 0x%08x", fDisable ? "DISABLE" : "ENABLE", ulDisableTimeout);
  571. #endif
  572. HRESULT hr = S_OK;
  573. if (fDisable)
  574. {
  575. if (HIWORD(ulDisableTimeout) & 0x8000)
  576. {
  577. // Called from private interface - disable all the events
  578. g_dwCurrentEventLevel = EVT_LVL_DISABLE_ALL;
  579. }
  580. else
  581. {
  582. // Called from public interface - only disable connection modified & status change events
  583. g_dwCurrentEventLevel = EVT_LVL_ENABLE_PRIVATE;
  584. }
  585. UINT uiEventTimeOut = LOWORD(ulDisableTimeout);
  586. if (uipTimer)
  587. {
  588. KillTimer(NULL, uipTimer);
  589. uipTimer = NULL;
  590. }
  591. uipTimer = SetTimer(NULL, NULL, uiEventTimeOut, EventTimerProc);
  592. }
  593. else
  594. {
  595. g_dwCurrentEventLevel = EVT_LVL_ENABLE_ALL;
  596. if (uipTimer)
  597. {
  598. KillTimer(NULL, uipTimer);
  599. uipTimer = NULL;
  600. }
  601. else
  602. {
  603. hr = S_FALSE; // Timer no more.
  604. }
  605. HrForceRefreshNoFlush(m_pidlFolder);
  606. }
  607. return hr;
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // Function: HrGetNotifyConPoint
  612. //
  613. // Purpose: Common code for getting the connection point for use in
  614. // NotifyAdd and NotifyRemove
  615. //
  616. // Arguments:
  617. // ppConPoint [out] Return ptr for IConnectionPoint
  618. //
  619. // Returns:
  620. //
  621. // Author: jeffspr 24 Aug 1998
  622. //
  623. // Notes:
  624. //
  625. HRESULT HrGetNotifyConPoint(
  626. IConnectionPoint ** ppConPoint)
  627. {
  628. TraceFileFunc(ttidNotifySink);
  629. HRESULT hr = S_OK;
  630. IConnectionPointContainer * pContainer = NULL;
  631. Assert(ppConPoint);
  632. // Get the debug interface from the connection manager
  633. //
  634. hr = HrCreateInstance(
  635. CLSID_ConnectionManager,
  636. CLSCTX_LOCAL_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  637. &pContainer);
  638. TraceHr(ttidError, FAL, hr, FALSE,
  639. "HrCreateInstance(CLSID_ConnectionManager) for IConnectionPointContainer");
  640. if (SUCCEEDED(hr))
  641. {
  642. IConnectionPoint * pConPoint = NULL;
  643. // Get the connection point itself and fill in the return param
  644. // on success
  645. //
  646. hr = pContainer->FindConnectionPoint(
  647. IID_INetConnectionNotifySink,
  648. &pConPoint);
  649. TraceHr(ttidError, FAL, hr, FALSE, "pContainer->FindConnectionPoint");
  650. if (SUCCEEDED(hr))
  651. {
  652. NcSetProxyBlanket (pConPoint);
  653. *ppConPoint = pConPoint;
  654. }
  655. ReleaseObj(pContainer);
  656. }
  657. TraceHr(ttidError, FAL, hr, FALSE, "HrGetNotifyConPoint");
  658. return hr;
  659. }