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.
413 lines
10 KiB
413 lines
10 KiB
//
|
|
// dllmain.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include "tim.h"
|
|
#include "imelist.h"
|
|
#include "utb.h"
|
|
#include "dam.h"
|
|
#include "catmgr.h"
|
|
#include "nuimgr.h"
|
|
#include "profiles.h"
|
|
#include "internat.h"
|
|
#include "acp2anch.h"
|
|
#include "cicmutex.h"
|
|
#include "strary.h"
|
|
#include "range.h"
|
|
#include "compart.h"
|
|
#include "marshal.h"
|
|
#include "timlist.h"
|
|
#include "gcompart.h"
|
|
#include "mui.h"
|
|
#include "anchoref.h"
|
|
#include "hotkey.h"
|
|
#include "lbaddin.h"
|
|
|
|
extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE, DWORD, LPVOID);
|
|
|
|
extern HINSTANCE g_hOle32;
|
|
|
|
extern CCicCriticalSectionStatic g_csDelayLoad;;
|
|
|
|
#ifdef DEBUG
|
|
void dbg_RangeDump(ITfRange *pRange);
|
|
#endif
|
|
|
|
extern void UninitThread(void);
|
|
|
|
extern void RegisterMarshalWndClass();
|
|
|
|
CCicMutex g_mutexLBES;
|
|
CCicMutex g_mutexCompart;
|
|
CCicMutex g_mutexAsm;
|
|
CCicMutex g_mutexLayouts;
|
|
CCicMutex g_mutexTMD;
|
|
extern void UninitLayoutMappedFile();
|
|
|
|
char g_szAsmListCache[MAX_PATH];
|
|
char g_szTimListCache[MAX_PATH];
|
|
char g_szLayoutsCache[MAX_PATH];
|
|
|
|
//
|
|
// Hack for Office10 BVT.
|
|
//
|
|
// MSACCESS 10 Debug version (CMallocSpy) shows MsgBox after DLL is detached
|
|
// from process.
|
|
// Showing MsgBox calls window Hook so Hook entry is called then.
|
|
// Need to check the DLL was already detached.
|
|
//
|
|
BOOL g_fDllProcessDetached = FALSE;
|
|
DWORD g_dwThreadDllMain = 0;
|
|
void InitStaticHooks();
|
|
|
|
BOOL g_bOnWow64;
|
|
|
|
|
|
BOOL gf_CRT_INIT = FALSE;
|
|
BOOL gfSharedMemory = FALSE;
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ProcessAttach
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL ProcessAttach(HINSTANCE hInstance)
|
|
{
|
|
CcshellGetDebugFlags();
|
|
|
|
Perf_Init();
|
|
|
|
#ifdef DEBUG
|
|
//
|
|
// Do you know how to link non-used function??
|
|
//
|
|
dbg_RangeDump(NULL);
|
|
#endif
|
|
|
|
#ifndef NOCLIB
|
|
gf_CRT_INIT = TRUE;
|
|
#endif
|
|
|
|
if (!g_cs.Init())
|
|
return FALSE;
|
|
|
|
if (!g_csInDllMain.Init())
|
|
return FALSE;
|
|
|
|
if (!g_csDelayLoad.Init())
|
|
return FALSE;
|
|
|
|
g_bOnWow64 = RunningOnWow64();
|
|
|
|
Dbg_MemInit( ! g_bOnWow64 ? TEXT("MSCTF") : TEXT("MSCTF(wow64)"), g_rgPerfObjCounters);
|
|
|
|
g_hInst = hInstance;
|
|
g_hklDefault = GetKeyboardLayout(0);
|
|
|
|
g_dwTLSIndex = TlsAlloc();
|
|
if (g_dwTLSIndex == TLS_OUT_OF_INDEXES)
|
|
return FALSE;
|
|
|
|
g_msgPrivate = RegisterWindowMessage(TEXT("MSUIM.Msg.Private"));
|
|
if (!g_msgPrivate)
|
|
return FALSE;
|
|
|
|
g_msgSetFocus = RegisterWindowMessage(TEXT("MSUIM.Msg.SetFocus"));
|
|
if (!g_msgSetFocus)
|
|
return FALSE;
|
|
|
|
g_msgThreadTerminate = RegisterWindowMessage(TEXT("MSUIM.Msg.ThreadTerminate"));
|
|
if (!g_msgThreadTerminate)
|
|
return FALSE;
|
|
|
|
g_msgThreadItemChange = RegisterWindowMessage(TEXT("MSUIM.Msg.ThreadItemChange"));
|
|
if (!g_msgThreadItemChange)
|
|
return FALSE;
|
|
|
|
g_msgLBarModal = RegisterWindowMessage(TEXT("MSUIM.Msg.LangBarModal"));
|
|
if (!g_msgLBarModal)
|
|
return FALSE;
|
|
|
|
g_msgRpcSendReceive = RegisterWindowMessage(TEXT("MSUIM.Msg.RpcSendReceive"));
|
|
if (!g_msgRpcSendReceive)
|
|
return FALSE;
|
|
|
|
g_msgThreadMarshal = RegisterWindowMessage(TEXT("MSUIM.Msg.ThreadMarshal"));
|
|
if (!g_msgThreadMarshal)
|
|
return FALSE;
|
|
|
|
g_msgCheckThreadInputIdel = RegisterWindowMessage(TEXT("MSUIM.Msg.CheckThreadInputIdel"));
|
|
if (!g_msgCheckThreadInputIdel)
|
|
return FALSE;
|
|
|
|
g_msgStubCleanUp = RegisterWindowMessage(TEXT("MSUIM.Msg.StubCleanUp"));
|
|
if (!g_msgStubCleanUp)
|
|
return FALSE;
|
|
|
|
g_msgShowFloating = RegisterWindowMessage(TEXT("MSUIM.Msg.ShowFloating"));
|
|
if (!g_msgShowFloating)
|
|
return FALSE;
|
|
|
|
g_msgLBUpdate = RegisterWindowMessage(TEXT("MSUIM.Msg.LBUpdate"));
|
|
if (!g_msgLBUpdate)
|
|
return FALSE;
|
|
|
|
g_msgNuiMgrDirtyUpdate = RegisterWindowMessage(TEXT("MSUIM.Msg.MuiMgrDirtyUpdate"));
|
|
if (!g_msgNuiMgrDirtyUpdate)
|
|
return FALSE;
|
|
|
|
InitOSVer();
|
|
|
|
//
|
|
// get imm32's hmodule.
|
|
//
|
|
InitDelayedLibs();
|
|
|
|
InitUniqueString();
|
|
|
|
g_SharedMemory.BaseInit();
|
|
if (!g_SharedMemory.Start())
|
|
return FALSE;
|
|
|
|
gfSharedMemory = TRUE;
|
|
|
|
InitAppCompatFlags();
|
|
InitCUASFlag();
|
|
|
|
g_rglbes = new CStructArray<LBAREVENTSINKLOCAL>;
|
|
if (!g_rglbes)
|
|
return FALSE;
|
|
|
|
RegisterMarshalWndClass();
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.AsmListCache.FMP"), g_szAsmListCache);
|
|
GetDesktopUniqueNameArray(TEXT("CTF.TimListCache.FMP"), g_szTimListCache);
|
|
GetDesktopUniqueNameArray(TEXT("CTF.LayoutsCache.FMP"), g_szLayoutsCache);
|
|
|
|
TCHAR ach[MAX_PATH];
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.LBES.Mutex"), ach);
|
|
|
|
CCicSecAttr sa;
|
|
if (!g_mutexLBES.Init(sa, ach))
|
|
return FALSE;
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.Compart.Mutex"), ach);
|
|
if (!g_mutexCompart.Init(sa, ach))
|
|
return FALSE;
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.Asm.Mutex"), ach);
|
|
if (!g_mutexAsm.Init(sa, ach))
|
|
return FALSE;
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.Layouts.Mutex"), ach);
|
|
if (!g_mutexLayouts.Init(sa, ach))
|
|
return FALSE;
|
|
|
|
GetDesktopUniqueNameArray(TEXT("CTF.TMD.Mutex"), ach);
|
|
if (!g_mutexTMD.Init(sa, ach))
|
|
return FALSE;
|
|
|
|
InitLangChangeHotKey();
|
|
|
|
CRange::_InitClass();
|
|
|
|
CAnchorRef::_InitClass();
|
|
|
|
dbg_InitMarshalTimeOut();
|
|
|
|
MuiLoadResource(hInstance, TEXT("msctf.dll"));
|
|
|
|
CheckAnchorStores();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ProcessDetach
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void ProcessDetach(HINSTANCE hInstance)
|
|
{
|
|
#ifndef NOCLIB
|
|
if (gf_CRT_INIT)
|
|
{
|
|
#endif
|
|
if (gfSharedMemory)
|
|
{
|
|
//
|
|
// If _Module.m_nLockCnt != 0, then TFUninitLib() doesn't calls from DllUninit().
|
|
// So critical section of g_csIMLib never deleted.
|
|
//
|
|
if (DllRefCount() != 0)
|
|
{
|
|
TFUninitLib();
|
|
}
|
|
|
|
CRange::_UninitClass();
|
|
CAnchorRef::_UninitClass();
|
|
|
|
MuiClearResource();
|
|
}
|
|
|
|
UninitINAT();
|
|
CDispAttrGuidCache::StaticUnInit();
|
|
|
|
UninitThread();
|
|
|
|
//
|
|
// clean up all marshal window in this thread.
|
|
//
|
|
CThreadMarshalWnd::ClearMarshalWndProc(GetCurrentProcessId());
|
|
|
|
TF_UninitThreadSystem();
|
|
|
|
UninitProcess();
|
|
if (g_dwTLSIndex != TLS_OUT_OF_INDEXES)
|
|
TlsFree(g_dwTLSIndex);
|
|
g_dwTLSIndex = TLS_OUT_OF_INDEXES;
|
|
|
|
if (g_rglbes)
|
|
delete g_rglbes;
|
|
|
|
g_rglbes = NULL;
|
|
|
|
g_gcomplist.CleanUp();
|
|
g_timlist.CleanUp();
|
|
Dbg_MemUninit();
|
|
|
|
g_cs.Delete();
|
|
g_csInDllMain.Delete();
|
|
g_csDelayLoad.Delete();
|
|
|
|
if (gfSharedMemory)
|
|
{
|
|
g_mutexLBES.Uninit();
|
|
g_mutexCompart.Uninit();
|
|
g_mutexAsm.Uninit();
|
|
|
|
//
|
|
// call UninitLayoutMappedFile before uninitializing the mutex.
|
|
//
|
|
UninitLayoutMappedFile();
|
|
g_mutexLayouts.Uninit();
|
|
|
|
g_mutexTMD.Uninit();
|
|
|
|
InitStaticHooks(); // must happen before we uninit shared memory
|
|
g_SharedMemory.Close();
|
|
}
|
|
g_SharedMemory.Finalize();
|
|
|
|
#ifndef NOCLIB
|
|
}
|
|
|
|
if (g_fDllProcessDetached)
|
|
{
|
|
// why were we called twice?
|
|
Assert(0);
|
|
}
|
|
#endif
|
|
|
|
Assert(DllRefCount() == 0); // leaked something?
|
|
|
|
g_fDllProcessDetached = TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllMain
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pvReserved)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
g_dwThreadDllMain = GetCurrentThreadId();
|
|
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
//
|
|
// Now real DllEntry point is _DllMainCRTStartup.
|
|
// _DllMainCRTStartup does not call our DllMain(DLL_PROCESS_DETACH)
|
|
// if our DllMain(DLL_PROCESS_ATTACH) fails.
|
|
// So we have to clean this up.
|
|
//
|
|
if (!ProcessAttach(hInstance))
|
|
{
|
|
ProcessDetach(hInstance);
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// fall thru
|
|
//
|
|
|
|
//
|
|
// to call TF_InitThreadSystem(), make sure we have not initialized
|
|
// timlist yet.
|
|
//
|
|
Assert(!g_timlist.IsInitialized());
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
TF_InitThreadSystem();
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
UninitThread();
|
|
TF_UninitThreadSystem();
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
ProcessDetach(hInstance);
|
|
break;
|
|
}
|
|
|
|
g_dwThreadDllMain = 0;
|
|
return bRet;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dbg_RangeDump
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void dbg_RangeDump(ITfRange *pRange)
|
|
{
|
|
WCHAR ach[256];
|
|
ULONG cch;
|
|
char ch[256];
|
|
ULONG cch1 = ARRAYSIZE(ch);
|
|
|
|
if (!pRange)
|
|
return;
|
|
|
|
pRange->GetText(BACKDOOR_EDIT_COOKIE, 0, ach, ARRAYSIZE(ach), &cch);
|
|
ach[cch] = L'\0';
|
|
|
|
TraceMsg(TF_GENERAL, "dbg_RangeDump");
|
|
TraceMsg(TF_GENERAL, "\tpRange: %x", (UINT_PTR)pRange);
|
|
cch1 = WideCharToMultiByte(CP_ACP, 0, ach, -1, ch, sizeof(ch)-1, NULL, NULL);
|
|
ch[cch1] = '\0';
|
|
TraceMsg(TF_GENERAL, "\t%s", ch);
|
|
|
|
char sz[512];
|
|
sz[0] = '\0';
|
|
for (UINT i = 0; i < cch; i++)
|
|
{
|
|
StringCchPrintf(sz, ARRAYSIZE(sz), "%s%04x ", sz, ach[i]);
|
|
}
|
|
TraceMsg(TF_GENERAL, "\t%s", sz);
|
|
}
|
|
|
|
#endif
|