cdfidl.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 30k
Category:

Windows Kernel

Development Platform:

Visual C++

  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 UNIX
  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 UNIX
  101.     cbItemId = ALIGN4(cbItemId);
  102. #endif /* !UNIX */
  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 UNIX
  123.             USHORT cbActaulItemId = sizeof(CDFITEMID) + cbName + cbURL - sizeof(TCHAR);
  124.             if(cbActaulItemId < cbItemId)
  125.                 memset((LPBYTE)pcdfidl + cbActaulItemId, 0, cbItemId-cbActaulItemId);
  126. #endif /* UNIX */
  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 UNIX
  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)(pcdfidl->mkid.szName));
  147.             SHUnicodeToTChar(pCdfItem->bstrName, pszTempName, cbName);
  148.         pszTempName = (LPTSTR)((ULONG)(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.    
  242.     return pcdfidlRet;
  243. }
  244. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  245. //
  246. // *** CDFIDL_Free ***
  247. //
  248. //
  249. // Description:
  250. //     Free the given cdf item id list.
  251. //
  252. // Parameters:
  253. //     [In]  pcdfidl - Pointer to the cdf id list to be freed.
  254. //
  255. // Return:
  256. //     No return value.
  257. //
  258. // Comments:
  259. //
  260. //
  261. ////////////////////////////////////////////////////////////////////////////////
  262. void
  263. CDFIDL_Free(
  264.     PCDFITEMIDLIST pcdfidl
  265. )
  266. {
  267.     ASSERT(CDFIDL_IsValid(pcdfidl));
  268.     IMalloc *pIMalloc;
  269.     if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
  270.     {
  271.         ASSERT(pIMalloc);
  272.         ASSERT(pIMalloc->DidAlloc(pcdfidl));
  273.         
  274.         pIMalloc->Free(pcdfidl);
  275.         pIMalloc->Release();
  276.     }
  277. }
  278. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  279. //
  280. // *** CDFIDL_GetDisplayName ***
  281. //
  282. //
  283. // Description:
  284. //     Gets the name stored in the given cdf item id list.
  285. //
  286. // Parameters:
  287. //     [In]  pcdfidl - A pointer to a cdf item id list.
  288. //     [Out] pName - A pointer to a STRRET structure.  STRRET has the following
  289. //                   structure:
  290. //                       UINT uType             - STRRET_CSTR, _OFFSET or _WSTR
  291. //                       union {
  292. //                           LPWSTR pOleStr;
  293. //                           UINT   uOffset;
  294. //                           char   cStr[MAX_PATH];
  295. //                       }
  296. //
  297. // Return:
  298. //     S_OK on success.  E_Fail otherwise.
  299. //
  300. // Comments:
  301. //     This function returns the name as an offset of the string from the start
  302. //     of the cdf item id list.
  303. //
  304. ////////////////////////////////////////////////////////////////////////////////
  305. HRESULT
  306. CDFIDL_GetDisplayName(
  307.     PCDFITEMIDLIST pcdfidl,
  308.     LPSTRRET pName
  309. )
  310. {
  311.     ASSERT(CDFIDL_IsValid(pcdfidl));
  312.     ASSERT(pName);
  313. #ifdef UNICODE
  314. #ifdef SHDOCVW_UNICODE     //open this when shdocvw becomes unicode
  315.     IMalloc* pIMalloc;
  316.     HRESULT hr = SHGetMalloc(&pIMalloc);
  317.     if (SUCCEEDED(hr))
  318.     {
  319.         ASSERT(pIMalloc);
  320.         pName->uType = STRRET_WSTR;
  321.         LPTSTR pszName = CDFIDL_GetName(pcdfidl);
  322.         pName->pOleStr = (LPWSTR)pIMalloc->Alloc(ARRAYSIZE(pszName));
  323.         if (pName->pOleStr)
  324.             lstrcpyW(pName->pOleStr, pszName);
  325.         pIMalloc->Release();
  326.     }
  327. #else
  328.     pName->uType = STRRET_CSTR;
  329.     LPTSTR pszName = CDFIDL_GetName(pcdfidl);
  330.     SHTCharToAnsi(pszName, pName->cStr, ARRAYSIZE(pName->cStr));
  331. #endif
  332. #else
  333.     pName->uType = STRRET_OFFSET;
  334.     pName->uOffset = (UINT)((LPBYTE)CDFIDL_GetName(pcdfidl) - (LPBYTE)pcdfidl);
  335. #endif
  336.     return S_OK;
  337. }
  338. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  339. //
  340. // *** CDFIDL_GetName ***
  341. //
  342. //
  343. // Description:
  344. //     Gets a pointer to the URL stored in the given cdf item id list.
  345. //
  346. // Parameters:
  347. //     [In]  pcdfidl - A pointer to a cdf item id list.
  348. //
  349. // Return:
  350. //     A LPTSTR to the Name stored in the pidl.
  351. //
  352. // Comments:
  353. //     This function returns a pointer to the Name in the cdf item id list.
  354. //     The pointer is valid for the life of the item id list.  The caller is
  355. //     resposible for maintaining the item id list and for not using the
  356. //     the returned pointer after the id list is freed.
  357. //
  358. //     The name returned is the name of the last item in the list. 
  359. //
  360. ////////////////////////////////////////////////////////////////////////////////
  361. LPTSTR
  362. CDFIDL_GetName(
  363.     PCDFITEMIDLIST pcdfidl
  364. )
  365. {
  366.     ASSERT(CDFIDL_IsValid(pcdfidl));
  367.     pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  368.     
  369.     return CDFIDL_GetNameId(&pcdfidl->mkid);
  370. }
  371. LPTSTR
  372. CDFIDL_GetNameId(
  373.     PCDFITEMID pcdfid
  374. )
  375. {
  376.     ASSERT(pcdfid);
  377. #ifndef UNIX
  378.     return pcdfid->szName;
  379. #else
  380.     return (LPTSTR)(ALIGN4((ULONG)pcdfid->szName));
  381. #endif
  382. }
  383. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  384. //
  385. // *** CDFIDL_GetURL ***
  386. //
  387. //
  388. // Description:
  389. //     Gets a pointer to the URL stored in the given cdf item id list.
  390. //
  391. // Parameters:
  392. //     [In]  pcdfidl - A pointer to a cdf item id list.
  393. //
  394. // Return:
  395. //     A LPTSTR to the URL value for the given pcdfidl.
  396. //
  397. // Comments:
  398. //     This function returns a pointer to the URL in the cdf item id list.  The
  399. //     pointer is valid for the life of the item id list.  The caller is
  400. //     resposible for maintaining the item id list and for not using the
  401. //     the returned pointer after the id list is freed. 
  402. //
  403. //     The URL returned is the URL of the last item in the list.
  404. //
  405. ////////////////////////////////////////////////////////////////////////////////
  406. LPTSTR
  407. CDFIDL_GetURL(
  408.     PCDFITEMIDLIST pcdfidl
  409. )
  410. {
  411.     ASSERT(CDFIDL_IsValid(pcdfidl));
  412.     //
  413.     // Get the first string after the name.
  414.     //
  415.     LPTSTR szURL = CDFIDL_GetName(pcdfidl);
  416.     while (*szURL++);
  417.     return szURL;
  418. }
  419. LPTSTR
  420. CDFIDL_GetURLId(
  421.     PCDFITEMID pcdfid
  422. )
  423. {
  424.     ASSERT(pcdfid);
  425.     //
  426.     // Get the first string after the name.
  427.     //
  428.     LPTSTR szURL = CDFIDL_GetNameId(pcdfid);
  429.     while (*szURL++);
  430.     return szURL;
  431. }
  432. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  433. //
  434. // *** CDFIDL_GetIndex ***
  435. //
  436. //
  437. // Description:
  438. //     Returns the index item of the given cdf id list.
  439. //
  440. // Parameters:
  441. //     [In]  pcdfidl - Pointer to the cdf item id list.
  442. //
  443. // Return:
  444. //     Returns the index item of the given id list.
  445. //
  446. // Comments:
  447. //
  448. //
  449. ////////////////////////////////////////////////////////////////////////////////
  450. ULONG
  451. CDFIDL_GetIndex(
  452.     PCDFITEMIDLIST pcdfidl
  453. )
  454. {
  455.     pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  456.     return CDFIDL_GetIndexId(&pcdfidl->mkid);
  457. }
  458. ULONG
  459. CDFIDL_GetIndexId(
  460.     PCDFITEMID pcdfid
  461. )
  462. {
  463.     return pcdfid->nIndex;
  464. }
  465. #define ASTR_HISTORY_PREFIX TEXT("Visited: ")
  466. //
  467. // Looks the URL up in the cache to see if the user has ever read this url
  468. //
  469. // REVIEW
  470. // REVIEW - Should probably use IUrlStorage instead of constructing the 
  471. // REVIEW
  472. // history cache URL on the fly
  473. //
  474. BOOL
  475. CDFIDL_IsUnreadURL(
  476.     LPTSTR szUrl
  477. )
  478. {
  479.     DWORD dwLen;
  480.     
  481.     //
  482.     //  Canonicalize the input url.
  483.     // 
  484.     TCHAR szCanonicalizedUrl[INTERNET_MAX_URL_LENGTH];
  485.     dwLen = INTERNET_MAX_URL_LENGTH;
  486.     InternetCanonicalizeUrl(szUrl, szCanonicalizedUrl, &dwLen, 0);
  487.     
  488.     //
  489.     // Build a string that is the URL prefixed with VISITED: and the UserName
  490.     //
  491.     TCHAR szVisited[
  492.         INTERNET_MAX_USER_NAME_LENGTH+
  493.         1+
  494.         INTERNET_MAX_URL_LENGTH+
  495.         ARRAYSIZE(ASTR_HISTORY_PREFIX)];
  496.  
  497.     StrCpy(szVisited, ASTR_HISTORY_PREFIX);
  498.     StrCatN(szVisited, CDFIDL_GetUserName(), ARRAYSIZE(szVisited));
  499.     int len = StrLen(szVisited);
  500.     StrCpyN(szVisited + len++, TEXT("@"), ARRAYSIZE(szVisited) - len);
  501.     //len++;        //bug, this will introduce a null char...
  502.     StrCpyN(szVisited + len++, szCanonicalizedUrl, ARRAYSIZE(szVisited) - len);          
  503.     // Check for trailing slash and eliminate, copied from shdocvwurlhist.cpp
  504.     LPTSTR pszT = CharPrev(szVisited, szVisited + lstrlen(szVisited));
  505.     if (*pszT == TEXT('/'))
  506.     {
  507.         ASSERT(lstrlen(pszT) == 1);
  508.         *pszT = 0;
  509.     }
  510.     //
  511.     // If the VISITED: entry does not exist in the cache assume url is unread
  512.     //
  513. #ifndef UNIX
  514.     BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  515.     LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)visitedCEI;
  516. #else
  517.     union
  518.     {
  519.         double align8;
  520.         BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  521.     } alignedvisitedCEI;
  522.     LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedvisitedCEI;
  523. #endif /* UNIX */
  524.     dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
  525.     if (GetUrlCacheEntryInfo(szVisited, pVisitedCEI, &dwLen) == FALSE)
  526.     {
  527.         return TRUE;
  528.     }
  529.     else
  530.     {
  531.         //
  532.         // URL has been visited, but it still may be unread if the page has
  533.         // been placed in the cache by the infodelivery mechanism
  534.         //
  535. #ifndef UNIX
  536.         BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  537.         LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)urlCEI;
  538. #else
  539.         union
  540.         {
  541.             double align8;
  542.             BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
  543.         } alignedurlCEI;
  544.         LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedurlCEI;
  545. #endif /* UNIX */
  546.         dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
  547.         if (GetUrlCacheEntryInfo(szCanonicalizedUrl, pUrlCEI, &dwLen) == FALSE)
  548.         {
  549.             return FALSE; // no url cache entry but url was visited so mark read
  550.         }
  551.         else
  552.         {
  553.             //
  554.             // If the url has been modified after the time of the visited 
  555.             // record then url is unread
  556.             //
  557.             if (CompareFileTime(&pUrlCEI->LastModifiedTime,
  558.                                 &pVisitedCEI->LastModifiedTime) > 0)
  559.             {
  560.                 return TRUE;
  561.             }
  562.             else
  563.             {
  564.                 return FALSE;
  565.             }
  566.         }
  567.     }
  568. }
  569. //
  570. // Looks the URL up in the cache. TRUE if it is and FALSE otherwise
  571. //
  572. BOOL
  573. CDFIDL_IsCachedURL(
  574.     LPWSTR wszUrl
  575. )
  576. {
  577.     BOOL  fCached;
  578.     TCHAR szUrlT[INTERNET_MAX_URL_LENGTH];
  579.     //
  580.     //  Canonicalize the input url.
  581.     // 
  582.     
  583.     if (SHUnicodeToTChar(wszUrl, szUrlT, ARRAYSIZE(szUrlT)))
  584.     {
  585.         URL_COMPONENTS uc;
  586.  
  587.         memset(&uc, 0, sizeof(uc));
  588.         uc.dwStructSize = sizeof(URL_COMPONENTS);
  589.         uc.dwSchemeLength = 1;
  590.         if (InternetCrackUrl(szUrlT, 0, 0, &uc))
  591.         {
  592.             // BUGBUG: zekel should look at this
  593.             TCHAR *pchLoc = StrChr(szUrlT, TEXT('#'));
  594.             if (pchLoc)
  595.                 *pchLoc = TEXT('');
  596.         
  597.             fCached = GetUrlCacheEntryInfoEx(szUrlT, NULL, NULL, NULL, NULL, NULL, 0);
  598.             if(fCached)
  599.             {
  600.                 return TRUE;
  601.             }
  602.             else
  603.             {
  604.                 TCHAR szCanonicalizedUrlT[INTERNET_MAX_URL_LENGTH];
  605.                 DWORD dwLen = INTERNET_MAX_URL_LENGTH;
  606.                 InternetCanonicalizeUrl(szUrlT, szCanonicalizedUrlT, &dwLen, 0);
  607.                 fCached = GetUrlCacheEntryInfoEx(szCanonicalizedUrlT, NULL, NULL, NULL, NULL, NULL, 0);
  608.                 if(fCached)
  609.                     return TRUE;
  610.             }
  611.         }
  612.     }
  613.     
  614.     return FALSE;
  615. }
  616. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  617. //
  618. // *** CDFIDL_GetAttributes ***
  619. //
  620. //
  621. // Description:
  622. //     Returns the attributes item of the given cdf item id list.
  623. //
  624. // Parameters:
  625. //     [In]  pIXMLElementCollectionparent - The containing element collection.
  626. //     [In]  pcdfidl                      - A pointer to the cdf item id list.
  627. //     [In]  fAttributesFilter            - Determines which flags to bother 
  628. //                                          looking at
  629. //
  630. // Return:
  631. //     The attributes of the given id list.
  632. //     Zero on failure.  Note: Zero is a valid attribute value.
  633. //
  634. // Comments:
  635. //     The attribute flags returned by this function can be used directly as a
  636. //     return value by IShellFolder->GetAttributesOf().
  637. //
  638. ////////////////////////////////////////////////////////////////////////////////
  639. ULONG
  640. CDFIDL_GetAttributes(
  641.     IXMLElementCollection* pIXMLElementCollectionParent,
  642.     PCDFITEMIDLIST pcdfidl,
  643.     ULONG fAttributesFilter
  644. )
  645. {
  646.     ASSERT(pIXMLElementCollectionParent);
  647.     ASSERT(CDFIDL_IsValid(pcdfidl));
  648.     ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  649.     //
  650.     // REVIEW:  Need to properly determine shell attributes of cdf items.
  651.     //
  652.     ULONG uRet;
  653.     if (CDFIDL_IsFolderId(&pcdfidl->mkid))
  654.     {
  655.         uRet = SFGAO_FOLDER | SFGAO_CANLINK;
  656.         //  If we weren't asked for HASSUBFOLDER don't bother looking for it
  657.         //  This should be a win in non tree views (ie. std open mode)
  658.         if ((SFGAO_HASSUBFOLDER & fAttributesFilter) &&
  659.             pIXMLElementCollectionParent && 
  660.             XML_ChildContainsFolder(pIXMLElementCollectionParent,
  661.                                     CDFIDL_GetIndex(pcdfidl)))
  662.         {
  663.             uRet |= SFGAO_HASSUBFOLDER;
  664.         }
  665.     }
  666.     else
  667.     {
  668.         uRet = SFGAO_CANLINK;
  669.         //  If we weren't asked for NEWCONTENT don't bother looking for it
  670.         //  This will be a win in non channel pane views.
  671.         //  BUGBUG: Can't test for SFGAO_NEWCONTENT since shell is never
  672.         //  expressing interest in it!
  673.         if (/*(SFGAO_NEWCONTENT & fAttributeFilter) && */
  674.             CDFIDL_IsUnreadURL(CDFIDL_GetURL(pcdfidl)))
  675.         {
  676.             uRet |= SFGAO_NEWCONTENT;
  677.         }
  678.     }
  679.     return uRet;
  680. }
  681. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  682. //
  683. // *** CDFIDL_Compare ***
  684. //
  685. //
  686. // Description:
  687. //     Compares two cdf item id lists
  688. //
  689. // Parameters:
  690. //     [In]  pcdfidl1 - A pointer to the first item id list to compare.
  691. //     [In]  pcdfidl2 - A pointer to the second item id list to compare.
  692. //
  693. // Return:
  694. //     -1 if item 1 comes before item 2.
  695. //      0 if the items are equal.
  696. //      1 if item 2 comes before item 1.
  697. //
  698. // Comments:
  699. //      Sort Order:
  700. //          1) Use the CompareId result of the first items in the lists.
  701. //          2) If 1) returns 0.  Compare the next two items in the lists.
  702. //          3) If both list are empty. They are equal.
  703. //          4) The shorter id list comes first.
  704. //
  705. ////////////////////////////////////////////////////////////////////////////////
  706. SHORT
  707. CDFIDL_Compare(
  708.     PCDFITEMIDLIST pcdfidl1,
  709.     PCDFITEMIDLIST pcdfidl2
  710. )
  711. {
  712.     ASSERT(CDFIDL_IsValid(pcdfidl1));
  713.     ASSERT(CDFIDL_IsValid(pcdfidl2));
  714.     SHORT sRet;
  715.     sRet = CDFIDL_CompareId(&pcdfidl1->mkid, &pcdfidl2->mkid);
  716.     if (0 == sRet)
  717.     {
  718.         if (!ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
  719.         {
  720.             sRet = CDFIDL_Compare((PCDFITEMIDLIST)_ILNext(pcdfidl1), 
  721.                                   (PCDFITEMIDLIST)_ILNext(pcdfidl2));
  722.         }
  723.         else if(!ILIsEmpty(_ILNext(pcdfidl1)) && ILIsEmpty(_ILNext(pcdfidl2)))
  724.         {
  725.             sRet = 1;
  726.         }
  727.         else if (ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
  728.         {
  729.             sRet = -1;
  730.         }
  731.     }
  732.     return sRet;
  733. }
  734. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  735. //
  736. // *** CDFIDL_CompareId ***
  737. //
  738. //
  739. // Description:
  740. //     Compares two item cdf item ids.
  741. //
  742. // Parameters:
  743. //     [In]  pcdfid1 - A pointer to the first item id to compare.
  744. //     [In]  pcdfid2 - A pointer to the second item id to compare.
  745. //
  746. // Return:
  747. //     -1 if item 1 comes before item 2.
  748. //      0 if the items are the same.
  749. //      1 if item 2 comes before item 1.
  750. //
  751. // Comments:
  752. //     Sort Order:
  753. //         1) CDF_FolderLink (Essentially an URL for the current folder). These
  754. //            have an index of -1.
  755. //         2) Everything else accoring to its order in the CDF.  These have
  756. //            a zero-based index.
  757. //         3) Non CDF items  (should't have any).
  758. //
  759. ////////////////////////////////////////////////////////////////////////////////
  760. SHORT
  761. CDFIDL_CompareId(
  762.     PCDFITEMID pcdfid1,
  763.     PCDFITEMID pcdfid2
  764. )
  765. {
  766.     ASSERT(CDFIDL_IsValidId(pcdfid1));
  767.     ASSERT(CDFIDL_IsValidId(pcdfid2));
  768.     SHORT sRet;
  769.     if (pcdfid1->nIndex < pcdfid2->nIndex)
  770.     {
  771.         sRet = -1;
  772.     }
  773.     else if (pcdfid1->nIndex > pcdfid2->nIndex)
  774.     {
  775.         sRet = 1;
  776.     }
  777.     else
  778.     {
  779.         sRet =  (short) CompareString(LOCALE_USER_DEFAULT, 0, CDFIDL_GetNameId(pcdfid1),
  780.                                       -1, CDFIDL_GetNameId(pcdfid2), -1);
  781.         //
  782.         // Note: CompareString returns 1 if S1 comes before S2, 2 if S1 is equal
  783.         // to S2, 3 if S2 comes before S1 and 0 on error.
  784.         //
  785.         sRet = sRet ? sRet - 2 : 0;
  786.         if (0 == sRet)
  787.         {
  788.             //
  789.             // If the URLs aren't equal just pick one at random.
  790.             //
  791.             sRet = !StrEql(CDFIDL_GetURLId(pcdfid1), CDFIDL_GetURLId(pcdfid2));
  792.             
  793.             ASSERT((pcdfid1->cb == pcdfid2->cb) || 0 != sRet);
  794.             ASSERT((pcdfid1->cdfItemType == pcdfid1->cdfItemType) || 0 != sRet);
  795.         }
  796.     }
  797.     return sRet;
  798. }
  799. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  800. //
  801. // *** CDFIDL_IsValid ***
  802. //
  803. //
  804. // Description:
  805. //     Determines if the given pcdfidl is valid.
  806. //
  807. // Parameters:
  808. //     pcdfid - A pointer to the cdf id to check.
  809. //
  810. // Return:
  811. //     TRUE if the id is a cdf id.
  812. //     FALSE otherwise.
  813. //
  814. // Comments:
  815. //     An empty list is not valid.
  816. //
  817. ////////////////////////////////////////////////////////////////////////////////
  818. BOOL
  819. CDFIDL_IsValid(
  820.     PCDFITEMIDLIST pcdfidl
  821. )
  822. {
  823.     BOOL bRet;
  824.     if (pcdfidl && (pcdfidl->mkid.cb > 0))
  825.     {
  826.         bRet = TRUE;
  827.         while (pcdfidl->mkid.cb && bRet)
  828.         {
  829.             bRet = CDFIDL_IsValidId(&pcdfidl->mkid);
  830.             pcdfidl = (PCDFITEMIDLIST)_ILNext((LPITEMIDLIST)pcdfidl);
  831.         }
  832.     }
  833.     else
  834.     {
  835.         bRet = FALSE;
  836.     }
  837.     return bRet;
  838. }
  839. //
  840. // Inline helper functions.
  841. //
  842. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  843. //
  844. // *** CDFIDL_IsValidId ***
  845. //
  846. //
  847. // Description:
  848. //     Inline function that returns TRUE if the given id is a pointer to a cdf
  849. //     item id.
  850. //
  851. // Parameters:
  852. //     pcdfid - A pointer to the cdf id to check.
  853. //
  854. // Return:
  855. //     TRUE if the id is a cdf id.
  856. //     FALSE otherwise.
  857. //
  858. // Comments:
  859. //     This function is not completely safe.  If the first word pointed to 
  860. //     is large but the memory block pointed to is smaller than a 8 bytes an
  861. //     access violation will occur.  Also, if the first word is large enough and
  862. //     the second DWORD is equal to CDFITEM_ID but the item isn't a cdf id a
  863. //     false positive will occur.
  864. //
  865. ////////////////////////////////////////////////////////////////////////////////
  866. BOOL
  867. CDFIDL_IsValidId(
  868.     PCDFITEMID pcdfid
  869. )
  870. {
  871.     ASSERT(pcdfid);
  872.     return (pcdfid->cb >= (sizeof(CDFITEMID) +  sizeof(TCHAR)) && 
  873.             pcdfid->dwId == CDFITEMID_ID                       &&
  874.             CDFIDL_IsValidSize(pcdfid)                         &&
  875.             CDFIDL_IsValidType(pcdfid)                         &&
  876.             CDFIDL_IsValidIndex(pcdfid)                        &&
  877.             CDFIDL_IsValidStrings(pcdfid)                         );
  878. }
  879. inline
  880. BOOL
  881. CDFIDL_IsValidSize(
  882.     PCDFITEMID pcdfid
  883. )
  884. {
  885.     int cbName = (StrLen(CDFIDL_GetNameId(pcdfid)) + 1) * 
  886.                  sizeof(TCHAR);
  887.     int cbURL  = (StrLen(CDFIDL_GetURLId(pcdfid)) + 1) *
  888.                  sizeof(TCHAR);
  889. #ifndef UNIX
  890.     return (sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL == pcdfid->cb);
  891. #else
  892.     return ((ALIGN4(sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL)) == pcdfid->cb);
  893. #endif /* !UNIX */
  894. }
  895. inline
  896. BOOL
  897. CDFIDL_IsValidType(
  898.     PCDFITEMID pcdfid
  899. )
  900. {
  901.     return ((CDF_Folder     == (CDFITEMTYPE)pcdfid->cdfItemType) ||
  902.             (CDF_Link       == (CDFITEMTYPE)pcdfid->cdfItemType) ||
  903.             (CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType)   );
  904. }
  905. inline
  906. BOOL
  907. CDFIDL_IsValidIndex(
  908.     PCDFITEMID pcdfid
  909. )
  910. {
  911.     return (  pcdfid->nIndex >= 0
  912.             || 
  913.               (INDEX_CHANNEL_LINK == pcdfid->nIndex &&
  914.               CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType));
  915. }
  916. inline
  917. BOOL
  918. CDFIDL_IsValidStrings(
  919.     PCDFITEMID pcdfid
  920. )
  921. {
  922.     //
  923.     // REVIEW: Validate pidl strings.
  924.     //
  925.     return TRUE;
  926. }
  927. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  928. //
  929. // *** CDFIDL_IsFolder ***
  930. //
  931. //
  932. // Description:
  933. //     Inline function that returns TRUE if the given cdfidl is a folder as far
  934. //     as the shel is concerned.
  935. //
  936. // Parameters:
  937. //     pcdfidl - The cdf item id list to check.
  938. //
  939. // Return:
  940. //     TRUE if the cdf item id list is a folder.
  941. //
  942. // Comments:
  943. //
  944. //
  945. ////////////////////////////////////////////////////////////////////////////////
  946. BOOL
  947. CDFIDL_IsFolder(
  948.     PCDFITEMIDLIST pcdfidl
  949. )
  950. {
  951.     ASSERT(CDFIDL_IsValid(pcdfidl));
  952.     pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
  953.     return CDFIDL_IsFolderId(&pcdfidl->mkid);
  954. }
  955. BOOL
  956. CDFIDL_IsFolderId(
  957.     PCDFITEMID pcdfid
  958. )
  959. {
  960.     ASSERT(CDFIDL_IsValidId(pcdfid));
  961.     return (CDF_Folder == (CDFITEMTYPE)pcdfid->cdfItemType);
  962. }
  963. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\
  964. //
  965. // *** CDFIDL_NonCdfGetName ***
  966. //
  967. //
  968. // Description:
  969. //     Gets the name stored in the given non-cdf item id list.
  970. //
  971. // Parameters:
  972. //     [In]  pcdfidl - A pointer to a cdf item id list.  Can be NULL.
  973. //     [Out] pName - A pointer to a STRRET structure.  STRRET has the following
  974. //                   structure:
  975. //                       UINT uType             - STRRET_CSTR, _OFFSET or _WSTR
  976. //                       union {
  977. //                           LPWSTR pOleStr;
  978. //                           UINT   uOffset;
  979. //                           char   cStr[MAX_PATH];
  980. //                       }
  981. //
  982. // Return:
  983. //     S_OK on success.  E_Fail otherwise.
  984. //
  985. // Comments:
  986. //     This function returns the name as a cString in the STRRET structure.
  987. //
  988. //     ILGetDisplayName returns the full path.  This function strips out the
  989. //     filename sans extension.
  990. //
  991. ////////////////////////////////////////////////////////////////////////////////
  992. #if 0
  993. HRESULT
  994. CDFIDL_NonCdfGetDisplayName(
  995.     LPCITEMIDLIST pidl,
  996.     LPSTRRET pName
  997. )
  998. {
  999.     ASSERT(pName);
  1000.     HRESULT hr;
  1001.     //
  1002.     // REVIEW:  Hack to get the name of a shell pidl.
  1003.     //
  1004.     if (ILGetDisplayName(pidl, pName->cStr))
  1005.     {
  1006.         TCHAR* p1 = pName->cStr;
  1007.         TCHAR* p2 = p1;
  1008.         while (*p1++);                          // Go to the end. 
  1009.         while (*--p1 != TEXT('\'));            // Back to last backslash.
  1010.         while (TEXT('.') != (*p2++ = *++p1));   // Copy the name.
  1011.         *--p2 = TEXT('');                     // NULL terminate.
  1012.         pName->uType = STRRET_CSTR;
  1013.         hr = S_OK;
  1014.     }
  1015.     else
  1016.     {
  1017.         hr = E_FAIL;
  1018.     }
  1019.     return hr;
  1020. }
  1021. #endif