|
|
//
// MODULE: CHMFileReader.CPP
//
// PURPOSE: implement CHM file reading class CCHMFileReader
//
// PROJECT: for Local Troubleshooter; not needed in Online TS
//
// COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
//
// AUTHOR: Joe Mabel
//
// ORIGINAL DATE: 01-18-99
//
// NOTES:
//
// Version Date By Comments
//--------------------------------------------------------------------
// V3.1 01-18-99 JM
//
#include "stdafx.h"
#include "fs.h"
#include "CHMFileReader.h"
// Utilize an unnamed namespace to limit scope to this source file
namespace { const CString kstr_CHMfileExtension=_T("chm"); const CString kstr_CHMpathMarker= _T("mk:@msitstore:"); const CString kstr_CHMstreamMarker= _T("::/"); }
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCHMFileReader::CCHMFileReader(CString strCHMPath, CString strStreamName) : m_strCHMPath(strCHMPath), m_strStreamName(strStreamName), m_pFileSystem(NULL), m_pSubFileSystem(NULL) { }
CCHMFileReader::CCHMFileReader( CString strFullCHMname ) : m_pFileSystem(NULL), m_pSubFileSystem(NULL) { int nPosPathMarker, nPosStreamMarker;
nPosPathMarker= strFullCHMname.Find( kstr_CHMpathMarker ); nPosStreamMarker= strFullCHMname.Find( kstr_CHMstreamMarker ); if ((nPosPathMarker == -1) || (nPosStreamMarker == -1)) { // >>> Need to think about how to handle this condition or whether we should
// be checking for a 'valid' CHM path outside of a constructor. RAB-19990120.
} else { // Extract the path and string names (bounds checking is handled by the CString class).
nPosPathMarker+= kstr_CHMpathMarker.GetLength(); m_strCHMPath= strFullCHMname.Mid( nPosPathMarker, nPosStreamMarker - nPosPathMarker ); nPosStreamMarker+= kstr_CHMstreamMarker.GetLength(); m_strStreamName= strFullCHMname.Mid( nPosStreamMarker ); } }
CCHMFileReader::~CCHMFileReader() { if (m_pSubFileSystem) delete m_pSubFileSystem; if (m_pFileSystem) delete m_pFileSystem; }
// doesn't throw exception, therefore may be used by exception class.
bool CCHMFileReader::CloseHandle() { if (m_pSubFileSystem) { delete m_pSubFileSystem; m_pSubFileSystem = NULL; } if (m_pFileSystem) { m_pFileSystem->Close(); delete m_pFileSystem; m_pFileSystem = NULL; }
return true; }
void CCHMFileReader::Open() { try { m_pFileSystem = new CFileSystem(); //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
if(!m_pFileSystem) { throw bad_alloc(); } m_pSubFileSystem = new CSubFileSystem(m_pFileSystem); //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
if(!m_pSubFileSystem) { throw bad_alloc(); } } catch (bad_alloc&) { CloseHandle(); throw CFileReaderException(this, CFileReaderException::eErrOpen, __FILE__, __LINE__); }
HRESULT hr; if (RUNNING_FREE_THREADED()) hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); // Initialize COM library
if (RUNNING_APARTMENT_THREADED()) hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // Initialize COM library
if (SUCCEEDED(hr)) hr = m_pFileSystem->Init(); // >>> $BUG$ potential - not sure. Oleg. 02.04.99
// Theoretically we do not need COM library after class factory
// was used in m_pFileSystem->Init() in order to obtain ITStorage pointer.
// Oleg. 02.04.99
// MS v-amitse 07.16.2001 RAID 432425 - added check for successful initialization
if ((RUNNING_FREE_THREADED() || RUNNING_APARTMENT_THREADED()) && SUCCEEDED(hr)) ::CoUninitialize(); // Uninitialize COM library
if (SUCCEEDED(hr)) hr = m_pFileSystem->Open(m_strCHMPath);
if (SUCCEEDED(hr)) hr = m_pSubFileSystem->OpenSub(m_strStreamName);
if (! SUCCEEDED(hr) ) { CloseHandle(); throw CFileReaderException( this, CFileReaderException::eErrOpen, __FILE__, __LINE__ ); } }
void CCHMFileReader::ReadData(LPTSTR * ppBuf) { if (!m_pSubFileSystem) throw CFileReaderException(this, CFileReaderException::eErrOpen, __FILE__, __LINE__);
ULONG cb = m_pSubFileSystem->GetUncompressedSize(); ULONG cbRead = 0;
try { *ppBuf = new TCHAR [cb/sizeof(TCHAR)+1]; //[BC-03022001] - added check for NULL ptr to satisfy MS code analysis tool.
if(!*ppBuf) throw bad_alloc(); memset(*ppBuf, 0, cb+sizeof(TCHAR)); } catch (bad_alloc&) { throw CFileReaderException(this, CFileReaderException::eErrAllocateToRead, __FILE__, __LINE__); }
HRESULT hr = m_pSubFileSystem->ReadSub(*ppBuf, cb, &cbRead); if (! SUCCEEDED(hr) ) throw CFileReaderException(this, CFileReaderException::eErrRead, __FILE__, __LINE__); }
CString CCHMFileReader::GetPathName() const { return (kstr_CHMpathMarker + m_strCHMPath + kstr_CHMstreamMarker + m_strStreamName ); }
CString CCHMFileReader::GetJustNameWithoutExtension() const { return CAbstractFileReader::GetJustNameWithoutExtension(m_strStreamName); }
CString CCHMFileReader::GetJustExtension() const { return CAbstractFileReader::GetJustExtension(m_strStreamName); }
bool CCHMFileReader::GetFileTime(CAbstractFileReader::EFileTime type, time_t& out) const { return CAbstractFileReader::GetFileTime(m_strCHMPath, type, out); }
CString CCHMFileReader::GetNameToLog() const { return GetPathName(); }
// Returns true if the first few characters of the path match a given string.
/*static*/ bool CCHMFileReader::IsCHMfile( const CString& strPath ) { // Make a copy of the path.
CString strTemp= strPath;
// Check for the string that denotes the beginning of a CHM file.
// The sequence must start in the initial byte of a left trimmed string.
strTemp.TrimLeft(); strTemp.MakeLower(); if (strTemp.Find( kstr_CHMpathMarker ) == 0) return( true ); else return( false ); }
/*static*/ bool CCHMFileReader::IsPathToCHMfile( const CString& strPath ) { CString strTemp = strPath;
strTemp.TrimRight(); strTemp.MakeLower(); // New approach, test for ANY extension
int dot_index = strTemp.ReverseFind(_T('.')); int back_slash_index = strTemp.ReverseFind(_T('\\')); int forward_slash_index = strTemp.ReverseFind(_T('/'));
if (dot_index != -1 && dot_index > back_slash_index && dot_index > forward_slash_index ) { // Now test, if it is a real file
WIN32_FIND_DATA find_data; HANDLE hFile = ::FindFirstFile(strTemp, &find_data);
if (hFile != INVALID_HANDLE_VALUE) { ::FindClose(hFile); return true; } } // Old approach, test for ".chm"
//if (CString(_T(".")) + kstr_CHMfileExtension == strTemp.Right(kstr_CHMfileExtension.GetLength() + 1))
// return true;
return false; }
/*static*/ CString CCHMFileReader::FormCHMPath( const CString strPathToCHMfile ) { return kstr_CHMpathMarker + strPathToCHMfile + kstr_CHMstreamMarker; }
|