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.
 
 
 
 
 
 

392 lines
9.8 KiB

//
// imecls.cpp
//
#include "private.h"
#include "imecls.h"
DBG_ID_INSTANCE(CSysImeClassWnd);
DBG_ID_INSTANCE(CSysImeClassWndArray);
#define IMECLASSNAME TEXT("ime")
//////////////////////////////////////////////////////////////////////////////
//
// misc func
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// CheckExistingImeClassWnd
//
//----------------------------------------------------------------------------
BOOL CheckExistingImeClassWnd(SYSTHREAD *psfn)
{
#ifdef USE_IMECLASS_SUBCLASS
if (!psfn->prgImeClassWnd)
{
HWND hwnd = NULL;
DWORD dwCurThreadId = GetCurrentThreadId();
while (hwnd = FindWindowEx(NULL, hwnd, IMECLASSNAME, NULL))
{
DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
if (dwThreadId != dwCurThreadId)
continue;
CSysImeClassWnd *picw = new CSysImeClassWnd();
picw->Init(hwnd);
}
}
if (!psfn->prgImeClassWnd)
return TRUE;
if (GetFocus())
psfn->prgImeClassWnd->StartSubclass();
#endif
return TRUE;
}
//+---------------------------------------------------------------------------
//
// UninitImeClassWndOnProcess
//
//----------------------------------------------------------------------------
BOOL UninitImeClassWndOnProcess()
{
HWND hwnd = NULL;
DWORD dwCurProcessId = GetCurrentProcessId();
while (hwnd = FindWindowEx(NULL, hwnd, IMECLASSNAME, NULL))
{
DWORD dwProcessId;
DWORD dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId != dwCurProcessId)
continue;
//
// Set the wndproc pointer back to original WndProc.
//
// some other subclass window may keep my WndProc pointer.
// but msctf.dll may be unloaded from memory so we don't want to
// call him to set the wndproc pointer back to our Wndproc pointer.
// The pointer will be bogus.
//
WNDPROC pfn = (WNDPROC)GetClassLongPtr(hwnd, GCLP_WNDPROC);
if (pfn != (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC))
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)pfn);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSysImeClassWnd
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSysImeClassWnd::CSysImeClassWnd()
{
Dbg_MemSetThisNameID(TEXT("CSysImeClassWnd"));
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CSysImeClassWnd::~CSysImeClassWnd()
{
if (IsWindow(_hwnd))
{
Stop();
if (_pfn)
{
//
// Set the wndproc pointer back to original WndProc.
//
// some other subclass window may keep my WndProc pointer.
// but msctf.dll may be unloaded from memory so we don't want to
// call him to set the wndproc pointer back to our Wndproc pointer.
// The pointer will be bogus.
//
WNDPROC pfnOrgImeWndProc;
pfnOrgImeWndProc = (WNDPROC)GetClassLongPtr(_hwnd, GCLP_WNDPROC);
SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)pfnOrgImeWndProc);
_pfn = NULL;
}
}
}
//+---------------------------------------------------------------------------
//
// IsImeClassWnd
//
//----------------------------------------------------------------------------
BOOL CSysImeClassWnd::IsImeClassWnd(HWND hwnd)
{
char szCls[6];
if (!GetClassName(hwnd, szCls, sizeof(szCls)))
return FALSE;
return lstrcmpi(szCls, IMECLASSNAME) ? FALSE : TRUE;
}
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
BOOL CSysImeClassWnd::Init(HWND hwnd)
{
SYSTHREAD *psfn = GetSYSTHREAD();
if (psfn == NULL)
return FALSE;
if (!psfn->prgImeClassWnd)
{
psfn->prgImeClassWnd = new CSysImeClassWndArray();
if (!psfn->prgImeClassWnd)
return FALSE;
}
CSysImeClassWnd **ppicw = psfn->prgImeClassWnd->Append(1);
if (!ppicw)
return FALSE;
*ppicw = this;
_hwnd = hwnd;
_pfn = NULL;
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Start
//
//----------------------------------------------------------------------------
void CSysImeClassWnd::Start()
{
Assert(IsWindow(_hwnd));
if (_pfn)
return;
_pfn = (WNDPROC)SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc);
}
//+---------------------------------------------------------------------------
//
// Stop
//
//----------------------------------------------------------------------------
void CSysImeClassWnd::Stop()
{
Assert(IsWindow(_hwnd));
WNDPROC pfnCur;
if (!_pfn)
return;
//
// unfortunately, we can not restore the wndproc pointer always.
// someone else subclassed it after we did.
//
pfnCur = (WNDPROC)GetWindowLongPtr(_hwnd, GWLP_WNDPROC);
if (pfnCur == WndProc)
{
SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)_pfn);
_pfn = NULL;
}
}
//+---------------------------------------------------------------------------
//
// WndProc
//
//----------------------------------------------------------------------------
LRESULT CSysImeClassWnd::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet;
SYSTHREAD *psfn = GetSYSTHREAD();
if (!psfn || !psfn->prgImeClassWnd)
{
Assert(0);
return 0;
}
CSysImeClassWnd *_this = psfn->prgImeClassWnd->Find(hwnd);
if (!_this)
{
#ifdef DEBUG
if ((uMsg != WM_DESTROY) && (uMsg != WM_NCDESTROY))
{
Assert(0);
}
#endif
return 0;
}
WNDPROC pfn = _this->_pfn;
if (!pfn)
{
Assert(0);
return 0;
}
switch (uMsg)
{
#if 0
//
// we have a fall back logic to set the original window proc back
// if we can not restore the window proc correctly.
// so we don't have to do paranoid subclassing here.
//
case WM_IME_SELECT:
case WM_IME_SETCONTEXT:
_this->Stop();
lRet = CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
_this->Start();
return lRet;
#endif
case WM_IME_NOTIFY:
if ((wParam == IMN_SETOPENSTATUS) ||
(wParam == IMN_SETCONVERSIONMODE))
OnIMENotify();
break;
case WM_DESTROY:
lRet = CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
psfn->prgImeClassWnd->Remove(_this);
return lRet;
}
return CallWindowProc(pfn, hwnd, uMsg, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////////////
//
// CSysImeClassWndArray
//
//////////////////////////////////////////////////////////////////////////////
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSysImeClassWndArray::CSysImeClassWndArray()
{
Dbg_MemSetThisNameID(TEXT("CSysImeClassWndArray"));
}
//+---------------------------------------------------------------------------
//
// StartSubClass
//
//----------------------------------------------------------------------------
BOOL CSysImeClassWndArray::StartSubclass()
{
for (int i = 0; i < Count(); i++)
{
CSysImeClassWnd *picw = Get(i);
picw->Start();
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// StopSubClass
//
//----------------------------------------------------------------------------
BOOL CSysImeClassWndArray::StopSubclass()
{
for (int i = 0; i < Count(); i++)
{
CSysImeClassWnd *picw = Get(i);
picw->Stop();
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Find
//
//----------------------------------------------------------------------------
CSysImeClassWnd *CSysImeClassWndArray::Find(HWND hwnd)
{
for (int i = 0; i < Count(); i++)
{
CSysImeClassWnd *picw = Get(i);
if (picw->GetWnd() == hwnd)
return picw;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Remove
//
//----------------------------------------------------------------------------
void CSysImeClassWndArray::Remove(CSysImeClassWnd *picw)
{
for (int i = 0; i < Count(); i++)
{
if (picw == Get(i))
{
CPtrArray<CSysImeClassWnd>::Remove(i, 1);
delete picw;
break;
}
}
}
//+---------------------------------------------------------------------------
//
// RemoveAll
//
//----------------------------------------------------------------------------
void CSysImeClassWndArray::RemoveAll()
{
for (int i = 0; i < Count(); i++)
{
CSysImeClassWnd *picw = Get(i);
delete picw;
}
Clear();
}