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.
 
 
 
 
 
 

824 lines
21 KiB

//
// dam.cpp
//
#include "private.h"
#include "tlhelp32.h"
#include "globals.h"
#include "dam.h"
#include "tim.h"
#include "thdutil.h"
#include "timlist.h"
// get CLSID_STRLEN
#include "regsvr.h"
/* ff4619e8-ea5e-43e5-b308-11cd26ab6b3a */
const IID IID_CDisplayAttributeMgr = { 0xff4619e8, 0xea5e, 0x43e5, {0xb3, 0x08, 0x11, 0xcd, 0x26, 0xab, 0x6b, 0x3a} };
const TCHAR c_szDAMCacheKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\DisplayAttributeCache\\");
const TCHAR c_szDAMNumValue[] = TEXT("CheckNum");
CDispAttrGuidCache *g_pDispAttrGuidCache = NULL;
//
// from aimm1.2\win32\aimmdap.cpp
//
/* 503286E2-5D2A-4D3D-B0D1-EE50D843B79D */
const CLSID CLSID_CAImmDAP = {
0x503286E2,
0x5D2A,
0x4D3D,
{0xB0, 0xD1, 0xEE, 0x50, 0xD8, 0x43, 0xB7, 0x9D}
};
DBG_ID_INSTANCE(CDisplayAttributeMgr);
DBG_ID_INSTANCE(CEnumDisplayAttributeInfo);
//////////////////////////////////////////////////////////////////////////////
//
// CDispAttrGuidCache
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// StaticUnInit
//
// Caller must hold mutex.
//----------------------------------------------------------------------------
void CDispAttrGuidCache::StaticUnInit()
{
Assert(ISINDLLMAIN()); // for mutex
if (g_pDispAttrGuidCache)
delete g_pDispAttrGuidCache;
g_pDispAttrGuidCache = NULL;
}
//+---------------------------------------------------------------------------
//
// StaticInit
//
//----------------------------------------------------------------------------
void CDispAttrGuidCache::StaticInit()
{
CicEnterCriticalSection(g_cs);
if (!g_pDispAttrGuidCache)
{
g_pDispAttrGuidCache = new CDispAttrGuidCache();
if (g_pDispAttrGuidCache)
g_pDispAttrGuidCache->Load();
}
CicLeaveCriticalSection(g_cs);
}
//+---------------------------------------------------------------------------
//
// Add
//
//----------------------------------------------------------------------------
BOOL CDispAttrGuidCache::Add(REFCLSID clsid, REFGUID guid)
{
BOOL bRet = FALSE;
TfGuidAtom gaGuid;
TfGuidAtom gaClsid;
if (FAILED(MyRegisterGUID(clsid, &gaClsid)))
return bRet;
if (FAILED(MyRegisterGUID(guid, &gaGuid)))
return bRet;
CicEnterCriticalSection(g_cs);
if (!Get(gaGuid, NULL))
{
DISPATTRGUID *pGuid;
if (!_rgDispAttrGuid.Insert(0, 1))
{
goto Exit;
}
pGuid = _rgDispAttrGuid.GetPtr(0);
pGuid->clsid = clsid;
pGuid->gaClsid = gaClsid;
pGuid->guid = guid;
pGuid->gaGuid = gaGuid;
}
bRet = TRUE;
Exit:
CicLeaveCriticalSection(g_cs);
return bRet;
}
//+---------------------------------------------------------------------------
//
// Remove
//
//----------------------------------------------------------------------------
void CDispAttrGuidCache::Remove(TfGuidAtom guidatom)
{
int nCnt = _rgDispAttrGuid.Count();
int i;
for (i = 0; i < nCnt; i++)
{
DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(i);
if (pGuid->gaGuid == guidatom)
{
_rgDispAttrGuid.Remove(i, 1);
return;
}
}
}
//+---------------------------------------------------------------------------
//
// RemoveClsid
//
//----------------------------------------------------------------------------
void CDispAttrGuidCache::RemoveClsid(TfGuidAtom guidatom)
{
int nCnt = _rgDispAttrGuid.Count();
int i;
i = 0;
while (i < nCnt)
{
DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(i);
if (pGuid->gaClsid == guidatom)
{
_rgDispAttrGuid.Remove(i, 1);
nCnt--;
continue;
}
i++;
}
}
//+---------------------------------------------------------------------------
//
// Get
//
//----------------------------------------------------------------------------
BOOL CDispAttrGuidCache::Get(TfGuidAtom guidatom, DISPATTRGUID *pDisp)
{
BOOL bRet;
CicEnterCriticalSection(g_cs);
bRet = InternalGet(guidatom, pDisp);
CicLeaveCriticalSection(g_cs);
return bRet;
}
//+---------------------------------------------------------------------------
//
// InternalGet
//
//----------------------------------------------------------------------------
BOOL CDispAttrGuidCache::InternalGet(TfGuidAtom guidatom, DISPATTRGUID *pDisp)
{
int nCnt;
int i;
BOOL bRet = FALSE;
nCnt = _rgDispAttrGuid.Count();
DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(0);
for (i = 0; i < nCnt; i++)
{
if (pGuid->gaGuid == guidatom)
{
if (pDisp)
*pDisp = *pGuid;
bRet = TRUE;
goto Exit;
}
pGuid++;
}
Exit:
return bRet;
}
//+---------------------------------------------------------------------------
//
// IsClsid
//
//----------------------------------------------------------------------------
BOOL CDispAttrGuidCache::IsClsid(TfGuidAtom gaClsid)
{
BOOL bRet = FALSE;
int nCnt;
int i;
DISPATTRGUID *pGuid;
CicEnterCriticalSection(g_cs);
pGuid = _rgDispAttrGuid.GetPtr(0);
nCnt = _rgDispAttrGuid.Count();
for (i = 0; i < nCnt; i++)
{
if (pGuid->gaClsid == gaClsid)
{
bRet = TRUE;
break;
}
pGuid++;
}
CicLeaveCriticalSection(g_cs);
return bRet;
}
//+---------------------------------------------------------------------------
//
// Save
//
//----------------------------------------------------------------------------
HRESULT CDispAttrGuidCache::Save()
{
DWORD dw;
HKEY hKeyDAM;
DISPATTRGUID *pDAG;
int nCnt;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDAMCacheKey, 0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKeyDAM,
&dw) != ERROR_SUCCESS)
{
return E_FAIL;
}
nCnt = _rgDispAttrGuid.Count();
if (nCnt)
{
pDAG = _rgDispAttrGuid.GetPtr(0);
RegSetValueEx(hKeyDAM, NULL, 0, REG_BINARY,
(CONST BYTE *)pDAG, sizeof(DISPATTRGUID) * nCnt);
RegSetValueEx(hKeyDAM, c_szDAMNumValue, 0, REG_DWORD,
(LPBYTE)&nCnt, sizeof(DWORD));
}
else
{
RegDeleteValue(hKeyDAM, NULL);
RegDeleteValue(hKeyDAM, c_szDAMNumValue);
}
RegCloseKey(hKeyDAM);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Load
//
//----------------------------------------------------------------------------
HRESULT CDispAttrGuidCache::Load()
{
HKEY hKeyDAM;
HRESULT hr = E_FAIL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDAMCacheKey, 0,
KEY_READ, &hKeyDAM) != ERROR_SUCCESS)
{
return hr;
}
Assert(_rgDispAttrGuid.Count() == 0);
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
DWORD dwCntReg = 0;
//
// Issue: should be removed before release.
// we changed the size of structre so old chace does not match with
// new one. Check the size of structure.
//
if (RegQueryValueEx(hKeyDAM, c_szDAMNumValue, 0, &dwType,
(LPBYTE)&dwCntReg, &dwSize) != ERROR_SUCCESS)
dwCntReg = 0;
dwType = REG_BINARY;
if (RegQueryValueEx(hKeyDAM, NULL, 0, &dwType,
NULL, &dwSize) == ERROR_SUCCESS)
{
DWORD i;
DWORD dwCnt = dwSize / sizeof(DISPATTRGUID);
if (dwCnt != dwCntReg)
goto Exit;
_rgDispAttrGuid.Insert(0, dwCnt);
DISPATTRGUID *pDAG = _rgDispAttrGuid.GetPtr(0);
RegQueryValueEx(hKeyDAM, NULL, 0, &dwType, (BYTE *)pDAG, &dwSize);
for (i = 0; i < dwCnt; i++)
{
if (FAILED(MyRegisterGUID(pDAG[i].clsid, &pDAG[i].gaClsid)))
goto Exit;
if (FAILED(MyRegisterGUID(pDAG[i].guid, &pDAG[i].gaGuid)))
goto Exit;
}
}
hr = S_OK;
Exit:
RegCloseKey(hKeyDAM);
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CDisplayAttributeMgr
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CDisplayAttributeMgr::CDisplayAttributeMgr()
{
Dbg_MemSetThisNameID(TEXT("CDisplayAttributeMgr"));
_SetThis(this);
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CDisplayAttributeMgr::~CDisplayAttributeMgr()
{
int nCnt = _rgDaPrv.Count();
if (nCnt)
{
DAPROVIDERMAP *pDaPrv;
pDaPrv = _rgDaPrv.GetPtr(0);
while(nCnt--)
{
pDaPrv->pPrv->Release();
pDaPrv++;
}
}
_SetThis(NULL); // clear out singleton tls
}
//----------------------------------------------------------------------------
//
// OnUndateinfo
//
// Use kernel32 or ntdll directly to enumerate all threads, because
// we don't have global TIM list.
//
//----------------------------------------------------------------------------
HRESULT CDisplayAttributeMgr::OnUpdateInfo()
{
PostTimListMessage(TLF_TIMACTIVE,
0,
g_msgPrivate,
TFPRIV_UPDATEDISPATTR,
0);
return S_OK;
}
//----------------------------------------------------------------------------
//
// EnumThreadProc
//
//----------------------------------------------------------------------------
BOOL CDisplayAttributeMgr::EnumThreadProc(DWORD dwThread, DWORD dwProcessId, void *pv)
{
PostThreadMessage(dwThread, g_msgPrivate, TFPRIV_UPDATEDISPATTR, 0);
return FALSE;
}
//----------------------------------------------------------------------------
//
// EnumDisplayAttributeInfo
//
//----------------------------------------------------------------------------
HRESULT CDisplayAttributeMgr::EnumDisplayAttributeInfo(IEnumTfDisplayAttributeInfo **ppEnum)
{
CEnumDisplayAttributeInfo *pEnum;
if (!ppEnum)
return E_INVALIDARG;
pEnum = new CEnumDisplayAttributeInfo();
if (!pEnum)
return E_OUTOFMEMORY;
if (pEnum->Init())
*ppEnum = pEnum;
else
SafeReleaseClear(pEnum);
return pEnum ? S_OK : E_FAIL;
}
//----------------------------------------------------------------------------
//
// GetDisplayAttributeInfo
//
//----------------------------------------------------------------------------
HRESULT CDisplayAttributeMgr::GetDisplayAttributeInfo(REFGUID guid, ITfDisplayAttributeInfo **ppInfo, CLSID *pclsid)
{
CLSID clsid;
ITfDisplayAttributeProvider *pProvider;
HRESULT hr = E_FAIL;
StaticCacheInit();
if (ppInfo)
*ppInfo = NULL;
if (g_pDispAttrGuidCache)
{
DISPATTRGUID dag;
TfGuidAtom gaGuid;
if (FAILED(MyRegisterGUID(guid, &gaGuid)))
return hr;
if (g_pDispAttrGuidCache->Get(gaGuid, &dag))
{
if (ppInfo)
{
DAPROVIDERMAP *pDaPrv;
int i;
int nCnt = _rgDaPrv.Count();
BOOL bFound = FALSE;
for (i = 0; i < nCnt; i++)
{
pDaPrv = _rgDaPrv.GetPtr(i);
if (pDaPrv->gaClsid == dag.gaClsid)
{
Assert(pDaPrv->pPrv);
hr = pDaPrv->pPrv->GetDisplayAttributeInfo(guid, ppInfo);
bFound = TRUE;
break;
}
}
if (!bFound &&
SUCCEEDED(CoCreateInstance(dag.clsid,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfDisplayAttributeProvider,
(void**)&pProvider)))
{
hr = pProvider->GetDisplayAttributeInfo(guid, ppInfo);
if (_rgDaPrv.Insert(nCnt, 1))
{
pDaPrv = _rgDaPrv.GetPtr(nCnt);
pDaPrv->gaClsid = dag.gaClsid;
pDaPrv->pPrv = pProvider;
}
else
pProvider->Release();
}
}
else
{
hr = S_OK;
}
if (SUCCEEDED(hr))
{
if (pclsid)
*pclsid = dag.clsid;
return hr;
}
//
// someone removed DisplayAttribute Info. So we clear the cache.
//
g_pDispAttrGuidCache->Clear();
}
}
IEnumGUID *pEnumGUID;
if (FAILED(MyEnumItemsInCategory(GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &pEnumGUID)))
return E_FAIL;
DWORD dwIndex = 0;
BOOL fFound = FALSE;
CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
if (ptim == NULL)
goto Exit;
while (!fFound && (pEnumGUID->Next(1, &clsid, NULL) == S_OK))
{
if (!IsEqualCLSID(clsid, CLSID_CAImmDAP) &&
(ptim->_IsActiveInputProcessor(clsid) != S_OK))
continue;
//
// Issue:
//
// we may want to load only providers that are enabled in this
// thread. Use CIMEList to check if tips is enabled.
//
if (SUCCEEDED(CoCreateInstance(clsid,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfDisplayAttributeProvider,
(void**)&pProvider)))
{
IEnumTfDisplayAttributeInfo *pEnumDAI;
if (SUCCEEDED(pProvider->EnumDisplayAttributeInfo(&pEnumDAI)))
{
ITfDisplayAttributeInfo *pInfo;
while (pEnumDAI->Next(1, &pInfo, NULL) == S_OK)
{
GUID guidTemp;
if (SUCCEEDED(pInfo->GetGUID(&guidTemp)))
{
if (g_pDispAttrGuidCache)
g_pDispAttrGuidCache->Add(clsid, guidTemp);
if (IsEqualGUID(guidTemp, guid))
{
if (ppInfo)
*ppInfo = pInfo;
if (pclsid)
*pclsid = clsid;
fFound = TRUE;
hr = S_OK;
break;
}
}
pInfo->Release();
}
pEnumDAI->Release();
}
pProvider->Release();
}
}
Exit:
pEnumGUID->Release();
if (g_pDispAttrGuidCache)
g_pDispAttrGuidCache->Save();
return hr;
}
//----------------------------------------------------------------------------
//
// RegisterGUID
//
//----------------------------------------------------------------------------
HRESULT CDisplayAttributeMgr::_RegisterGUID(const TCHAR *pszKey, REFGUID rguid, WCHAR *pszDesc, ULONG cchDesc)
{
DWORD dw;
HKEY hKeyDAM;
HKEY hKeyItem;
TCHAR achGuid[CLSID_STRLEN+1];
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKeyDAM,
&dw) != ERROR_SUCCESS)
{
return E_FAIL;
}
CLSIDToStringA(rguid, achGuid);
if (RegCreateKeyEx(hKeyDAM, achGuid, 0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKeyItem,
&dw) == ERROR_SUCCESS)
{
int cchDescA = cchDesc * sizeof(WCHAR) + 1;
char *pszDescA = new char[cchDescA];
if (pszDescA)
{
cchDescA = WideCharToMultiByte(CP_ACP, 0,
pszDesc, wcslen(pszDesc),
pszDescA, cchDescA,
NULL, NULL);
*(pszDescA + cchDescA) = L'\0';
RegSetValueEx(hKeyItem, TEXT("Description"), 0, REG_SZ,
(CONST BYTE *)pszDescA, cchDescA);
delete pszDescA;
}
RegCloseKey(hKeyItem);
}
RegCloseKey(hKeyDAM);
return S_OK;
}
//----------------------------------------------------------------------------
//
// UnregisterGUID
//
//----------------------------------------------------------------------------
HRESULT CDisplayAttributeMgr::_UnregisterGUID(const TCHAR *pszKey, REFGUID rguid)
{
DWORD dw;
HKEY hKeyDAM;
TCHAR achGuid[CLSID_STRLEN+1];
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKeyDAM,
&dw) != ERROR_SUCCESS)
{
return E_FAIL;
}
CLSIDToStringA(rguid, achGuid);
RegDeleteKey(hKeyDAM, achGuid);
RegCloseKey(hKeyDAM);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//
// CEnumDisplayAttributeInfo
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo()
{
Dbg_MemSetThisNameID(TEXT("CEnumDisplayAttributeInfo"));
}
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
BOOL CEnumDisplayAttributeInfo::Init()
{
IEnumGUID *pEnumGUID;
CLSID clsid;
ULONG uDAMax;
BOOL fRet;
StaticCacheInit();
if (FAILED(MyEnumItemsInCategory(GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &pEnumGUID)))
return FALSE;
fRet = FALSE;
if ((_prgUnk = SUA_Alloc(1)) == NULL)
goto Exit;
_prgUnk->cRef = 1;
_prgUnk->cUnk = 0;
uDAMax = 1;
while (pEnumGUID->Next(1, &clsid, NULL) == S_OK)
{
ITfDisplayAttributeProvider *pProvider;
//
// Issue:
//
// we may want to load only providers that are enabled in this
// thread. Use CIMEList to check if tips is enabled.
//
if (SUCCEEDED(CoCreateInstance(clsid,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfDisplayAttributeProvider,
(void**)&pProvider)))
{
IEnumTfDisplayAttributeInfo *pEnum;
if (SUCCEEDED(pProvider->EnumDisplayAttributeInfo(&pEnum)))
{
ITfDisplayAttributeInfo *pInfo;
while (pEnum->Next(1, &pInfo, NULL) == S_OK)
{
GUID guidTemp;
if (SUCCEEDED(pInfo->GetGUID(&guidTemp)))
{
if (g_pDispAttrGuidCache)
g_pDispAttrGuidCache->Add(clsid, guidTemp);
}
if (_prgUnk->cUnk >= uDAMax)
{
// need a bigger array
uDAMax *= 2;
if (!SUA_ReAlloc(&_prgUnk, uDAMax))
{
pInfo->Release();
SUA_Release(_prgUnk);
_prgUnk = NULL;
goto Exit;
}
}
_prgUnk->rgUnk[_prgUnk->cUnk++] = pInfo;
}
pEnum->Release();
}
pProvider->Release();
}
}
if (uDAMax > _prgUnk->cUnk)
{
// free up unused mem
SUA_ReAlloc(&_prgUnk, _prgUnk->cUnk);
}
fRet = TRUE;
Exit:
pEnumGUID->Release();
if (g_pDispAttrGuidCache)
g_pDispAttrGuidCache->Save();
return fRet;
}