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.

452 lines
13 KiB

  1. /*******************************************************************************
  2. * LtsLx.cpp *
  3. *--------------*
  4. * Implements the LTS lexicon object.
  5. *
  6. * Owner: YUNUSM Date: 06/18/99
  7. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  8. *******************************************************************************/
  9. //--- Includes ----------------------------------------------------------------
  10. #include "StdAfx.h"
  11. #include "LtsLx.h"
  12. #include <initguid.h>
  13. //--- Globals -----------------------------------------------------------------
  14. // CAUTION: This validation GUID also defined in the tool to build LTS lexicons
  15. // {578EAD4E-330C-11d3-9C26-00C04F8EF87C}
  16. DEFINE_GUID(guidLtsValidationId,
  17. 0x578ead4e, 0x330c, 0x11d3, 0x9c, 0x26, 0x0, 0xc0, 0x4f, 0x8e, 0xf8, 0x7c);
  18. extern CSpUnicodeSupport g_Unicode;
  19. //--- Constructor, Initializer and Destructor functions ------------------------
  20. /*******************************************************************************
  21. * CLTSLexicon::CLTSLexicon *
  22. *--------------------------*
  23. *
  24. * Description:
  25. * Constructor
  26. *
  27. * Return:
  28. * n/a
  29. ***************************************************************** YUNUSM ******/
  30. CLTSLexicon::CLTSLexicon(void)
  31. {
  32. SPDBG_FUNC("CLTSLexicon::CLTSLexicon");
  33. }
  34. /*******************************************************************************
  35. * CLTSLexicon::FinalConstruct *
  36. *-----------------------------*
  37. *
  38. * Description:
  39. * Initializes the CLTSLexicon object
  40. *
  41. * Return:
  42. * S_OK
  43. ***************************************************************** YUNUSM ******/
  44. HRESULT CLTSLexicon::FinalConstruct(void)
  45. {
  46. SPDBG_FUNC("CLTSLexicon::FinalConstruct");
  47. NullMembers();
  48. return S_OK;
  49. }
  50. /*****************************************************************************
  51. * CLTSLexicon::~CLTSLexicon *
  52. *---------------------------*
  53. *
  54. * Description:
  55. * Destructor
  56. *
  57. * Return:
  58. * n/a
  59. **********************************************************************YUNUSM*/
  60. CLTSLexicon::~CLTSLexicon()
  61. {
  62. SPDBG_FUNC("CLTSLexicon::~CLTSLexicon");
  63. CleanUp();
  64. }
  65. /*******************************************************************************
  66. * CLTSLexicon::CleanUp *
  67. *----------------------*
  68. *
  69. * Description:
  70. * real destructor
  71. *
  72. * Return:
  73. * n/a
  74. ***************************************************************** YUNUSM ******/
  75. void CLTSLexicon::CleanUp(void)
  76. {
  77. SPDBG_FUNC("CLTSLexicon::CleanUp");
  78. if (m_pLtsData)
  79. {
  80. UnmapViewOfFile(m_pLtsData);
  81. }
  82. if (m_hLtsMap)
  83. {
  84. CloseHandle(m_hLtsMap);
  85. }
  86. if (m_hLtsFile)
  87. {
  88. CloseHandle(m_hLtsFile);
  89. }
  90. if (m_pLTSForest)
  91. {
  92. ::LtscartFreeData(m_pLTSForest);
  93. }
  94. NullMembers();
  95. }
  96. /*******************************************************************************
  97. * CLTSLexicon::NullMembers *
  98. *--------------------------*
  99. *
  100. * Description:
  101. * null data
  102. *
  103. * Return:
  104. * n/a
  105. ***************************************************************** YUNUSM ******/
  106. void CLTSLexicon::NullMembers(void)
  107. {
  108. SPDBG_FUNC("CLTSLexicon::NullMembers");
  109. m_fInit = false;
  110. m_cpObjectToken = NULL;
  111. m_pLtsData = NULL;
  112. m_hLtsMap = NULL;
  113. m_hLtsFile = NULL;
  114. m_pLTSForest = NULL;
  115. m_pLtsLexInfo = NULL;
  116. m_cpPhoneConv = NULL;
  117. }
  118. //--- ISpLexicon methods -------------------------------------------------------
  119. /*******************************************************************************
  120. * GetPronunciations *
  121. *-------------------*
  122. *
  123. * Description:
  124. * Gets the pronunciations and POSs of a word
  125. *
  126. * Return:
  127. * E_POINTER
  128. * E_INVALIDARG
  129. * E_OUTOFMEMORY
  130. * S_OK
  131. ***************************************************************** YUNUSM ******/
  132. STDMETHODIMP CLTSLexicon::GetPronunciations(const WCHAR * pwWord, // word
  133. LANGID LangID, // LANGID of the word
  134. DWORD dwFlags, // lextype
  135. SPWORDPRONUNCIATIONLIST * pWordPronunciationList // buffer to return info in
  136. )
  137. {
  138. USES_CONVERSION;
  139. SPDBG_FUNC("CLTSLexicon::GetPronunciations");
  140. HRESULT hr = S_OK;
  141. LANGID LangIDPassedIn = LangID;
  142. BOOL fBogusPron = FALSE;
  143. if (!pwWord || !pWordPronunciationList)
  144. {
  145. hr = E_POINTER;
  146. }
  147. if (SUCCEEDED(hr))
  148. {
  149. // Yuncj: Chinese SR is using English LTS, so bypass the gollowing test by replacing its LangID
  150. if ( 2052 == LangID )
  151. {
  152. LangID = 1033;
  153. }
  154. if (!m_fInit)
  155. {
  156. hr = SPERR_UNINITIALIZED;
  157. }
  158. else if (SPIsBadLexWord(pwWord) ||
  159. (LangID != m_pLtsLexInfo->LangID && LangID) ||
  160. SPIsBadWordPronunciationList(pWordPronunciationList))
  161. {
  162. hr = E_INVALIDARG;
  163. }
  164. }
  165. if (SUCCEEDED(hr) && LangID == 1041)
  166. {
  167. // Check if the string is all english chars - Japanese LTS handles only english strings
  168. char szWord[SP_MAX_WORD_LENGTH];
  169. strcpy(szWord, W2A(pwWord));
  170. _strlwr(szWord);
  171. for (int i = 0; szWord[i]; i++)
  172. {
  173. if ((szWord[i] < 'a' || szWord[i] > 'z') && (szWord[i] != '\''))
  174. {
  175. hr = SPERR_NOT_IN_LEX; // Not returning E_INVALIDARG here since that would be hard for app to interpret
  176. break;
  177. }
  178. }
  179. }
  180. char szWord[SP_MAX_WORD_LENGTH];
  181. if (SUCCEEDED(hr))
  182. {
  183. if (!WideCharToMultiByte (CP_ACP, 0, pwWord, -1, szWord, SP_MAX_WORD_LENGTH, NULL, NULL))
  184. {
  185. hr = SpHrFromLastWin32Error();
  186. }
  187. }
  188. size_t cbPronsLen = 0;
  189. WCHAR aWordsProns[MAX_OUTPUT_STRINGS][SP_MAX_PRON_LENGTH];
  190. LTS_OUTPUT * pLTSOutput = NULL;
  191. int cProns = 0;
  192. ZeroMemory(aWordsProns, SP_MAX_PRON_LENGTH * MAX_OUTPUT_STRINGS * sizeof(WCHAR));
  193. if (SUCCEEDED(hr))
  194. {
  195. hr = LtscartGetPron(m_pLTSForest, szWord, &pLTSOutput);
  196. fBogusPron = S_FALSE == hr;
  197. if (SUCCEEDED(hr))
  198. {
  199. for (int i = 0; i < pLTSOutput->num_prons; i++)
  200. {
  201. HRESULT hrPhone = m_cpPhoneConv->PhoneToId(A2W(pLTSOutput->pron[i].pstr), aWordsProns[cProns]);
  202. if (SUCCEEDED(hrPhone))
  203. {
  204. cbPronsLen += PronSize(aWordsProns[cProns]);
  205. cProns++;
  206. }
  207. }
  208. }
  209. }
  210. if (SUCCEEDED(hr) && 0 == cProns)
  211. {
  212. hr = SPERR_NOT_IN_LEX;
  213. }
  214. if (SUCCEEDED(hr))
  215. {
  216. hr = ReallocSPWORDPRONList(pWordPronunciationList, cbPronsLen);
  217. }
  218. if (SUCCEEDED(hr))
  219. {
  220. SPWORDPRONUNCIATION *p = pWordPronunciationList->pFirstWordPronunciation;
  221. SPWORDPRONUNCIATION **ppNext = &pWordPronunciationList->pFirstWordPronunciation;
  222. for (int i = 0; i < cProns; i++)
  223. {
  224. p->ePartOfSpeech = SPPS_NotOverriden;
  225. wcscpy(p->szPronunciation, aWordsProns[i]);
  226. p->eLexiconType = (SPLEXICONTYPE)dwFlags;
  227. p->LangID = LangIDPassedIn;
  228. *ppNext = p;
  229. ppNext = &p->pNextWordPronunciation;
  230. p = CreateNextPronunciation(p);
  231. }
  232. *ppNext = NULL;
  233. }
  234. hr = SUCCEEDED(hr) ? (fBogusPron ? S_FALSE : S_OK) : hr;
  235. SPDBG_RETURN(hr);
  236. }
  237. STDMETHODIMP CLTSLexicon::AddPronunciation(const WCHAR *, LANGID, SPPARTOFSPEECH, const SPPHONEID *)
  238. {
  239. return E_NOTIMPL;
  240. }
  241. STDMETHODIMP CLTSLexicon::RemovePronunciation(const WCHAR *, LANGID, SPPARTOFSPEECH, const SPPHONEID *)
  242. {
  243. return E_NOTIMPL;
  244. }
  245. STDMETHODIMP CLTSLexicon::GetGeneration(DWORD *)
  246. {
  247. return E_NOTIMPL;
  248. }
  249. STDMETHODIMP CLTSLexicon::GetGenerationChange(DWORD, DWORD*, SPWORDLIST *)
  250. {
  251. return E_NOTIMPL;
  252. }
  253. STDMETHODIMP CLTSLexicon::GetWords(DWORD, DWORD *, DWORD *, SPWORDLIST *)
  254. {
  255. return E_NOTIMPL;
  256. }
  257. //--- ISpObjectToken methods ---------------------------------------------------
  258. STDMETHODIMP CLTSLexicon::GetObjectToken(ISpObjectToken **ppToken)
  259. {
  260. return SpGenericGetObjectToken(ppToken, m_cpObjectToken);
  261. }
  262. /*****************************************************************************
  263. * CLTSLexicon::SetObjectToken *
  264. *-----------------------------*
  265. * Description:
  266. * Initializes the CLTSLexicon object
  267. *
  268. * Return:
  269. * E_POINTER
  270. * E_INVALIDARG
  271. * GetLastError()
  272. * E_OUTOFMEMORY
  273. * S_OK
  274. **********************************************************************YUNUSM*/
  275. HRESULT CLTSLexicon::SetObjectToken(ISpObjectToken * pToken // token pointer
  276. )
  277. {
  278. USES_CONVERSION;
  279. SPDBG_FUNC("CLTSLexicon::SetObjectToken");
  280. HRESULT hr = S_OK;
  281. WCHAR *pszLexFile = NULL;
  282. if (!pToken)
  283. {
  284. hr = E_POINTER;
  285. }
  286. if (SUCCEEDED(hr))
  287. {
  288. if (SPIsBadInterfacePtr(pToken))
  289. {
  290. hr = E_INVALIDARG;
  291. }
  292. }
  293. if (SUCCEEDED(hr))
  294. {
  295. CleanUp();
  296. hr = SpGenericSetObjectToken(pToken, m_cpObjectToken);
  297. }
  298. // Get the lts data file name
  299. if (SUCCEEDED(hr))
  300. {
  301. hr = m_cpObjectToken->GetStringValue(L"Datafile", &pszLexFile);
  302. }
  303. // Open the Lts lexicon file
  304. if (SUCCEEDED(hr))
  305. {
  306. m_hLtsFile = g_Unicode.CreateFile (pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  307. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
  308. if (m_hLtsFile == INVALID_HANDLE_VALUE)
  309. {
  310. hr = SpHrFromLastWin32Error(); // bad input
  311. }
  312. }
  313. LTSLEXINFO LtsInfo;
  314. DWORD dwRead;
  315. if (SUCCEEDED(hr))
  316. {
  317. if (!ReadFile(m_hLtsFile, &LtsInfo, sizeof(LTSLEXINFO), &dwRead, NULL) || dwRead != sizeof(LTSLEXINFO))
  318. {
  319. hr = SpHrFromLastWin32Error();
  320. }
  321. }
  322. if (SUCCEEDED(hr))
  323. {
  324. if (guidLtsValidationId != LtsInfo.guidValidationId ||
  325. (LtsInfo.LangID != 1033 && LtsInfo.LangID != 1041))
  326. {
  327. hr = E_INVALIDARG;
  328. }
  329. }
  330. /** WARNINIG **/
  331. // It is not recommended to do ReadFile/WriteFile and CreateFileMapping
  332. // on the same file handle. That is why we close the file handle and open it again and
  333. // create the map
  334. // Close the file and reopen since we have read from this file
  335. CloseHandle(m_hLtsFile);
  336. // Get the map name - We build the map name from the lexicon file name
  337. OLECHAR szMapName[_MAX_PATH];
  338. wcscpy(szMapName, pszLexFile);
  339. for( int i = 0; i < _MAX_PATH-1 && szMapName[i]; i++ )
  340. {
  341. if( szMapName[i] == '\\' )
  342. {
  343. // Change backslash to underscore
  344. szMapName[i] = '_';
  345. }
  346. }
  347. // Open the Lts lexicon file
  348. if (SUCCEEDED(hr))
  349. {
  350. #ifdef _WIN32_WCE
  351. m_hLtsFile = g_Unicode.CreateFileForMappingW(pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  352. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
  353. #else
  354. m_hLtsFile = g_Unicode.CreateFile(pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  355. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
  356. #endif
  357. if (m_hLtsFile == INVALID_HANDLE_VALUE)
  358. {
  359. hr = SpHrFromLastWin32Error(); // bad input
  360. }
  361. ::CoTaskMemFree(pszLexFile);
  362. }
  363. // Map the Lts lexicon
  364. if (SUCCEEDED(hr))
  365. {
  366. m_hLtsMap = g_Unicode.CreateFileMapping(m_hLtsFile, NULL, PAGE_READONLY | SEC_COMMIT, 0 , 0, szMapName);
  367. if (!m_hLtsMap)
  368. {
  369. hr = SpHrFromLastWin32Error();
  370. }
  371. }
  372. if (SUCCEEDED(hr))
  373. {
  374. m_pLtsData = (PBYTE) MapViewOfFile (m_hLtsMap, FILE_MAP_READ, 0, 0, 0);
  375. if (!m_pLtsData)
  376. {
  377. hr = SpHrFromLastWin32Error();
  378. }
  379. }
  380. if (SUCCEEDED(hr))
  381. {
  382. m_pLtsLexInfo = (LTSLEXINFO*)m_pLtsData;
  383. }
  384. DWORD nOffset = sizeof(LTSLEXINFO);
  385. // Create and init the converter object
  386. if (SUCCEEDED(hr))
  387. {
  388. // hr = SpCreatePhoneConverter(LtsInfo.LangID, L"Type=LTS", NULL, &m_cpPhoneConv);
  389. hr = SpCreateObjectFromSubToken(pToken, L"PhoneConverter", &m_cpPhoneConv);
  390. }
  391. if (SUCCEEDED(hr))
  392. {
  393. nOffset += strlen((char*)(m_pLtsData + nOffset)) + 1;
  394. m_pLTSForest = ::LtscartReadData(m_pLtsLexInfo->LangID, m_pLtsData + nOffset);
  395. if (!m_pLTSForest)
  396. {
  397. hr = E_OUTOFMEMORY;
  398. }
  399. }
  400. if (SUCCEEDED(hr))
  401. {
  402. m_fInit = true;
  403. }
  404. return hr;
  405. }