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.

1274 lines
40 KiB

  1. #include <cache.hxx>
  2. #include "401imprt.hxx"
  3. #include "401inc.hxx"
  4. #ifdef UNICODE
  5. #error "401imprt.cxx doesn't support UNICODE compilation."
  6. #endif
  7. #define PRE5_CACHE_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache"
  8. #define IE401_HIST_ROOT "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Extensible Cache"
  9. //IE401_PER_USER_CACHE_LOCATION is in HKCU
  10. #define IE401_PER_USER_CACHE_LOCATION \
  11. "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
  12. #define IE401_PER_USER_CACHE_KEY "Cache"
  13. //IE401_ONE_USER_CACHE_LOCATION is in HKLM
  14. #define IE401_ONE_USER_CACHE_LOCATION \
  15. "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Content"
  16. #define IE401_ONE_USER_CACHE_KEY "CachePath"
  17. #define MSHIST_DIR_SZ "MSHIST011998020119980225"##FILENAME_SEPARATOR_STR
  18. #define MSHIST_KEY_SZ "MSHIST011998020119980225"
  19. #define MSHIST_SZ "MSHIST"
  20. #define MSHIST_PREFIX_SZ ":1998010119980101:"
  21. #define VISITED_PREFIX_SZ "Visited:"
  22. #define INDEX_DAT_SZ "index.dat"
  23. #define CACHE_LIMIT_SZ "CacheLimit"
  24. #define CACHE_OPTIONS_SZ "CacheOptions"
  25. #define CACHE_PATH_SZ "CachePath"
  26. #define CACHE_PREFIX_SZ "CachePrefix"
  27. //----------------------------------------
  28. //The following tructures and macro, _HISTDATA_V001 and SET_HISTORY_FLAG()
  29. //allow us to notify members of the Visited: cache that they are to be
  30. //listed in the History view. The structure was cut'n'pasted from
  31. //shdocvw\urlhist.cpp and any changes made to the original need
  32. //to be reflected here as well.
  33. #define PIDISF_HISTORY 0x10000000
  34. #define PID_INTSITE_TITLE 16
  35. //** BUGBUG
  36. struct _HISTDATA_V001
  37. {
  38. UINT cbSize : 16; // size of this header
  39. UINT cbVer : 16; // version
  40. DWORD dwFlags; // PID_INTSITE_FLAGS (PIDISF_ flags)
  41. DWORD dwWatch; // PID_INTSITE_WATCH (PIDISM_ flags)
  42. DWORD dwVisits; // PID_INTSITE_VISITCOUNT
  43. };
  44. #define SET_HISTORY_FLAG(lpHeaderInfo) \
  45. (((_HISTDATA_V001*)lpHeaderInfo)->dwFlags |= PIDISF_HISTORY)
  46. //
  47. // Right after HISTDATA (always at cbSize), we have optional (typically
  48. // variable length) data which has following data structure. It may have
  49. // more than one but always has a null-terimiator (cbExtra == 0).
  50. //
  51. //HISTEXTRA is also cut'n'pasted from shdocvw.
  52. struct HISTEXTRA
  53. {
  54. UINT cbExtra : 16;
  55. UINT idExtra : 8; // PID_INTSITE_*
  56. UINT vtExtra : 8; // VT_*
  57. BYTE abExtra[1]; // abExtra[cbExtra-4];
  58. };
  59. // HISTEXTRA without the abExtra ==> (sizeof(HISTEXTRA) - sizeof(BYTE))
  60. #define HISTEXTRA_HEAD_SIZE 4
  61. //-----------------------------------------
  62. BOOL IsPerUserCache();
  63. namespace ie401
  64. {
  65. //--------------------------------------------------------
  66. // The code that enumerates through a IE401 index.dat file is provided
  67. //by IE401IndexFile. Classes derived from IE401IndexFile override HandleHashElement
  68. //to handle each HASH_ELEMENT as the index file is enumerated.
  69. // IE401IndexFile::Import401Url is provided to import URLs without overwriting
  70. //already existing entries.
  71. class IE401IndexFile
  72. {
  73. public:
  74. // EnumHashValues enumerates hash tables, calling HandleHashElement for each.
  75. virtual BOOL EnumHashValues();
  76. protected:
  77. IE401IndexFile( LPCSTR szFilename);
  78. IE401IndexFile();
  79. virtual ~IE401IndexFile();
  80. // given by derived class
  81. virtual BOOL HandleHashElement( ie401::HASH_ITEM* pEntry) = 0;
  82. // probably useful to many, default URL import. Not for REDIRs.
  83. virtual BOOL Import401Url( ie401::URL_FILEMAP_ENTRY* pEntry);
  84. BYTE* m_pBuf;
  85. };
  86. //--------------------------------------------------------
  87. // IE401Visited overrides HandleHashElement to import all URLs,
  88. //translating CEI to its current format.
  89. // All the dependencies on the change in CEI format are
  90. //contained in UpgradeHeaderData.
  91. class IE401Visited : public IE401IndexFile
  92. {
  93. public:
  94. IE401Visited( LPCSTR szFilename);
  95. protected:
  96. IE401Visited() {}
  97. virtual BOOL HandleHashElement( ie401::HASH_ITEM* pEntry);
  98. virtual BOOL Import401UrlTranslatingCEI( ie401::URL_FILEMAP_ENTRY* pEntry);
  99. virtual BOOL UpgradeHeaderData(
  100. IN const CHAR* pIn,
  101. OUT CHAR* pOut,
  102. IN OUT DWORD* pcbOutSize);
  103. };
  104. //--------------------------------------------------------
  105. // IE401History overrides HandleHashElement to import all URLs
  106. //and mark them in the Visited: container.
  107. // All the dependencies on the format for the Visited mark
  108. //are contained in MarkUrlAsVisited.
  109. //(colliding items are not imported and associated data
  110. //files are not copied.)
  111. class IE401History : public IE401IndexFile
  112. {
  113. public:
  114. IE401History( LPCSTR szFilename);
  115. protected:
  116. IE401History() {}
  117. virtual BOOL HandleHashElement( ie401::HASH_ITEM* pEntry);
  118. static BOOL MarkUrlAsVisited( LPSTR szUrlName);
  119. };
  120. //--------------------------------------------------------
  121. // pre-declaration included so IE401Redirects can be declared as a friend
  122. class IE401Redirects;
  123. // IE401Content overrides HandleHashElement to import all URLs
  124. //and also copy associated data files.
  125. //(colliding items are not imported)
  126. class IE401Content : public IE401IndexFile
  127. {
  128. public:
  129. IE401Content( LPCSTR szFilename);
  130. friend IE401Redirects;
  131. protected:
  132. IE401Content() {}
  133. virtual BOOL HandleHashElement( ie401::HASH_ITEM* pEntry);
  134. // Extends the default to import files
  135. BOOL Import401UrlWithFile( ie401::URL_FILEMAP_ENTRY* pEntry);
  136. CHAR m_szRootPath[MAX_PATH];
  137. DWORD m_cbRootPathLength;
  138. DWORD m_nDirs;
  139. CHAR m_szDir[DEFAULT_MAX_DIRS][DIR_NAME_SIZE + 1];
  140. };
  141. //--------------------------------------------------------
  142. // IE401Redirects override HandleHashElement to import redirects.
  143. // This should be done to an index file after IE401Content has
  144. //enumerated over it, so the constructor takes a IE401Content object
  145. //rather than a filename. This IE401Content represents a process
  146. //that is finished, so its functionality is taken away.
  147. // Importing redirects is done with a separate enumerator than
  148. //IE401Content since its less work then retooling IE401IndexFile
  149. //to enumerate an arbitrary number of times.
  150. class IE401Redirects : public IE401IndexFile
  151. {
  152. public:
  153. IE401Redirects( IE401Content* pContent);
  154. protected:
  155. IE401Redirects() {}
  156. virtual BOOL HandleHashElement( ie401::HASH_ITEM* pEntry);
  157. BOOL Import401Redirect( ie401::REDIR_FILEMAP_ENTRY* pEntry);
  158. };
  159. //******************************************************
  160. //
  161. // class OutputStream - utility
  162. //
  163. // outputs data to a buffer, tracking buffer used
  164. //and checking for overflow.
  165. class OutputStream
  166. {
  167. public:
  168. OutputStream( VOID* pBuffer, DWORD cbBufferSize)
  169. : m_pBuffer( (BYTE*)pBuffer), m_cbBufferSize( cbBufferSize), m_cbPosition(0)
  170. {
  171. }
  172. BOOL Memcpy( const VOID* pSource, DWORD cbSize)
  173. {
  174. if( cbSize + m_cbPosition <= m_cbBufferSize)
  175. {
  176. memcpy(&m_pBuffer[m_cbPosition], (BYTE*)pSource, cbSize);
  177. m_cbPosition += cbSize;
  178. return TRUE;
  179. }
  180. else
  181. return FALSE;
  182. }
  183. BOOL CopyAnsiToUnicode( const CHAR* pSource, DWORD cSize)
  184. {
  185. if( m_cbPosition + cSize * sizeof(WCHAR) / sizeof(CHAR)
  186. <= m_cbBufferSize)
  187. {
  188. DWORD dwSizeCopied;
  189. // the semantics of MultiByteToWideChar is different
  190. //if you give it a zero-length buffer.
  191. INET_ASSERT( m_cbBufferSize - m_cbPosition != 0);
  192. dwSizeCopied =
  193. MultiByteToWideChar( CP_ACP, 0, pSource, cSize,
  194. (WCHAR*)&m_pBuffer[m_cbPosition],
  195. (m_cbBufferSize - m_cbPosition) / sizeof(WCHAR));
  196. if( dwSizeCopied != 0)
  197. {
  198. m_cbPosition += dwSizeCopied * sizeof(WCHAR);
  199. return TRUE;
  200. }
  201. else
  202. return FALSE;
  203. }
  204. else
  205. return FALSE;
  206. }
  207. DWORD GetFinalLength()
  208. {
  209. return m_cbPosition;
  210. }
  211. private:
  212. BYTE* m_pBuffer;
  213. DWORD m_cbBufferSize, m_cbPosition;
  214. };
  215. //*************************************************************************
  216. //
  217. // IE401IndexFile
  218. //
  219. // On creation, load the contents of the given file into memory.
  220. IE401IndexFile::IE401IndexFile( LPCSTR szFilename)
  221. {
  222. m_pBuf = NULL;
  223. // load the file into the buffer
  224. DWORD cbBufSize;
  225. if( ReadFileToBuffer( szFilename, &m_pBuf, &cbBufSize) == FALSE)
  226. {
  227. if( m_pBuf != NULL)
  228. {
  229. delete [] m_pBuf;
  230. m_pBuf = NULL;
  231. }
  232. }
  233. else if( cbBufSize < sizeof(_MEMMAP_HEADER_SMALL)
  234. || strcmp((LPSTR) m_pBuf, "Client UrlCache MMF Ver 4.7"))
  235. {
  236. // If this file doesn't even have a memmap header, forget it.
  237. // Now all derived classes can assume they have at least a memmap header
  238. //if m_pBuf != NULL
  239. delete [] m_pBuf;
  240. m_pBuf = NULL;
  241. }
  242. }
  243. // Default constructor made protected to prevent direct creation
  244. IE401IndexFile::IE401IndexFile()
  245. : m_pBuf(NULL)
  246. {
  247. }
  248. IE401IndexFile::~IE401IndexFile()
  249. {
  250. if( m_pBuf != NULL)
  251. delete [] m_pBuf;
  252. }
  253. //---------------------------------------------------
  254. //
  255. // Enumerate through the entries in an ie401 index
  256. //file, calling HandleHashElement on each entry.
  257. BOOL IE401IndexFile::EnumHashValues()
  258. {
  259. BOOL retVal = FALSE;
  260. if( m_pBuf == NULL)
  261. goto doneEnumHashValues;
  262. HASH_FILEMAP_ENTRY* pTable;
  263. HASH_ITEM* pItem;
  264. // pTable is located by an offset which is located at dwHashTableOffset
  265. pTable = (HASH_FILEMAP_ENTRY*)(m_pBuf + (((_MEMMAP_HEADER_SMALL*)m_pBuf)->dwHashTableOffset));
  266. // The first location in the table follows immediately after the HASH_FILEMAP_ENTRY pTable
  267. pItem = (HASH_ITEM*)(pTable + 1);
  268. if (pTable->dwSig != SIG_HASH)
  269. goto doneEnumHashValues;
  270. do // Scan the list of tables.
  271. {
  272. // Scan the current table.
  273. for (; (LPBYTE)pItem < (LPBYTE)pTable + BYTES_PER_TABLE; pItem++)
  274. {
  275. // call virtual entry handler
  276. if( HandleHashElement( pItem) == FALSE)
  277. goto doneEnumHashValues;
  278. }
  279. // Follow the link to the next table.
  280. if (!pTable->dwNext)
  281. {
  282. pTable = NULL;
  283. }
  284. else
  285. {
  286. // Validate the table signature and sequence number.
  287. DWORD nBlock;
  288. nBlock = pTable->nBlock;
  289. pTable = (HASH_FILEMAP_ENTRY*) (m_pBuf + pTable->dwNext);
  290. if (pTable->dwSig != SIG_HASH || pTable->nBlock != nBlock + 1)
  291. goto doneEnumHashValues;
  292. // Set pointer to first location in table.
  293. pItem = (HASH_ITEM*) (pTable + 1);
  294. }
  295. }
  296. while (pTable);
  297. retVal = TRUE;
  298. doneEnumHashValues:
  299. return retVal;
  300. }
  301. //---------------------------------------------------
  302. //
  303. // Imports an URL entry without overwriting existing
  304. //cache entries or copying any associated data files.
  305. BOOL IE401IndexFile::Import401Url( ie401::URL_FILEMAP_ENTRY* pEntry)
  306. {
  307. BOOL retVal = FALSE;
  308. // don't import Url if it is already in the buffer
  309. if( GetUrlCacheEntryInfo( (LPSTR)((BYTE*)pEntry + pEntry->UrlNameOffset), NULL, 0) == TRUE
  310. || GetLastError() != ERROR_FILE_NOT_FOUND)
  311. {
  312. goto doneImport401Url;
  313. }
  314. if( pEntry->FileSize != 0)
  315. {
  316. INET_ASSERT(0); // Are you importing URL cache entries with external data?
  317. goto doneImport401Url;
  318. }
  319. if( !CommitUrlCacheEntry(
  320. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  321. NULL,
  322. *LONGLONG_TO_FILETIME(&pEntry->ExpireTime),
  323. *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime),
  324. pEntry->CacheEntryType,
  325. pEntry->HeaderInfoOffset != NULL ?
  326. (BYTE*)((BYTE*)pEntry + pEntry->HeaderInfoOffset) : NULL,
  327. pEntry->HeaderInfoSize,
  328. pEntry->FileExtensionOffset != 0 ?
  329. (LPCSTR)((BYTE*)pEntry + pEntry->FileExtensionOffset) : NULL,
  330. NULL))
  331. goto doneImport401Url;
  332. CACHE_ENTRY_INFO cei;
  333. cei.dwStructSize = sizeof(cei);
  334. cei.LastAccessTime = *LONGLONG_TO_FILETIME(&pEntry->LastAccessedTime);
  335. cei.dwHitRate = pEntry->NumAccessed;
  336. cei.ExpireTime = *LONGLONG_TO_FILETIME(&pEntry->ExpireTime);
  337. cei.LastModifiedTime = *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime);
  338. if( !SetUrlCacheEntryInfo(
  339. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  340. &cei,
  341. CACHE_ENTRY_ACCTIME_FC | CACHE_ENTRY_HITRATE_FC
  342. | CACHE_ENTRY_EXPTIME_FC | CACHE_ENTRY_MODTIME_FC))
  343. goto doneImport401Url;
  344. retVal = TRUE;
  345. doneImport401Url:
  346. return retVal;
  347. }
  348. //************************************************************************8
  349. //
  350. // IE401Visited : public IE401IndexFile
  351. //
  352. IE401Visited::IE401Visited( LPCSTR szFilename) : IE401IndexFile( szFilename)
  353. {
  354. }
  355. // imports only URLs using Import401Url- nothing special
  356. BOOL IE401Visited::HandleHashElement( ie401::HASH_ITEM* pEntry)
  357. {
  358. // No reserved bits should be set.
  359. INET_ASSERT (!(pEntry->dwHash & HASH_BIT_RESERVED));
  360. if( !(pEntry->dwHash & HASH_BIT_NOTURL)
  361. && ((ie401::FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset))->dwSig == SIG_URL)
  362. {
  363. Import401UrlTranslatingCEI( (ie401::URL_FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset));
  364. }
  365. // after wrapping above in try-catch block, return FALSE on unhandled exception.
  366. return TRUE;
  367. }
  368. //----------------------------------------
  369. //
  370. // IE401Visited::Import401UrlTranslatingCEI
  371. //
  372. // Very much like Import401Url except it makes
  373. //a call to UpgradeHeaderData before calling CommitCacheEntry.
  374. BOOL IE401Visited::Import401UrlTranslatingCEI( ie401::URL_FILEMAP_ENTRY* pEntry)
  375. {
  376. BOOL retVal = FALSE;
  377. // don't import Url if it is already in the buffer
  378. if( GetUrlCacheEntryInfo( (LPSTR)((BYTE*)pEntry + pEntry->UrlNameOffset), NULL, 0) == TRUE
  379. || GetLastError() != ERROR_FILE_NOT_FOUND)
  380. {
  381. goto doneImport401UrlTranslatingCEI;
  382. }
  383. if( pEntry->FileSize != 0)
  384. {
  385. INET_ASSERT(0); // Are you importing URL cache entries with external data?
  386. goto doneImport401UrlTranslatingCEI;
  387. }
  388. DWORD cbHeaderBufSize;
  389. //BUGBUG: Does shdocvw still obey MAX_CACHE_ENTRY_INFO_SIZE
  390. //in the version being imported?
  391. CHAR szHeaderBuf[ MAX_CACHE_ENTRY_INFO_SIZE];
  392. cbHeaderBufSize = MAX_CACHE_ENTRY_INFO_SIZE;
  393. if( pEntry->HeaderInfoOffset != 0)
  394. {
  395. if( UpgradeHeaderData( (CHAR*)((BYTE*)pEntry + pEntry->HeaderInfoOffset),
  396. szHeaderBuf, &cbHeaderBufSize) != TRUE)
  397. {
  398. goto doneImport401UrlTranslatingCEI;
  399. }
  400. }
  401. else
  402. cbHeaderBufSize = 0;
  403. if( !CommitUrlCacheEntry(
  404. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  405. NULL,
  406. *LONGLONG_TO_FILETIME(&pEntry->ExpireTime),
  407. *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime),
  408. pEntry->CacheEntryType,
  409. cbHeaderBufSize != 0 ?
  410. (BYTE*)szHeaderBuf : NULL,
  411. cbHeaderBufSize,
  412. pEntry->FileExtensionOffset != 0 ?
  413. ((CHAR*)pEntry + pEntry->FileExtensionOffset) : NULL,
  414. NULL))
  415. goto doneImport401UrlTranslatingCEI;
  416. CACHE_ENTRY_INFO cei;
  417. cei.dwStructSize = sizeof(cei);
  418. cei.LastAccessTime = *LONGLONG_TO_FILETIME(&pEntry->LastAccessedTime);
  419. cei.dwHitRate = pEntry->NumAccessed;
  420. cei.ExpireTime = *LONGLONG_TO_FILETIME(&pEntry->ExpireTime);
  421. cei.LastModifiedTime = *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime);
  422. if( !SetUrlCacheEntryInfo(
  423. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  424. &cei,
  425. CACHE_ENTRY_ACCTIME_FC | CACHE_ENTRY_HITRATE_FC
  426. | CACHE_ENTRY_EXPTIME_FC | CACHE_ENTRY_MODTIME_FC))
  427. goto doneImport401UrlTranslatingCEI;
  428. retVal = TRUE;
  429. doneImport401UrlTranslatingCEI:
  430. return retVal;
  431. }
  432. BOOL IE401Visited::UpgradeHeaderData(
  433. IN const CHAR* pIn,
  434. OUT CHAR* pOut,
  435. IN OUT DWORD* pcbOutSize)
  436. {
  437. BOOL retVal = FALSE;
  438. OutputStream op( pOut, *pcbOutSize);
  439. // The header info struct contains a HISTDATA followed by
  440. //a list of HISTEXTRAs.. Their sizes can vary but they should
  441. //be adjacent. The last HISTEXTRA has a cbExtra of 0 and a sizeof(UINT).
  442. // When we import a HISTEXTRA (idExtra = PID_INTSITE_TITLE) then
  443. //we must convert the attached string from ANSI to Unicode
  444. HISTEXTRA* pExtra = NULL;
  445. //first copy the HISTDATA
  446. if( op.Memcpy( pIn, ((_HISTDATA_V001*)pIn)->cbSize) == FALSE)
  447. goto doneUpgradeCEIData;
  448. for(pExtra = (HISTEXTRA*) (pIn + ((_HISTDATA_V001*)pIn)->cbSize);
  449. pExtra->cbExtra != 0;
  450. pExtra = (HISTEXTRA*)((BYTE*)pExtra + pExtra->cbExtra))
  451. {
  452. if( pExtra->idExtra != PID_INTSITE_TITLE)
  453. {
  454. if( op.Memcpy( pExtra, pExtra->cbExtra) == FALSE)
  455. goto doneUpgradeCEIData;
  456. }
  457. else
  458. {
  459. HISTEXTRA* pNew = (HISTEXTRA*)((BYTE*)pOut + op.GetFinalLength());
  460. // copy the HISTEXTRA head
  461. INET_ASSERT( pExtra->cbExtra >= HISTEXTRA_HEAD_SIZE);
  462. if( op.Memcpy( pExtra, HISTEXTRA_HEAD_SIZE) == FALSE)
  463. goto doneUpgradeCEIData;
  464. if( op.CopyAnsiToUnicode( (CHAR*)&(pExtra->abExtra),
  465. pExtra->cbExtra - HISTEXTRA_HEAD_SIZE)
  466. == FALSE)
  467. goto doneUpgradeCEIData;
  468. pNew->vtExtra = VT_LPWSTR;
  469. // cbExtra(size) is the change in position of the output stream.
  470. pNew->cbExtra = ((BYTE*)pOut + op.GetFinalLength()) - (BYTE*)pNew;
  471. }
  472. }
  473. // the final member in the list is just a DWORD, value == 0.
  474. // determined from assertions in Urlhist.cpp:
  475. //ASSERT( phext->cbExtra == 0); // terminator
  476. //ASSERT( (LPBYTE)phdNew+cbHeader == (LPBYTE)phext+SIZEOF(DWORD) );
  477. if( op.Memcpy( pExtra, sizeof(DWORD)) == FALSE)
  478. goto doneUpgradeCEIData;
  479. retVal = TRUE;
  480. doneUpgradeCEIData:
  481. if( retVal == TRUE)
  482. *pcbOutSize = op.GetFinalLength();
  483. return retVal;
  484. }
  485. //************************************************************************8
  486. //
  487. // IE401History : public IE401IndexFile
  488. //
  489. IE401History::IE401History( LPCSTR szFilename) : IE401IndexFile( szFilename)
  490. {
  491. }
  492. // imports only URLs using Import401Url then marks them
  493. //as Visited
  494. BOOL IE401History::HandleHashElement( ie401::HASH_ITEM* pEntry)
  495. {
  496. // No reserved bits should be set.
  497. INET_ASSERT (!(pEntry->dwHash & HASH_BIT_RESERVED));
  498. if( !(pEntry->dwHash & HASH_BIT_NOTURL)
  499. && ((ie401::FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset))->dwSig == SIG_URL)
  500. {
  501. ie401::URL_FILEMAP_ENTRY* pUrlToImport = (ie401::URL_FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset);
  502. if( Import401Url( pUrlToImport) == TRUE)
  503. MarkUrlAsVisited( (CHAR*)pUrlToImport + pUrlToImport->UrlNameOffset);
  504. }
  505. // after wrapping above in try-catch block, return FALSE on unhandled exception.
  506. return TRUE;
  507. }
  508. // Marks an Url given with a history prefix in the Visited container
  509. BOOL IE401History::MarkUrlAsVisited( LPSTR szUrlName)
  510. {
  511. BOOL retVal = FALSE;
  512. LPCACHE_ENTRY_INFO pCei = NULL;
  513. DWORD cbCei = 0;
  514. //I'm changing the string from "MSHIST_PREFIX_SZhttp:\\www.urlname"
  515. //to "VISITED_PREFIX_SZhttp:\\www.urlname" in order to locate/change
  516. //the cache entry.
  517. //This requires backing up the old prefix, and setting a new pointer
  518. //to the correct location to place the new prefix. Once the modified
  519. //szUrlName is used the old prefix is always restored.
  520. // backup the old prefix
  521. CHAR szBackup[sizeof(MSHIST_PREFIX_SZ)];
  522. memcpy( szBackup, szUrlName, sizeof(MSHIST_PREFIX_SZ));
  523. // Move the pointer to later in the string so that the new, smaller
  524. //prefix fits, and put the new prefix there.
  525. LPSTR szModifiedUrl = szUrlName + sizeof(MSHIST_PREFIX_SZ) - sizeof(VISITED_PREFIX_SZ);
  526. memcpy( szModifiedUrl, VISITED_PREFIX_SZ, sizeof(VISITED_PREFIX_SZ) - 1);
  527. // Get the cei
  528. if( GetUrlCacheEntryInfo( szModifiedUrl, NULL, &cbCei) == TRUE)
  529. goto doneMarkUrlAsVisited;
  530. pCei = (CACHE_ENTRY_INFO*)(new BYTE[cbCei]);
  531. if( pCei == NULL)
  532. goto doneMarkUrlAsVisited;
  533. if( GetUrlCacheEntryInfo( szModifiedUrl, pCei, &cbCei) != TRUE)
  534. goto doneMarkUrlAsVisited;
  535. if( pCei->dwHeaderInfoSize < sizeof(_HISTDATA_V001))
  536. goto doneMarkUrlAsVisited;
  537. // set the Visited flag
  538. SET_HISTORY_FLAG(pCei->lpHeaderInfo);
  539. CHAR* pStrStr;
  540. if( pCei->lpHeaderInfo != NULL
  541. && (pStrStr = StrStr( pCei->lpHeaderInfo, CACHE_CONTROL_SZ)) != NULL
  542. && (pStrStr = StrStr( pStrStr, MUST_REVALIDATE_SZ)) != NULL)
  543. {
  544. pCei->CacheEntryType |= MUST_REVALIDATE_CACHE_ENTRY;
  545. }
  546. if( CommitUrlCacheEntry( szModifiedUrl, NULL, pCei->ExpireTime,
  547. pCei->LastModifiedTime, pCei->CacheEntryType, (BYTE*)pCei->lpHeaderInfo,
  548. pCei->dwHeaderInfoSize, pCei->lpszFileExtension, NULL) != TRUE)
  549. goto doneMarkUrlAsVisited;
  550. if( SetUrlCacheEntryInfo(
  551. szModifiedUrl,
  552. pCei,
  553. CACHE_ENTRY_ACCTIME_FC | CACHE_ENTRY_HITRATE_FC | CACHE_ENTRY_EXPTIME_FC ) != TRUE)
  554. goto doneMarkUrlAsVisited;
  555. retVal = TRUE;
  556. doneMarkUrlAsVisited:
  557. memcpy( szUrlName, szBackup, sizeof(MSHIST_PREFIX_SZ));
  558. if( pCei != NULL)
  559. delete [] pCei;
  560. return retVal;
  561. }
  562. //************************************************************************8
  563. //
  564. // IE401Content : public IE401IndexFile
  565. //
  566. // on the creation of a IE401Content object, we
  567. //prepare for the enumeration of its entries by:
  568. // - identifying the subdirectories of the old cache
  569. // - register each subdirectory in the new cache
  570. // - move each subdirectory into the new cache's location
  571. IE401Content::IE401Content( LPCSTR szFilename)
  572. : IE401IndexFile( szFilename)
  573. {
  574. BOOL fConstructionSuccessful = FALSE;
  575. // make sure the index file loaded alright.
  576. if( m_pBuf == NULL)
  577. goto exitIE401Construct;
  578. // ConfigInfo is retrieved since it contains the path of the new cachefile.
  579. CACHE_CONFIG_INFO sConfigInfo;
  580. DWORD dwTemp;
  581. if( GetUrlCacheConfigInfo( &sConfigInfo,
  582. &(dwTemp = sizeof(sConfigInfo)),
  583. CACHE_CONFIG_CONTENT_PATHS_FC)
  584. == FALSE)
  585. {
  586. goto exitIE401Construct;
  587. }
  588. // get the target path for subcontainer move
  589. m_cbRootPathLength = lstrlen( sConfigInfo.CachePath);
  590. memcpy( m_szRootPath, sConfigInfo.CachePath, m_cbRootPathLength + 1);
  591. //target path example: m_szRootPath = "c:\winnt\content.ie5"
  592. // get the source path for the subcontainers from the given filename
  593. DWORD cbSourcePathLength;
  594. CHAR szSourcePath[MAX_PATH];
  595. cbSourcePathLength = lstrlen( szFilename);
  596. memcpy( szSourcePath, szFilename, cbSourcePathLength + 1);
  597. // clip off the filename so that we have just the path.
  598. while( cbSourcePathLength > 0 && szSourcePath[cbSourcePathLength] != FILENAME_SEPARATOR)
  599. {
  600. cbSourcePathLength--;
  601. }
  602. szSourcePath[ ++cbSourcePathLength] = '\0';
  603. //source path example: szSourcePath = "c:\winnt\content\"
  604. // enumerate through the subdirectories,
  605. // attempt to register that directory in the new cache
  606. // then move the old directory into the new cache.
  607. // If the directory cannot be registered or moved, then
  608. //m_szDir contains "" for that directory index.
  609. m_nDirs = ((_MEMMAP_HEADER_SMALL*)m_pBuf)->nDirCount;
  610. DWORD index;
  611. for( index = 0; index < m_nDirs; index++)
  612. {
  613. // get the name of the old subdirectory from the cache.
  614. memcpy( m_szDir[index],
  615. ((_MEMMAP_HEADER_SMALL*)m_pBuf)->DirArray[index].sDirName,
  616. DIR_NAME_SIZE);
  617. m_szDir[index][DIR_NAME_SIZE] = '\0';
  618. if( GlobalUrlContainers->CreateContentDirWithSecureName( m_szDir[index]) != TRUE)
  619. {
  620. // signal that the directory couldn't be imported and try the next.
  621. m_szDir[index][0] = '\0';
  622. continue;
  623. }
  624. // append the subcontainer names to the appropiate destination and source
  625. //paths.
  626. memcpy( m_szRootPath + m_cbRootPathLength, m_szDir[index], DIR_NAME_SIZE + 1);
  627. memcpy( szSourcePath + cbSourcePathLength, m_szDir[index], DIR_NAME_SIZE + 1);
  628. #ifndef UNIX
  629. if( MoveFile( szSourcePath, m_szRootPath) == 0)
  630. #else
  631. if (!hConstructSubDirs(m_szRootPath) ||
  632. CopyDir(szSourcePath, m_szRootPath))
  633. #endif /* UNIX */
  634. {
  635. // signal that the directory couldn't be imported and try the next.
  636. m_szDir[index][0] = '\0';
  637. continue;
  638. }
  639. }
  640. szSourcePath[ cbSourcePathLength] = '\0';
  641. m_szRootPath[ m_cbRootPathLength] = '\0';
  642. #ifndef UNIX
  643. // The old index file now is full of dead entries,
  644. //so we don't keep it around.
  645. DeleteFile( szFilename);
  646. #endif /* UNIX */
  647. fConstructionSuccessful = TRUE;
  648. exitIE401Construct:
  649. if( fConstructionSuccessful != TRUE)
  650. {
  651. if( m_pBuf != NULL)
  652. delete [] m_pBuf;
  653. m_pBuf = NULL;
  654. }
  655. }
  656. // imports only URLs using Import401Url
  657. BOOL IE401Content::HandleHashElement( ie401::HASH_ITEM* pEntry)
  658. {
  659. // No reserved bits should be set.
  660. INET_ASSERT (!(pEntry->dwHash & HASH_BIT_RESERVED));
  661. if( !(pEntry->dwHash & HASH_BIT_NOTURL)
  662. && ((ie401::FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset))->dwSig == SIG_URL)
  663. {
  664. Import401UrlWithFile( (ie401::URL_FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset));
  665. }
  666. // after wrapping above in try-catch block, return FALSE on unhandled exception.
  667. return TRUE;
  668. }
  669. // Extends the default to import files
  670. BOOL IE401Content::Import401UrlWithFile( ie401::URL_FILEMAP_ENTRY* pEntry)
  671. {
  672. BOOL retVal = FALSE;
  673. // don't import Url if it is already in the buffer
  674. if( GetUrlCacheEntryInfo( (LPSTR)((BYTE*)pEntry + pEntry->UrlNameOffset), NULL, 0) == TRUE
  675. || GetLastError() != ERROR_FILE_NOT_FOUND)
  676. {
  677. goto doneImport401Url;
  678. }
  679. // don't import an URL if its one of those weird registered files.
  680. if( (pEntry->DirIndex == IE401_NOT_A_CACHE_SUBDIRECTORY)
  681. || (pEntry->CacheEntryType & IE401_EDITED_CACHE_ENTRY))
  682. {
  683. goto doneImport401Url;
  684. }
  685. if( pEntry->FileSize != 0)
  686. {
  687. // don't import Url if it's subdirectory didn't get created
  688. if( m_szDir[pEntry->DirIndex][0] == '\0')
  689. goto doneImport401Url;
  690. // store the new file path in m_szRoot
  691. memcpy( m_szRootPath + m_cbRootPathLength, m_szDir[pEntry->DirIndex], DIR_NAME_SIZE);
  692. m_szRootPath[ m_cbRootPathLength + DIR_NAME_SIZE] = FILENAME_SEPARATOR;
  693. m_szRootPath[ m_cbRootPathLength + DIR_NAME_SIZE + 1] = '\0';
  694. // This may result in truncation of the filename, when the 401 generated filename to
  695. // particularly long, causing the total path to exceed MAX_PATH.
  696. // We won't worry abou this.
  697. StrCatBuff(m_szRootPath,
  698. (CHAR*)pEntry + pEntry->InternalFileNameOffset,
  699. MAX_PATH);
  700. }
  701. if( !CommitUrlCacheEntry(
  702. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  703. (pEntry->FileSize != 0)
  704. ? m_szRootPath : NULL,
  705. *LONGLONG_TO_FILETIME(&pEntry->ExpireTime),
  706. *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime),
  707. pEntry->CacheEntryType,
  708. pEntry->HeaderInfoOffset != NULL ?
  709. (BYTE*)((BYTE*)pEntry + pEntry->HeaderInfoOffset) : NULL,
  710. pEntry->HeaderInfoSize,
  711. pEntry->FileExtensionOffset != 0 ?
  712. (LPCSTR)((BYTE*)pEntry + pEntry->FileExtensionOffset) : NULL,
  713. NULL))
  714. goto doneImport401Url;
  715. CACHE_ENTRY_INFO cei;
  716. cei.dwStructSize = sizeof(cei);
  717. cei.LastAccessTime = *LONGLONG_TO_FILETIME(&pEntry->LastAccessedTime);
  718. cei.dwHitRate = pEntry->NumAccessed;
  719. cei.ExpireTime = *LONGLONG_TO_FILETIME(&pEntry->ExpireTime);
  720. cei.LastModifiedTime = *LONGLONG_TO_FILETIME(&pEntry->LastModifiedTime);
  721. if( !SetUrlCacheEntryInfo(
  722. (LPCSTR)((BYTE*)pEntry + pEntry->UrlNameOffset),
  723. &cei,
  724. CACHE_ENTRY_ACCTIME_FC | CACHE_ENTRY_HITRATE_FC
  725. | CACHE_ENTRY_EXPTIME_FC | CACHE_ENTRY_MODTIME_FC))
  726. goto doneImport401Url;
  727. retVal = TRUE;
  728. doneImport401Url:
  729. // Remove appended data
  730. m_szRootPath[m_cbRootPathLength] = '\0';
  731. return retVal;
  732. }
  733. //*************************************************************************
  734. //
  735. // Import401Redirects()
  736. //
  737. IE401Redirects::IE401Redirects( IE401Content* pContent)
  738. {
  739. INET_ASSERT( m_pBuf == NULL);
  740. m_pBuf = pContent->m_pBuf;
  741. pContent->m_pBuf = NULL;
  742. }
  743. // import items that are redirects
  744. BOOL IE401Redirects::HandleHashElement( ie401::HASH_ITEM* pEntry)
  745. {
  746. // No reserved bits should be set.
  747. INET_ASSERT (!(pEntry->dwHash & HASH_BIT_RESERVED));
  748. if((pEntry->dwOffset != HASH_END) && ((ie401::FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset))->dwSig == SIG_REDIR)
  749. {
  750. Import401Redirect( (ie401::REDIR_FILEMAP_ENTRY*)(m_pBuf + pEntry->dwOffset));
  751. }
  752. // after wrapping above in try-catch block, return FALSE on unhandled exception.
  753. return TRUE;
  754. }
  755. // Imports entries that are redirects
  756. BOOL IE401Redirects::Import401Redirect( ie401::REDIR_FILEMAP_ENTRY* pEntry)
  757. {
  758. LPSTR szTargetUrl = NULL;
  759. //** wrap this one in an exception block, because just one of these guys
  760. //might just try to reference into space.
  761. // pEntry is an entry to a redirect entry, which contains an offset to a hash entry.
  762. // That hash entry contains an offset to the filemap entry of the redirect target.
  763. FILEMAP_ENTRY* pRedirTarget =
  764. (FILEMAP_ENTRY*)(m_pBuf + ((HASH_ITEM*)(m_pBuf + pEntry->dwItemOffset))->dwOffset);
  765. // The filemap entry of the redirect target could be a URL filmap entry or another
  766. //redirect filemap entry. Either way extract the url of that entry as the target url.
  767. switch( pRedirTarget->dwSig)
  768. {
  769. case SIG_REDIR:
  770. szTargetUrl = ((REDIR_FILEMAP_ENTRY*)pRedirTarget)->szUrl;
  771. break;
  772. case SIG_URL:
  773. szTargetUrl = (CHAR*)pRedirTarget + ((URL_FILEMAP_ENTRY*)pRedirTarget)->UrlNameOffset;
  774. break;
  775. default:
  776. return FALSE;
  777. }
  778. return GlobalUrlContainers->CreateContentRedirect( szTargetUrl, pEntry->szUrl);
  779. }
  780. //*************************************************************************
  781. //
  782. // Import401History()
  783. //
  784. // Inside IE401_HIST_ROOT{hHistRoot}, there are some keys that list
  785. //the history containers we want to import. Before we can import those containers,
  786. //we import the Visited: container. This file will be found in the subdirectory of
  787. //the location of the first history subcontainer.
  788. // When we reach a new container, we create it but don't worry about collisions.
  789. //Existing Url entries are never overwritten by the import process.
  790. BOOL Import401History()
  791. {
  792. BOOL retVal = FALSE;
  793. HKEY hHistRoot = (HKEY) INVALID_HANDLE_VALUE;
  794. // get key to root of history information (which is the root of all extensible containers)
  795. if( REGOPENKEYEX( IsPerUserCache() ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
  796. IE401_HIST_ROOT, 0, KEY_READ, &hHistRoot)
  797. != ERROR_SUCCESS)
  798. {
  799. hHistRoot = (HKEY) INVALID_HANDLE_VALUE;
  800. goto doneImport401History;
  801. }
  802. DWORD index; index = 0;
  803. CHAR szContainerName[MAX_PATH];
  804. DWORD cbContainerNameLength;
  805. DWORD dwCacheLimit;
  806. DWORD dwCacheOptions;
  807. CHAR szCachePath[MAX_PATH];
  808. DWORD cbCachePathSize;
  809. CHAR szCachePrefix[MAX_PATH];
  810. // Enumerate through the extensible containers, if they are History containers import them.
  811. // When the first history container is found, its path can be used to locate the Visited:
  812. //container which also must be imported.
  813. while( RegEnumKeyEx( hHistRoot, index++, szContainerName, &(cbContainerNameLength = MAX_PATH),
  814. NULL,NULL,NULL,NULL) == ERROR_SUCCESS)
  815. {
  816. static BOOL fFirstRun = TRUE;
  817. // we can't be sure all the extended containers are history containers.
  818. //This check verifies we only import history containers.
  819. if( StrCmpNI( szContainerName, MSHIST_SZ, sizeof(MSHIST_SZ) - 1) != 0
  820. || cbContainerNameLength != sizeof(MSHIST_KEY_SZ) - 1)
  821. {
  822. continue;
  823. }
  824. HKEY hHistContainer = (HKEY) INVALID_HANDLE_VALUE;
  825. DWORD dwTemp;
  826. DWORD dwType;
  827. if( REGOPENKEYEX( hHistRoot, szContainerName, 0, KEY_READ, &hHistContainer) != ERROR_SUCCESS)
  828. goto doneImportHistContainer;
  829. if( RegQueryValueEx( hHistContainer, CACHE_LIMIT_SZ, 0, &dwType,
  830. (BYTE*)&dwCacheLimit, &(dwTemp = sizeof(dwCacheLimit))) != ERROR_SUCCESS
  831. || dwType != REG_DWORD)
  832. {
  833. goto doneImportHistContainer;
  834. }
  835. if( RegQueryValueEx( hHistContainer, CACHE_OPTIONS_SZ, 0, &dwType,
  836. (BYTE*)&dwCacheOptions, &(dwTemp = sizeof(dwCacheOptions))) != ERROR_SUCCESS
  837. || dwType != REG_DWORD)
  838. {
  839. goto doneImportHistContainer;
  840. }
  841. if( RegQueryValueEx( hHistContainer, CACHE_PATH_SZ, 0, &dwType,
  842. (BYTE*)szCachePath, &(cbCachePathSize = sizeof(szCachePath))) != ERROR_SUCCESS
  843. || dwType != REG_SZ)
  844. {
  845. goto doneImportHistContainer;
  846. }
  847. if( RegQueryValueEx( hHistContainer, CACHE_PREFIX_SZ, 0, &dwType,
  848. (BYTE*)&szCachePrefix, &(dwTemp = sizeof(szCachePrefix))) != ERROR_SUCCESS
  849. || dwType != REG_SZ)
  850. {
  851. goto doneImportHistContainer;
  852. }
  853. // After finding the first container, import the Visited: container.
  854. if( fFirstRun == TRUE)
  855. {
  856. // Clip off the path of the history container, and substitute 'index.dat'
  857. //to identify the Visited container. Import the visited container, and
  858. //restore the path to the history container.
  859. CHAR szBuf[sizeof(MSHIST_DIR_SZ)];
  860. LPSTR szMSHIST = szCachePath + cbCachePathSize - sizeof(MSHIST_DIR_SZ);
  861. // ex result: szCachePath:"c:\path\MSHIST011998020119980225\", szMSHIST:"MSHIST011998020119980225\"
  862. memcpy( szBuf, szMSHIST, sizeof(MSHIST_DIR_SZ));
  863. // szBuf:"MSHIST011998020119980225\"
  864. memcpy( szMSHIST, "index.dat", sizeof("index.dat"));
  865. // szMSHIST:"index.dat" --> szCachePath:"c:\path\index.dat"
  866. IE401Visited Visited(szCachePath);
  867. Visited.EnumHashValues();
  868. memcpy( szMSHIST, szBuf, sizeof(MSHIST_DIR_SZ));
  869. // szMSHIST:"MSHIST011998020119980225\" --> szCachePath:"c:\path\MSHIST011998020119980225\"
  870. fFirstRun = FALSE;
  871. }
  872. // we don't pass the old path so that the container is put in the new one.
  873. if( CreateUrlCacheContainer( szContainerName, szCachePrefix, NULL,
  874. dwCacheLimit, 0, dwCacheOptions, NULL, NULL) != TRUE
  875. && GetLastError() != ERROR_ALREADY_EXISTS)
  876. {
  877. goto doneImportHistContainer;
  878. }
  879. if( cbCachePathSize + (sizeof(INDEX_DAT_SZ) - 1) > MAX_PATH)
  880. goto doneImportHistContainer;
  881. memcpy( szCachePath + cbCachePathSize - 1, INDEX_DAT_SZ, sizeof(INDEX_DAT_SZ));
  882. {
  883. IE401History History( szCachePath);
  884. History.EnumHashValues();
  885. }
  886. doneImportHistContainer:
  887. if( hHistContainer != (HKEY) INVALID_HANDLE_VALUE)
  888. REGCLOSEKEY( hHistContainer);
  889. }
  890. retVal = TRUE;
  891. doneImport401History:
  892. if( hHistRoot != (HKEY) INVALID_HANDLE_VALUE)
  893. REGCLOSEKEY( hHistRoot);
  894. return retVal;
  895. }
  896. //*************************************************************************
  897. //
  898. // Import401Content()
  899. //
  900. BOOL Import401Content()
  901. {
  902. BOOL retVal = FALSE;
  903. HKEY hContentKey = (HKEY) INVALID_HANDLE_VALUE;
  904. CHAR szContentFilename[MAX_PATH];
  905. LPSTR szKeyName = NULL;
  906. if( !GetIE5ContentPath(szContentFilename))
  907. goto doneImport401Content;
  908. // we now have something like 'c:\..\content\content.ie5'
  909. //and we want something like 'c:\..\content\index.dat'
  910. LONG index;
  911. // find the position of the last '\\'
  912. index = lstrlen( szContentFilename);
  913. while( index >= 0 && szContentFilename[index] != FILENAME_SEPARATOR)
  914. index--;
  915. // append an 'index.dat'
  916. memcpy( szContentFilename + index + 1, INDEX_DAT_SZ, sizeof(INDEX_DAT_SZ));
  917. #ifdef UNIX
  918. {
  919. // HACK HACK
  920. //
  921. // we now have something like
  922. // '/home/blah/.microsoft/ie5/TempInternetFiles/index.dat'
  923. // and we want something like
  924. // /home/blah/.microsoft/TempInternetFiles/index.dat
  925. char szSearchStr[] = "ie5/";
  926. char *pszWhere = StrStr(szContentFilename, szSearchStr);
  927. if (pszWhere)
  928. {
  929. memmove(pszWhere, pszWhere+sizeof(szSearchStr)-1,
  930. lstrlen(pszWhere+sizeof(szSearchStr)-1)+1);
  931. }
  932. }
  933. #endif /* UNIX */
  934. {
  935. IE401Content Content(szContentFilename);
  936. if( Content.EnumHashValues() == TRUE)
  937. {
  938. IE401Redirects Redirects( &Content);
  939. Redirects.EnumHashValues();
  940. }
  941. }
  942. doneImport401Content:
  943. if( hContentKey != (HKEY) INVALID_HANDLE_VALUE)
  944. REGCLOSEKEY( hContentKey);
  945. return retVal;
  946. }
  947. //-- end of namespace ie401
  948. }
  949. //--
  950. //
  951. //
  952. // Returns if caches are per user.
  953. //
  954. BOOL IsPerUserCache()
  955. {
  956. BOOL fProfilesEnabled = FALSE;
  957. static BOOL fPerUser = FALSE;
  958. #ifndef UNIX
  959. // Is the OS version Windows 95 or Windows NT?
  960. if (GlobalPlatformType == PLATFORM_TYPE_WIN95)
  961. {
  962. // Operating System is Windows 95.
  963. // Look for special key indicating profiles are enables. If its not found,
  964. //know that profiles aren't enabled.
  965. // Determine if profiles are enabled by OS.
  966. REGISTRY_OBJ roProfilesEnabled(HKEY_LOCAL_MACHINE, PROFILES_ENABLED_VALUE);
  967. if (roProfilesEnabled.GetStatus() == ERROR_SUCCESS)
  968. {
  969. DWORD dwProfilesEnabled = 0;
  970. if( roProfilesEnabled.GetValue(PROFILES_ENABLED, &dwProfilesEnabled) == ERROR_SUCCESS)
  971. {
  972. // Found the registry entry.
  973. fProfilesEnabled = (BOOL) dwProfilesEnabled;
  974. }
  975. }
  976. }
  977. else if (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  978. {
  979. // Profiles always enabled for NT.
  980. fProfilesEnabled = TRUE;
  981. }
  982. #else
  983. fProfilesEnabled = TRUE;
  984. #endif /* UNIX */
  985. // Determine if per user cache is allowed.
  986. REGISTRY_OBJ roProfilesAllowed(HKEY_LOCAL_MACHINE, PRE5_CACHE_KEY);
  987. if( fProfilesEnabled && roProfilesAllowed.GetStatus() == ERROR_SUCCESS)
  988. {
  989. DWORD dwPerUserCache = 0;
  990. if( roProfilesAllowed.GetValue(PROFILES_ENABLED,&dwPerUserCache) == ERROR_SUCCESS)
  991. {
  992. // Found the registry entry. Set g_fPerUserCache to
  993. // TRUE only if profiles are enabled.
  994. fPerUser = ((BOOL) dwPerUserCache);
  995. }
  996. else
  997. {
  998. // No entry. If profiles are enabled, assume they're allowed.
  999. fPerUser = fProfilesEnabled;
  1000. }
  1001. }
  1002. else
  1003. {
  1004. fPerUser = fProfilesEnabled;
  1005. }
  1006. return fPerUser;
  1007. }