630 lines
16 KiB
C++
630 lines
16 KiB
C++
//*********************************************************************
|
|
//* Microsoft Windows **
|
|
//* Copyright(c) Microsoft Corp., 1999 **
|
|
//*********************************************************************
|
|
//
|
|
// LANGUAGE.CPP - Header for the implementation of CLanguage
|
|
//
|
|
// HISTORY:
|
|
//
|
|
// 1/27/99 a-jaswed Created.
|
|
//
|
|
|
|
#include "precomp.h"
|
|
#include "msobmain.h"
|
|
#include "language.h"
|
|
#include "appdefs.h"
|
|
#include "dispids.h"
|
|
|
|
#define DEFAULT_BUFFER_SIZE BYTES_REQUIRED_BY_CCH(2048)
|
|
|
|
DISPATCHLIST LanguageExternalInterface[] =
|
|
{
|
|
{L"get_NumOfRegions", DISPID_GETNUMOFREGIONS },
|
|
{L"get_RegionName", DISPID_GETREGIONNAME },
|
|
{L"get_RegionIndex", DISPID_GETREGIONINDEX },
|
|
{L"set_RegionIndex", DISPID_SETREGIONINDEX },
|
|
{L"get_NumOfLangs", DISPID_GETNUMOFLANGS },
|
|
{L"get_LangName", DISPID_GETLANGNAME },
|
|
{L"get_LangIndex", DISPID_GETLANGINDEX },
|
|
{L"set_LangIndex", DISPID_SETLANGINDEX },
|
|
{L"get_NumOfKeyboardLayouts", DISPID_GETNUMOFKEYLAYOUTS },
|
|
{L"get_KeyboardLayoutName", DISPID_GETKEYNAME },
|
|
{L"get_KeyboardLayoutIndex", DISPID_GETKEYLAYOUTINDEX },
|
|
{L"set_KeyboardLayoutIndex", DISPID_SETKEYLAYOUTINDEX },
|
|
{L"get_RebootState", DISPID_LANGUAGE_GETREBOOTSTATE },
|
|
{L"SaveSettings", DISPID_LANGUAGE_SAVESETTINGS },
|
|
{L"get_PhoneCountries", DISPID_GETPHONECOUNTRIES }
|
|
};
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompareNameLookUpElements()
|
|
//
|
|
// Synopsis: Function to compare names used by sort
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
int __cdecl CompareNameLookUpElements(const void *e1, const void *e2)
|
|
{
|
|
|
|
LPNAMELOOKUPELEMENT pCUE1 = (LPNAMELOOKUPELEMENT)e1;
|
|
LPNAMELOOKUPELEMENT pCUE2 = (LPNAMELOOKUPELEMENT)e2;
|
|
|
|
return CompareString(LOCALE_USER_DEFAULT, 0,
|
|
pCUE1->pszName,
|
|
-1,
|
|
pCUE2->pszName,
|
|
-1) - 2;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::CLanguage
|
|
CLanguage::CLanguage()
|
|
{
|
|
WCHAR szINIPath[MAX_PATH] = L"";
|
|
WCHAR Answer[MAX_PATH];
|
|
|
|
|
|
// Init member vars
|
|
m_cRef = 0;
|
|
m_lRebootState = LANGUAGE_REBOOT_NEVER;
|
|
|
|
m_poliRegions = NULL;
|
|
m_lRegionTotal = 0;
|
|
m_lRegionDefault = -1;
|
|
|
|
m_poliLangs = NULL;
|
|
m_lLangTotal = 0;
|
|
m_lLangDefault = -1;
|
|
|
|
m_poliKeyboards = NULL;
|
|
m_lKeyboardLayoutTotal = 0;
|
|
m_lKeyboardLayoutDefault = -1;
|
|
|
|
GetCanonicalizedPath(szINIPath, INI_SETTINGS_FILENAME);
|
|
|
|
m_DefaultRegion = GetPrivateProfileInt(
|
|
OPTIONS_SECTION,
|
|
DEFAULT_REGION,
|
|
0,
|
|
szINIPath
|
|
);
|
|
|
|
GetPrivateProfileString(
|
|
OPTIONS_SECTION,
|
|
DEFAULT_LANGUAGE,
|
|
L"",
|
|
Answer,
|
|
MAX_PATH,
|
|
szINIPath
|
|
);
|
|
m_DefaultLanguage = wcstoul(Answer, NULL, 16);
|
|
|
|
GetPrivateProfileString(
|
|
OPTIONS_SECTION,
|
|
DEFAULT_KEYBOARD,
|
|
L"",
|
|
Answer,
|
|
MAX_PATH,
|
|
szINIPath
|
|
);
|
|
m_DefaultKeyboard = wcstoul(Answer, NULL, 16);
|
|
|
|
SetupGetGeoOptions(
|
|
m_DefaultRegion,
|
|
&m_poliRegions,
|
|
(LPDWORD) &m_lRegionTotal,
|
|
(LPDWORD) &m_lRegionDefault
|
|
);
|
|
MYASSERT( m_poliRegions );
|
|
|
|
SetupGetLocaleOptions(
|
|
m_DefaultLanguage,
|
|
&m_poliLangs,
|
|
(LPDWORD) &m_lLangTotal,
|
|
(LPDWORD) &m_lLangDefault
|
|
);
|
|
MYASSERT( m_poliLangs );
|
|
|
|
SetupGetKeyboardOptions(
|
|
m_DefaultKeyboard,
|
|
&m_poliKeyboards,
|
|
(LPDWORD) &m_lKeyboardLayoutTotal,
|
|
(LPDWORD) &m_lKeyboardLayoutDefault);
|
|
MYASSERT( m_poliKeyboards );
|
|
|
|
// The current index should be the defaults.
|
|
//
|
|
m_lRegionIndex = m_lRegionDefault;
|
|
m_lLangIndex = m_lLangDefault;
|
|
m_lKeyboardLayoutIndex = m_lKeyboardLayoutDefault;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::~CLanguage
|
|
CLanguage::~CLanguage()
|
|
{
|
|
if ( m_poliRegions )
|
|
SetupDestroyLanguageList( m_poliRegions, m_lRegionTotal );
|
|
if ( m_poliLangs )
|
|
SetupDestroyLanguageList( m_poliLangs, m_lLangTotal );
|
|
if ( m_poliKeyboards )
|
|
SetupDestroyLanguageList( m_poliKeyboards, m_lKeyboardLayoutTotal );
|
|
|
|
MYASSERT(m_cRef == 0);
|
|
}
|
|
|
|
HRESULT CLanguage::get_NumOfRegions(long* plVal)
|
|
{
|
|
*plVal = m_lRegionTotal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::get_NumOfKeyboardLayouts(long* plVal)
|
|
{
|
|
*plVal = m_lKeyboardLayoutTotal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::get_RegionName(long lIndex, BSTR* pbstrVal)
|
|
{
|
|
|
|
if ( lIndex >= m_lRegionTotal )
|
|
return E_FAIL;
|
|
|
|
// *pbstrVal = SysAllocString(m_pRegionNameLookUp[lIndex].pszName);
|
|
*pbstrVal = SysAllocString( m_poliRegions[lIndex].Name );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::get_KeyboardLayoutName(long lIndex, BSTR* pbstrVal)
|
|
{
|
|
|
|
if ( lIndex >= m_lKeyboardLayoutTotal )
|
|
return E_FAIL;
|
|
|
|
// *pbstrVal = SysAllocString(m_pKeyboardNameLookUp[lIndex].pszName);
|
|
*pbstrVal = SysAllocString( m_poliKeyboards[lIndex].Name );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::get_RebootState(long* plVal)
|
|
{
|
|
*plVal = m_lRebootState;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::SaveSettings()
|
|
{
|
|
// Only save the settings if they changed.
|
|
//
|
|
if ( ( m_lRegionIndex >= 0 ) &&
|
|
( m_lLangIndex >= 0 ) &&
|
|
( m_lKeyboardLayoutIndex >= 0 ) &&
|
|
m_poliRegions &&
|
|
m_poliLangs &&
|
|
m_poliKeyboards
|
|
)
|
|
//( m_lRegionDefault != m_lRegionIndex ) ||
|
|
//( m_lKeyboardLayoutDefault != m_lKeyboardLayoutIndex ) )
|
|
{
|
|
if (SetupSetIntlOptions(
|
|
m_poliRegions[m_lRegionIndex].Id,
|
|
m_poliLangs[m_lLangIndex].Id,
|
|
m_poliKeyboards[m_lKeyboardLayoutIndex].Id
|
|
))
|
|
{
|
|
// BUGBUG: The return value from SetIntlOptions on Win9x is
|
|
// interpreted as a reboot state. How do we determine reboot state
|
|
// on Whistler?
|
|
// Now the defaults are what is currently saved.
|
|
//
|
|
m_lRegionDefault = m_lRegionIndex;
|
|
m_lLangDefault = m_lLangIndex;
|
|
m_lKeyboardLayoutDefault = m_lKeyboardLayoutIndex;
|
|
}
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
////////////////////////////////////////////////
|
|
//// GET / SET :: RegionIndex
|
|
////
|
|
HRESULT CLanguage::get_RegionIndex(long* plVal)
|
|
{
|
|
*plVal = m_lRegionIndex;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::set_RegionIndex(long lVal)
|
|
{
|
|
m_lRegionIndex = lVal;
|
|
// m_lRegionIndex = m_pRegionNameLookUp[lVal].nIndex;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
////////////////////////////////////////////////
|
|
//// GET / SET :: KeyboardLayoutIndex
|
|
////
|
|
HRESULT CLanguage::get_KeyboardLayoutIndex(long* plVal)
|
|
{
|
|
*plVal = m_lKeyboardLayoutIndex;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CLanguage::set_KeyboardLayoutIndex(long lVal)
|
|
{
|
|
m_lKeyboardLayoutIndex = lVal;
|
|
// m_lKeyboardLayoutIndex = m_pKeyboardNameLookUp[lVal].nIndex;;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////
|
|
/////// IUnknown implementation
|
|
///////
|
|
///////
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::QueryInterface
|
|
STDMETHODIMP CLanguage::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
// must set out pointer parameters to NULL
|
|
*ppvObj = NULL;
|
|
|
|
if ( riid == IID_IUnknown)
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IUnknown*)this;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
if (riid == IID_IDispatch)
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IDispatch*)this;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
// Not a supported interface
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::AddRef
|
|
STDMETHODIMP_(ULONG) CLanguage::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::Release
|
|
STDMETHODIMP_(ULONG) CLanguage::Release()
|
|
{
|
|
return --m_cRef;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////
|
|
/////// IDispatch implementation
|
|
///////
|
|
///////
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::GetTypeInfo
|
|
STDMETHODIMP CLanguage::GetTypeInfo(UINT, LCID, ITypeInfo**)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::GetTypeInfoCount
|
|
STDMETHODIMP CLanguage::GetTypeInfoCount(UINT* pcInfo)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::GetIDsOfNames
|
|
STDMETHODIMP CLanguage::GetIDsOfNames(REFIID riid,
|
|
OLECHAR** rgszNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID* rgDispId)
|
|
{
|
|
|
|
HRESULT hr = DISP_E_UNKNOWNNAME;
|
|
rgDispId[0] = DISPID_UNKNOWN;
|
|
|
|
for (int iX = 0; iX < sizeof(LanguageExternalInterface)/sizeof(DISPATCHLIST); iX ++)
|
|
{
|
|
if(lstrcmp(LanguageExternalInterface[iX].szName, rgszNames[0]) == 0)
|
|
{
|
|
rgDispId[0] = LanguageExternalInterface[iX].dwDispID;
|
|
hr = NOERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set the disid's for the parameters
|
|
if (cNames > 1)
|
|
{
|
|
// Set a DISPID for function parameters
|
|
for (UINT i = 1; i < cNames ; i++)
|
|
rgDispId[i] = DISPID_UNKNOWN;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// CLanguage::Invoke
|
|
HRESULT CLanguage::Invoke
|
|
(
|
|
DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS* pdispparams,
|
|
VARIANT* pvarResult,
|
|
EXCEPINFO* pexcepinfo,
|
|
UINT* puArgErr
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
switch(dispidMember)
|
|
{
|
|
case DISPID_GETNUMOFREGIONS:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETNUMOFREGIONS\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
get_NumOfRegions(&(pvarResult->lVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETREGIONINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETREGIONINDEX\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
get_RegionIndex(&(pvarResult->lVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_SETREGIONINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_SETREGIONINDEX\n");
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0])
|
|
set_RegionIndex(pdispparams[0].rgvarg[0].lVal);
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETREGIONNAME:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETREGIONNAME\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_BSTR;
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0])
|
|
get_RegionName(pdispparams[0].rgvarg[0].lVal, &(pvarResult->bstrVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
// BUGBUG: Need to Lang processing to syssetup.dll
|
|
case DISPID_GETNUMOFLANGS:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETNUMOFFLANGS\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
pvarResult->lVal = m_lLangTotal;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETLANGINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETLANGINDEX\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
pvarResult->lVal = m_lLangIndex;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_SETLANGINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_SETLANGINDEX\n");
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0]) {
|
|
m_lLangIndex = pdispparams[0].rgvarg[0].lVal;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETLANGNAME:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETLANGNAME\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_BSTR;
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0]) {
|
|
|
|
long lIndex = pdispparams[0].rgvarg[0].lVal;
|
|
|
|
// BUGBUG: What if lIndex < 0??
|
|
if ( lIndex >= m_lLangTotal )
|
|
return E_FAIL;
|
|
|
|
pvarResult->bstrVal = SysAllocString( m_poliLangs[lIndex].Name );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case DISPID_GETNUMOFKEYLAYOUTS:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETNUMOFKEYLAYOUTS\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
get_NumOfKeyboardLayouts(&(pvarResult->lVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETKEYLAYOUTINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETKEYLAYOUTINDEX\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
get_KeyboardLayoutIndex(&(pvarResult->lVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_SETKEYLAYOUTINDEX:
|
|
{
|
|
|
|
TRACE(L"DISPID_SETKEYLAYOUTINDEX\n");
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0])
|
|
set_KeyboardLayoutIndex(pdispparams[0].rgvarg[0].lVal);
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETKEYNAME:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETKEYNAME\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_BSTR;
|
|
|
|
if(pdispparams && &pdispparams[0].rgvarg[0])
|
|
get_KeyboardLayoutName(pdispparams[0].rgvarg[0].lVal, &(pvarResult->bstrVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_LANGUAGE_GETREBOOTSTATE:
|
|
{
|
|
|
|
TRACE(L"DISPID_LANGUAGE_GETREBOOTSTATE\n");
|
|
|
|
if(pvarResult)
|
|
{
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_I4;
|
|
|
|
get_RebootState(&(pvarResult->lVal));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_LANGUAGE_SAVESETTINGS:
|
|
{
|
|
|
|
TRACE(L"DISPID_LANGUAGE_SAVESETTINGS\n");
|
|
|
|
SaveSettings();
|
|
break;
|
|
}
|
|
|
|
case DISPID_GETPHONECOUNTRIES:
|
|
{
|
|
|
|
TRACE(L"DISPID_GETPHONECOUNTRIES");
|
|
|
|
if(pvarResult)
|
|
{
|
|
WCHAR PhoneInfName[MAX_PATH];
|
|
|
|
GetOOBEMUIPath( PhoneInfName );
|
|
lstrcat( PhoneInfName, L"\\phone.inf" );
|
|
|
|
VariantInit(pvarResult);
|
|
V_VT(pvarResult) = VT_BSTR;
|
|
|
|
pvarResult->bstrVal = SysAllocString(
|
|
SetupReadPhoneList( PhoneInfName ) );
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = DISP_E_MEMBERNOTFOUND;
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|