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.

234 lines
5.2 KiB

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