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.

433 lines
11 KiB

  1. //
  2. // cicload.cpp
  3. //
  4. #include "private.h"
  5. #include "cicload.h"
  6. #include "loader.h"
  7. #include "immxutil.h"
  8. #include "osver.h"
  9. #include "regwatch.h"
  10. #include "mem.h"
  11. #include "msutbapi.h"
  12. #include "ciccs.h"
  13. DECLARE_OSVER();
  14. typedef BOOL (WINAPI *PFNSETPROCESSSHUTDOWNPARAMETERS)( DWORD dwLevel, DWORD dwFlags);
  15. LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
  16. CLoaderWnd *g_pLoaderWnd;
  17. HINSTANCE g_hInst;
  18. HANDLE g_hInstanceMutex;
  19. BOOL g_fWinLogon = FALSE;
  20. BOOL g_fRunOnceMode = FALSE;
  21. BOOL g_bOnWow64 = FALSE;
  22. BOOL g_fNoRunKey = FALSE;
  23. #ifdef DEBUG
  24. DWORD g_dwThreadDllMain = 0;
  25. #endif
  26. CCicCriticalSectionStatic g_cs;
  27. extern "C" HANDLE WINAPI TF_CreateCicLoadMutex(BOOL *pfWinLogon);
  28. extern "C" HRESULT WINAPI TF_GetGlobalCompartment(ITfCompartmentMgr **pCompMgr);
  29. HRESULT GetGlobalCompartment(REFGUID rguidComp, ITfCompartment **ppComp)
  30. {
  31. HRESULT hr = E_FAIL;
  32. ITfCompartmentMgr *pCompMgr = NULL;
  33. *ppComp = NULL;
  34. if (FAILED(hr = TF_GetGlobalCompartment(&pCompMgr)))
  35. {
  36. Assert(0);
  37. goto Exit;
  38. }
  39. if (SUCCEEDED(hr) && pCompMgr)
  40. {
  41. hr = pCompMgr->GetCompartment(rguidComp, ppComp);
  42. pCompMgr->Release();
  43. }
  44. else
  45. hr = E_FAIL;
  46. Exit:
  47. return hr;
  48. }
  49. HRESULT SetGlobalCompartmentDWORD(REFGUID rguidComp, DWORD dw)
  50. {
  51. HRESULT hr;
  52. ITfCompartment *pComp;
  53. VARIANT var;
  54. if (SUCCEEDED(hr = GetGlobalCompartment(rguidComp, &pComp)))
  55. {
  56. var.vt = VT_I4;
  57. var.lVal = dw;
  58. hr = pComp->SetValue(0, &var);
  59. pComp->Release();
  60. }
  61. return hr;
  62. }
  63. HRESULT STDAPICALLTYPE StubCoCreateInstance(REFCLSID rclsid, LPUNKNOWN punkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
  64. {
  65. // we should never get here! This function is a stub to keep the library happy, so it won't actually
  66. // load ole32.dll. ctfmon.exe should never be loading ole32.dll!
  67. Assert(0);
  68. if (ppv != NULL)
  69. {
  70. *ppv = NULL;
  71. }
  72. return E_UNEXPECTED;
  73. }
  74. void AddRunRegkey()
  75. {
  76. HKEY hkeyRun;
  77. const static TCHAR c_szCTFMon[] = TEXT("ctfmon.exe");
  78. if (g_fNoRunKey)
  79. return;
  80. if (RegCreateKey( HKEY_CURRENT_USER,
  81. REGSTR_PATH_RUN,
  82. &hkeyRun ) == ERROR_SUCCESS)
  83. {
  84. CicSystemModulePath pathCTFMon;
  85. if (pathCTFMon.Init(c_szCTFMon))
  86. {
  87. RegSetValueEx(hkeyRun,
  88. c_szCTFMon,
  89. 0,
  90. REG_SZ,
  91. (LPBYTE)pathCTFMon.GetPath(),
  92. pathCTFMon.GetLength() * sizeof(TCHAR));
  93. RegCloseKey(hkeyRun);
  94. }
  95. }
  96. }
  97. BOOL InitApp(HINSTANCE hInstance)
  98. {
  99. g_hInstanceMutex = TF_CreateCicLoadMutex(&g_fWinLogon);
  100. if (!g_hInstanceMutex)
  101. return FALSE;
  102. AddRunRegkey();
  103. g_hInst = hInstance;
  104. if (!g_cs.Init())
  105. return FALSE;
  106. TFInitLib_PrivateForCiceroOnly(StubCoCreateInstance);
  107. InitOSVer();
  108. //
  109. // Specify the shutdown order of the progman process.
  110. //
  111. // Progman (level = 2)
  112. // taskman (level = 1)
  113. // ntsd or windbg (level = 0)
  114. //
  115. // Ctfmon is enough to have 0xf0 after any programs..
  116. //
  117. if (IsOnNT())
  118. {
  119. static PFNSETPROCESSSHUTDOWNPARAMETERS pfnSetShutdownParam;
  120. static HINSTANCE hLibKernel32 = NULL;
  121. hLibKernel32 = GetSystemModuleHandle( TEXT("kernel32.dll") );
  122. if (hLibKernel32)
  123. {
  124. pfnSetShutdownParam = (PFNSETPROCESSSHUTDOWNPARAMETERS)GetProcAddress(hLibKernel32, TEXT("SetProcessShutdownParameters"));
  125. if (pfnSetShutdownParam)
  126. pfnSetShutdownParam(0xf0, SHUTDOWN_NORETRY);
  127. }
  128. }
  129. // rev up default Cicero support for the system
  130. TF_InitSystem();
  131. if (! g_bOnWow64)
  132. {
  133. CRegWatcher::Init();
  134. }
  135. g_pLoaderWnd = new CLoaderWnd();
  136. if (!g_pLoaderWnd)
  137. {
  138. return FALSE;
  139. }
  140. if (!g_pLoaderWnd->Init())
  141. {
  142. return FALSE;
  143. }
  144. g_pLoaderWnd->CreateWnd();
  145. //
  146. // locate this window at the bottom of z-order list.
  147. // so we can delay WM_QUERYENDSESSION under Win9x platform.
  148. //
  149. if (g_pLoaderWnd->GetWnd())
  150. SetWindowPos(g_pLoaderWnd->GetWnd(), HWND_BOTTOM, 0, 0, 0, 0,
  151. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  152. return TRUE;
  153. }
  154. void UninitApp(void)
  155. {
  156. ClosePopupTipbar();
  157. TFUninitLib();
  158. CloseHandle(g_hInstanceMutex);
  159. if (! g_bOnWow64)
  160. {
  161. CRegWatcher::Uninit();
  162. }
  163. }
  164. void CheckCmdLine(PSTR pszCmdLine)
  165. {
  166. PSTR psz = pszCmdLine;
  167. while (*psz)
  168. {
  169. if (*psz == ' ')
  170. {
  171. psz++;
  172. if (!*psz)
  173. return;
  174. if ((*psz == '-') || (*psz == '/'))
  175. {
  176. psz++;
  177. if (!*psz)
  178. return;
  179. switch (*psz)
  180. {
  181. case 'r':
  182. case 'R':
  183. g_fRunOnceMode = TRUE;
  184. break;
  185. case 'n':
  186. case 'N':
  187. g_fNoRunKey = TRUE;
  188. break;
  189. default:
  190. break;
  191. }
  192. }
  193. }
  194. psz++;
  195. }
  196. }
  197. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pszCmdLine, int iCmdShow)
  198. {
  199. MSG msg;
  200. DWORD dwWaitObj;
  201. CcshellGetDebugFlags();
  202. Dbg_MemInit(TEXT("CTFMON"), NULL);
  203. //
  204. // Retrive WOW64
  205. //
  206. g_bOnWow64 = RunningOnWow64();
  207. CheckCmdLine(pszCmdLine);
  208. if (g_fRunOnceMode)
  209. {
  210. AddRunRegkey();
  211. Dbg_MemUninit();
  212. return 1;
  213. }
  214. if (!InitApp(hInstance))
  215. {
  216. Dbg_MemUninit();
  217. return 0;
  218. }
  219. if (! g_bOnWow64)
  220. {
  221. //
  222. // Load MSUTB.DLL
  223. //
  224. GetPopupTipbar(g_pLoaderWnd->GetWnd(), g_fWinLogon ? UTB_GTI_WINLOGON : 0);
  225. }
  226. //
  227. // For 64bit only.
  228. // Launch ctfmon(32).
  229. //
  230. {
  231. SYSTEM_INFO sys;
  232. GetSystemInfo(&sys);
  233. if ((sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ||
  234. (sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64))
  235. {
  236. HMODULE h = GetSystemModuleHandle("kernel32.dll");
  237. if (h)
  238. {
  239. const char c_szCtfMonExe[] = "\\ctfmon.exe";
  240. PGET_SYSTEM_WOW64_DIRECTORY_A lpfn;
  241. lpfn = (PGET_SYSTEM_WOW64_DIRECTORY_A)GetProcAddress(h, GET_SYSTEM_WOW64_DIRECTORY_NAME_T_A);
  242. if (lpfn)
  243. {
  244. char buf[MAX_PATH];
  245. UINT len;
  246. len = (lpfn)(buf, sizeof(buf)/sizeof(char));
  247. if (len &&
  248. (ARRAYSIZE(buf) > len + ARRAYSIZE(c_szCtfMonExe)))
  249. {
  250. PROCESS_INFORMATION process;
  251. STARTUPINFO si;
  252. memset(&si, 0, sizeof(si));
  253. si.cb = sizeof(si);
  254. si.wShowWindow = SW_SHOWMINNOACTIVE;
  255. lstrcat(buf, c_szCtfMonExe);
  256. if (CreateProcess(buf, // application name
  257. pszCmdLine, // command line
  258. NULL, // process SD
  259. NULL, // thread SD
  260. FALSE, // inherit handle
  261. 0, // creation flags
  262. NULL, // environment
  263. NULL, // current directory
  264. &si, // startup info
  265. &process)) // process information
  266. {
  267. CloseHandle(process.hProcess);
  268. CloseHandle(process.hThread);
  269. }
  270. }
  271. }
  272. }
  273. }
  274. }
  275. HANDLE hEventWS0 = 0;
  276. if (! g_bOnWow64)
  277. hEventWS0 = OpenEvent(SYNCHRONIZE, FALSE, _T("WinSta0_DesktopSwitch"));
  278. while (TRUE)
  279. {
  280. if (! g_bOnWow64)
  281. {
  282. HANDLE rgAllEvents[NUM_REG_WATCH+1];
  283. const HANDLE *prgRegEvents = CRegWatcher::GetEvents();
  284. memcpy(rgAllEvents, prgRegEvents, NUM_REG_WATCH*sizeof(HANDLE));
  285. #define IDX_EVENT_WS NUM_REG_WATCH
  286. #define NUM_ALL_EVENTS (NUM_REG_WATCH+1)
  287. rgAllEvents[IDX_EVENT_WS] = hEventWS0;
  288. dwWaitObj = MsgWaitForMultipleObjects(NUM_ALL_EVENTS, rgAllEvents, FALSE, INFINITE, QS_ALLINPUT);
  289. if (dwWaitObj == WAIT_OBJECT_0 + NUM_ALL_EVENTS)
  290. {
  291. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  292. {
  293. if (msg.message == WM_QUIT)
  294. goto Exit;
  295. TranslateMessage(&msg);
  296. DispatchMessage(&msg);
  297. }
  298. }
  299. else if (dwWaitObj == WAIT_OBJECT_0 + IDX_EVENT_WS)
  300. {
  301. // win station switching event
  302. // set mic off
  303. SetGlobalCompartmentDWORD(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0);
  304. // reset the event (needed? not sure if this is auto-reset)
  305. ::ResetEvent(rgAllEvents[IDX_EVENT_WS]);
  306. }
  307. else if (dwWaitObj < WAIT_OBJECT_0 + NUM_REG_WATCH)
  308. {
  309. CRegWatcher::OnEvent(dwWaitObj - WAIT_OBJECT_0);
  310. }
  311. else
  312. {
  313. Assert(0); // error
  314. msg.wParam = 0;
  315. break;
  316. }
  317. }
  318. else
  319. {
  320. while (GetMessage(&msg, NULL, 0, 0))
  321. {
  322. TranslateMessage(&msg);
  323. DispatchMessage(&msg);
  324. }
  325. break;
  326. }
  327. }
  328. Exit:
  329. delete g_pLoaderWnd;
  330. if (!CLoaderWnd::_bUninitedSystem)
  331. {
  332. UninitApp();
  333. // it is over!
  334. TF_UninitSystem();
  335. }
  336. g_cs.Delete();
  337. Dbg_MemUninit();
  338. return (int)(msg.wParam);
  339. }
  340. int _stdcall ModuleEntry(void)
  341. {
  342. int i;
  343. STARTUPINFO si;
  344. si.dwFlags = 0;
  345. GetStartupInfoA(&si);
  346. i = WinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  347. ExitProcess(i);
  348. return i;
  349. }