Leaked source code of windows server 2003
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.

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