// // cicload.cpp // #include "private.h" #include "cicload.h" #include "loader.h" #include "immxutil.h" #include "osver.h" #include "regwatch.h" #include "mem.h" #include "msutbapi.h" #include "ciccs.h" DECLARE_OSVER(); typedef BOOL (WINAPI *PFNSETPROCESSSHUTDOWNPARAMETERS)( DWORD dwLevel, DWORD dwFlags); LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM); CLoaderWnd *g_pLoaderWnd; HINSTANCE g_hInst; HANDLE g_hInstanceMutex; BOOL g_fWinLogon = FALSE; BOOL g_fRunOnceMode = FALSE; BOOL g_bOnWow64 = FALSE; BOOL g_fNoRunKey = FALSE; #ifdef DEBUG DWORD g_dwThreadDllMain = 0; #endif CCicCriticalSectionStatic g_cs; extern "C" HANDLE WINAPI TF_CreateCicLoadMutex(BOOL *pfWinLogon); extern "C" HRESULT WINAPI TF_GetGlobalCompartment(ITfCompartmentMgr **pCompMgr); HRESULT GetGlobalCompartment(REFGUID rguidComp, ITfCompartment **ppComp) { HRESULT hr = E_FAIL; ITfCompartmentMgr *pCompMgr = NULL; *ppComp = NULL; if (FAILED(hr = TF_GetGlobalCompartment(&pCompMgr))) { Assert(0); goto Exit; } if (SUCCEEDED(hr) && pCompMgr) { hr = pCompMgr->GetCompartment(rguidComp, ppComp); pCompMgr->Release(); } else hr = E_FAIL; Exit: return hr; } HRESULT SetGlobalCompartmentDWORD(REFGUID rguidComp, DWORD dw) { HRESULT hr; ITfCompartment *pComp; VARIANT var; if (SUCCEEDED(hr = GetGlobalCompartment(rguidComp, &pComp))) { var.vt = VT_I4; var.lVal = dw; hr = pComp->SetValue(0, &var); pComp->Release(); } return hr; } HRESULT STDAPICALLTYPE StubCoCreateInstance(REFCLSID rclsid, LPUNKNOWN punkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv) { // we should never get here! This function is a stub to keep the library happy, so it won't actually // load ole32.dll. ctfmon.exe should never be loading ole32.dll! Assert(0); if (ppv != NULL) { *ppv = NULL; } return E_UNEXPECTED; } void AddRunRegkey() { HKEY hkeyRun; const static TCHAR c_szCTFMon[] = TEXT("ctfmon.exe"); if (g_fNoRunKey) return; if (RegCreateKey( HKEY_CURRENT_USER, REGSTR_PATH_RUN, &hkeyRun ) == ERROR_SUCCESS) { CicSystemModulePath pathCTFMon; if (pathCTFMon.Init(c_szCTFMon)) { RegSetValueEx(hkeyRun, c_szCTFMon, 0, REG_SZ, (LPBYTE)pathCTFMon.GetPath(), pathCTFMon.GetLength() * sizeof(TCHAR)); RegCloseKey(hkeyRun); } } } BOOL InitApp(HINSTANCE hInstance) { g_hInstanceMutex = TF_CreateCicLoadMutex(&g_fWinLogon); if (!g_hInstanceMutex) return FALSE; AddRunRegkey(); g_hInst = hInstance; if (!g_cs.Init()) return FALSE; TFInitLib_PrivateForCiceroOnly(StubCoCreateInstance); InitOSVer(); // // Specify the shutdown order of the progman process. // // Progman (level = 2) // taskman (level = 1) // ntsd or windbg (level = 0) // // Ctfmon is enough to have 0xf0 after any programs.. // if (IsOnNT()) { static PFNSETPROCESSSHUTDOWNPARAMETERS pfnSetShutdownParam; static HINSTANCE hLibKernel32 = NULL; hLibKernel32 = GetSystemModuleHandle( TEXT("kernel32.dll") ); if (hLibKernel32) { pfnSetShutdownParam = (PFNSETPROCESSSHUTDOWNPARAMETERS)GetProcAddress(hLibKernel32, TEXT("SetProcessShutdownParameters")); if (pfnSetShutdownParam) pfnSetShutdownParam(0xf0, SHUTDOWN_NORETRY); } } // rev up default Cicero support for the system TF_InitSystem(); if (! g_bOnWow64) { CRegWatcher::Init(); } g_pLoaderWnd = new CLoaderWnd(); if (!g_pLoaderWnd) { return FALSE; } if (!g_pLoaderWnd->Init()) { return FALSE; } g_pLoaderWnd->CreateWnd(); // // locate this window at the bottom of z-order list. // so we can delay WM_QUERYENDSESSION under Win9x platform. // if (g_pLoaderWnd->GetWnd()) SetWindowPos(g_pLoaderWnd->GetWnd(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); return TRUE; } void UninitApp(void) { ClosePopupTipbar(); TFUninitLib(); CloseHandle(g_hInstanceMutex); if (! g_bOnWow64) { CRegWatcher::Uninit(); } } void CheckCmdLine(PSTR pszCmdLine) { PSTR psz = pszCmdLine; while (*psz) { if (*psz == ' ') { psz++; if (!*psz) return; if ((*psz == '-') || (*psz == '/')) { psz++; if (!*psz) return; switch (*psz) { case 'r': case 'R': g_fRunOnceMode = TRUE; break; case 'n': case 'N': g_fNoRunKey = TRUE; break; default: break; } } } psz++; } } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pszCmdLine, int iCmdShow) { MSG msg; DWORD dwWaitObj; CcshellGetDebugFlags(); Dbg_MemInit(TEXT("CTFMON"), NULL); // // Retrive WOW64 // g_bOnWow64 = RunningOnWow64(); CheckCmdLine(pszCmdLine); if (g_fRunOnceMode) { AddRunRegkey(); Dbg_MemUninit(); return 1; } if (!InitApp(hInstance)) { Dbg_MemUninit(); return 0; } if (! g_bOnWow64) { // // Load MSUTB.DLL // GetPopupTipbar(g_pLoaderWnd->GetWnd(), g_fWinLogon ? UTB_GTI_WINLOGON : 0); } // // For 64bit only. // Launch ctfmon(32). // { SYSTEM_INFO sys; GetSystemInfo(&sys); if ((sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) || (sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)) { HMODULE h = GetSystemModuleHandle("kernel32.dll"); if (h) { const char c_szCtfMonExe[] = "\\ctfmon.exe"; PGET_SYSTEM_WOW64_DIRECTORY_A lpfn; lpfn = (PGET_SYSTEM_WOW64_DIRECTORY_A)GetProcAddress(h, GET_SYSTEM_WOW64_DIRECTORY_NAME_T_A); if (lpfn) { char buf[MAX_PATH]; UINT len; len = (lpfn)(buf, sizeof(buf)/sizeof(char)); if (len && (ARRAYSIZE(buf) > len + ARRAYSIZE(c_szCtfMonExe))) { PROCESS_INFORMATION process; STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = SW_SHOWMINNOACTIVE; lstrcat(buf, c_szCtfMonExe); if (CreateProcess(buf, // application name pszCmdLine, // command line NULL, // process SD NULL, // thread SD FALSE, // inherit handle 0, // creation flags NULL, // environment NULL, // current directory &si, // startup info &process)) // process information { CloseHandle(process.hProcess); CloseHandle(process.hThread); } } } } } } HANDLE hEventWS0 = 0; if (! g_bOnWow64) hEventWS0 = OpenEvent(SYNCHRONIZE, FALSE, _T("WinSta0_DesktopSwitch")); while (TRUE) { if (! g_bOnWow64) { HANDLE rgAllEvents[NUM_REG_WATCH+1]; const HANDLE *prgRegEvents = CRegWatcher::GetEvents(); memcpy(rgAllEvents, prgRegEvents, NUM_REG_WATCH*sizeof(HANDLE)); #define IDX_EVENT_WS NUM_REG_WATCH #define NUM_ALL_EVENTS (NUM_REG_WATCH+1) rgAllEvents[IDX_EVENT_WS] = hEventWS0; dwWaitObj = MsgWaitForMultipleObjects(NUM_ALL_EVENTS, rgAllEvents, FALSE, INFINITE, QS_ALLINPUT); if (dwWaitObj == WAIT_OBJECT_0 + NUM_ALL_EVENTS) { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) goto Exit; TranslateMessage(&msg); DispatchMessage(&msg); } } else if (dwWaitObj == WAIT_OBJECT_0 + IDX_EVENT_WS) { // win station switching event // set mic off SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0); // reset the event (needed? not sure if this is auto-reset) ::ResetEvent(rgAllEvents[IDX_EVENT_WS]); } else if (dwWaitObj < WAIT_OBJECT_0 + NUM_REG_WATCH) { CRegWatcher::OnEvent(dwWaitObj - WAIT_OBJECT_0); } else { Assert(0); // error msg.wParam = 0; break; } } else { while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } break; } } Exit: delete g_pLoaderWnd; if (!CLoaderWnd::_bUninitedSystem) { UninitApp(); // it is over! TF_UninitSystem(); } g_cs.Delete(); Dbg_MemUninit(); return (int)(msg.wParam); } int _stdcall ModuleEntry(void) { int i; STARTUPINFO si; si.dwFlags = 0; GetStartupInfoA(&si); i = WinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT); ExitProcess(i); return i; }