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.

1013 lines
26 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // folder.cpp
  4. //
  5. // IShellFolder 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 "resource.h"
  17. #include "cdfidl.h"
  18. #include "xmlutil.h"
  19. #include "persist.h"
  20. #include "cdfview.h"
  21. #include "enum.h"
  22. #include "view.h"
  23. #include "exticon.h"
  24. #include "itemmenu.h"
  25. #include "tooltip.h"
  26. //
  27. // IShellFolder methods.
  28. //
  29. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  30. //
  31. // *** CCdfView::ParseDisplayName ***
  32. //
  33. //
  34. // Description:
  35. //
  36. //
  37. // Parameters:
  38. //
  39. //
  40. // Return:
  41. //
  42. //
  43. // Comments:
  44. //
  45. //
  46. ////////////////////////////////////////////////////////////////////////////////
  47. STDMETHODIMP
  48. CCdfView::ParseDisplayName(
  49. HWND hwndOwner,
  50. LPBC pbcReserved,
  51. LPOLESTR lpszDisplayName,
  52. ULONG* pchEaten,
  53. LPITEMIDLIST* ppidl,
  54. ULONG* pdwAttributes
  55. )
  56. {
  57. return E_NOTIMPL;
  58. }
  59. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  60. //
  61. // *** CCdfView::EnumObjects ***
  62. //
  63. //
  64. // Description:
  65. // Returns an enumerator for this folder.
  66. //
  67. // Parameters:
  68. // [In] hwndOwner - Handle of the owner window. Ignored.
  69. // [In] grfFlags - A combination of Folders, NonFolders and Include
  70. // Hidden.
  71. // [Out] ppenumIdList - A pointer to receive the IEnumIDList interface.
  72. //
  73. // Return:
  74. // S_OK if the enumrator was created and returned.
  75. // E_OUTOFMEMORY if the enumerator couldn't be created.
  76. //
  77. // Comments:
  78. // The caller must Release() the returned enumerator.
  79. //
  80. ////////////////////////////////////////////////////////////////////////////////
  81. STDMETHODIMP
  82. CCdfView::EnumObjects(
  83. HWND hwndOwner,
  84. DWORD grfFlags,
  85. LPENUMIDLIST* ppIEnumIDList
  86. )
  87. {
  88. ASSERT(ppIEnumIDList);
  89. TraceMsg(TF_CDFENUM, "<IN> EnumObjects tid:0x%x", GetCurrentThreadId());
  90. HRESULT hr = S_OK;
  91. if (!m_bCdfParsed)
  92. {
  93. TraceMsg(TF_CDFPARSE, "IShellFolder EnumObjects(%s) %s",
  94. hwndOwner ? TEXT("HWND") : TEXT("NULL"),
  95. PathFindFileName(m_szPath));
  96. hr = ParseCdfFolder(NULL, PARSE_LOCAL);
  97. }
  98. if (SUCCEEDED(hr))
  99. {
  100. *ppIEnumIDList = (IEnumIDList*) new CCdfEnum(m_pIXMLElementCollection,
  101. grfFlags, m_pcdfidl);
  102. hr = *ppIEnumIDList ? S_OK : E_OUTOFMEMORY;
  103. }
  104. else
  105. {
  106. *ppIEnumIDList = NULL;
  107. }
  108. ASSERT((SUCCEEDED(hr) && *ppIEnumIDList) ||
  109. (FAILED(hr) && NULL == *ppIEnumIDList));
  110. TraceMsg(TF_CDFENUM, "<OUT> EnumObjects tid:0x%x", GetCurrentThreadId());
  111. return hr;
  112. }
  113. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  114. //
  115. // *** CCdfView::BindToObject ***
  116. //
  117. //
  118. // Description:
  119. // Creates an IShellFolder for a given subfolder.
  120. //
  121. // Parameters:
  122. // [In] pidl - Pointer to the id list of the subfolder.
  123. // [] pdcReserved - Not used.
  124. // [In] riid - The requested interface.
  125. // [Out] ppvOut - A pointer to receive the returned interface.
  126. //
  127. // Return:
  128. // S_OK if the request folder is created and the interface returned.
  129. // E_OUTOFMEMORY if there isn't enough memory to create the folder.
  130. // E_NOINTERFACE if the requested interface isn't supported.
  131. //
  132. // Comments:
  133. // This function is generaly called on a member of the current folder
  134. // to create a subfolder.
  135. //
  136. ////////////////////////////////////////////////////////////////////////////////
  137. STDMETHODIMP
  138. CCdfView::BindToObject(
  139. LPCITEMIDLIST pidl,
  140. LPBC pbcReserved,
  141. REFIID riid,
  142. LPVOID* ppvOut
  143. )
  144. {
  145. ASSERT(ppvOut);
  146. //
  147. // REVIEW: Hack to get around shell pidls. Bug in shell!
  148. //
  149. #if 1 //Hack
  150. while(!ILIsEmpty(pidl) && !CDFIDL_IsValidId((PCDFITEMID)&pidl->mkid))
  151. pidl = _ILNext(pidl);
  152. if (ILIsEmpty(pidl))
  153. {
  154. HRESULT hr = S_OK;
  155. if (!m_bCdfParsed)
  156. {
  157. TraceMsg(TF_CDFPARSE, "IShellFolder BindToObject (Hack) %s",
  158. PathFindFileName(m_szPath));
  159. hr = ParseCdfFolder(NULL, PARSE_LOCAL);
  160. }
  161. if (SUCCEEDED(hr))
  162. {
  163. AddRef();
  164. *ppvOut = (void**)(IShellFolder*)this;
  165. }
  166. return hr;
  167. }
  168. #endif //Hack
  169. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl));
  170. //
  171. // REVIEW: nsc.cpp calls this function with non-folder pidls.
  172. // Currently remove the ASSERT and replace it with a check. nsc
  173. // shouldn't make this call with non-folder pidls.
  174. //
  175. //ASSERT(CDFIDL_IsFolderId((PCDFITEMID)&pidl->mkid));
  176. HRESULT hr = S_OK;
  177. *ppvOut = NULL;
  178. if (CDFIDL_IsFolderId((PCDFITEMID)&pidl->mkid))
  179. {
  180. if (!m_bCdfParsed)
  181. {
  182. TraceMsg(TF_CDFPARSE, "IShellFolder BindToObject %s",
  183. PathFindFileName(m_szPath));
  184. hr = ParseCdfFolder(NULL, PARSE_LOCAL);
  185. }
  186. if (SUCCEEDED(hr))
  187. {
  188. ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
  189. (PCDFITEMIDLIST)pidl));
  190. CCdfView* pCCdfView = (CCdfView*)new CCdfView((PCDFITEMIDLIST)pidl,
  191. m_pidlPath,
  192. m_pIXMLElementCollection);
  193. if (pCCdfView)
  194. {
  195. if (ILIsEmpty(_ILNext(pidl)))
  196. {
  197. hr = pCCdfView->QueryInterface(riid, ppvOut);
  198. }
  199. else
  200. {
  201. hr = pCCdfView->BindToObject(_ILNext(pidl), pbcReserved, riid,
  202. ppvOut);
  203. }
  204. pCCdfView->Release();
  205. }
  206. else
  207. {
  208. hr = E_OUTOFMEMORY;
  209. }
  210. }
  211. }
  212. else
  213. {
  214. hr = E_INVALIDARG;
  215. }
  216. ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
  217. return hr;
  218. }
  219. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  220. //
  221. // *** CCdfView::BindToStorage ***
  222. //
  223. //
  224. // Description:
  225. //
  226. //
  227. // Parameters:
  228. //
  229. //
  230. // Return:
  231. //
  232. //
  233. // Comments:
  234. //
  235. //
  236. ////////////////////////////////////////////////////////////////////////////////
  237. STDMETHODIMP
  238. CCdfView::BindToStorage(
  239. LPCITEMIDLIST pidl,
  240. LPBC pbcReserved,
  241. REFIID riid,
  242. LPVOID* ppvObj
  243. )
  244. {
  245. return E_NOTIMPL;
  246. }
  247. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  248. //
  249. // *** CCdfView::CompareIDs ***
  250. //
  251. //
  252. // Description:
  253. // Determines the relative ordering of two objects given their id lists.
  254. //
  255. // Parameters:
  256. // [In] lParam - Value specifying the type of comparison to perform.
  257. // Currently ignored. Always sort by name.
  258. // [In] pidl1 - The id list of the first item to compare.
  259. // [In] pidl2 - The id list of the second item to compare.
  260. //
  261. // Return:
  262. // The SCODE of the HRESULT (low word) is <0 if pidl1 comes before pidl2,
  263. // =0 if pidl1 is the same as pidl2 and >0 if pidl1 comes after pidl2.
  264. //
  265. // Comments:
  266. // Shell expects this function to never fail.
  267. //
  268. ////////////////////////////////////////////////////////////////////////////////
  269. STDMETHODIMP
  270. CCdfView::CompareIDs(
  271. LPARAM lParam,
  272. LPCITEMIDLIST pidl1,
  273. LPCITEMIDLIST pidl2
  274. )
  275. {
  276. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl1));
  277. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl2));
  278. SHORT sRes = CDFIDL_Compare((PCDFITEMIDLIST)pidl1,(PCDFITEMIDLIST)pidl2);
  279. return 0x0000ffff & sRes;
  280. }
  281. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  282. //
  283. // *** CCdfView::CreateViewObject ***
  284. //
  285. //
  286. // Description:
  287. // Creates a com object for the current folder implementing the specified
  288. // interface
  289. //
  290. // Parameters:
  291. // [In] hwndOwner - Owner window. Ignored.
  292. // [In] riid - The interface to create.
  293. // [Out] ppvOut - A pointer that receives the new object.
  294. //
  295. // Return:
  296. // S_OK if the requested object was successfully created.
  297. // E_NOINTERFACE if the object is not suppported.
  298. // E_OUTOFMEMORY if the pidl couldn't be cloned.
  299. // The return value from SHCreateShellFolderViewEx otherwise.
  300. //
  301. // Comments:
  302. // It is important to remember that the COM object created by
  303. // CreateViewObject must be a different object than the shell folder object.
  304. // The Explorer may call CreateViewObject more than once to create more than
  305. // one view object and expects them to behave as independent objects. A new
  306. // view object must be created for each call.
  307. //
  308. // Request for IShellView return a default Shell implementation.
  309. //
  310. ////////////////////////////////////////////////////////////////////////////////
  311. STDMETHODIMP
  312. CCdfView::CreateViewObject(
  313. HWND hwndOwner,
  314. REFIID riid,
  315. LPVOID* ppvOut
  316. )
  317. {
  318. ASSERT(ppvOut);
  319. //
  320. // This function is called when the cdf hasn't been parsed. m_pcdfidl is
  321. // likely NULL in this case. This doesn't appear to be a problem so the
  322. // ASSERT has been commented out.
  323. //
  324. // ASSERT(m_bCdfParsed);
  325. HRESULT hr;
  326. if (IID_IShellView == riid)
  327. {
  328. hr = CreateDefaultShellView((IShellFolder*)this,
  329. (LPITEMIDLIST)m_pidlPath,
  330. (IShellView**)ppvOut);
  331. }
  332. else
  333. {
  334. *ppvOut = NULL;
  335. hr = E_NOINTERFACE;
  336. }
  337. ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
  338. return hr;
  339. }
  340. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  341. //
  342. // *** CCdfView::GetAttributesOf ***
  343. //
  344. //
  345. // Description:
  346. // Returns the common attributes of the given id lists.
  347. //
  348. // Parameters:
  349. // [In] cidl - The number of id lists passed in.
  350. // [In] apidl - An array of id list pointers.
  351. // [Out] pfAttributesOut - Address to receive the common attributes. These
  352. // attributes are defined with the SFGAO_ prefix.
  353. // For example SFGAO_FOLDER and SFGAO_CANDELETE.
  354. //
  355. // Return:
  356. // S_OK if the attributes of the given id lists could be determined.
  357. // E_FAIL otherwise.
  358. //
  359. // Comments:
  360. // The attributes of the given id lists are AND'ed to obtain the common
  361. // members.
  362. //
  363. // Shell calls this on the root folder with cidl set to zero to get the
  364. // attributes of the root folder. It also doesn't bother to check the
  365. // return value so make sure the attributes are set correctly for this
  366. // case.
  367. //
  368. ////////////////////////////////////////////////////////////////////////////////
  369. STDMETHODIMP
  370. CCdfView::GetAttributesOf(
  371. UINT cidl,
  372. LPCITEMIDLIST* apidl,
  373. ULONG* pfAttributesOut
  374. )
  375. {
  376. ASSERT(apidl || cidl == 0);
  377. ASSERT(pfAttributesOut);
  378. ULONG fAttributeFilter = *pfAttributesOut;
  379. if (!m_bCdfParsed)
  380. {
  381. TraceMsg(TF_CDFPARSE, "IShellFolder GetAttributesOf %s",
  382. PathFindFileName(m_szPath));
  383. ParseCdfFolder(NULL, PARSE_LOCAL);
  384. }
  385. if (m_pIXMLElementCollection)
  386. {
  387. if (cidl)
  388. {
  389. *pfAttributesOut = (ULONG)-1;
  390. while(cidl-- && *pfAttributesOut)
  391. {
  392. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)apidl[cidl]));
  393. ASSERT(ILIsEmpty(_ILNext(apidl[cidl])));
  394. ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
  395. (PCDFITEMIDLIST)apidl[cidl]));
  396. //
  397. // CDFIDL_GetAttributes returns zero on failure.
  398. //
  399. *pfAttributesOut &= CDFIDL_GetAttributes(
  400. m_pIXMLElementCollection,
  401. (PCDFITEMIDLIST)apidl[cidl],
  402. fAttributeFilter);
  403. }
  404. }
  405. else
  406. {
  407. //
  408. // Return this folder's attributes.
  409. //
  410. *pfAttributesOut = SFGAO_FOLDER;
  411. if (XML_ContainsFolder(m_pIXMLElementCollection))
  412. *pfAttributesOut |= SFGAO_HASSUBFOLDER;
  413. }
  414. }
  415. else
  416. {
  417. //
  418. // m_pIXMLElementCollection == NULL in low memory situations.
  419. //
  420. *pfAttributesOut = 0;
  421. }
  422. return S_OK;
  423. }
  424. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  425. //
  426. // *** CCdfView::GetUIObjectOf ***
  427. //
  428. //
  429. // Description:
  430. // Creates a COM object implemeneting the requested interface for the
  431. // specidied id lists.
  432. //
  433. // Parameters:
  434. // [In] hwndOwner - The owner window.
  435. // [In] cidl - The number of idlist passed in.
  436. // [In] apild - An array of id list pointers.
  437. // [In] riid - The requested interface. Can be IExtractIcon,
  438. // IContextMenu, IDataObject or IDropTarget.
  439. // [] prgfInOut - Not used.
  440. // [Out] ppvOut - The pointer to receive the requested COM object.
  441. //
  442. // Return:
  443. // S_OK if the interface was created.
  444. // E_OUTOFMEMORY if the COM object couldn't be created.
  445. // E_NOINTERFACE if the requested interface isn't supported.
  446. // E_FAIL if cidl is zero.
  447. //
  448. // Comments:
  449. //
  450. //
  451. ////////////////////////////////////////////////////////////////////////////////
  452. STDMETHODIMP
  453. CCdfView::GetUIObjectOf(
  454. HWND hwndOwner,
  455. UINT cidl,
  456. LPCITEMIDLIST* apidl,
  457. REFIID riid,
  458. UINT* prgfInOut,
  459. LPVOID * ppvOut
  460. )
  461. {
  462. ASSERT(apidl || 0 == cidl);
  463. ASSERT(ppvOut);
  464. // ASSERT(m_bCdfParsed); Called when cdf is not parsed.
  465. #ifdef DEBUG
  466. for(UINT i = 0; i < cidl; i++)
  467. {
  468. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)apidl[i]));
  469. ASSERT(ILIsEmpty(_ILNext(apidl[i])));
  470. ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
  471. (PCDFITEMIDLIST)apidl[i]));
  472. }
  473. #endif // DEBUG
  474. HRESULT hr;
  475. *ppvOut = NULL;
  476. if (cidl)
  477. {
  478. if (IID_IExtractIcon == riid
  479. #ifdef UNICODE
  480. || IID_IExtractIconA == riid
  481. #endif
  482. )
  483. {
  484. ASSERT(1 == cidl);
  485. if (!m_bCdfParsed)
  486. {
  487. TraceMsg(TF_CDFPARSE, "IShellFolder IExtractIcon %s",
  488. PathFindFileName(m_szPath));
  489. ParseCdfFolder(NULL, PARSE_LOCAL);
  490. }
  491. #ifdef UNICODE
  492. CExtractIcon *pxi = new CExtractIcon((PCDFITEMIDLIST)apidl[0],
  493. m_pIXMLElementCollection);
  494. if (riid == IID_IExtractIconW)
  495. *ppvOut = (IExtractIconW *)pxi;
  496. else
  497. *ppvOut = (IExtractIconA *)pxi;
  498. #else
  499. *ppvOut = (IExtractIcon*)new CExtractIcon((PCDFITEMIDLIST)apidl[0],
  500. m_pIXMLElementCollection);
  501. #endif
  502. hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
  503. }
  504. else if (IID_IContextMenu == riid)
  505. {
  506. #if USE_DEFAULT_MENU_HANDLER
  507. hr = CDefFolderMenu_Create((LPITEMIDLIST)m_pcdfidl, hwndOwner, cidl,
  508. apidl, (IShellFolder*)this, MenuCallBack,
  509. NULL, NULL, (IContextMenu**)ppvOut);
  510. #else // USE_DEFAULT_MENU_HANDLER
  511. *ppvOut = (IContextMenu*)new CContextMenu((PCDFITEMIDLIST*)apidl,
  512. m_pidlPath, cidl);
  513. hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
  514. #endif // USE_DEFAULT_MENU_HANDLER
  515. }
  516. else if (IID_IQueryInfo == riid)
  517. {
  518. ASSERT(1 == cidl);
  519. if (!m_bCdfParsed)
  520. {
  521. TraceMsg(TF_CDFPARSE, "IShellFolder IQueryInfo %s",
  522. PathFindFileName(m_szPath));
  523. ParseCdfFolder(NULL, PARSE_LOCAL);
  524. }
  525. *ppvOut = (IQueryInfo*)new CQueryInfo((PCDFITEMIDLIST)apidl[0],
  526. m_pIXMLElementCollection);
  527. hr = *ppvOut ? S_OK : E_OUTOFMEMORY;
  528. }
  529. else if (IID_IShellLink == riid || IID_IDataObject == riid
  530. #ifdef UNICODE
  531. || IID_IShellLinkA == riid
  532. #endif
  533. )
  534. {
  535. ASSERT(1 == cidl); // IDataObject should handle cidl > 1!
  536. hr = QueryInternetShortcut((PCDFITEMIDLIST)apidl[0], riid, ppvOut);
  537. }
  538. else
  539. {
  540. hr = E_NOINTERFACE;
  541. }
  542. }
  543. else
  544. {
  545. ASSERT(0); // Is this ever called with cidl == 0?
  546. hr = E_FAIL;
  547. }
  548. ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
  549. return hr;
  550. }
  551. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  552. //
  553. // *** CCdfView::GetDisplayNameOf ***
  554. //
  555. //
  556. // Description:
  557. // Returns the diaply name for the specified Id list.
  558. //
  559. // Parameters:
  560. // [In] pidl - A pointer to the id list.
  561. // [In] uFlags - SHGDN_NORMAL, SHGN_INFOLDER or SHGDN_FORPARSING.
  562. // [Out] lpName - A pointer to a STRRET structure that receives the name.
  563. //
  564. // Return:
  565. // S_OK if the name can be determined.
  566. // E_FAIL otherwise.
  567. //
  568. // Comments:
  569. // This may be called on the root element in which case the pidl is a shell
  570. // id list and not a cdf id list.
  571. //
  572. ////////////////////////////////////////////////////////////////////////////////
  573. STDMETHODIMP
  574. CCdfView::GetDisplayNameOf(
  575. LPCITEMIDLIST pidl,
  576. DWORD uFlags,
  577. LPSTRRET lpName
  578. )
  579. {
  580. ASSERT(CDFIDL_IsValid((PCDFITEMIDLIST)pidl));
  581. ASSERT(ILIsEmpty(_ILNext(pidl)));
  582. ASSERT(XML_IsCdfidlMemberOf(m_pIXMLElementCollection,
  583. (PCDFITEMIDLIST)pidl));
  584. ASSERT(lpName);
  585. return CDFIDL_GetDisplayName((PCDFITEMIDLIST)pidl, lpName);
  586. }
  587. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  588. //
  589. // *** CCdfView::SetNameOf ***
  590. //
  591. //
  592. // Description:
  593. //
  594. //
  595. // Parameters:
  596. //
  597. //
  598. // Return:
  599. //
  600. //
  601. // Comments:
  602. //
  603. //
  604. ////////////////////////////////////////////////////////////////////////////////
  605. STDMETHODIMP
  606. CCdfView::SetNameOf(
  607. HWND hwndOwner,
  608. LPCITEMIDLIST pidl,
  609. LPCOLESTR lpszName,
  610. DWORD uFlags,
  611. LPITEMIDLIST* ppidlOut
  612. )
  613. {
  614. return E_NOTIMPL;
  615. }
  616. //
  617. // IPersistFolder method,
  618. //
  619. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  620. //
  621. // *** CCdfView::Initialize ***
  622. //
  623. //
  624. // Description:
  625. // This function is called with the fully qualified id list (location) of
  626. // the selected cdf file.
  627. //
  628. // Parameters:
  629. // [In] pidl - The pidl of the selected cdf file. This pidl conatins the
  630. // full path to the CDF.
  631. //
  632. // Return:
  633. // S_OK if content for the cdf file could be created.
  634. // E_OUTOFMEMORY otherwise.
  635. //
  636. // Comments:
  637. // This function can be called more than once for a given folder. When a
  638. // CDFView is being instantiated from a desktop.ini file the shell calls
  639. // Initialize once before it calls GetUIObjectOf asking for IDropTarget.
  640. // After the GetUIObjectOf call the folder is Released. It then calls
  641. // Initialize again on a new folder. This time it keeps the folder and it
  642. // ends up being displayed.
  643. //
  644. ////////////////////////////////////////////////////////////////////////////////
  645. STDMETHODIMP
  646. CCdfView::Initialize(
  647. LPCITEMIDLIST pidl
  648. )
  649. {
  650. ASSERT(pidl);
  651. HRESULT hr;
  652. ASSERT(NULL == m_pidlPath);
  653. m_pidlPath = ILClone(pidl);
  654. if (m_pidlPath)
  655. {
  656. hr = CPersist::Initialize(pidl);
  657. }
  658. else
  659. {
  660. hr = E_OUTOFMEMORY;
  661. }
  662. return hr;
  663. }
  664. //
  665. // Helper functions.
  666. //
  667. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  668. //
  669. // *** CCdfView::ParseCdf ***
  670. //
  671. //
  672. // Description:
  673. // Parses the cdf file associated with this folder.
  674. //
  675. // Parameters:
  676. // [In] hwndOwner - The parent window of any dialogs that need to be
  677. // displayed.
  678. // [In] dwFParseType - PARSE_LOCAL, PARSE_NET and PARSE_REPARSE.
  679. //
  680. // Return:
  681. // S_OK if the cdf file was found and successfully parsed.
  682. // E_FAIL otherwise.
  683. //
  684. // Comments:
  685. // Uses the m_pidlRoot that was set during IPersistFolder::Initialize.
  686. //
  687. ////////////////////////////////////////////////////////////////////////////////
  688. HRESULT
  689. CCdfView::ParseCdfFolder(
  690. HWND hwndOwner,
  691. DWORD dwParseFlags
  692. )
  693. {
  694. HRESULT hr;
  695. //
  696. // Parse the file and get the first channel element.
  697. //
  698. IXMLDocument* pIXMLDocument = NULL;
  699. hr = CPersist::ParseCdf(hwndOwner, &pIXMLDocument, dwParseFlags);
  700. if (SUCCEEDED(hr))
  701. {
  702. ASSERT(pIXMLDocument);
  703. IXMLElement* pIXMLElement;
  704. LONG nIndex;
  705. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  706. if (SUCCEEDED(hr))
  707. {
  708. ASSERT(pIXMLElement);
  709. //ASSERT(NULL == m_pcdfidl); Can be non-NULL on a reparse.
  710. if (m_pcdfidl)
  711. CDFIDL_Free(m_pcdfidl);
  712. if (m_pIXMLElementCollection)
  713. m_pIXMLElementCollection->Release();
  714. m_pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement, nIndex);
  715. HRESULT hr2 = pIXMLElement->get_children(&m_pIXMLElementCollection);
  716. if(!m_pIXMLElementCollection)
  717. {
  718. ASSERT(hr2 != S_OK);
  719. hr = E_FAIL;
  720. }
  721. ASSERT((S_OK == hr2 && m_pIXMLElementCollection) ||
  722. (S_OK != hr2 && NULL == m_pIXMLElementCollection));
  723. pIXMLElement->Release();
  724. }
  725. }
  726. if (pIXMLDocument)
  727. pIXMLDocument->Release();
  728. return hr;
  729. }
  730. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  731. //
  732. // *** CCdfView::QueryInternetShortcut ***
  733. //
  734. //
  735. // Description:
  736. // Sets up an internet shorcut object for the given URL.
  737. //
  738. // Parameters:
  739. // [In] pszURL - The URL.
  740. // [In] riid - The requested interface on the shortcut object.
  741. // [Out] ppvOut - A pointer that receives the interface.
  742. //
  743. // Return:
  744. // S_OK if the object is created and the interface is found.
  745. // A COM error code otherwise.
  746. //
  747. // Comments:
  748. //
  749. //
  750. ////////////////////////////////////////////////////////////////////////////////
  751. HRESULT
  752. QueryInternetShortcut(
  753. LPCTSTR pszURL,
  754. REFIID riid,
  755. void** ppvOut
  756. )
  757. {
  758. ASSERT(pszURL);
  759. ASSERT(ppvOut);
  760. HRESULT hr = E_FAIL;
  761. WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  762. if (SHTCharToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL)))
  763. {
  764. BSTR bstrURL = SysAllocString(wszURL);
  765. if (bstrURL)
  766. {
  767. CDFITEM cdfi;
  768. cdfi.nIndex = 1;
  769. cdfi.cdfItemType = CDF_Folder;
  770. cdfi.bstrName = bstrURL;
  771. cdfi.bstrURL = bstrURL;
  772. PCDFITEMIDLIST pcdfidl = CDFIDL_Create(&cdfi);
  773. if (pcdfidl)
  774. {
  775. hr = QueryInternetShortcut(pcdfidl, riid, ppvOut);
  776. CDFIDL_Free(pcdfidl);
  777. }
  778. SysFreeString(bstrURL);
  779. }
  780. }
  781. return hr;
  782. }
  783. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  784. //
  785. // *** CCdfView::QueryInternetShortcut ***
  786. //
  787. //
  788. // Description:
  789. // Sets up an internet shorcut object for the given pidl.
  790. //
  791. // Parameters:
  792. // [In] pcdfidl - The shortcut object is created for the URL stored in this
  793. // cdf item id list.
  794. // [In] riid - The requested interface on the shortcut object.
  795. // [Out] ppvOut - A pointer that receives the interface.
  796. //
  797. // Return:
  798. // S_OK if the object is created and the interface is found.
  799. // A COM error code otherwise.
  800. //
  801. // Comments:
  802. //
  803. //
  804. ////////////////////////////////////////////////////////////////////////////////
  805. HRESULT
  806. QueryInternetShortcut(
  807. PCDFITEMIDLIST pcdfidl,
  808. REFIID riid,
  809. void** ppvOut
  810. )
  811. {
  812. ASSERT(CDFIDL_IsValid(pcdfidl));
  813. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  814. ASSERT(ppvOut);
  815. HRESULT hr;
  816. *ppvOut = NULL;
  817. //
  818. // Only create a shell link object if the CDF contains an URL
  819. //
  820. if (*(CDFIDL_GetURL(pcdfidl)) != 0)
  821. {
  822. IShellLinkA * pIShellLink;
  823. hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  824. IID_IShellLinkA, (void**)&pIShellLink);
  825. BOOL bCoInit = FALSE;
  826. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  827. SUCCEEDED(CoInitialize(NULL)))
  828. {
  829. bCoInit = TRUE;
  830. hr = CoCreateInstance(CLSID_InternetShortcut, NULL,
  831. CLSCTX_INPROC_SERVER, IID_IShellLinkA,
  832. (void**)&pIShellLink);
  833. }
  834. if (SUCCEEDED(hr))
  835. {
  836. ASSERT(pIShellLink);
  837. #ifdef UNICODE
  838. CHAR szUrlA[INTERNET_MAX_URL_LENGTH];
  839. SHTCharToAnsi(CDFIDL_GetURL(pcdfidl), szUrlA, ARRAYSIZE(szUrlA));
  840. hr = pIShellLink->SetPath(szUrlA);
  841. #else
  842. hr = pIShellLink->SetPath(CDFIDL_GetURL(pcdfidl));
  843. #endif
  844. if (SUCCEEDED(hr))
  845. {
  846. //
  847. // The description ends up being the file name created.
  848. //
  849. TCHAR szPath[MAX_PATH];
  850. #ifdef UNICODE
  851. CHAR szPathA[MAX_PATH];
  852. #endif
  853. StrCpyN(szPath, CDFIDL_GetName(pcdfidl), ARRAYSIZE(szPath) - 5);
  854. StrCat(szPath, TEXT(".url"));
  855. #ifdef UNICODE
  856. SHTCharToAnsi(szPath, szPathA, ARRAYSIZE(szPathA));
  857. pIShellLink->SetDescription(szPathA);
  858. #else
  859. pIShellLink->SetDescription(szPath);
  860. #endif
  861. hr = pIShellLink->QueryInterface(riid, ppvOut);
  862. }
  863. pIShellLink->Release();
  864. }
  865. if (bCoInit)
  866. CoUninitialize();
  867. }
  868. else
  869. {
  870. hr = E_FAIL;
  871. }
  872. ASSERT((SUCCEEDED(hr) && *ppvOut) || (FAILED(hr) && NULL == *ppvOut));
  873. return hr;
  874. }