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.

1463 lines
44 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: clinit.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains all the init code for the USER.DLL. When the DLL is
  7. * dynlinked its initialization procedure (UserClientDllInitialize) is called by
  8. * the loader.
  9. *
  10. * History:
  11. * 18-Sep-1990 DarrinM Created.
  12. \***************************************************************************/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "csrhlpr.h"
  16. /*
  17. * Global variables local to this module (startup).
  18. */
  19. BOOL gfFirstThread = TRUE;
  20. PDESKTOPINFO pdiLocal;
  21. #if DBG
  22. BOOL gbIhaveBeenInited;
  23. #endif
  24. static DWORD gdwLpkEntryPoints;
  25. CONST WCHAR szWindowsKey[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
  26. CONST WCHAR szAppInit[] = L"AppInit_DLLs";
  27. WCHAR szWindowStationDirectory[MAX_SESSION_PATH];
  28. extern CONST PVOID apfnDispatch[];
  29. /*
  30. * External declared routines needed for startup.
  31. */
  32. NTSTATUS GdiProcessSetup(VOID);
  33. NTSTATUS GdiDllInitialize(IN PVOID hmod, IN DWORD Reason);
  34. /***************************************************************************\
  35. * UserClientDllInitialize
  36. *
  37. * When USER32.DLL is loaded by an EXE (either at EXE load or at LoadModule
  38. * time) this routine is called by the loader. Its purpose is to initialize
  39. * everything that will be needed for future User API calls by the app.
  40. *
  41. * History:
  42. * 19-Sep-1990 DarrinM Created.
  43. \***************************************************************************/
  44. BOOL UserClientDllInitialize(
  45. IN PVOID hmod,
  46. IN DWORD Reason,
  47. IN PCONTEXT pctx)
  48. {
  49. SYSTEM_BASIC_INFORMATION SystemInformation;
  50. NTSTATUS Status;
  51. UNREFERENCED_PARAMETER(pctx);
  52. #if DBG
  53. if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) {
  54. RIPMSG1(RIP_WARNING,
  55. "UserClientDllInitialize: entered for reason %x",
  56. Reason);
  57. }
  58. #endif
  59. if (Reason == DLL_PROCESS_ATTACH) {
  60. USERCONNECT userconnect;
  61. ULONG ulConnect = sizeof(USERCONNECT);
  62. ULONG SessionId = NtCurrentPeb()->SessionId;
  63. UserVerify(DisableThreadLibraryCalls(hmod));
  64. #if DBG
  65. UserAssert(!gbIhaveBeenInited);
  66. if (gbIhaveBeenInited) {
  67. return TRUE;
  68. } else {
  69. gbIhaveBeenInited = TRUE;
  70. }
  71. #endif
  72. Status = RtlInitializeCriticalSection(&gcsClipboard);
  73. Status |= RtlInitializeCriticalSection(&gcsLookaside);
  74. Status |= RtlInitializeCriticalSection(&gcsHdc);
  75. Status |= RtlInitializeCriticalSection(&gcsAccelCache);
  76. Status |= RtlInitializeCriticalSection(&gcsDDEML);
  77. Status |= RtlInitializeCriticalSection(&gcsUserApiHook);
  78. #ifdef MESSAGE_PUMP_HOOK
  79. Status |= RtlInitializeCriticalSection(&gcsMPH);
  80. #endif
  81. if (!NT_SUCCESS(Status)) {
  82. RIPMSG1(RIP_WARNING,
  83. "Failed to create critical sections. Status 0x%x",
  84. Status);
  85. return FALSE;
  86. }
  87. #ifdef LAME_BUTTON
  88. gatomLameButton = AddAtomW(LAMEBUTTON_PROP_NAME);
  89. if (gatomLameButton == 0) {
  90. RIPMSG0(RIP_WARNING, "Failed to create lame button atom");
  91. return FALSE;
  92. }
  93. #endif
  94. #if DBG
  95. gpDDEMLHeap = RtlCreateHeap(HEAP_GROWABLE | HEAP_CLASS_1
  96. | HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED
  97. , NULL, 8 * 1024, 2 * 1024, NULL, NULL);
  98. if (gpDDEMLHeap == NULL) {
  99. gpDDEMLHeap = RtlProcessHeap();
  100. }
  101. #endif
  102. Status = NtQuerySystemInformation(SystemBasicInformation,
  103. &SystemInformation,
  104. sizeof(SystemInformation),
  105. NULL);
  106. if (!NT_SUCCESS(Status)) {
  107. RIPMSG1(RIP_WARNING,
  108. "NtQuerySystemInformation failed with Status 0x%x",
  109. Status);
  110. return FALSE;
  111. }
  112. gHighestUserAddress = SystemInformation.MaximumUserModeAddress;
  113. userconnect.ulVersion = USERCURRENTVERSION;
  114. if (SessionId != 0) {
  115. WCHAR szSessionDir[MAX_SESSION_PATH];
  116. swprintf(szSessionDir,
  117. L"%ws\\%ld%ws",
  118. SESSION_ROOT,
  119. SessionId,
  120. WINSS_OBJECT_DIRECTORY_NAME);
  121. Status = UserConnectToServer(szSessionDir,
  122. &userconnect,
  123. &ulConnect,
  124. (PBOOLEAN)&gfServerProcess);
  125. } else {
  126. Status = UserConnectToServer(WINSS_OBJECT_DIRECTORY_NAME,
  127. &userconnect,
  128. &ulConnect,
  129. (PBOOLEAN)&gfServerProcess);
  130. }
  131. if (!NT_SUCCESS(Status)) {
  132. RIPMSG1(RIP_WARNING,
  133. "UserConnectToServer failed with Status 0x%x",
  134. Status);
  135. return FALSE;
  136. }
  137. /*
  138. * If this is the server process, the shared info is not yet valid,
  139. * so don't copy out the returned info.
  140. */
  141. if (!gfServerProcess) {
  142. HINSTANCE hImm32 = NULL;
  143. gSharedInfo = userconnect.siClient;
  144. gpsi = gSharedInfo.psi;
  145. if (IS_IME_ENABLED()) {
  146. WCHAR wszImmFile[MAX_PATH];
  147. InitializeImmEntryTable();
  148. GetImmFileName(wszImmFile);
  149. hImm32 = GetModuleHandleW(wszImmFile);
  150. }
  151. if (!fpImmRegisterClient(&userconnect.siClient, hImm32)) {
  152. RIPMSG0(RIP_WARNING,
  153. "UserClientDllInitialize: ImmRegisterClient failed");
  154. return FALSE;
  155. }
  156. }
  157. pfnFindResourceExA = (PFNFINDA)FindResourceExA;
  158. pfnFindResourceExW = (PFNFINDW)FindResourceExW;
  159. pfnLoadResource = (PFNLOAD)LoadResource;
  160. pfnSizeofResource = (PFNSIZEOF)SizeofResource;
  161. /*
  162. * Register with the base the USER hook it should call when it
  163. * does a WinExec() (this is soft-linked because some people still
  164. * use charmode nt!)
  165. */
  166. RegisterWaitForInputIdle(WaitForInputIdle);
  167. /*
  168. * Remember USER32.DLL's hmodule so we can grab resources from it later.
  169. */
  170. hmodUser = hmod;
  171. pUserHeap = RtlProcessHeap();
  172. /*
  173. * Initialize callback table
  174. */
  175. NtCurrentPeb()->KernelCallbackTable = apfnDispatch;
  176. NtCurrentPeb()->PostProcessInitRoutine = NULL;
  177. if (SessionId != 0) {
  178. swprintf(szWindowStationDirectory, L"%ws\\%ld%ws", SESSION_ROOT, SessionId, WINSTA_DIR);
  179. RtlInitUnicodeString(&strRootDirectory, szWindowStationDirectory);
  180. } else {
  181. RtlInitUnicodeString(&strRootDirectory, WINSTA_DIR);
  182. }
  183. #ifdef _JANUS_
  184. if (gfServerProcess) {
  185. gfEMIEnable = FALSE;
  186. } else {
  187. gfEMIEnable = InitInstrument(&gdwEMIControl);
  188. }
  189. #endif
  190. } else if (Reason == DLL_PROCESS_DETACH) {
  191. if (ghImm32 != NULL) {
  192. // IMM32.DLL is loaded by USER32, so free it.
  193. FreeLibrary(ghImm32);
  194. }
  195. /*
  196. * If we loaded OLE, tell it we're done.
  197. */
  198. if (ghinstOLE != NULL) {
  199. /*
  200. * Later5.0 GerardoB. This causes check OLE32.DLL to fault
  201. * because they get their DLL_PROCESS_DETACH first
  202. * (*(OLEUNINITIALIZEPROC)gpfnOLEOleUninitialize)();
  203. */
  204. RIPMSG0(RIP_WARNING, "OLE would fault if I call OleUninitialize now");
  205. FreeLibrary(ghinstOLE);
  206. }
  207. #ifdef _JANUS_
  208. /*
  209. * If the user has enabled the Error Instrumentation and we've had to
  210. * log something (which is indicated by gEventSource being non-NULL),
  211. * unregister the event source.
  212. */
  213. if (gEventSource != NULL) {
  214. DeregisterEventSource(gEventSource);
  215. }
  216. #endif
  217. RtlDeleteCriticalSection(&gcsClipboard);
  218. RtlDeleteCriticalSection(&gcsLookaside);
  219. RtlDeleteCriticalSection(&gcsHdc);
  220. RtlDeleteCriticalSection(&gcsAccelCache);
  221. RtlDeleteCriticalSection(&gcsDDEML);
  222. RtlDeleteCriticalSection(&gcsUserApiHook);
  223. #ifdef MESSAGE_PUMP_HOOK
  224. RtlDeleteCriticalSection(&gcsMPH);
  225. #endif
  226. #if DBG
  227. if (gpDDEMLHeap != RtlProcessHeap()) {
  228. RtlDestroyHeap(gpDDEMLHeap);
  229. }
  230. #endif
  231. }
  232. Status = GdiDllInitialize(hmod, Reason);
  233. if (!NT_SUCCESS(Status)) {
  234. RIPMSG1(RIP_WARNING,
  235. "GdiDllInitialize failed with Status 0x%x",
  236. Status);
  237. }
  238. return NT_SUCCESS(Status);
  239. }
  240. BOOL LoadIcons(
  241. VOID)
  242. {
  243. int i;
  244. /*
  245. * Load the small version of WINLOGO which will be set into
  246. * gpsi->hIconSmWindows on the kernel side.
  247. */
  248. if (LoadIcoCur(NULL,
  249. (LPCWSTR)UIntToPtr(OIC_WINLOGO_DEFAULT),
  250. RT_ICON,
  251. SYSMET(CXSMICON),
  252. SYSMET(CYSMICON),
  253. LR_GLOBAL) == NULL) {
  254. RIPMSG0(RIP_WARNING, "Couldn't load small winlogo icon");
  255. return FALSE;
  256. }
  257. for (i = 0; i < COIC_CONFIGURABLE; i++) {
  258. if (LoadIcoCur(NULL,
  259. (LPCWSTR)UIntToPtr(OIC_FIRST_DEFAULT + i),
  260. RT_ICON,
  261. 0,
  262. 0,
  263. LR_SHARED | LR_GLOBAL) == NULL) {
  264. RIPMSG1(RIP_WARNING, "Couldn't load icon 0x%x", i);
  265. return FALSE;
  266. }
  267. }
  268. return TRUE;
  269. }
  270. BOOL LoadCursors(
  271. VOID)
  272. {
  273. int i = 0;
  274. for (i = 0; i < COCR_CONFIGURABLE; i++) {
  275. if (LoadIcoCur(NULL,
  276. (LPCWSTR)UIntToPtr(OCR_FIRST_DEFAULT + i),
  277. RT_CURSOR,
  278. 0,
  279. 0,
  280. LR_SHARED | LR_GLOBAL | LR_DEFAULTSIZE) == NULL) {
  281. RIPMSG1(RIP_WARNING, "Couldn't load cursor 0x%x", i);
  282. return FALSE;
  283. }
  284. }
  285. return TRUE;
  286. }
  287. /***************************************************************************\
  288. * LoadCursorsAndIcons
  289. *
  290. * This gets called from our initialization call from csr so they're around
  291. * when window classes get registered. Window classes get registered right
  292. * after the initial csr initialization call.
  293. *
  294. * Later on these default images will get overwritten by custom
  295. * registry entries. See UpdateCursors/IconsFromRegistry().
  296. *
  297. * 27-Sep-1992 ScottLu Created.
  298. * 14-Oct-1995 SanfordS Rewrote.
  299. \***************************************************************************/
  300. BOOL LoadCursorsAndIcons(
  301. VOID)
  302. {
  303. if (!LoadCursors() || !LoadIcons()) {
  304. return FALSE;
  305. } else {
  306. /*
  307. * Now go to the kernel and fixup the IDs from DEFAULT values to
  308. * standard values.
  309. */
  310. NtUserCallNoParam(SFI__LOADCURSORSANDICONS);
  311. return TRUE;
  312. }
  313. }
  314. /***************************************************************************\
  315. * UserRegisterControls
  316. *
  317. * Register the control classes. This function must be called for each
  318. * client process.
  319. *
  320. * History:
  321. * ??-??-?? DarrinM Ported.
  322. * ??-??-?? MikeKe Moved here from server.
  323. \***************************************************************************/
  324. BOOL UserRegisterControls(
  325. VOID)
  326. {
  327. int i;
  328. WNDCLASSEX wndcls;
  329. static CONST struct {
  330. UINT style;
  331. WNDPROC lpfnWndProcW;
  332. int cbWndExtra;
  333. LPCTSTR lpszCursor;
  334. HBRUSH hbrBackground;
  335. LPCTSTR lpszClassName;
  336. WORD fnid;
  337. } rc[] = {
  338. {CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW,
  339. ButtonWndProcW,
  340. sizeof(BUTNWND) - sizeof(WND),
  341. IDC_ARROW,
  342. NULL,
  343. L"Button",
  344. FNID_BUTTON
  345. },
  346. {CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC | CS_VREDRAW | CS_HREDRAW,
  347. ComboBoxWndProcW,
  348. sizeof(COMBOWND) - sizeof(WND),
  349. IDC_ARROW,
  350. NULL,
  351. L"ComboBox",
  352. FNID_COMBOBOX
  353. },
  354. {CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
  355. ComboListBoxWndProcW,
  356. sizeof(LBWND) - sizeof(WND),
  357. IDC_ARROW,
  358. NULL,
  359. L"ComboLBox",
  360. FNID_COMBOLISTBOX
  361. },
  362. {CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
  363. DefDlgProcW,
  364. DLGWINDOWEXTRA,
  365. IDC_ARROW,
  366. NULL,
  367. DIALOGCLASS,
  368. FNID_DIALOG
  369. },
  370. {CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
  371. EditWndProcW,
  372. max((sizeof(EDITWND) - sizeof(WND)), CBEDITEXTRA),
  373. IDC_IBEAM,
  374. NULL,
  375. L"Edit",
  376. FNID_EDIT
  377. },
  378. {CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
  379. ListBoxWndProcW,
  380. sizeof(LBWND) - sizeof(WND),
  381. IDC_ARROW,
  382. NULL,
  383. L"ListBox",
  384. FNID_LISTBOX
  385. },
  386. {CS_GLOBALCLASS,
  387. MDIClientWndProcW,
  388. sizeof(MDIWND) - sizeof(WND),
  389. IDC_ARROW,
  390. (HBRUSH)(COLOR_APPWORKSPACE + 1),
  391. L"MDIClient",
  392. FNID_MDICLIENT
  393. },
  394. {CS_GLOBALCLASS,
  395. ImeWndProcW,
  396. sizeof(IMEWND) - sizeof(WND),
  397. IDC_ARROW,
  398. NULL,
  399. L"IME",
  400. FNID_IME
  401. },
  402. {CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
  403. StaticWndProcW,
  404. sizeof(STATWND) - sizeof(WND),
  405. IDC_ARROW,
  406. NULL,
  407. L"Static",
  408. FNID_STATIC
  409. }
  410. };
  411. /*
  412. * Classes are registered via the table.
  413. */
  414. RtlZeroMemory(&wndcls, sizeof(wndcls));
  415. wndcls.cbSize = sizeof(wndcls);
  416. wndcls.hInstance = hmodUser;
  417. for (i = 0; i < ARRAY_SIZE(rc); i++) {
  418. wndcls.style = rc[i].style;
  419. wndcls.lpfnWndProc = rc[i].lpfnWndProcW;
  420. wndcls.cbWndExtra = rc[i].cbWndExtra;
  421. wndcls.hCursor = LoadCursor(NULL, rc[i].lpszCursor);
  422. wndcls.hbrBackground= rc[i].hbrBackground;
  423. wndcls.lpszClassName= rc[i].lpszClassName;
  424. if (!RegisterClassExWOWW(&wndcls, NULL, rc[i].fnid, 0)) {
  425. RIPMSGF1(RIP_WARNING,
  426. "Failed to register class 0x%x",
  427. (ULONG)rc[i].fnid);
  428. return FALSE;
  429. }
  430. }
  431. return TRUE;
  432. }
  433. /***************************************************************************\
  434. * UserRegisterDDEML
  435. *
  436. * Register all the DDEML classes.
  437. *
  438. * History:
  439. * 01-Dec-1991 Sanfords Created.
  440. \***************************************************************************/
  441. BOOL UserRegisterDDEML(
  442. VOID)
  443. {
  444. WNDCLASSEXA wndclsa;
  445. WNDCLASSEXW wndclsw;
  446. int i;
  447. static CONST struct {
  448. WNDPROC lpfnWndProc;
  449. ULONG cbWndExtra;
  450. LPCWSTR lpszClassName;
  451. } classesW[] = {
  452. {DDEMLMotherWndProc,
  453. sizeof(PCL_INSTANCE_INFO),
  454. L"DDEMLMom"
  455. },
  456. {DDEMLServerWndProc,
  457. sizeof(PSVR_CONV_INFO), // GWL_PSI
  458. L"DDEMLUnicodeServer"
  459. },
  460. {DDEMLClientWndProc,
  461. sizeof(PCL_CONV_INFO) + // GWL_PCI
  462. sizeof(CONVCONTEXT) + // GWL_CONVCONTEXT
  463. sizeof(LONG) + // GWL_CONVSTATE
  464. sizeof(HANDLE) + // GWL_CHINST
  465. sizeof(HANDLE), // GWL_SHINST
  466. L"DDEMLUnicodeClient"
  467. }
  468. };
  469. static CONST struct {
  470. WNDPROC lpfnWndProc;
  471. ULONG cbWndExtra;
  472. LPCSTR lpszClassName;
  473. } classesA[] = {
  474. {DDEMLClientWndProc,
  475. sizeof(PCL_CONV_INFO) + // GWL_PCI
  476. sizeof(CONVCONTEXT) + // GWL_CONVCONTEXT
  477. sizeof(LONG) + // GWL_CONVSTATE
  478. sizeof(HANDLE) + // GWL_CHINST
  479. sizeof(HANDLE), // GWL_SHINST
  480. "DDEMLAnsiClient"
  481. },
  482. {DDEMLServerWndProc,
  483. sizeof(PSVR_CONV_INFO), // GWL_PSI
  484. "DDEMLAnsiServer"
  485. }
  486. };
  487. /*
  488. * Classes are registered via the table.
  489. */
  490. RtlZeroMemory(&wndclsa, sizeof(wndclsa));
  491. wndclsa.cbSize = sizeof(wndclsa);
  492. wndclsa.hInstance = hmodUser;
  493. RtlZeroMemory(&wndclsw, sizeof(wndclsw));
  494. wndclsw.cbSize = sizeof(wndclsw);
  495. wndclsw.hInstance = hmodUser;
  496. for (i = 0; i < ARRAY_SIZE(classesW); ++i) {
  497. wndclsw.lpfnWndProc = classesW[i].lpfnWndProc;
  498. wndclsw.cbWndExtra = classesW[i].cbWndExtra;
  499. wndclsw.lpszClassName = classesW[i].lpszClassName;
  500. if (!RegisterClassExWOWW(&wndclsw, NULL, FNID_DDE_BIT, 0)) {
  501. RIPMSGF1(RIP_WARNING, "Failed to register UNICODE class 0x%x", i);
  502. return FALSE;
  503. }
  504. }
  505. for (i = 0; i < ARRAY_SIZE(classesA); ++i) {
  506. wndclsa.lpfnWndProc = classesA[i].lpfnWndProc;
  507. wndclsa.cbWndExtra = classesA[i].cbWndExtra;
  508. wndclsa.lpszClassName = classesA[i].lpszClassName;
  509. if (!RegisterClassExWOWA(&wndclsa, NULL, FNID_DDE_BIT, 0)) {
  510. RIPMSGF1(RIP_WARNING, "Failed to register ANSI class 0x%x", i);
  511. return FALSE;
  512. }
  513. }
  514. return TRUE;
  515. }
  516. /***************************************************************************\
  517. * LoadAppDlls
  518. *
  519. * History:
  520. *
  521. * 10-Apr-1992 sanfords Birthed.
  522. \***************************************************************************/
  523. VOID LoadAppDlls(
  524. VOID)
  525. {
  526. UNICODE_STRING UnicodeString;
  527. OBJECT_ATTRIBUTES ObjA;
  528. HKEY hKeyWindows;
  529. NTSTATUS Status;
  530. DWORD cbSize;
  531. struct {
  532. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  533. WCHAR awch[24];
  534. } KeyFile;
  535. PKEY_VALUE_PARTIAL_INFORMATION lpKeyFile = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyFile;
  536. DWORD cbSizeCurrent = sizeof(KeyFile);
  537. BOOL bAlloc = FALSE;
  538. if (gfLogonProcess || gfServerProcess || SYSMET(CLEANBOOT)) {
  539. /*
  540. * Don't let the logon process load appdlls because if the dll
  541. * sets any hooks or creates any windows, the logon process
  542. * will fail SetThreadDesktop().
  543. *
  544. * Additionally, we should not load app DLLs when in safe mode.
  545. */
  546. return;
  547. }
  548. /*
  549. * If the image is an NT Native image, we are running in the
  550. * context of the server.
  551. */
  552. if (RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress)->
  553. OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) {
  554. return;
  555. }
  556. RtlInitUnicodeString(&UnicodeString, szWindowsKey);
  557. InitializeObjectAttributes(&ObjA,
  558. &UnicodeString,
  559. OBJ_CASE_INSENSITIVE,
  560. NULL,
  561. NULL);
  562. Status = NtOpenKey(&hKeyWindows, KEY_READ, &ObjA);
  563. if (!NT_SUCCESS(Status)) {
  564. return;
  565. }
  566. /*
  567. * Read the "AppInit_Dlls" value.
  568. */
  569. RtlInitUnicodeString(&UnicodeString, szAppInit);
  570. while (TRUE) {
  571. Status = NtQueryValueKey(hKeyWindows,
  572. &UnicodeString,
  573. KeyValuePartialInformation,
  574. lpKeyFile,
  575. cbSizeCurrent,
  576. &cbSize);
  577. if (Status == STATUS_BUFFER_OVERFLOW) {
  578. if (bAlloc) {
  579. UserGlobalFree(lpKeyFile);
  580. }
  581. lpKeyFile = GlobalAlloc(LPTR, cbSize);
  582. if (!lpKeyFile) {
  583. RIPERR0(ERROR_OUTOFMEMORY,
  584. RIP_WARNING,
  585. "LoadAppDlls failed");
  586. NtClose(hKeyWindows);
  587. return;
  588. }
  589. bAlloc = TRUE;
  590. cbSizeCurrent = cbSize;
  591. continue;
  592. }
  593. break;
  594. }
  595. if (NT_SUCCESS(Status)) {
  596. LPWSTR pszSrc, pszDst, pszBase;
  597. WCHAR ch;
  598. pszBase = pszDst = pszSrc = (LPWSTR)lpKeyFile->Data;
  599. while (*pszSrc != L'\0') {
  600. while (*pszSrc == L' ' || *pszSrc == L',') {
  601. pszSrc++;
  602. }
  603. if (*pszSrc == L'\0') {
  604. break;
  605. }
  606. while (*pszSrc != L',' &&
  607. *pszSrc != L'\0' &&
  608. *pszSrc != L' ') {
  609. *pszDst++ = *pszSrc++;
  610. }
  611. ch = *pszSrc; // get it here cuz its being done in-place.
  612. *pszDst++ = L'\0'; // '\0' is dll name delimiter
  613. LoadLibrary(pszBase);
  614. pszBase = pszDst;
  615. pszSrc++;
  616. if (ch == L'\0') {
  617. break;
  618. }
  619. }
  620. }
  621. if (bAlloc) {
  622. UserGlobalFree(lpKeyFile);
  623. }
  624. NtClose(hKeyWindows);
  625. }
  626. VOID InitOemXlateTables(
  627. VOID)
  628. {
  629. char ach[NCHARS];
  630. WCHAR awch[NCHARS];
  631. WCHAR awchCtrl[NCTRLS];
  632. INT i;
  633. INT cch;
  634. char OemToAnsi[NCHARS];
  635. char AnsiToOem[NCHARS];
  636. for (i = 0; i < NCHARS; i++) {
  637. ach[i] = (char)i;
  638. }
  639. /*
  640. * First generate pAnsiToOem table.
  641. */
  642. if (GetOEMCP() == GetACP()) {
  643. /*
  644. * For far east code pages using MultiByteToWideChar below
  645. * won't work. Conveniently for these code pages the OEM
  646. * CP equals the ANSI codepage making it trivial to compute
  647. * pOemToAnsi and pAnsiToOem arrays
  648. *
  649. */
  650. RtlCopyMemory(OemToAnsi, ach, NCHARS);
  651. RtlCopyMemory(AnsiToOem, ach, NCHARS);
  652. } else {
  653. cch = MultiByteToWideChar(CP_ACP,
  654. MB_PRECOMPOSED,
  655. ach,
  656. NCHARS,
  657. awch,
  658. NCHARS);
  659. UserAssert(cch == NCHARS);
  660. WideCharToMultiByte(CP_OEMCP,
  661. 0,
  662. awch,
  663. NCHARS,
  664. AnsiToOem,
  665. NCHARS,
  666. "_",
  667. NULL);
  668. /*
  669. * Now generate pOemToAnsi table.
  670. */
  671. cch = MultiByteToWideChar(CP_OEMCP,
  672. MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  673. ach,
  674. NCHARS,
  675. awch,
  676. NCHARS);
  677. UserAssert(cch == NCHARS);
  678. /*
  679. * Now patch special cases for Win3.1 compatibility
  680. *
  681. * 0x07 BULLET (glyph 0x2022) must become 0x0007 BELL
  682. * 0x0F WHITE STAR WITH SUN (glyph 0x263C) must become 0x00A4 CURRENCY SIGN
  683. * 0x7F HOUSE (glyph 0x2302) must become 0x007f DELETE
  684. */
  685. awch[0x07] = 0x0007;
  686. awch[0x0F] = 0x00a4;
  687. awch[0x7f] = 0x007f;
  688. WideCharToMultiByte(CP_ACP,
  689. 0,
  690. awch,
  691. NCHARS,
  692. OemToAnsi,
  693. NCHARS,
  694. "_",
  695. NULL);
  696. /*
  697. * Now for all OEM chars < 0x20 (control chars), test whether the glyph
  698. * we have is really in CP_ACP or not. If not, then restore the
  699. * original control character. Note: 0x00 remains 0x00.
  700. */
  701. MultiByteToWideChar(CP_ACP, 0, OemToAnsi, NCTRLS, awchCtrl, NCTRLS);
  702. for (i = 1; i < NCTRLS; i++) {
  703. if (awchCtrl[i] != awch[i]) {
  704. OemToAnsi[i] = (char)i;
  705. }
  706. }
  707. }
  708. NtUserCallTwoParam((ULONG_PTR)OemToAnsi, (ULONG_PTR)AnsiToOem, SFI_INITANSIOEM);
  709. }
  710. const PFNCLIENT pfnClientA = {
  711. (KPROC)ScrollBarWndProcA,
  712. (KPROC)DefWindowProcA,
  713. (KPROC)MenuWndProcA,
  714. (KPROC)DesktopWndProcA,
  715. (KPROC)DefWindowProcA,
  716. (KPROC)DefWindowProcA,
  717. (KPROC)DefWindowProcA,
  718. (KPROC)ButtonWndProcA,
  719. (KPROC)ComboBoxWndProcA,
  720. (KPROC)ComboListBoxWndProcA,
  721. (KPROC)DefDlgProcA,
  722. (KPROC)EditWndProcA,
  723. (KPROC)ListBoxWndProcA,
  724. (KPROC)MDIClientWndProcA,
  725. (KPROC)StaticWndProcA,
  726. (KPROC)ImeWndProcA,
  727. (KPROC)fnHkINLPCWPSTRUCTA,
  728. (KPROC)fnHkINLPCWPRETSTRUCTA,
  729. (KPROC)DispatchHookA,
  730. (KPROC)DispatchDefWindowProcA,
  731. (KPROC)DispatchClientMessage,
  732. (KPROC)MDIActivateDlgProcA};
  733. const PFNCLIENT pfnClientW = {
  734. (KPROC)ScrollBarWndProcW,
  735. (KPROC)DefWindowProcW,
  736. (KPROC)MenuWndProcW,
  737. (KPROC)DesktopWndProcW,
  738. (KPROC)DefWindowProcW,
  739. (KPROC)DefWindowProcW,
  740. (KPROC)DefWindowProcW,
  741. (KPROC)ButtonWndProcW,
  742. (KPROC)ComboBoxWndProcW,
  743. (KPROC)ComboListBoxWndProcW,
  744. (KPROC)DefDlgProcW,
  745. (KPROC)EditWndProcW,
  746. (KPROC)ListBoxWndProcW,
  747. (KPROC)MDIClientWndProcW,
  748. (KPROC)StaticWndProcW,
  749. (KPROC)ImeWndProcW,
  750. (KPROC)fnHkINLPCWPSTRUCTW,
  751. (KPROC)fnHkINLPCWPRETSTRUCTW,
  752. (KPROC)DispatchHookW,
  753. (KPROC)DispatchDefWindowProcW,
  754. (KPROC)DispatchClientMessage,
  755. (KPROC)MDIActivateDlgProcW};
  756. const PFNCLIENTWORKER pfnClientWorker = {
  757. (KPROC)ButtonWndProcWorker,
  758. (KPROC)ComboBoxWndProcWorker,
  759. (KPROC)ListBoxWndProcWorker,
  760. (KPROC)DefDlgProcWorker,
  761. (KPROC)EditWndProcWorker,
  762. (KPROC)ListBoxWndProcWorker,
  763. (KPROC)MDIClientWndProcWorker,
  764. (KPROC)StaticWndProcWorker,
  765. (KPROC)ImeWndProcWorker};
  766. /***************************************************************************\
  767. * ClientThreadSetup
  768. *
  769. \***************************************************************************/
  770. BOOL ClientThreadSetup(
  771. VOID)
  772. {
  773. PCLIENTINFO pci;
  774. BOOL fFirstThread;
  775. DWORD ConnectState;
  776. /*
  777. * NT BUG 268642: Only the first thread calls GdiProcessSetup but all the
  778. * other threads must wait until the setup for GDI is finished.
  779. *
  780. * We can safely use gcsAccelCache critical section to protect this (even
  781. * though the name is not intuitive at all)
  782. */
  783. RtlEnterCriticalSection(&gcsAccelCache);
  784. fFirstThread = gfFirstThread;
  785. /*
  786. * Setup GDI before continuing.
  787. */
  788. if (fFirstThread) {
  789. gfFirstThread = FALSE;
  790. GdiProcessSetup();
  791. }
  792. RtlLeaveCriticalSection(&gcsAccelCache);
  793. /*
  794. * We've already checked to see if we need to connect
  795. * (i.e. NtCurrentTeb()->Win32ThreadInfo == NULL). This routine
  796. * just does the connecting. If we've already been through here
  797. * once, don't do it again.
  798. */
  799. pci = GetClientInfo();
  800. if (pci->CI_flags & CI_INITIALIZED) {
  801. RIPMSG0(RIP_ERROR, "Already initialized!");
  802. return FALSE;
  803. }
  804. /*
  805. * Create the queue info and thread info. Only once for this process do
  806. * we pass client side addresses to the server (for server callbacks).
  807. */
  808. if (gfServerProcess && fFirstThread) {
  809. USERCONNECT userconnect;
  810. NTSTATUS Status;
  811. /*
  812. * We know that the shared info is now available in
  813. * the kernel. Map it into the server process.
  814. */
  815. userconnect.ulVersion = USERCURRENTVERSION;
  816. userconnect.dwDispatchCount = gDispatchTableValues;
  817. Status = NtUserProcessConnect(NtCurrentProcess(),
  818. &userconnect,
  819. sizeof(USERCONNECT));
  820. if (!NT_SUCCESS(Status)) {
  821. return FALSE;
  822. }
  823. gSharedInfo = userconnect.siClient;
  824. gpsi = gSharedInfo.psi;
  825. UserAssert(gpsi);
  826. UserAssert(pfnClientA.pfnScrollBarWndProc == (KPROC)ScrollBarWndProcA);
  827. UserAssert(pfnClientA.pfnTitleWndProc == (KPROC)DefWindowProcA);
  828. UserAssert(pfnClientA.pfnMenuWndProc == (KPROC)MenuWndProcA);
  829. UserAssert(pfnClientA.pfnDesktopWndProc == (KPROC)DesktopWndProcA);
  830. UserAssert(pfnClientA.pfnDefWindowProc == (KPROC)DefWindowProcA);
  831. UserAssert(pfnClientA.pfnMessageWindowProc == (KPROC)DefWindowProcA);
  832. UserAssert(pfnClientA.pfnHkINLPCWPSTRUCT == (KPROC)fnHkINLPCWPSTRUCTA);
  833. UserAssert(pfnClientA.pfnHkINLPCWPRETSTRUCT == (KPROC)fnHkINLPCWPRETSTRUCTA);
  834. UserAssert(pfnClientA.pfnButtonWndProc == (KPROC)ButtonWndProcA);
  835. UserAssert(pfnClientA.pfnComboBoxWndProc == (KPROC)ComboBoxWndProcA);
  836. UserAssert(pfnClientA.pfnComboListBoxProc == (KPROC)ComboListBoxWndProcA);
  837. UserAssert(pfnClientA.pfnDialogWndProc == (KPROC)DefDlgProcA);
  838. UserAssert(pfnClientA.pfnEditWndProc == (KPROC)EditWndProcA);
  839. UserAssert(pfnClientA.pfnListBoxWndProc == (KPROC)ListBoxWndProcA);
  840. UserAssert(pfnClientA.pfnMDIActivateDlgProc == (KPROC)MDIActivateDlgProcA);
  841. UserAssert(pfnClientA.pfnMDIClientWndProc == (KPROC)MDIClientWndProcA);
  842. UserAssert(pfnClientA.pfnStaticWndProc == (KPROC)StaticWndProcA);
  843. UserAssert(pfnClientA.pfnDispatchHook == (KPROC)DispatchHookA);
  844. UserAssert(pfnClientA.pfnDispatchMessage == (KPROC)DispatchClientMessage);
  845. UserAssert(pfnClientA.pfnImeWndProc == (KPROC)ImeWndProcA);
  846. UserAssert(pfnClientW.pfnScrollBarWndProc == (KPROC)ScrollBarWndProcW);
  847. UserAssert(pfnClientW.pfnTitleWndProc == (KPROC)DefWindowProcW);
  848. UserAssert(pfnClientW.pfnMenuWndProc == (KPROC)MenuWndProcW);
  849. UserAssert(pfnClientW.pfnDesktopWndProc == (KPROC)DesktopWndProcW);
  850. UserAssert(pfnClientW.pfnDefWindowProc == (KPROC)DefWindowProcW);
  851. UserAssert(pfnClientW.pfnMessageWindowProc == (KPROC)DefWindowProcW);
  852. UserAssert(pfnClientW.pfnHkINLPCWPSTRUCT == (KPROC)fnHkINLPCWPSTRUCTW);
  853. UserAssert(pfnClientW.pfnHkINLPCWPRETSTRUCT == (KPROC)fnHkINLPCWPRETSTRUCTW);
  854. UserAssert(pfnClientW.pfnButtonWndProc == (KPROC)ButtonWndProcW);
  855. UserAssert(pfnClientW.pfnComboBoxWndProc == (KPROC)ComboBoxWndProcW);
  856. UserAssert(pfnClientW.pfnComboListBoxProc == (KPROC)ComboListBoxWndProcW);
  857. UserAssert(pfnClientW.pfnDialogWndProc == (KPROC)DefDlgProcW);
  858. UserAssert(pfnClientW.pfnEditWndProc == (KPROC)EditWndProcW);
  859. UserAssert(pfnClientW.pfnListBoxWndProc == (KPROC)ListBoxWndProcW);
  860. UserAssert(pfnClientW.pfnMDIActivateDlgProc == (KPROC)MDIActivateDlgProcW);
  861. UserAssert(pfnClientW.pfnMDIClientWndProc == (KPROC)MDIClientWndProcW);
  862. UserAssert(pfnClientW.pfnStaticWndProc == (KPROC)StaticWndProcW);
  863. UserAssert(pfnClientW.pfnDispatchHook == (KPROC)DispatchHookW);
  864. UserAssert(pfnClientW.pfnDispatchMessage == (KPROC)DispatchClientMessage);
  865. UserAssert(pfnClientW.pfnImeWndProc == (KPROC)ImeWndProcW);
  866. UserAssert(pfnClientWorker.pfnButtonWndProc == (KPROC)ButtonWndProcWorker);
  867. UserAssert(pfnClientWorker.pfnComboBoxWndProc == (KPROC)ComboBoxWndProcWorker);
  868. UserAssert(pfnClientWorker.pfnComboListBoxProc == (KPROC)ListBoxWndProcWorker);
  869. UserAssert(pfnClientWorker.pfnDialogWndProc == (KPROC)DefDlgProcWorker);
  870. UserAssert(pfnClientWorker.pfnEditWndProc == (KPROC)EditWndProcWorker);
  871. UserAssert(pfnClientWorker.pfnListBoxWndProc == (KPROC)ListBoxWndProcWorker);
  872. UserAssert(pfnClientWorker.pfnMDIClientWndProc == (KPROC)MDIClientWndProcWorker);
  873. UserAssert(pfnClientWorker.pfnStaticWndProc == (KPROC)StaticWndProcWorker);
  874. UserAssert(pfnClientWorker.pfnImeWndProc == (KPROC)ImeWndProcWorker);
  875. #if DBG
  876. {
  877. PULONG_PTR pdw;
  878. /*
  879. * Make sure that everyone got initialized
  880. */
  881. for (pdw = (PULONG_PTR)&pfnClientA;
  882. (ULONG_PTR)pdw<(ULONG_PTR)(&pfnClientA) + sizeof(pfnClientA);
  883. pdw++) {
  884. UserAssert(*pdw);
  885. }
  886. for (pdw = (PULONG_PTR)&pfnClientW;
  887. (ULONG_PTR)pdw<(ULONG_PTR)(&pfnClientW) + sizeof(pfnClientW);
  888. pdw++) {
  889. UserAssert(*pdw);
  890. }
  891. }
  892. #endif
  893. #if DBG
  894. {
  895. extern CONST INT gcapfnScSendMessage;
  896. BOOLEAN apfnCheckMessage[64];
  897. int i;
  898. /*
  899. * Do some verification of the message table. Since we only have
  900. * 6 bits to store the function index, the function table can have
  901. * at most 64 entries. Also verify that none of the indexes point
  902. * past the end of the table and that all the function entries
  903. * are used.
  904. */
  905. UserAssert(gcapfnScSendMessage <= 64);
  906. RtlZeroMemory(apfnCheckMessage, sizeof(apfnCheckMessage));
  907. for (i = 0; i < WM_USER; i++) {
  908. UserAssert(MessageTable[i].iFunction < gcapfnScSendMessage);
  909. apfnCheckMessage[MessageTable[i].iFunction] = TRUE;
  910. }
  911. for (i = 0; i < gcapfnScSendMessage; i++) {
  912. UserAssert(apfnCheckMessage[i]);
  913. }
  914. }
  915. #endif
  916. }
  917. /*
  918. * Pass the function pointer arrays to the kernel. This also establishes
  919. * the kernel state for the thread. If ClientThreadSetup is called from
  920. * CsrConnectToUser this call will raise an exception if the thread
  921. * cannot be converted to a gui thread. The exception is handled in
  922. * CsrConnectToUser.
  923. */
  924. #if DBG && !defined(BUILD_WOW6432)
  925. /*
  926. * On debug systems, go to the kernel for all processes to verify we're
  927. * loading user32.dll at the right address.
  928. */
  929. if (fFirstThread) {
  930. #elif defined(BUILD_WOW6432)
  931. /*
  932. * On WOW64 always register the client fns.
  933. */
  934. {
  935. #else
  936. if (gfServerProcess && fFirstThread) {
  937. #endif
  938. if (!NT_SUCCESS(NtUserInitializeClientPfnArrays(&pfnClientA, &pfnClientW, &pfnClientWorker, hmodUser))) {
  939. RIPERR0(ERROR_OUTOFMEMORY,
  940. RIP_WARNING,
  941. "NtUserInitializeClientPfnArrays failed");
  942. return FALSE;
  943. }
  944. }
  945. /*
  946. * Mark this thread as being initialized. If the connection to the
  947. * server fails, NtCurrentTeb()->Win32ThreadInfo will remain NULL.
  948. */
  949. pci->CI_flags |= CI_INITIALIZED;
  950. /*
  951. * Some initialization only has to occur once per process.
  952. */
  953. if (fFirstThread) {
  954. ConnectState = (DWORD)NtUserCallNoParam(SFI_REMOTECONNECTSTATE);
  955. /*
  956. * Winstation Winlogon and CSR must do graphics initialization
  957. * after the connect.
  958. */
  959. if (ConnectState != CTX_W32_CONNECT_STATE_IDLE) {
  960. if ((ghdcBits2 = CreateCompatibleDC(NULL)) == NULL) {
  961. RIPERR0(ERROR_OUTOFMEMORY, RIP_WARNING, "ghdcBits2 creation failed");
  962. return FALSE;
  963. }
  964. if (!InitClientDrawing()) {
  965. RIPERR0(ERROR_OUTOFMEMORY, RIP_WARNING, "InitClientDrawing failed");
  966. return FALSE;
  967. }
  968. }
  969. gfSystemInitialized = NtUserGetThreadDesktop(GetCurrentThreadId(),
  970. NULL) != NULL;
  971. /*
  972. * If an lpk is loaded for this process notify the kernel.
  973. */
  974. if (gdwLpkEntryPoints) {
  975. NtUserCallOneParam(gdwLpkEntryPoints, SFI_REGISTERLPK);
  976. }
  977. if (gfServerProcess || GetClientInfo()->pDeskInfo == NULL) {
  978. /*
  979. * Perform any server initialization.
  980. */
  981. UserAssert(gpsi);
  982. if (pdiLocal = UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(DESKTOPINFO))) {
  983. GetClientInfo()->pDeskInfo = pdiLocal;
  984. } else {
  985. RIPERR0(ERROR_OUTOFMEMORY, RIP_WARNING, "pdiLocal creation failed");
  986. return FALSE;
  987. }
  988. }
  989. if (gfServerProcess) {
  990. /*
  991. * Winstation Winlogon and CSR must do graphics initialization
  992. * after the connect.
  993. */
  994. if (ConnectState != CTX_W32_CONNECT_STATE_IDLE) {
  995. if (!LoadCursorsAndIcons()) {
  996. RIPERR0(ERROR_OUTOFMEMORY, RIP_WARNING, "LoadCursorsAndIcons failed");
  997. return FALSE;
  998. }
  999. }
  1000. InitOemXlateTables();
  1001. }
  1002. LoadAppDlls();
  1003. } else if (gfServerProcess) {
  1004. GetClientInfo()->pDeskInfo = pdiLocal;
  1005. }
  1006. pci->lpClassesRegistered = &gbClassesRegistered;
  1007. #ifndef LAZY_CLASS_INIT
  1008. /*
  1009. * Kernel sets CI_REGISTERCLASSES when appropriate (i.e. always
  1010. * for the first thread and for other threads if the last GUI
  1011. * thread for a process has exited) except for the CSR proces.
  1012. * For the CSR process, you must register the classes on the
  1013. * first thread anyways.
  1014. */
  1015. if (fFirstThread || (pci->CI_flags & CI_REGISTERCLASSES)) {
  1016. /*
  1017. * If it's the first thread we already made it to the kernel
  1018. * to get the ConnectState.
  1019. */
  1020. if (!fFirstThread) {
  1021. ConnectState = (DWORD)NtUserCallNoParam(SFI_REMOTECONNECTSTATE);
  1022. }
  1023. if (ConnectState != CTX_W32_CONNECT_STATE_IDLE) {
  1024. /*
  1025. * Register the control classes.
  1026. */
  1027. if (!UserRegisterControls() || !UserRegisterDDEML()) {
  1028. return FALSE;
  1029. }
  1030. }
  1031. }
  1032. #endif
  1033. return TRUE;
  1034. }
  1035. /***************************************************************************\
  1036. * Dispatch routines.
  1037. *
  1038. *
  1039. \***************************************************************************/
  1040. HLOCAL WINAPI DispatchLocalAlloc(
  1041. UINT uFlags,
  1042. UINT uBytes,
  1043. HANDLE hInstance)
  1044. {
  1045. UNREFERENCED_PARAMETER(hInstance);
  1046. return LocalAlloc(uFlags, uBytes);
  1047. }
  1048. HLOCAL WINAPI DispatchLocalReAlloc(
  1049. HLOCAL hMem,
  1050. UINT uBytes,
  1051. UINT uFlags,
  1052. HANDLE hInstance,
  1053. PVOID* ppv)
  1054. {
  1055. UNREFERENCED_PARAMETER(hInstance);
  1056. UNREFERENCED_PARAMETER(ppv);
  1057. return LocalReAlloc(hMem, uBytes, uFlags);
  1058. }
  1059. LPVOID WINAPI DispatchLocalLock(
  1060. HLOCAL hMem,
  1061. HANDLE hInstance)
  1062. {
  1063. UNREFERENCED_PARAMETER(hInstance);
  1064. return LocalLock(hMem);
  1065. }
  1066. BOOL WINAPI DispatchLocalUnlock(
  1067. HLOCAL hMem,
  1068. HANDLE hInstance)
  1069. {
  1070. UNREFERENCED_PARAMETER(hInstance);
  1071. return LocalUnlock(hMem);
  1072. }
  1073. UINT WINAPI DispatchLocalSize(
  1074. HLOCAL hMem,
  1075. HANDLE hInstance)
  1076. {
  1077. UNREFERENCED_PARAMETER(hInstance);
  1078. return (UINT)LocalSize(hMem);
  1079. }
  1080. HLOCAL WINAPI DispatchLocalFree(
  1081. HLOCAL hMem,
  1082. HANDLE hInstance)
  1083. {
  1084. UNREFERENCED_PARAMETER(hInstance);
  1085. return LocalFree(hMem);
  1086. }
  1087. /***************************************************************************\
  1088. * Allocation routines for RTL functions.
  1089. *
  1090. *
  1091. \***************************************************************************/
  1092. PVOID UserRtlAllocMem(
  1093. ULONG uBytes)
  1094. {
  1095. return UserLocalAlloc(HEAP_ZERO_MEMORY, uBytes);
  1096. }
  1097. VOID UserRtlFreeMem(
  1098. PVOID pMem)
  1099. {
  1100. UserLocalFree(pMem);
  1101. }
  1102. /***************************************************************************\
  1103. * InitClientDrawing
  1104. *
  1105. * History:
  1106. * 20-Aug-1992 mikeke Created
  1107. \***************************************************************************/
  1108. BOOL InitClientDrawing(
  1109. VOID)
  1110. {
  1111. static CONST WORD patGray[8] = {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
  1112. BOOL fSuccess = TRUE;
  1113. HBITMAP hbmGray = CreateBitmap(8, 8, 1, 1, (LPBYTE)patGray);
  1114. fSuccess &= !!hbmGray;
  1115. UserAssert(ghbrWhite == NULL);
  1116. ghbrWhite = GetStockObject(WHITE_BRUSH);
  1117. fSuccess &= !!ghbrWhite;
  1118. UserAssert(ghbrBlack == NULL);
  1119. ghbrBlack = GetStockObject(BLACK_BRUSH);
  1120. fSuccess &= !!ghbrBlack;
  1121. /*
  1122. * Create the global-objects for client drawing.
  1123. */
  1124. ghbrWindowText = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
  1125. fSuccess &= !!ghbrWindowText;
  1126. ghFontSys = GetStockObject(SYSTEM_FONT);
  1127. fSuccess &= !!ghFontSys;
  1128. ghdcGray = CreateCompatibleDC(NULL);
  1129. fSuccess &= !!ghdcGray;
  1130. if (!fSuccess) {
  1131. RIPMSG0(RIP_WARNING, "InitClientDrawing failed to allocate resources");
  1132. return FALSE;
  1133. }
  1134. /*
  1135. * Setup the gray surface.
  1136. */
  1137. SelectObject(ghdcGray, hbmGray);
  1138. SelectObject(ghdcGray, ghFontSys);
  1139. SelectObject(ghdcGray, KHBRUSH_TO_HBRUSH(gpsi->hbrGray));
  1140. /*
  1141. * Setup the gray attributes.
  1142. */
  1143. SetBkMode(ghdcGray, OPAQUE);
  1144. SetTextColor(ghdcGray, 0x00000000L);
  1145. SetBkColor(ghdcGray, 0x00FFFFFFL);
  1146. gcxGray = 8;
  1147. gcyGray = 8;
  1148. return TRUE;
  1149. }
  1150. VOID
  1151. InitializeLpkHooks(
  1152. CONST FARPROC *lpfpLpkHooks)
  1153. {
  1154. /*
  1155. * Called from GdiInitializeLanguagePack(). Remember what entry points
  1156. * are supported. Pass the information to the kernel the first time this
  1157. * process connects in ClientThreadSetup().
  1158. */
  1159. if (lpfpLpkHooks[LPK_TABBED_TEXT_OUT]) {
  1160. fpLpkTabbedTextOut = (FPLPKTABBEDTEXTOUT)lpfpLpkHooks[LPK_TABBED_TEXT_OUT];
  1161. gdwLpkEntryPoints |= (1 << LPK_TABBED_TEXT_OUT);
  1162. }
  1163. if (lpfpLpkHooks[LPK_PSM_TEXT_OUT]) {
  1164. fpLpkPSMTextOut = (FPLPKPSMTEXTOUT)lpfpLpkHooks[LPK_PSM_TEXT_OUT];
  1165. gdwLpkEntryPoints |= (1 << LPK_PSM_TEXT_OUT);
  1166. }
  1167. if (lpfpLpkHooks[LPK_DRAW_TEXT_EX]) {
  1168. fpLpkDrawTextEx = (FPLPKDRAWTEXTEX)lpfpLpkHooks[LPK_DRAW_TEXT_EX];
  1169. gdwLpkEntryPoints |= (1 << LPK_DRAW_TEXT_EX);
  1170. }
  1171. if (lpfpLpkHooks[LPK_EDIT_CONTROL]) {
  1172. fpLpkEditControl = (PLPKEDITCALLOUT)lpfpLpkHooks[LPK_EDIT_CONTROL];
  1173. gdwLpkEntryPoints |= (1 << LPK_EDIT_CONTROL);
  1174. }
  1175. }
  1176. /***************************************************************************\
  1177. *
  1178. * CtxInitUser32
  1179. *
  1180. * Called by CreateWindowStation() and winsrv.dll DoConnect routine.
  1181. *
  1182. * Winstation Winlogon and CSR must do graphics initialization after the
  1183. * connect. This is because no video driver is loaded until then.
  1184. *
  1185. * This routine must contain everything that was skipped before.
  1186. *
  1187. * History:
  1188. * Dec-11-1997 clupu Ported from Citrix
  1189. \***************************************************************************/
  1190. BOOL CtxInitUser32(
  1191. VOID)
  1192. {
  1193. /*
  1194. * Only do once.
  1195. */
  1196. if (ghdcBits2 != NULL || NtCurrentPeb()->SessionId == 0) {
  1197. return TRUE;
  1198. }
  1199. ghdcBits2 = CreateCompatibleDC(NULL);
  1200. if (ghdcBits2 == NULL) {
  1201. RIPMSG0(RIP_WARNING, "Could not allocate ghdcBits2");
  1202. return FALSE;
  1203. }
  1204. if (!InitClientDrawing()) {
  1205. RIPMSG0(RIP_WARNING, "InitClientDrawing failed");
  1206. return FALSE;
  1207. }
  1208. if (gfServerProcess) {
  1209. if (!LoadCursorsAndIcons()) {
  1210. RIPMSG0(RIP_WARNING, "LoadCursorsAndIcons failed");
  1211. return FALSE;
  1212. }
  1213. }
  1214. #ifndef LAZY_CLASS_INIT
  1215. /*
  1216. * Register the control and DDE classes.
  1217. */
  1218. if (!UserRegisterControls() || !UserRegisterDDEML()) {
  1219. return FALSE;
  1220. }
  1221. #endif
  1222. return TRUE;
  1223. }
  1224. #if DBG
  1225. DWORD GetRipComponent(
  1226. VOID)
  1227. {
  1228. return RIP_USER;
  1229. }
  1230. VOID SetRipFlags(
  1231. DWORD dwRipFlags)
  1232. {
  1233. NtUserSetRipFlags(dwRipFlags);
  1234. }
  1235. VOID SetDbgTag(
  1236. int tag,
  1237. DWORD dwBitFlags)
  1238. {
  1239. NtUserSetDbgTag(tag, dwBitFlags);
  1240. }
  1241. VOID PrivateSetRipFlags(
  1242. DWORD dwRipFlags)
  1243. {
  1244. gDbgGlobals.dwTouchedMask |= USERDBG_FLAGSTOUCHED;
  1245. gDbgGlobals.dwRIPFlags = dwRipFlags;
  1246. }
  1247. VOID PrivateSetDbgTag(
  1248. int tag,
  1249. DWORD dwBitFlags)
  1250. {
  1251. gDbgGlobals.dwTouchedMask |= USERDBG_TAGSTOUCHED;
  1252. gDbgGlobals.adwDBGTAGFlags[tag] = dwBitFlags;
  1253. }
  1254. DWORD GetDbgTagFlags(
  1255. int tag)
  1256. {
  1257. if (gDbgGlobals.dwTouchedMask & USERDBG_TAGSTOUCHED) {
  1258. return gDbgGlobals.adwDBGTAGFlags[tag];
  1259. } else {
  1260. return (gpsi != NULL ? gpsi->adwDBGTAGFlags[tag] : 0);
  1261. }
  1262. }
  1263. DWORD GetRipFlags(
  1264. VOID)
  1265. {
  1266. if (gDbgGlobals.dwTouchedMask & USERDBG_FLAGSTOUCHED) {
  1267. return gDbgGlobals.dwRIPFlags;
  1268. } else {
  1269. return (gpsi != NULL ? gpsi->dwRIPFlags : RIPF_DEFAULT);
  1270. }
  1271. }
  1272. #endif