// // 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; 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