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.
 
 
 
 
 
 

2662 lines
70 KiB

#include "private.h"
#include "globals.h"
#include "regsvr.h"
#include "catutil.h"
#include "cregkey.h"
#include "assembly.h"
#include "immxutil.h"
#include "osver.h"
#include "internat.h"
#include "cicmutex.h"
#include "imelist.h"
#include "tim.h"
extern CCicMutex g_mutexAsm;
extern char g_szAsmListCache[];
extern HRESULT g_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum);
//+---------------------------------------------------------------------------
//
// TF_GetLangIcon
//
//+---------------------------------------------------------------------------
HICON WINAPI TF_GetLangIcon(WORD langid , WCHAR *psz, UINT cchMax)
{
if (psz)
{
SYSTHREAD *psfn = GetSYSTHREAD();
CAssemblyList *pAsmList;
*psz = L'\0';
if (psfn && (pAsmList = EnsureAssemblyList(psfn)))
{
CAssembly *pAsm = pAsmList->FindAssemblyByLangId(langid);
if (pAsm)
{
StringCchCopyW(psz, cchMax, pAsm->GetLangName());
}
}
}
return InatCreateIcon(langid);
}
//----------------------------------------------------------------------------
//
// GetSubstituteHKLfromKey
//
//----------------------------------------------------------------------------
HKL GetSubstituteHKLfromKey(CMyRegKey *pkey, LANGID langid)
{
char sz[16];
if (pkey->QueryValueCch(sz, c_szSubstitutehKL, ARRAYSIZE(sz)) != S_OK)
return NULL;
HKL hkl = NULL;
if ((sz[0] == '0') && ((sz[1] == 'X') || (sz[1] == 'x')))
{
hkl = (HKL)IntToPtr(AsciiToNum(&sz[2]));
if (LOWORD(HandleToLong(hkl)) != langid)
{
//
// bad substitution.
//
Assert(0);
hkl = 0;
}
}
return hkl;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAssembly
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CAssembly::CAssembly(LANGID langid)
{
_langid = langid;
if (IsOnNT())
{
if (!GetLocaleInfoW(MAKELCID(langid, SORT_DEFAULT),
LOCALE_SLANGUAGE,
_szLangName,
ARRAYSIZE(_szLangName)))
{
StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language");
}
else
{
_szLangName[ARRAYSIZE(_szLangName)-1] = 0; // in case GetLocaleInfoW truncates
}
}
else
{
char szLangName[64];
if (GetLocaleInfo(MAKELCID(langid, SORT_DEFAULT),
LOCALE_SLANGUAGE,
szLangName,
sizeof(szLangName)))
{
szLangName[ARRAYSIZE(szLangName)-1] = 0; // in case GetLocaleInfoW truncates
StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), AtoW(szLangName));
}
else
{
StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language");
}
}
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CAssembly::~CAssembly()
{
}
//+---------------------------------------------------------------------------
//
// IsFEIMEActive()
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsFEIMEActive()
{
int i;
if (IsFELangId(GetLangId()))
{
for (i = 0; i < Count(); i++)
{
ASSEMBLYITEM *pItem = GetItem(i);
if (pItem->fActive && IsPureIMEHKL(pItem->hkl))
{
Assert(IsEqualGUID(pItem->clsid, GUID_NULL));
return TRUE;
}
}
}
#ifdef CHECKFEIMESELECTED
if (_fUnknownFEIMESelected)
return TRUE;
#endif CHECKFEIMESELECTED
return FALSE;
}
//+---------------------------------------------------------------------------
//
// FindItemByCategory
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindItemByCategory(REFGUID catid)
{
int nCnt = _rgAsmItem.Count();
int i;
if (IsEqualGUID(catid, GUID_NULL))
return NULL;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (IsEqualGUID(pItemTmp->catid, catid))
return pItemTmp;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// FindActiveKeyboardItem
//
// Why do you call this if there is no FocusDIM? You should not do.
// fActive is not reliable if there is no FocusDIM.
// Ser SetFocusDIMForAssembly(BOOL fSetFocus) in profiles.cpp. we don't
// change fActive but switch hKL when the focus moves to non DIM control.
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindActiveKeyboardItem()
{
int nCnt = _rgAsmItem.Count();
int i;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled)
continue;
if (!pItemTmp->fActive)
continue;
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
return pItemTmp;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// FindKeyboardLayoutItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindKeyboardLayoutItem(HKL hkl)
{
int nCnt = _rgAsmItem.Count();
int i;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (!IsEqualGUID(pItemTmp->clsid, GUID_NULL))
continue;
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) &&
(pItemTmp->hkl == hkl))
{
return pItemTmp;
}
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// FindItemByCategory2
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledItemByCategory(REFGUID catid)
{
int nCnt = _rgAsmItem.Count();
int i;
if (IsEqualGUID(catid, GUID_NULL))
return FALSE;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (!IsEqualGUID(pItemTmp->catid, catid) && pItemTmp->fEnabled)
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// IsEnabledItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledItem()
{
int nCnt = _rgAsmItem.Count();
int i;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (pItemTmp->fEnabled)
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// FindPureKbdTipItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::FindPureKbdTipItem()
{
int nCnt = _rgAsmItem.Count();
int i;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) && !IsPureIMEHKL(pItemTmp->hkl))
return pItemTmp;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// IsNonCiceroItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsNonCiceroItem()
{
int nCnt = _rgAsmItem.Count();
int i;
BOOL fFound = FALSE;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled)
continue;
if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
continue;
if (IsEqualGUID(pItemTmp->clsid, GUID_NULL))
{
if (IsFELangId(LOWORD((DWORD)(LONG_PTR)(HKL)pItemTmp->hkl)))
{
if (!IsPureIMEHKL(pItemTmp->hkl))
{
// Assert(0);
continue;
}
}
return TRUE;
}
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// IsEnabled
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabled(SYSTHREAD *psfn)
{
CThreadInputMgr *ptim;
ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
if (!ptim || !ptim->_GetFocusDocInputMgr())
return IsNonCiceroItem() ? TRUE : FALSE;
return IsEnabledKeyboardItem(psfn);
}
//+---------------------------------------------------------------------------
//
// IsEnabledKeyboardItem
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsEnabledKeyboardItem(SYSTHREAD *psfn)
{
int nCnt = _rgAsmItem.Count();
int i;
BOOL fFound = FALSE;
for (i = 0; i < nCnt; i++)
{
ASSEMBLYITEM *pItemTmp;
pItemTmp = _rgAsmItem.GetPtr(i);
if (!pItemTmp->fEnabled)
continue;
if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
continue;
fFound = TRUE;
break;
}
return fFound;
}
//+---------------------------------------------------------------------------
//
// RebuildSubstitutedHKLList
//
//----------------------------------------------------------------------------
void CAssembly::RebuildSubstitutedHKLList()
{
int i;
_rghklSubstituted.Clear();
for (i = 0; i < Count(); i++)
{
ASSEMBLYITEM *pItem = GetItem(i);
if (!pItem->fEnabled)
continue;
if (!pItem->hklSubstitute)
continue;
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
!IsEqualGUID(pItem->clsid, GUID_NULL))
{
HKL *phkl = _rghklSubstituted.Append(1);
if (phkl)
*phkl = pItem->hklSubstitute;
}
}
}
//+---------------------------------------------------------------------------
//
// IsSubstitutedHKL
//
//----------------------------------------------------------------------------
BOOL CAssembly::IsSubstitutedHKL(HKL hkl)
{
int nCnt = _rghklSubstituted.Count();
int i;
for (i = 0; i < nCnt; i++)
{
HKL *phkl = _rghklSubstituted.GetPtr(i);
if (*phkl == hkl)
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// GetSubstituteItem
//
//----------------------------------------------------------------------------
ASSEMBLYITEM *CAssembly::GetSubstituteItem(HKL hKL)
{
int i;
BOOL fCheckActive = TRUE;
TryAgain:
for (i = 0; i < Count(); i++)
{
ASSEMBLYITEM *pItem = GetItem(i);
if (!pItem->fEnabled)
continue;
if (!pItem->hklSubstitute)
continue;
if (fCheckActive)
{
if (!pItem->fActive)
continue;
}
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
!IsEqualGUID(pItem->clsid, GUID_NULL))
{
if (hKL == pItem->hklSubstitute)
{
return pItem;
}
}
}
if (fCheckActive)
{
fCheckActive = FALSE;
goto TryAgain;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////////
//
// CDefaultProfiles
//
// This class is a database for the default profiles and this database is
// created from HKCU\Software\Microsoft\CTF\TIP
//
// however we need to respect the system default hKL setting. If the keyboard
// tip's profile has a substitute hKL and this is not the system default hKL
// we use the system default hKL as a default profile.
//
//////////////////////////////////////////////////////////////////////////////
class CDefaultProfiles
{
public:
CDefaultProfiles(LANGID langid)
{
_langid = langid;
}
~CDefaultProfiles()
{
_rgDefProfiles.Clear();
}
BOOL Init(HKL *phkl);
BOOL FilterProfiles(CAssembly *pAsm);
typedef struct tag_DEFAULTPROFILE
{
GUID catid;
CLSID clsid;
GUID guidProfile;
HKL hkl;
} DEFAULTPROFILE;
BOOL GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl);
BOOL Append(GUID catid, CLSID clsid, GUID guidProfile, HKL hkl)
{
DEFAULTPROFILE defpro;
DEFAULTPROFILE *pdefpro;
int i;
for (i = 0; i < _rgDefProfiles.Count(); i++)
{
pdefpro = _rgDefProfiles.GetPtr(i);
if (!pdefpro)
{
Assert(0);
return FALSE;
}
if (IsEqualGUID(catid, pdefpro->catid))
return FALSE;
}
defpro.catid = catid;
defpro.clsid = clsid;
defpro.guidProfile = guidProfile;
defpro.hkl = hkl;
pdefpro = _rgDefProfiles.Append(1);
if (!pdefpro)
return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro));
return TRUE;
}
private:
BOOL GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro);
LANGID _langid;
CStructArray<DEFAULTPROFILE> _rgDefProfiles;
};
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::Init(HKL *phkl)
{
CMyRegKey key;
DWORD dw;
char szKey[256];
char szName[CLSID_STRLEN + 1];
HKL hklDef = GetSystemDefaultHKL();
BOOL fFoundKeyboardIteminDefLang = FALSE;
DEFAULTPROFILE defpro;
DEFAULTPROFILE *pdefpro;
DWORD dwIndex;
StringCopyArray(szKey, c_szAsmKey);
StringCatArray(szKey, "\\");
StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey)-lstrlen(szKey), "0x%08x", _langid);
if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK)
goto Exit;
dwIndex = 0;
while (key.EnumKey(dwIndex, szKey, ARRAYSIZE(szKey)) == S_OK)
{
CMyRegKey subkey;
if (subkey.Open(key, szKey, KEY_READ) != S_OK)
goto Next;
StringAToCLSID(szKey, &defpro.catid);
//
// retreive tip clsid.
//
if (subkey.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK)
goto Next;
StringAToCLSID(szName, &defpro.clsid);
//
// retreive guid profile
//
if (subkey.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK)
goto Next;
StringAToCLSID(szName, &defpro.guidProfile);
if (subkey.QueryValue(dw, c_szKeyboardLayout) != S_OK)
goto Next;
//
// check the hkl from registry is valid or not.
//
defpro.hkl = (HKL)IntToPtr(dw);
if (defpro.hkl)
{
int i = 0;
BOOL fFound = FALSE;
while(phkl[i])
{
if (defpro.hkl == phkl[i])
{
fFound = TRUE;
break;
}
i++;
}
if (!fFound)
goto Next;
}
//
// if the system default hKL does not matched with
// the substite hKL of this profile, this profile can not be
// default profile. Instead the system default hKL became a
// default profile item.
//
if ((LOWORD(HandleToLong(hklDef)) == _langid) &&
IsEqualGUID(defpro.catid, GUID_TFCAT_TIP_KEYBOARD))
{
char szTmp[256];
HKL hklSubstitute = NULL;
fFoundKeyboardIteminDefLang = TRUE;
if (InitProfileRegKeyStr(szTmp,
ARRAYSIZE(szTmp),
defpro.clsid,
_langid,
defpro.guidProfile))
{
CMyRegKey keySubstitute;
if (keySubstitute.Open(HKEY_LOCAL_MACHINE, szTmp, KEY_READ) == S_OK)
{
hklSubstitute = GetSubstituteHKLfromKey(&keySubstitute, _langid);
}
}
// Removed Chinese specific code for bug#427476
if (IsEqualGUID(defpro.clsid, GUID_NULL) ||
(hklSubstitute && (hklSubstitute != hklDef)))
{
defpro.clsid = CLSID_NULL;
defpro.guidProfile = GUID_NULL;
defpro.hkl = hklDef;
}
}
pdefpro = _rgDefProfiles.Append(1);
if (!pdefpro)
return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro));
#ifdef DEBUG
{
char szDbgCatid[CLSID_STRLEN + 1];
char szDbgClsid[CLSID_STRLEN + 1];
char szDbgguidProfile[CLSID_STRLEN + 1];
CLSIDToStringA(defpro.catid, szDbgCatid);
CLSIDToStringA(defpro.clsid, szDbgClsid);
CLSIDToStringA(defpro.guidProfile, szDbgguidProfile);
TraceMsg(TF_GENERAL, "CDefaultProfiles:: langid %08x", _langid);
TraceMsg(TF_GENERAL, " catid %s", szDbgCatid);
TraceMsg(TF_GENERAL, " clsid %s", szDbgClsid);
TraceMsg(TF_GENERAL, " guidProfile %s", szDbgguidProfile);
TraceMsg(TF_GENERAL, " hkl %08x", (DWORD)HandleToLong(defpro.hkl));
}
#endif
Next:
dwIndex++;
}
Exit:
if (LOWORD(HandleToLong(hklDef)) == _langid)
{
if (!fFoundKeyboardIteminDefLang)
{
//
// Check if the default hkl is a substitute hKL of a TIP's
// profile.
//
if (!GetSubstitutedItem(hklDef, &defpro))
{
//
// we could not find TIP profile. Use this hkl as a default
// item.
//
defpro.catid = GUID_TFCAT_TIP_KEYBOARD;
defpro.clsid = CLSID_NULL;
defpro.guidProfile = GUID_NULL;
defpro.hkl = hklDef;
}
pdefpro = _rgDefProfiles.Append(1);
if (!pdefpro)
return FALSE;
memcpy(pdefpro, &defpro, sizeof(defpro));
}
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// GetSubstitutedItem
//
// this function walks HKLM\Software\Microsoft\CTF\TIPs to find the
// TIP profile that uses hklSub as its substitute hKL.
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro)
{
CMyRegKey key;
DWORD dwIndex;
TCHAR szKey[256];
TCHAR szSubKey[256];
TCHAR szLangKey[256];
TCHAR szValue[256];
StringCopyArray(szKey, c_szCTFTIPKey);
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK)
{
return FALSE;
}
// get all profiles from LanguageProfile registry.
//
dwIndex = 0;
while (key.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
{
CMyRegKey subkey;
CLSID clsid;
StringAToCLSID(szSubKey, &clsid);
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK)
goto Next0;
if (subkey.Open(key, szSubKey, KEY_READ) != S_OK)
goto Next0;
DWORD dwIndexLang = 0;
while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK)
{
CMyRegKey langkey;
LANGID langid;
if ((szLangKey[0] != '0') ||
((szLangKey[1] != 'X') && (szLangKey[1] != 'x')))
goto Next1;
langid = (LANGID)AsciiToNum(&szLangKey[2]);
//
// The language ID does not meet the given hklSub.
//
if (langid != LANGIDFROMHKL(hklSub))
goto Next1;
if (langkey.Open(subkey, szLangKey, KEY_READ) != S_OK)
goto Next1;
DWORD dwProfileIndex = 0;
while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
{
GUID guidProfile;
CRegKeyMUI keyProfile;
if (!StringAToCLSID(szValue, &guidProfile))
goto Next2;
if (keyProfile.Open(langkey, szValue, KEY_READ) == S_OK)
{
if (hklSub == GetSubstituteHKLfromKey(&keyProfile, langid))
{
//
// ok, we found it. Assume it is Keyboard category.
//
pdefpro->catid = GUID_TFCAT_TIP_KEYBOARD;
pdefpro->clsid = clsid;
pdefpro->guidProfile = guidProfile;
pdefpro->hkl = 0;
return TRUE;
}
}
Next2:
dwProfileIndex++;
}
Next1:
dwIndexLang++;
}
Next0:
dwIndex++;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// FilterProfiles
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::FilterProfiles(CAssembly *pAsm)
{
int i;
int j;
Assert(_langid == pAsm->GetLangId());
for (i = _rgDefProfiles.Count() - 1; i >= 0 ; i--)
{
DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i);
if (!pdefpro)
{
Assert(0);
return FALSE;
}
BOOL fFound = FALSE;
for (j = 0; j < pAsm->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
if (IsEqualGUID(pItem->catid, pdefpro->catid) &&
IsEqualGUID(pItem->clsid, pdefpro->clsid) &&
IsEqualGUID(pItem->guidProfile, pdefpro->guidProfile))
{
fFound = pItem->fEnabled ? TRUE : FALSE;
break;
}
}
if (!fFound)
{
_rgDefProfiles.Remove(i, 1);
}
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// GetDefaultProfile
//
//----------------------------------------------------------------------------
BOOL CDefaultProfiles::GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl)
{
int i;
for (i = 0; i < _rgDefProfiles.Count(); i++)
{
DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i);
if (!pdefpro)
{
Assert(0);
return FALSE;
}
if (IsEqualGUID(catid, pdefpro->catid))
{
*pclsid = pdefpro->clsid;
*pguidProfile = pdefpro->guidProfile;
*phkl = pdefpro->hkl;
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAssemblyList
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CAssemblyList::CAssemblyList()
{
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CAssemblyList::~CAssemblyList()
{
ClearAsms();
}
//+---------------------------------------------------------------------------
//
// ClearAsms
//
//----------------------------------------------------------------------------
void CAssemblyList::ClearAsms()
{
int i = 0;
while (i < _rgAsm.Count())
{
CAssembly *pAsm = _rgAsm.Get(i);
delete pAsm;
i++;
}
_rgAsm.Clear();
}
//+---------------------------------------------------------------------------
//
// FindAndCreateNewAssembly
//
//----------------------------------------------------------------------------
extern INATSYMBOL symInatSymbols[];
CAssembly *CAssemblyList::FindAndCreateNewAssembly(CPtrArray<CAssembly> *prgAsm, CPtrArray<CAssembly> *prgNutralAsm, LANGID langid)
{
CPtrArray<CAssembly> *prg;
if (langid == 0xffff)
prg = prgNutralAsm;
else
prg = (langid & 0xfc00) ? prgAsm : prgNutralAsm;
//
// do we already have pAsm?
//
CAssembly *pAsm = FindAssemblyByLangIdInArray(prg, langid);
if (pAsm == NULL)
{
pAsm = new CAssembly(langid);
if (pAsm)
{
CAssembly **ppAsm;
ppAsm = prg->Append(1);
if (ppAsm)
{
*ppAsm = pAsm;
}
else
{
delete pAsm;
pAsm = NULL;
}
}
}
return pAsm;
}
//+---------------------------------------------------------------------------
//
// AttachOriginalAssembly
//
//----------------------------------------------------------------------------
void CAssemblyList::AttachOriginalAssembly(CPtrArray<CAssembly> *prgAsmOrg)
{
int i;
int j;
SYSTHREAD *psfn = GetSYSTHREAD();
CAssembly *pAsm = FindAssemblyByLangId(GetCurrentAssemblyLangId(psfn));
if (!pAsm)
return;
for (i = 0; i < prgAsmOrg->Count(); i++)
{
CAssembly *pAsmOrg = prgAsmOrg->Get(i);
if (pAsm->GetLangId() == pAsmOrg->GetLangId())
{
for (j = 0; j < pAsm->Count(); j++)
{
int nId;
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
if (!pItem)
continue;
nId = pAsmOrg->Find(pItem);
if (nId >= 0)
{
ASSEMBLYITEM *pItemOrg;
pItemOrg = pAsmOrg->GetItem(nId);
BOOL fPrevActive = pItem->fActive;
if (pItemOrg && (pItemOrg->fActive))
{
pItem->fActive = pItemOrg->fActive;
//
// we need to deactivate all other item in the
// category.
//
if (!fPrevActive && pItem->fActive)
{
for (int k = 0; k < pAsm->Count(); k++)
{
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k);
if (pItemTemp == pItem)
continue;
if (IsEqualGUID(pItemTemp->catid, pItem->catid))
pItemTemp->fActive = FALSE;
}
}
}
}
}
break;
}
}
}
//+---------------------------------------------------------------------------
//
// Load
//
//----------------------------------------------------------------------------
extern INATSYMBOL symInatSymbols[];
HRESULT CAssemblyList::Load()
{
CMyRegKey key;
CMyRegKey key2;
int nhkl;
HKL *lphkl = NULL;
HKL hklList[2];
LANGID langid;
int i;
ASSEMBLYITEM ai;
DWORD dwIndex;
CAssembly *pAsm = NULL;
BOOL fFoundActiveNoCic = FALSE;
CPtrArray<CAssembly> *prgNutralAsm = NULL;
IEnumGUID *pEnumCat = NULL;
HRESULT hr;
int nAsmCnt;
CPtrArray<CAssembly> rgAsmOrg;
TCHAR szKey[256];
TCHAR szSubKey[256];
TCHAR szLangKey[256];
TCHAR szValue[256];
//
// backup original assembly in rgAsmOrg;
//
for (i = 0; i < _rgAsm.Count(); i++)
{
pAsm = _rgAsm.Get(i);
if (pAsm)
{
CAssembly **ppAsm = rgAsmOrg.Append(1);
if (ppAsm)
*ppAsm = pAsm;
}
}
_rgAsm.Clear();
#ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
if (IsUpdated())
{
ClearUpdatedFlag();
}
else
#endif
{
if (LoadFromCache())
{
AttachOriginalAssembly(&rgAsmOrg);
hr = S_OK;
goto Exit;
}
}
prgNutralAsm = new CPtrArray<CAssembly>;
if (!prgNutralAsm)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
StringCopyArray(szKey, c_szCTFTIPKey);
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK)
{
hr = E_FAIL;
goto Exit;
}
nhkl = GetKeyboardLayoutList(0, NULL);
if (nhkl)
{
lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1));
GetKeyboardLayoutList(nhkl, lphkl);
}
else
{
hklList[0] = GetKeyboardLayout(NULL);
hklList[1] = NULL;
lphkl = hklList;
}
//
// clear Category cache
//
CCategoryMgr::FreeCatCache();
hr = g_EnumItemsInCategory(GUID_TFCAT_CATEGORY_OF_TIP, &pEnumCat);
if (FAILED(hr))
{
goto Exit;
}
//
// Check all TIP CLSID under HKCU is valid TIP CLSIDs.
//
StringCopyArray(szKey, c_szCTFTIPKey);
if (key2.Open(HKEY_CURRENT_USER, szKey, KEY_ALL_ACCESS) == S_OK)
{
dwIndex = 0;
while (key2.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
{
CMyRegKey subkey;
dwIndex++;
//
// if we could not open the subkey (CLSID key) in HKLM,
// HKCU should not have the subkey.
//
if (subkey.Open(key, szSubKey, KEY_READ) != S_OK)
{
if (key2.RecurseDeleteKey(szSubKey) == S_OK)
dwIndex--;
}
}
}
//
// get all profiles from LanguageProfile registry.
//
dwIndex = 0;
while (key.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
{
CMyRegKey subkey;
CLSID clsid;
StringAToCLSID(szSubKey, &clsid);
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK)
continue;
if (subkey.Open(key, szSubKey, KEY_READ) == S_OK)
{
DWORD dwIndexLang = 0;
while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK)
{
CMyRegKey langkey;
if ((szLangKey[0] != '0') ||
((szLangKey[1] != 'X') && (szLangKey[1] != 'x')))
goto Next;
langid = (LANGID)AsciiToNum(&szLangKey[2]);
//
// do we already have pAsm?
//
pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid);
if (pAsm == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
if (langkey.Open(subkey, szLangKey, KEY_READ) == S_OK)
{
DWORD dwProfileIndex = 0;
while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
{
GUID guidProfile;
CRegKeyMUI keyProfile;
if (!StringAToCLSID(szValue, &guidProfile))
goto NextKey;
memset(&ai, 0, ai.GetAlignSize());
ai.InitIconIndex();
ai.clsid = clsid;
ai.fActive = FALSE;
GetTIPCategory(clsid, &ai.catid, pEnumCat);
ai.guidProfile = guidProfile;
ai.fEnabled = FALSE;
// we will assign proper hKL later.
ai.hkl = NULL;
hr = keyProfile.Open(langkey, szValue, KEY_READ);
if (hr == S_OK)
{
ai.hklSubstitute = GetSubstituteHKLfromKey(&keyProfile, langid);
hr = keyProfile.QueryMUIValueW(ai.szProfile,
c_szDescriptionW,
c_szMUIDescriptionW,
ARRAYSIZE(ai.szProfile));
DWORD dw;
if ((keyProfile.QueryValue(dw, c_szDisabledOnTransitory) == S_OK) && dw)
ai.fDisabledOnTransitory = TRUE;
}
if (hr == S_OK)
pAsm->Add(&ai);
NextKey:
dwProfileIndex++;
}
}
Next:
dwIndexLang++;
}
}
}
//
// check all assembly has KEYBOARD category.
// If not, we load keyboard layout for the assembly.
//
nAsmCnt = _rgAsm.Count();
for (i = 0; i < nAsmCnt; i++)
{
BOOL bLoaded;
int j;
CAssembly *pAsmTmp = _rgAsm.Get(i);
if (pAsmTmp->FindItemByCategory(GUID_TFCAT_TIP_KEYBOARD))
continue;
LANGID langidTmp = pAsmTmp->GetLangId();
//
// we can not use IsEnabledItem() here. We have not updated
// the enbaled status of Items yet.
//
// if (!pAsmTmp->IsEnabledItem())
// continue;
//
BOOL fFound = FALSE;
for (j = 0; j < pAsmTmp->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsmTmp->GetItem(j);
if (pItem->fEnabled ||
IsEnabledLanguageProfileFromReg(pItem->clsid,
pAsmTmp->_langid,
pItem->guidProfile))
{
fFound = TRUE;
break;
}
}
if (!fFound)
continue;
//
// Load a proper keyboard layout....
//
GetProperHKL(langidTmp, lphkl, &bLoaded);
if (bLoaded)
{
//
// re-create the keyboard layout list.
//
nhkl = GetKeyboardLayoutList(0, NULL);
if (nhkl)
{
if (lphkl && (lphkl != hklList))
cicMemFree(lphkl);
lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1));
GetKeyboardLayoutList(nhkl, lphkl);
}
else
{
hklList[0] = GetKeyboardLayout(NULL);
hklList[1] = NULL;
lphkl = hklList;
}
}
}
//
// get all hKLs.
//
if (lphkl)
{
HKL *lphklCur = lphkl;
DWORD *pdwPreload = NULL;
UINT uPreloadCnt;
//
// load preload layouts infomation.
//
uPreloadCnt = GetPreloadListForNT(NULL, 0);
if (uPreloadCnt)
{
Assert(IsOnNT());
pdwPreload = new DWORD[uPreloadCnt];
if (pdwPreload)
GetPreloadListForNT(pdwPreload, uPreloadCnt);
}
while (*lphklCur)
{
BOOL fIsDefaultHKLinPreload = FALSE;
WORD wLayout = HIWORD((DWORD)(LONG_PTR)(*lphklCur));
langid = (LANGID)((DWORD)(LONG_PTR)(*lphklCur) & 0x0000ffff);
//
// do we already have pAsm?
//
pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid);
if (pAsm == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
//
// See Preload to check if this default hKL is real dummy or not.
// The default FE layout is not a dummy hKL if it is in Preload
// list.
//
if (IsFELangId(langid))
{
if (wLayout == (WORD)langid)
{
UINT uCur;
for (uCur = 0; uCur < uPreloadCnt; uCur++)
{
//
// check if we have 0x00000411 in preload.
//
if (pdwPreload[uCur] == (DWORD)(wLayout))
{
fIsDefaultHKLinPreload = TRUE;
break;
}
}
}
else if ((wLayout & 0xf000) != 0xe000)
{
fIsDefaultHKLinPreload = TRUE;
}
}
//
// we skip dummy FE hKL.
//
if (!IsFELangId(langid) ||
IsPureIMEHKL(*lphklCur) ||
fIsDefaultHKLinPreload ||
!pAsm->FindPureKbdTipItem())
{
TF_InitMlngInfo();
MLNGINFO mlInfo;
if (pAsm == NULL)
pAsm = new CAssembly(langid);
memset(&ai, 0, ai.GetAlignSize());
ai.InitIconIndex();
ai.hkl = *lphklCur;
ai.clsid = GUID_NULL;
ai.catid = GUID_TFCAT_TIP_KEYBOARD;
ai.fActive = FALSE;
ai.fEnabled = TRUE;
if (GetMlngInfoByhKL(ai.hkl, &mlInfo) == -1)
mlInfo.SetDesc(L"");
ai.guidProfile = GUID_NULL;
StringCopyArrayW(ai.szProfile, mlInfo.GetDesc());
pAsm->Add(&ai);
}
lphklCur++;
}
if (pdwPreload)
delete pdwPreload;
}
//
// filter neutral langiage assembly
//
while (prgNutralAsm->Count())
{
pAsm = prgNutralAsm->Get(0);
langid = pAsm->GetLangId();
Assert((langid == 0xffff) || !(langid & 0xFC00));
//
// find valid langid ang merge there.
//
for (i = 0; i < _rgAsm.Count(); i++)
{
CAssembly *pAsmDst = _rgAsm.Get(i);
LANGID langidDst = pAsmDst->GetLangId();
Assert(langidDst & 0xFC00);
//
// we found a valid langid.
//
if ((langid == 0xffff) ||
(PRIMARYLANGID(langid) == PRIMARYLANGID(langidDst)))
{
int j;
for (j = 0; j < pAsm->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
pItem->fActive = FALSE;
pItem->fActiveNoCic = FALSE;
// we will assign proper hKL later.
pItem->hkl = NULL;
pAsmDst->Add(pItem);
}
}
}
//
// we don't need a neutral lang assembly.
//
prgNutralAsm->Remove(0, 1);
delete pAsm;
}
//
// It is time to decide this profile should be activated by default.
//
for (i = 0; i < _rgAsm.Count(); i++)
{
int j;
pAsm = _rgAsm.Get(i);
CDefaultProfiles defProfiles(pAsm->_langid);
defProfiles.Init(lphkl);
//
// update Enable status.
//
// this must be done before filtering the default profiles.
// disabled item should not be the default proble.
//
for (j = 0; j < pAsm->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
if (!pItem->fEnabled)
pItem->fEnabled = IsEnabledLanguageProfileFromReg(pItem->clsid,
pAsm->_langid,
pItem->guidProfile);
}
//
// check if the default profile is enabled.
//
defProfiles.FilterProfiles(pAsm);
for (j = 0; j < pAsm->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
CLSID clsid;
GUID guidProfile;
HKL hkl;
//
// If the item is not categoried, we activate it.
//
if (IsEqualGUID(pItem->catid, GUID_NULL))
{
pItem->fActive = TRUE;
continue;
}
//
// if this item is enabled, load proper hkl.
//
if (pItem->fEnabled &&
IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
!pItem->hkl)
pItem->hkl = GetProperHKL(pAsm->_langid, lphkl, NULL);
//
// init fActivate to false by default.
//
pItem->fActive = FALSE;
if (pItem->fEnabled)
{
//
// GetDefaultProfile() may return NULL in hkl if someone calls
// ITfInputProcessorProfiles::SetDefaultLanguageProfile() method
// from outside. We should not check hkl value then.
//
if (defProfiles.GetDefaultProfile(pItem->catid,
&clsid,
&guidProfile,
&hkl))
{
//
// ok this item is not default profile.
//
if (!IsEqualCLSID(pItem->clsid, clsid) ||
!IsEqualCLSID(pItem->guidProfile, guidProfile) ||
(hkl && (pItem->hkl != hkl)))
continue;
pItem->fActive = TRUE;
}
else if (defProfiles.Append(pItem->catid,
pItem->clsid,
pItem->guidProfile,
pItem->hkl))
{
pItem->fActive = TRUE;
}
}
}
#ifdef DEBUG
for (j = 0; j < pAsm->Count(); j++)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(j);
int k;
if (!pItem->fActive)
{
UINT uCnt = 0;
for (k = 0; k < pAsm->Count(); k++)
{
ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k);
if (IsEqualGUID(pItemTemp->catid, pItem->catid))
uCnt += (pItemTemp->fActive) ? 1 : 0;
}
Assert(uCnt <= 1);
}
}
#endif
}
//
// we should create cache before attaching the original assembly active
// status.
// AttachOriginalAssembly() is just for the current thread.
//
if (IsAsmCache())
CreateCache();
if (rgAsmOrg.Count())
AttachOriginalAssembly(&rgAsmOrg);
hr = S_OK;
Exit:
if (lphkl && (lphkl != hklList))
cicMemFree(lphkl);
if (prgNutralAsm)
{
Assert(!prgNutralAsm->Count())
delete prgNutralAsm;
}
if (pEnumCat)
pEnumCat->Release();
//
// clean up original assemblies.
//
for (i = 0; i < rgAsmOrg.Count(); i++)
{
pAsm = rgAsmOrg.Get(i);
delete pAsm;
}
rgAsmOrg.Clear();
return hr;
}
//+---------------------------------------------------------------------------
//
// GetDefaultAssembly
//
//----------------------------------------------------------------------------
CAssembly *CAssemblyList::GetDefaultAssembly()
{
CAssembly *pAsm = NULL;
int nAsmCnt = _rgAsm.Count();
DWORD langid;
if (!nAsmCnt)
return NULL;
langid = (LANGID)LOWORD(HandleToLong(GetSystemDefaultHKL()));
if (!langid)
return _rgAsm.Get(0);
int nCurAsm = 0;
while (nCurAsm < nAsmCnt)
{
CAssembly *pAsmTmp = _rgAsm.Get(nCurAsm);
if (pAsmTmp->_langid == langid)
{
pAsm = pAsmTmp;
break;
}
nCurAsm++;
}
if (!pAsm)
pAsm = _rgAsm.Get(0);
return pAsm;
}
//+---------------------------------------------------------------------------
//
// CreateCache
//
//----------------------------------------------------------------------------
typedef struct tag_ASSEMBLY_ROOT
{
DWORD dwAssemblyCount;
// ASSEMBLYHDR[]
static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLY_ROOT)); }
} ASSEMBLY_ROOT;
typedef struct tag_ASSEMBLYHDR
{
DWORD dwCnt;
LANGID langid;
// ASSEMBLYITEM[]
static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLYHDR)); }
} ASSEMBLYHDR;
CCicFileMapping *g_pcfmAsmCache = NULL;
BOOL EnsureAsmCacheFileMap()
{
if (!g_pcfmAsmCache)
g_pcfmAsmCache = new CCicFileMapping();
return g_pcfmAsmCache ? TRUE : FALSE;
}
BOOL UninitAsmCacheFileMap()
{
if (g_pcfmAsmCache)
{
delete g_pcfmAsmCache;
g_pcfmAsmCache = NULL;
}
return TRUE;
}
BOOL IsAsmCache()
{
return g_pcfmAsmCache ? TRUE : FALSE;
}
//+---------------------------------------------------------------------------
//
// CreateCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::CreateCache()
{
int nAsmCnt = _rgAsm.Count();
int nCurAsm = 0;
HANDLE hfm = NULL;
DWORD cbSize = 0;
BYTE *pv;
BOOL bRet = FALSE;
CCicSecAttr sa;
if (!g_pcfmAsmCache)
return TRUE;
if (!g_pcfmAsmCache->Enter())
return FALSE;
g_pcfmAsmCache->Close();
g_pcfmAsmCache->Init(g_szAsmListCache, &g_mutexAsm);
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
cbSize += ASSEMBLY_ROOT::GetAlignSize();
while (nCurAsm < nAsmCnt)
{
CAssembly *pAsm = _rgAsm.Get(nCurAsm);
cbSize += ASSEMBLYHDR::GetAlignSize();
cbSize += (pAsm->Count() * ASSEMBLYITEM::GetAlignSize());
nCurAsm++;
}
pv = (BYTE *)g_pcfmAsmCache->Create(sa, cbSize, NULL);
if (!pv)
goto Exit;
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
pasm_root->dwAssemblyCount = nAsmCnt;
pv += ASSEMBLY_ROOT::GetAlignSize();
nCurAsm = 0;
while (nCurAsm < nAsmCnt)
{
ASSEMBLYHDR *pAsmHdr;
CAssembly *pAsm = _rgAsm.Get(nCurAsm);
pAsmHdr = (ASSEMBLYHDR *)pv;
pAsmHdr->dwCnt = pAsm->Count();
pAsmHdr->langid = pAsm->GetLangId();
pv += ASSEMBLYHDR::GetAlignSize();
int nItemCnt = pAsm->Count();
int nCurItem = 0;
while (nCurItem < nItemCnt)
{
ASSEMBLYITEM *pItem = pAsm->GetItem(nCurItem);
memcpy(pv, pItem, ASSEMBLYITEM::GetAlignSize());
pv += ASSEMBLYITEM::GetAlignSize();
nCurItem++;
}
nCurAsm++;
}
bRet = TRUE;
Exit:
g_pcfmAsmCache->Leave();
return bRet;
}
//+---------------------------------------------------------------------------
//
// LoadFromCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::LoadFromCache()
{
HANDLE hfm = NULL;
BYTE *pv;
int nAsmCnt;
int nCurAsm = 0;
BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter())
return FALSE;
pv = (BYTE *)cfm.Open();
if (!pv)
goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
cfm.Flush(ASSEMBLY_ROOT::GetAlignSize());
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
nAsmCnt = pasm_root->dwAssemblyCount;
pv += ASSEMBLY_ROOT::GetAlignSize();
if (!nAsmCnt)
goto Exit;
while (nCurAsm < nAsmCnt)
{
ASSEMBLYHDR *pAsmHdr;
CAssembly *pAsm;
int nItemCnt;
int nCurItem = 0;
pAsmHdr = (ASSEMBLYHDR *)pv;
nItemCnt = pAsmHdr->dwCnt;
pAsm = new CAssembly(pAsmHdr->langid);
pv += ASSEMBLYHDR::GetAlignSize();
while (nCurItem < nItemCnt)
{
ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv;
pItem->InitIconIndex();
if (pAsm)
pAsm->Add(pItem);
pv += ASSEMBLYITEM::GetAlignSize();
nCurItem++;
}
if (pAsm)
{
CAssembly **ppAsm;
ppAsm = _rgAsm.Append(1);
if (ppAsm)
{
*ppAsm = pAsm;
}
else
{
delete pAsm;
}
}
nCurAsm++;
}
bRet = TRUE;
Exit:
cfm.Leave();
return bRet;
}
//+---------------------------------------------------------------------------
//
// InvalidCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::InvalidCache()
{
HANDLE hfm = NULL;
DWORD *pv;
BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter())
return FALSE;
pv = (DWORD *)cfm.Open();
if (!pv)
goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
if (pv)
{
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
pasm_root->dwAssemblyCount = 0;
cfm.Flush(ASSEMBLY_ROOT::GetAlignSize());
bRet = TRUE;
}
Exit:
cfm.Leave();
return bRet;
}
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssemblyForCache
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssemblyForCache(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile)
{
BYTE *pv;
int nAsmCnt;
int nCurAsm = 0;
BOOL bRet = FALSE;
CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
if (!cfm.Enter())
return FALSE;
pv = (BYTE *)cfm.Open();
if (!pv)
goto Exit;
//
// ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
//
// When calc next data struc pointer, should not use sizeof()
// because need adjust data alignment for 64/32bit on IA64.
// Please use GetAlignSize() method instead of sizeof().
//
ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
nAsmCnt = pasm_root->dwAssemblyCount;
pv += ASSEMBLY_ROOT::GetAlignSize();
if (!nAsmCnt)
goto Exit;
while (nCurAsm < nAsmCnt)
{
ASSEMBLYHDR *pAsmHdr;
int nItemCnt;
int nCurItem = 0;
pAsmHdr = (ASSEMBLYHDR *)pv;
BOOL fTargetLang = (pAsmHdr->langid == langid) ? TRUE : FALSE;
nItemCnt = pAsmHdr->dwCnt;
pv += ASSEMBLYHDR::GetAlignSize();
while (nCurItem < nItemCnt)
{
if (fTargetLang)
{
ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv;
if (IsEqualGUID(pItem->catid, catid))
{
if (IsEqualGUID(pItem->clsid, clsid) &&
IsEqualGUID(pItem->guidProfile, guidProfile) &&
(!hKL || (hKL == pItem->hkl)))
{
pItem->fActive = TRUE;
}
else
{
pItem->fActive = FALSE;
}
}
}
pv += ASSEMBLYITEM::GetAlignSize();
nCurItem++;
}
if (fTargetLang)
break;
nCurAsm++;
}
bRet = TRUE;
Exit:
cfm.Leave();
return bRet;
}
#ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
//+---------------------------------------------------------------------------
//
// IsUpdated
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::IsUpdated()
{
CMyRegKey key;
if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey, KEY_READ) != S_OK)
return FALSE;
char szName[16];
DWORD dwCnt = sizeof(szName);
if (key.QueryValue(szName, c_szUpdateProfile, &dwCnt) != S_OK)
return FALSE;
return (szName[0] == '1') ? TRUE : FALSE;
}
//+---------------------------------------------------------------------------
//
// ClearUpdatedFlag
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::ClearUpdatedFlag()
{
CMyRegKey key;
if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey) != S_OK)
return FALSE;
if (key.DeleteValue(c_szUpdateProfile) != S_OK)
return FALSE;
return TRUE;
}
#endif
//+---------------------------------------------------------------------------
//
// CheckLangSupport
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::CheckLangSupport(REFCLSID rclsid, LANGID langid)
{
CMyRegKey key;
TCHAR szKey[256];
TCHAR szLang[256];
int i = 0;
StringCopyArray(szKey, c_szCTFTIPKey);
CLSIDToStringA(rclsid, szKey + lstrlen(szKey));
StringCatArray(szKey, "\\");
StringCatArray(szKey, c_szLanguageProfileKey);
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) == S_OK)
{
CMyRegKey subkey;
//
// Check a valid language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(langid));
StringCopyArray(szKey, szLang);
if (subkey.Open(key, szKey, KEY_READ) == S_OK)
return TRUE;
//
// Check a primary language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(PRIMARYLANGID(langid)));
StringCopyArray(szKey, szLang);
if (subkey.Open(key, szKey, KEY_READ) == S_OK)
return TRUE;
//
// Check a neutral language id.
//
StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x0000ffff");
StringCopyArray(szKey, szLang);
if (subkey.Open(key, szKey, KEY_READ) == S_OK)
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// GetTIPCategory
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::GetTIPCategory(REFCLSID clsid, GUID *pcatid, IEnumGUID *pEnumCat)
{
HRESULT hr;
BOOL fFound = FALSE;
*pcatid = GUID_NULL;
hr = pEnumCat->Reset();
if (SUCCEEDED(hr))
{
GUID guidCat;
while (!fFound && (pEnumCat->Next(1, &guidCat, NULL) == S_OK))
{
IEnumGUID *pEnumTip;
hr = g_EnumItemsInCategory(guidCat, &pEnumTip);
if (SUCCEEDED(hr) && pEnumTip)
{
GUID guidTip;
while (!fFound && (pEnumTip->Next(1, &guidTip, NULL) == S_OK))
{
if (IsEqualGUID(clsid, guidTip))
{
*pcatid = guidCat;
fFound = TRUE;
}
}
pEnumTip->Release();
}
}
}
return fFound;
}
//+---------------------------------------------------------------------------
//
// GetDefaultTIPInAssembly
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::GetDefaultTIPInAssembly(LANGID langid, REFGUID catid, CLSID *pclsid, HKL *phKL, GUID *pguidProfile)
{
CMyRegKey key;
DWORD dw;
char szKey[256];
char szName[CLSID_STRLEN + 1];
StringCopyArray(szKey, c_szAsmKey);
StringCatArray(szKey, "\\");
StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid);
StringCatArray(szKey, "\\");
CLSIDToStringA(catid, szKey + lstrlen(szKey));
*pclsid = GUID_NULL;
if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK)
return FALSE;
if (key.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK)
return FALSE;
StringAToCLSID(szName, pclsid);
if (key.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK)
return FALSE;
StringAToCLSID(szName, pguidProfile);
if (phKL)
{
*phKL = NULL;
if (key.QueryValue(dw, c_szKeyboardLayout) != S_OK)
return FALSE;
*phKL = (HKL)IntToPtr(dw);
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssemblyInternal
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssemblyInternal(CAssembly *pAsm, ASSEMBLYITEM *pItem, BOOL fChangeDefault)
{
ASSEMBLYITEM *pItemSub = NULL;
BOOL bRet = FALSE;
Assert(!pItem->hkl || (pAsm->GetLangId() == LOWORD((DWORD)(LONG_PTR)(HKL)pItem->hkl)));
//
// If given hKL is substituted hKL, we set the original TIP as a default.
//
if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD))
{
#if 0
//
// Chienese platform special. We don't set the new default keyboard.
//
if (IsChinesePlatform())
{
return TRUE;
}
pItemSub = pAsm->GetSubstituteItem(pItem->hkl);
if (fChangeDefault)
{
//
// try to change the system default hKL.
//
// When TIP that has substitute HKL is selected.
// if the language of the system default hKL is same,
// set the hKL.
//
// When IME is selected.
// if the language of the system default hKL is same, set it.
//
HKL hklNewDef = IsPureIMEHKL(pItem->hkl) ? pItem->hkl : (IsPureIMEHKL(pItem->hklSubstitute) ? pItem->hklSubstitute : pItem->hkl);
if (!IsFELangId(LOWORD((WORD)(LONG_PTR)(HKL)pItem->hkl)) || hklNewDef)
{
HKL hklDef = GetSystemDefaultHKL();
if ((hklDef != hklNewDef) &&
(LOWORD((WORD)(LONG_PTR)hklDef) == LOWORD((WORD)(LONG_PTR)hklNewDef)))
{
SetSystemDefaultHKL(hklNewDef);
}
}
}
#else
HKL hklDef = GetSystemDefaultHKL();
if (pAsm->GetLangId() == LANGIDFROMHKL(hklDef))
{
//
// Now we can set the default layout directly from CPL instead of
// just set language(bug#353989)
//
return TRUE;
}
pItemSub = pAsm->GetSubstituteItem(pItem->hkl);
#endif
}
if (pItemSub)
{
bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(),
pItemSub->catid,
pItemSub->clsid,
pItemSub->hkl,
pItemSub->guidProfile);
}
else
{
bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(),
pItem->catid,
pItem->clsid,
pItem->hkl,
pItem->guidProfile);
}
return bRet;
}
//+---------------------------------------------------------------------------
//
// SetDefaultTIPInAssembly
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::SetDefaultTIPInAssembly(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile)
{
CMyRegKey key;
char szKey[256];
char szName[256];
StringCopyArray(szKey, c_szAsmKey);
StringCatArray(szKey, "\\");
StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid);
StringCatArray(szKey, "\\");
CLSIDToStringA(catid, szKey + lstrlen(szKey));
if (key.Create(HKEY_CURRENT_USER, szKey) != S_OK)
return FALSE;
CLSIDToStringA(clsid, szName);
if (key.SetValue(szName, c_szDefault) != S_OK)
return FALSE;
CLSIDToStringA(guidProfile, szName);
if (key.SetValue(szName, c_szProfile) != S_OK)
return FALSE;
if (key.SetValue((DWORD)(ULONG_PTR)hKL, c_szKeyboardLayout) != S_OK)
return FALSE;
return TRUE;
}
//+---------------------------------------------------------------------------
//
// IsFEDummyKL
//
//----------------------------------------------------------------------------
BOOL CAssemblyList::IsFEDummyKL(HKL hkl)
{
char szProfile[256];
char szDummyProfile[256];
static HKL hkl411Dummy = 0;
static HKL hkl404Dummy = 0;
static HKL hkl412Dummy = 0;
static HKL hkl804Dummy = 0;
HKL *phklDummy = NULL;
BOOL bRet = FALSE;
//
// we don't use DummyHKL under NT.
//
if (IsOnNT())
return FALSE;
switch (LANGIDFROMLCID(hkl))
{
case 0x411: phklDummy = &hkl411Dummy; break;
case 0x412: phklDummy = &hkl412Dummy; break;
case 0x404: phklDummy = &hkl404Dummy; break;
case 0x804: phklDummy = &hkl804Dummy; break;
default:
return FALSE;
}
if (!ImmGetDescription(hkl, szProfile, ARRAYSIZE(szProfile)))
{
return FALSE;
}
CicEnterCriticalSection(g_cs);
if (*phklDummy)
{
bRet = (*phklDummy == hkl) ? TRUE : FALSE;
}
else
{
StringCchPrintf(szDummyProfile, ARRAYSIZE(szDummyProfile), "hkl%04x", LOWORD((DWORD)(UINT_PTR)hkl));
if (!lstrcmp(szDummyProfile, szProfile))
{
*phklDummy = hkl;
bRet = TRUE;
}
}
CicLeaveCriticalSection(g_cs);
return bRet;
}
//+---------------------------------------------------------------------------
//
// CheckKeyboardLayoutReg
//
//
// Hack for IMM32 hard code for "kbdjp.kbd" for Japanese hKL.
// If ImmInstallIME() fails, we try it after patching registry key.
//
//----------------------------------------------------------------------------
HKL CheckKeyboardLayoutReg(LANGID langid)
{
CMyRegKey key;
DWORD dwIndex;
TCHAR szValue[MAX_PATH];
//
// This is just for Win9x Kor,CHT,CHS
//
if (IsOnNT())
return NULL;
if ((g_uACP != 936) && (g_uACP != 949) && (g_uACP != 950))
return NULL;
//
// This is for HKL0411 only.
//
if (langid != 0x0411)
return NULL;
if (key.Open(HKEY_LOCAL_MACHINE, c_szKeyboardLayoutKey, KEY_READ) != S_OK)
return NULL;
dwIndex = 0;
while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
{
CMyRegKey keyHKL;
TCHAR szName[13];
if (keyHKL.Open(key, szValue, KEY_ALL_ACCESS) != S_OK)
goto Next;
if (keyHKL.QueryValueCch(szName, c_szIMEFile, ARRAYSIZE(szName)) != S_OK)
goto Next;
if (!lstrcmpi(szName, "hkl0411.dll"))
{
//
// patch LayoutFile to kbdus.kbd and load the keyboard layout.
//
if (keyHKL.SetValue(c_szKbdUSName, c_szLayoutFile) != S_OK)
return NULL;
return LoadKeyboardLayout(szValue, KLF_NOTELLSHELL);
}
Next:
dwIndex++;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// GetProperHKL
//
//----------------------------------------------------------------------------
HKL CAssemblyList::GetProperHKL(LANGID langid, HKL *lphkl, BOOL *pfLoaded)
{
char szhkl[16];
HKL hkl = NULL;
BOOL fFELang = IsFELangId(langid) ? TRUE : FALSE;
if (pfLoaded)
*pfLoaded = FALSE;
if (lphkl)
{
while (*lphkl)
{
if (langid == (LANGID)((DWORD)(UINT_PTR)(*lphkl) & 0x0000ffff))
{
//
// Under FE language, we have a specialcase.
//
if (fFELang)
{
//
// Dummy HKL should be used.
//
if (IsIMEHKL(*lphkl))
{
if (IsFEDummyKL(*lphkl))
{
hkl = *lphkl;
break;
}
goto Next;
}
//
// We strongly want to use a primary hKL for FE.
//
if ((HIWORD((DWORD)(UINT_PTR)*lphkl) != langid))
goto Next;
}
hkl = *lphkl;
break;
}
Next:
lphkl++;
}
}
//
// if we could find any, return.
//
if (hkl)
return hkl;
if (!IsOnNT() && IsOnFE() && IsFELangId(langid))
{
char szSys[MAX_PATH];
char szDll[MAX_PATH];
char szLayout[16];
GetSystemDirectory(szSys, sizeof(szSys));
StringCchPrintf(szDll, ARRAYSIZE(szDll),"%s\\hkl%04x.dll", szSys, langid);
StringCchPrintf(szLayout, ARRAYSIZE(szLayout),"hkl%04x", langid);
hkl = ImmInstallIME(szDll, szLayout);
if (!hkl)
{
hkl = CheckKeyboardLayoutReg(langid);
if (hkl)
{
#if 0
RemoveFEDummyHKLFromPreloadReg(hkl);
#endif
goto Exit;
}
//
// error to load Dummy hKL.
// we just use a primary English language.
//
StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", 0x0409);
hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
}
#if 0
else
{
//
// check the dummy HKL from Preload section of registry and remove
// it since ImmInstallIME automatically add hkl to Preload section.
//
RemoveFEDummyHKLFromPreloadReg(hkl);
}
#endif
goto Exit;
}
StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", langid);
hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
//
// if we fail to create a hKL for langid, check this registry entry.
//
// HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\[langid]
//
// without the key, it fails to create a default keyboard layout.
//
Assert(LOWORD(hkl) == langid);
//
// if hkl has NULL value and the current langid is FE, then we try to add
// the default keyboard layout in the system.
//
if (IsFELangId(langid) && ((LOWORD(hkl) != langid) || IsPureIMEHKL(hkl)))
{
char szKey[256];
CMyRegKey key;
if (IsOn98orNT5())
StringCopyArray(szKey, c_szLocaleInfo);
else
StringCopyArray(szKey, c_szLocaleInfoNT4);
//
// see if the user has Administrative privileges by checking for
// write permission to the registry key(NLS path).
//
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_WRITE) != S_OK)
goto Exit;
else
{
StringCopyArray(szKey, c_szKeyboardLayoutKey);
StringCchPrintf(szhkl, ARRAYSIZE(szhkl), "%08x", langid);
StringCatArray(szKey, szhkl);
//
// create new keyboard layout registry key and value.
//
if (key.Create(HKEY_LOCAL_MACHINE, szKey) == S_OK)
{
char szKbdName[256];
if (IsOnNT())
StringCopyArray(szKbdName, c_szKbdUSNameNT);
else
StringCopyArray(szKbdName, c_szKbdUSName);
if (key.SetValue(szKbdName, c_szLayoutFile) == S_OK)
{
//
// now try to reload keyboard layout again.
//
hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
}
}
}
}
Exit:
if (hkl && pfLoaded)
*pfLoaded = TRUE;
return hkl;
}