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.

1161 lines
29 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // cdfidl.cpp
  4. //
  5. // Cdf id list helper functions.
  6. //
  7. // History:
  8. //
  9. // 3/19/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "xmlutil.h"
  18. #include "winineti.h" // for MAX_CACHE_ENTRY_INFO_SIZE
  19. //
  20. // Helper functions
  21. //
  22. LPTSTR CDFIDL_GetUserName()
  23. {
  24. static BOOL gunCalled = FALSE;
  25. static TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH] = TEXT("");
  26. if (!gunCalled)
  27. {
  28. char szUserNameA[INTERNET_MAX_USER_NAME_LENGTH];
  29. szUserNameA[0] = 0;
  30. DWORD size = INTERNET_MAX_USER_NAME_LENGTH;
  31. GetUserNameA(szUserNameA, &size);
  32. SHAnsiToTChar(szUserNameA, szUserName, ARRAYSIZE(szUserName));
  33. gunCalled = TRUE;
  34. }
  35. return szUserName;
  36. }
  37. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  38. //
  39. // *** CDFIDL_Create ***
  40. //
  41. //
  42. // Description:
  43. // Creates a cdf id list.
  44. //
  45. // Parameters:
  46. // [In] pCdfItem - A pointer to cdf item data.
  47. //
  48. // Return:
  49. // A new cdf id list on success.
  50. // NULL otherwise.
  51. //
  52. // Comments:
  53. // This function builds a variable length cdf item id list. The item id
  54. // consists of a fixed length initial section followed by two or more null
  55. // terminated strings. It has the following form:
  56. //
  57. // USHORT cb - Size in bytes of this cdf item id.
  58. // WORD wVersion; - Version number of this item id structure.
  59. // DWORD dwId; - Used to identify cdf item ids. Set to
  60. // 0x0ed1964ed
  61. // CDFITEMTYPE cdfItemType - CDF_Folder, CDF_FolderLink or CDF_Link.
  62. // LONG nIndex - The object model index for this item.
  63. // TCHAR szName[1]; - Two or more null terminated strings
  64. // beggining with the name of this item.
  65. // USHORT next.cb - The size of the next item in the list.
  66. // Set to zero to terminate the list.
  67. //
  68. // It is the callers responsability to free the item id list. This should
  69. // be done using the IMalloc returned from SHGetMalloc();
  70. //
  71. ////////////////////////////////////////////////////////////////////////////////
  72. PCDFITEMIDLIST
  73. CDFIDL_Create(
  74. PCDFITEM pCdfItem
  75. )
  76. {
  77. #ifdef ALIGNMENT_MACHINE
  78. TCHAR *pszTempName;
  79. #endif
  80. ASSERT(pCdfItem);
  81. ASSERT(pCdfItem->bstrName);
  82. ASSERT(pCdfItem->bstrURL);
  83. PCDFITEMIDLIST pcdfidl = NULL;
  84. //
  85. // Get the number of chars of the name of the item including the terminating
  86. // null character.
  87. //
  88. USHORT cbName = StrLenW(pCdfItem->bstrName) + 1;
  89. //
  90. // Get the number of chars of the URL of the item including the terminating
  91. // null character.
  92. //
  93. USHORT cbURL = StrLenW(pCdfItem->bstrURL) + 1;
  94. //
  95. // Calculate the total size of the cdf item id in bytes. When calculating the size
  96. // of a cdf item id one TCHAR should be subtracted to account for the TCHAR
  97. // szName[1] included in the CDFITEMID struct definition.
  98. //
  99. USHORT cbItemId = sizeof(CDFITEMID) + (cbName + cbURL) * sizeof(TCHAR) - sizeof(TCHAR);
  100. #ifdef ALIGNMENT_MACHINE
  101. cbItemId = ALIGN4(cbItemId);
  102. #endif
  103. //
  104. // Item ids must allocated by the shell's IMalloc interface.
  105. //
  106. IMalloc* pIMalloc;
  107. HRESULT hr = SHGetMalloc(&pIMalloc);
  108. if (SUCCEEDED(hr))
  109. {
  110. ASSERT(pIMalloc);
  111. //
  112. // An item id *list* must be NULL terminated so an additional USHORT is
  113. // allocated to hold the terminating NULL.
  114. //
  115. pcdfidl = (PCDFITEMIDLIST)pIMalloc->Alloc(cbItemId + sizeof(USHORT));
  116. if (pcdfidl)
  117. {
  118. //
  119. // NULL terminate the list.
  120. //
  121. *((UNALIGNED USHORT*) ( ((LPBYTE)pcdfidl) + cbItemId )) = 0;
  122. #ifdef ALIGNMENT_MACHINE
  123. USHORT cbActaulItemId = sizeof(CDFITEMID) + cbName + cbURL - sizeof(TCHAR);
  124. if(cbActaulItemId < cbItemId)
  125. memset((LPBYTE)pcdfidl + cbActaulItemId, 0, cbItemId-cbActaulItemId);
  126. #endif
  127. //
  128. // Fill in the data shared by all cdf item ids.
  129. //
  130. pcdfidl->mkid.cb = cbItemId;
  131. pcdfidl->mkid.wVersion = CDFITEMID_VERSION;
  132. pcdfidl->mkid.dwId = CDFITEMID_ID;
  133. //
  134. // Set the data that is specific to this cdf item id.
  135. //
  136. pcdfidl->mkid.cdfItemType = pCdfItem->cdfItemType;
  137. pcdfidl->mkid.nIndex = pCdfItem->nIndex;
  138. //
  139. // REVIEW: Need WSTR to TSTR conversion.
  140. //
  141. #ifndef ALIGNMENT_MACHINE
  142. SHUnicodeToTChar(pCdfItem->bstrName, pcdfidl->mkid.szName, cbName);
  143. SHUnicodeToTChar(pCdfItem->bstrURL, pcdfidl->mkid.szName + cbName,
  144. cbURL);
  145. #else
  146. pszTempName = (LPTSTR)ALIGN4((ULONG_PTR)(pcdfidl->mkid.szName));
  147. SHUnicodeToTChar(pCdfItem->bstrName, pszTempName, cbName);
  148. pszTempName = (LPTSTR)((ULONG_PTR)(pcdfidl->mkid.szName+cbName));
  149. SHUnicodeToTChar(pCdfItem->bstrURL, pszTempName,
  150. cbURL);
  151. #endif
  152. }
  153. else
  154. {
  155. pcdfidl = NULL;
  156. }
  157. pIMalloc->Release();
  158. }
  159. ASSERT(CDFIDL_IsValid(pcdfidl) || NULL == pcdfidl);
  160. return pcdfidl;
  161. }
  162. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  163. //
  164. // *** CDFIDL_CreateFromXMLElement ***
  165. //
  166. //
  167. // Description:
  168. // Creates a cdf item id list from a xml element.
  169. //
  170. // Parameters:
  171. // [In] pIXMLElement - A pointer to the xml element.
  172. // [In] nIndex - The index value used to set the cdfidl index field.
  173. //
  174. // Return:
  175. // A poniter to a new cdf item id list if successful.
  176. // NULL otherwise.
  177. //
  178. // Comments:
  179. // The caller is responsible for freeing the returned id list.
  180. //
  181. ////////////////////////////////////////////////////////////////////////////////
  182. PCDFITEMIDLIST
  183. CDFIDL_CreateFromXMLElement(
  184. IXMLElement* pIXMLElement,
  185. ULONG nIndex
  186. )
  187. {
  188. ASSERT(pIXMLElement);
  189. PCDFITEMIDLIST pcdfidl = NULL;
  190. CDFITEM cdfItem;
  191. if (cdfItem.bstrName = XML_GetAttribute(pIXMLElement, XML_TITLE))
  192. {
  193. if (cdfItem.bstrURL = XML_GetAttribute(pIXMLElement, XML_HREF))
  194. {
  195. cdfItem.nIndex = nIndex;
  196. if (INDEX_CHANNEL_LINK == nIndex)
  197. {
  198. cdfItem.cdfItemType = CDF_FolderLink;
  199. }
  200. else
  201. {
  202. cdfItem.cdfItemType = XML_IsFolder(pIXMLElement) ? CDF_Folder :
  203. CDF_Link;
  204. }
  205. pcdfidl = CDFIDL_Create(&cdfItem);
  206. SysFreeString(cdfItem.bstrURL);
  207. }
  208. SysFreeString(cdfItem.bstrName);
  209. }
  210. ASSERT(CDFIDL_IsValid(pcdfidl) || NULL == pcdfidl);
  211. return pcdfidl;
  212. }
  213. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  214. //
  215. // *** CDFIDL_CreateFolderPidl ***
  216. //
  217. //
  218. // Description: creates a special folder pidl
  219. //
  220. //
  221. // Parameters:
  222. // [In] pcdfidl - Pointer to the cdf id list to be created from
  223. //
  224. // Comments:
  225. //
  226. //
  227. ////////////////////////////////////////////////////////////////////////////////
  228. PCDFITEMIDLIST
  229. CDFIDL_CreateFolderPidl(
  230. PCDFITEMIDLIST pcdfidl
  231. )
  232. {
  233. ASSERT(CDFIDL_IsValid(pcdfidl));
  234. PCDFITEMIDLIST pcdfidlRet = (PCDFITEMIDLIST)ILClone((LPITEMIDLIST)pcdfidl);
  235. if (pcdfidlRet)
  236. {
  237. ((PCDFITEMID)pcdfidlRet)->nIndex = INDEX_CHANNEL_LINK;
  238. ((PCDFITEMID)pcdfidlRet)->cdfItemType = CDF_FolderLink; //CDF_Link instead?
  239. }
  240. ASSERT(CDFIDL_IsValid(pcdfidlRet));
  241. return pcdfidlRet;
  242. }
  243. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  244. //
  245. // *** CDFIDL_Free ***
  246. //
  247. //
  248. // Description:
  249. // Free the given cdf item id list.
  250. //
  251. // Parameters:
  252. // [In] pcdfidl - Pointer to the cdf id list to be freed.
  253. //
  254. // Return:
  255. // No return value.
  256. //
  257. // Comments:
  258. //
  259. //
  260. ////////////////////////////////////////////////////////////////////////////////
  261. void
  262. CDFIDL_Free(
  263. PCDFITEMIDLIST pcdfidl
  264. )
  265. {
  266. ASSERT(CDFIDL_IsValid(pcdfidl));
  267. IMalloc *pIMalloc;
  268. if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
  269. {
  270. ASSERT(pIMalloc);
  271. ASSERT(pIMalloc->DidAlloc(pcdfidl));
  272. pIMalloc->Free(pcdfidl);
  273. pIMalloc->Release();
  274. }
  275. }
  276. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  277. //
  278. // *** CDFIDL_GetDisplayName ***
  279. //
  280. //
  281. // Description:
  282. // Gets the name stored in the given cdf item id list.
  283. //
  284. // Parameters:
  285. // [In] pcdfidl - A pointer to a cdf item id list.
  286. // [Out] pName - A pointer to a STRRET structure. STRRET has the following
  287. // structure:
  288. // UINT uType - STRRET_CSTR, _OFFSET or _WSTR
  289. // union {
  290. // LPWSTR pOleStr;
  291. // UINT uOffset;
  292. // char cStr[MAX_PATH];
  293. // }
  294. //
  295. // Return:
  296. // S_OK on success. E_Fail otherwise.
  297. //
  298. // Comments:
  299. // This function returns the name as an offset of the string from the start
  300. // of the cdf item id list.
  301. //
  302. ////////////////////////////////////////////////////////////////////////////////
  303. HRESULT
  304. CDFIDL_GetDisplayName(
  305. PCDFITEMIDLIST pcdfidl,
  306. LPSTRRET pName
  307. )
  308. {
  309. ASSERT(CDFIDL_IsValid(pcdfidl));
  310. ASSERT(pName);
  311. #ifdef UNICODE
  312. #ifdef SHDOCVW_UNICODE //open this when shdocvw becomes unicode
  313. IMalloc* pIMalloc;
  314. HRESULT hr = SHGetMalloc(&pIMalloc);
  315. if (SUCCEEDED(hr))
  316. {
  317. ASSERT(pIMalloc);
  318. pName->uType = STRRET_WSTR;
  319. LPTSTR pszName = CDFIDL_GetName(pcdfidl);
  320. pName->pOleStr = (LPWSTR)pIMalloc->Alloc(ARRAYSIZE(pszName));
  321. if (pName->pOleStr)
  322. lstrcpyW(pName->pOleStr, pszName);
  323. pIMalloc->Release();
  324. }
  325. #else
  326. pName->uType = STRRET_CSTR;
  327. LPTSTR pszName = CDFIDL_GetName(pcdfidl);
  328. SHTCharToAnsi(pszName, pName->cStr, ARRAYSIZE(pName->cStr));
  329. #endif
  330. #else
  331. pName->uType = STRRET_OFFSET;
  332. pName->uOffset = (UINT)((LPBYTE)CDFIDL_GetName(pcdfidl) - (LPBYTE)pcdfidl);
  333. #endif
  334. return S_OK;
  335. }
  336. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  337. //
  338. // *** CDFIDL_GetName ***
  339. //
  340. //
  341. // Description:
  342. // Gets a pointer to the URL stored in the given cdf item id list.
  343. //
  344. // Parameters:
  345. // [In] pcdfidl - A pointer to a cdf item id list.
  346. //
  347. // Return:
  348. // A LPTSTR to the Name stored in the pidl.
  349. //
  350. // Comments:
  351. // This function returns a pointer to the Name in the cdf item id list.
  352. // The pointer is valid for the life of the item id list. The caller is
  353. // resposible for maintaining the item id list and for not using the
  354. // the returned pointer after the id list is freed.
  355. //
  356. // The name returned is the name of the last item in the list.
  357. //
  358. ////////////////////////////////////////////////////////////////////////////////
  359. LPTSTR
  360. CDFIDL_GetName(
  361. PCDFITEMIDLIST pcdfidl
  362. )
  363. {
  364. ASSERT(CDFIDL_IsValid(pcdfidl));
  365. pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  366. return CDFIDL_GetNameId(&pcdfidl->mkid);
  367. }
  368. LPTSTR
  369. CDFIDL_GetNameId(
  370. PCDFITEMID pcdfid
  371. )
  372. {
  373. ASSERT(pcdfid);
  374. #if defined(ALIGNMENT_MACHINE)
  375. return (LPTSTR)(ALIGN4((ULONG_PTR)pcdfid->szName));
  376. #else
  377. return pcdfid->szName;
  378. #endif
  379. }
  380. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  381. //
  382. // *** CDFIDL_GetURL ***
  383. //
  384. //
  385. // Description:
  386. // Gets a pointer to the URL stored in the given cdf item id list.
  387. //
  388. // Parameters:
  389. // [In] pcdfidl - A pointer to a cdf item id list.
  390. //
  391. // Return:
  392. // A LPTSTR to the URL value for the given pcdfidl.
  393. //
  394. // Comments:
  395. // This function returns a pointer to the URL in the cdf item id list. The
  396. // pointer is valid for the life of the item id list. The caller is
  397. // resposible for maintaining the item id list and for not using the
  398. // the returned pointer after the id list is freed.
  399. //
  400. // The URL returned is the URL of the last item in the list.
  401. //
  402. ////////////////////////////////////////////////////////////////////////////////
  403. LPTSTR
  404. CDFIDL_GetURL(
  405. PCDFITEMIDLIST pcdfidl
  406. )
  407. {
  408. ASSERT(CDFIDL_IsValid(pcdfidl));
  409. //
  410. // Get the first string after the name.
  411. //
  412. LPTSTR szURL = CDFIDL_GetName(pcdfidl);
  413. while (*szURL++);
  414. return szURL;
  415. }
  416. LPTSTR
  417. CDFIDL_GetURLId(
  418. PCDFITEMID pcdfid
  419. )
  420. {
  421. ASSERT(pcdfid);
  422. //
  423. // Get the first string after the name.
  424. //
  425. LPTSTR szURL = CDFIDL_GetNameId(pcdfid);
  426. while (*szURL++);
  427. return szURL;
  428. }
  429. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  430. //
  431. // *** CDFIDL_GetIndex ***
  432. //
  433. //
  434. // Description:
  435. // Returns the index item of the given cdf id list.
  436. //
  437. // Parameters:
  438. // [In] pcdfidl - Pointer to the cdf item id list.
  439. //
  440. // Return:
  441. // Returns the index item of the given id list.
  442. //
  443. // Comments:
  444. //
  445. //
  446. ////////////////////////////////////////////////////////////////////////////////
  447. ULONG
  448. CDFIDL_GetIndex(
  449. PCDFITEMIDLIST pcdfidl
  450. )
  451. {
  452. pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  453. return CDFIDL_GetIndexId(&pcdfidl->mkid);
  454. }
  455. ULONG
  456. CDFIDL_GetIndexId(
  457. PCDFITEMID pcdfid
  458. )
  459. {
  460. return pcdfid->nIndex;
  461. }
  462. #define ASTR_HISTORY_PREFIX TEXT("Visited: ")
  463. //
  464. // Looks the URL up in the cache to see if the user has ever read this url
  465. //
  466. // REVIEW
  467. // REVIEW - Should probably use IUrlStorage instead of constructing the
  468. // REVIEW
  469. // history cache URL on the fly
  470. //
  471. BOOL
  472. CDFIDL_IsUnreadURL(
  473. LPTSTR szUrl
  474. )
  475. {
  476. DWORD dwLen;
  477. //
  478. // Canonicalize the input url.
  479. //
  480. TCHAR szCanonicalizedUrl[INTERNET_MAX_URL_LENGTH];
  481. dwLen = INTERNET_MAX_URL_LENGTH;
  482. if (!InternetCanonicalizeUrl(szUrl, szCanonicalizedUrl, &dwLen, 0))
  483. StrCpyN(szCanonicalizedUrl, szUrl, ARRAYSIZE(szCanonicalizedUrl));
  484. //
  485. // Build a string that is the URL prefixed with VISITED: and the UserName
  486. //
  487. TCHAR szVisited[
  488. INTERNET_MAX_USER_NAME_LENGTH+
  489. 1+
  490. INTERNET_MAX_URL_LENGTH+
  491. ARRAYSIZE(ASTR_HISTORY_PREFIX)];
  492. StrCpy(szVisited, ASTR_HISTORY_PREFIX);
  493. StrCatN(szVisited, CDFIDL_GetUserName(), ARRAYSIZE(szVisited));
  494. int len = StrLen(szVisited);
  495. StrCpyN(szVisited + len++, TEXT("@"), ARRAYSIZE(szVisited) - len);
  496. //len++; //bug, this will introduce a null char...
  497. StrCpyN(szVisited + len++, szCanonicalizedUrl, ARRAYSIZE(szVisited) - len);
  498. // Check for trailing slash and eliminate, copied from shdocvw\urlhist.cpp
  499. LPTSTR pszT = CharPrev(szVisited, szVisited + lstrlen(szVisited));
  500. if (*pszT == TEXT('/'))
  501. {
  502. ASSERT(lstrlen(pszT) == 1);
  503. *pszT = 0;
  504. }
  505. //
  506. // If the VISITED: entry does not exist in the cache assume url is unread
  507. //
  508. #ifndef ALIGNMENT_MACHINE
  509. BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  510. LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)visitedCEI;
  511. #else
  512. union
  513. {
  514. double align8;
  515. BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  516. } alignedvisitedCEI;
  517. LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedvisitedCEI;
  518. #endif /* ALIGNMENT_MACHINE */
  519. dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
  520. if (GetUrlCacheEntryInfo(szVisited, pVisitedCEI, &dwLen) == FALSE)
  521. {
  522. return TRUE;
  523. }
  524. else
  525. {
  526. //
  527. // URL has been visited, but it still may be unread if the page has
  528. // been placed in the cache by the infodelivery mechanism
  529. //
  530. #ifndef ALIGNMENT_MACHINE
  531. BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  532. LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)urlCEI;
  533. #else
  534. union
  535. {
  536. double align8;
  537. BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  538. } alignedurlCEI;
  539. LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedurlCEI;
  540. #endif /* ALIGNMENT_MACHINE */
  541. dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
  542. if (GetUrlCacheEntryInfo(szCanonicalizedUrl, pUrlCEI, &dwLen) == FALSE)
  543. {
  544. return FALSE; // no url cache entry but url was visited so mark read
  545. }
  546. else
  547. {
  548. //
  549. // If the url has been modified after the time of the visited
  550. // record then url is unread
  551. //
  552. if (CompareFileTime(&pUrlCEI->LastModifiedTime,
  553. &pVisitedCEI->LastModifiedTime) > 0)
  554. {
  555. return TRUE;
  556. }
  557. else
  558. {
  559. return FALSE;
  560. }
  561. }
  562. }
  563. }
  564. //
  565. // Looks the URL up in the cache. TRUE if it is and FALSE otherwise
  566. //
  567. BOOL
  568. CDFIDL_IsCachedURL(
  569. LPWSTR wszUrl
  570. )
  571. {
  572. BOOL fCached;
  573. TCHAR szUrlT[INTERNET_MAX_URL_LENGTH];
  574. //
  575. // Canonicalize the input url.
  576. //
  577. if (SHUnicodeToTChar(wszUrl, szUrlT, ARRAYSIZE(szUrlT)))
  578. {
  579. URL_COMPONENTS uc;
  580. memset(&uc, 0, sizeof(uc));
  581. uc.dwStructSize = sizeof(URL_COMPONENTS);
  582. uc.dwSchemeLength = 1;
  583. if (InternetCrackUrl(szUrlT, 0, 0, &uc))
  584. {
  585. // zekel should look at this
  586. TCHAR *pchLoc = StrChr(szUrlT, TEXT('#'));
  587. if (pchLoc)
  588. *pchLoc = TEXT('\0');
  589. fCached = GetUrlCacheEntryInfoEx(szUrlT, NULL, NULL, NULL, NULL, NULL, 0);
  590. if(fCached)
  591. {
  592. return TRUE;
  593. }
  594. else
  595. {
  596. TCHAR szCanonicalizedUrlT[INTERNET_MAX_URL_LENGTH];
  597. DWORD dwLen = INTERNET_MAX_URL_LENGTH;
  598. InternetCanonicalizeUrl(szUrlT, szCanonicalizedUrlT, &dwLen, 0);
  599. fCached = GetUrlCacheEntryInfoEx(szCanonicalizedUrlT, NULL, NULL, NULL, NULL, NULL, 0);
  600. if(fCached)
  601. return TRUE;
  602. }
  603. }
  604. }
  605. return FALSE;
  606. }
  607. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  608. //
  609. // *** CDFIDL_GetAttributes ***
  610. //
  611. //
  612. // Description:
  613. // Returns the attributes item of the given cdf item id list.
  614. //
  615. // Parameters:
  616. // [In] pIXMLElementCollectionparent - The containing element collection.
  617. // [In] pcdfidl - A pointer to the cdf item id list.
  618. // [In] fAttributesFilter - Determines which flags to bother
  619. // looking at
  620. //
  621. // Return:
  622. // The attributes of the given id list.
  623. // Zero on failure. Note: Zero is a valid attribute value.
  624. //
  625. // Comments:
  626. // The attribute flags returned by this function can be used directly as a
  627. // return value by IShellFolder->GetAttributesOf().
  628. //
  629. ////////////////////////////////////////////////////////////////////////////////
  630. ULONG
  631. CDFIDL_GetAttributes(
  632. IXMLElementCollection* pIXMLElementCollectionParent,
  633. PCDFITEMIDLIST pcdfidl,
  634. ULONG fAttributesFilter
  635. )
  636. {
  637. ASSERT(pIXMLElementCollectionParent);
  638. ASSERT(CDFIDL_IsValid(pcdfidl));
  639. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  640. //
  641. // REVIEW: Need to properly determine shell attributes of cdf items.
  642. //
  643. ULONG uRet;
  644. if (CDFIDL_IsFolderId(&pcdfidl->mkid))
  645. {
  646. uRet = SFGAO_FOLDER | SFGAO_CANLINK;
  647. // If we weren't asked for HASSUBFOLDER don't bother looking for it
  648. // This should be a win in non tree views (ie. std open mode)
  649. if ((SFGAO_HASSUBFOLDER & fAttributesFilter) &&
  650. pIXMLElementCollectionParent &&
  651. XML_ChildContainsFolder(pIXMLElementCollectionParent,
  652. CDFIDL_GetIndex(pcdfidl)))
  653. {
  654. uRet |= SFGAO_HASSUBFOLDER;
  655. }
  656. }
  657. else
  658. {
  659. uRet = SFGAO_CANLINK;
  660. // If we weren't asked for NEWCONTENT don't bother looking for it
  661. // This will be a win in non channel pane views.
  662. // Can't test for SFGAO_NEWCONTENT since shell is never
  663. // expressing interest in it!
  664. if (/*(SFGAO_NEWCONTENT & fAttributeFilter) && */
  665. CDFIDL_IsUnreadURL(CDFIDL_GetURL(pcdfidl)))
  666. {
  667. uRet |= SFGAO_NEWCONTENT;
  668. }
  669. }
  670. return uRet;
  671. }
  672. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  673. //
  674. // *** CDFIDL_Compare ***
  675. //
  676. //
  677. // Description:
  678. // Compares two cdf item id lists
  679. //
  680. // Parameters:
  681. // [In] pcdfidl1 - A pointer to the first item id list to compare.
  682. // [In] pcdfidl2 - A pointer to the second item id list to compare.
  683. //
  684. // Return:
  685. // -1 if item 1 comes before item 2.
  686. // 0 if the items are equal.
  687. // 1 if item 2 comes before item 1.
  688. //
  689. // Comments:
  690. // Sort Order:
  691. // 1) Use the CompareId result of the first items in the lists.
  692. // 2) If 1) returns 0. Compare the next two items in the lists.
  693. // 3) If both list are empty. They are equal.
  694. // 4) The shorter id list comes first.
  695. //
  696. ////////////////////////////////////////////////////////////////////////////////
  697. SHORT
  698. CDFIDL_Compare(
  699. PCDFITEMIDLIST pcdfidl1,
  700. PCDFITEMIDLIST pcdfidl2
  701. )
  702. {
  703. ASSERT(CDFIDL_IsValid(pcdfidl1));
  704. ASSERT(CDFIDL_IsValid(pcdfidl2));
  705. SHORT sRet;
  706. sRet = CDFIDL_CompareId(&pcdfidl1->mkid, &pcdfidl2->mkid);
  707. if (0 == sRet)
  708. {
  709. if (!ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
  710. {
  711. sRet = CDFIDL_Compare((PCDFITEMIDLIST)_ILNext(pcdfidl1),
  712. (PCDFITEMIDLIST)_ILNext(pcdfidl2));
  713. }
  714. else if(!ILIsEmpty(_ILNext(pcdfidl1)) && ILIsEmpty(_ILNext(pcdfidl2)))
  715. {
  716. sRet = 1;
  717. }
  718. else if (ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
  719. {
  720. sRet = -1;
  721. }
  722. }
  723. return sRet;
  724. }
  725. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  726. //
  727. // *** CDFIDL_CompareId ***
  728. //
  729. //
  730. // Description:
  731. // Compares two item cdf item ids.
  732. //
  733. // Parameters:
  734. // [In] pcdfid1 - A pointer to the first item id to compare.
  735. // [In] pcdfid2 - A pointer to the second item id to compare.
  736. //
  737. // Return:
  738. // -1 if item 1 comes before item 2.
  739. // 0 if the items are the same.
  740. // 1 if item 2 comes before item 1.
  741. //
  742. // Comments:
  743. // Sort Order:
  744. // 1) CDF_FolderLink (Essentially an URL for the current folder). These
  745. // have an index of -1.
  746. // 2) Everything else accoring to its order in the CDF. These have
  747. // a zero-based index.
  748. // 3) Non CDF items (should't have any).
  749. //
  750. ////////////////////////////////////////////////////////////////////////////////
  751. SHORT
  752. CDFIDL_CompareId(
  753. PCDFITEMID pcdfid1,
  754. PCDFITEMID pcdfid2
  755. )
  756. {
  757. ASSERT(CDFIDL_IsValidId(pcdfid1));
  758. ASSERT(CDFIDL_IsValidId(pcdfid2));
  759. SHORT sRet;
  760. if (pcdfid1->nIndex < pcdfid2->nIndex)
  761. {
  762. sRet = -1;
  763. }
  764. else if (pcdfid1->nIndex > pcdfid2->nIndex)
  765. {
  766. sRet = 1;
  767. }
  768. else
  769. {
  770. sRet = (short) CompareString(LOCALE_USER_DEFAULT, 0, CDFIDL_GetNameId(pcdfid1),
  771. -1, CDFIDL_GetNameId(pcdfid2), -1);
  772. //
  773. // Note: CompareString returns 1 if S1 comes before S2, 2 if S1 is equal
  774. // to S2, 3 if S2 comes before S1 and 0 on error.
  775. //
  776. sRet = sRet ? sRet - 2 : 0;
  777. if (0 == sRet)
  778. {
  779. //
  780. // If the URLs aren't equal just pick one at random.
  781. //
  782. sRet = !StrEql(CDFIDL_GetURLId(pcdfid1), CDFIDL_GetURLId(pcdfid2));
  783. ASSERT((pcdfid1->cb == pcdfid2->cb) || 0 != sRet);
  784. ASSERT((pcdfid1->cdfItemType == pcdfid1->cdfItemType) || 0 != sRet);
  785. }
  786. }
  787. return sRet;
  788. }
  789. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  790. //
  791. // *** CDFIDL_IsValid ***
  792. //
  793. //
  794. // Description:
  795. // Determines if the given pcdfidl is valid.
  796. //
  797. // Parameters:
  798. // pcdfid - A pointer to the cdf id to check.
  799. //
  800. // Return:
  801. // TRUE if the id is a cdf id.
  802. // FALSE otherwise.
  803. //
  804. // Comments:
  805. // An empty list is not valid.
  806. //
  807. ////////////////////////////////////////////////////////////////////////////////
  808. BOOL
  809. CDFIDL_IsValid(
  810. PCDFITEMIDLIST pcdfidl
  811. )
  812. {
  813. BOOL bRet;
  814. if (pcdfidl && (pcdfidl->mkid.cb > 0))
  815. {
  816. bRet = TRUE;
  817. while (pcdfidl->mkid.cb && bRet)
  818. {
  819. bRet = CDFIDL_IsValidId(&pcdfidl->mkid);
  820. pcdfidl = (PCDFITEMIDLIST)_ILNext((LPITEMIDLIST)pcdfidl);
  821. }
  822. }
  823. else
  824. {
  825. bRet = FALSE;
  826. }
  827. return bRet;
  828. }
  829. //
  830. // Inline helper functions.
  831. //
  832. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  833. //
  834. // *** CDFIDL_IsValidId ***
  835. //
  836. //
  837. // Description:
  838. // Inline function that returns TRUE if the given id is a pointer to a cdf
  839. // item id.
  840. //
  841. // Parameters:
  842. // pcdfid - A pointer to the cdf id to check.
  843. //
  844. // Return:
  845. // TRUE if the id is a cdf id.
  846. // FALSE otherwise.
  847. //
  848. // Comments:
  849. // This function is not completely safe. If the first word pointed to
  850. // is large but the memory block pointed to is smaller than a 8 bytes an
  851. // access violation will occur. Also, if the first word is large enough and
  852. // the second DWORD is equal to CDFITEM_ID but the item isn't a cdf id a
  853. // false positive will occur.
  854. //
  855. ////////////////////////////////////////////////////////////////////////////////
  856. BOOL
  857. CDFIDL_IsValidId(
  858. PCDFITEMID pcdfid
  859. )
  860. {
  861. ASSERT(pcdfid);
  862. return (pcdfid->cb >= (sizeof(CDFITEMID) + sizeof(TCHAR)) &&
  863. pcdfid->dwId == CDFITEMID_ID &&
  864. CDFIDL_IsValidSize(pcdfid) &&
  865. CDFIDL_IsValidType(pcdfid) &&
  866. CDFIDL_IsValidIndex(pcdfid) &&
  867. CDFIDL_IsValidStrings(pcdfid) );
  868. }
  869. inline
  870. BOOL
  871. CDFIDL_IsValidSize(
  872. PCDFITEMID pcdfid
  873. )
  874. {
  875. int cbName = (StrLen(CDFIDL_GetNameId(pcdfid)) + 1) *
  876. sizeof(TCHAR);
  877. int cbURL = (StrLen(CDFIDL_GetURLId(pcdfid)) + 1) *
  878. sizeof(TCHAR);
  879. #ifndef ALIGNMENT_MACHINE
  880. return (sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL == pcdfid->cb);
  881. #else
  882. return ((ALIGN4(sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL)) == pcdfid->cb);
  883. #endif
  884. }
  885. inline
  886. BOOL
  887. CDFIDL_IsValidType(
  888. PCDFITEMID pcdfid
  889. )
  890. {
  891. return ((CDF_Folder == (CDFITEMTYPE)pcdfid->cdfItemType) ||
  892. (CDF_Link == (CDFITEMTYPE)pcdfid->cdfItemType) ||
  893. (CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType) );
  894. }
  895. inline
  896. BOOL
  897. CDFIDL_IsValidIndex(
  898. PCDFITEMID pcdfid
  899. )
  900. {
  901. return ( pcdfid->nIndex >= 0
  902. ||
  903. (INDEX_CHANNEL_LINK == pcdfid->nIndex &&
  904. CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType));
  905. }
  906. inline
  907. BOOL
  908. CDFIDL_IsValidStrings(
  909. PCDFITEMID pcdfid
  910. )
  911. {
  912. //
  913. // REVIEW: Validate pidl strings.
  914. //
  915. return TRUE;
  916. }
  917. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  918. //
  919. // *** CDFIDL_IsFolder ***
  920. //
  921. //
  922. // Description:
  923. // Inline function that returns TRUE if the given cdfidl is a folder as far
  924. // as the shel is concerned.
  925. //
  926. // Parameters:
  927. // pcdfidl - The cdf item id list to check.
  928. //
  929. // Return:
  930. // TRUE if the cdf item id list is a folder.
  931. //
  932. // Comments:
  933. //
  934. //
  935. ////////////////////////////////////////////////////////////////////////////////
  936. BOOL
  937. CDFIDL_IsFolder(
  938. PCDFITEMIDLIST pcdfidl
  939. )
  940. {
  941. ASSERT(CDFIDL_IsValid(pcdfidl));
  942. pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  943. return CDFIDL_IsFolderId(&pcdfidl->mkid);
  944. }
  945. BOOL
  946. CDFIDL_IsFolderId(
  947. PCDFITEMID pcdfid
  948. )
  949. {
  950. ASSERT(CDFIDL_IsValidId(pcdfid));
  951. return (CDF_Folder == (CDFITEMTYPE)pcdfid->cdfItemType);
  952. }
  953. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  954. //
  955. // *** CDFIDL_NonCdfGetName ***
  956. //
  957. //
  958. // Description:
  959. // Gets the name stored in the given non-cdf item id list.
  960. //
  961. // Parameters:
  962. // [In] pcdfidl - A pointer to a cdf item id list. Can be NULL.
  963. // [Out] pName - A pointer to a STRRET structure. STRRET has the following
  964. // structure:
  965. // UINT uType - STRRET_CSTR, _OFFSET or _WSTR
  966. // union {
  967. // LPWSTR pOleStr;
  968. // UINT uOffset;
  969. // char cStr[MAX_PATH];
  970. // }
  971. //
  972. // Return:
  973. // S_OK on success. E_Fail otherwise.
  974. //
  975. // Comments:
  976. // This function returns the name as a cString in the STRRET structure.
  977. //
  978. // ILGetDisplayName returns the full path. This function strips out the
  979. // filename sans extension.
  980. //
  981. ////////////////////////////////////////////////////////////////////////////////
  982. #if 0
  983. HRESULT
  984. CDFIDL_NonCdfGetDisplayName(
  985. LPCITEMIDLIST pidl,
  986. LPSTRRET pName
  987. )
  988. {
  989. ASSERT(pName);
  990. HRESULT hr;
  991. //
  992. // REVIEW: Hack to get the name of a shell pidl.
  993. //
  994. if (ILGetDisplayName(pidl, pName->cStr))
  995. {
  996. TCHAR* p1 = pName->cStr;
  997. TCHAR* p2 = p1;
  998. while (*p1++); // Go to the end.
  999. while (*--p1 != TEXT('\\')); // Back to last backslash.
  1000. while (TEXT('.') != (*p2++ = *++p1)); // Copy the name.
  1001. *--p2 = TEXT('\0'); // NULL terminate.
  1002. pName->uType = STRRET_CSTR;
  1003. hr = S_OK;
  1004. }
  1005. else
  1006. {
  1007. hr = E_FAIL;
  1008. }
  1009. return hr;
  1010. }
  1011. #endif