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.

255 lines
6.6 KiB

  1. //
  2. // MODULE: CHMFileReader.CPP
  3. //
  4. // PURPOSE: implement CHM file reading class CCHMFileReader
  5. //
  6. // PROJECT: for Local Troubleshooter; not needed in Online TS
  7. //
  8. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  9. //
  10. // AUTHOR: Joe Mabel
  11. //
  12. // ORIGINAL DATE: 01-18-99
  13. //
  14. // NOTES:
  15. //
  16. // Version Date By Comments
  17. //--------------------------------------------------------------------
  18. // V3.1 01-18-99 JM
  19. //
  20. #include "stdafx.h"
  21. #include "fs.h"
  22. #include "CHMFileReader.h"
  23. // Utilize an unnamed namespace to limit scope to this source file
  24. namespace
  25. {
  26. const CString kstr_CHMfileExtension=_T("chm");
  27. const CString kstr_CHMpathMarker= _T("mk:@msitstore:");
  28. const CString kstr_CHMstreamMarker= _T("::/");
  29. }
  30. //////////////////////////////////////////////////////////////////////
  31. // Construction/Destruction
  32. //////////////////////////////////////////////////////////////////////
  33. CCHMFileReader::CCHMFileReader(CString strCHMPath, CString strStreamName)
  34. : m_strCHMPath(strCHMPath),
  35. m_strStreamName(strStreamName),
  36. m_pFileSystem(NULL),
  37. m_pSubFileSystem(NULL)
  38. {
  39. }
  40. CCHMFileReader::CCHMFileReader( CString strFullCHMname )
  41. : m_pFileSystem(NULL),
  42. m_pSubFileSystem(NULL)
  43. {
  44. int nPosPathMarker, nPosStreamMarker;
  45. nPosPathMarker= strFullCHMname.Find( kstr_CHMpathMarker );
  46. nPosStreamMarker= strFullCHMname.Find( kstr_CHMstreamMarker );
  47. if ((nPosPathMarker == -1) || (nPosStreamMarker == -1))
  48. {
  49. // >>> Need to think about how to handle this condition or whether we should
  50. // be checking for a 'valid' CHM path outside of a constructor. RAB-19990120.
  51. }
  52. else
  53. {
  54. // Extract the path and string names (bounds checking is handled by the CString class).
  55. nPosPathMarker+= kstr_CHMpathMarker.GetLength();
  56. m_strCHMPath= strFullCHMname.Mid( nPosPathMarker, nPosStreamMarker - nPosPathMarker );
  57. nPosStreamMarker+= kstr_CHMstreamMarker.GetLength();
  58. m_strStreamName= strFullCHMname.Mid( nPosStreamMarker );
  59. }
  60. }
  61. CCHMFileReader::~CCHMFileReader()
  62. {
  63. if (m_pSubFileSystem)
  64. delete m_pSubFileSystem;
  65. if (m_pFileSystem)
  66. delete m_pFileSystem;
  67. }
  68. // doesn't throw exception, therefore may be used by exception class.
  69. bool CCHMFileReader::CloseHandle()
  70. {
  71. if (m_pSubFileSystem)
  72. {
  73. delete m_pSubFileSystem;
  74. m_pSubFileSystem = NULL;
  75. }
  76. if (m_pFileSystem)
  77. {
  78. m_pFileSystem->Close();
  79. delete m_pFileSystem;
  80. m_pFileSystem = NULL;
  81. }
  82. return true;
  83. }
  84. void CCHMFileReader::Open()
  85. {
  86. try
  87. {
  88. m_pFileSystem = new CFileSystem();
  89. //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
  90. if(!m_pFileSystem)
  91. {
  92. throw bad_alloc();
  93. }
  94. m_pSubFileSystem = new CSubFileSystem(m_pFileSystem);
  95. //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
  96. if(!m_pSubFileSystem)
  97. {
  98. throw bad_alloc();
  99. }
  100. }
  101. catch (bad_alloc&)
  102. {
  103. CloseHandle();
  104. throw CFileReaderException(this, CFileReaderException::eErrOpen, __FILE__, __LINE__);
  105. }
  106. HRESULT hr;
  107. if (RUNNING_FREE_THREADED())
  108. hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); // Initialize COM library
  109. if (RUNNING_APARTMENT_THREADED())
  110. hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Initialize COM library
  111. if (SUCCEEDED(hr))
  112. hr = m_pFileSystem->Init();
  113. // >>> $BUG$ potential - not sure. Oleg. 02.04.99
  114. // Theoretically we do not need COM library after class factory
  115. // was used in m_pFileSystem->Init() in order to obtain ITStorage pointer.
  116. // Oleg. 02.04.99
  117. // MS v-amitse 07.16.2001 RAID 432425 - added check for successful initialization
  118. if ((RUNNING_FREE_THREADED() || RUNNING_APARTMENT_THREADED()) && SUCCEEDED(hr))
  119. ::CoUninitialize(); // Uninitialize COM library
  120. if (SUCCEEDED(hr))
  121. hr = m_pFileSystem->Open(m_strCHMPath);
  122. if (SUCCEEDED(hr))
  123. hr = m_pSubFileSystem->OpenSub(m_strStreamName);
  124. if (! SUCCEEDED(hr) )
  125. {
  126. CloseHandle();
  127. throw CFileReaderException( this, CFileReaderException::eErrOpen, __FILE__, __LINE__ );
  128. }
  129. }
  130. void CCHMFileReader::ReadData(LPTSTR * ppBuf)
  131. {
  132. if (!m_pSubFileSystem)
  133. throw CFileReaderException(this, CFileReaderException::eErrOpen, __FILE__, __LINE__);
  134. ULONG cb = m_pSubFileSystem->GetUncompressedSize();
  135. ULONG cbRead = 0;
  136. try
  137. {
  138. *ppBuf = new TCHAR [cb/sizeof(TCHAR)+1];
  139. //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
  140. if(!*ppBuf)
  141. throw bad_alloc();
  142. memset(*ppBuf, 0, cb+sizeof(TCHAR));
  143. }
  144. catch (bad_alloc&)
  145. {
  146. throw CFileReaderException(this, CFileReaderException::eErrAllocateToRead, __FILE__, __LINE__);
  147. }
  148. HRESULT hr = m_pSubFileSystem->ReadSub(*ppBuf, cb, &cbRead);
  149. if (! SUCCEEDED(hr) )
  150. throw CFileReaderException(this, CFileReaderException::eErrRead, __FILE__, __LINE__);
  151. }
  152. CString CCHMFileReader::GetPathName() const
  153. {
  154. return (kstr_CHMpathMarker + m_strCHMPath + kstr_CHMstreamMarker + m_strStreamName );
  155. }
  156. CString CCHMFileReader::GetJustNameWithoutExtension() const
  157. {
  158. return CAbstractFileReader::GetJustNameWithoutExtension(m_strStreamName);
  159. }
  160. CString CCHMFileReader::GetJustExtension() const
  161. {
  162. return CAbstractFileReader::GetJustExtension(m_strStreamName);
  163. }
  164. bool CCHMFileReader::GetFileTime(CAbstractFileReader::EFileTime type, time_t& out) const
  165. {
  166. return CAbstractFileReader::GetFileTime(m_strCHMPath, type, out);
  167. }
  168. CString CCHMFileReader::GetNameToLog() const
  169. {
  170. return GetPathName();
  171. }
  172. // Returns true if the first few characters of the path match a given string.
  173. /*static*/ bool CCHMFileReader::IsCHMfile( const CString& strPath )
  174. {
  175. // Make a copy of the path.
  176. CString strTemp= strPath;
  177. // Check for the string that denotes the beginning of a CHM file.
  178. // The sequence must start in the initial byte of a left trimmed string.
  179. strTemp.TrimLeft();
  180. strTemp.MakeLower();
  181. if (strTemp.Find( kstr_CHMpathMarker ) == 0)
  182. return( true );
  183. else
  184. return( false );
  185. }
  186. /*static*/ bool CCHMFileReader::IsPathToCHMfile( const CString& strPath )
  187. {
  188. CString strTemp = strPath;
  189. strTemp.TrimRight();
  190. strTemp.MakeLower();
  191. // New approach, test for ANY extension
  192. int dot_index = strTemp.ReverseFind(_T('.'));
  193. int back_slash_index = strTemp.ReverseFind(_T('\\'));
  194. int forward_slash_index = strTemp.ReverseFind(_T('/'));
  195. if (dot_index != -1 &&
  196. dot_index > back_slash_index &&
  197. dot_index > forward_slash_index
  198. )
  199. {
  200. // Now test, if it is a real file
  201. WIN32_FIND_DATA find_data;
  202. HANDLE hFile = ::FindFirstFile(strTemp, &find_data);
  203. if (hFile != INVALID_HANDLE_VALUE)
  204. {
  205. ::FindClose(hFile);
  206. return true;
  207. }
  208. }
  209. // Old approach, test for ".chm"
  210. //if (CString(_T(".")) + kstr_CHMfileExtension == strTemp.Right(kstr_CHMfileExtension.GetLength() + 1))
  211. // return true;
  212. return false;
  213. }
  214. /*static*/ CString CCHMFileReader::FormCHMPath( const CString strPathToCHMfile )
  215. {
  216. return kstr_CHMpathMarker + strPathToCHMfile + kstr_CHMstreamMarker;
  217. }