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.
 
 
 
 
 
 

387 lines
9.3 KiB

// TitleInfo.cpp : implementation file
//
//
// includes
//
#include "stdafx.h"
#include "titleinfo.h"
#include <locale.h>
#include <strsafe.h>
// constants
//
const char txtTopicsFile[] = "#TOPICS";
const char txtUrlTblFile[] = "#URLTBL";
const char txtUrlStrFile[] = "#URLSTR";
const char txtStringsFile[] = "#STRINGS";
const char txtMkStore[] = "ms-its:";
const char txtSepBack[] = "::/";
const char txtDoubleColonSep[] = "::";
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo Class
//
// This class provides the ability to retrieve topic titles and topic URLs
// from topic numbers from a CHM file (HTML Help title).
//
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo class constructor
//
CTitleInfo::CTitleInfo()
{
// init members
//
m_bOpen = FALSE;
m_szTitlePath[0] = NULL;
m_pUrlStrings = NULL;
m_pTopics = NULL;
m_pStrTbl = NULL;
m_pUrlTbl = NULL;
m_pTitleInfo = NULL;
m_pCFileSystem = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo class destructor
//
CTitleInfo::~CTitleInfo()
{
// make sure the title was opened
//
if (!m_bOpen)
return;
// close the subfiles
//
if (m_pUrlTbl)
delete m_pUrlTbl;
if(m_pTopics)
delete m_pTopics;
if(m_pStrTbl)
delete m_pStrTbl;
if(m_pUrlStrings)
delete m_pUrlStrings;
if(m_pTitleInfo)
delete m_pTitleInfo;
// delete the mail filesystem
//
if(m_pCFileSystem)
delete m_pCFileSystem;
// deinit the members
//
m_pUrlStrings = NULL;
m_pTopics = NULL;
m_pStrTbl = NULL;
m_pUrlTbl = NULL;
// no longer open
//
m_bOpen = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: OpenTitle method
//
// This funciton opens a help title
//
// Note: This method must be called before any other methods
//
// pwcTitlePath Path the help title (chm file)
//
BOOL CTitleInfo::OpenTitle(WCHAR *pwcTitlePath)
{
HRESULT hr;
// make sure we're not already open
//
if (m_bOpen)
return TRUE;
WCHAR wcFullPath[_MAX_PATH];
WCHAR *pwcFilePart = NULL;
// get the full path to title
//
if(!GetFullPathNameW(pwcTitlePath, sizeof(wcFullPath)/sizeof(WCHAR), wcFullPath, &pwcFilePart))
return FALSE;
// create filesystem object
//
if (m_pCFileSystem) delete m_pCFileSystem;
m_pCFileSystem = new CFileSystem();
if(!m_pCFileSystem)
return FALSE;
hr = m_pCFileSystem->Init();
if(FAILED(hr))
{
delete m_pCFileSystem;
m_pCFileSystem = NULL;
return FALSE;
}
// open the CHM file
//
hr = m_pCFileSystem->Open(wcFullPath);
if (FAILED(hr))
{
delete m_pCFileSystem;
m_pCFileSystem = NULL;
return FALSE;
}
if (m_pTitleInfo) delete m_pTitleInfo;
m_pTitleInfo = new CTitleInformation(m_pCFileSystem);
if(!m_pTitleInfo)
{
delete m_pCFileSystem;
m_pCFileSystem = NULL;
return FALSE;
}
// save the full path to the CHM (used when constructing URLs)
//
WideCharToMultiByte(CP_ACP, 0, wcFullPath, -1, m_szTitlePath, sizeof(m_szTitlePath), 0, 0);
// success!
//
m_bOpen = TRUE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetLocationName
//
// This function retrieves the location name of the CHM. This string is the
// friendly name for the CHM that appears in result lists.
//
// pwszLocationName Destination buffer for location name
// cch Size of pwszLocationName
//
HRESULT CTitleInfo::GetLocationName(WCHAR *pwszLocationName, int cch, UINT cp)
{
if(!pwszLocationName || !cch)
return E_INVALIDARG;
if(m_pTitleInfo)
{
const CHAR* psz = NULL;
psz = m_pTitleInfo->GetDefaultCaption();
if( !psz || !*psz )
psz = m_pTitleInfo->GetShortName();
if( psz && *psz )
{
MultiByteToWideChar(cp, 0, psz, -1, pwszLocationName, cch);
pwszLocationName[cch-1] = 0;
return S_OK;
}
}
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicName
//
// This function retrieves a topic title from a topic number
//
// dwTopic Topic Number
// pwszTitle Destination buffer for topic title
// cch Size of pwszTitle
//
HRESULT CTitleInfo::GetTopicName(DWORD dwTopic, WCHAR* pwszTitle, int cch, UINT cp)
{
TOC_TOPIC topic;
HRESULT hr;
if (SUCCEEDED(hr = GetTopicData(dwTopic, &topic)))
return GetString(topic.dwOffsTitle, pwszTitle, cch, cp);
else
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicURL
//
// This function retrieves a topic URL from a topic number
//
// dwTopic Topic Number
// pwszURL Destination buffer for URL
// cch Size of pwcURL
//
HRESULT CTitleInfo::GetTopicURL(DWORD dwTopic, CHAR* pwszURL, int cch)
{
TOC_TOPIC topic;
HRESULT hr;
CHAR* psz;
if (m_bOpen == FALSE)
return E_FAIL;
if (!m_pUrlTbl)
{
m_pUrlTbl = new CPagedSubfile; if(!m_pUrlTbl) return E_FAIL;
if (FAILED(hr = m_pUrlTbl->Open(this, txtUrlTblFile)))
{
delete m_pUrlTbl;
m_pUrlTbl = NULL;
return hr;
}
}
if (!m_pUrlStrings)
{
m_pUrlStrings = new CPagedSubfile; if(!m_pUrlStrings) return E_FAIL;
if (FAILED(hr = m_pUrlStrings->Open(this, txtUrlStrFile)))
{
delete m_pUrlStrings;
m_pUrlStrings = NULL;
return hr;
}
}
if ( (hr = GetTopicData(dwTopic, &topic)) == S_OK )
{
PCURL pUrlTbl;
if ( (pUrlTbl = (PCURL)m_pUrlTbl->Offset(topic.dwOffsURL)) )
{
PURLSTR purl = (PURLSTR) m_pUrlStrings->Offset(pUrlTbl->dwOffsURL);
if (purl)
{
// If not an interfile jump, the create the full URL
//
if (! StrChr(purl->szURL, ':'))
{
psz = purl->szURL;
if ((int) (strlen(psz) + strlen(txtMkStore) + strlen(m_szTitlePath) + 7) > cch)
return E_OUTOFMEMORY;
StringCchCopyA(pwszURL, cch, txtMkStore);
pwszURL[cch-1] = 0;
StringCchCatA(pwszURL, cch, m_szTitlePath);
if (*psz != '/')
StringCchCatA(pwszURL, cch, txtSepBack);
else
StringCchCatA(pwszURL, cch, txtDoubleColonSep);
StringCchCatA(pwszURL, cch, psz);
}
else
return E_FAIL; // inter-chm jump, not supported by this function
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetTopicData
//
// This funciton retrieves data from the topics sub-file
//
HRESULT CTitleInfo::GetTopicData(DWORD dwTopic, TOC_TOPIC * pTopicData)
{
HRESULT hr;
BYTE * pb;
if (m_bOpen == FALSE)
return E_FAIL;
if (!m_pTopics)
{
m_pTopics = new CPagedSubfile; if(!m_pTopics) return E_FAIL;
if (FAILED(hr = m_pTopics->Open(this, txtTopicsFile)))
{
delete m_pTopics;
m_pTopics = NULL;
return hr;
}
}
pb = (BYTE*)m_pTopics->Offset(dwTopic * sizeof(TOC_TOPIC));
if (pb)
{
memcpy(pTopicData, pb, sizeof(TOC_TOPIC));
return S_OK;
}
else
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
HRESULT CTitleInfo::GetString( DWORD dwOffset, WCHAR* pwsz, int cch, UINT cp )
{
const CHAR* pStr = GetString( dwOffset );
if( pStr ) {
MultiByteToWideChar(cp, 0, pStr, -1, pwsz, cch );
return S_OK;
}
else
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
const CHAR* CTitleInfo::GetString( DWORD dwOffset )
{
HRESULT hr;
const CHAR* pStr;
if( !m_bOpen )
return NULL;
if( !m_pStrTbl )
{
m_pStrTbl = new CPagedSubfile; if(!m_pStrTbl) return NULL;
if( FAILED(hr = m_pStrTbl->Open(this,txtStringsFile)) )
{
delete m_pStrTbl; m_pStrTbl = NULL;
return NULL;
}
}
pStr = (const CHAR*) m_pStrTbl->Offset( dwOffset );
return pStr;
}
/////////////////////////////////////////////////////////////////////////////
// CTitleInfo: GetString
//
// This funciton retrieves data from the strings sub-file
//
HRESULT CTitleInfo::GetString( DWORD dwOffset, CHAR* psz, int cb )
{
const CHAR* pStr = GetString( dwOffset );
if( pStr )
{
StringCbCopyA( psz, cb, pStr );
psz[cb-1] = 0;
return S_OK;
}
else
return E_FAIL;
}