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

  1. // TitleInfo.cpp : implementation file
  2. //
  3. //
  4. // includes
  5. //
  6. #include "stdafx.h"
  7. #include "titleinfo.h"
  8. #include <locale.h>
  9. #include <strsafe.h>
  10. // constants
  11. //
  12. const char txtTopicsFile[] = "#TOPICS";
  13. const char txtUrlTblFile[] = "#URLTBL";
  14. const char txtUrlStrFile[] = "#URLSTR";
  15. const char txtStringsFile[] = "#STRINGS";
  16. const char txtMkStore[] = "ms-its:";
  17. const char txtSepBack[] = "::/";
  18. const char txtDoubleColonSep[] = "::";
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CTitleInfo Class
  21. //
  22. // This class provides the ability to retrieve topic titles and topic URLs
  23. // from topic numbers from a CHM file (HTML Help title).
  24. //
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CTitleInfo class constructor
  27. //
  28. CTitleInfo::CTitleInfo()
  29. {
  30. // init members
  31. //
  32. m_bOpen = FALSE;
  33. m_szTitlePath[0] = NULL;
  34. m_pUrlStrings = NULL;
  35. m_pTopics = NULL;
  36. m_pStrTbl = NULL;
  37. m_pUrlTbl = NULL;
  38. m_pTitleInfo = NULL;
  39. m_pCFileSystem = NULL;
  40. }
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CTitleInfo class destructor
  43. //
  44. CTitleInfo::~CTitleInfo()
  45. {
  46. // make sure the title was opened
  47. //
  48. if (!m_bOpen)
  49. return;
  50. // close the subfiles
  51. //
  52. if (m_pUrlTbl)
  53. delete m_pUrlTbl;
  54. if(m_pTopics)
  55. delete m_pTopics;
  56. if(m_pStrTbl)
  57. delete m_pStrTbl;
  58. if(m_pUrlStrings)
  59. delete m_pUrlStrings;
  60. if(m_pTitleInfo)
  61. delete m_pTitleInfo;
  62. // delete the mail filesystem
  63. //
  64. if(m_pCFileSystem)
  65. delete m_pCFileSystem;
  66. // deinit the members
  67. //
  68. m_pUrlStrings = NULL;
  69. m_pTopics = NULL;
  70. m_pStrTbl = NULL;
  71. m_pUrlTbl = NULL;
  72. // no longer open
  73. //
  74. m_bOpen = FALSE;
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CTitleInfo: OpenTitle method
  78. //
  79. // This funciton opens a help title
  80. //
  81. // Note: This method must be called before any other methods
  82. //
  83. // pwcTitlePath Path the help title (chm file)
  84. //
  85. BOOL CTitleInfo::OpenTitle(WCHAR *pwcTitlePath)
  86. {
  87. HRESULT hr;
  88. // make sure we're not already open
  89. //
  90. if (m_bOpen)
  91. return TRUE;
  92. WCHAR wcFullPath[_MAX_PATH];
  93. WCHAR *pwcFilePart = NULL;
  94. // get the full path to title
  95. //
  96. if(!GetFullPathNameW(pwcTitlePath, sizeof(wcFullPath)/sizeof(WCHAR), wcFullPath, &pwcFilePart))
  97. return FALSE;
  98. // create filesystem object
  99. //
  100. if (m_pCFileSystem) delete m_pCFileSystem;
  101. m_pCFileSystem = new CFileSystem();
  102. if(!m_pCFileSystem)
  103. return FALSE;
  104. hr = m_pCFileSystem->Init();
  105. if(FAILED(hr))
  106. {
  107. delete m_pCFileSystem;
  108. m_pCFileSystem = NULL;
  109. return FALSE;
  110. }
  111. // open the CHM file
  112. //
  113. hr = m_pCFileSystem->Open(wcFullPath);
  114. if (FAILED(hr))
  115. {
  116. delete m_pCFileSystem;
  117. m_pCFileSystem = NULL;
  118. return FALSE;
  119. }
  120. if (m_pTitleInfo) delete m_pTitleInfo;
  121. m_pTitleInfo = new CTitleInformation(m_pCFileSystem);
  122. if(!m_pTitleInfo)
  123. {
  124. delete m_pCFileSystem;
  125. m_pCFileSystem = NULL;
  126. return FALSE;
  127. }
  128. // save the full path to the CHM (used when constructing URLs)
  129. //
  130. WideCharToMultiByte(CP_ACP, 0, wcFullPath, -1, m_szTitlePath, sizeof(m_szTitlePath), 0, 0);
  131. // success!
  132. //
  133. m_bOpen = TRUE;
  134. return TRUE;
  135. }
  136. /////////////////////////////////////////////////////////////////////////////
  137. // CTitleInfo: GetLocationName
  138. //
  139. // This function retrieves the location name of the CHM. This string is the
  140. // friendly name for the CHM that appears in result lists.
  141. //
  142. // pwszLocationName Destination buffer for location name
  143. // cch Size of pwszLocationName
  144. //
  145. HRESULT CTitleInfo::GetLocationName(WCHAR *pwszLocationName, int cch, UINT cp)
  146. {
  147. if(!pwszLocationName || !cch)
  148. return E_INVALIDARG;
  149. if(m_pTitleInfo)
  150. {
  151. const CHAR* psz = NULL;
  152. psz = m_pTitleInfo->GetDefaultCaption();
  153. if( !psz || !*psz )
  154. psz = m_pTitleInfo->GetShortName();
  155. if( psz && *psz )
  156. {
  157. MultiByteToWideChar(cp, 0, psz, -1, pwszLocationName, cch);
  158. pwszLocationName[cch-1] = 0;
  159. return S_OK;
  160. }
  161. }
  162. return E_FAIL;
  163. }
  164. /////////////////////////////////////////////////////////////////////////////
  165. // CTitleInfo: GetTopicName
  166. //
  167. // This function retrieves a topic title from a topic number
  168. //
  169. // dwTopic Topic Number
  170. // pwszTitle Destination buffer for topic title
  171. // cch Size of pwszTitle
  172. //
  173. HRESULT CTitleInfo::GetTopicName(DWORD dwTopic, WCHAR* pwszTitle, int cch, UINT cp)
  174. {
  175. TOC_TOPIC topic;
  176. HRESULT hr;
  177. if (SUCCEEDED(hr = GetTopicData(dwTopic, &topic)))
  178. return GetString(topic.dwOffsTitle, pwszTitle, cch, cp);
  179. else
  180. return hr;
  181. }
  182. /////////////////////////////////////////////////////////////////////////////
  183. // CTitleInfo: GetTopicURL
  184. //
  185. // This function retrieves a topic URL from a topic number
  186. //
  187. // dwTopic Topic Number
  188. // pwszURL Destination buffer for URL
  189. // cch Size of pwcURL
  190. //
  191. HRESULT CTitleInfo::GetTopicURL(DWORD dwTopic, CHAR* pwszURL, int cch)
  192. {
  193. TOC_TOPIC topic;
  194. HRESULT hr;
  195. CHAR* psz;
  196. if (m_bOpen == FALSE)
  197. return E_FAIL;
  198. if (!m_pUrlTbl)
  199. {
  200. m_pUrlTbl = new CPagedSubfile; if(!m_pUrlTbl) return E_FAIL;
  201. if (FAILED(hr = m_pUrlTbl->Open(this, txtUrlTblFile)))
  202. {
  203. delete m_pUrlTbl;
  204. m_pUrlTbl = NULL;
  205. return hr;
  206. }
  207. }
  208. if (!m_pUrlStrings)
  209. {
  210. m_pUrlStrings = new CPagedSubfile; if(!m_pUrlStrings) return E_FAIL;
  211. if (FAILED(hr = m_pUrlStrings->Open(this, txtUrlStrFile)))
  212. {
  213. delete m_pUrlStrings;
  214. m_pUrlStrings = NULL;
  215. return hr;
  216. }
  217. }
  218. if ( (hr = GetTopicData(dwTopic, &topic)) == S_OK )
  219. {
  220. PCURL pUrlTbl;
  221. if ( (pUrlTbl = (PCURL)m_pUrlTbl->Offset(topic.dwOffsURL)) )
  222. {
  223. PURLSTR purl = (PURLSTR) m_pUrlStrings->Offset(pUrlTbl->dwOffsURL);
  224. if (purl)
  225. {
  226. // If not an interfile jump, the create the full URL
  227. //
  228. if (! StrChr(purl->szURL, ':'))
  229. {
  230. psz = purl->szURL;
  231. if ((int) (strlen(psz) + strlen(txtMkStore) + strlen(m_szTitlePath) + 7) > cch)
  232. return E_OUTOFMEMORY;
  233. StringCchCopyA(pwszURL, cch, txtMkStore);
  234. pwszURL[cch-1] = 0;
  235. StringCchCatA(pwszURL, cch, m_szTitlePath);
  236. if (*psz != '/')
  237. StringCchCatA(pwszURL, cch, txtSepBack);
  238. else
  239. StringCchCatA(pwszURL, cch, txtDoubleColonSep);
  240. StringCchCatA(pwszURL, cch, psz);
  241. }
  242. else
  243. return E_FAIL; // inter-chm jump, not supported by this function
  244. }
  245. }
  246. }
  247. return hr;
  248. }
  249. /////////////////////////////////////////////////////////////////////////////
  250. // CTitleInfo: GetTopicData
  251. //
  252. // This funciton retrieves data from the topics sub-file
  253. //
  254. HRESULT CTitleInfo::GetTopicData(DWORD dwTopic, TOC_TOPIC * pTopicData)
  255. {
  256. HRESULT hr;
  257. BYTE * pb;
  258. if (m_bOpen == FALSE)
  259. return E_FAIL;
  260. if (!m_pTopics)
  261. {
  262. m_pTopics = new CPagedSubfile; if(!m_pTopics) return E_FAIL;
  263. if (FAILED(hr = m_pTopics->Open(this, txtTopicsFile)))
  264. {
  265. delete m_pTopics;
  266. m_pTopics = NULL;
  267. return hr;
  268. }
  269. }
  270. pb = (BYTE*)m_pTopics->Offset(dwTopic * sizeof(TOC_TOPIC));
  271. if (pb)
  272. {
  273. memcpy(pTopicData, pb, sizeof(TOC_TOPIC));
  274. return S_OK;
  275. }
  276. else
  277. return E_FAIL;
  278. }
  279. /////////////////////////////////////////////////////////////////////////////
  280. // CTitleInfo: GetString
  281. //
  282. // This funciton retrieves data from the strings sub-file
  283. //
  284. HRESULT CTitleInfo::GetString( DWORD dwOffset, WCHAR* pwsz, int cch, UINT cp )
  285. {
  286. const CHAR* pStr = GetString( dwOffset );
  287. if( pStr ) {
  288. MultiByteToWideChar(cp, 0, pStr, -1, pwsz, cch );
  289. return S_OK;
  290. }
  291. else
  292. return E_FAIL;
  293. }
  294. /////////////////////////////////////////////////////////////////////////////
  295. // CTitleInfo: GetString
  296. //
  297. // This funciton retrieves data from the strings sub-file
  298. //
  299. const CHAR* CTitleInfo::GetString( DWORD dwOffset )
  300. {
  301. HRESULT hr;
  302. const CHAR* pStr;
  303. if( !m_bOpen )
  304. return NULL;
  305. if( !m_pStrTbl )
  306. {
  307. m_pStrTbl = new CPagedSubfile; if(!m_pStrTbl) return NULL;
  308. if( FAILED(hr = m_pStrTbl->Open(this,txtStringsFile)) )
  309. {
  310. delete m_pStrTbl; m_pStrTbl = NULL;
  311. return NULL;
  312. }
  313. }
  314. pStr = (const CHAR*) m_pStrTbl->Offset( dwOffset );
  315. return pStr;
  316. }
  317. /////////////////////////////////////////////////////////////////////////////
  318. // CTitleInfo: GetString
  319. //
  320. // This funciton retrieves data from the strings sub-file
  321. //
  322. HRESULT CTitleInfo::GetString( DWORD dwOffset, CHAR* psz, int cb )
  323. {
  324. const CHAR* pStr = GetString( dwOffset );
  325. if( pStr )
  326. {
  327. StringCbCopyA( psz, cb, pStr );
  328. psz[cb-1] = 0;
  329. return S_OK;
  330. }
  331. else
  332. return E_FAIL;
  333. }