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.

1217 lines
26 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // persist.cpp
  4. //
  5. // IPersistFolder for the cdfview class.
  6. //
  7. // History:
  8. //
  9. // 3/16/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "persist.h"
  18. #include "xmlutil.h"
  19. #include "cdfview.h"
  20. #include "bindstcb.h"
  21. #include "chanapi.h"
  22. #include "resource.h"
  23. #include <winineti.h> // MAX_CACHE_ENTRY_INFO_SIZE
  24. #include "dll.h"
  25. #define _SHDOCVW_
  26. #include <shdocvw.h>
  27. #include <mluisupp.h>
  28. //
  29. // Constructor and destructor
  30. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  31. //
  32. // *** CPersist::CPersist ***
  33. //
  34. // Constructor.
  35. //
  36. ////////////////////////////////////////////////////////////////////////////////
  37. CPersist::CPersist(
  38. void
  39. )
  40. : m_bCdfParsed(FALSE)
  41. {
  42. ASSERT(0 == *m_szPath);
  43. ASSERT(NULL == m_polestrURL);
  44. ASSERT(NULL == m_pIWebBrowser2);
  45. ASSERT(NULL == m_hwnd);
  46. ASSERT(NULL == m_pIXMLDocument);
  47. ASSERT(FALSE == m_fPendingNavigation);
  48. ASSERT(IT_UNKNOWN == m_rgInitType);
  49. return;
  50. }
  51. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  52. //
  53. // *** CPersist::CPersist ***
  54. //
  55. // Constructor.
  56. //
  57. ////////////////////////////////////////////////////////////////////////////////
  58. CPersist::CPersist(
  59. BOOL bCdfParsed
  60. )
  61. : m_bCdfParsed(bCdfParsed)
  62. {
  63. ASSERT(0 == *m_szPath);
  64. ASSERT(NULL == m_polestrURL);
  65. ASSERT(NULL == m_pIWebBrowser2);
  66. ASSERT(NULL == m_hwnd);
  67. ASSERT(NULL == m_pIXMLDocument);
  68. ASSERT(FALSE == m_fPendingNavigation);
  69. return;
  70. }
  71. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  72. //
  73. // *** CPersist::CPersist ***
  74. //
  75. // Constructor.
  76. //
  77. ////////////////////////////////////////////////////////////////////////////////
  78. CPersist::~CPersist(
  79. void
  80. )
  81. {
  82. if (m_fPendingNavigation && m_pIWebBrowser2 && m_pIXMLDocument)
  83. {
  84. }
  85. if (m_polestrURL)
  86. CoTaskMemFree(m_polestrURL);
  87. if (m_pIWebBrowser2)
  88. m_pIWebBrowser2->Release();
  89. if (m_pIXMLDocument)
  90. m_pIXMLDocument->Release();
  91. return;
  92. }
  93. //
  94. // IPersist methods.
  95. //
  96. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  97. //
  98. // *** CCdfView::GetClassID ***
  99. //
  100. //
  101. // Description:
  102. //
  103. //
  104. // Parameters:
  105. //
  106. //
  107. // Return:
  108. //
  109. //
  110. // Comments:
  111. //
  112. //
  113. ////////////////////////////////////////////////////////////////////////////////
  114. STDMETHODIMP
  115. CPersist::GetClassID(
  116. LPCLSID lpClassID
  117. )
  118. {
  119. ASSERT(lpClassID);
  120. //
  121. // REVIEW: Two possible class IDs CLSID_CDFVIEW & CLSID_CDF_INI
  122. //
  123. *lpClassID = CLSID_CDFVIEW;
  124. return S_OK;
  125. }
  126. //
  127. // IPersistFile methods.
  128. //
  129. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  130. //
  131. // *** CCdfView::IsDirty ***
  132. //
  133. //
  134. // Description:
  135. //
  136. //
  137. // Parameters:
  138. //
  139. //
  140. // Return:
  141. //
  142. //
  143. // Comments:
  144. //
  145. //
  146. ////////////////////////////////////////////////////////////////////////////////
  147. STDMETHODIMP
  148. CPersist::IsDirty(
  149. void
  150. )
  151. {
  152. return E_NOTIMPL;
  153. }
  154. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  155. //
  156. // *** CCdfView::Load ***
  157. //
  158. //
  159. // Description:
  160. //
  161. //
  162. // Parameters:
  163. //
  164. //
  165. // Return:
  166. //
  167. //
  168. // Comments:
  169. //
  170. //
  171. ////////////////////////////////////////////////////////////////////////////////
  172. STDMETHODIMP
  173. CPersist::Load(
  174. LPCOLESTR pszFileName,
  175. DWORD dwMode
  176. )
  177. {
  178. ASSERT(pszFileName);
  179. HRESULT hr;
  180. if (SHUnicodeToTChar(pszFileName, m_szPath, ARRAYSIZE(m_szPath)))
  181. {
  182. hr = S_OK;
  183. QuickCheckInitType();
  184. }
  185. else
  186. {
  187. hr = E_FAIL;
  188. }
  189. return hr;
  190. }
  191. void CPersist::QuickCheckInitType( void )
  192. {
  193. // if the path is a directory then
  194. // it has to be a Shellfolder we were initialised for.
  195. // we are calculating this here so that we can avoid hitting the disk
  196. // in GetInitType if at all possible.
  197. if (PathIsDirectory(m_szPath))
  198. {
  199. m_rgInitType = IT_INI;
  200. }
  201. }
  202. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  203. //
  204. // *** CCdfView::Save ***
  205. //
  206. //
  207. // Description:
  208. //
  209. //
  210. // Parameters:
  211. //
  212. //
  213. // Return:
  214. //
  215. //
  216. // Comments:
  217. //
  218. //
  219. ////////////////////////////////////////////////////////////////////////////////
  220. STDMETHODIMP
  221. CPersist::Save(
  222. LPCOLESTR pszFileName,
  223. BOOL fRemember
  224. )
  225. {
  226. return E_NOTIMPL;
  227. }
  228. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  229. //
  230. // *** CCdfView::SaveCompleted ***
  231. //
  232. //
  233. // Description:
  234. //
  235. //
  236. // Parameters:
  237. //
  238. //
  239. // Return:
  240. //
  241. //
  242. // Comments:
  243. //
  244. //
  245. ////////////////////////////////////////////////////////////////////////////////
  246. STDMETHODIMP
  247. CPersist::SaveCompleted(
  248. LPCOLESTR pszFileName
  249. )
  250. {
  251. return E_NOTIMPL;
  252. }
  253. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  254. //
  255. // *** CCdfView::GetCurFile ***
  256. //
  257. //
  258. // Description:
  259. //
  260. //
  261. // Parameters:
  262. //
  263. //
  264. // Return:
  265. //
  266. //
  267. // Comments:
  268. //
  269. //
  270. ////////////////////////////////////////////////////////////////////////////////
  271. STDMETHODIMP
  272. CPersist::GetCurFile(
  273. LPOLESTR* ppszFileName
  274. )
  275. {
  276. return E_NOTIMPL;
  277. }
  278. //
  279. // IPersistFolder methods.
  280. //
  281. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  282. //
  283. // *** CCdfView::Initialize ***
  284. //
  285. //
  286. // Description:
  287. // This function is called with the fully qualified id list (location) of
  288. // the selected cdf file.
  289. //
  290. // Parameters:
  291. // [In] pidl - The pidl of the selected cdf file. This pidl conatins the
  292. // full path to the CDF.
  293. //
  294. // Return:
  295. // S_OK if content for the cdf file could be created.
  296. // E_OUTOFMEMORY otherwise.
  297. //
  298. // Comments:
  299. // This function can be called more than once for a given folder. When a
  300. // CDFView is being instantiated from a desktop.ini file the shell calls
  301. // Initialize once before it calls GetUIObjectOf asking for IDropTarget.
  302. // After the GetUIObjectOf call the folder is Released. It then calls
  303. // Initialize again on a new folder. This time it keeps the folder and it
  304. // ends up being displayed.
  305. //
  306. ////////////////////////////////////////////////////////////////////////////////
  307. STDMETHODIMP
  308. CPersist::Initialize(
  309. LPCITEMIDLIST pidl
  310. )
  311. {
  312. ASSERT(pidl);
  313. ASSERT(0 == *m_szPath);
  314. HRESULT hr = SHGetPathFromIDList(pidl, m_szPath) ? S_OK : E_FAIL;
  315. QuickCheckInitType();
  316. return hr;
  317. }
  318. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  319. //
  320. // *** CPersist::Parse ***
  321. //
  322. //
  323. // Description:
  324. //
  325. //
  326. // Parameters:
  327. //
  328. //
  329. // Return:
  330. //
  331. //
  332. // Comments:
  333. //
  334. //
  335. ////////////////////////////////////////////////////////////////////////////////
  336. HRESULT
  337. CPersist::Parse(
  338. LPTSTR szURL,
  339. IXMLDocument** ppIXMLDocument
  340. )
  341. {
  342. ASSERT(szURL);
  343. HRESULT hr;
  344. DLL_ForcePreloadDlls(PRELOAD_MSXML);
  345. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  346. IID_IXMLDocument, (void**)ppIXMLDocument);
  347. BOOL bCoInit = FALSE;
  348. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  349. SUCCEEDED(CoInitialize(NULL)))
  350. {
  351. bCoInit = TRUE;
  352. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  353. IID_IXMLDocument, (void**)ppIXMLDocument);
  354. }
  355. if (SUCCEEDED(hr))
  356. {
  357. ASSERT(*ppIXMLDocument);
  358. hr = XML_SynchronousParse(*ppIXMLDocument, szURL);
  359. }
  360. if (bCoInit)
  361. CoUninitialize();
  362. return hr;
  363. }
  364. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  365. //
  366. // *** CCdfView::ParseCdf ***
  367. //
  368. //
  369. // Description:
  370. // Parses the cdf file associated with this folder.
  371. //
  372. // Parameters:
  373. // [In] hwndOwner - The parent window of any dialogs that need to be
  374. // displayed.
  375. // [Out] ppIXMLDocument - A pointer that receives the xml document.
  376. //
  377. // Return:
  378. // S_OK if the cdf file was found and successfully parsed.
  379. // E_FAIL otherwise.
  380. //
  381. // Comments:
  382. // Uses the m_pidlRoot that was set during IPersistFolder::Initialize.
  383. //
  384. ////////////////////////////////////////////////////////////////////////////////
  385. HRESULT
  386. CPersist::ParseCdf(
  387. HWND hwndOwner,
  388. IXMLDocument** ppIXMLDocument,
  389. DWORD dwParseFlags
  390. )
  391. {
  392. ASSERT(ppIXMLDocument);
  393. HRESULT hr;
  394. if (*m_szPath)
  395. {
  396. INITTYPE it = GetInitType(m_szPath);
  397. switch(it)
  398. {
  399. case IT_FILE:
  400. hr = InitializeFromURL(m_szPath, ppIXMLDocument, dwParseFlags);
  401. break;
  402. case IT_INI:
  403. {
  404. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  405. if (ReadFromIni(TSTR_INI_URL, szURL, ARRAYSIZE(szURL)))
  406. {
  407. hr = InitializeFromURL(szURL, ppIXMLDocument, dwParseFlags);
  408. }
  409. else
  410. {
  411. hr = E_FAIL;
  412. }
  413. }
  414. break;
  415. case IT_SHORTCUT:
  416. case IT_UNKNOWN:
  417. hr = E_FAIL;
  418. break;
  419. }
  420. }
  421. else
  422. {
  423. hr = E_OUTOFMEMORY;
  424. }
  425. //
  426. // REVIEW: Properly notify user on failure to init.
  427. //
  428. if (FAILED(hr) && hwndOwner)
  429. {
  430. TCHAR szText[MAX_PATH];
  431. TCHAR szTitle[MAX_PATH];
  432. MLLoadString(IDS_ERROR_DLG_TEXT, szText, MAX_PATH);
  433. MLLoadString(IDS_ERROR_DLG_TITLE, szTitle, MAX_PATH);
  434. MessageBox(hwndOwner, szText, szTitle, MB_OK | MB_ICONWARNING);
  435. }
  436. ASSERT((SUCCEEDED(hr) && *ppIXMLDocument) || FAILED(hr));
  437. return hr;
  438. }
  439. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  440. //
  441. // *** CCdfView::GetInitType ***
  442. //
  443. //
  444. // Description:
  445. // Determines the method being used to designate the cdf file.
  446. //
  447. // Parameters:
  448. // [In] szPath - The path passed in to IPersistFolder::Initialize.
  449. //
  450. // Return:
  451. // IT_INI if this instance is being created from a desktop.ini file
  452. // located in a right protected directory.
  453. // IT_FILE if this instance is being created from opening a cdf file.
  454. // IT_UNKNOWN if the method can not be determined.
  455. //
  456. // Comments:
  457. //
  458. //
  459. ////////////////////////////////////////////////////////////////////////////////
  460. INITTYPE
  461. CPersist::GetInitType(
  462. LPTSTR szPath
  463. )
  464. {
  465. if ( m_rgInitType != IT_UNKNOWN )
  466. {
  467. return m_rgInitType;
  468. }
  469. ASSERT(szPath);
  470. INITTYPE itRet;
  471. if (PathIsDirectory(szPath))
  472. {
  473. itRet = IT_INI;
  474. }
  475. else
  476. {
  477. itRet = IT_FILE;
  478. }
  479. m_rgInitType = itRet;
  480. return itRet;
  481. }
  482. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  483. //
  484. // *** CCdfView::InitializeFromURL ***
  485. //
  486. //
  487. // Description:
  488. // Given an URL to a cdf an attempt is made to parse the cdf and initialize
  489. // the current (root) folder.
  490. //
  491. // Parameters:
  492. // [In] szURL - The URL of the cdf file.
  493. // [Out] ppIXMLDocument - A pointer that receives the xml document.
  494. //
  495. // Return:
  496. // S_OK if initializtion succeeded.
  497. // E_FAIL otherwise.
  498. //
  499. // Comments:
  500. // All other initialize methods eventually resolve to an URL and call this
  501. // methhod.
  502. //
  503. ////////////////////////////////////////////////////////////////////////////////
  504. HRESULT
  505. CPersist::InitializeFromURL(
  506. LPTSTR pszURL,
  507. IXMLDocument** ppIXMLDocument,
  508. DWORD dwParseFlags
  509. )
  510. {
  511. ASSERT(pszURL);
  512. ASSERT(ppIXMLDocument);
  513. HRESULT hr;
  514. TCHAR szCanonicalURL[INTERNET_MAX_URL_LENGTH];
  515. if (PathIsURL(pszURL))
  516. {
  517. ULONG cch = ARRAYSIZE(szCanonicalURL);
  518. if (InternetCanonicalizeUrl(pszURL, szCanonicalURL, &cch, 0))
  519. pszURL = szCanonicalURL;
  520. }
  521. //
  522. // Get an XML document object from the cache if it's there. Otherwise
  523. // parse it and place it in the cache.
  524. //
  525. if (PARSE_REPARSE & dwParseFlags)
  526. {
  527. (void)Cache_RemoveItem(pszURL);
  528. hr = E_FAIL;
  529. }
  530. else
  531. {
  532. hr = Cache_QueryItem(pszURL, ppIXMLDocument, dwParseFlags);
  533. if (SUCCEEDED(hr))
  534. TraceMsg(TF_CDFPARSE, "[XML Document Cache]");
  535. }
  536. if (FAILED(hr))
  537. {
  538. DWORD dwCacheCount = g_dwCacheCount;
  539. FILETIME ftLastMod;
  540. if (dwParseFlags & PARSE_LOCAL)
  541. {
  542. TCHAR szLocalFile[MAX_PATH];
  543. hr = URLGetLocalFileName(pszURL, szLocalFile,
  544. ARRAYSIZE(szLocalFile), &ftLastMod);
  545. if (SUCCEEDED(hr))
  546. {
  547. hr = Parse(szLocalFile, ppIXMLDocument);
  548. }
  549. else
  550. {
  551. hr = OLE_E_NOCACHE;
  552. }
  553. }
  554. else
  555. {
  556. TraceMsg(TF_CDFPARSE, "[*** CDF parse enabled to hit net!!! ***]");
  557. hr = Parse(pszURL, ppIXMLDocument);
  558. URLGetLastModTime(pszURL, &ftLastMod);
  559. //
  560. // Stuff the images files into the cache.
  561. //
  562. if (SUCCEEDED(hr))
  563. {
  564. ASSERT(*ppIXMLDocument);
  565. XML_DownloadImages(*ppIXMLDocument);
  566. }
  567. }
  568. if (SUCCEEDED(hr))
  569. {
  570. Cache_AddItem(pszURL, *ppIXMLDocument, dwParseFlags, ftLastMod,
  571. dwCacheCount);
  572. }
  573. }
  574. if (SUCCEEDED(hr))
  575. {
  576. ASSERT(*ppIXMLDocument);
  577. m_bCdfParsed = TRUE;
  578. if (dwParseFlags & PARSE_REMOVEGLEAM)
  579. ClearGleamFlag(pszURL, m_szPath);
  580. }
  581. ASSERT((SUCCEEDED(hr) && m_bCdfParsed && *ppIXMLDocument) || FAILED(hr));
  582. return hr;
  583. }
  584. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  585. //
  586. // *** CPersist::ReadFromIni ***
  587. //
  588. //
  589. // Description:
  590. // Reads a string from the channel desktop.ini file.
  591. //
  592. // Parameters:
  593. // pszKey - The key to read.
  594. // szOut - The result.
  595. // cch - The size of the szout Buffer
  596. //
  597. // Return:
  598. // A bstr containing the value associated with the key.
  599. //
  600. // Comments:
  601. //
  602. //
  603. ////////////////////////////////////////////////////////////////////////////////
  604. BOOL
  605. CPersist::ReadFromIni(
  606. LPCTSTR pszKey,
  607. LPTSTR szOut,
  608. int cch
  609. )
  610. {
  611. ASSERT(pszKey);
  612. ASSERT(szOut || 0 == cch);
  613. BOOL fRet = FALSE;
  614. if (m_szPath && *m_szPath)
  615. {
  616. INITTYPE it = GetInitType(m_szPath);
  617. if (it == IT_INI)
  618. {
  619. LPCTSTR szFile = TSTR_INI_FILE;
  620. LPCTSTR szSection = TSTR_INI_SECTION;
  621. LPCTSTR szKey = pszKey;
  622. TCHAR szPath[MAX_PATH];
  623. StrCpyN(szPath, m_szPath, ARRAYSIZE(szPath) - StrLen(szFile));
  624. StrCat(szPath, szFile);
  625. if (GetPrivateProfileString(szSection, szKey, TEXT(""), szOut, cch,
  626. szPath))
  627. {
  628. fRet = TRUE;
  629. }
  630. }
  631. }
  632. return fRet;
  633. }
  634. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  635. //
  636. // *** CPersist::ReadFromIni ***
  637. //
  638. //
  639. // Description:
  640. // Reads a string from the channel desktop.ini file.
  641. //
  642. // Parameters:
  643. // pszKey - The key to read.
  644. //
  645. // Return:
  646. // A bstr containing the value associated with the key.
  647. //
  648. // Comments:
  649. //
  650. //
  651. ////////////////////////////////////////////////////////////////////////////////
  652. BSTR
  653. CPersist::ReadFromIni(
  654. LPCTSTR pszKey
  655. )
  656. {
  657. ASSERT(pszKey);
  658. BSTR bstrRet = NULL;
  659. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  660. if (ReadFromIni(pszKey, szURL, ARRAYSIZE(szURL)))
  661. {
  662. WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  663. if (SHTCharToUnicode(szURL, wszURL, ARRAYSIZE(wszURL)))
  664. bstrRet = SysAllocString(wszURL);
  665. }
  666. return bstrRet;
  667. }
  668. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  669. //
  670. // *** CPersist::IsUnreadCdf ***
  671. //
  672. //
  673. // Description:
  674. //
  675. // Parameters:
  676. //
  677. // Return:
  678. //
  679. // Comments:
  680. //
  681. ////////////////////////////////////////////////////////////////////////////////
  682. BOOL
  683. CPersist::IsUnreadCdf(
  684. void
  685. )
  686. {
  687. BOOL fRet = FALSE;
  688. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  689. if (ReadFromIni(TSTR_INI_URL, szURL, ARRAYSIZE(szURL)))
  690. {
  691. fRet = IsRecentlyChangedURL(szURL);
  692. }
  693. return fRet;
  694. }
  695. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  696. //
  697. // *** CPersist::IsNewContent ***
  698. //
  699. //
  700. // Description:
  701. //
  702. // Parameters:
  703. //
  704. // Return:
  705. //
  706. // Comments:
  707. //
  708. ////////////////////////////////////////////////////////////////////////////////
  709. BOOL
  710. CPersist::IsRecentlyChangedURL(
  711. LPCTSTR pszURL
  712. )
  713. {
  714. ASSERT(pszURL);
  715. BOOL fRet = FALSE;
  716. HRESULT hr;
  717. IPropertySetStorage* pIPropertySetStorage;
  718. hr = QueryInternetShortcut(pszURL, IID_IPropertySetStorage,
  719. (void**)&pIPropertySetStorage);
  720. if (SUCCEEDED(hr))
  721. {
  722. ASSERT(pIPropertySetStorage);
  723. IPropertyStorage* pIPropertyStorage;
  724. hr = pIPropertySetStorage->Open(FMTID_InternetSite, STGM_READWRITE,
  725. &pIPropertyStorage);
  726. if (SUCCEEDED(hr))
  727. {
  728. ASSERT(pIPropertyStorage);
  729. PROPSPEC propspec = { PRSPEC_PROPID, PID_INTSITE_FLAGS };
  730. PROPVARIANT propvar;
  731. PropVariantInit(&propvar);
  732. hr = pIPropertyStorage->ReadMultiple(1, &propspec, &propvar);
  733. if (SUCCEEDED(hr) && (VT_UI4 == propvar.vt))
  734. {
  735. fRet = propvar.ulVal & PIDISF_RECENTLYCHANGED;
  736. }
  737. else
  738. {
  739. PropVariantClear(&propvar);
  740. }
  741. pIPropertyStorage->Release();
  742. }
  743. pIPropertySetStorage->Release();
  744. }
  745. return fRet;
  746. }
  747. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  748. //
  749. // *** ClearGleamFlag ***
  750. //
  751. //
  752. // Description:
  753. //
  754. // Parameters:
  755. //
  756. // Return:
  757. //
  758. // Comments:
  759. //
  760. ////////////////////////////////////////////////////////////////////////////////
  761. HRESULT
  762. ClearGleamFlag(
  763. LPCTSTR pszURL,
  764. LPCTSTR pszPath
  765. )
  766. {
  767. ASSERT(pszURL);
  768. ASSERT(pszPath);
  769. HRESULT hr;
  770. IPropertySetStorage* pIPropertySetStorage;
  771. hr = QueryInternetShortcut(pszURL, IID_IPropertySetStorage,
  772. (void**)&pIPropertySetStorage);
  773. if (SUCCEEDED(hr))
  774. {
  775. ASSERT(pIPropertySetStorage);
  776. IPropertyStorage* pIPropertyStorage;
  777. hr = pIPropertySetStorage->Open(FMTID_InternetSite, STGM_READWRITE,
  778. &pIPropertyStorage);
  779. if (SUCCEEDED(hr))
  780. {
  781. ASSERT(pIPropertyStorage);
  782. PROPSPEC propspec = { PRSPEC_PROPID, PID_INTSITE_FLAGS };
  783. PROPVARIANT propvar;
  784. PropVariantInit(&propvar);
  785. hr = pIPropertyStorage->ReadMultiple(1, &propspec, &propvar);
  786. if (SUCCEEDED(hr) && (VT_UI4 == propvar.vt) &&
  787. (propvar.ulVal & PIDISF_RECENTLYCHANGED))
  788. {
  789. TCHAR szHash[MAX_PATH];
  790. int iIndex;
  791. UINT uFlags;
  792. int iImageIndex;
  793. HRESULT hr2 = PreUpdateChannelImage(pszPath, szHash, &iIndex,
  794. &uFlags, &iImageIndex);
  795. propvar.ulVal &= ~PIDISF_RECENTLYCHANGED;
  796. hr = pIPropertyStorage->WriteMultiple(1, &propspec, &propvar,
  797. 0);
  798. if (SUCCEEDED(hr))
  799. hr = pIPropertyStorage->Commit(STGC_DEFAULT);
  800. TraceMsg(TF_GLEAM, "- Gleam Cleared %s", pszURL);
  801. if (SUCCEEDED(hr) && SUCCEEDED(hr2))
  802. {
  803. WCHAR wszHash[MAX_PATH];
  804. SHTCharToUnicode(szHash, wszHash, ARRAYSIZE(wszHash));
  805. UpdateChannelImage(wszHash, iIndex, uFlags, iImageIndex);
  806. }
  807. }
  808. else
  809. {
  810. PropVariantClear(&propvar);
  811. }
  812. pIPropertyStorage->Release();
  813. }
  814. pIPropertySetStorage->Release();
  815. }
  816. return hr;
  817. }
  818. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  819. //
  820. // *** URLGetLocalFileName ***
  821. //
  822. //
  823. // Description:
  824. //
  825. //
  826. // Parameters:
  827. //
  828. //
  829. // Return:
  830. //
  831. //
  832. // Comments:
  833. //
  834. //
  835. ////////////////////////////////////////////////////////////////////////////////
  836. HRESULT
  837. URLGetLocalFileName(
  838. LPCTSTR pszURL,
  839. LPTSTR szLocalFile,
  840. int cch,
  841. FILETIME* pftLastMod
  842. )
  843. {
  844. ASSERT(pszURL);
  845. ASSERT(szLocalFile || 0 == cch);
  846. HRESULT hr = E_FAIL;
  847. if (pftLastMod)
  848. {
  849. pftLastMod->dwLowDateTime = 0;
  850. pftLastMod->dwHighDateTime = 0;
  851. }
  852. // by using the internal shlwapi function, we avoid loading WININET
  853. // unless we really really need it...
  854. if (PathIsURL(pszURL))
  855. {
  856. PARSEDURL rgCrackedURL = {0};
  857. rgCrackedURL.cbSize = sizeof( rgCrackedURL );
  858. if ( SUCCEEDED( ParseURL( pszURL, &rgCrackedURL )))
  859. {
  860. switch(rgCrackedURL.nScheme)
  861. {
  862. case URL_SCHEME_HTTP:
  863. case URL_SCHEME_FTP:
  864. case URL_SCHEME_GOPHER:
  865. {
  866. ULONG cbSize = MAX_CACHE_ENTRY_INFO_SIZE;
  867. INTERNET_CACHE_ENTRY_INFO* piceiAlloced =
  868. (INTERNET_CACHE_ENTRY_INFO*) new BYTE[cbSize];
  869. if (piceiAlloced)
  870. {
  871. piceiAlloced->dwStructSize =
  872. sizeof(INTERNET_CACHE_ENTRY_INFO);
  873. if (GetUrlCacheEntryInfoEx(pszURL, piceiAlloced,
  874. &cbSize, NULL, NULL,
  875. NULL, 0))
  876. {
  877. if (StrCpyN(szLocalFile,
  878. piceiAlloced->lpszLocalFileName, cch))
  879. {
  880. if (pftLastMod)
  881. {
  882. *pftLastMod =
  883. piceiAlloced->LastModifiedTime;
  884. }
  885. hr = S_OK;
  886. }
  887. }
  888. delete [] piceiAlloced;
  889. }
  890. }
  891. break;
  892. case URL_SCHEME_FILE:
  893. hr = PathCreateFromUrl(pszURL, szLocalFile, (LPDWORD)&cch, 0);
  894. break;
  895. }
  896. }
  897. }
  898. else
  899. {
  900. if (StrCpyN(szLocalFile, pszURL, cch))
  901. hr = S_OK;
  902. }
  903. return hr;
  904. }
  905. //
  906. // Get the last modified time of the URL.
  907. //
  908. HRESULT
  909. URLGetLastModTime(
  910. LPCTSTR pszURL,
  911. FILETIME* pftLastMod
  912. )
  913. {
  914. ASSERT(pszURL);
  915. ASSERT(pftLastMod);
  916. pftLastMod->dwLowDateTime = 0;
  917. pftLastMod->dwHighDateTime = 0;
  918. ULONG cbSize = 0;
  919. if (!GetUrlCacheEntryInfoEx(pszURL, NULL, &cbSize, NULL, NULL, NULL, 0)
  920. && cbSize > 0)
  921. {
  922. INTERNET_CACHE_ENTRY_INFO* piceiAlloced =
  923. (INTERNET_CACHE_ENTRY_INFO*) new BYTE[cbSize];
  924. if (piceiAlloced)
  925. {
  926. piceiAlloced->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO);
  927. if (GetUrlCacheEntryInfoEx(pszURL, piceiAlloced, &cbSize, NULL,
  928. NULL, NULL, 0))
  929. {
  930. *pftLastMod = piceiAlloced->LastModifiedTime;
  931. }
  932. delete [] piceiAlloced;
  933. }
  934. }
  935. return S_OK;
  936. }
  937. /*STDMETHODIMP
  938. CPersist::IsDirty(
  939. void
  940. )
  941. {
  942. return E_NOTIMPL;
  943. }*/
  944. STDMETHODIMP
  945. CPersist::Load(
  946. BOOL fFullyAvailable,
  947. IMoniker* pIMoniker,
  948. IBindCtx* pIBindCtx,
  949. DWORD grfMode
  950. )
  951. {
  952. ASSERT(pIMoniker);
  953. ASSERT(pIBindCtx);
  954. HRESULT hr;
  955. ASSERT(NULL == m_polestrURL);
  956. hr = pIMoniker->GetDisplayName(pIBindCtx, NULL, &m_polestrURL);
  957. if (SUCCEEDED(hr))
  958. {
  959. ASSERT(m_polestrURL);
  960. ASSERT(NULL == m_pIXMLDocument)
  961. DLL_ForcePreloadDlls(PRELOAD_MSXML);
  962. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  963. IID_IXMLDocument, (void**)&m_pIXMLDocument);
  964. if (SUCCEEDED(hr))
  965. {
  966. ASSERT(m_pIXMLDocument);
  967. CBindStatusCallback* pCBindStatusCallback = new CBindStatusCallback(
  968. m_pIXMLDocument,
  969. m_polestrURL);
  970. if (pCBindStatusCallback)
  971. {
  972. IBindStatusCallback* pPrevIBindStatusCallback;
  973. hr = RegisterBindStatusCallback(pIBindCtx,
  974. (IBindStatusCallback*)pCBindStatusCallback,
  975. &pPrevIBindStatusCallback, 0);
  976. if (SUCCEEDED(hr))
  977. {
  978. pCBindStatusCallback->Init(pPrevIBindStatusCallback);
  979. IPersistMoniker* pIPersistMoniker;
  980. hr = m_pIXMLDocument->QueryInterface(IID_IPersistMoniker,
  981. (void**)&pIPersistMoniker);
  982. if (SUCCEEDED(hr))
  983. {
  984. ASSERT(pIPersistMoniker);
  985. hr = pIPersistMoniker->Load(fFullyAvailable, pIMoniker,
  986. pIBindCtx, grfMode);
  987. pIPersistMoniker->Release();
  988. }
  989. }
  990. pCBindStatusCallback->Release();
  991. }
  992. else
  993. {
  994. hr = E_OUTOFMEMORY;
  995. }
  996. }
  997. }
  998. return hr;
  999. }
  1000. STDMETHODIMP
  1001. CPersist::Save(
  1002. IMoniker* pIMoniker,
  1003. IBindCtx* pIBindCtx,
  1004. BOOL fRemember
  1005. )
  1006. {
  1007. return E_NOTIMPL;
  1008. }
  1009. STDMETHODIMP
  1010. CPersist::SaveCompleted(
  1011. IMoniker* pIMoniker,
  1012. IBindCtx* pIBindCtx
  1013. )
  1014. {
  1015. return E_NOTIMPL;
  1016. }
  1017. STDMETHODIMP
  1018. CPersist::GetCurMoniker(
  1019. IMoniker** ppIMoniker
  1020. )
  1021. {
  1022. return E_NOTIMPL;
  1023. }