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.

3463 lines
98 KiB

  1. /**************************************************************************\
  2. * Module Name: server.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Server support routines for the CSR stuff. This basically performs the
  7. * startup/initialization for USER.
  8. *
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include "prefetch.h"
  13. extern WORD gDispatchTableValues;
  14. BOOL gbUserInitialized;
  15. /*
  16. * Initialization Routines (external).
  17. */
  18. NTSTATUS InitQEntryLookaside(VOID);
  19. NTSTATUS InitSMSLookaside(VOID);
  20. NTSTATUS InitCreateSharedSection(VOID);
  21. NTSTATUS InitCreateObjectDirectory(VOID);
  22. BOOL InitCreateUserSubsystem(VOID);
  23. VOID InitFunctionTables(VOID);
  24. VOID InitMessageTables(VOID);
  25. VOID InitWindowMsgTable(PBYTE*, PUINT, CONST WORD*);
  26. VOID VerifySyncOnlyMessages(VOID);
  27. BOOL InitOLEFormats(VOID);
  28. NTSTATUS Win32UserInitialize(VOID);
  29. #pragma alloc_text(INIT, InitCreateSharedSection)
  30. #pragma alloc_text(INIT, InitCreateUserCrit)
  31. #pragma alloc_text(INIT, InitCreateObjectDirectory)
  32. #pragma alloc_text(INIT, InitCreateUserSubsystem)
  33. #pragma alloc_text(INIT, InitFunctionTables)
  34. #pragma alloc_text(INIT, InitMessageTables)
  35. #pragma alloc_text(INIT, InitWindowMsgTable)
  36. #pragma alloc_text(INIT, VerifySyncOnlyMessages)
  37. #pragma alloc_text(INIT, InitOLEFormats)
  38. #pragma alloc_text(INIT, Win32UserInitialize)
  39. /*
  40. * Constants pertaining to the user-initialization.
  41. */
  42. #define USRINIT_SHAREDSECT_SIZE 32
  43. #define USRINIT_ATOMBUCKET_SIZE 37
  44. #define USRINIT_WINDOWSECT_SIZE 512
  45. #define USRINIT_NOIOSECT_SIZE 128
  46. #define USRINIT_SHAREDSECT_BUFF_SIZE 640
  47. #define USRINIT_SHAREDSECT_READ_SIZE (USRINIT_SHAREDSECT_BUFF_SIZE-33)
  48. /***************************************************************************\
  49. * Globals stored in the INIT section. These should only be accessed at
  50. * load time!
  51. \***************************************************************************/
  52. #ifdef ALLOC_DATA_PRAGMA
  53. #pragma data_seg("INIT$Data")
  54. #endif
  55. CONST WCHAR szCHECKPOINT_PROP_NAME[] = L"SysCP";
  56. CONST WCHAR szDDETRACK_PROP_NAME[] = L"SysDT";
  57. CONST WCHAR szQOS_PROP_NAME[] = L"SysQOS";
  58. CONST WCHAR szDDEIMP_PROP_NAME[] = L"SysDDEI";
  59. CONST WCHAR szWNDOBJ_PROP_NAME[] = L"SysWNDO";
  60. CONST WCHAR szIMELEVEL_PROP_NAME[] = L"SysIMEL";
  61. CONST WCHAR szLAYER_PROP_NAME[] = L"SysLayer";
  62. CONST WCHAR szUSER32[] = L"USER32";
  63. CONST WCHAR szCONTEXTHELPIDPROP[] = L"SysCH";
  64. CONST WCHAR szICONSM_PROP_NAME[] = L"SysICS";
  65. CONST WCHAR szICON_PROP_NAME[] = ICON_PROP_NAME;
  66. CONST WCHAR szSHELLHOOK[] = L"SHELLHOOK";
  67. CONST WCHAR szACTIVATESHELLWINDOW[] = L"ACTIVATESHELLWINDOW";
  68. CONST WCHAR szOTHERWINDOWCREATED[] = L"OTHERWINDOWCREATED";
  69. CONST WCHAR szOTHERWINDOWDESTROYED[] = L"OTHERWINDOWDESTROYED";
  70. CONST WCHAR szOLEMAINTHREADWNDCLASS[] = L"OleMainThreadWndClass";
  71. CONST WCHAR szFLASHWSTATE[] = L"FlashWState";
  72. #ifdef HUNGAPP_GHOSTING
  73. CONST WCHAR szGHOST[] = L"Ghost";
  74. #endif
  75. CONST WCHAR szSHADOW[] = L"SysShadow";
  76. /***************************************************************************\
  77. * Message Tables
  78. *
  79. * DefDlgProc
  80. * MenuWndProc
  81. * ScrollBarWndProc
  82. * StaticWndProc
  83. * ButtonWndProc
  84. * ListboxWndProc
  85. * ComboWndProc
  86. * EditWndProc
  87. * DefWindowMsgs
  88. * DefWindowSpecMsgs
  89. *
  90. * These are used in InitMessageTables() to initialize gSharedInfo.awmControl[]
  91. * using the INITMSGTABLE() macro.
  92. *
  93. * 25-Aug-1995 ChrisWil Created comment block.
  94. \***************************************************************************/
  95. CONST WORD gawDefDlgProc[] = {
  96. WM_COMPAREITEM,
  97. WM_VKEYTOITEM,
  98. WM_CHARTOITEM,
  99. WM_INITDIALOG,
  100. WM_QUERYDRAGICON,
  101. WM_CTLCOLOR,
  102. WM_CTLCOLORMSGBOX,
  103. WM_CTLCOLOREDIT,
  104. WM_CTLCOLORLISTBOX,
  105. WM_CTLCOLORBTN,
  106. WM_CTLCOLORDLG,
  107. WM_CTLCOLORSCROLLBAR,
  108. WM_CTLCOLORSTATIC,
  109. WM_ERASEBKGND,
  110. WM_SHOWWINDOW,
  111. WM_SYSCOMMAND,
  112. WM_SYSKEYDOWN,
  113. WM_ACTIVATE,
  114. WM_SETFOCUS,
  115. WM_CLOSE,
  116. WM_NCDESTROY,
  117. WM_FINALDESTROY,
  118. DM_REPOSITION,
  119. DM_SETDEFID,
  120. DM_GETDEFID,
  121. WM_NEXTDLGCTL,
  122. WM_ENTERMENULOOP,
  123. WM_LBUTTONDOWN,
  124. WM_NCLBUTTONDOWN,
  125. WM_GETFONT,
  126. WM_NOTIFYFORMAT,
  127. WM_INPUTLANGCHANGEREQUEST,
  128. 0
  129. };
  130. CONST WORD gawMenuWndProc[] = {
  131. WM_NCCREATE,
  132. WM_FINALDESTROY,
  133. WM_PAINT,
  134. WM_NCCALCSIZE,
  135. WM_CHAR,
  136. WM_SYSCHAR,
  137. WM_KEYDOWN,
  138. WM_SYSKEYDOWN,
  139. WM_TIMER,
  140. MN_SETHMENU,
  141. MN_SIZEWINDOW,
  142. MN_OPENHIERARCHY,
  143. MN_CLOSEHIERARCHY,
  144. MN_SELECTITEM,
  145. MN_SELECTFIRSTVALIDITEM,
  146. MN_CANCELMENUS,
  147. MN_FINDMENUWINDOWFROMPOINT,
  148. MN_SHOWPOPUPWINDOW,
  149. MN_BUTTONDOWN,
  150. MN_MOUSEMOVE,
  151. MN_BUTTONUP,
  152. MN_SETTIMERTOOPENHIERARCHY,
  153. WM_ACTIVATE,
  154. MN_GETHMENU,
  155. MN_DBLCLK,
  156. MN_ACTIVATEPOPUP,
  157. MN_ENDMENU,
  158. MN_DODRAGDROP,
  159. WM_ACTIVATEAPP,
  160. WM_MOUSELEAVE,
  161. WM_SIZE,
  162. WM_MOVE,
  163. WM_NCHITTEST,
  164. WM_NCPAINT,
  165. WM_PRINT,
  166. WM_PRINTCLIENT,
  167. WM_ERASEBKGND,
  168. WM_WINDOWPOSCHANGING,
  169. WM_WINDOWPOSCHANGED,
  170. 0
  171. };
  172. CONST WORD gawDesktopWndProc[] = {
  173. WM_PAINT,
  174. WM_ERASEBKGND,
  175. 0
  176. };
  177. CONST WORD gawScrollBarWndProc[] = {
  178. WM_CREATE,
  179. WM_SETFOCUS,
  180. WM_KILLFOCUS,
  181. WM_ERASEBKGND,
  182. WM_PAINT,
  183. WM_LBUTTONDBLCLK,
  184. WM_LBUTTONDOWN,
  185. WM_KEYUP,
  186. WM_KEYDOWN,
  187. WM_ENABLE,
  188. SBM_ENABLE_ARROWS,
  189. SBM_SETPOS,
  190. SBM_SETRANGEREDRAW,
  191. SBM_SETRANGE,
  192. SBM_SETSCROLLINFO,
  193. SBM_GETSCROLLINFO,
  194. SBM_GETSCROLLBARINFO,
  195. WM_PRINTCLIENT,
  196. WM_MOUSEMOVE,
  197. WM_MOUSELEAVE,
  198. 0
  199. };
  200. CONST WORD gawStaticWndProc[] = {
  201. STM_GETICON,
  202. STM_GETIMAGE,
  203. STM_SETICON,
  204. STM_SETIMAGE,
  205. WM_ERASEBKGND,
  206. WM_PAINT,
  207. WM_PRINTCLIENT,
  208. WM_CREATE,
  209. WM_DESTROY,
  210. WM_NCCREATE,
  211. WM_NCDESTROY,
  212. WM_FINALDESTROY,
  213. WM_NCHITTEST,
  214. WM_LBUTTONDOWN,
  215. WM_NCLBUTTONDOWN,
  216. WM_LBUTTONDBLCLK,
  217. WM_NCLBUTTONDBLCLK,
  218. WM_SETTEXT,
  219. WM_ENABLE,
  220. WM_GETDLGCODE,
  221. WM_SETFONT,
  222. WM_GETFONT,
  223. WM_GETTEXT,
  224. WM_TIMER,
  225. WM_INPUTLANGCHANGEREQUEST,
  226. WM_UPDATEUISTATE,
  227. 0
  228. };
  229. CONST WORD gawButtonWndProc[] = {
  230. WM_NCHITTEST,
  231. WM_ERASEBKGND,
  232. WM_PRINTCLIENT,
  233. WM_PAINT,
  234. WM_SETFOCUS,
  235. WM_GETDLGCODE,
  236. WM_CAPTURECHANGED,
  237. WM_KILLFOCUS,
  238. WM_LBUTTONDBLCLK,
  239. WM_LBUTTONUP,
  240. WM_MOUSEMOVE,
  241. WM_LBUTTONDOWN,
  242. WM_CHAR,
  243. BM_CLICK,
  244. WM_KEYDOWN,
  245. WM_KEYUP,
  246. WM_SYSKEYUP,
  247. BM_GETSTATE,
  248. BM_SETSTATE,
  249. BM_GETCHECK,
  250. BM_SETCHECK,
  251. BM_SETSTYLE,
  252. WM_SETTEXT,
  253. WM_ENABLE,
  254. WM_SETFONT,
  255. WM_GETFONT,
  256. BM_GETIMAGE,
  257. BM_SETIMAGE,
  258. WM_NCDESTROY,
  259. WM_FINALDESTROY,
  260. WM_NCCREATE,
  261. WM_INPUTLANGCHANGEREQUEST,
  262. WM_UPDATEUISTATE,
  263. 0
  264. };
  265. CONST WORD gawListboxWndProc[] = {
  266. LB_GETTOPINDEX,
  267. LB_SETTOPINDEX,
  268. WM_SIZE,
  269. WM_ERASEBKGND,
  270. LB_RESETCONTENT,
  271. WM_TIMER,
  272. WM_MOUSEMOVE,
  273. WM_MBUTTONDOWN,
  274. WM_LBUTTONDOWN,
  275. WM_LBUTTONUP,
  276. WM_LBUTTONDBLCLK,
  277. WM_CAPTURECHANGED,
  278. LBCB_STARTTRACK,
  279. LBCB_ENDTRACK,
  280. WM_PRINTCLIENT,
  281. WM_PAINT,
  282. WM_NCDESTROY,
  283. WM_FINALDESTROY,
  284. WM_SETFOCUS,
  285. WM_KILLFOCUS,
  286. WM_VSCROLL,
  287. WM_HSCROLL,
  288. WM_GETDLGCODE,
  289. WM_CREATE,
  290. WM_SETREDRAW,
  291. WM_ENABLE,
  292. WM_SETFONT,
  293. WM_GETFONT,
  294. WM_DRAGSELECT,
  295. WM_DRAGLOOP,
  296. WM_DRAGMOVE,
  297. WM_DROPFILES,
  298. WM_QUERYDROPOBJECT,
  299. WM_DROPOBJECT,
  300. LB_GETITEMRECT,
  301. LB_GETITEMDATA,
  302. LB_SETITEMDATA,
  303. LB_ADDSTRINGUPPER,
  304. LB_ADDSTRINGLOWER,
  305. LB_ADDSTRING,
  306. LB_INSERTSTRINGUPPER,
  307. LB_INSERTSTRINGLOWER,
  308. LB_INSERTSTRING,
  309. LB_INITSTORAGE,
  310. LB_DELETESTRING,
  311. LB_DIR,
  312. LB_ADDFILE,
  313. LB_SETSEL,
  314. LB_SETCURSEL,
  315. LB_GETSEL,
  316. LB_GETCURSEL,
  317. LB_SELITEMRANGE,
  318. LB_SELITEMRANGEEX,
  319. LB_GETTEXTLEN,
  320. LB_GETTEXT,
  321. LB_GETCOUNT,
  322. LB_SETCOUNT,
  323. LB_SELECTSTRING,
  324. LB_FINDSTRING,
  325. LB_GETLOCALE,
  326. LB_SETLOCALE,
  327. WM_KEYDOWN,
  328. WM_CHAR,
  329. LB_GETSELITEMS,
  330. LB_GETSELCOUNT,
  331. LB_SETTABSTOPS,
  332. LB_GETHORIZONTALEXTENT,
  333. LB_SETHORIZONTALEXTENT,
  334. LB_SETCOLUMNWIDTH,
  335. LB_SETANCHORINDEX,
  336. LB_GETANCHORINDEX,
  337. LB_SETCARETINDEX,
  338. LB_GETCARETINDEX,
  339. LB_SETITEMHEIGHT,
  340. LB_GETITEMHEIGHT,
  341. LB_FINDSTRINGEXACT,
  342. LB_ITEMFROMPOINT,
  343. LB_SETLOCALE,
  344. LB_GETLOCALE,
  345. LBCB_CARETON,
  346. LBCB_CARETOFF,
  347. LB_GETLISTBOXINFO,
  348. WM_NCCREATE,
  349. WM_WINDOWPOSCHANGED,
  350. WM_MOUSEWHEEL,
  351. WM_STYLECHANGED,
  352. WM_STYLECHANGING,
  353. 0
  354. };
  355. CONST WORD gawComboWndProc[] = {
  356. CBEC_KILLCOMBOFOCUS,
  357. WM_COMMAND,
  358. WM_CTLCOLORMSGBOX,
  359. WM_CTLCOLOREDIT,
  360. WM_CTLCOLORLISTBOX,
  361. WM_CTLCOLORBTN,
  362. WM_CTLCOLORDLG,
  363. WM_CTLCOLORSCROLLBAR,
  364. WM_CTLCOLORSTATIC,
  365. WM_CTLCOLOR,
  366. WM_GETTEXT,
  367. WM_GETTEXTLENGTH,
  368. WM_CLEAR,
  369. WM_CUT,
  370. WM_PASTE,
  371. WM_COPY,
  372. WM_SETTEXT,
  373. WM_CREATE,
  374. WM_ERASEBKGND,
  375. WM_GETFONT,
  376. WM_PRINT,
  377. WM_PRINTCLIENT,
  378. WM_PAINT,
  379. WM_GETDLGCODE,
  380. WM_SETFONT,
  381. WM_SYSKEYDOWN,
  382. WM_KEYDOWN,
  383. WM_CHAR,
  384. WM_LBUTTONDBLCLK,
  385. WM_LBUTTONDOWN,
  386. WM_CAPTURECHANGED,
  387. WM_LBUTTONUP,
  388. WM_MOUSEMOVE,
  389. WM_NCDESTROY,
  390. WM_FINALDESTROY,
  391. WM_SETFOCUS,
  392. WM_KILLFOCUS,
  393. WM_SETREDRAW,
  394. WM_ENABLE,
  395. WM_SIZE,
  396. CB_GETDROPPEDSTATE,
  397. CB_GETDROPPEDCONTROLRECT,
  398. CB_SETDROPPEDWIDTH,
  399. CB_GETDROPPEDWIDTH,
  400. CB_DIR,
  401. CB_SETEXTENDEDUI,
  402. CB_GETEXTENDEDUI,
  403. CB_GETEDITSEL,
  404. CB_LIMITTEXT,
  405. CB_SETEDITSEL,
  406. CB_ADDSTRING,
  407. CB_DELETESTRING,
  408. CB_INITSTORAGE,
  409. CB_SETTOPINDEX,
  410. CB_GETTOPINDEX,
  411. CB_GETCOUNT,
  412. CB_GETCURSEL,
  413. CB_GETLBTEXT,
  414. CB_GETLBTEXTLEN,
  415. CB_INSERTSTRING,
  416. CB_RESETCONTENT,
  417. CB_GETHORIZONTALEXTENT,
  418. CB_SETHORIZONTALEXTENT,
  419. CB_FINDSTRING,
  420. CB_FINDSTRINGEXACT,
  421. CB_SELECTSTRING,
  422. CB_SETCURSEL,
  423. CB_GETITEMDATA,
  424. CB_SETITEMDATA,
  425. CB_SETITEMHEIGHT,
  426. CB_GETITEMHEIGHT,
  427. CB_SHOWDROPDOWN,
  428. CB_SETLOCALE,
  429. CB_GETLOCALE,
  430. CB_GETCOMBOBOXINFO,
  431. WM_MEASUREITEM,
  432. WM_DELETEITEM,
  433. WM_DRAWITEM,
  434. WM_COMPAREITEM,
  435. WM_NCCREATE,
  436. WM_HELP,
  437. WM_MOUSEWHEEL,
  438. WM_MOUSELEAVE,
  439. WM_STYLECHANGED,
  440. WM_STYLECHANGING,
  441. WM_UPDATEUISTATE,
  442. 0
  443. };
  444. CONST WORD gawEditWndProc[] = {
  445. EM_CANUNDO,
  446. EM_CHARFROMPOS,
  447. EM_EMPTYUNDOBUFFER,
  448. EM_FMTLINES,
  449. EM_GETFIRSTVISIBLELINE,
  450. EM_GETFIRSTVISIBLELINE,
  451. EM_GETHANDLE,
  452. EM_GETLIMITTEXT,
  453. EM_GETLINE,
  454. EM_GETLINECOUNT,
  455. EM_GETMARGINS,
  456. EM_GETMODIFY,
  457. EM_GETPASSWORDCHAR,
  458. EM_GETRECT,
  459. EM_GETSEL,
  460. EM_GETWORDBREAKPROC,
  461. EM_SETIMESTATUS,
  462. EM_GETIMESTATUS,
  463. EM_LINEFROMCHAR,
  464. EM_LINEINDEX,
  465. EM_LINELENGTH,
  466. EM_LINESCROLL,
  467. EM_POSFROMCHAR,
  468. EM_REPLACESEL,
  469. EM_SCROLL,
  470. EM_SCROLLCARET,
  471. EM_SETHANDLE,
  472. EM_SETLIMITTEXT,
  473. EM_SETMARGINS,
  474. EM_SETMODIFY,
  475. EM_SETPASSWORDCHAR,
  476. EM_SETREADONLY,
  477. EM_SETRECT,
  478. EM_SETRECTNP,
  479. EM_SETSEL,
  480. EM_SETTABSTOPS,
  481. EM_SETWORDBREAKPROC,
  482. EM_UNDO,
  483. WM_CAPTURECHANGED,
  484. WM_CHAR,
  485. WM_CLEAR,
  486. WM_CONTEXTMENU,
  487. WM_COPY,
  488. WM_CREATE,
  489. WM_CUT,
  490. WM_ENABLE,
  491. WM_ERASEBKGND,
  492. WM_GETDLGCODE,
  493. WM_GETFONT,
  494. WM_GETTEXT,
  495. WM_GETTEXTLENGTH,
  496. WM_HSCROLL,
  497. WM_IME_STARTCOMPOSITION,
  498. WM_IME_ENDCOMPOSITION,
  499. WM_IME_COMPOSITION,
  500. WM_IME_SETCONTEXT,
  501. WM_IME_NOTIFY,
  502. WM_IME_COMPOSITIONFULL,
  503. WM_IME_SELECT,
  504. WM_IME_CHAR,
  505. WM_IME_REQUEST,
  506. WM_INPUTLANGCHANGE,
  507. WM_KEYUP,
  508. WM_KEYDOWN,
  509. WM_KILLFOCUS,
  510. WM_MBUTTONDOWN,
  511. WM_LBUTTONDBLCLK,
  512. WM_LBUTTONDOWN,
  513. WM_LBUTTONUP,
  514. WM_MOUSEMOVE,
  515. WM_NCCREATE,
  516. WM_NCDESTROY,
  517. WM_RBUTTONDOWN,
  518. WM_RBUTTONUP,
  519. WM_FINALDESTROY,
  520. WM_PAINT,
  521. WM_PASTE,
  522. WM_PRINTCLIENT,
  523. WM_SETFOCUS,
  524. WM_SETFONT,
  525. WM_SETREDRAW,
  526. WM_SETTEXT,
  527. WM_SIZE,
  528. WM_STYLECHANGED,
  529. WM_STYLECHANGING,
  530. WM_SYSCHAR,
  531. WM_SYSKEYDOWN,
  532. WM_SYSTIMER,
  533. WM_UNDO,
  534. WM_VSCROLL,
  535. WM_MOUSEWHEEL,
  536. 0
  537. };
  538. CONST WORD gawImeWndProc[] = {
  539. WM_ERASEBKGND,
  540. WM_PAINT,
  541. WM_DESTROY,
  542. WM_NCDESTROY,
  543. WM_FINALDESTROY,
  544. WM_CREATE,
  545. WM_IME_SYSTEM,
  546. WM_IME_SELECT,
  547. WM_IME_CONTROL,
  548. WM_IME_SETCONTEXT,
  549. WM_IME_NOTIFY,
  550. WM_IME_COMPOSITION,
  551. WM_IME_STARTCOMPOSITION,
  552. WM_IME_ENDCOMPOSITION,
  553. WM_IME_REQUEST,
  554. WM_COPYDATA,
  555. 0
  556. };
  557. /*
  558. * This array is for all the messages that need to be passed straight
  559. * across to the server for handling.
  560. */
  561. CONST WORD gawDefWindowMsgs[] = {
  562. WM_GETHOTKEY,
  563. WM_SETHOTKEY,
  564. WM_SETREDRAW,
  565. WM_SETTEXT,
  566. WM_PAINT,
  567. WM_CLOSE,
  568. WM_ERASEBKGND,
  569. WM_CANCELMODE,
  570. WM_SETCURSOR,
  571. WM_PAINTICON,
  572. WM_ICONERASEBKGND,
  573. WM_DRAWITEM,
  574. WM_KEYF1,
  575. WM_ISACTIVEICON,
  576. WM_NCCREATE,
  577. WM_SETICON,
  578. WM_NCCALCSIZE,
  579. WM_NCPAINT,
  580. WM_NCACTIVATE,
  581. WM_NCMOUSEMOVE,
  582. WM_NCRBUTTONUP,
  583. WM_NCRBUTTONDOWN,
  584. #ifndef LAME_BUTTON
  585. WM_NCLBUTTONDOWN,
  586. #endif
  587. WM_NCLBUTTONUP,
  588. WM_NCLBUTTONDBLCLK,
  589. WM_KEYUP,
  590. WM_SYSKEYUP,
  591. #ifndef LAME_BUTTON
  592. WM_SYSCHAR,
  593. WM_SYSCOMMAND,
  594. #endif
  595. WM_QUERYDROPOBJECT,
  596. WM_CLIENTSHUTDOWN,
  597. WM_SYNCPAINT,
  598. WM_PRINT,
  599. WM_GETICON,
  600. WM_CONTEXTMENU,
  601. WM_SYSMENU,
  602. WM_INPUTLANGCHANGEREQUEST,
  603. WM_INPUTLANGCHANGE,
  604. WM_UPDATEUISTATE,
  605. WM_NCUAHDRAWCAPTION,
  606. WM_NCUAHDRAWFRAME,
  607. WM_UAHINIT,
  608. 0
  609. };
  610. /*
  611. * This array is for all messages that can be handled with some special
  612. * code by the client. DefWindowProcWorker returns 0 for all messages
  613. * that aren't in this array or the one above.
  614. */
  615. CONST WORD gawDefWindowSpecMsgs[] = {
  616. WM_ACTIVATE,
  617. WM_GETTEXT,
  618. WM_GETTEXTLENGTH,
  619. WM_RBUTTONUP,
  620. WM_QUERYENDSESSION,
  621. WM_QUERYOPEN,
  622. WM_SHOWWINDOW,
  623. WM_MOUSEACTIVATE,
  624. WM_HELP,
  625. WM_VKEYTOITEM,
  626. WM_CHARTOITEM,
  627. WM_KEYDOWN,
  628. #ifdef LAME_BUTTON
  629. WM_SYSCOMMAND,
  630. WM_SYSCHAR,
  631. #endif
  632. WM_SYSKEYDOWN,
  633. WM_UNICHAR,
  634. WM_DROPOBJECT,
  635. WM_WINDOWPOSCHANGING,
  636. WM_WINDOWPOSCHANGED,
  637. WM_KLUDGEMINRECT,
  638. WM_CTLCOLOR,
  639. WM_CTLCOLORMSGBOX,
  640. WM_CTLCOLOREDIT,
  641. WM_CTLCOLORLISTBOX,
  642. WM_CTLCOLORBTN,
  643. WM_CTLCOLORDLG,
  644. WM_CTLCOLORSCROLLBAR,
  645. WM_NCHITTEST,
  646. #ifdef LAME_BUTTON
  647. WM_NCLBUTTONDOWN,
  648. #endif
  649. WM_NCXBUTTONUP,
  650. WM_CTLCOLORSTATIC,
  651. WM_NOTIFYFORMAT,
  652. WM_DEVICECHANGE,
  653. WM_POWERBROADCAST,
  654. WM_MOUSEWHEEL,
  655. WM_XBUTTONUP,
  656. WM_IME_KEYDOWN,
  657. WM_IME_KEYUP,
  658. WM_IME_CHAR,
  659. WM_IME_COMPOSITION,
  660. WM_IME_STARTCOMPOSITION,
  661. WM_IME_ENDCOMPOSITION,
  662. WM_IME_COMPOSITIONFULL,
  663. WM_IME_SETCONTEXT,
  664. WM_IME_CONTROL,
  665. WM_IME_NOTIFY,
  666. WM_IME_SELECT,
  667. WM_IME_SYSTEM,
  668. WM_LPKDRAWSWITCHWND,
  669. WM_QUERYDRAGICON,
  670. WM_CHANGEUISTATE,
  671. WM_QUERYUISTATE,
  672. WM_APPCOMMAND,
  673. 0
  674. };
  675. static CONST LPCWSTR lpszOLEFormats[] = {
  676. L"ObjectLink",
  677. L"OwnerLink",
  678. L"Native",
  679. L"Binary",
  680. L"FileName",
  681. L"FileNameW",
  682. L"NetworkName",
  683. L"DataObject",
  684. L"Embedded Object",
  685. L"Embed Source",
  686. L"Custom Link Source",
  687. L"Link Source",
  688. L"Object Descriptor",
  689. L"Link Source Descriptor",
  690. L"OleDraw",
  691. L"PBrush",
  692. L"MSDraw",
  693. L"Ole Private Data",
  694. L"Screen Picture",
  695. L"OleClipboardPersistOnFlush",
  696. L"MoreOlePrivateData"
  697. };
  698. static CONST LPCWSTR lpszControls[] = {
  699. L"Button",
  700. L"Edit",
  701. L"Static",
  702. L"ListBox",
  703. L"ScrollBar",
  704. L"ComboBox",
  705. L"MDIClient",
  706. L"ComboLBox",
  707. L"DDEMLEvent",
  708. L"DDEMLMom",
  709. L"DMGClass",
  710. L"DDEMLAnsiClient",
  711. L"DDEMLUnicodeClient",
  712. L"DDEMLAnsiServer",
  713. L"DDEMLUnicodeServer",
  714. L"IME",
  715. };
  716. #ifdef ALLOC_DATA_PRAGMA
  717. #pragma data_seg()
  718. #endif
  719. /***************************************************************************\
  720. * DispatchServerMessage
  721. *
  722. *
  723. * 19-Aug-1992 MikeKe Created
  724. \***************************************************************************/
  725. #define WRAPPFN(pfn, type) \
  726. LRESULT xxxWrap ## pfn( \
  727. PWND pwnd, \
  728. UINT message, \
  729. WPARAM wParam, \
  730. LPARAM lParam, \
  731. ULONG_PTR xParam) \
  732. { \
  733. UNREFERENCED_PARAMETER(xParam); \
  734. \
  735. return xxx ## pfn((type)pwnd, message, wParam, lParam); \
  736. }
  737. WRAPPFN(SBWndProc, PSBWND)
  738. WRAPPFN(MenuWindowProc, PWND)
  739. WRAPPFN(DesktopWndProc, PWND);
  740. WRAPPFN(RealDefWindowProc, PWND)
  741. WRAPPFN(SwitchWndProc, PWND)
  742. LRESULT xxxWrapSendMessageCallback(
  743. PWND pwnd,
  744. UINT message,
  745. WPARAM wParam,
  746. LPARAM lParam,
  747. ULONG_PTR xParam)
  748. {
  749. SNDMSGCALLBACK smcb;
  750. TL tlpwnd;
  751. LRESULT lRet = 0;
  752. NTSTATUS Status = STATUS_SUCCESS;
  753. UserAssert (xParam != 0L);
  754. /*
  755. * Prevent apps from setting hi 16 bits so we can use them internally.
  756. */
  757. if (message & MSGFLAG_MASK) {
  758. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
  759. return 0;
  760. }
  761. /*
  762. * Probe all read arguments
  763. */
  764. try {
  765. ProbeForWrite((PVOID)xParam, sizeof(smcb), sizeof(ULONG));
  766. smcb = *(PSNDMSGCALLBACK)xParam;
  767. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  768. Status = GetExceptionCode();
  769. }
  770. if ( !NT_SUCCESS(Status) ) {
  771. return 0;
  772. }
  773. if (pwnd != PWND_BROADCAST)
  774. ThreadLockAlways(pwnd, &tlpwnd);
  775. lRet = (LRESULT)xxxSendMessageCallback(pwnd,
  776. message,
  777. wParam,
  778. lParam,
  779. smcb.lpResultCallBack,
  780. smcb.dwData,
  781. TRUE);
  782. if (pwnd != PWND_BROADCAST)
  783. ThreadUnlock(&tlpwnd);
  784. return lRet;
  785. }
  786. LRESULT xxxWrapSendNotifyMessage(
  787. PWND pwnd,
  788. UINT message,
  789. WPARAM wParam,
  790. LPARAM lParam,
  791. ULONG_PTR xParam)
  792. {
  793. TL tlpwnd;
  794. LRESULT lRet = 0;
  795. UNREFERENCED_PARAMETER(xParam);
  796. if (message & MSGFLAG_MASK) {
  797. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
  798. return 0;
  799. }
  800. if (pwnd != PWND_BROADCAST) {
  801. ThreadLockAlways(pwnd, &tlpwnd);
  802. }
  803. lRet = (LRESULT)xxxSendNotifyMessage(pwnd,
  804. message,
  805. wParam,
  806. lParam);
  807. if (pwnd != PWND_BROADCAST) {
  808. ThreadUnlock(&tlpwnd);
  809. }
  810. return lRet;
  811. }
  812. LRESULT xxxWrapSendMessage(
  813. PWND pwnd,
  814. UINT message,
  815. WPARAM wParam,
  816. LPARAM lParam,
  817. ULONG_PTR xParam)
  818. {
  819. UNREFERENCED_PARAMETER(xParam);
  820. return xxxSendMessageTimeout(pwnd,
  821. message,
  822. wParam,
  823. lParam,
  824. SMTO_NORMAL,
  825. 0,
  826. NULL);
  827. }
  828. LRESULT xxxWrapSendMessageBSM(
  829. PWND pwnd,
  830. UINT message,
  831. WPARAM wParam,
  832. LPARAM lParam,
  833. ULONG_PTR xParam)
  834. {
  835. BROADCASTSYSTEMMSGPARAMS bsmParams;
  836. LRESULT lRet;
  837. try {
  838. ProbeForWriteBroadcastSystemMsgParams((LPBROADCASTSYSTEMMSGPARAMS)xParam);
  839. RtlCopyMemory(&bsmParams, (LPBROADCASTSYSTEMMSGPARAMS)xParam, sizeof(BROADCASTSYSTEMMSGPARAMS));
  840. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  841. return 0;
  842. }
  843. /*
  844. * If this broadcast is going to all desktops, make sure the thread has
  845. * sufficient privileges. Do the check here, so we don't effect kernel
  846. * generated broadcasts (i.e power messages).
  847. */
  848. if (bsmParams.dwRecipients & (BSM_ALLDESKTOPS)) {
  849. if (!IsPrivileged(&psTcb)) {
  850. bsmParams.dwRecipients &= ~(BSM_ALLDESKTOPS);
  851. try {
  852. RtlCopyMemory((LPBROADCASTSYSTEMMSGPARAMS)xParam, &bsmParams, sizeof(BROADCASTSYSTEMMSGPARAMS));
  853. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  854. /* empty */
  855. }
  856. }
  857. }
  858. lRet = xxxSendMessageBSM(pwnd,
  859. message,
  860. wParam,
  861. lParam,
  862. &bsmParams);
  863. /*
  864. * If our query was denied, return who denied the query.
  865. */
  866. if (lRet == 0 && (bsmParams.dwFlags & BSF_QUERY)) {
  867. try {
  868. RtlCopyMemory((LPBROADCASTSYSTEMMSGPARAMS)xParam, &bsmParams, sizeof(BROADCASTSYSTEMMSGPARAMS));
  869. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  870. return 0;
  871. }
  872. }
  873. return lRet;
  874. }
  875. /***************************************************************************\
  876. * xxxUnusedFunctionId
  877. *
  878. * This function is catches attempts to access invalid entries in the server
  879. * side function dispatch table.
  880. *
  881. \***************************************************************************/
  882. LRESULT xxxUnusedFunctionId(
  883. PWND pwnd,
  884. UINT message,
  885. WPARAM wParam,
  886. LPARAM lParam,
  887. ULONG_PTR xParam)
  888. {
  889. UNREFERENCED_PARAMETER(pwnd);
  890. UNREFERENCED_PARAMETER(message);
  891. UNREFERENCED_PARAMETER(wParam);
  892. UNREFERENCED_PARAMETER(lParam);
  893. UNREFERENCED_PARAMETER(xParam);
  894. UserAssert(FALSE);
  895. return 0;
  896. }
  897. /***************************************************************************\
  898. * xxxWrapCallWindowProc
  899. *
  900. * Warning should only be called with valid CallProc Handles or the
  901. * EditWndProc special handlers.
  902. *
  903. *
  904. * 21-Apr-1993 JohnC Created
  905. \***************************************************************************/
  906. LRESULT xxxWrapCallWindowProc(
  907. PWND pwnd,
  908. UINT message,
  909. WPARAM wParam,
  910. LPARAM lParam,
  911. ULONG_PTR xParam)
  912. {
  913. PCALLPROCDATA pCPD;
  914. LRESULT lRet = 0;
  915. if (pCPD = HMValidateHandleNoRip((PVOID)xParam, TYPE_CALLPROC)) {
  916. lRet = ScSendMessage(pwnd,
  917. message,
  918. wParam,
  919. lParam,
  920. pCPD->pfnClientPrevious,
  921. gpsi->apfnClientW.pfnDispatchMessage,
  922. (pCPD->wType & CPD_UNICODE_TO_ANSI) ?
  923. SCMS_FLAGS_ANSI : 0);
  924. } else {
  925. /*
  926. * If it is not a real call proc handle it must be a special
  927. * handler for editwndproc or regular EditWndProc
  928. */
  929. lRet = ScSendMessage(pwnd,
  930. message,
  931. wParam,
  932. lParam,
  933. xParam,
  934. gpsi->apfnClientA.pfnDispatchMessage,
  935. (xParam == (ULONG_PTR)gpsi->apfnClientA.pfnEditWndProc) ?
  936. SCMS_FLAGS_ANSI : 0);
  937. }
  938. return lRet;
  939. }
  940. #if DBG
  941. VOID VerifySyncOnlyMessages(VOID)
  942. {
  943. int i;
  944. TRACE_INIT(("UserInit: Verify Sync Only Messages\n"));
  945. /*
  946. * There are a couple of thunks that just pass parameters. There are other
  947. * thunks besides SfnDWORD that do a straight pass through because they
  948. * do other processing beside the wparam and lparam
  949. */
  950. /*
  951. * Allow posting of LB_DIR and CB_DIR because DlgDirList allows a DDL_POSTMSGS
  952. * flag that makes the API post the messages. This should be OK as long as we
  953. * don't handle these messages in the kernel. NT 3.51 allowed posting these.
  954. */
  955. for (i=0; i<WM_USER; i++) {
  956. if ( i != LB_DIR
  957. && i != CB_DIR
  958. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnDWORD)
  959. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnNCDESTROY)
  960. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMCHAR)
  961. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMDBCSCHAR)
  962. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnSENTDDEMSG)
  963. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnPOWERBROADCAST)
  964. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnLOGONNOTIFY)
  965. && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINDESTROYCLIPBRD)) {
  966. if (!(TESTSYNCONLYMESSAGE(i,0x8000)))
  967. RIPMSG1(RIP_ERROR, "InitSyncOnly: is this message sync-only 0x%lX", i);
  968. } else {
  969. if (TESTSYNCONLYMESSAGE(i,0))
  970. RIPMSG1(RIP_VERBOSE, "InitSyncOnly: is this message not sync-only 0x%lX", i);
  971. }
  972. }
  973. }
  974. #endif // DBG
  975. /***************************************************************************\
  976. * InitWindowMsgTables
  977. *
  978. * This function generates a bit-array lookup table from a list of messages.
  979. * The lookup table is used to determine whether the message needs to be
  980. * passed over to the server for handling or whether it can be handled
  981. * directly on the client.
  982. *
  983. * LATER: Some memory (a couple hundred bytes per process) could be saved
  984. * by putting this in the shared read-only heap.
  985. *
  986. *
  987. * 27-Mar-1992 DarrinM Created.
  988. * 06-Dec-1993 MikeKe Added support for all of our window procs.
  989. \***************************************************************************/
  990. VOID InitWindowMsgTable(
  991. PBYTE *ppbyte,
  992. PUINT pmax,
  993. CONST WORD *pw)
  994. {
  995. UINT i;
  996. WORD msg;
  997. UINT cbTable;
  998. *pmax = 0;
  999. for (i = 0; (msg = pw[i]) != 0; i++) {
  1000. if (msg > *pmax)
  1001. *pmax = msg;
  1002. }
  1003. cbTable = *pmax / 8 + 1;
  1004. *ppbyte = SharedAlloc(cbTable);
  1005. if (*ppbyte == NULL) {
  1006. return;
  1007. }
  1008. for (i = 0; (msg = pw[i]) != 0; i++) {
  1009. (*ppbyte)[msg / 8] |= (BYTE)(1 << (msg & 7));
  1010. }
  1011. }
  1012. /***************************************************************************\
  1013. * InitFunctionTables
  1014. *
  1015. * Initialize the procedures and function tables.
  1016. *
  1017. *
  1018. * 25-Aug-1995 ChrisWil Created comment block.
  1019. \***************************************************************************/
  1020. VOID InitFunctionTables(
  1021. VOID)
  1022. {
  1023. UINT i;
  1024. TRACE_INIT(("UserInit: Initialize Function Tables\n"));
  1025. UserAssert(sizeof(CLIENTINFO) <= sizeof(NtCurrentTeb()->Win32ClientInfo));
  1026. /*
  1027. * This table is used to convert from server procs to client procs.
  1028. */
  1029. STOCID(FNID_SCROLLBAR) = (WNDPROC_PWND)xxxSBWndProc;
  1030. STOCID(FNID_ICONTITLE) = xxxDefWindowProc;
  1031. STOCID(FNID_MENU) = xxxMenuWindowProc;
  1032. STOCID(FNID_DESKTOP) = xxxDesktopWndProc;
  1033. STOCID(FNID_DEFWINDOWPROC) = xxxDefWindowProc;
  1034. STOCID(FNID_MESSAGEWND) = xxxDefWindowProc;
  1035. /*
  1036. * This table is used to determine the number minimum number of reserved
  1037. * windows words required for the server proc.
  1038. */
  1039. CBFNID(FNID_SCROLLBAR) = sizeof(SBWND);
  1040. CBFNID(FNID_ICONTITLE) = sizeof(WND);
  1041. CBFNID(FNID_MENU) = sizeof(MENUWND);
  1042. /*
  1043. * Initialize this data structure (api function table).
  1044. */
  1045. for (i = 0; i < FNID_ARRAY_SIZE; i++) {
  1046. FNID((i + FNID_START)) = xxxUnusedFunctionId;
  1047. }
  1048. FNID(FNID_SCROLLBAR) = xxxWrapSBWndProc;
  1049. FNID(FNID_ICONTITLE) = xxxWrapRealDefWindowProc;
  1050. FNID(FNID_MENU) = xxxWrapMenuWindowProc;
  1051. FNID(FNID_DESKTOP) = xxxWrapDesktopWndProc;
  1052. FNID(FNID_DEFWINDOWPROC) = xxxWrapRealDefWindowProc;
  1053. FNID(FNID_MESSAGEWND) = xxxWrapRealDefWindowProc;
  1054. FNID(FNID_SENDMESSAGE) = xxxWrapSendMessage;
  1055. FNID(FNID_HKINLPCWPEXSTRUCT) = fnHkINLPCWPEXSTRUCT;
  1056. FNID(FNID_HKINLPCWPRETEXSTRUCT) = fnHkINLPCWPRETEXSTRUCT;
  1057. FNID(FNID_SENDMESSAGEFF) = xxxSendMessageFF;
  1058. FNID(FNID_SENDMESSAGEEX) = xxxSendMessageEx;
  1059. FNID(FNID_CALLWINDOWPROC) = xxxWrapCallWindowProc;
  1060. FNID(FNID_SENDMESSAGEBSM) = xxxWrapSendMessageBSM;
  1061. FNID(FNID_SWITCH) = xxxWrapSwitchWndProc;
  1062. FNID(FNID_SENDNOTIFYMESSAGE) = xxxWrapSendNotifyMessage;
  1063. FNID(FNID_SENDMESSAGECALLBACK) = xxxWrapSendMessageCallback;
  1064. #if DBG
  1065. {
  1066. PULONG_PTR pdw;
  1067. /*
  1068. * Make sure that everyone got initialized.
  1069. */
  1070. for (pdw = (PULONG_PTR)&STOCID(FNID_START);
  1071. (ULONG_PTR)pdw<(ULONG_PTR)(&STOCID(FNID_WNDPROCEND)); pdw++) {
  1072. UserAssert(*pdw);
  1073. }
  1074. for (pdw=(PULONG_PTR)&FNID(FNID_START);
  1075. (ULONG_PTR)pdw<(ULONG_PTR)(&FNID(FNID_WNDPROCEND)); pdw++) {
  1076. UserAssert(*pdw);
  1077. }
  1078. }
  1079. #endif
  1080. }
  1081. /***************************************************************************\
  1082. * InitMessageTables
  1083. *
  1084. * Initialize the message tables.
  1085. *
  1086. * 25-Aug-1995 ChrisWil Created.
  1087. \***************************************************************************/
  1088. VOID InitMessageTables(
  1089. VOID)
  1090. {
  1091. TRACE_INIT(("UserInit: Initialize Message Tables\n"));
  1092. #define INITMSGTABLE(member, procname) \
  1093. InitWindowMsgTable(&(gSharedInfo.member.abMsgs), \
  1094. &(gSharedInfo.member.maxMsgs), \
  1095. gaw ## procname);
  1096. INITMSGTABLE(DefWindowMsgs, DefWindowMsgs);
  1097. INITMSGTABLE(DefWindowSpecMsgs, DefWindowSpecMsgs);
  1098. INITMSGTABLE(awmControl[FNID_DIALOG - FNID_START], DefDlgProc);
  1099. INITMSGTABLE(awmControl[FNID_SCROLLBAR - FNID_START], ScrollBarWndProc);
  1100. INITMSGTABLE(awmControl[FNID_MENU - FNID_START], MenuWndProc);
  1101. INITMSGTABLE(awmControl[FNID_DESKTOP - FNID_START], DesktopWndProc);
  1102. INITMSGTABLE(awmControl[FNID_STATIC - FNID_START], StaticWndProc);
  1103. INITMSGTABLE(awmControl[FNID_BUTTON - FNID_START], ButtonWndProc);
  1104. INITMSGTABLE(awmControl[FNID_LISTBOX - FNID_START], ListboxWndProc);
  1105. INITMSGTABLE(awmControl[FNID_COMBOBOX - FNID_START], ComboWndProc);
  1106. INITMSGTABLE(awmControl[FNID_COMBOLISTBOX - FNID_START], ListboxWndProc);
  1107. INITMSGTABLE(awmControl[FNID_EDIT - FNID_START], EditWndProc);
  1108. INITMSGTABLE(awmControl[FNID_IME - FNID_START], ImeWndProc);
  1109. }
  1110. /***************************************************************************\
  1111. * InitOLEFormats
  1112. *
  1113. * OLE performance hack. OLE was previously having to call the server 15
  1114. * times for clipboard formats and another 15 LPC calls for the global atoms.
  1115. * Now we preregister them. We also assert they are in order so OLE only has
  1116. * to query the first to know them all. We call AddAtom directly instead of
  1117. * RegisterClipboardFormat.
  1118. *
  1119. * 25-Aug-1995 ChrisWil Created.
  1120. \***************************************************************************/
  1121. BOOL InitOLEFormats(
  1122. VOID)
  1123. {
  1124. UINT idx;
  1125. ATOM a1;
  1126. ATOM a2;
  1127. BOOL fSuccess = TRUE;
  1128. TRACE_INIT(("UserInit: Initialize OLE Formats\n"));
  1129. a1 = UserAddAtom(lpszOLEFormats[0], TRUE);
  1130. for (idx = 1; idx < ARRAY_SIZE(lpszOLEFormats); idx++) {
  1131. a2 = UserAddAtom(lpszOLEFormats[idx], TRUE);
  1132. fSuccess &= !!a2;
  1133. UserAssert(((a1 + 1) == a2) && (a1 = a2));
  1134. }
  1135. if (!fSuccess) {
  1136. RIPMSG0(RIP_ERROR, "InitOLEFormats: at least one atom not registered");
  1137. }
  1138. return fSuccess;
  1139. }
  1140. #if DBG
  1141. /***************************************************************************\
  1142. * InitGlobalRIPFlags (CHK only).
  1143. *
  1144. * This initializes the global RIP flags from the registry.
  1145. *
  1146. * 25-Aug-1995 ChrisWil Created.
  1147. \***************************************************************************/
  1148. VOID InitGlobalRIPFlags(
  1149. VOID)
  1150. {
  1151. UINT idx;
  1152. UINT nCount;
  1153. DWORD dwFlag;
  1154. static CONST struct {
  1155. LPWSTR lpszKey;
  1156. DWORD dwDef;
  1157. DWORD dwFlag;
  1158. } aRIPFlags[] = {
  1159. {L"fPromptOnError" , 1, RIPF_PROMPTONERROR},
  1160. {L"fPromptOnWarning", 0, RIPF_PROMPTONWARNING},
  1161. {L"fPromptOnVerbose", 0, RIPF_PROMPTONVERBOSE},
  1162. {L"fPrintError" , 1, RIPF_PRINTONERROR},
  1163. {L"fPrintWarning" , 1, RIPF_PRINTONWARNING},
  1164. {L"fPrintVerbose" , 0, RIPF_PRINTONVERBOSE},
  1165. {L"fPrintFileLine" , 0, RIPF_PRINTFILELINE},
  1166. };
  1167. TRACE_INIT(("UserInit: Initialize Global RIP Flags\n"));
  1168. nCount = ARRAY_SIZE(aRIPFlags);
  1169. /*
  1170. * Turn off the rip-on-warning bit. This is necessary to prevent the
  1171. * FastGetProfileDwordW() routine from breaking into the debugger if an
  1172. * entry can't be found. Since we provide default values, there's no sense
  1173. * to break.
  1174. */
  1175. CLEAR_FLAG(gpsi->dwRIPFlags, RIPF_PROMPTONWARNING);
  1176. CLEAR_FLAG(gpsi->dwRIPFlags, RIPF_PRINTONWARNING);
  1177. for (idx = 0; idx < nCount; idx++) {
  1178. FastGetProfileDwordW(NULL,
  1179. PMAP_WINDOWSM,
  1180. aRIPFlags[idx].lpszKey,
  1181. aRIPFlags[idx].dwDef,
  1182. &dwFlag,
  1183. 0);
  1184. SET_OR_CLEAR_FLAG(gpsi->dwRIPFlags, aRIPFlags[idx].dwFlag, dwFlag);
  1185. }
  1186. }
  1187. #else
  1188. #define InitGlobalRIPFlags()
  1189. #endif
  1190. /***************************************************************************\
  1191. * _GetTextMetricsW
  1192. * _TextOutW
  1193. *
  1194. * Server shared function thunks.
  1195. *
  1196. * History:
  1197. * 10-Nov-1993 MikeKe Created
  1198. \***************************************************************************/
  1199. BOOL _GetTextMetricsW(
  1200. HDC hdc,
  1201. LPTEXTMETRICW ptm)
  1202. {
  1203. TMW_INTERNAL tmi;
  1204. BOOL fret;
  1205. fret = GreGetTextMetricsW(hdc, &tmi);
  1206. *ptm = tmi.tmw;
  1207. return fret;
  1208. }
  1209. BOOL _TextOutW(
  1210. HDC hdc,
  1211. int x,
  1212. int y,
  1213. LPCWSTR lp,
  1214. UINT cc)
  1215. {
  1216. return GreExtTextOutW(hdc, x, y, 0, NULL, (LPWSTR)lp, cc, NULL);
  1217. }
  1218. #define ROUND_UP_TO_PAGES(SIZE) \
  1219. (((ULONG)(SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
  1220. /***************************************************************************\
  1221. * InitCreateSharedSection
  1222. *
  1223. * This creates the shared section.
  1224. *
  1225. *
  1226. * 25-Aug-1995 ChrisWil Created comment block.
  1227. \***************************************************************************/
  1228. NTSTATUS InitCreateSharedSection(
  1229. VOID)
  1230. {
  1231. ULONG ulHeapSize;
  1232. ULONG ulHandleTableSize;
  1233. NTSTATUS Status;
  1234. LARGE_INTEGER SectionSize;
  1235. SIZE_T ViewSize;
  1236. PVOID pHeapBase;
  1237. TRACE_INIT(("UserInit: Create Shared Memory Section\n"));
  1238. UserAssert(ghSectionShared == NULL);
  1239. ulHeapSize = ROUND_UP_TO_PAGES(USRINIT_SHAREDSECT_SIZE * 1024);
  1240. ulHandleTableSize = ROUND_UP_TO_PAGES(0x10000 * sizeof(HANDLEENTRY));
  1241. TRACE_INIT(("UserInit: Share: TableSize = %X; HeapSize = %X\n",
  1242. ulHandleTableSize, ulHeapSize));
  1243. SectionSize.LowPart = ulHeapSize + ulHandleTableSize;
  1244. SectionSize.HighPart = 0;
  1245. Status = Win32CreateSection(&ghSectionShared,
  1246. SECTION_ALL_ACCESS,
  1247. NULL,
  1248. &SectionSize,
  1249. PAGE_EXECUTE_READWRITE,
  1250. SEC_RESERVE,
  1251. NULL,
  1252. NULL,
  1253. TAG_SECTION_SHARED);
  1254. if (!NT_SUCCESS(Status)) {
  1255. RIPMSG1(RIP_WARNING,
  1256. "MmCreateSection failed in InitCreateSharedSection with Status %x",
  1257. Status);
  1258. return Status;
  1259. }
  1260. ViewSize = 0;
  1261. gpvSharedBase = NULL;
  1262. Status = Win32MapViewInSessionSpace(ghSectionShared, &gpvSharedBase, &ViewSize);
  1263. if (!NT_SUCCESS(Status)) {
  1264. RIPMSG1(RIP_WARNING,
  1265. "Win32MapViewInSessionSpace failed with Status %x",
  1266. Status);
  1267. Win32DestroySection(ghSectionShared);
  1268. ghSectionShared = NULL;
  1269. return Status;
  1270. }
  1271. pHeapBase = ((PBYTE)gpvSharedBase + ulHandleTableSize);
  1272. TRACE_INIT(("UserInit: Share: BaseAddr = %#p; Heap = %#p, ViewSize = %X\n",
  1273. gpvSharedBase, pHeapBase, ViewSize));
  1274. /*
  1275. * Create shared heap.
  1276. */
  1277. if ((gpvSharedAlloc = UserCreateHeap(
  1278. ghSectionShared,
  1279. ulHandleTableSize,
  1280. pHeapBase,
  1281. ulHeapSize,
  1282. UserCommitSharedMemory)) == NULL) {
  1283. RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
  1284. RIP_WARNING,
  1285. "Can't create shared memory heap.");
  1286. Win32UnmapViewInSessionSpace(gpvSharedBase);
  1287. Win32DestroySection(ghSectionShared);
  1288. gpvSharedAlloc = NULL;
  1289. gpvSharedBase = NULL;
  1290. ghSectionShared = NULL;
  1291. return STATUS_NO_MEMORY;
  1292. }
  1293. UserAssert(Win32HeapGetHandle(gpvSharedAlloc) == pHeapBase);
  1294. return STATUS_SUCCESS;
  1295. }
  1296. /**************************************************************************\
  1297. * InitCreateUserCrit
  1298. *
  1299. * Create and initialize the user critical sections needed throughout the
  1300. * system.
  1301. *
  1302. * 23-Jan-1996 ChrisWil Created.
  1303. \**************************************************************************/
  1304. BOOL InitCreateUserCrit(
  1305. VOID)
  1306. {
  1307. TRACE_INIT(("Win32UserInit: InitCreateUserCrit()\n"));
  1308. /*
  1309. * Initialize a critical section structure that will be used to protect
  1310. * all of the User Server's critical sections (except a few special
  1311. * cases like the RIT -- see below).
  1312. */
  1313. gpresUser = ExAllocatePoolWithTag(NonPagedPool,
  1314. sizeof(ERESOURCE),
  1315. TAG_ERESOURCE);
  1316. if (!gpresUser) {
  1317. goto InitCreateUserCritExit;
  1318. }
  1319. if (!NT_SUCCESS(ExInitializeResourceLite(gpresUser))) {
  1320. goto InitCreateUserCritExit;
  1321. }
  1322. /*
  1323. * Initialize a critical section to be used in [Un]QueueMouseEvent
  1324. * to protect the queue of mouse input events that the desktop thread
  1325. * uses to pass input on to the RIT, after having moved the cursor
  1326. * without obtaining gpresUser itself.
  1327. */
  1328. gpresMouseEventQueue = ExAllocatePoolWithTag(NonPagedPool,
  1329. sizeof(ERESOURCE),
  1330. TAG_ERESOURCE);
  1331. if (!gpresMouseEventQueue) {
  1332. goto InitCreateUserCritExit;
  1333. }
  1334. if (!NT_SUCCESS(ExInitializeResourceLite(gpresMouseEventQueue))) {
  1335. goto InitCreateUserCritExit;
  1336. }
  1337. /*
  1338. * Initialize a critical section to protect the list of DEVICEINFO structs
  1339. * kept under gpDeviceInfoList. This is used by the RIT when reading kbd
  1340. * input, the desktop thread when reading mouse input, and the PnP callback
  1341. * routines DeviceClassNotify() and DeviceNotify() when devices come and go.
  1342. */
  1343. gpresDeviceInfoList = ExAllocatePoolWithTag(NonPagedPool,
  1344. sizeof(ERESOURCE),
  1345. TAG_ERESOURCE);
  1346. if (!gpresDeviceInfoList) {
  1347. goto InitCreateUserCritExit;
  1348. }
  1349. if (!NT_SUCCESS(ExInitializeResourceLite(gpresDeviceInfoList))) {
  1350. goto InitCreateUserCritExit;
  1351. }
  1352. /*
  1353. * Create the handle flag mutex. We'll need this once we start creating
  1354. * windowstations and desktops.
  1355. */
  1356. gpHandleFlagsMutex = ExAllocatePoolWithTag(NonPagedPool,
  1357. sizeof(FAST_MUTEX),
  1358. TAG_SYSTEM);
  1359. if (gpHandleFlagsMutex == NULL) {
  1360. goto InitCreateUserCritExit;
  1361. }
  1362. ExInitializeFastMutex(gpHandleFlagsMutex);
  1363. TRACE_INIT(("Win32UserInit: gpHandleFlagsMutex = %#p\n", gpHandleFlagsMutex));
  1364. TRACE_INIT(("Win32UserInit: gpresDeviceInfoList = %#p\n", gpresDeviceInfoList));
  1365. TRACE_INIT(("Win32UserInit: gpresMouseEventQueue = %#p\n", gpresMouseEventQueue));
  1366. TRACE_INIT(("Win32UserInit: gpresUser = %#p\n", gpresUser));
  1367. TRACE_INIT(("Win32UserInit: exit InitCreateUserCrit()\n"));
  1368. return TRUE;
  1369. InitCreateUserCritExit:
  1370. RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
  1371. RIP_WARNING,
  1372. "Win32UserInit: InitCreateUserCrit failed");
  1373. if (gpresUser) {
  1374. ExFreePool(gpresUser);
  1375. }
  1376. if (gpresMouseEventQueue) {
  1377. ExFreePool(gpresMouseEventQueue);
  1378. }
  1379. if (gpresDeviceInfoList) {
  1380. ExFreePool(gpresDeviceInfoList);
  1381. }
  1382. return FALSE;
  1383. }
  1384. /**************************************************************************\
  1385. * InitCreateObjectDirectory
  1386. *
  1387. * Create and initialize the user critical sections needed throughout the
  1388. * system.
  1389. *
  1390. * 23-Jan-1996 ChrisWil Created.
  1391. \**************************************************************************/
  1392. NTSTATUS InitCreateObjectDirectory(VOID)
  1393. {
  1394. HANDLE hDir;
  1395. NTSTATUS Status;
  1396. OBJECT_ATTRIBUTES ObjectAttributes;
  1397. UNICODE_STRING UnicodeString;
  1398. ULONG attributes = OBJ_CASE_INSENSITIVE | OBJ_PERMANENT;
  1399. TRACE_INIT(("UserInit: Create User Object-Directory\n"));
  1400. RtlInitUnicodeString(&UnicodeString, szWindowStationDirectory);
  1401. if (gbRemoteSession) {
  1402. /*
  1403. * Remote sessions don't use this flag
  1404. */
  1405. attributes &= ~OBJ_PERMANENT;
  1406. }
  1407. InitializeObjectAttributes(&ObjectAttributes,
  1408. &UnicodeString,
  1409. attributes,
  1410. NULL,
  1411. gpsdInitWinSta);
  1412. Status = ZwCreateDirectoryObject(&hDir,
  1413. DIRECTORY_CREATE_OBJECT,
  1414. &ObjectAttributes);
  1415. UserFreePool(gpsdInitWinSta);
  1416. /*
  1417. * Do not close this handle for remote session because
  1418. * if we do close it then the directory will go away and
  1419. * we don't want that to happen. When CSRSS will go away
  1420. * this handle will be freed also.
  1421. */
  1422. if (!gbRemoteSession)
  1423. ZwClose(hDir);
  1424. gpsdInitWinSta = NULL;
  1425. return Status;
  1426. }
  1427. /**************************************************************************\
  1428. * InitCreateUserSubsystem
  1429. *
  1430. * Create and initialize the user subsystem stuff.
  1431. * system.
  1432. *
  1433. * 23-Jan-1996 ChrisWil Created.
  1434. \**************************************************************************/
  1435. BOOL
  1436. InitCreateUserSubsystem()
  1437. {
  1438. LPWSTR lpszSubSystem;
  1439. LPWSTR lpszT;
  1440. UNICODE_STRING strSize;
  1441. TRACE_INIT(("UserInit: Create User SubSystem\n"));
  1442. /*
  1443. * Initialize the subsystem section. This identifies the default
  1444. * user-heap size.
  1445. */
  1446. lpszSubSystem = UserAllocPoolWithQuota(USRINIT_SHAREDSECT_BUFF_SIZE * sizeof(WCHAR),
  1447. TAG_SYSTEM);
  1448. if (lpszSubSystem == NULL) {
  1449. return FALSE;
  1450. }
  1451. if (FastGetProfileStringW(NULL,
  1452. PMAP_SUBSYSTEMS,
  1453. L"Windows",
  1454. L"SharedSection=,3072",
  1455. lpszSubSystem,
  1456. USRINIT_SHAREDSECT_READ_SIZE,
  1457. 0) == 0) {
  1458. RIPMSG0(RIP_WARNING,
  1459. "UserInit: Windows subsystem definition not found");
  1460. UserFreePool(lpszSubSystem);
  1461. return FALSE;
  1462. }
  1463. /*
  1464. * Locate the SharedSection portion of the definition and extract
  1465. * the second value.
  1466. */
  1467. gdwDesktopSectionSize = USER_WINDOWSECT_SIZE;
  1468. gdwNOIOSectionSize = USER_NOIOSECT_SIZE;
  1469. if (lpszT = wcsstr(lpszSubSystem, L"SharedSection")) {
  1470. *(lpszT + 32) = UNICODE_NULL;
  1471. if (lpszT = wcschr(lpszT, L',')) {
  1472. RtlInitUnicodeString(&strSize, ++lpszT);
  1473. RtlUnicodeStringToInteger(&strSize, 0, &gdwDesktopSectionSize);
  1474. /*
  1475. * Assert this logic doesn't need to change.
  1476. */
  1477. UserAssert(gdwDesktopSectionSize >= USER_WINDOWSECT_SIZE);
  1478. gdwDesktopSectionSize = max(USER_WINDOWSECT_SIZE, gdwDesktopSectionSize);
  1479. gdwNOIOSectionSize = gdwDesktopSectionSize;
  1480. /*
  1481. * Now see if the optional non-interactive desktop
  1482. * heap size was specified.
  1483. */
  1484. if (lpszT = wcschr(lpszT, L',')) {
  1485. RtlInitUnicodeString(&strSize, ++lpszT);
  1486. RtlUnicodeStringToInteger(&strSize, 0, &gdwNOIOSectionSize);
  1487. UserAssert(gdwNOIOSectionSize >= USER_NOIOSECT_SIZE);
  1488. gdwNOIOSectionSize = max(USER_NOIOSECT_SIZE, gdwNOIOSectionSize);
  1489. }
  1490. }
  1491. }
  1492. UserFreePool(lpszSubSystem);
  1493. return TRUE;
  1494. }
  1495. extern UNICODE_STRING *gpastrSetupExe; // These are used in
  1496. extern int giSetupExe; // SetAppImeCompatFlags in
  1497. // queue.c
  1498. WCHAR* glpSetupPrograms;
  1499. /**************************************************************************\
  1500. * CreateSetupNameArray
  1501. *
  1502. * Create and initialize the arrary of setup app names. We inherited this
  1503. * hack From Chicago. See queue.c for more details.
  1504. \**************************************************************************/
  1505. BOOL CreateSetupNameArray(
  1506. VOID)
  1507. {
  1508. DWORD dwProgNames;
  1509. int iSetupProgramCount = 0;
  1510. WCHAR* lpTemp;
  1511. int ic, icnt, icMax;
  1512. dwProgNames = FastGetProfileValue(NULL,
  1513. PMAP_SETUPPROGRAMNAMES,
  1514. L"SetupProgramNames",
  1515. NULL,
  1516. NULL,
  1517. 0,
  1518. 0);
  1519. /*
  1520. * This key is a multi-string, so is best to read as a value.
  1521. * First, get the length and create the buffer to hold all of
  1522. * the strings.
  1523. */
  1524. if (dwProgNames == 0) {
  1525. return FALSE;
  1526. }
  1527. glpSetupPrograms = UserAllocPoolWithQuota(dwProgNames,
  1528. TAG_SYSTEM);
  1529. if (glpSetupPrograms == NULL) {
  1530. RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
  1531. return FALSE;
  1532. }
  1533. FastGetProfileValue(NULL,
  1534. PMAP_SETUPPROGRAMNAMES,
  1535. L"SetupProgramNames",
  1536. NULL,
  1537. (PBYTE)glpSetupPrograms,
  1538. dwProgNames,
  1539. 0);
  1540. lpTemp = glpSetupPrograms;
  1541. icMax = dwProgNames/2;
  1542. ic = 0; icnt=0;
  1543. /*
  1544. * Now count the strings.
  1545. */
  1546. while (ic < icMax) {
  1547. if (*(lpTemp+ic) == 0) {
  1548. ic++;
  1549. continue;
  1550. }
  1551. ic += wcslen(lpTemp+ic)+1;
  1552. icnt++;
  1553. }
  1554. /*
  1555. * gpastrSetupExe is a pointer to an array of UNICODE_STRING structures.
  1556. * Each structure is the name of one setup program.
  1557. */
  1558. giSetupExe = icnt;
  1559. gpastrSetupExe = UserAllocPoolWithQuota(giSetupExe * sizeof(UNICODE_STRING),
  1560. TAG_SYSTEM);
  1561. if (gpastrSetupExe == NULL) {
  1562. RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
  1563. giSetupExe = 0;
  1564. UserFreePool(glpSetupPrograms);
  1565. glpSetupPrograms = NULL;
  1566. return FALSE;
  1567. }
  1568. ic = 0; icnt=0;
  1569. while (ic < icMax) {
  1570. if (*(lpTemp+ic) == 0) {
  1571. ic++;
  1572. continue;
  1573. }
  1574. gpastrSetupExe[icnt].Buffer = lpTemp+ic;
  1575. gpastrSetupExe[icnt].Length = sizeof(WCHAR)*wcslen(lpTemp+ic);
  1576. gpastrSetupExe[icnt].MaximumLength = gpastrSetupExe[icnt].Length + sizeof(WCHAR);
  1577. ic += wcslen(lpTemp+ic)+1;
  1578. icnt++;
  1579. }
  1580. return TRUE;
  1581. }
  1582. #define CALC_DELTA(element) \
  1583. (PVOID)((PBYTE)pClientBase + \
  1584. ((PBYTE)gSharedInfo.element - \
  1585. (PBYTE)gpvSharedBase))
  1586. /***************************************************************************\
  1587. * InitMapSharedSection
  1588. *
  1589. * This maps the shared section.
  1590. *
  1591. *
  1592. * 25-Aug-1995 ChrisWil Created comment block.
  1593. \***************************************************************************/
  1594. NTSTATUS InitMapSharedSection(
  1595. PEPROCESS Process,
  1596. PUSERCONNECT pUserConnect)
  1597. {
  1598. int i;
  1599. PVOID pClientBase = NULL;
  1600. ULONG_PTR ulSharedDelta;
  1601. PW32PROCESS pw32p;
  1602. TRACE_INIT(("UserInit: Map Shared Memory Section\n"));
  1603. UserAssert(ghSectionShared != NULL);
  1604. ValidateProcessSessionId(Process);
  1605. /*
  1606. * Check to see if we haven't already mapped the section
  1607. * This might happen for multiple LoadLibrary()/FreeLibrary calls
  1608. * in one process. MCostea #56946
  1609. */
  1610. pw32p = PsGetProcessWin32Process(Process);
  1611. if (pw32p == NULL ||
  1612. ((PPROCESSINFO)pw32p)->pClientBase == NULL) {
  1613. SIZE_T ViewSize;
  1614. LARGE_INTEGER liOffset;
  1615. NTSTATUS Status;
  1616. ViewSize = 0;
  1617. liOffset.QuadPart = 0;
  1618. Status = MmMapViewOfSection(ghSectionShared,
  1619. Process,
  1620. &pClientBase,
  1621. 0,
  1622. 0,
  1623. &liOffset,
  1624. &ViewSize,
  1625. ViewUnmap,
  1626. SEC_NO_CHANGE,
  1627. PAGE_EXECUTE_READ);
  1628. if (NT_SUCCESS(Status)) {
  1629. TRACE_INIT(("UserInit: Map: Client SharedInfo Base = %#p\n", pClientBase));
  1630. UserAssert(gpvSharedBase > pClientBase);
  1631. pw32p = PsGetProcessWin32Process(Process);
  1632. if (pw32p != NULL) {
  1633. ((PPROCESSINFO)pw32p)->pClientBase = pClientBase;
  1634. }
  1635. } else {
  1636. return Status;
  1637. }
  1638. } else {
  1639. pClientBase = ((PPROCESSINFO)PsGetProcessWin32Process(Process))->pClientBase;
  1640. }
  1641. ulSharedDelta = (PBYTE)gpvSharedBase - (PBYTE)pClientBase;
  1642. pUserConnect->siClient.ulSharedDelta = ulSharedDelta;
  1643. pUserConnect->siClient.psi = CALC_DELTA(psi);
  1644. pUserConnect->siClient.aheList = CALC_DELTA(aheList);
  1645. pUserConnect->siClient.pDispInfo = CALC_DELTA(pDispInfo);
  1646. pUserConnect->siClient.DefWindowMsgs.maxMsgs = gSharedInfo.DefWindowMsgs.maxMsgs;
  1647. pUserConnect->siClient.DefWindowMsgs.abMsgs = CALC_DELTA(DefWindowMsgs.abMsgs);
  1648. pUserConnect->siClient.DefWindowSpecMsgs.maxMsgs = gSharedInfo.DefWindowSpecMsgs.maxMsgs;
  1649. pUserConnect->siClient.DefWindowSpecMsgs.abMsgs = CALC_DELTA(DefWindowSpecMsgs.abMsgs);
  1650. for (i = 0; i < (FNID_END - FNID_START + 1); ++i) {
  1651. pUserConnect->siClient.awmControl[i].maxMsgs = gSharedInfo.awmControl[i].maxMsgs;
  1652. if (gSharedInfo.awmControl[i].abMsgs)
  1653. pUserConnect->siClient.awmControl[i].abMsgs = CALC_DELTA(awmControl[i].abMsgs);
  1654. else
  1655. pUserConnect->siClient.awmControl[i].abMsgs = NULL;
  1656. }
  1657. return STATUS_SUCCESS;
  1658. }
  1659. /**************************************************************************\
  1660. * InitLoadResources
  1661. *
  1662. *
  1663. * 25-Aug-1995 ChrisWil Created.
  1664. \**************************************************************************/
  1665. VOID InitLoadResources()
  1666. {
  1667. PRECT prc;
  1668. DISPLAYRESOURCE dr = {
  1669. 17, // Height of vertical thumb
  1670. 17, // Width of horizontal thumb
  1671. 2, // Icon horiz compression factor
  1672. 2, // Icon vert compression factor
  1673. 2, // Cursor horz compression factor
  1674. 2, // Cursor vert compression factor
  1675. 0, // Kanji window height
  1676. 1, // cxBorder (thickness of vertical lines)
  1677. 1 // cyBorder (thickness of horizontal lines)
  1678. };
  1679. TRACE_INIT(("UserInit: Load Display Resources\n"));
  1680. /*
  1681. * For high-DPI systems, don't compress the cursor as much.
  1682. * This really should be a more configurable method, such as a System
  1683. * Parameter Info setting or something. But for now, we'll hard-code
  1684. * 150dpi to be the threshhold at which we'll double the cursor size.
  1685. */
  1686. if (gpsi->dmLogPixels >= 150) {
  1687. dr.xCompressCursor = 1;
  1688. dr.yCompressCursor = 1;
  1689. }
  1690. if (dr.xCompressIcon > 10) {
  1691. /*
  1692. * If so, the actual dimensions of icons and cursors are
  1693. * kept in OEMBIN.
  1694. */
  1695. SYSMET(CXICON) = dr.xCompressIcon;
  1696. SYSMET(CYICON) = dr.yCompressIcon;
  1697. SYSMET(CXCURSOR) = dr.xCompressCursor;
  1698. SYSMET(CYCURSOR) = dr.yCompressCursor;
  1699. } else {
  1700. /*
  1701. * Else, only the ratio of (64/icon dimensions) is kept there.
  1702. */
  1703. SYSMET(CXICON) = (64 / dr.xCompressIcon);
  1704. SYSMET(CYICON) = (64 / dr.yCompressIcon);
  1705. SYSMET(CXCURSOR) = (64 / dr.xCompressCursor);
  1706. SYSMET(CYCURSOR) = (64 / dr.yCompressCursor);
  1707. }
  1708. SYSMET(CXSMICON) = SYSMET(CXICON) / 2;
  1709. SYSMET(CYSMICON) = SYSMET(CYICON) / 2;
  1710. SYSMET(CYKANJIWINDOW) = dr.yKanji;
  1711. /*
  1712. * Get border thicknesses.
  1713. */
  1714. SYSMET(CXBORDER) = dr.cxBorder;
  1715. SYSMET(CYBORDER) = dr.cyBorder;
  1716. /*
  1717. * Edge is two borders.
  1718. */
  1719. SYSMET(CXEDGE) = 2 * SYSMET(CXBORDER);
  1720. SYSMET(CYEDGE) = 2 * SYSMET(CYBORDER);
  1721. /*
  1722. * Fixed frame is outer edge + border.
  1723. */
  1724. SYSMET(CXDLGFRAME) = SYSMET(CXEDGE) + SYSMET(CXBORDER);
  1725. SYSMET(CYDLGFRAME) = SYSMET(CYEDGE) + SYSMET(CYBORDER);
  1726. if (gbRemoteSession) {
  1727. return;
  1728. }
  1729. prc = &GetPrimaryMonitor()->rcMonitor;
  1730. SYSMET(CXFULLSCREEN) = prc->right;
  1731. SYSMET(CYFULLSCREEN) = prc->bottom - SYSMET(CYCAPTION);
  1732. /*
  1733. * Set the initial cursor position to the center of the primary screen.
  1734. */
  1735. gpsi->ptCursor.x = prc->right / 2;
  1736. gpsi->ptCursor.y = prc->bottom / 2;
  1737. }
  1738. /***************************************************************************\
  1739. * GetCharDimensions
  1740. *
  1741. * This function loads the Textmetrics of the font currently selected into
  1742. * the hDC and returns the Average char width of the font; Pl Note that the
  1743. * AveCharWidth value returned by the Text metrics call is wrong for
  1744. * proportional fonts. So, we compute them On return, lpTextMetrics contains
  1745. * the text metrics of the currently selected font.
  1746. *
  1747. * History:
  1748. * 10-Nov-1993 mikeke Created
  1749. \***************************************************************************/
  1750. int GetCharDimensions(
  1751. HDC hdc,
  1752. TEXTMETRIC* lptm,
  1753. LPINT lpcy
  1754. )
  1755. {
  1756. TEXTMETRIC tm;
  1757. /*
  1758. * Didn't find it in cache, store the font metrics info.
  1759. */
  1760. if (!_GetTextMetricsW(hdc, &tm)) {
  1761. RIPMSG1(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW failed. hdc %#lx", hdc);
  1762. tm = gpsi->tmSysFont; // damage control
  1763. if (tm.tmAveCharWidth == 0) {
  1764. RIPMSG0(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW first time failure");
  1765. tm.tmAveCharWidth = 8;
  1766. }
  1767. }
  1768. if (lptm != NULL)
  1769. *lptm = tm;
  1770. if (lpcy != NULL)
  1771. *lpcy = tm.tmHeight;
  1772. /*
  1773. * If variable_width font
  1774. */
  1775. if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) {
  1776. SIZE size;
  1777. static CONST WCHAR wszAvgChars[] =
  1778. L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1779. /*
  1780. * Change from tmAveCharWidth. We will calculate a true average
  1781. * as opposed to the one returned by tmAveCharWidth. This works
  1782. * better when dealing with proportional spaced fonts.
  1783. */
  1784. if (GreGetTextExtentW(
  1785. hdc, (LPWSTR)wszAvgChars,
  1786. (sizeof(wszAvgChars) / sizeof(WCHAR)) - 1,
  1787. &size, GGTE_WIN3_EXTENT)) {
  1788. UserAssert((((size.cx / 26) + 1) / 2) > 0);
  1789. return ((size.cx / 26) + 1) / 2; // round up
  1790. } else {
  1791. RIPMSG1(RIP_WARNING, "GetCharDimensions: GreGetTextExtentW failed. hdc %#lx", hdc);
  1792. }
  1793. }
  1794. UserAssert(tm.tmAveCharWidth > 0);
  1795. return tm.tmAveCharWidth;
  1796. }
  1797. /**************************************************************************\
  1798. * InitVideo
  1799. *
  1800. * Create pmdev.
  1801. *
  1802. * 03-March-1998 CLupu Moved from UserInitialize code
  1803. \**************************************************************************/
  1804. PMDEV InitVideo(
  1805. BOOL bReenumerationNeeded)
  1806. {
  1807. PMDEV pmdev;
  1808. LONG ChangeStatus;
  1809. /*
  1810. * NOTE: Need to get a status return from this call.
  1811. * DrvInitConsole doesn't return failure, if or when it does we
  1812. * should check for it and return NULL. However there seem to be
  1813. * no known problems related to this.
  1814. */
  1815. DrvInitConsole(bReenumerationNeeded);
  1816. /*
  1817. * BASEVIDEO may be on or off, whether we are in setup or not.
  1818. */
  1819. ChangeStatus = DrvChangeDisplaySettings(NULL,
  1820. NULL,
  1821. NULL,
  1822. (PVOID)GW_DESKTOP_ID,
  1823. KernelMode,
  1824. FALSE,
  1825. TRUE,
  1826. NULL,
  1827. &pmdev,
  1828. GRE_DEFAULT,
  1829. TRUE);
  1830. if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
  1831. /*
  1832. * If we fail, try BASEVIDEO temporarily.
  1833. */
  1834. DrvSetBaseVideo(TRUE);
  1835. ChangeStatus = DrvChangeDisplaySettings(NULL,
  1836. NULL,
  1837. NULL,
  1838. (PVOID)GW_DESKTOP_ID,
  1839. KernelMode,
  1840. FALSE,
  1841. TRUE,
  1842. NULL,
  1843. &pmdev,
  1844. GRE_DEFAULT,
  1845. TRUE);
  1846. DrvSetBaseVideo(FALSE);
  1847. /*
  1848. * Give it one last try, not in basevideo, to handle TGA
  1849. * (non-vgacompatible) during GUI-mode setup (BASEVIDEO is on by
  1850. * default)
  1851. */
  1852. if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
  1853. ChangeStatus = DrvChangeDisplaySettings(NULL,
  1854. NULL,
  1855. NULL,
  1856. (PVOID)GW_DESKTOP_ID,
  1857. KernelMode,
  1858. FALSE,
  1859. TRUE,
  1860. NULL,
  1861. &pmdev,
  1862. GRE_DEFAULT,
  1863. TRUE);
  1864. }
  1865. }
  1866. if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
  1867. RIPMSG0(RIP_WARNING, "InitVideo: No working display driver found");
  1868. return NULL;
  1869. }
  1870. /*
  1871. * Remove the basevideo flag. We want it set only on the first modeset.
  1872. */
  1873. DrvSetBaseVideo(FALSE);
  1874. gpDispInfo->hDev = pmdev->hdevParent;
  1875. gpDispInfo->pmdev = pmdev;
  1876. GreUpdateSharedDevCaps(gpDispInfo->hDev);
  1877. if (!InitUserScreen()) {
  1878. RIPMSG0(RIP_WARNING, "InitUserScreen failed");
  1879. return NULL;
  1880. }
  1881. HYDRA_HINT(HH_INITVIDEO);
  1882. return pmdev;
  1883. }
  1884. VOID DrvDriverFailure(
  1885. VOID)
  1886. {
  1887. KeBugCheckEx(VIDEO_DRIVER_INIT_FAILURE,
  1888. 0,
  1889. 0,
  1890. 0,
  1891. USERCURRENTVERSION);
  1892. }
  1893. /***************************************************************************\
  1894. * BeginBootPhase
  1895. *
  1896. * Let's kernel know of boot progress on the console.
  1897. *
  1898. * 10-Apr-2001 Cenke Created.
  1899. \***************************************************************************/
  1900. NTSTATUS BeginBootPhase(
  1901. PF_BOOT_PHASE_ID Phase)
  1902. {
  1903. PREFETCHER_INFORMATION PrefetcherInformation;
  1904. NTSTATUS Status;
  1905. /*
  1906. * We should be called only on the console.
  1907. */
  1908. UserAssert(gSessionId == 0);
  1909. /*
  1910. * Setup the structure that will be passed to system call.
  1911. */
  1912. PrefetcherInformation.Magic = PF_SYSINFO_MAGIC_NUMBER;
  1913. PrefetcherInformation.Version = PF_CURRENT_VERSION;
  1914. PrefetcherInformation.PrefetcherInformationClass = PrefetcherBootPhase;
  1915. PrefetcherInformation.PrefetcherInformation = &Phase;
  1916. PrefetcherInformation.PrefetcherInformationLength = sizeof(Phase);
  1917. /*
  1918. * Call system and return status to caller.
  1919. */
  1920. Status = ZwSetSystemInformation(SystemPrefetcherInformation,
  1921. &PrefetcherInformation,
  1922. sizeof(PrefetcherInformation));
  1923. return Status;
  1924. }
  1925. /**************************************************************************\
  1926. * ReserveUserSessionViews
  1927. *
  1928. * Reserve user needed session views beforhand to prevert GDI from eating
  1929. * uo the session view space when hardware acceleration is turned off.
  1930. *
  1931. * 27-Nov-2001 MSadek Created it
  1932. \**************************************************************************/
  1933. NTSTATUS
  1934. ReserveUserSessionViews(
  1935. PHANDLE phSection,
  1936. PPVOID ppMapBase)
  1937. {
  1938. LARGE_INTEGER SectionSize;
  1939. ULONG ulSectionSize;
  1940. SIZE_T ulViewSize;
  1941. NTSTATUS Status;
  1942. /*
  1943. * We need to reserve session view space for:
  1944. * - Winlogon desktop heap.
  1945. * - Disconnect desktop heap.
  1946. * - Winlogon desktop heap.
  1947. * - Services desktops heap (how many?, let's have a factor of safety here).
  1948. */
  1949. ulSectionSize = GetDesktopHeapSize(DHS_LOGON) +
  1950. GetDesktopHeapSize(DHS_DISCONNECT) +
  1951. GetDesktopHeapSize(0) +
  1952. GetDesktopHeapSize(DHS_NOIO) * NOIO_DESKTOP_NUMBER;
  1953. SectionSize.QuadPart = ulSectionSize;
  1954. Status = Win32CreateSection(phSection,
  1955. SECTION_ALL_ACCESS,
  1956. (POBJECT_ATTRIBUTES)NULL,
  1957. &SectionSize,
  1958. PAGE_EXECUTE_READWRITE,
  1959. SEC_RESERVE,
  1960. (HANDLE)NULL,
  1961. NULL,
  1962. TAG_SECTION_DESKTOP);
  1963. if (!NT_SUCCESS( Status )) {
  1964. RIPNTERR0(Status,
  1965. RIP_WARNING,
  1966. "Can't create section for reserved session views.");
  1967. return Status;
  1968. }
  1969. ulViewSize = ulSectionSize;
  1970. *ppMapBase = NULL;
  1971. Status = Win32MapViewInSessionSpace(*phSection, ppMapBase, &ulViewSize);
  1972. if (!NT_SUCCESS(Status)) {
  1973. RIPNTERR0(Status,
  1974. RIP_WARNING,
  1975. "Can't map section for for reserved session views into session space.");
  1976. Win32DestroySection(&phSection);
  1977. }
  1978. return Status;
  1979. }
  1980. /**************************************************************************\
  1981. * UserInitialize
  1982. *
  1983. * Worker routine for user initialization.
  1984. *
  1985. * 25-Aug-1995 ChrisWil Created comment block/Multiple desktop support.
  1986. * 15-Dec-1995 BradG Modified to return MediaChangeEvent Handle.
  1987. \**************************************************************************/
  1988. NTSTATUS
  1989. UserInitialize(
  1990. VOID)
  1991. {
  1992. NTSTATUS Status;
  1993. DWORD dwData;
  1994. HANDLE hSection;
  1995. PVOID pSectionBase;
  1996. #if DBG
  1997. /*
  1998. * Allow a trace of all the init stuff going on related to display
  1999. * drivers. Useful to debug boot time problems related to graphics.
  2000. */
  2001. if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) {
  2002. TraceInitialization = 1;
  2003. }
  2004. #endif
  2005. TRACE_INIT(("Entering UserInitialize\n"));
  2006. EnterCrit();
  2007. HYDRA_HINT(HH_USERINITIALIZE);
  2008. if (ISTS() && gbRemoteSession) {
  2009. swprintf(szWindowStationDirectory, L"%ws\\%ld%ws",
  2010. SESSION_ROOT, gSessionId, WINSTA_DIR);
  2011. } else {
  2012. wcscpy(szWindowStationDirectory, WINSTA_DIR);
  2013. }
  2014. /*
  2015. * Create WindowStation object directory.
  2016. */
  2017. Status = InitCreateObjectDirectory();
  2018. if (!NT_SUCCESS(Status)) {
  2019. RIPMSG1(RIP_WARNING, "InitCreateObjectDirectory failed with Status %x",
  2020. Status);
  2021. goto Exit;
  2022. }
  2023. /*
  2024. * Create the event for PnP RequestDeviceChangeSyncronization
  2025. */
  2026. gpEventPnPWainting = CreateKernelEvent(SynchronizationEvent, TRUE);
  2027. if (gpEventPnPWainting == NULL) {
  2028. RIPMSG0(RIP_WARNING, "Failed to create gpEventPnPWainting");
  2029. Status = STATUS_NO_MEMORY;
  2030. goto Exit;
  2031. }
  2032. /*
  2033. * Read the registry configuration for the multimon snapsot flag
  2034. */
  2035. if (FastGetProfileIntFromID(NULL,PMAP_TS, STR_SNAPSHOTMONITORS, 1, &dwData, 0)) {
  2036. if (dwData != 0) {
  2037. gbSnapShotWindowsAndMonitors = TRUE;
  2038. } else {
  2039. gbSnapShotWindowsAndMonitors = FALSE;
  2040. }
  2041. } else{
  2042. gbSnapShotWindowsAndMonitors = TRUE;
  2043. }
  2044. /*
  2045. * Create the event for the diconnect desktop creation
  2046. */
  2047. gpEventDiconnectDesktop = CreateKernelEvent(SynchronizationEvent, FALSE);
  2048. if (gpEventDiconnectDesktop == NULL) {
  2049. RIPMSG0(RIP_WARNING, "Failed to create gpEventDiconnectDesktop");
  2050. Status = STATUS_NO_MEMORY;
  2051. goto Exit;
  2052. }
  2053. /*
  2054. * WinStations get init'ed on the first connect.
  2055. */
  2056. if (!gbRemoteSession) {
  2057. BeginBootPhase(PfVideoInitPhase);
  2058. /* If hardware acceleration is turned off, GDI will map huge sections for the panning
  2059. * surfaces. We might end up exceeding the session view size quota before mapping the heap
  2060. * section for critical desktops.
  2061. * Let's pre-reserve approximately what we need now.
  2062. */
  2063. Status = ReserveUserSessionViews(&hSection, &pSectionBase);
  2064. if (!NT_SUCCESS(Status)) {
  2065. goto Exit;
  2066. }
  2067. if (InitVideo(TRUE) == NULL) {
  2068. DrvDriverFailure();
  2069. }
  2070. Status = Win32UnmapViewInSessionSpace(pSectionBase);
  2071. Win32DestroySection(hSection);
  2072. BeginBootPhase(PfPostVideoInitPhase);
  2073. /*
  2074. * Do this here so power callouts
  2075. * have the pmdev in gpDispInfo set
  2076. */
  2077. gbVideoInitialized = TRUE;
  2078. }
  2079. gbUserInitialized = TRUE;
  2080. /*
  2081. * Now that the system is initialized, allocate a pti for this thread.
  2082. */
  2083. Status = xxxCreateThreadInfo(PsGetCurrentThread());
  2084. if (!NT_SUCCESS(Status)) {
  2085. RIPMSG1(RIP_WARNING,
  2086. "xxxCreateThreadInfo failed during UserInitialize with Status 0x%x",
  2087. Status);
  2088. goto Exit;
  2089. }
  2090. /*
  2091. * Initialize Global RIP flags (debug only).
  2092. */
  2093. InitGlobalRIPFlags();
  2094. /*
  2095. * WinStations get init'ed on the first connect.
  2096. */
  2097. if (!gbRemoteSession) {
  2098. UserVerify(LW_BrushInit());
  2099. }
  2100. InitLoadResources();
  2101. Exit:
  2102. LeaveCrit();
  2103. TRACE_INIT(("Leaving UserInitialize\n"));
  2104. return Status;
  2105. }
  2106. /**************************************************************************\
  2107. * IsDBCSEnabledSystem
  2108. *
  2109. * check if the system is configured as FE Enabled
  2110. *
  2111. * 07-Feb-1997 HiroYama Created
  2112. \**************************************************************************/
  2113. __inline BOOL IsDBCSEnabledSystem(
  2114. VOID)
  2115. {
  2116. return !!NLS_MB_CODE_PAGE_TAG;
  2117. }
  2118. BOOL IsIMMEnabledSystem(
  2119. VOID)
  2120. {
  2121. DWORD dwRet = 0;
  2122. /*
  2123. * If the entire system is DBCS enabled, IMM/IME should be activated
  2124. * anyway.
  2125. */
  2126. if (IsDBCSEnabledSystem()) {
  2127. return TRUE;
  2128. }
  2129. FastGetProfileDwordW(NULL, PMAP_IMM, TEXT("LoadIMM"), 0, &dwRet, 0);
  2130. return dwRet;
  2131. }
  2132. #ifdef CUAS_ENABLE
  2133. BOOL IsCTFIMEEnabledSystem(
  2134. VOID)
  2135. {
  2136. DWORD dwRet = 0;
  2137. FastGetProfileDwordW(NULL, PMAP_IMM, TEXT("DontLoadCTFIME"), 0, &dwRet, 0);
  2138. if (dwRet)
  2139. return FALSE;
  2140. return IsIMMEnabledSystem();
  2141. }
  2142. #endif
  2143. /*
  2144. * Get ACP and check if the system is configured as ME Enabled.
  2145. */
  2146. BOOL IsMidEastEnabledSystem(
  2147. VOID)
  2148. {
  2149. extern __declspec(dllimport) USHORT NlsAnsiCodePage;
  2150. /*
  2151. * 1255 == Hebrew and 1256 == Arabic.
  2152. */
  2153. if (NlsAnsiCodePage == 1255 || NlsAnsiCodePage == 1256) {
  2154. return TRUE;
  2155. }
  2156. return FALSE;
  2157. }
  2158. /***************************************************************************\
  2159. * SetupClassAtoms
  2160. *
  2161. * 10/01/1998 clupu moved from Win32UserInitialize
  2162. \***************************************************************************/
  2163. BOOL SetupClassAtoms(
  2164. VOID)
  2165. {
  2166. BOOL fSuccess = TRUE;
  2167. int ind;
  2168. /*
  2169. * Set up class atoms.
  2170. *
  2171. * HACK: Controls are registered on the client side so we can't fill in
  2172. * their atomSysClass entry the same way we do for the other classes.
  2173. */
  2174. for (ind = ICLS_BUTTON; ind < ICLS_CTL_MAX; ind++) {
  2175. gpsi->atomSysClass[ind] = UserAddAtom(lpszControls[ind], TRUE);
  2176. fSuccess &= !!gpsi->atomSysClass[ind];
  2177. }
  2178. gpsi->atomSysClass[ICLS_DIALOG] = PTR_TO_ID(DIALOGCLASS);
  2179. gpsi->atomSysClass[ICLS_ICONTITLE] = PTR_TO_ID(ICONTITLECLASS);
  2180. gpsi->atomSysClass[ICLS_TOOLTIP] = PTR_TO_ID(TOOLTIPCLASS);
  2181. gpsi->atomSysClass[ICLS_DESKTOP] = PTR_TO_ID(DESKTOPCLASS);
  2182. gpsi->atomSysClass[ICLS_SWITCH] = PTR_TO_ID(SWITCHWNDCLASS);
  2183. gpsi->atomSysClass[ICLS_MENU] = PTR_TO_ID(MENUCLASS);
  2184. gpsi->atomContextHelpIdProp = UserAddAtom(szCONTEXTHELPIDPROP, TRUE);
  2185. fSuccess &= !!gpsi->atomContextHelpIdProp;
  2186. gpsi->atomIconSmProp = UserAddAtom(szICONSM_PROP_NAME, TRUE);
  2187. fSuccess &= !!gpsi->atomIconSmProp;
  2188. gpsi->atomIconProp = UserAddAtom(szICON_PROP_NAME, TRUE);
  2189. fSuccess &= !!gpsi->atomIconProp;
  2190. gpsi->uiShellMsg = UserAddAtom(szSHELLHOOK, TRUE);
  2191. fSuccess &= !!gpsi->uiShellMsg;
  2192. /*
  2193. * Initialize the integer atoms for our magic window properties
  2194. */
  2195. atomCheckpointProp = UserAddAtom(szCHECKPOINT_PROP_NAME, TRUE);
  2196. fSuccess &= !!atomCheckpointProp;
  2197. atomDDETrack = UserAddAtom(szDDETRACK_PROP_NAME, TRUE);
  2198. fSuccess &= !!atomDDETrack;
  2199. atomQOS = UserAddAtom(szQOS_PROP_NAME, TRUE);
  2200. fSuccess &= !!atomQOS;
  2201. atomDDEImp = UserAddAtom(szDDEIMP_PROP_NAME, TRUE);
  2202. fSuccess &= !!atomDDEImp;
  2203. atomWndObj = UserAddAtom(szWNDOBJ_PROP_NAME, TRUE);
  2204. fSuccess &= !!atomWndObj;
  2205. atomImeLevel = UserAddAtom(szIMELEVEL_PROP_NAME, TRUE);
  2206. fSuccess &= !!atomImeLevel;
  2207. atomLayer = UserAddAtom(szLAYER_PROP_NAME, TRUE);
  2208. fSuccess &= !!atomLayer;
  2209. guiActivateShellWindow = UserAddAtom(szACTIVATESHELLWINDOW, TRUE);
  2210. fSuccess &= !!guiActivateShellWindow;
  2211. guiOtherWindowCreated = UserAddAtom(szOTHERWINDOWCREATED, TRUE);
  2212. fSuccess &= !!guiOtherWindowCreated;
  2213. guiOtherWindowDestroyed = UserAddAtom(szOTHERWINDOWDESTROYED, TRUE);
  2214. fSuccess &= !!guiOtherWindowDestroyed;
  2215. gatomMessage = UserAddAtom(szMESSAGE, TRUE);
  2216. fSuccess &= !!gatomMessage;
  2217. #ifdef HUNGAPP_GHOSTING
  2218. gatomGhost = UserAddAtom(szGHOST, TRUE);
  2219. fSuccess &= !!gatomGhost;
  2220. #endif
  2221. gatomShadow = UserAddAtom(szSHADOW, TRUE);
  2222. fSuccess &= !!gatomShadow;
  2223. gaOleMainThreadWndClass = UserAddAtom(szOLEMAINTHREADWNDCLASS, TRUE);
  2224. fSuccess &= !!gaOleMainThreadWndClass;
  2225. gaFlashWState = UserAddAtom(szFLASHWSTATE, TRUE);
  2226. fSuccess &= !!gaFlashWState;
  2227. gatomLastPinned = gaOleMainThreadWndClass;
  2228. return fSuccess;
  2229. }
  2230. /**************************************************************************\
  2231. * IsDesktopHeapLoggingOn
  2232. *
  2233. * Checks the registry to determine if we should write a message to the
  2234. * event log on desktop heap allocation failures.
  2235. *
  2236. * 05-19-2002 JasonSch Created.
  2237. \**************************************************************************/
  2238. BOOL IsDesktopHeapLoggingOn(
  2239. VOID)
  2240. {
  2241. DWORD dwDesktopHeapLogging;
  2242. FastGetProfileDwordW(NULL,
  2243. PMAP_WINDOWSM,
  2244. L"DesktopHeapLogging",
  2245. 0,
  2246. &dwDesktopHeapLogging,
  2247. 0);
  2248. return (dwDesktopHeapLogging != 0);
  2249. }
  2250. /**************************************************************************\
  2251. * Win32UserInitialize
  2252. *
  2253. * Worker routine for user initialization called from Win32k's DriverEntry.
  2254. \**************************************************************************/
  2255. NTSTATUS Win32UserInitialize(
  2256. VOID)
  2257. {
  2258. NTSTATUS Status;
  2259. POBJECT_TYPE_INITIALIZER pTypeInfo;
  2260. LONG lTemp;
  2261. TRACE_INIT(("Entering Win32UserInitialize\n"));
  2262. /*
  2263. * Create the shared section.
  2264. */
  2265. Status = InitCreateSharedSection();
  2266. if (!NT_SUCCESS(Status)) {
  2267. RIPMSG1(RIP_WARNING,
  2268. "InitCreateSharedSection failed with Status 0x%x",
  2269. Status);
  2270. return Status;
  2271. }
  2272. EnterCrit();
  2273. /*
  2274. * Initialize security stuff.
  2275. */
  2276. if (!InitSecurity()) {
  2277. RIPMSG0(RIP_WARNING, "InitSecurity failed");
  2278. goto ExitWin32UserInitialize;
  2279. }
  2280. /*
  2281. * Fill in windowstation and desktop object types
  2282. */
  2283. pTypeInfo = &(*ExWindowStationObjectType)->TypeInfo;
  2284. pTypeInfo->DefaultNonPagedPoolCharge = sizeof(WINDOWSTATION) + sizeof(KEVENT);
  2285. pTypeInfo->DefaultPagedPoolCharge = 0;
  2286. pTypeInfo->MaintainHandleCount = TRUE;
  2287. pTypeInfo->ValidAccessMask = WinStaMapping.GenericAll;
  2288. pTypeInfo->GenericMapping = WinStaMapping;
  2289. pTypeInfo = &(*ExDesktopObjectType)->TypeInfo;
  2290. pTypeInfo->DefaultNonPagedPoolCharge = sizeof(DESKTOP);
  2291. pTypeInfo->DefaultPagedPoolCharge = 0;
  2292. pTypeInfo->MaintainHandleCount = TRUE;
  2293. pTypeInfo->ValidAccessMask = DesktopMapping.GenericAll;
  2294. pTypeInfo->GenericMapping = DesktopMapping;
  2295. /*
  2296. * Get this process so we can use the profiles.
  2297. */
  2298. gpepInit = PsGetCurrentProcess();
  2299. Status = InitQEntryLookaside();
  2300. Status |= InitSMSLookaside();
  2301. Status |= UserRtlCreateAtomTable(USRINIT_ATOMBUCKET_SIZE);
  2302. if (!NT_SUCCESS(Status)) {
  2303. RIPMSG1(RIP_WARNING,
  2304. "Initialization failure (Status = 0x%x)",
  2305. Status);
  2306. goto ExitWin32UserInitialize;
  2307. }
  2308. atomUSER32 = UserAddAtom(szUSER32, TRUE);
  2309. gatomFirstPinned = atomUSER32;
  2310. if (gatomFirstPinned == 0) {
  2311. RIPMSG0(RIP_WARNING, "Could not create atomUSER32");
  2312. goto ExitWin32UserInitialize;
  2313. }
  2314. /*
  2315. * Initialize the user subsystem information.
  2316. */
  2317. if (!InitCreateUserSubsystem()) {
  2318. RIPMSG0(RIP_WARNING, "InitCreateUserSubsystem failed");
  2319. goto ExitWin32UserInitialize;
  2320. }
  2321. /*
  2322. * Don't bail out if CreateSetupNameArray fails.
  2323. */
  2324. CreateSetupNameArray();
  2325. /*
  2326. * Allocated shared SERVERINFO structure.
  2327. */
  2328. if ((gpsi = (PSERVERINFO)SharedAlloc(sizeof(SERVERINFO))) == NULL) {
  2329. RIPMSG0(RIP_WARNING, "Could not allocate SERVERINFO");
  2330. goto ExitWin32UserInitialize;
  2331. }
  2332. /*
  2333. * Set the default rip-flags to rip on just about everything. We'll
  2334. * truly set this in the InitGlobalRIPFlags() routine. These are needed
  2335. * so that we can do appropriate ripping during the rest of the init
  2336. * calls.
  2337. */
  2338. #if DBG
  2339. SET_FLAG(gpsi->dwRIPFlags, RIPF_DEFAULT);
  2340. #endif
  2341. /*
  2342. * Make sure we will not get a division by zero if the initialization
  2343. * will not complete correctly. Set these to their normal values.
  2344. */
  2345. gpsi->cxMsgFontChar = 6;
  2346. gpsi->cyMsgFontChar = 13;
  2347. gpsi->cxSysFontChar = 8;
  2348. gpsi->cySysFontChar = 16;
  2349. /*
  2350. * Initialize the last time we updated system-wide LastSystemRITEventTickCount
  2351. * on system shared page.
  2352. */
  2353. gpsi->dwLastSystemRITEventTickCountUpdate = 0;
  2354. /*
  2355. * Initialize the DISPLAYINFO structure.
  2356. */
  2357. gpDispInfo = SharedAlloc(sizeof(*gpDispInfo));
  2358. if (!gpDispInfo) {
  2359. RIPMSG0(RIP_WARNING, "Could not allocate gpDispInfo");
  2360. goto ExitWin32UserInitialize;
  2361. }
  2362. InitDbgTags();
  2363. SET_OR_CLEAR_SRVIF(SRVIF_LOGDESKTOPHEAPFAILURE, IsDesktopHeapLoggingOn());
  2364. SET_OR_CLEAR_SRVIF(SRVIF_DBCS, IsDBCSEnabledSystem());
  2365. SET_OR_CLEAR_SRVIF(SRVIF_IME, IsIMMEnabledSystem());
  2366. #ifdef CUAS_ENABLE
  2367. SET_OR_CLEAR_SRVIF(SRVIF_CTFIME_ENABLED, IsCTFIMEEnabledSystem());
  2368. #endif // CUAS_ENABLE
  2369. SET_OR_CLEAR_SRVIF(SRVIF_MIDEAST, IsMidEastEnabledSystem());
  2370. #if DBG
  2371. SET_SRVIF(SRVIF_CHECKED);
  2372. #if !defined(CUAS_ENABLE)
  2373. RIPMSG3(RIP_WARNING, "*** win32k: DBCS:[%d] IME:[%d] MiddleEast:[%d]",
  2374. IS_DBCS_ENABLED(),
  2375. IS_IME_ENABLED(),
  2376. IS_MIDEAST_ENABLED());
  2377. #else
  2378. RIPMSG4(RIP_WARNING, "*** win32k: DBCS:[%d] IME:[%d] MiddleEast:[%d] CTFIME:[%d]",
  2379. IS_DBCS_ENABLED(),
  2380. IS_IME_ENABLED(),
  2381. IS_MIDEAST_ENABLED(),
  2382. IS_CICERO_ENABLED());
  2383. #endif
  2384. #endif
  2385. gpsi->dwDefaultHeapSize = gdwDesktopSectionSize * 1024;
  2386. /*
  2387. * Initialize procedures and message tables.
  2388. * Initialize the class structures for Get/SetClassWord/Long.
  2389. * Initialize message-box strings.
  2390. * Initialize OLE-Formats (performance-hack).
  2391. */
  2392. InitFunctionTables();
  2393. InitMessageTables();
  2394. #if DBG
  2395. VerifySyncOnlyMessages();
  2396. #endif
  2397. if (!InitOLEFormats()) {
  2398. RIPMSG0(RIP_WARNING, "InitOLEFormats failed");
  2399. goto ExitWin32UserInitialize;
  2400. }
  2401. /*
  2402. * Set up class atoms
  2403. */
  2404. if (!SetupClassAtoms()) {
  2405. RIPMSG0(RIP_WARNING, "SetupClassAtoms failed to register atoms");
  2406. goto ExitWin32UserInitialize;
  2407. }
  2408. /*
  2409. * Initialize the handle manager.
  2410. */
  2411. if (!HMInitHandleTable(gpvSharedBase)) {
  2412. RIPMSG0(RIP_WARNING, "HMInitHandleTable failed");
  2413. goto ExitWin32UserInitialize;
  2414. }
  2415. /*
  2416. * Setup shared info block.
  2417. */
  2418. gSharedInfo.psi = gpsi;
  2419. gSharedInfo.pDispInfo = gpDispInfo;
  2420. /*
  2421. * Determine if we have unsigned drivers installed
  2422. * Use 2BD63D28D7BCD0E251195AEB519243C13142EBC3 as current key to check.
  2423. * Old key: 300B971A74F97E098B67A4FCEBBBF6B9AE2F404C
  2424. */
  2425. if (NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\SOFTWARE\\Policies\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3")) ||
  2426. NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3")) ||
  2427. NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_USER, L"\\SOFTWARE\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3"))) {
  2428. gfUnsignedDrivers = TRUE;
  2429. }
  2430. FastGetProfileDwordW(NULL,
  2431. PMAP_WINDOWSM,
  2432. L"USERProcessHandleQuota",
  2433. DEFAULT_USER_HANDLE_QUOTA,
  2434. &lTemp,
  2435. 0);
  2436. gUserProcessHandleQuota = lTemp;
  2437. /*
  2438. * The maximum number of posted message for a thread.
  2439. */
  2440. FastGetProfileDwordW(NULL,
  2441. PMAP_WINDOWSM,
  2442. L"USERPostMessageLimit",
  2443. DEFAULT_POSTMESSAGE_LIMIT,
  2444. &lTemp,
  2445. 0);
  2446. if (lTemp == 0) {
  2447. /*
  2448. * 0 means (virtually) no limit.
  2449. */
  2450. gUserPostMessageLimit = ~0;
  2451. } else {
  2452. gUserPostMessageLimit = lTemp;
  2453. }
  2454. if (!gDrawVersionAlways) {
  2455. FastGetProfileDwordW(NULL,
  2456. PMAP_WINDOWSM,
  2457. L"DisplayVersion",
  2458. 0,
  2459. &gDrawVersionAlways,
  2460. 0);
  2461. }
  2462. FastGetProfileDwordW(NULL,
  2463. PMAP_TS_EXCLUDE_DESKTOP_VERSION,
  2464. L"TSExcludeDesktopVersion",
  2465. 0,
  2466. &gdwTSExcludeDesktopVersion,
  2467. 0);
  2468. FastGetProfileDwordW(NULL,
  2469. PMAP_TABLETPC,
  2470. L"Installed",
  2471. 0,
  2472. &SYSMET(TABLETPC),
  2473. 0);
  2474. FastGetProfileDwordW(NULL,
  2475. PMAP_MEDIACENTER,
  2476. L"Installed",
  2477. 0,
  2478. &SYSMET(MEDIACENTER),
  2479. 0);
  2480. /*
  2481. * Initialize SMWP structure.
  2482. */
  2483. if (!AllocateCvr(&gSMWP, 4)) {
  2484. RIPMSG0(RIP_WARNING, "AllocateCvr failed");
  2485. goto ExitWin32UserInitialize;
  2486. }
  2487. LeaveCrit();
  2488. UserAssert(NT_SUCCESS(Status));
  2489. return Status;
  2490. ExitWin32UserInitialize:
  2491. LeaveCrit();
  2492. if (NT_SUCCESS(Status)) {
  2493. Status = STATUS_NO_MEMORY;
  2494. }
  2495. RIPMSG1(RIP_WARNING, "UserInitialize failed with Status = 0x%x", Status);
  2496. return Status;
  2497. }
  2498. /**************************************************************************\
  2499. * UserGetDesktopDC
  2500. *
  2501. * 09-Jan-1992 mikeke created
  2502. * Dec-1993 andreva changed to support desktops.
  2503. \**************************************************************************/
  2504. HDC UserGetDesktopDC(
  2505. ULONG type,
  2506. BOOL bAltType,
  2507. BOOL bValidate)
  2508. {
  2509. PETHREAD Thread;
  2510. HDC hdc;
  2511. PTHREADINFO pti = PtiCurrentShared(); // This is called from outside the crit sec
  2512. HDEV hdev = gpDispInfo->hDev;
  2513. if (bValidate && type != DCTYPE_INFO &&
  2514. IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_HANDLES)) {
  2515. UserAssert(pti->rpdesk != NULL);
  2516. if (!ValidateHwnd(PtoH(pti->rpdesk->pDeskInfo->spwnd))) {
  2517. RIPMSG0(RIP_WARNING,
  2518. "UserGetDesktopDC fails desktop window validation");
  2519. return NULL;
  2520. }
  2521. }
  2522. /*
  2523. * NOTE:
  2524. * This is a real nasty trick to get both DCs created on a desktop on
  2525. * a different device to work (for the video applet) and to be able
  2526. * to clip DCs that are actually on the same device ...
  2527. */
  2528. if (pti && pti->rpdesk)
  2529. hdev = pti->rpdesk->pDispInfo->hDev;
  2530. /*
  2531. * We want to turn this call that was originally OpenDC("Display", ...)
  2532. * into GetDC null call so this DC will be clipped to the current
  2533. * desktop or else the DC can write to any desktop. Only do this
  2534. * for client apps; let the server do whatever it wants.
  2535. */
  2536. Thread = PsGetCurrentThread();
  2537. if ((type != DCTYPE_DIRECT) ||
  2538. (hdev != gpDispInfo->hDev) ||
  2539. PsIsSystemThread(Thread) ||
  2540. (PsGetThreadProcess(Thread) == gpepCSRSS)) {
  2541. hdc = GreCreateDisplayDC(hdev, type, bAltType);
  2542. } else {
  2543. PDESKTOP pdesk;
  2544. EnterCrit();
  2545. if (pdesk = PtiCurrent()->rpdesk) {
  2546. hdc = _GetDCEx(pdesk->pDeskInfo->spwnd,
  2547. NULL,
  2548. DCX_WINDOW | DCX_CACHE | DCX_CREATEDC);
  2549. } else {
  2550. hdc = NULL;
  2551. }
  2552. LeaveCrit();
  2553. }
  2554. return hdc;
  2555. }
  2556. /**************************************************************************\
  2557. * UserThreadCallout
  2558. *
  2559. *
  2560. * Called by the kernel when a thread starts or ends.
  2561. *
  2562. * Dec-1993 andreva created.
  2563. \**************************************************************************/
  2564. NTSTATUS UserThreadCallout(
  2565. IN PETHREAD pEThread,
  2566. IN PSW32THREADCALLOUTTYPE CalloutType)
  2567. {
  2568. PTHREADINFO pti;
  2569. NTSTATUS Status = STATUS_SUCCESS;
  2570. UserAssert(gpresUser != NULL);
  2571. switch (CalloutType) {
  2572. case PsW32ThreadCalloutInitialize:
  2573. TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutInitialize\n"));
  2574. if (gbNoMorePowerCallouts) {
  2575. RIPMSG0(RIP_WARNING, "No more GUI threads allowed");
  2576. return STATUS_UNSUCCESSFUL;
  2577. }
  2578. /*
  2579. * Only create a thread info structure if we're initialized.
  2580. */
  2581. if (gbUserInitialized) {
  2582. EnterCrit();
  2583. UserAssert(gpepCSRSS != NULL);
  2584. /*
  2585. * Initialize this thread
  2586. */
  2587. Status = xxxCreateThreadInfo(pEThread);
  2588. LeaveCrit();
  2589. }
  2590. break;
  2591. case PsW32ThreadCalloutExit:
  2592. TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutExit\n"));
  2593. /*
  2594. * If we aren't already inside the critical section, enter it.
  2595. * Because this is the first pass, we remain in the critical
  2596. * section when we return so that our try/finally handlers
  2597. * are protected by the critical section.
  2598. * EnterCrit here before GreUnlockDisplay() provides a pti which
  2599. * may be required if unlocking the display may release some
  2600. * deferred WinEvents, for which a pti is required.
  2601. */
  2602. EnterCrit();
  2603. pti = (PTHREADINFO)PsGetThreadWin32Thread(pEThread);
  2604. /*
  2605. * Mark this thread as in the middle of cleanup. This is useful for
  2606. * several problems in USER where we need to know this information.
  2607. */
  2608. pti->TIF_flags |= TIF_INCLEANUP;
  2609. /*
  2610. * If we died during a full screen switch make sure we cleanup
  2611. * correctly
  2612. */
  2613. FullScreenCleanup();
  2614. /*
  2615. * Cleanup gpDispInfo->hdcScreen - if we crashed while using it,
  2616. * it may have owned objects still selected into it. Cleaning
  2617. * it this way will ensure that gdi doesn't try to delete these
  2618. * objects while they are still selected into this public hdc.
  2619. */
  2620. /*
  2621. * WinStations that haven't gone through the first connect do not
  2622. * have any of the graphics setup.
  2623. */
  2624. if (!gbRemoteSession || gbVideoInitialized) {
  2625. GreCleanDC(gpDispInfo->hdcScreen);
  2626. }
  2627. /*
  2628. * This thread is exiting execution; xxxDestroyThreadInfo cleans
  2629. * up everything that can go now
  2630. */
  2631. UserAssert(pti == PtiCurrent());
  2632. xxxDestroyThreadInfo();
  2633. LeaveCrit();
  2634. break;
  2635. }
  2636. TRACE_INIT(("Leaving UserThreadCallout\n"));
  2637. return Status;
  2638. }
  2639. /**************************************************************************\
  2640. * NtUserInitialize
  2641. *
  2642. * 01-Dec-1993 andreva created.
  2643. * 01-Dec-1995 BradG Modified to return handle to Media Change Event
  2644. \**************************************************************************/
  2645. BOOL TellGdiToGetReady();
  2646. NTSTATUS NtUserInitialize(
  2647. IN DWORD dwVersion,
  2648. IN HANDLE hPowerRequestEvent,
  2649. IN HANDLE hMediaRequestEvent)
  2650. {
  2651. NTSTATUS Status;
  2652. TRACE_INIT(("Entering NtUserInitialize\n"));
  2653. /*
  2654. * Make sure we're not trying to load this twice.
  2655. */
  2656. if (gpepCSRSS != NULL) {
  2657. RIPMSG0(RIP_WARNING, "Can't initialize more than once");
  2658. return STATUS_UNSUCCESSFUL;
  2659. }
  2660. /*
  2661. * Check version number
  2662. */
  2663. if (dwVersion != USERCURRENTVERSION) {
  2664. KeBugCheckEx(WIN32K_INIT_OR_RIT_FAILURE,
  2665. 0,
  2666. 0,
  2667. dwVersion,
  2668. USERCURRENTVERSION);
  2669. }
  2670. /*
  2671. * Get the session ID from the EPROCESS structure
  2672. */
  2673. gSessionId = PsGetCurrentProcessSessionId();
  2674. UserAssert(gSessionId == 0 || gbRemoteSession == TRUE);
  2675. Status = InitializePowerRequestList(hPowerRequestEvent);
  2676. if (!NT_SUCCESS(Status)) {
  2677. return Status;
  2678. }
  2679. Status = InitializeMediaChange(hMediaRequestEvent);
  2680. if (!NT_SUCCESS(Status)) {
  2681. return Status;
  2682. }
  2683. /*
  2684. * Save the system process structure.
  2685. */
  2686. gpepCSRSS = PsGetCurrentProcess();
  2687. ObReferenceObject(gpepCSRSS);
  2688. if (!TellGdiToGetReady()) {
  2689. RIPMSG0(RIP_WARNING, "TellGdiToGetReady failed");
  2690. Status = STATUS_UNSUCCESSFUL;
  2691. return Status;
  2692. }
  2693. /*
  2694. * Allow CSR to read the screen
  2695. */
  2696. ((PW32PROCESS)PsGetProcessWin32Process(gpepCSRSS))->W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED|W32PF_IOWINSTA);
  2697. Status = UserInitialize();
  2698. TRACE_INIT(("Leaving NtUserInitialize\n"));
  2699. return Status;
  2700. }
  2701. /**************************************************************************\
  2702. * NtUserProcessConnect
  2703. *
  2704. * 01-Dec-1993 Andreva Created.
  2705. \**************************************************************************/
  2706. NTSTATUS NtUserProcessConnect(
  2707. IN HANDLE hProcess,
  2708. IN OUT PVOID pConnectInfo,
  2709. IN ULONG cbConnectInfo)
  2710. {
  2711. PEPROCESS Process;
  2712. PUSERCONNECT pucConnect = (PUSERCONNECT)pConnectInfo;
  2713. USERCONNECT ucLocal;
  2714. NTSTATUS Status = STATUS_SUCCESS;
  2715. TRACE_INIT(("Entering NtUserProcessConnect\n"));
  2716. if (!pucConnect || (cbConnectInfo != sizeof(USERCONNECT))) {
  2717. return STATUS_UNSUCCESSFUL;
  2718. }
  2719. try {
  2720. ProbeForWrite(pucConnect, cbConnectInfo, sizeof(DWORD));
  2721. ucLocal = *pucConnect;
  2722. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  2723. return GetExceptionCode();
  2724. }
  2725. /*
  2726. * Check client/server versions.
  2727. */
  2728. if (ucLocal.ulVersion != USERCURRENTVERSION) {
  2729. RIPMSG2(RIP_ERROR,
  2730. "Client version %lx > server version %lx\n",
  2731. ucLocal.ulVersion, USERCURRENTVERSION);
  2732. return STATUS_UNSUCCESSFUL;
  2733. }
  2734. if (ucLocal.dwDispatchCount != gDispatchTableValues) {
  2735. RIPMSG2(RIP_ERROR,
  2736. "!!!! Client Dispatch info %lX != Server %lX\n",
  2737. ucLocal.dwDispatchCount, gDispatchTableValues);
  2738. }
  2739. /*
  2740. * Reference the process.
  2741. */
  2742. Status = ObReferenceObjectByHandle(hProcess,
  2743. PROCESS_VM_OPERATION,
  2744. *PsProcessType,
  2745. UserMode,
  2746. &Process,
  2747. NULL);
  2748. if (!NT_SUCCESS(Status))
  2749. return Status;
  2750. /*
  2751. * Return client's view of shared data.
  2752. */
  2753. EnterCrit();
  2754. Status = InitMapSharedSection(Process, &ucLocal);
  2755. LeaveCrit();
  2756. if (!NT_SUCCESS(Status)) {
  2757. RIPMSG2(RIP_WARNING,
  2758. "Failed to map shared data into client %x, status = %x\n",
  2759. PsGetCurrentProcessId(), Status);
  2760. }
  2761. ObDereferenceObject(Process);
  2762. if (NT_SUCCESS(Status)) {
  2763. try {
  2764. *pucConnect = ucLocal;
  2765. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  2766. Status = GetExceptionCode();
  2767. }
  2768. }
  2769. TRACE_INIT(("Leaving NtUserProcessConnect\n"));
  2770. return Status;
  2771. }
  2772. /**************************************************************************\
  2773. * xxxUserProcessCallout
  2774. *
  2775. * 01-Dec-1993 andreva Created.
  2776. \**************************************************************************/
  2777. NTSTATUS xxxUserProcessCallout(
  2778. IN PW32PROCESS Process,
  2779. IN BOOLEAN Initialize)
  2780. {
  2781. NTSTATUS Status = STATUS_SUCCESS;
  2782. if (Initialize) {
  2783. TRACE_INIT(("Entering xxxUserProcessCallout Initialize\n"));
  2784. UserAssert(gpresUser != NULL);
  2785. EnterCrit();
  2786. /*
  2787. * Initialize the important process level stuff.
  2788. */
  2789. Status = xxxInitProcessInfo(Process);
  2790. LeaveCrit();
  2791. if (Status == STATUS_SUCCESS) {
  2792. PEJOB Job = PsGetProcessJob(Process->Process);
  2793. if (Job != NULL &&
  2794. PsGetJobUIRestrictionsClass(Job) != 0) {
  2795. WIN32_JOBCALLOUT_PARAMETERS Parms;
  2796. /*
  2797. * aquire the job's lock and after that enter the user
  2798. * critical section.
  2799. */
  2800. KeEnterCriticalRegion();
  2801. ExAcquireResourceExclusiveLite(PsGetJobLock(Job), TRUE);
  2802. Parms.Job = Job;
  2803. Parms.CalloutType = PsW32JobCalloutAddProcess;
  2804. Parms.Data = Process;
  2805. UserAssert(PsGetJobSessionId(Job) == PsGetProcessSessionId(Process->Process));
  2806. UserJobCallout(&Parms);
  2807. ExReleaseResourceLite(PsGetJobLock(Job));
  2808. KeLeaveCriticalRegion();
  2809. }
  2810. }
  2811. } else {
  2812. int i;
  2813. PHE phe;
  2814. PDCE *ppdce;
  2815. PDCE pdce;
  2816. TRACE_INIT(("Entering xxxUserProcessCallout Cleanup\n"));
  2817. UserAssert(gpresUser != NULL);
  2818. EnterCrit();
  2819. #if DBG
  2820. if (Process->Process == gpepCSRSS) {
  2821. /*
  2822. * CSRSS should be the last to go ...
  2823. */
  2824. UserAssert(gppiList->ppiNextRunning == NULL);
  2825. }
  2826. #endif // DBG
  2827. if (Process->Process && PsGetProcessJob(Process->Process) != NULL) {
  2828. RemoveProcessFromJob((PPROCESSINFO)Process);
  2829. }
  2830. /*
  2831. * DestroyProcessInfo will return TRUE if any threads ever
  2832. * connected. If nothing ever connected, we needn't do
  2833. * this cleanup.
  2834. */
  2835. if (DestroyProcessInfo(Process)) {
  2836. /*
  2837. * See if we can compact the handle table.
  2838. */
  2839. i = giheLast;
  2840. phe = &gSharedInfo.aheList[giheLast];
  2841. while ((phe > &gSharedInfo.aheList[0]) && (phe->bType == TYPE_FREE)) {
  2842. phe--;
  2843. giheLast--;
  2844. }
  2845. /*
  2846. * Scan the DC cache to find any DC's that need to be destroyed.
  2847. */
  2848. for (ppdce = &gpDispInfo->pdceFirst; *ppdce != NULL; ) {
  2849. pdce = *ppdce;
  2850. if (pdce->DCX_flags & DCX_DESTROYTHIS)
  2851. DestroyCacheDC(ppdce, pdce->hdc);
  2852. /*
  2853. * Step to the next DC. If the DC was deleted, there
  2854. * is no need to calculate the address of the next entry.
  2855. */
  2856. if (pdce == *ppdce)
  2857. ppdce = &pdce->pdceNext;
  2858. }
  2859. }
  2860. UserAssert(gpresUser != NULL);
  2861. LeaveCrit();
  2862. }
  2863. TRACE_INIT(("Leaving xxxUserProcessCallout\n"));
  2864. return Status;
  2865. }
  2866. /**************************************************************************\
  2867. * UserGetHDEV
  2868. *
  2869. * Provided as a means for GDI to get a hold of USER's hDev.
  2870. *
  2871. * 01-Jan-1996 ChrisWil Created.
  2872. \**************************************************************************/
  2873. HDEV UserGetHDEV(VOID)
  2874. {
  2875. /*
  2876. * NOTE: This is busted.
  2877. * This need to return the device for the current desktop.
  2878. * The graphics device may not be the same for all desktops.
  2879. * -Andre
  2880. */
  2881. return gpDispInfo->hDev;
  2882. }
  2883. /**************************************************************************\
  2884. * _UserGetGlobalAtomTable
  2885. *
  2886. * This function is called by the kernel mode global atom manager to get the
  2887. * address of the current thread's global atom table.
  2888. *
  2889. * Pointer to the global atom table for the current thread or NULL if unable
  2890. * to access it.
  2891. \**************************************************************************/
  2892. PVOID UserGlobalAtomTableCallout(
  2893. VOID)
  2894. {
  2895. PETHREAD Thread;
  2896. PTHREADINFO pti;
  2897. PWINDOWSTATION pwinsta;
  2898. PW32JOB pW32Job;
  2899. PEJOB Job;
  2900. PVOID GlobalAtomTable = NULL;
  2901. Thread = PsGetCurrentThread();
  2902. pti = PtiFromThread(Thread);
  2903. EnterCrit();
  2904. /*
  2905. * For restricted threads access the atom table off of the job object
  2906. */
  2907. if (pti != NULL && IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
  2908. TAGMSG1(DBGTAG_Callout, "Retrieving global atom table for pti 0x%p", pti);
  2909. pW32Job = pti->ppi->pW32Job;
  2910. UserAssert(pW32Job->pAtomTable != NULL);
  2911. GlobalAtomTable = pW32Job->pAtomTable;
  2912. goto End;
  2913. }
  2914. Job = PsGetProcessJob(PsGetCurrentProcess());
  2915. /*
  2916. * Now handle the case where this is not a GUI thread/process
  2917. * but it is assigned to a job that has JOB_OBJECT_UILIMIT_GLOBALATOMS
  2918. * restrictions set. There is no easy way to convert this thread
  2919. * to GUI.
  2920. */
  2921. if (pti == NULL && Job != NULL &&
  2922. (PsGetJobUIRestrictionsClass(Job) & JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
  2923. /*
  2924. * find the W32JOB in the global list
  2925. */
  2926. pW32Job = gpJobsList;
  2927. while (pW32Job) {
  2928. if (pW32Job->Job == Job) {
  2929. break;
  2930. }
  2931. pW32Job = pW32Job->pNext;
  2932. }
  2933. UserAssert(pW32Job != NULL && pW32Job->pAtomTable != NULL);
  2934. GlobalAtomTable = pW32Job->pAtomTable;
  2935. goto End;
  2936. }
  2937. #if DBG
  2938. pwinsta = NULL;
  2939. #endif
  2940. if (NT_SUCCESS(ReferenceWindowStation(Thread,
  2941. PsGetCurrentProcessWin32WindowStation(),
  2942. WINSTA_ACCESSGLOBALATOMS,
  2943. &pwinsta,
  2944. TRUE))) {
  2945. UserAssert(pwinsta != NULL);
  2946. GlobalAtomTable = pwinsta->pGlobalAtomTable;
  2947. }
  2948. End:
  2949. LeaveCrit();
  2950. #if DBG
  2951. if (GlobalAtomTable == NULL) {
  2952. RIPMSG1(RIP_WARNING,
  2953. "_UserGetGlobalAtomTable: NULL Atom Table for pwinsta=%#p",
  2954. pwinsta);
  2955. }
  2956. #endif
  2957. return GlobalAtomTable;
  2958. }