/******************************************************************************* * LtsLx.cpp * *--------------* * Implements the LTS lexicon object. * * Owner: YUNUSM Date: 06/18/99 * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. *******************************************************************************/ //--- Includes ---------------------------------------------------------------- #include "StdAfx.h" #include "LtsLx.h" #include //--- Globals ----------------------------------------------------------------- // CAUTION: This validation GUID also defined in the tool to build LTS lexicons // {578EAD4E-330C-11d3-9C26-00C04F8EF87C} DEFINE_GUID(guidLtsValidationId, 0x578ead4e, 0x330c, 0x11d3, 0x9c, 0x26, 0x0, 0xc0, 0x4f, 0x8e, 0xf8, 0x7c); extern CSpUnicodeSupport g_Unicode; //--- Constructor, Initializer and Destructor functions ------------------------ /******************************************************************************* * CLTSLexicon::CLTSLexicon * *--------------------------* * * Description: * Constructor * * Return: * n/a ***************************************************************** YUNUSM ******/ CLTSLexicon::CLTSLexicon(void) { SPDBG_FUNC("CLTSLexicon::CLTSLexicon"); } /******************************************************************************* * CLTSLexicon::FinalConstruct * *-----------------------------* * * Description: * Initializes the CLTSLexicon object * * Return: * S_OK ***************************************************************** YUNUSM ******/ HRESULT CLTSLexicon::FinalConstruct(void) { SPDBG_FUNC("CLTSLexicon::FinalConstruct"); NullMembers(); return S_OK; } /***************************************************************************** * CLTSLexicon::~CLTSLexicon * *---------------------------* * * Description: * Destructor * * Return: * n/a **********************************************************************YUNUSM*/ CLTSLexicon::~CLTSLexicon() { SPDBG_FUNC("CLTSLexicon::~CLTSLexicon"); CleanUp(); } /******************************************************************************* * CLTSLexicon::CleanUp * *----------------------* * * Description: * real destructor * * Return: * n/a ***************************************************************** YUNUSM ******/ void CLTSLexicon::CleanUp(void) { SPDBG_FUNC("CLTSLexicon::CleanUp"); if (m_pLtsData) { UnmapViewOfFile(m_pLtsData); } if (m_hLtsMap) { CloseHandle(m_hLtsMap); } if (m_hLtsFile) { CloseHandle(m_hLtsFile); } if (m_pLTSForest) { ::LtscartFreeData(m_pLTSForest); } NullMembers(); } /******************************************************************************* * CLTSLexicon::NullMembers * *--------------------------* * * Description: * null data * * Return: * n/a ***************************************************************** YUNUSM ******/ void CLTSLexicon::NullMembers(void) { SPDBG_FUNC("CLTSLexicon::NullMembers"); m_fInit = false; m_cpObjectToken = NULL; m_pLtsData = NULL; m_hLtsMap = NULL; m_hLtsFile = NULL; m_pLTSForest = NULL; m_pLtsLexInfo = NULL; m_cpPhoneConv = NULL; } //--- ISpLexicon methods ------------------------------------------------------- /******************************************************************************* * GetPronunciations * *-------------------* * * Description: * Gets the pronunciations and POSs of a word * * Return: * E_POINTER * E_INVALIDARG * E_OUTOFMEMORY * S_OK ***************************************************************** YUNUSM ******/ STDMETHODIMP CLTSLexicon::GetPronunciations(const WCHAR * pwWord, // word LANGID LangID, // LANGID of the word DWORD dwFlags, // lextype SPWORDPRONUNCIATIONLIST * pWordPronunciationList // buffer to return info in ) { USES_CONVERSION; SPDBG_FUNC("CLTSLexicon::GetPronunciations"); HRESULT hr = S_OK; LANGID LangIDPassedIn = LangID; BOOL fBogusPron = FALSE; if (!pwWord || !pWordPronunciationList) { hr = E_POINTER; } if (SUCCEEDED(hr)) { // Yuncj: Chinese SR is using English LTS, so bypass the gollowing test by replacing its LangID if ( 2052 == LangID ) { LangID = 1033; } if (!m_fInit) { hr = SPERR_UNINITIALIZED; } else if (SPIsBadLexWord(pwWord) || (LangID != m_pLtsLexInfo->LangID && LangID) || SPIsBadWordPronunciationList(pWordPronunciationList)) { hr = E_INVALIDARG; } } if (SUCCEEDED(hr) && LangID == 1041) { // Check if the string is all english chars - Japanese LTS handles only english strings char szWord[SP_MAX_WORD_LENGTH]; strcpy(szWord, W2A(pwWord)); _strlwr(szWord); for (int i = 0; szWord[i]; i++) { if ((szWord[i] < 'a' || szWord[i] > 'z') && (szWord[i] != '\'')) { hr = SPERR_NOT_IN_LEX; // Not returning E_INVALIDARG here since that would be hard for app to interpret break; } } } char szWord[SP_MAX_WORD_LENGTH]; if (SUCCEEDED(hr)) { if (!WideCharToMultiByte (CP_ACP, 0, pwWord, -1, szWord, SP_MAX_WORD_LENGTH, NULL, NULL)) { hr = SpHrFromLastWin32Error(); } } size_t cbPronsLen = 0; WCHAR aWordsProns[MAX_OUTPUT_STRINGS][SP_MAX_PRON_LENGTH]; LTS_OUTPUT * pLTSOutput = NULL; int cProns = 0; ZeroMemory(aWordsProns, SP_MAX_PRON_LENGTH * MAX_OUTPUT_STRINGS * sizeof(WCHAR)); if (SUCCEEDED(hr)) { hr = LtscartGetPron(m_pLTSForest, szWord, &pLTSOutput); fBogusPron = S_FALSE == hr; if (SUCCEEDED(hr)) { for (int i = 0; i < pLTSOutput->num_prons; i++) { HRESULT hrPhone = m_cpPhoneConv->PhoneToId(A2W(pLTSOutput->pron[i].pstr), aWordsProns[cProns]); if (SUCCEEDED(hrPhone)) { cbPronsLen += PronSize(aWordsProns[cProns]); cProns++; } } } } if (SUCCEEDED(hr) && 0 == cProns) { hr = SPERR_NOT_IN_LEX; } if (SUCCEEDED(hr)) { hr = ReallocSPWORDPRONList(pWordPronunciationList, cbPronsLen); } if (SUCCEEDED(hr)) { SPWORDPRONUNCIATION *p = pWordPronunciationList->pFirstWordPronunciation; SPWORDPRONUNCIATION **ppNext = &pWordPronunciationList->pFirstWordPronunciation; for (int i = 0; i < cProns; i++) { p->ePartOfSpeech = SPPS_NotOverriden; wcscpy(p->szPronunciation, aWordsProns[i]); p->eLexiconType = (SPLEXICONTYPE)dwFlags; p->LangID = LangIDPassedIn; *ppNext = p; ppNext = &p->pNextWordPronunciation; p = CreateNextPronunciation(p); } *ppNext = NULL; } hr = SUCCEEDED(hr) ? (fBogusPron ? S_FALSE : S_OK) : hr; SPDBG_RETURN(hr); } STDMETHODIMP CLTSLexicon::AddPronunciation(const WCHAR *, LANGID, SPPARTOFSPEECH, const SPPHONEID *) { return E_NOTIMPL; } STDMETHODIMP CLTSLexicon::RemovePronunciation(const WCHAR *, LANGID, SPPARTOFSPEECH, const SPPHONEID *) { return E_NOTIMPL; } STDMETHODIMP CLTSLexicon::GetGeneration(DWORD *) { return E_NOTIMPL; } STDMETHODIMP CLTSLexicon::GetGenerationChange(DWORD, DWORD*, SPWORDLIST *) { return E_NOTIMPL; } STDMETHODIMP CLTSLexicon::GetWords(DWORD, DWORD *, DWORD *, SPWORDLIST *) { return E_NOTIMPL; } //--- ISpObjectToken methods --------------------------------------------------- STDMETHODIMP CLTSLexicon::GetObjectToken(ISpObjectToken **ppToken) { return SpGenericGetObjectToken(ppToken, m_cpObjectToken); } /***************************************************************************** * CLTSLexicon::SetObjectToken * *-----------------------------* * Description: * Initializes the CLTSLexicon object * * Return: * E_POINTER * E_INVALIDARG * GetLastError() * E_OUTOFMEMORY * S_OK **********************************************************************YUNUSM*/ HRESULT CLTSLexicon::SetObjectToken(ISpObjectToken * pToken // token pointer ) { USES_CONVERSION; SPDBG_FUNC("CLTSLexicon::SetObjectToken"); HRESULT hr = S_OK; WCHAR *pszLexFile = NULL; if (!pToken) { hr = E_POINTER; } if (SUCCEEDED(hr)) { if (SPIsBadInterfacePtr(pToken)) { hr = E_INVALIDARG; } } if (SUCCEEDED(hr)) { CleanUp(); hr = SpGenericSetObjectToken(pToken, m_cpObjectToken); } // Get the lts data file name if (SUCCEEDED(hr)) { hr = m_cpObjectToken->GetStringValue(L"Datafile", &pszLexFile); } // Open the Lts lexicon file if (SUCCEEDED(hr)) { m_hLtsFile = g_Unicode.CreateFile (pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); if (m_hLtsFile == INVALID_HANDLE_VALUE) { hr = SpHrFromLastWin32Error(); // bad input } } LTSLEXINFO LtsInfo; DWORD dwRead; if (SUCCEEDED(hr)) { if (!ReadFile(m_hLtsFile, &LtsInfo, sizeof(LTSLEXINFO), &dwRead, NULL) || dwRead != sizeof(LTSLEXINFO)) { hr = SpHrFromLastWin32Error(); } } if (SUCCEEDED(hr)) { if (guidLtsValidationId != LtsInfo.guidValidationId || (LtsInfo.LangID != 1033 && LtsInfo.LangID != 1041)) { hr = E_INVALIDARG; } } /** WARNINIG **/ // It is not recommended to do ReadFile/WriteFile and CreateFileMapping // on the same file handle. That is why we close the file handle and open it again and // create the map // Close the file and reopen since we have read from this file CloseHandle(m_hLtsFile); // Get the map name - We build the map name from the lexicon file name OLECHAR szMapName[_MAX_PATH]; wcscpy(szMapName, pszLexFile); for( int i = 0; i < _MAX_PATH-1 && szMapName[i]; i++ ) { if( szMapName[i] == '\\' ) { // Change backslash to underscore szMapName[i] = '_'; } } // Open the Lts lexicon file if (SUCCEEDED(hr)) { #ifdef _WIN32_WCE m_hLtsFile = g_Unicode.CreateFileForMappingW(pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); #else m_hLtsFile = g_Unicode.CreateFile(pszLexFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); #endif if (m_hLtsFile == INVALID_HANDLE_VALUE) { hr = SpHrFromLastWin32Error(); // bad input } ::CoTaskMemFree(pszLexFile); } // Map the Lts lexicon if (SUCCEEDED(hr)) { m_hLtsMap = g_Unicode.CreateFileMapping(m_hLtsFile, NULL, PAGE_READONLY | SEC_COMMIT, 0 , 0, szMapName); if (!m_hLtsMap) { hr = SpHrFromLastWin32Error(); } } if (SUCCEEDED(hr)) { m_pLtsData = (PBYTE) MapViewOfFile (m_hLtsMap, FILE_MAP_READ, 0, 0, 0); if (!m_pLtsData) { hr = SpHrFromLastWin32Error(); } } if (SUCCEEDED(hr)) { m_pLtsLexInfo = (LTSLEXINFO*)m_pLtsData; } DWORD nOffset = sizeof(LTSLEXINFO); // Create and init the converter object if (SUCCEEDED(hr)) { // hr = SpCreatePhoneConverter(LtsInfo.LangID, L"Type=LTS", NULL, &m_cpPhoneConv); hr = SpCreateObjectFromSubToken(pToken, L"PhoneConverter", &m_cpPhoneConv); } if (SUCCEEDED(hr)) { nOffset += strlen((char*)(m_pLtsData + nOffset)) + 1; m_pLTSForest = ::LtscartReadData(m_pLtsLexInfo->LangID, m_pLtsData + nOffset); if (!m_pLTSForest) { hr = E_OUTOFMEMORY; } } if (SUCCEEDED(hr)) { m_fInit = true; } return hr; }