Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
4.8 KiB

  1. // Copyright (C) 1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "subfile.h"
  4. #include "fs.h"
  5. #include "toc.h"
  6. static CPagesList listSubfiles;
  7. //////////////////////////////////////////////
  8. //
  9. // CPagesList
  10. //
  11. //////////////////////////////////////////////
  12. CPagesList::~CPagesList()
  13. {
  14. CPages* p;
  15. while (p = m_pFirst)
  16. {
  17. m_pFirst = p->m_pNext;
  18. delete p;
  19. }
  20. }
  21. CPages* CPagesList::GetPages( HASH hash )
  22. {
  23. CPages * p;
  24. for (p = m_pFirst; p; p = p->m_pNext)
  25. if ( hash == p->m_hash )
  26. return p;
  27. p = new CPages( hash );
  28. p->m_pNext = m_pFirst;
  29. m_pFirst = p;
  30. return p;
  31. }
  32. ////////////////////////////////////////
  33. //
  34. // CPages
  35. //
  36. ////////////////////////////////////////
  37. CPages::CPages( HASH hash )
  38. {
  39. m_pNext = 0;
  40. m_hash = hash;
  41. Flush();
  42. }
  43. void* CPages::Find(const CExTitle * pTitle, HASH hashPathname, DWORD dwPage)
  44. {
  45. int i;
  46. for( i = 0; i < CACHE_PAGE_COUNT; i++ )
  47. {
  48. // test if lowest LRU
  49. if( m_pages[i].dwLRU < m_pages[m_dwLRUPage].dwLRU ) {
  50. m_dwLRUPage = i;
  51. }
  52. if( m_pages[i].dwLRU &&
  53. m_pages[i].hashPathname == hashPathname &&
  54. m_pages[i].dwPage == dwPage &&
  55. m_pages[i].pTitle == pTitle )
  56. {
  57. m_pages[i].dwLRU = ++m_dwLRUCount; // update LRU
  58. return m_pages[i].rgb;
  59. }
  60. }
  61. return NULL;
  62. }
  63. void* CPages::Alloc(CExTitle * pTitle, HASH hashPathname, DWORD dwPage)
  64. {
  65. // if we reached the max LRU number then flush the cache and start over
  66. if( m_dwLRUCount == ((DWORD) -1) )
  67. Flush();
  68. m_pages[m_dwLRUPage].dwLRU = ++m_dwLRUCount;
  69. m_pages[m_dwLRUPage].hashPathname = hashPathname;
  70. m_pages[m_dwLRUPage].dwPage = dwPage;
  71. m_pages[m_dwLRUPage].pTitle = pTitle;
  72. return m_pages[m_dwLRUPage].rgb;
  73. }
  74. void CPages::Flush(void)
  75. {
  76. int i;
  77. for( i = 0; i < CACHE_PAGE_COUNT; i++ )
  78. m_pages[i].dwLRU = 0;
  79. m_dwLRUPage = 0;
  80. m_dwLRUCount = 0;
  81. }
  82. void CPages::Flush( CExTitle* pTitle )
  83. {
  84. if( !pTitle )
  85. return;
  86. int i;
  87. for( i = 0; i < CACHE_PAGE_COUNT; i++ )
  88. if( m_pages[i].pTitle == pTitle )
  89. m_pages[i].dwLRU = 0;
  90. }
  91. //////////////////////////////////////////////
  92. //
  93. // CPagedSubfile
  94. //
  95. //////////////////////////////////////////////
  96. CPagedSubfile::CPagedSubfile()
  97. {
  98. m_pCSubFileSystem = 0; // type CSubFileSystem from fs.h/fs.cpp
  99. m_pTitle = 0;
  100. m_pPages = 0;
  101. m_cbSize = 0xFFFFFFFF;
  102. }
  103. CPagedSubfile::~CPagedSubfile()
  104. {
  105. if ( m_pCSubFileSystem )
  106. delete m_pCSubFileSystem;
  107. // flush all of its owned pages since
  108. // the same pTitle value may be re-used and thus
  109. // the cache is invalid
  110. m_pPages->Flush( m_pTitle );
  111. }
  112. HRESULT CPagedSubfile::Open(CExTitle * pTitle, LPCSTR lpsz)
  113. {
  114. if (m_pCSubFileSystem || m_pTitle || m_pPages || !pTitle->m_pCFileSystem )
  115. return E_FAIL;
  116. m_pTitle = pTitle;
  117. // hash the filename
  118. m_hashPathname = HashFromSz( lpsz );
  119. #ifdef _DEBUG
  120. char sz[1024];
  121. wsprintf( sz, "Hash:%d File:%s\n", m_hashPathname, lpsz );
  122. OutputDebugString( sz );
  123. #endif
  124. #if defined( HH_FAST_CACHE )
  125. // keep CACHE_PAGE_COUNT small (2-3) and hash the title and the filename
  126. char szHash[MAX_PATH*2];
  127. strcpy( szHash, pTitle->GetInfo2()->GetShortName() );
  128. strcat( szHash, "::" );
  129. strcat( szHash, lpsz );
  130. m_hash = HashFromSz( szHash );
  131. #elif defined ( HH_EFFICIENT_CACHE )
  132. // keep CACHE_PAGE_COUNT moderately low (3-5) and hash just the filename
  133. m_hash = HashFromSz( lpsz );
  134. #else // HH_SHARED_CACHE
  135. // keep CACHE_PAGE_COUNT high (30+) and have only one shared cache group
  136. m_hash = HashFromSz( "HTMLHelpSharedCache" );
  137. #endif
  138. if (!(m_pPages = listSubfiles.GetPages(m_hash)))
  139. return E_FAIL;
  140. m_pCSubFileSystem = new CSubFileSystem(pTitle->m_pCFileSystem);
  141. if(FAILED(m_pCSubFileSystem->OpenSub(lpsz)))
  142. {
  143. delete m_pCSubFileSystem;
  144. m_pCSubFileSystem = NULL;
  145. return E_FAIL;
  146. }
  147. m_cbSize = m_pCSubFileSystem->GetUncompressedSize();
  148. return S_OK;
  149. }
  150. void* CPagedSubfile::Offset(DWORD dwOffs)
  151. {
  152. DWORD dwPage;
  153. void* pv;
  154. if (dwOffs >= m_cbSize)
  155. return NULL;
  156. dwPage = dwOffs / PAGE_SIZE;
  157. dwOffs -= (dwPage * PAGE_SIZE);
  158. if (pv = Page(dwPage))
  159. return (BYTE*)pv + dwOffs;
  160. else
  161. return NULL;
  162. }
  163. void* CPagedSubfile::Page(DWORD dwPage)
  164. {
  165. void* pv;
  166. if (pv = m_pPages->Find(m_pTitle, m_hashPathname, dwPage))
  167. return pv;
  168. if (!(pv = m_pPages->Alloc(m_pTitle, m_hashPathname, dwPage)))
  169. return NULL;
  170. DWORD li = dwPage * PAGE_SIZE;
  171. if ( m_pCSubFileSystem->SeekSub(li,0) != li )
  172. return NULL;
  173. // init the page in case we don't read it all...
  174. //
  175. #ifdef _DEBUG
  176. memset(pv,0xFF,PAGE_SIZE);
  177. #endif
  178. ULONG cb;
  179. if (FAILED(m_pCSubFileSystem->ReadSub(pv, PAGE_SIZE, &cb)))
  180. return NULL;
  181. return pv;
  182. }