256 lines
6.6 KiB
C++
256 lines
6.6 KiB
C++
//
|
|
// 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 support@saltmine.com
|
|
//
|
|
// 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;
|
|
}
|