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.

975 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: T F I N D . C P P
  7. //
  8. // Contents: Asynchronous find mechanism for UPnP tray monitor.
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 22 Nov 1999
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <wininet.h>
  18. #include "tfind.h"
  19. #include "clist.h"
  20. #include "clistndn.h"
  21. #include "tconst.h"
  22. extern UINT g_iTotalBalloons;
  23. CListString g_CListUDN;
  24. CListString g_CListUDNSearch;
  25. CListNDN g_CListNewDeviceNode;
  26. CListNameMap g_CListNameMap;
  27. BOOL g_fIconPresent = FALSE;
  28. // (tongl)
  29. // List of devices currently on the network
  30. // This is the cached device list to show in "My Network Places" folder
  31. CListFolderDeviceNode g_CListFolderDeviceNode;
  32. CRITICAL_SECTION g_csFolderDeviceList;
  33. // CLSID_NetworkNeighborhood
  34. CONST WCHAR c_szNetworkNeighborhoodFolderPath[] = L"::{208D2C60-3AEA-1069-A2D7-08002B30309D}\\";
  35. // CLSID UPnP Delegate Folder - note "," is used for the new parse syntax (guru)
  36. CONST WCHAR c_szUPnPFolderPath[] = L"::{e57ce731-33e8-4c51-8354-bb4de9d215d1},";
  37. CONST WCHAR c_szDelegateFolderPrefix[] = L"__upnpitem:";
  38. CONST SIZE_T c_cchDelegateFolderPrefix = celems(c_szDelegateFolderPrefix) - 1;
  39. BOOL CListFolderDeviceNode::FCompare(FolderDeviceNode * pNode, PCWSTR pszUDN)
  40. {
  41. // see whether UDNs match between two device nodes
  42. Assert(pNode);
  43. Assert(pszUDN);
  44. return (wcscmp(pNode->pszUDN, pszUDN) == 0);
  45. }
  46. BOOL CListNDN::FCompare(NewDeviceNode * pNode, LPCTSTR pszUDN)
  47. {
  48. // see whether UDNs match between two device nodes
  49. Assert(pNode);
  50. Assert(pszUDN);
  51. return (_tcscmp(pNode->pszUDN, pszUDN) == 0);
  52. }
  53. BOOL CListString::FCompare(LPTSTR pszCurrentNodeString, LPCTSTR pszKey)
  54. {
  55. // see whether UDNs match between two device nodes
  56. Assert(pszCurrentNodeString);
  57. Assert(pszKey);
  58. return (_tcscmp(pszCurrentNodeString, pszKey) == 0);
  59. }
  60. BOOL CListNameMap::FCompare(NAME_MAP *pnm, LPCTSTR szUdn)
  61. {
  62. // see whether UDNs match between two device nodes
  63. Assert(pnm);
  64. Assert(szUdn);
  65. return (_tcscmp(pnm->szUdn, szUdn) == 0);
  66. }
  67. TCHAR * BSTRToTsz(BSTR bstrInput)
  68. {
  69. return TszFromWsz(bstrInput);
  70. }
  71. // The string created is:
  72. // "::CLSID_NetworkNeighborhood\\__upnpitem:UPNP_device_UDN"
  73. //
  74. // The new shell changes
  75. // "::CLSID_NetworkNeighborhood\\::GUID for UPnP Delegate Folder,<parse string>
  76. // <parse string > __upnpitem:UDN of the device
  77. LPWSTR
  78. CreateChangeNotifyString(LPCWSTR pszUdn)
  79. {
  80. LPWSTR pszNotifyString;
  81. pszNotifyString = new WCHAR [ MAX_PATH ];
  82. if (pszNotifyString)
  83. {
  84. Assert((celems(c_szNetworkNeighborhoodFolderPath) +
  85. celems(c_szDelegateFolderPrefix)) < MAX_PATH);
  86. CONST SIZE_T cchMax = MAX_PATH
  87. - (celems(c_szNetworkNeighborhoodFolderPath) * sizeof(WCHAR))
  88. - (celems(c_szUPnPFolderPath) * sizeof(WCHAR))
  89. - (celems(c_szDelegateFolderPrefix) * sizeof(WCHAR))
  90. + 2; // +2 we have subtracted Three null characters
  91. // note: we know that the folder path and the prefix can fit
  92. // in the MAX_PATH buffer
  93. wcscpy(pszNotifyString, c_szNetworkNeighborhoodFolderPath);
  94. wcscat(pszNotifyString, c_szUPnPFolderPath);
  95. wcscat(pszNotifyString, c_szDelegateFolderPrefix);
  96. wcsncat(pszNotifyString, pszUdn, cchMax);
  97. }
  98. else
  99. {
  100. TraceTag(ttidShellFolder, "CreateChangeNotifyString: new failed");
  101. }
  102. return pszNotifyString;
  103. }
  104. //+---------------------------------------------------------------------------
  105. //
  106. // Function: NewDeviceNode::NewDeviceNode
  107. //
  108. // Purpose: Initializes a NewDeviceNode structure.
  109. //
  110. // Notes:
  111. //
  112. NewDeviceNode::NewDeviceNode()
  113. {
  114. pszUDN = NULL;
  115. pszDisplayName = NULL;
  116. pszType = NULL;
  117. pszPresentationURL = NULL;
  118. pszManufacturerName = NULL;
  119. pszModelName = NULL;
  120. pszModelNumber = NULL;
  121. pszDescription = NULL;
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Function: NewDeviceNode::~NewDeviceNode
  126. //
  127. // Purpose: Deletes a NewDeviceNode structure.
  128. //
  129. // Author: donryan 18 Feb 2000
  130. //
  131. // Notes: Moved from CUPnPMonitorDeviceFinderCallback::DeviceAdded
  132. //
  133. NewDeviceNode::~NewDeviceNode()
  134. {
  135. delete pszUDN;
  136. delete pszDisplayName;
  137. delete pszType;
  138. delete pszPresentationURL;
  139. delete pszManufacturerName;
  140. delete pszModelName;
  141. delete pszModelNumber;
  142. delete pszDescription;
  143. }
  144. //+---------------------------------------------------------------------------
  145. //
  146. // Function: HrMapUdnToFriendlyName
  147. //
  148. // Purpose: Given a UPnP device and UDN, maps the UDN to a friendly name
  149. // from the registry if it is present, otherwise falls back to
  150. // the friendly name from the device
  151. //
  152. // Arguments:
  153. // pdev [in] UPnP device to check
  154. // bstrUdn [in] UDN of device
  155. // pbstrName [out] Returns friendly name of device
  156. //
  157. // Returns: S_OK if success, E_OUTOFMEMORY if no memory, or Win32 error
  158. // code
  159. //
  160. // Author: danielwe 2000/10/25
  161. //
  162. // Notes:
  163. //
  164. HRESULT HrMapUdnToFriendlyName(IUPnPDevice *pdev, BSTR bstrUdn, BSTR *pbstrName)
  165. {
  166. HRESULT hr = S_OK;
  167. NAME_MAP * pnm = NULL;
  168. Assert(pbstrName);
  169. *pbstrName = NULL;
  170. if (g_CListNameMap.FFind(bstrUdn, &pnm))
  171. {
  172. Assert(pnm);
  173. *pbstrName = SysAllocString(pnm->szName);
  174. if (!*pbstrName)
  175. {
  176. hr = E_OUTOFMEMORY;
  177. }
  178. }
  179. else
  180. {
  181. // UDN doesn't have a mapping in registry. Fall back to device's
  182. // friendly name
  183. //
  184. hr = pdev->get_FriendlyName(pbstrName);
  185. }
  186. TraceError("HrMapUdnToFriendlyName", hr);
  187. return hr;
  188. }
  189. //+---------------------------------------------------------------------------
  190. //
  191. // Function: HrCreateDeviceNodeFromDevice
  192. //
  193. // Purpose: Utility function to transfer information from device object
  194. // into NewDeviceNode structure.
  195. //
  196. // Arguments:
  197. // pDevice [in] The device pointer
  198. // ppNDN [out] The pointer to the NewDeviceNode pointer.
  199. //
  200. // Returns:
  201. //
  202. // Author: donryan 18 Feb 2000
  203. //
  204. // Notes: Moved from CUPnPMonitorDeviceFinderCallback::DeviceAdded
  205. //
  206. HRESULT
  207. HrCreateDeviceNodeFromDevice(
  208. IUPnPDevice * pDevice,
  209. NewDeviceNode ** ppNDN
  210. )
  211. {
  212. HRESULT hr = S_OK;
  213. BSTR bstrUDN = NULL;
  214. BSTR bstrDisplayName = NULL;
  215. BSTR bstrType = NULL;
  216. BSTR bstrPresentationURL = NULL;
  217. BSTR bstrManufacturerName = NULL;
  218. BSTR bstrModelName = NULL;
  219. BSTR bstrModelNumber = NULL;
  220. BSTR bstrDescription = NULL;
  221. PTSTR pszUDN = NULL;
  222. NewDeviceNode * pNDN = NULL;
  223. Assert(pDevice);
  224. Assert(ppNDN);
  225. hr = pDevice->get_UniqueDeviceName(&bstrUDN);
  226. if (FAILED(hr))
  227. {
  228. TraceTag(ttidShellTray, "Error calling pDevice->get_UniqueDeviceName");
  229. goto Exit;
  230. }
  231. hr = HrMapUdnToFriendlyName(pDevice, bstrUDN, &bstrDisplayName);
  232. if (FAILED(hr))
  233. {
  234. goto Exit;
  235. }
  236. hr = pDevice->get_Type(&bstrType);
  237. if (FAILED(hr))
  238. {
  239. TraceTag(ttidShellTray, "Error calling pDevice->get_Type");
  240. goto Exit;
  241. }
  242. hr = pDevice->get_PresentationURL(&bstrPresentationURL);
  243. if (FAILED(hr))
  244. {
  245. TraceTag(ttidShellTray, "Error calling pDevice->get_PresentationURL");
  246. goto Exit;
  247. }
  248. hr = pDevice->get_ManufacturerName(&bstrManufacturerName);
  249. if (FAILED(hr))
  250. {
  251. TraceTag(ttidShellTray, "Error calling pDevice->get_ManufacturerName");
  252. goto Exit;
  253. }
  254. hr = pDevice->get_ModelName(&bstrModelName);
  255. if (FAILED(hr))
  256. {
  257. TraceTag(ttidShellTray, "Error calling pDevice->get_ModelName");
  258. goto Exit;
  259. }
  260. hr = pDevice->get_ModelNumber(&bstrModelNumber);
  261. if (FAILED(hr))
  262. {
  263. TraceTag(ttidShellTray, "Error calling pDevice->get_ModelNumber");
  264. goto Exit;
  265. }
  266. hr = pDevice->get_Description(&bstrDescription);
  267. if (FAILED(hr))
  268. {
  269. TraceTag(ttidShellTray, "Error calling pDevice->get_Description");
  270. goto Exit;
  271. }
  272. // Create a new Device node, copy the strings into it, and add it to the device map
  273. //
  274. pNDN = new NewDeviceNode;
  275. if (pNDN)
  276. {
  277. Assert(bstrUDN);
  278. pNDN->pszUDN = BSTRToTsz(bstrUDN);
  279. Assert(bstrDisplayName);
  280. pNDN->pszDisplayName = BSTRToTsz(bstrDisplayName);
  281. Assert(bstrType);
  282. pNDN->pszType = BSTRToTsz(bstrType);
  283. if (bstrPresentationURL)
  284. {
  285. pNDN->pszPresentationURL = BSTRToTsz(bstrPresentationURL);
  286. }
  287. else
  288. {
  289. pNDN->pszPresentationURL = new TCHAR [ 1 ];
  290. if (pNDN->pszPresentationURL)
  291. {
  292. pNDN->pszPresentationURL[0] = TEXT('\0');
  293. }
  294. }
  295. Assert(bstrManufacturerName);
  296. pNDN->pszManufacturerName = BSTRToTsz(bstrManufacturerName);
  297. Assert(bstrModelName);
  298. pNDN->pszModelName = BSTRToTsz(bstrModelName);
  299. if (bstrModelNumber)
  300. {
  301. pNDN->pszModelNumber = BSTRToTsz(bstrModelNumber);
  302. }
  303. else
  304. {
  305. pNDN->pszModelNumber = new TCHAR [ 1 ];
  306. if (pNDN->pszModelNumber)
  307. {
  308. pNDN->pszModelNumber[0] = TEXT('\0');
  309. }
  310. }
  311. if (bstrDescription)
  312. {
  313. pNDN->pszDescription = BSTRToTsz(bstrDescription);
  314. }
  315. else
  316. {
  317. pNDN->pszDescription = new TCHAR [ 1 ];
  318. if (pNDN->pszDescription)
  319. {
  320. pNDN->pszDescription[0] = TEXT('\0');
  321. }
  322. }
  323. // If they didn't all copy fine, delete them
  324. //
  325. if (!(pNDN->pszUDN && pNDN->pszDisplayName &&
  326. pNDN->pszType && pNDN->pszPresentationURL &&
  327. pNDN->pszManufacturerName && pNDN->pszModelName &&
  328. pNDN->pszModelNumber && pNDN->pszDescription))
  329. {
  330. hr = E_OUTOFMEMORY;
  331. delete pNDN;
  332. pNDN = NULL;
  333. }
  334. }
  335. else
  336. {
  337. TraceTag(ttidShellTray, "Could not allocate NewDeviceNode");
  338. hr = E_OUTOFMEMORY;
  339. }
  340. Exit:
  341. // transfer
  342. *ppNDN = pNDN;
  343. SysFreeString(bstrUDN);
  344. SysFreeString(bstrDisplayName);
  345. SysFreeString(bstrPresentationURL);
  346. SysFreeString(bstrType);
  347. SysFreeString(bstrManufacturerName);
  348. SysFreeString(bstrModelName);
  349. SysFreeString(bstrModelNumber);
  350. SysFreeString(bstrDescription);
  351. TraceHr(ttidShellTray, FAL, hr, FALSE, "HrCreateDeviceNodeFromDevice");
  352. return hr;
  353. }
  354. //+---------------------------------------------------------------------------
  355. //
  356. // Member: HrAddFolderDevice
  357. //
  358. // Purpose:
  359. //
  360. // Arguments:
  361. // pDevice
  362. //
  363. // Returns:
  364. //
  365. // Author: tongl 15 Feb 2000
  366. //
  367. // Notes:
  368. //
  369. HRESULT HrAddFolderDevice(IUPnPDevice * pDevice)
  370. {
  371. HRESULT hr = S_OK;
  372. BSTR bstrUDN = NULL;
  373. BSTR bstrDisplayName = NULL;
  374. BSTR bstrType = NULL;
  375. BSTR bstrPresentationURL = NULL;
  376. BSTR bstrDescription = NULL;
  377. // (tongl) Per cmr, some device property (display name, presentation url)
  378. // could change on an existing device and this function will be called but
  379. // the device was not first removed. In this case we need to notify shell
  380. // to first remove the existing device then add the new one.
  381. BOOL fUpdate = FALSE;
  382. BOOL fUpdateOldDevice = FALSE;
  383. // fNewNode - If its really a new device
  384. // fUpdate - The device is in MNP but must be updated bcoz device property has
  385. // changed. Note above.
  386. // fUpdateOldDevice - An old device has sent bye bye and later comes up alive
  387. // with same UDN. We have cached the list of UDNs.
  388. //
  389. Assert(pDevice);
  390. pDevice->AddRef();
  391. hr = pDevice->get_UniqueDeviceName(&bstrUDN);
  392. if (SUCCEEDED(hr))
  393. {
  394. // If we're doing a search right now, just add this UDN to the list
  395. // of devices that we've found so far in the search
  396. //
  397. if (g_fSearchInProgress)
  398. {
  399. if (!g_CListUDNSearch.FAdd(WszDupWsz(bstrUDN)))
  400. {
  401. hr = E_OUTOFMEMORY;
  402. }
  403. }
  404. }
  405. else
  406. {
  407. TraceTag(ttidShellFolder, "Failed in pDevice->get_UniqueDeviceName from HrAddFolderDevice");
  408. }
  409. if (SUCCEEDED(hr))
  410. {
  411. hr = HrMapUdnToFriendlyName(pDevice, bstrUDN, &bstrDisplayName);
  412. if (SUCCEEDED(hr))
  413. {
  414. hr = pDevice->get_Type(&bstrType);
  415. if (SUCCEEDED(hr))
  416. {
  417. hr = pDevice->get_PresentationURL(&bstrPresentationURL);
  418. if (SUCCEEDED(hr))
  419. {
  420. hr = pDevice->get_Description(&bstrDescription);
  421. if (SUCCEEDED(hr))
  422. {
  423. BOOL fNewNode;
  424. EnterCriticalSection(&g_csFolderDeviceList);
  425. FolderDeviceNode * pNewDevice = NULL;
  426. if( g_CListFolderDeviceNode.FFind((PWSTR)bstrUDN, &pNewDevice))
  427. {
  428. Assert(pNewDevice);
  429. fNewNode = FALSE;
  430. if (!pNewDevice->fDeleted)
  431. {
  432. // Only update if friendly name or description
  433. // changed.
  434. //
  435. if ((wcscmp(pNewDevice->pszDescription, bstrDescription)) ||
  436. (wcscmp(pNewDevice->pszDisplayName, bstrDisplayName)))
  437. {
  438. fUpdate = TRUE;
  439. }
  440. }
  441. else
  442. {
  443. fUpdateOldDevice = TRUE;
  444. }
  445. }
  446. else
  447. {
  448. // truely a new device
  449. pNewDevice = new FolderDeviceNode;
  450. fNewNode = TRUE;
  451. if (!pNewDevice)
  452. {
  453. hr = E_OUTOFMEMORY;
  454. }
  455. }
  456. if (pNewDevice)
  457. {
  458. CONST SIZE_T cchMax = MAX_PATH - 1;
  459. pNewDevice->fDeleted = FALSE;
  460. Assert(bstrUDN);
  461. wcscpy(pNewDevice->pszUDN, L"");
  462. wcsncat(pNewDevice->pszUDN,(PWSTR)bstrUDN, cchMax);
  463. Assert(bstrDisplayName);
  464. wcscpy(pNewDevice->pszDisplayName, L"");
  465. wcsncat(pNewDevice->pszDisplayName, bstrDisplayName, cchMax);
  466. Assert(bstrType);
  467. wcscpy(pNewDevice->pszType, L"");
  468. wcsncat(pNewDevice->pszType, (PWSTR)bstrType, cchMax);
  469. wcscpy(pNewDevice->pszPresentationURL, L"");
  470. if (bstrPresentationURL)
  471. {
  472. wcsncat(pNewDevice->pszPresentationURL,
  473. (PWSTR)bstrPresentationURL,
  474. cchMax);
  475. }
  476. wcscpy(pNewDevice->pszDescription, L"");
  477. if (bstrDescription)
  478. {
  479. wcsncat(pNewDevice->pszDescription,
  480. (PWSTR)bstrDescription,
  481. cchMax);
  482. }
  483. // add to our list if a true new device
  484. if (fNewNode)
  485. {
  486. g_CListFolderDeviceNode.FAdd(pNewDevice);
  487. TraceTag(ttidShellFolder, "HrAddFolderDevice: Added %S to g_CListFolderDeviceNode", bstrDisplayName);
  488. }
  489. else
  490. {
  491. TraceTag(ttidShellFolder, "HrAddFolderDevice: Modified %S in g_CListFolderDeviceNode", bstrDisplayName);
  492. }
  493. TraceTag(ttidShellFolder, "HrAddFolderDevice: Now, g_CListFolderDeviceNode has %d elements", g_CListFolderDeviceNode.GetCount());
  494. }
  495. LeaveCriticalSection(&g_csFolderDeviceList);
  496. if (fNewNode || fUpdate || fUpdateOldDevice)
  497. {
  498. if (SUCCEEDED(hr))
  499. {
  500. // notify shell to add the new device
  501. LPWSTR pszNotifyString;
  502. pszNotifyString = CreateChangeNotifyString(bstrUDN);
  503. if (pszNotifyString)
  504. {
  505. if (fUpdate)
  506. {
  507. TraceTag(ttidShellFolder, "Generating update device event for %S", bstrDisplayName);
  508. SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW, pszNotifyString, NULL);
  509. }
  510. else
  511. {
  512. // Assert(fNewNode);
  513. // fNewNode or fUpdateOldDevice
  514. TraceTag(ttidShellFolder, "Generating new device event for %S", bstrDisplayName);
  515. SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, pszNotifyString, NULL);
  516. }
  517. delete [] pszNotifyString;
  518. }
  519. }
  520. else
  521. {
  522. // Don't make a failure here.
  523. //
  524. TraceTag(ttidShellFolder, "Couldn't add device to list in CUPnPDeviceFolderDeviceFinderCallback::DeviceAdded");
  525. }
  526. }
  527. else
  528. {
  529. TraceTag(ttidShellFolder, "Nothing about device %S:%S changed", bstrUDN, bstrDisplayName);
  530. }
  531. }
  532. else
  533. {
  534. TraceTag(ttidShellFolder, "Failed in get_Description from HrAddFolderDevice");
  535. }
  536. }
  537. else
  538. {
  539. TraceTag(ttidShellFolder, "Failed in get_PresentationURL from HrAddFolderDevice");
  540. }
  541. }
  542. else
  543. {
  544. TraceTag(ttidShellFolder, "Failed in pDevice->get_Type from HrAddFolderDevice");
  545. }
  546. }
  547. else
  548. {
  549. TraceTag(ttidShellFolder, "Failed in pDevice->get_FriendlyName from HrAddFolderDevice");
  550. }
  551. }
  552. SysFreeString(bstrUDN);
  553. SysFreeString(bstrDisplayName);
  554. SysFreeString(bstrPresentationURL);
  555. SysFreeString(bstrType);
  556. SysFreeString(bstrDescription);
  557. pDevice->Release();
  558. TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "HrAddFolderDevice");
  559. return hr;
  560. }
  561. //+---------------------------------------------------------------------------
  562. //
  563. // Member: HrDeleteFolderDevice
  564. //
  565. // Purpose:
  566. //
  567. // Arguments:
  568. // szUDN
  569. //
  570. // Returns:
  571. //
  572. // Author: tongl 18 Feb 2000
  573. //
  574. // Notes:
  575. //
  576. HRESULT HrDeleteFolderDevice(PWSTR szUDN)
  577. {
  578. HRESULT hr = S_OK;
  579. FolderDeviceNode * pDevice = NULL;
  580. EnterCriticalSection(&g_csFolderDeviceList);
  581. if (g_CListFolderDeviceNode.FFind(szUDN, &pDevice))
  582. {
  583. pDevice->fDeleted = TRUE;
  584. }
  585. else
  586. {
  587. // can't delete a device that's not in our cache
  588. TraceTag(ttidShellFolder, "The device to delete is not in the cache: %S.", szUDN);
  589. hr = E_FAIL;
  590. }
  591. LeaveCriticalSection(&g_csFolderDeviceList);
  592. if (SUCCEEDED(hr))
  593. {
  594. // notify shell to delete the device
  595. LPWSTR pszNotifyString;
  596. pszNotifyString = CreateChangeNotifyString(szUDN);
  597. if (pszNotifyString)
  598. {
  599. TraceTag(ttidShellFolder, "Delete device event for %S", szUDN);
  600. SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, pszNotifyString, NULL);
  601. delete [] pszNotifyString;
  602. }
  603. else
  604. {
  605. hr = E_OUTOFMEMORY;
  606. }
  607. }
  608. TraceError("HrDeleteFolderDevice", hr);
  609. return hr;
  610. }
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Member: CUPnPMonitorDeviceFinderCallback::DeviceAdded
  614. //
  615. // Purpose: Our callback for "new device" -- duh. Here we get the
  616. // important properties, pack them in a struct, and store them
  617. // in our device list. We'll use this data if the user opens
  618. // properties on one of the dialogs, or adds shortcuts.
  619. //
  620. // Arguments:
  621. // lFindData [in] Our callback ID
  622. // pDevice [in] The device pointer.
  623. //
  624. // Returns:
  625. //
  626. // Author: jeffspr 23 Nov 1999
  627. //
  628. // Notes:
  629. //
  630. HRESULT CUPnPMonitorDeviceFinderCallback::DeviceAdded(LONG lFindData,
  631. IUPnPDevice * pDevice)
  632. {
  633. HRESULT hr = S_OK;
  634. NewDeviceNode * pNDN = NULL;
  635. Assert(pDevice);
  636. pDevice->AddRef();
  637. #if DBG
  638. BSTR bstrUDN = NULL;
  639. hr = pDevice->get_UniqueDeviceName(&bstrUDN);
  640. TraceTag(ttidShellTray, "DeviceFinderCallback -- New Device. SearchId: %x, UDN: %S",
  641. lFindData, bstrUDN);
  642. SysFreeString(bstrUDN);
  643. #endif // DBG
  644. BSTR bstrPresUrl;
  645. hr = pDevice->get_PresentationURL(&bstrPresUrl);
  646. if (S_OK == hr)
  647. {
  648. URL_COMPONENTS urlComp = {0};
  649. TraceTag(ttidShellTray, "Checking if %S is a valid URL...",
  650. bstrPresUrl);
  651. // All we want to do here is verify that the URL is valid. We don't
  652. // need anything back from this function
  653. //
  654. urlComp.dwStructSize = sizeof(URL_COMPONENTS);
  655. if (!InternetCrackUrl(bstrPresUrl, 0, 0, &urlComp))
  656. {
  657. TraceTag(ttidShellTray, "%S is NOT a valid URL!", bstrPresUrl);
  658. hr = HrFromLastWin32Error();
  659. }
  660. SysFreeString(bstrPresUrl);
  661. }
  662. else
  663. {
  664. hr = E_FAIL;
  665. TraceError("Device did not have presentation URL!", hr);
  666. }
  667. if (SUCCEEDED(hr))
  668. {
  669. // (tongl)
  670. // add the device to our folder device list and notify shell in case folder is open
  671. hr = HrAddFolderDevice(pDevice);
  672. if (SUCCEEDED(hr))
  673. {
  674. // transfer information from device object
  675. hr = HrCreateDeviceNodeFromDevice(pDevice, &pNDN);
  676. if (SUCCEEDED(hr))
  677. {
  678. // Assuming we don't already have this device is our list, add it.
  679. //
  680. if (!g_CListUDN.FFind(pNDN->pszUDN, NULL))
  681. {
  682. // Add it to the New Device list.
  683. //
  684. g_CListNewDeviceNode.FAdd(pNDN);
  685. // reset the total balloon count
  686. g_iTotalBalloons =0;
  687. }
  688. else
  689. {
  690. // Cleanup already known device
  691. //
  692. delete pNDN;
  693. }
  694. }
  695. }
  696. }
  697. pDevice->Release();
  698. if (SUCCEEDED(hr))
  699. {
  700. if (!g_fSearchInProgress)
  701. {
  702. hr = HrUpdateTrayInfo();
  703. }
  704. }
  705. TraceError("CUPnPMonitorDeviceFinderCallback::DeviceAdded", hr);
  706. return S_OK;
  707. }
  708. //+---------------------------------------------------------------------------
  709. //
  710. // Member: CUPnPMonitorDeviceFinderCallback::DeviceRemoved
  711. //
  712. // Purpose: Device removed notification. NYI
  713. //
  714. // Arguments:
  715. // lFindData []
  716. // bstrUDN []
  717. //
  718. // Returns:
  719. //
  720. // Author: jeffspr 23 Nov 1999
  721. //
  722. // Notes:
  723. //
  724. HRESULT CUPnPMonitorDeviceFinderCallback::DeviceRemoved(
  725. LONG lFindData,
  726. BSTR bstrUDN)
  727. {
  728. TraceTag(ttidShellTray, "CUPnPMonitorDeviceFinderCallback::DeviceRemoved"
  729. " lFindData = %x, UDN = %S", lFindData, bstrUDN);
  730. Assert(bstrUDN);
  731. // (tongl)
  732. // delete the device from our folder device list and notify shell in case folder is open
  733. HrDeleteFolderDevice((PWSTR)bstrUDN);
  734. HRESULT hr = S_OK;
  735. LPTSTR pszUdn;
  736. BOOL fResult;
  737. pszUdn = BSTRToTsz(bstrUDN);
  738. if (!pszUdn)
  739. {
  740. TraceTag(ttidShellTray, "Could not copy UDN to TCHAR");
  741. hr = E_OUTOFMEMORY;
  742. goto Exit;
  743. }
  744. // search through new device list for new node, removing any nodes
  745. // with matching UDNs
  746. //
  747. fResult = g_CListNewDeviceNode.FDelete(pszUdn);
  748. if (!fResult)
  749. {
  750. // node wasn't deleted
  751. TraceTag(ttidShellTray, "CUPnPMonitorDeviceFinderCallback::DeviceRemoved: "
  752. "%S not found in g_CListNewDeviceNode", pszUdn);
  753. }
  754. // update tray information if search has completed
  755. if (!g_fSearchInProgress)
  756. {
  757. hr = HrUpdateTrayInfo();
  758. }
  759. else
  760. {
  761. // search is still running so delete this from the search list
  762. fResult = g_CListUDNSearch.FDelete(pszUdn);
  763. if (!fResult)
  764. {
  765. // node wasn't deleted
  766. TraceTag(ttidShellTray, "CUPnPMonitorDeviceFinderCallback::DeviceRemoved: "
  767. "%S not found in g_CListUDNSearch", pszUdn);
  768. }
  769. }
  770. Exit:
  771. delete [] pszUdn;
  772. TraceError("CUPnPMonitorDeviceFinderCallback::DeviceRemoved", hr);
  773. return S_OK;
  774. }
  775. //+---------------------------------------------------------------------------
  776. //
  777. // Member: CUPnPMonitorDeviceFinderCallback::SearchComplete
  778. //
  779. // Purpose: Search complete. At this point I can add the tray icon
  780. // if needed and allow for the UI to come up.
  781. //
  782. // Arguments:
  783. // lFindData []
  784. //
  785. // Returns:
  786. //
  787. // Author: jeffspr 6 Jan 2000
  788. //
  789. // Notes:
  790. //
  791. HRESULT CUPnPMonitorDeviceFinderCallback::SearchComplete(LONG lFindData)
  792. {
  793. TraceTag(ttidShellTray, "CUPnPMonitorDeviceFinderCallback::SearchComplete"
  794. " lFindData = %x", lFindData);
  795. HRESULT hr = S_OK;
  796. g_fSearchInProgress = FALSE;
  797. // Add the tray icon and such (if appropriate)
  798. //
  799. hr = HrInitializeUI();
  800. if (SUCCEEDED(hr))
  801. {
  802. EnterCriticalSection(&g_csFolderDeviceList);
  803. FolderDeviceNode * pCurrentNode = NULL;
  804. BOOL fReturn = g_CListFolderDeviceNode.FFirst(&pCurrentNode);
  805. // Loop through all UDNs in the cached list of devices we've found
  806. // and for each one, see if it was found during the search. If not,
  807. // we should delete it from the folder view and from the cache.
  808. while (fReturn && SUCCEEDED(hr))
  809. {
  810. LPWSTR szUdn;
  811. if (!g_CListUDNSearch.FFind(pCurrentNode->pszUDN, &szUdn))
  812. {
  813. hr = HrDeleteFolderDevice(pCurrentNode->pszUDN);
  814. if (SUCCEEDED(hr))
  815. {
  816. if (!g_CListFolderDeviceNode.FDelete(pCurrentNode->pszUDN))
  817. {
  818. hr = E_FAIL;
  819. }
  820. }
  821. }
  822. // move to the next node
  823. fReturn = g_CListFolderDeviceNode.FNext(&pCurrentNode);
  824. }
  825. LeaveCriticalSection(&g_csFolderDeviceList);
  826. }
  827. g_CListUDNSearch.Flush();
  828. TraceError("CUPnPMonitorDeviceFinderCallback::SearchComplete", hr);
  829. return S_OK;
  830. }
  831. CUPnPMonitorDeviceFinderCallback::CUPnPMonitorDeviceFinderCallback()
  832. {
  833. m_pUnkMarshaler = NULL;
  834. TraceTag(ttidShellTray, "CUPnPMonitorDeviceFinderCallback");
  835. }
  836. CUPnPMonitorDeviceFinderCallback::~CUPnPMonitorDeviceFinderCallback()
  837. {
  838. TraceTag(ttidShellTray, "~CUPnPMonitorDeviceFinderCallback");
  839. }