test: server.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# server.c

Go to the documentation of this file.

    00001 /**************************************************************************\
    00002 * Module Name: server.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * Server support routines for the CSR stuff.  This basically performs the
    00007 * startup/initialization for USER.
    00008 *
    00009 \**************************************************************************/
    00010
    00011 #include "precomp.h"
    00012 #pragma hdrstop
    00013
    00014 extern WORD gDispatchTableValues;
    00015
    00016 BOOL gbUserInitialized;
    00017
    00018 /*
    00019  * Initialization Routines (external).
    00020  */
    00021 NTSTATUS     InitQEntryLookaside(VOID);
    00022 NTSTATUS     InitSMSLookaside(VOID);
    00023
    00024 NTSTATUS    InitCreateSharedSection(VOID);
    00025 NTSTATUS    InitCreateObjectDirectory(VOID);
    00026 BOOL        InitCreateUserSubsystem(VOID);
    00027 VOID        InitFunctionTables(VOID);
    00028 VOID        InitMessageTables(VOID);
    00029 VOID        InitWindowMsgTable(PBYTE*, PUINT, CONST WORD*);
    00030
    00031 VOID        VerifySyncOnlyMessages(VOID);
    00032 BOOL        InitOLEFormats(VOID);
    00033 NTSTATUS    Win32UserInitialize(VOID);
    00034
    00035 #pragma alloc_text(INIT, InitCreateSharedSection)
    00036 #pragma alloc_text(INIT, InitCreateUserCrit)
    00037 #pragma alloc_text(INIT, InitCreateObjectDirectory)
    00038 #pragma alloc_text(INIT, InitCreateUserSubsystem)
    00039 //#pragma alloc_text(INIT, InitDbgTags)
    00040 #pragma alloc_text(INIT, InitFunctionTables)
    00041 #pragma alloc_text(INIT, InitMessageTables)
    00042 #pragma alloc_text(INIT, InitWindowMsgTable)
    00043
    00044 #pragma alloc_text(INIT, VerifySyncOnlyMessages)
    00045 #pragma alloc_text(INIT, InitOLEFormats)
    00046 #pragma alloc_text(INIT, Win32UserInitialize)
    00047
    00048 /*
    00049  * Constants pertaining to the user-initialization.
    00050  */
    00051 #define USRINIT_SHAREDSECT_SIZE   32
    00052 #define USRINIT_ATOMBUCKET_SIZE   37
    00053
    00054 #define USRINIT_WINDOWSECT_SIZE  512
    00055 #define USRINIT_NOIOSECT_SIZE    128
    00056
    00057 #define USRINIT_SHAREDSECT_BUFF_SIZE     640
    00058 #define USRINIT_SHAREDSECT_READ_SIZE     (USRINIT_SHAREDSECT_BUFF_SIZE-33)
    00059
    00060
    00061 /***************************************************************************\
    00062 * Globals stored in the INIT section. These should only be accessed at
    00063 * load time!
    00064 \***************************************************************************/
    00065 #ifdef ALLOC_DATA_PRAGMA
    00066 #pragma data_seg("INIT$Data")
    00067 #endif
    00068
    00069 CONST WCHAR szCHECKPOINT_PROP_NAME[]  = L"SysCP";
    00070 CONST WCHAR szDDETRACK_PROP_NAME[]    = L"SysDT";
    00071 CONST WCHAR szQOS_PROP_NAME[]         = L"SysQOS";
    00072 CONST WCHAR szDDEIMP_PROP_NAME[]      = L"SysDDEI";
    00073 CONST WCHAR szWNDOBJ_PROP_NAME[]      = L"SysWNDO";
    00074 CONST WCHAR szIMELEVEL_PROP_NAME[]    = L"SysIMEL";
    00075 CONST WCHAR szLAYER_PROP_NAME[]       = L"SysLayer";
    00076 CONST WCHAR szUSER32[]                = L"USER32";
    00077 CONST WCHAR szMESSAGE[]               = L"Message";
    00078 CONST WCHAR szCONTEXTHELPIDPROP[]     = L"SysCH";
    00079 CONST WCHAR szICONSM_PROP_NAME[]      = L"SysICS";
    00080 CONST WCHAR szICON_PROP_NAME[]        = ICON_PROP_NAME;
    00081 CONST WCHAR szSHELLHOOK[]             = L"SHELLHOOK";
    00082 CONST WCHAR szACTIVATESHELLWINDOW[]   = L"ACTIVATESHELLWINDOW";
    00083 CONST WCHAR szOTHERWINDOWCREATED[]    = L"OTHERWINDOWCREATED";
    00084 CONST WCHAR szOTHERWINDOWDESTROYED[]  = L"OTHERWINDOWDESTROYED";
    00085 CONST WCHAR szOLEMAINTHREADWNDCLASS[] = L"OleMainThreadWndClass";
    00086 CONST WCHAR szFLASHWSTATE[]           = L"FlashWState";
    00087
    00088 #ifdef HUNGAPP_GHOSTING
    00089 CONST WCHAR szGHOST[]                 = L"Ghost";
    00090 #endif // HUNGAPP_GHOSTING
    00091
    00092
    00093 /***************************************************************************\
    00094 * Message Tables
    00095 *
    00096 *   DefDlgProc
    00097 *   MenuWndProc
    00098 *   ScrollBarWndProc
    00099 *   StaticWndProc
    00100 *   ButtonWndProc
    00101 *   ListboxWndProc
    00102 *   ComboWndProc
    00103 *   EditWndProc
    00104 *   DefWindowMsgs
    00105 *   DefWindowSpecMsgs
    00106 *
    00107 * These are used in InitMessageTables() to initialize gSharedInfo.awmControl[]
    00108 * using the INITMSGTABLE() macro.
    00109 *
    00110 * 25-Aug-1995 ChrisWil  Created comment block.
    00111 \***************************************************************************/
    00112
    00113 CONST WORD gawDefDlgProc[] = {
    00114     WM_COMPAREITEM,
    00115     WM_VKEYTOITEM,
    00116     WM_CHARTOITEM,
    00117     WM_INITDIALOG,
    00118     WM_QUERYDRAGICON,
    00119     WM_CTLCOLOR,
    00120     WM_CTLCOLORMSGBOX,
    00121     WM_CTLCOLOREDIT,
    00122     WM_CTLCOLORLISTBOX,
    00123     WM_CTLCOLORBTN,
    00124     WM_CTLCOLORDLG,
    00125     WM_CTLCOLORSCROLLBAR,
    00126     WM_CTLCOLORSTATIC,
    00127     WM_ERASEBKGND,
    00128     WM_SHOWWINDOW,
    00129     WM_SYSCOMMAND,
    00130     WM_SYSKEYDOWN,
    00131     WM_ACTIVATE,
    00132     WM_SETFOCUS,
    00133     WM_CLOSE,
    00134     WM_NCDESTROY,
    00135     WM_FINALDESTROY,
    00136     DM_REPOSITION,
    00137     DM_SETDEFID,
    00138     DM_GETDEFID,
    00139     WM_NEXTDLGCTL,
    00140     WM_ENTERMENULOOP,
    00141     WM_LBUTTONDOWN,
    00142     WM_NCLBUTTONDOWN,
    00143     WM_GETFONT,
    00144     WM_NOTIFYFORMAT,
    00145     WM_INPUTLANGCHANGEREQUEST,
    00146     0
    00147 };
    00148
    00149 CONST WORD gawMenuWndProc[] = {
    00150     WM_NCCREATE,
    00151     WM_FINALDESTROY,
    00152     WM_PAINT,
    00153     WM_NCCALCSIZE,
    00154     WM_CHAR,
    00155     WM_SYSCHAR,
    00156     WM_KEYDOWN,
    00157     WM_SYSKEYDOWN,
    00158     WM_TIMER,
    00159     MN_SETHMENU,
    00160     MN_SIZEWINDOW,
    00161     MN_OPENHIERARCHY,
    00162     MN_CLOSEHIERARCHY,
    00163     MN_SELECTITEM,
    00164     MN_SELECTFIRSTVALIDITEM,
    00165     MN_CANCELMENUS,
    00166     MN_FINDMENUWINDOWFROMPOINT,
    00167     MN_SHOWPOPUPWINDOW,
    00168     MN_BUTTONDOWN,
    00169     MN_MOUSEMOVE,
    00170     MN_BUTTONUP,
    00171     MN_SETTIMERTOOPENHIERARCHY,
    00172     WM_ACTIVATE,
    00173     MN_GETHMENU,
    00174     MN_DBLCLK,
    00175     MN_ACTIVATEPOPUP,
    00176     MN_ENDMENU,
    00177     MN_DODRAGDROP,
    00178     WM_ACTIVATEAPP,
    00179     WM_MOUSELEAVE,
    00180     WM_SIZE,
    00181     WM_MOVE,
    00182     WM_NCHITTEST,
    00183     WM_NCPAINT,
    00184     WM_PRINT,
    00185     WM_PRINTCLIENT,
    00186     WM_ERASEBKGND,
    00187     WM_WINDOWPOSCHANGING,
    00188     WM_WINDOWPOSCHANGED,
    00189     0
    00190 };
    00191
    00192 CONST WORD gawDesktopWndProc[] = {
    00193     WM_PAINT,
    00194     WM_ERASEBKGND,
    00195     0
    00196 };
    00197
    00198 CONST WORD gawScrollBarWndProc[] = {
    00199     WM_CREATE,
    00200     WM_SETFOCUS,
    00201     WM_KILLFOCUS,
    00202     WM_ERASEBKGND,
    00203     WM_PAINT,
    00204     WM_LBUTTONDBLCLK,
    00205     WM_LBUTTONDOWN,
    00206     WM_KEYUP,
    00207     WM_KEYDOWN,
    00208     WM_ENABLE,
    00209     SBM_ENABLE_ARROWS,
    00210     SBM_SETPOS,
    00211     SBM_SETRANGEREDRAW,
    00212     SBM_SETRANGE,
    00213     SBM_SETSCROLLINFO,
    00214     SBM_GETSCROLLINFO,
    00215     WM_PRINTCLIENT,
    00216     WM_MOUSEMOVE,
    00217     WM_MOUSELEAVE,
    00218     0
    00219 };
    00220
    00221 CONST WORD gawStaticWndProc[] = {
    00222     STM_GETICON,
    00223     STM_GETIMAGE,
    00224     STM_SETICON,
    00225     STM_SETIMAGE,
    00226     WM_ERASEBKGND,
    00227     WM_PAINT,
    00228     WM_PRINTCLIENT,
    00229     WM_CREATE,
    00230     WM_DESTROY,
    00231     WM_NCCREATE,
    00232     WM_NCDESTROY,
    00233     WM_FINALDESTROY,
    00234     WM_NCHITTEST,
    00235     WM_LBUTTONDOWN,
    00236     WM_NCLBUTTONDOWN,
    00237     WM_LBUTTONDBLCLK,
    00238     WM_NCLBUTTONDBLCLK,
    00239     WM_SETTEXT,
    00240     WM_ENABLE,
    00241     WM_GETDLGCODE,
    00242     WM_SETFONT,
    00243     WM_GETFONT,
    00244     WM_GETTEXT,
    00245     WM_TIMER,
    00246     WM_INPUTLANGCHANGEREQUEST,
    00247     WM_UPDATEUISTATE,
    00248     0
    00249 };
    00250
    00251 CONST WORD gawButtonWndProc[] = {
    00252     WM_NCHITTEST,
    00253     WM_ERASEBKGND,
    00254     WM_PRINTCLIENT,
    00255     WM_PAINT,
    00256     WM_SETFOCUS,
    00257     WM_GETDLGCODE,
    00258     WM_CAPTURECHANGED,
    00259     WM_KILLFOCUS,
    00260     WM_LBUTTONDBLCLK,
    00261     WM_LBUTTONUP,
    00262     WM_MOUSEMOVE,
    00263     WM_LBUTTONDOWN,
    00264     WM_CHAR,
    00265     BM_CLICK,
    00266     WM_KEYDOWN,
    00267     WM_KEYUP,
    00268     WM_SYSKEYUP,
    00269     BM_GETSTATE,
    00270     BM_SETSTATE,
    00271     BM_GETCHECK,
    00272     BM_SETCHECK,
    00273     BM_SETSTYLE,
    00274     WM_SETTEXT,
    00275     WM_ENABLE,
    00276     WM_SETFONT,
    00277     WM_GETFONT,
    00278     BM_GETIMAGE,
    00279     BM_SETIMAGE,
    00280     WM_NCDESTROY,
    00281     WM_FINALDESTROY,
    00282     WM_NCCREATE,
    00283     WM_INPUTLANGCHANGEREQUEST,
    00284     WM_UPDATEUISTATE,
    00285     0
    00286 };
    00287
    00288 CONST WORD gawListboxWndProc[] = {
    00289     LB_GETTOPINDEX,
    00290     LB_SETTOPINDEX,
    00291     WM_SIZE,
    00292     WM_ERASEBKGND,
    00293     LB_RESETCONTENT,
    00294     WM_TIMER,
    00295     WM_MOUSEMOVE,
    00296     WM_MBUTTONDOWN,
    00297     WM_LBUTTONDOWN,
    00298     WM_LBUTTONUP,
    00299     WM_LBUTTONDBLCLK,
    00300     WM_CAPTURECHANGED,
    00301     LBCB_STARTTRACK,
    00302     LBCB_ENDTRACK,
    00303     WM_PRINTCLIENT,
    00304     WM_PAINT,
    00305     WM_NCDESTROY,
    00306     WM_FINALDESTROY,
    00307     WM_SETFOCUS,
    00308     WM_KILLFOCUS,
    00309     WM_VSCROLL,
    00310     WM_HSCROLL,
    00311     WM_GETDLGCODE,
    00312     WM_CREATE,
    00313     WM_SETREDRAW,
    00314     WM_ENABLE,
    00315     WM_SETFONT,
    00316     WM_GETFONT,
    00317     WM_DRAGSELECT,
    00318     WM_DRAGLOOP,
    00319     WM_DRAGMOVE,
    00320     WM_DROPFILES,
    00321     WM_QUERYDROPOBJECT,
    00322     WM_DROPOBJECT,
    00323     LB_GETITEMRECT,
    00324     LB_GETITEMDATA,
    00325     LB_SETITEMDATA,
    00326     LB_ADDSTRINGUPPER,
    00327     LB_ADDSTRINGLOWER,
    00328     LB_ADDSTRING,
    00329     LB_INSERTSTRINGUPPER,
    00330     LB_INSERTSTRINGLOWER,
    00331     LB_INSERTSTRING,
    00332     LB_INITSTORAGE,
    00333     LB_DELETESTRING,
    00334     LB_DIR,
    00335     LB_ADDFILE,
    00336     LB_SETSEL,
    00337     LB_SETCURSEL,
    00338     LB_GETSEL,
    00339     LB_GETCURSEL,
    00340     LB_SELITEMRANGE,
    00341     LB_SELITEMRANGEEX,
    00342     LB_GETTEXTLEN,
    00343     LB_GETTEXT,
    00344     LB_GETCOUNT,
    00345     LB_SETCOUNT,
    00346     LB_SELECTSTRING,
    00347     LB_FINDSTRING,
    00348     LB_GETLOCALE,
    00349     LB_SETLOCALE,
    00350     WM_KEYDOWN,
    00351     WM_CHAR,
    00352     LB_GETSELITEMS,
    00353     LB_GETSELCOUNT,
    00354     LB_SETTABSTOPS,
    00355     LB_GETHORIZONTALEXTENT,
    00356     LB_SETHORIZONTALEXTENT,
    00357     LB_SETCOLUMNWIDTH,
    00358     LB_SETANCHORINDEX,
    00359     LB_GETANCHORINDEX,
    00360     LB_SETCARETINDEX,
    00361     LB_GETCARETINDEX,
    00362     LB_SETITEMHEIGHT,
    00363     LB_GETITEMHEIGHT,
    00364     LB_FINDSTRINGEXACT,
    00365     LB_ITEMFROMPOINT,
    00366     LB_SETLOCALE,
    00367     LB_GETLOCALE,
    00368     LBCB_CARETON,
    00369     LBCB_CARETOFF,
    00370     WM_NCCREATE,
    00371     WM_WINDOWPOSCHANGED,
    00372     WM_MOUSEWHEEL,
    00373     WM_STYLECHANGED,
    00374     WM_STYLECHANGING,
    00375     0
    00376 };
    00377
    00378 CONST WORD gawComboWndProc[] = {
    00379     CBEC_KILLCOMBOFOCUS,
    00380     WM_COMMAND,
    00381     WM_CTLCOLORMSGBOX,
    00382     WM_CTLCOLOREDIT,
    00383     WM_CTLCOLORLISTBOX,
    00384     WM_CTLCOLORBTN,
    00385     WM_CTLCOLORDLG,
    00386     WM_CTLCOLORSCROLLBAR,
    00387     WM_CTLCOLORSTATIC,
    00388     WM_CTLCOLOR,
    00389     WM_GETTEXT,
    00390     WM_GETTEXTLENGTH,
    00391     WM_CLEAR,
    00392     WM_CUT,
    00393     WM_PASTE,
    00394     WM_COPY,
    00395     WM_SETTEXT,
    00396     WM_CREATE,
    00397     WM_ERASEBKGND,
    00398     WM_GETFONT,
    00399     WM_PRINT,
    00400     WM_PRINTCLIENT,
    00401     WM_PAINT,
    00402     WM_GETDLGCODE,
    00403     WM_SETFONT,
    00404     WM_SYSKEYDOWN,
    00405     WM_KEYDOWN,
    00406     WM_CHAR,
    00407     WM_LBUTTONDBLCLK,
    00408     WM_LBUTTONDOWN,
    00409     WM_CAPTURECHANGED,
    00410     WM_LBUTTONUP,
    00411     WM_MOUSEMOVE,
    00412     WM_NCDESTROY,
    00413     WM_FINALDESTROY,
    00414     WM_SETFOCUS,
    00415     WM_KILLFOCUS,
    00416     WM_SETREDRAW,
    00417     WM_ENABLE,
    00418     WM_SIZE,
    00419     CB_GETDROPPEDSTATE,
    00420     CB_GETDROPPEDCONTROLRECT,
    00421     CB_SETDROPPEDWIDTH,
    00422     CB_GETDROPPEDWIDTH,
    00423     CB_DIR,
    00424     CB_SETEXTENDEDUI,
    00425     CB_GETEXTENDEDUI,
    00426     CB_GETEDITSEL,
    00427     CB_LIMITTEXT,
    00428     CB_SETEDITSEL,
    00429     CB_ADDSTRING,
    00430     CB_DELETESTRING,
    00431     CB_INITSTORAGE,
    00432     CB_SETTOPINDEX,
    00433     CB_GETTOPINDEX,
    00434     CB_GETCOUNT,
    00435     CB_GETCURSEL,
    00436     CB_GETLBTEXT,
    00437     CB_GETLBTEXTLEN,
    00438     CB_INSERTSTRING,
    00439     CB_RESETCONTENT,
    00440     CB_GETHORIZONTALEXTENT,
    00441     CB_SETHORIZONTALEXTENT,
    00442     CB_FINDSTRING,
    00443     CB_FINDSTRINGEXACT,
    00444     CB_SELECTSTRING,
    00445     CB_SETCURSEL,
    00446     CB_GETITEMDATA,
    00447     CB_SETITEMDATA,
    00448     CB_SETITEMHEIGHT,
    00449     CB_GETITEMHEIGHT,
    00450     CB_SHOWDROPDOWN,
    00451     CB_SETLOCALE,
    00452     CB_GETLOCALE,
    00453     WM_MEASUREITEM,
    00454     WM_DELETEITEM,
    00455     WM_DRAWITEM,
    00456     WM_COMPAREITEM,
    00457     WM_NCCREATE,
    00458     WM_HELP,
    00459     WM_MOUSEWHEEL,
    00460     WM_MOUSELEAVE,
    00461     WM_STYLECHANGED,
    00462     WM_STYLECHANGING,
    00463     WM_UPDATEUISTATE,
    00464     0
    00465 };
    00466
    00467 CONST WORD gawEditWndProc[] = {
    00468     EM_CANUNDO,
    00469     EM_CHARFROMPOS,
    00470     EM_EMPTYUNDOBUFFER,
    00471     EM_FMTLINES,
    00472     EM_GETFIRSTVISIBLELINE,
    00473     EM_GETFIRSTVISIBLELINE,
    00474     EM_GETHANDLE,
    00475     EM_GETLIMITTEXT,
    00476     EM_GETLINE,
    00477     EM_GETLINECOUNT,
    00478     EM_GETMARGINS,
    00479     EM_GETMODIFY,
    00480     EM_GETPASSWORDCHAR,
    00481     EM_GETRECT,
    00482     EM_GETSEL,
    00483     EM_GETWORDBREAKPROC,
    00484     EM_SETIMESTATUS,
    00485     EM_GETIMESTATUS,
    00486     EM_LINEFROMCHAR,
    00487     EM_LINEINDEX,
    00488     EM_LINELENGTH,
    00489     EM_LINESCROLL,
    00490     EM_POSFROMCHAR,
    00491     EM_REPLACESEL,
    00492     EM_SCROLL,
    00493     EM_SCROLLCARET,
    00494     EM_SETHANDLE,
    00495     EM_SETLIMITTEXT,
    00496     EM_SETMARGINS,
    00497     EM_SETMODIFY,
    00498     EM_SETPASSWORDCHAR,
    00499     EM_SETREADONLY,
    00500     EM_SETRECT,
    00501     EM_SETRECTNP,
    00502     EM_SETSEL,
    00503     EM_SETTABSTOPS,
    00504     EM_SETWORDBREAKPROC,
    00505     EM_UNDO,
    00506     WM_CAPTURECHANGED,
    00507     WM_CHAR,
    00508     WM_CLEAR,
    00509     WM_CONTEXTMENU,
    00510     WM_COPY,
    00511     WM_CREATE,
    00512     WM_CUT,
    00513     WM_ENABLE,
    00514     WM_ERASEBKGND,
    00515     WM_GETDLGCODE,
    00516     WM_GETFONT,
    00517     WM_GETTEXT,
    00518     WM_GETTEXTLENGTH,
    00519     WM_HSCROLL,
    00520     WM_IME_STARTCOMPOSITION,
    00521     WM_IME_ENDCOMPOSITION,
    00522     WM_IME_COMPOSITION,
    00523     WM_IME_SETCONTEXT,
    00524     WM_IME_NOTIFY,
    00525     WM_IME_COMPOSITIONFULL,
    00526     WM_IME_SELECT,
    00527     WM_IME_CHAR,
    00528     WM_IME_REQUEST,
    00529     WM_INPUTLANGCHANGE,
    00530     WM_KEYUP,
    00531     WM_KEYDOWN,
    00532     WM_KILLFOCUS,
    00533     WM_MBUTTONDOWN,
    00534     WM_LBUTTONDBLCLK,
    00535     WM_LBUTTONDOWN,
    00536     WM_LBUTTONUP,
    00537     WM_MOUSEMOVE,
    00538     WM_NCCREATE,
    00539     WM_NCDESTROY,
    00540     WM_RBUTTONDOWN,
    00541     WM_RBUTTONUP,
    00542     WM_FINALDESTROY,
    00543 #if 0
    00544     WM_NCPAINT,
    00545 #endif
    00546     WM_PAINT,
    00547     WM_PASTE,
    00548     WM_PRINTCLIENT,
    00549     WM_SETFOCUS,
    00550     WM_SETFONT,
    00551     WM_SETREDRAW,
    00552     WM_SETTEXT,
    00553     WM_SIZE,
    00554     WM_STYLECHANGED,
    00555     WM_STYLECHANGING,
    00556     WM_SYSCHAR,
    00557     WM_SYSKEYDOWN,
    00558     WM_SYSTIMER,
    00559     WM_UNDO,
    00560     WM_VSCROLL,
    00561     WM_MOUSEWHEEL,
    00562     0
    00563 };
    00564
    00565 CONST WORD gawImeWndProc[] = {
    00566     WM_ERASEBKGND,
    00567     WM_PAINT,
    00568     WM_DESTROY,
    00569     WM_NCDESTROY,
    00570     WM_FINALDESTROY,
    00571     WM_CREATE,
    00572     WM_IME_SYSTEM,
    00573     WM_IME_SELECT,
    00574     WM_IME_CONTROL,
    00575     WM_IME_SETCONTEXT,
    00576     WM_IME_NOTIFY,
    00577     WM_IME_COMPOSITION,
    00578     WM_IME_STARTCOMPOSITION,
    00579     WM_IME_ENDCOMPOSITION,
    00580     WM_IME_REQUEST,
    00581     WM_COPYDATA,
    00582     0
    00583 };
    00584
    00585 /*
    00586  * This array is for all the messages that need to be passed straight
    00587  * across to the server for handling.
    00588  */
    00589 CONST WORD gawDefWindowMsgs[] = {
    00590     WM_GETHOTKEY,
    00591     WM_SETHOTKEY,
    00592     WM_SETREDRAW,
    00593     WM_SETTEXT,
    00594     WM_PAINT,
    00595     WM_CLOSE,
    00596     WM_ERASEBKGND,
    00597     WM_CANCELMODE,
    00598     WM_SETCURSOR,
    00599     WM_PAINTICON,
    00600     WM_ICONERASEBKGND,
    00601     WM_DRAWITEM,
    00602     WM_KEYF1,
    00603     WM_ISACTIVEICON,
    00604     WM_NCCREATE,
    00605     WM_SETICON,
    00606     WM_NCCALCSIZE,
    00607     WM_NCPAINT,
    00608     WM_NCACTIVATE,
    00609     WM_NCMOUSEMOVE,
    00610     WM_NCRBUTTONUP,
    00611     WM_NCRBUTTONDOWN,
    00612     WM_NCLBUTTONDOWN,
    00613     WM_NCLBUTTONUP,
    00614     WM_NCLBUTTONDBLCLK,
    00615     WM_KEYUP,
    00616     WM_SYSKEYUP,
    00617     WM_SYSCHAR,
    00618     WM_SYSCOMMAND,
    00619     WM_QUERYDROPOBJECT,
    00620     WM_CLIENTSHUTDOWN,
    00621     WM_SYNCPAINT,
    00622     WM_PRINT,
    00623     WM_GETICON,
    00624     WM_CONTEXTMENU,
    00625     WM_SYSMENU,
    00626     WM_INPUTLANGCHANGEREQUEST,
    00627     WM_INPUTLANGCHANGE,
    00628     WM_UPDATEUISTATE,
    00629     0
    00630 };
    00631
    00632 /*
    00633  * This array is for all messages that can be handled with some special
    00634  * code by the client.  DefWindowProcWorker returns 0 for all messages
    00635  * that aren't in this array or the one above.
    00636  */
    00637 CONST WORD gawDefWindowSpecMsgs[] = {
    00638     WM_ACTIVATE,
    00639     WM_GETTEXT,
    00640     WM_GETTEXTLENGTH,
    00641     WM_RBUTTONUP,
    00642     WM_QUERYENDSESSION,
    00643     WM_QUERYOPEN,
    00644     WM_SHOWWINDOW,
    00645     WM_MOUSEACTIVATE,
    00646     WM_HELP,
    00647     WM_VKEYTOITEM,
    00648     WM_CHARTOITEM,
    00649     WM_KEYDOWN,
    00650     WM_SYSKEYDOWN,
    00651     WM_DROPOBJECT,
    00652     WM_WINDOWPOSCHANGING,
    00653     WM_WINDOWPOSCHANGED,
    00654     WM_KLUDGEMINRECT,
    00655     WM_CTLCOLOR,
    00656     WM_CTLCOLORMSGBOX,
    00657     WM_CTLCOLOREDIT,
    00658     WM_CTLCOLORLISTBOX,
    00659     WM_CTLCOLORBTN,
    00660     WM_CTLCOLORDLG,
    00661     WM_CTLCOLORSCROLLBAR,
    00662     WM_NCHITTEST,
    00663     WM_NCXBUTTONUP,
    00664     WM_CTLCOLORSTATIC,
    00665     WM_NOTIFYFORMAT,
    00666     WM_DEVICECHANGE,
    00667     WM_POWERBROADCAST,
    00668     WM_MOUSEWHEEL,
    00669     WM_XBUTTONUP,
    00670     WM_IME_KEYDOWN,
    00671     WM_IME_KEYUP,
    00672     WM_IME_CHAR,
    00673     WM_IME_COMPOSITION,
    00674     WM_IME_STARTCOMPOSITION,
    00675     WM_IME_ENDCOMPOSITION,
    00676     WM_IME_COMPOSITIONFULL,
    00677     WM_IME_SETCONTEXT,
    00678     WM_IME_CONTROL,
    00679     WM_IME_NOTIFY,
    00680     WM_IME_SELECT,
    00681     WM_IME_SYSTEM,
    00682     WM_LPKDRAWSWITCHWND,
    00683     WM_QUERYDRAGICON,
    00684     WM_CHANGEUISTATE,
    00685     WM_QUERYUISTATE,
    00686     WM_APPCOMMAND,
    00687     0
    00688 };
    00689
    00690 static CONST LPCWSTR lpszOLEFormats[] = {
    00691     L"ObjectLink",
    00692     L"OwnerLink",
    00693     L"Native",
    00694     L"Binary",
    00695     L"FileName",
    00696     L"FileNameW",
    00697     L"NetworkName",
    00698     L"DataObject",
    00699     L"Embedded Object",
    00700     L"Embed Source",
    00701     L"Custom Link Source",
    00702     L"Link Source",
    00703     L"Object Descriptor",
    00704     L"Link Source Descriptor",
    00705     L"OleDraw",
    00706     L"PBrush",
    00707     L"MSDraw",
    00708     L"Ole Private Data",
    00709     L"Screen Picture",
    00710     L"OleClipboardPersistOnFlush",
    00711     L"MoreOlePrivateData"
    00712 };
    00713
    00714 static CONST LPCWSTR lpszControls[] = {
    00715     L"Button",
    00716     L"Edit",
    00717     L"Static",
    00718     L"ListBox",
    00719     L"ScrollBar",
    00720     L"ComboBox",
    00721     L"MDIClient",
    00722     L"ComboLBox",
    00723     L"DDEMLEvent",
    00724     L"DDEMLMom",
    00725     L"DMGClass",
    00726     L"DDEMLAnsiClient",
    00727     L"DDEMLUnicodeClient",
    00728     L"DDEMLAnsiServer",
    00729     L"DDEMLUnicodeServer",
    00730     L"IME",
    00731 };
    00732
    00733
    00734 #ifdef ALLOC_DATA_PRAGMA
    00735 #pragma data_seg()
    00736 #endif
    00737
    00738 /***************************************************************************\
    00739 * DispatchServerMessage
    00740 *
    00741 *
    00742 * 19-Aug-1992 MikeKe    Created
    00743 \***************************************************************************/
    00744
    00745 #define WRAPPFN(pfn, type)                                   \
    00746 LRESULT xxxWrap ## pfn(                                      \
    00747     PWND  pwnd,                                              \
    00748     UINT  message,                                           \
    00749     WPARAM wParam,                                           \
    00750     LPARAM lParam,                                           \
    00751     ULONG_PTR xParam)                                         \
    00752 {                                                            \
    00753     DBG_UNREFERENCED_PARAMETER(xParam);                      \
    00754                                                              \
    00755     return xxx ## pfn((type)pwnd, message, wParam, lParam);  \
    00756 }
    00757
    00758 WRAPPFN(SBWndProc, PSBWND)
    00759 WRAPPFN(MenuWindowProc, PWND)
    00760 WRAPPFN(DesktopWndProc, PWND);
    00761 WRAPPFN(DefWindowProc, PWND)
    00762
    00763 LRESULT xxxWrapSendMessage(
    00764     PWND  pwnd,
    00765     UINT  message,
    00766     WPARAM wParam,
    00767     LPARAM lParam,
    00768     ULONG_PTR xParam)
    00769 {
    00770     DBG_UNREFERENCED_PARAMETER(xParam);
    00771
    00772     return xxxSendMessageTimeout(pwnd,
    00773                                  message,
    00774                                  wParam,
    00775                                  lParam,
    00776                                  SMTO_NORMAL,
    00777                                  0,
    00778                                  NULL);
    00779 }
    00780
    00781 LRESULT xxxWrapSendMessageBSM(
    00782     PWND  pwnd,
    00783     UINT  message,
    00784     WPARAM wParam,
    00785     LPARAM lParam,
    00786     ULONG_PTR xParam)
    00787 {
    00788     BROADCASTSYSTEMMSGPARAMS bsmParams;
    00789
    00790     try {
    00791         bsmParams = ProbeAndReadBroadcastSystemMsgParams((LPBROADCASTSYSTEMMSGPARAMS)xParam);
    00792     } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    00793         return 0;
    00794     }
    00795
    00796     /*
    00797      * If this broadcast is going to all desktops, make sure the thread has
    00798      * sufficient privileges. Do the check here, so we don't effect kernel
    00799      * generated broadcasts (i.e power messages).
    00800      */
    00801     if (bsmParams.dwRecipients & (BSM_ALLDESKTOPS)) {
    00802         if (!IsPrivileged(&psTcb)) {
    00803             bsmParams.dwRecipients &= ~(BSM_ALLDESKTOPS);
    00804         }
    00805     }
    00806
    00807     return xxxSendMessageBSM(pwnd,
    00808                              message,
    00809                              wParam,
    00810                              lParam,
    00811                              &bsmParams);
    00812 }
    00813
    00814 /***************************************************************************\
    00815 * xxxUnusedFunctionId
    00816 *
    00817 * This function is catches attempts to access invalid entries in the server
    00818 * side function dispatch table.
    00819 *
    00820 \***************************************************************************/
    00821
    00822 LRESULT xxxUnusedFunctionId(
    00823     PWND  pwnd,
    00824     UINT  message,
    00825     WPARAM wParam,
    00826     LPARAM lParam,
    00827     ULONG_PTR xParam)
    00828 {
    00829     DBG_UNREFERENCED_PARAMETER(pwnd);
    00830     DBG_UNREFERENCED_PARAMETER(message);
    00831     DBG_UNREFERENCED_PARAMETER(wParam);
    00832     DBG_UNREFERENCED_PARAMETER(lParam);
    00833     DBG_UNREFERENCED_PARAMETER(xParam);
    00834
    00835     UserAssert(FALSE);
    00836     return 0;
    00837 }
    00838
    00839 /***************************************************************************\
    00840 * xxxWrapCallWindowProc
    00841 *
    00842 * Warning should only be called with valid CallProc Handles or the
    00843 * EditWndProc special handlers.
    00844 *
    00845 *
    00846 * 21-Apr-1993 JohnC     Created
    00847 \***************************************************************************/
    00848
    00849 LRESULT xxxWrapCallWindowProc(
    00850     PWND  pwnd,
    00851     UINT  message,
    00852     WPARAM wParam,
    00853     LPARAM lParam,
    00854     ULONG_PTR xParam)
    00855 {
    00856     PCALLPROCDATA pCPD;
    00857     LRESULT       lRet = 0;
    00858
    00859     if (pCPD = HMValidateHandleNoRip((PVOID)xParam, TYPE_CALLPROC)) {
    00860
    00861         lRet = ScSendMessage(pwnd,
    00862                               message,
    00863                               wParam,
    00864                               lParam,
    00865                               pCPD->pfnClientPrevious,
    00866                               gpsi->apfnClientW.pfnDispatchMessage,
    00867                               (pCPD->wType & CPD_UNICODE_TO_ANSI) ?
    00868                                       SCMS_FLAGS_ANSI : 0);
    00869
    00870     } else {
    00871
    00872         /*
    00873          * If it is not a real call proc handle it must be a special
    00874          * handler for editwndproc or regular EditWndProc
    00875          */
    00876         lRet = ScSendMessage(pwnd,
    00877                               message,
    00878                               wParam,
    00879                               lParam,
    00880                               xParam,
    00881                               gpsi->apfnClientA.pfnDispatchMessage,
    00882                               (xParam == (ULONG_PTR)gpsi->apfnClientA.pfnEditWndProc) ?
    00883                                       SCMS_FLAGS_ANSI : 0);
    00884     }
    00885
    00886     return lRet;
    00887 }
    00888
    00889 #if DBG
    00890 VOID VerifySyncOnlyMessages(VOID)
    00891 {
    00892     int i;
    00893
    00894     TRACE_INIT(("UserInit: Verify Sync Only Messages\n"));
    00895
    00896     /*
    00897      * There are a couple of thunks that just pass parameters.  There are other
    00898      * thunks besides SfnDWORD that do a straight pass through because they
    00899      * do other processing beside the wparam and lparam
    00900      */
    00901
    00902     /*
    00903      * Allow posting of LB_DIR and CB_DIR because DlgDirList allows a DDL_POSTMSGS
    00904      * flag that makes the API post the messages.  This should be OK as long as we
    00905      * don't handle these messages in the kernel.  NT 3.51 allowed posting these.
    00906      */
    00907     for (i=0; i<WM_USER; i++) {
    00908         if (    i != LB_DIR
    00909                 && i != CB_DIR
    00910                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnDWORD)
    00911                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMCHAR)
    00912                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMDBCSCHAR)
    00913                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnSENTDDEMSG)
    00914                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnPOWERBROADCAST)
    00915                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnLOGONNOTIFY)
    00916                 && (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINDESTROYCLIPBRD)) {
    00917             if (!(TESTSYNCONLYMESSAGE(i,0x8000)))
    00918                 RIPMSG1(RIP_ERROR, "InitSyncOnly: is this message sync-only 0x%lX", i);
    00919         } else {
    00920             if (TESTSYNCONLYMESSAGE(i,0))
    00921                 RIPMSG1(RIP_VERBOSE, "InitSyncOnly: is this message not sync-only 0x%lX", i);
    00922         }
    00923
    00924     }
    00925 }
    00926 #endif // DBG
    00927
    00928 /***************************************************************************\
    00929 * InitWindowMsgTables
    00930 *
    00931 * This function generates a bit-array lookup table from a list of messages.
    00932 * The lookup table is used to determine whether the message needs to be
    00933 * passed over to the server for handling or whether it can be handled
    00934 * directly on the client.
    00935 *
    00936 * LATER: Some memory (a couple hundred bytes per process) could be saved
    00937 *        by putting this in the shared read-only heap.
    00938 *
    00939 *
    00940 * 27-Mar-1992 DarrinM   Created.
    00941 * 06-Dec-1993 MikeKe    Added support for all of our window procs.
    00942 \***************************************************************************/
    00943
    00944 VOID InitWindowMsgTable(
    00945     PBYTE      *ppbyte,
    00946     PUINT      pmax,
    00947     CONST WORD *pw)
    00948 {
    00949     UINT i;
    00950     WORD msg;
    00951     UINT cbTable;
    00952
    00953     *pmax = 0;
    00954     for (i = 0; (msg = pw[i]) != 0; i++) {
    00955         if (msg > *pmax)
    00956             *pmax = msg;
    00957     }
    00958
    00959     cbTable = *pmax / 8 + 1;
    00960     *ppbyte = SharedAlloc(cbTable);
    00961
    00962     for (i = 0; (msg = pw[i]) != 0; i++)
    00963         (*ppbyte)[msg / 8] |= (BYTE)(1 << (msg & 7));
    00964 }
    00965
    00966 /***************************************************************************\
    00967 * InitFunctionTables
    00968 *
    00969 * Initialize the procedures and function tables.
    00970 *
    00971 *
    00972 * 25-Aug-1995 ChrisWil  Created comment block.
    00973 \***************************************************************************/
    00974
    00975 VOID InitFunctionTables(VOID)
    00976 {
    00977     UINT i;
    00978
    00979     TRACE_INIT(("UserInit: Initialize Function Tables\n"));
    00980
    00981     UserAssert(sizeof(CLIENTINFO) <= sizeof(NtCurrentTeb()->Win32ClientInfo));
    00982
    00983     /*
    00984      * This table is used to convert from server procs to client procs.
    00985      */
    00986     STOCID(FNID_SCROLLBAR)              = (WNDPROC_PWND)xxxSBWndProc;
    00987     STOCID(FNID_ICONTITLE)              = xxxDefWindowProc;
    00988     STOCID(FNID_MENU)                   = xxxMenuWindowProc;
    00989     STOCID(FNID_DESKTOP)                = xxxDesktopWndProc;
    00990     STOCID(FNID_DEFWINDOWPROC)          = xxxDefWindowProc;
    00991
    00992     /*
    00993      * This table is used to determine the number minimum number
    00994      * of reserved windows words required for the server proc.
    00995      */
    00996     CBFNID(FNID_SCROLLBAR)              = sizeof(SBWND);
    00997     CBFNID(FNID_ICONTITLE)              = sizeof(WND);
    00998     CBFNID(FNID_MENU)                   = sizeof(MENUWND);
    00999
    01000     /*
    01001      * Initialize this data structure (api function table).
    01002      */
    01003     for (i = 0; i < FNID_ARRAY_SIZE; i++) {
    01004         FNID((i + FNID_START)) = xxxUnusedFunctionId;
    01005     }
    01006     FNID(FNID_SCROLLBAR)                = xxxWrapSBWndProc;
    01007     FNID(FNID_ICONTITLE)                = xxxWrapDefWindowProc;
    01008     FNID(FNID_MENU)                     = xxxWrapMenuWindowProc;
    01009     FNID(FNID_DESKTOP)                  = xxxWrapDesktopWndProc;
    01010     FNID(FNID_DEFWINDOWPROC)            = xxxWrapDefWindowProc;
    01011     FNID(FNID_SENDMESSAGE)              = xxxWrapSendMessage;
    01012     FNID(FNID_HKINLPCWPEXSTRUCT)        = fnHkINLPCWPEXSTRUCT;
    01013     FNID(FNID_HKINLPCWPRETEXSTRUCT)     = fnHkINLPCWPRETEXSTRUCT;
    01014     FNID(FNID_SENDMESSAGEFF)            = xxxSendMessageFF;
    01015     FNID(FNID_SENDMESSAGEEX)            = xxxSendMessageEx;
    01016     FNID(FNID_CALLWINDOWPROC)           = xxxWrapCallWindowProc;
    01017     FNID(FNID_SENDMESSAGEBSM)           = xxxWrapSendMessageBSM;
    01018
    01019 #if DBG
    01020     {
    01021         PULONG_PTR pdw;
    01022
    01023         /*
    01024          * Make sure that everyone got initialized.
    01025          */
    01026         for (pdw=(PULONG_PTR)&STOCID(FNID_START);
    01027                 (ULONG_PTR)pdw<(ULONG_PTR)(&STOCID(FNID_WNDPROCEND)); pdw++) {
    01028             UserAssert(*pdw);
    01029         }
    01030
    01031         for (pdw=(PULONG_PTR)&FNID(FNID_START);
    01032                 (ULONG_PTR)pdw<(ULONG_PTR)(&FNID(FNID_WNDPROCEND)); pdw++) {
    01033             UserAssert(*pdw);
    01034         }
    01035     }
    01036 #endif
    01037
    01038 }
    01039
    01040 /***************************************************************************\
    01041 * InitMessageTables
    01042 *
    01043 * Initialize the message tables.
    01044 *
    01045 *
    01046 * 25-Aug-1995 ChrisWil      Created.
    01047 \***************************************************************************/
    01048
    01049 VOID InitMessageTables(VOID)
    01050 {
    01051     TRACE_INIT(("UserInit: Initialize Message Tables\n"));
    01052
    01053 #define INITMSGTABLE(member, procname)                \
    01054     InitWindowMsgTable(&(gSharedInfo.member.abMsgs),  \
    01055                        &(gSharedInfo.member.maxMsgs), \
    01056                        gaw ## procname);
    01057
    01058     INITMSGTABLE(DefWindowMsgs, DefWindowMsgs);
    01059     INITMSGTABLE(DefWindowSpecMsgs, DefWindowSpecMsgs);
    01060
    01061     INITMSGTABLE(awmControl[FNID_DIALOG       - FNID_START], DefDlgProc);
    01062     INITMSGTABLE(awmControl[FNID_SCROLLBAR    - FNID_START], ScrollBarWndProc);
    01063     INITMSGTABLE(awmControl[FNID_MENU         - FNID_START], MenuWndProc);
    01064     INITMSGTABLE(awmControl[FNID_DESKTOP      - FNID_START], DesktopWndProc);
    01065     INITMSGTABLE(awmControl[FNID_STATIC       - FNID_START], StaticWndProc);
    01066     INITMSGTABLE(awmControl[FNID_BUTTON       - FNID_START], ButtonWndProc);
    01067     INITMSGTABLE(awmControl[FNID_LISTBOX      - FNID_START], ListboxWndProc);
    01068     INITMSGTABLE(awmControl[FNID_COMBOBOX     - FNID_START], ComboWndProc);
    01069     INITMSGTABLE(awmControl[FNID_COMBOLISTBOX - FNID_START], ListboxWndProc);
    01070     INITMSGTABLE(awmControl[FNID_EDIT         - FNID_START], EditWndProc);
    01071     INITMSGTABLE(awmControl[FNID_IME          - FNID_START], ImeWndProc);
    01072 }
    01073
    01074 /***************************************************************************\
    01075 * InitOLEFormats
    01076 *
    01077 * OLE performance hack.  OLE was previously having to call the server
    01078 * 15 times for clipboard formats and another 15 LPC calls for the global
    01079 * atoms.  Now we preregister them.  We also assert they are in order so
    01080 * OLE only has to query the first to know them all.  We call AddAtom
    01081 * directly instead of RegisterClipboardFormat.
    01082 *
    01083 *
    01084 * 25-Aug-1995 ChrisWil      Created.
    01085 \***************************************************************************/
    01086
    01087 BOOL InitOLEFormats(VOID)
    01088 {
    01089     UINT idx;
    01090     ATOM a1;
    01091     ATOM a2;
    01092     BOOL fSuccess = TRUE;
    01093
    01094     TRACE_INIT(("UserInit: Initialize OLE Formats\n"));
    01095
    01096     a1 = UserAddAtom(lpszOLEFormats[0], TRUE);
    01097
    01098     for (idx = 1; idx < ARRAY_SIZE(lpszOLEFormats); idx++) {
    01099         a2 = UserAddAtom(lpszOLEFormats[idx], TRUE);
    01100         fSuccess &= !!a2;
    01101
    01102         UserAssert(((a1 + 1) == a2) && (a1 = a2));
    01103     }
    01104
    01105     if (!fSuccess) {
    01106         RIPMSG0(RIP_ERROR, "InitOLEFormats: at least one atom not registered");
    01107     }
    01108
    01109     return fSuccess;
    01110 }
    01111
    01112 /***************************************************************************\
    01113 * InitGlobalRIPFlags (debug only)
    01114 *
    01115 * This initializes the global RIP flags from the registry.
    01116 *
    01117 *
    01118 * 25-Aug-1995 ChrisWil      Created.
    01119 \***************************************************************************/
    01120 #if DBG
    01121 VOID
    01122 InitGlobalRIPFlags()
    01123 {
    01124
    01125     UINT  idx;
    01126     UINT  nCount;
    01127     DWORD dwFlag;
    01128
    01129     static CONST struct {
    01130         LPWSTR lpszKey;
    01131         DWORD  dwDef;
    01132         DWORD  dwFlag;
    01133     } aRIPFlags[] = {
    01134         {L"fPromptOnError"  , 1, RIPF_PROMPTONERROR  },
    01135         {L"fPromptOnWarning", 0, RIPF_PROMPTONWARNING},
    01136         {L"fPromptOnVerbose", 0, RIPF_PROMPTONVERBOSE},
    01137         {L"fPrintError"     , 1, RIPF_PRINTONERROR   },
    01138         {L"fPrintWarning"   , 1, RIPF_PRINTONWARNING },
    01139         {L"fPrintVerbose"   , 0, RIPF_PRINTONVERBOSE },
    01140         {L"fPrintFileLine"  , 0, RIPF_PRINTFILELINE  },
    01141     };
    01142
    01143     TRACE_INIT(("UserInit: Initialize Global RIP Flags\n"));
    01144
    01145     nCount = sizeof(aRIPFlags) / sizeof(aRIPFlags[0]);
    01146
    01147     /*
    01148      * Turn off the rip-on-warning bit.  This is necessary to prevent
    01149      * the FastGetProfileDwordW() routine from breaking into the
    01150      * debugger if an entry can't be found.  Since we provide default
    01151      * values, there's no sense to break.
    01152      */
    01153     UserAssert(gpsi != NULL);
    01154
    01155     CLEAR_FLAG(gpsi->wRIPFlags, RIPF_PROMPTONWARNING);
    01156     CLEAR_FLAG(gpsi->wRIPFlags, RIPF_PRINTONWARNING);
    01157
    01158     for (idx=0; idx < nCount; idx++) {
    01159
    01160         dwFlag = FastGetProfileDwordW(NULL, PMAP_WINDOWSM,
    01161                                       aRIPFlags[idx].lpszKey,
    01162                                       aRIPFlags[idx].dwDef
    01163                                       );
    01164
    01165         SET_OR_CLEAR_FLAG(gpsi->wRIPFlags, aRIPFlags[idx].dwFlag, dwFlag);
    01166     }
    01167
    01168 }
    01169
    01170 #else // DBG
    01171
    01172 #define InitGlobalRIPFlags()
    01173
    01174 #endif // DBG
    01175
    01176
    01177 /***************************************************************************\
    01178 * _GetTextMetricsW
    01179 * _TextOutW
    01180 *
    01181 * Server shared function thunks.
    01182 *
    01183 * History:
    01184 * 10-Nov-1993 MikeKe    Created
    01185 \***************************************************************************/
    01186
    01187 BOOL _GetTextMetricsW(
    01188     HDC           hdc,
    01189     LPTEXTMETRICW ptm)
    01190 {
    01191     TMW_INTERNAL tmi;
    01192     BOOL         fret;
    01193
    01194     fret = GreGetTextMetricsW(hdc, &tmi);
    01195
    01196     *ptm = tmi.tmw;
    01197
    01198     return fret;
    01199 }
    01200
    01201 BOOL _TextOutW(
    01202     HDC     hdc,
    01203     int     x,
    01204     int     y,
    01205     LPCWSTR lp,
    01206     UINT    cc)
    01207 {
    01208     return GreExtTextOutW(hdc, x, y, 0, NULL, (LPWSTR)lp, cc, NULL);
    01209 }
    01210
    01211
    01212
    01213 #ifndef PAGE_SIZE
    01214 #define PAGE_SIZE 0x1000
    01215 #endif
    01216
    01217 #define ROUND_UP_TO_PAGES(SIZE) \
    01218         (((ULONG)(SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
    01219
    01220 /***************************************************************************\
    01221 * InitCreateSharedSection
    01222 *
    01223 * This creates the shared section.
    01224 *
    01225 *
    01226 * 25-Aug-1995 ChrisWil      Created comment block.
    01227 \***************************************************************************/
    01228
    01229 NTSTATUS InitCreateSharedSection(VOID)
    01230 {
    01231     ULONG             ulHeapSize;
    01232     ULONG             ulHandleTableSize;
    01233     NTSTATUS          Status;
    01234     LARGE_INTEGER     SectionSize;
    01235     SIZE_T            ViewSize;
    01236     PVOID             pHeapBase;
    01237
    01238     TRACE_INIT(("UserInit: Create Shared Memory Section\n"));
    01239
    01240     UserAssert(ghSectionShared == NULL);
    01241
    01242     ulHeapSize        = ROUND_UP_TO_PAGES(USRINIT_SHAREDSECT_SIZE * 1024);
    01243     ulHandleTableSize = ROUND_UP_TO_PAGES(0x10000 * sizeof(HANDLEENTRY));
    01244
    01245     TRACE_INIT(("UserInit: Share: TableSize = %X; HeapSize = %X\n",
    01246             ulHandleTableSize, ulHeapSize));
    01247
    01248     SectionSize.LowPart  = ulHeapSize + ulHandleTableSize;
    01249     SectionSize.HighPart = 0;
    01250
    01251     Status = Win32CreateSection(&ghSectionShared,
    01252                                 SECTION_ALL_ACCESS,
    01253                                 (POBJECT_ATTRIBUTES)NULL,
    01254                                 &SectionSize,
    01255                                 PAGE_EXECUTE_READWRITE,
    01256                                 SEC_RESERVE,
    01257                                 (HANDLE)NULL,
    01258                                 NULL,
    01259                                 TAG_SECTION_SHARED);
    01260
    01261     if (!NT_SUCCESS(Status)) {
    01262         RIPMSG1(RIP_WARNING,
    01263                 "MmCreateSection failed in InitCreateSharedSection with Status %x",
    01264                 Status);
    01265         return Status;
    01266     }
    01267
    01268     ViewSize = 0;
    01269     gpvSharedBase = NULL;
    01270
    01271     Status = Win32MapViewInSessionSpace(ghSectionShared, &gpvSharedBase, &ViewSize);
    01272
    01273     if (!NT_SUCCESS(Status)) {
    01274         RIPMSG1(RIP_WARNING, "Win32MapViewInSessionSpace failed with Status %x",
    01275                 Status);
    01276         Win32DestroySection(ghSectionShared);
    01277         ghSectionShared = NULL;
    01278         return Status;
    01279     }
    01280
    01281     pHeapBase = ((PBYTE)gpvSharedBase + ulHandleTableSize);
    01282
    01283     TRACE_INIT(("UserInit: Share: BaseAddr = %X; Heap = %X, ViewSize = %X\n",
    01284             gpvSharedBase, pHeapBase, ViewSize));
    01285
    01286     /*
    01287      * Create shared heap.
    01288      */
    01289     if ((gpvSharedAlloc = UserCreateHeap(
    01290             ghSectionShared,
    01291             ulHandleTableSize,
    01292             pHeapBase,
    01293             ulHeapSize,
    01294             UserCommitSharedMemory)) == NULL) {
    01295
    01296         RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "Can't create shared memory heap.");
    01297
    01298         Win32UnmapViewInSessionSpace(gpvSharedBase);
    01299
    01300         Win32DestroySection(ghSectionShared);
    01301         gpvSharedAlloc = NULL;
    01302         gpvSharedBase = NULL;
    01303         ghSectionShared = NULL;
    01304
    01305         return STATUS_NO_MEMORY;
    01306     }
    01307
    01308     UserAssert(Win32HeapGetHandle(gpvSharedAlloc) == pHeapBase);
    01309
    01310     return STATUS_SUCCESS;
    01311 }
    01312
    01313 /**************************************************************************\
    01314 * InitCreateUserCrit
    01315 *
    01316 * Create and initialize the user critical sections needed throughout the
    01317 * system.
    01318 *
    01319 * 23-Jan-1996 ChrisWil      Created.
    01320 \**************************************************************************/
    01321
    01322 BOOL InitCreateUserCrit(VOID)
    01323 {
    01324     TRACE_INIT(("Win32UserInit: InitCreateUserCrit()\n"));
    01325
    01326     /*
    01327      * Initialize a critical section structure that will be used to protect
    01328      * all of the User Server's critical sections (except a few special
    01329      * cases like the RIT -- see below).
    01330      */
    01331     gpresUser = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
    01332                                       sizeof(ERESOURCE),
    01333                                       TAG_ERESOURCE);
    01334     if (!gpresUser) {
    01335         goto InitCreateUserCritExit;
    01336     }
    01337     if (!NT_SUCCESS(ExInitializeResourceLite(gpresUser))) {
    01338         goto InitCreateUserCritExit;
    01339     }
    01340
    01341     /*
    01342      * Initialize a critical section to be used in [Un]QueueMouseEvent
    01343      * to protect the queue of mouse input events that the desktop thread
    01344      * uses to pass input on to the RIT, after having moved the cursor
    01345      * without obtaining gpresUser itself.
    01346      */
    01347     gpresMouseEventQueue = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
    01348                                                  sizeof(ERESOURCE),
    01349                                                  TAG_ERESOURCE);
    01350     if (!gpresMouseEventQueue) {
    01351         goto InitCreateUserCritExit;
    01352     }
    01353     if (!NT_SUCCESS(ExInitializeResourceLite(gpresMouseEventQueue))) {
    01354         goto InitCreateUserCritExit;
    01355     }
    01356
    01357     /*
    01358      * Initialize a critical section to protect the list of DEVICEINFO structs
    01359      * kept under gpDeviceInfoList.  This is used by the RIT when reading kbd
    01360      * input, the desktop thread when reading mouse input, and the PnP callback
    01361      * routines DeviceClassNotify() and DeviceNotify() when devices come and go.
    01362      */
    01363     gpresDeviceInfoList = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
    01364                                             sizeof(ERESOURCE),
    01365                                             TAG_ERESOURCE);
    01366     if (!gpresDeviceInfoList) {
    01367         goto InitCreateUserCritExit;
    01368     }
    01369     if (!NT_SUCCESS(ExInitializeResourceLite(gpresDeviceInfoList))) {
    01370         goto InitCreateUserCritExit;
    01371     }
    01372
    01373     /*
    01374      * Create the handle flag mutex. We'll need this once we start creating
    01375      * windowstations and desktops.
    01376      */
    01377     gpHandleFlagsMutex = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
    01378                                                sizeof(FAST_MUTEX),
    01379                                                TAG_SYSTEM);
    01380     if (gpHandleFlagsMutex == NULL) {
    01381         goto InitCreateUserCritExit;
    01382     }
    01383     ExInitializeFastMutex(gpHandleFlagsMutex);
    01384
    01385     TRACE_INIT(("Win32UserInit: gpHandleFlagsMutex = 0x%p\n", gpHandleFlagsMutex));
    01386     TRACE_INIT(("Win32UserInit: gpresDeviceInfoList = 0x%X\n", gpresDeviceInfoList));
    01387     TRACE_INIT(("Win32UserInit: gpresMouseEventQueue = 0x%X\n", gpresMouseEventQueue));
    01388     TRACE_INIT(("Win32UserInit: gpresUser  = 0x%X\n", gpresUser));
    01389
    01390     TRACE_INIT(("Win32UserInit: exit InitCreateUserCrit()\n"));
    01391     return TRUE;
    01392
    01393 InitCreateUserCritExit:
    01394     RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_ERROR,
    01395             "Win32UserInit: InitCreateUserCrit failed");
    01396
    01397     if (gpresUser) {
    01398         ExFreePool(gpresUser);
    01399     }
    01400     if (gpresMouseEventQueue) {
    01401         ExFreePool(gpresMouseEventQueue);
    01402     }
    01403     if (gpresDeviceInfoList) {
    01404         ExFreePool(gpresDeviceInfoList);
    01405     }
    01406     return FALSE;
    01407 }
    01408
    01409 /**************************************************************************\
    01410 * InitCreateObjectDirectory
    01411 *
    01412 * Create and initialize the user critical sections needed throughout the
    01413 * system.
    01414 *
    01415 * 23-Jan-1996 ChrisWil      Created.
    01416 \**************************************************************************/
    01417 NTSTATUS InitCreateObjectDirectory(VOID)
    01418 {
    01419     HANDLE            hDir;
    01420     NTSTATUS          Status;
    01421     OBJECT_ATTRIBUTES ObjectAttributes;
    01422     UNICODE_STRING    UnicodeString;
    01423     ULONG             attributes = OBJ_CASE_INSENSITIVE | OBJ_PERMANENT;
    01424
    01425     TRACE_INIT(("UserInit: Create User Object-Directory\n"));
    01426
    01427     RtlInitUnicodeString(&UnicodeString, szWindowStationDirectory);
    01428
    01429     if (gbRemoteSession) {
    01430        /*
    01431         * Remote sessions don't use this flag
    01432         */
    01433        attributes &= ~OBJ_PERMANENT;
    01434     }
    01435
    01436     InitializeObjectAttributes(&ObjectAttributes,
    01437                                &UnicodeString,
    01438                                attributes,
    01439                                NULL,
    01440                                gpsdInitWinSta);
    01441
    01442     Status = ZwCreateDirectoryObject(&hDir,
    01443                                      DIRECTORY_CREATE_OBJECT,
    01444                                      &ObjectAttributes);
    01445
    01446     UserFreePool(gpsdInitWinSta);
    01447
    01448     /*
    01449      * Do not close this handle for remote session because
    01450      * if we do close it then the directory will go away and
    01451      * we don't want that to happen. When CSRSS will go away
    01452      * this handle will be freed also.
    01453      */
    01454     if (!gbRemoteSession)
    01455         ZwClose(hDir);
    01456
    01457     gpsdInitWinSta = NULL;
    01458
    01459     return Status;
    01460 }
    01461
    01462 /**************************************************************************\
    01463 * InitCreateUserSubsystem
    01464 *
    01465 * Create and initialize the user subsystem stuff.
    01466 * system.
    01467 *
    01468 * 23-Jan-1996 ChrisWil      Created.
    01469 \**************************************************************************/
    01470 BOOL
    01471 InitCreateUserSubsystem()
    01472 {
    01473     LPWSTR         lpszSubSystem;
    01474     LPWSTR         lpszT;
    01475     UNICODE_STRING strSize;
    01476
    01477     TRACE_INIT(("UserInit: Create User SubSystem\n"));
    01478
    01479     /*
    01480      * Initialize the subsystem section.  This identifies the default
    01481      * user-heap size.
    01482      */
    01483     lpszSubSystem = UserAllocPoolWithQuota(USRINIT_SHAREDSECT_BUFF_SIZE * sizeof(WCHAR),
    01484                                            TAG_SYSTEM);
    01485
    01486     if (lpszSubSystem == NULL) {
    01487         return FALSE;
    01488     }
    01489
    01490     if (FastGetProfileStringW(NULL, PMAP_SUBSYSTEMS,
    01491                               L"Windows",
    01492                               L"SharedSection=,3072",
    01493                               lpszSubSystem,
    01494                               USRINIT_SHAREDSECT_READ_SIZE
    01495                               ) == 0) {
    01496         RIPMSG0(RIP_WARNING,
    01497                 "UserInit: Windows subsystem definition not found");
    01498         UserFreePool(lpszSubSystem);
    01499         return FALSE;
    01500     }
    01501
    01502     /*
    01503      * Locate the SharedSection portion of the definition and extract
    01504      * the second value.
    01505      */
    01506     gdwDesktopSectionSize = USRINIT_WINDOWSECT_SIZE;
    01507     gdwNOIOSectionSize    = USRINIT_NOIOSECT_SIZE;
    01508
    01509     if (lpszT = wcsstr(lpszSubSystem, L"SharedSection")) {
    01510
    01511         *(lpszT + 32) = UNICODE_NULL;
    01512
    01513         if (lpszT = wcschr(lpszT, L',')) {
    01514
    01515             RtlInitUnicodeString(&strSize, ++lpszT);
    01516             RtlUnicodeStringToInteger(&strSize, 0, &gdwDesktopSectionSize);
    01517
    01518             /*
    01519              * Assert this logic doesn't need to change.
    01520              */
    01521             UserAssert(gdwDesktopSectionSize >= USRINIT_WINDOWSECT_SIZE);
    01522
    01523             gdwDesktopSectionSize = max(USRINIT_WINDOWSECT_SIZE, gdwDesktopSectionSize);
    01524             gdwNOIOSectionSize    = gdwDesktopSectionSize;
    01525
    01526             /*
    01527              * Now see if the optional non-interactive desktop
    01528              * heap size was specified.
    01529              */
    01530             if (lpszT = wcschr(lpszT, L',')) {
    01531
    01532                 RtlInitUnicodeString(&strSize, ++lpszT);
    01533                 RtlUnicodeStringToInteger(&strSize, 0, &gdwNOIOSectionSize);
    01534
    01535                 UserAssert(gdwNOIOSectionSize >= USRINIT_NOIOSECT_SIZE);
    01536                 gdwNOIOSectionSize = max(USRINIT_NOIOSECT_SIZE, gdwNOIOSectionSize);
    01537             }
    01538         }
    01539     }
    01540
    01541     UserFreePool(lpszSubSystem);
    01542
    01543     return TRUE;
    01544 }
    01545
    01546 extern UNICODE_STRING *gpastrSetupExe;     // These are used in
    01547 extern int giSetupExe;                     // SetAppImeCompatFlags in
    01548                                            // queue.c
    01549
    01550 WCHAR* glpSetupPrograms;
    01551
    01552 /******************************************************
    01553 *
    01554 * Create and initialize the arrary of setup app names.
    01555 * We inherited this hack From Chicago.  See queue.c for
    01556 * more details.
    01557 *******************************************************/
    01558
    01559 BOOL CreateSetupNameArray() {
    01560     DWORD  dwProgNames;
    01561     int    iSetupProgramCount = 0;
    01562     WCHAR* lpTemp;
    01563     int    ic, icnt, icMax;
    01564
    01565     dwProgNames = FastGetProfileValue(NULL, PMAP_SETUPPROGRAMNAMES,
    01566                         L"SetupProgramNames",NULL,NULL, 0);
    01567
    01568     /*
    01569      * This key is a multi-string, so is best to read as a value.
    01570      * First, get the length and create the buffer to hold all of
    01571      * the strings.
    01572      */
    01573     if (dwProgNames == 0) {
    01574         return FALSE;
    01575     }
    01576
    01577     glpSetupPrograms = UserAllocPoolWithQuota(dwProgNames,
    01578                                        TAG_SYSTEM);
    01579
    01580     if (glpSetupPrograms == NULL) {
    01581         RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
    01582         return FALSE;
    01583     }
    01584
    01585     FastGetProfileValue(NULL,
    01586                         PMAP_SETUPPROGRAMNAMES,
    01587                         L"SetupProgramNames",
    01588                         NULL,
    01589                         (PBYTE)glpSetupPrograms,
    01590                         dwProgNames);
    01591
    01592     lpTemp = glpSetupPrograms;
    01593     icMax = dwProgNames/2;
    01594     ic = 0; icnt=0;
    01595     /*
    01596      * Now count the strings.
    01597      */
    01598     while (ic < icMax) {
    01599         if (*(lpTemp+ic) == 0) {
    01600             ic++;
    01601             continue;
    01602         }
    01603         ic += wcslen(lpTemp+ic)+1;
    01604         icnt++;
    01605     }
    01606
    01607     /*
    01608      * gpastrSetupExe is a pointer to an array of UNICODE_STRING structures.
    01609      * Each structure is the name of one setup program.
    01610      */
    01611     giSetupExe = icnt;
    01612     gpastrSetupExe = UserAllocPoolWithQuota(giSetupExe * sizeof(UNICODE_STRING),
    01613                                        TAG_SYSTEM);
    01614
    01615     if (gpastrSetupExe == NULL) {
    01616         RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
    01617         giSetupExe = 0;
    01618         UserFreePool(glpSetupPrograms);
    01619         glpSetupPrograms = NULL;
    01620         return FALSE;
    01621     }
    01622
    01623     ic = 0; icnt=0;
    01624     while (ic < icMax) {
    01625         if (*(lpTemp+ic) == 0) {
    01626             ic++;
    01627             continue;
    01628         }
    01629         gpastrSetupExe[icnt].Buffer = lpTemp+ic;
    01630         gpastrSetupExe[icnt].Length = sizeof(WCHAR)*wcslen(lpTemp+ic);
    01631         gpastrSetupExe[icnt].MaximumLength = gpastrSetupExe[icnt].Length + sizeof(WCHAR);
    01632         ic += wcslen(lpTemp+ic)+1;
    01633         icnt++;
    01634
    01635     }
    01636
    01637     return TRUE;
    01638 }
    01639
    01640 #define CALC_DELTA(element)                   \
    01641         (PVOID)((PBYTE)pClientBase +          \
    01642         ((PBYTE)gSharedInfo.element -         \
    01643         (PBYTE)gpvSharedBase))
    01644
    01645 /***************************************************************************\
    01646 * InitMapSharedSection
    01647 *
    01648 * This maps the shared section.
    01649 *
    01650 *
    01651 * 25-Aug-1995 ChrisWil      Created comment block.
    01652 \***************************************************************************/
    01653
    01654 NTSTATUS InitMapSharedSection(
    01655     PEPROCESS    Process,
    01656     PUSERCONNECT pUserConnect)
    01657 {
    01658     int           i;
    01659     PVOID         pClientBase = NULL;
    01660     ULONG_PTR      ulSharedDelta;
    01661
    01662     TRACE_INIT(("UserInit: Map Shared Memory Section\n"));
    01663
    01664     UserAssert(ghSectionShared != NULL);
    01665
    01666     ValidateProcessSessionId(Process);
    01667
    01668     /*
    01669      * Check to see if we haven't already mapped the section
    01670      * This might happen for multiple LoadLibrary()/FreeLibrary calls
    01671      * in one process.  MCostea #56946
    01672      */
    01673     if (Process->Win32Process == NULL ||
    01674         ((PPROCESSINFO)Process->Win32Process)->pClientBase == NULL) {
    01675
    01676         SIZE_T        ViewSize;
    01677         LARGE_INTEGER liOffset;
    01678         NTSTATUS Status;
    01679
    01680         ViewSize = 0;
    01681         liOffset.QuadPart = 0;
    01682
    01683         Status = MmMapViewOfSection(ghSectionShared,
    01684                                 Process,
    01685                                 &pClientBase,
    01686                                 0,
    01687                                 0,
    01688                                 &liOffset,
    01689                                 &ViewSize,
    01690                                 ViewUnmap,
    01691                                 SEC_NO_CHANGE,
    01692                                 PAGE_EXECUTE_READ);
    01693         if (NT_SUCCESS(Status)) {
    01694             TRACE_INIT(("UserInit: Map: Client SharedInfo Base = %x\n", pClientBase));
    01695
    01696             UserAssert(gpvSharedBase > pClientBase);
    01697             if (Process->Win32Process != NULL) {
    01698                 ((PPROCESSINFO)Process->Win32Process)->pClientBase = pClientBase;
    01699             }
    01700         } else {
    01701             return Status;
    01702         }
    01703
    01704     } else {
    01705         pClientBase = ((PPROCESSINFO)Process->Win32Process)->pClientBase;
    01706     }
    01707     ulSharedDelta = (PBYTE)gpvSharedBase - (PBYTE)pClientBase;
    01708     pUserConnect->siClient.ulSharedDelta = ulSharedDelta;
    01709
    01710     pUserConnect->siClient.psi          = CALC_DELTA(psi);
    01711     pUserConnect->siClient.aheList      = CALC_DELTA(aheList);
    01712     pUserConnect->siClient.pDispInfo    = CALC_DELTA(pDispInfo);
    01713
    01714
    01715     pUserConnect->siClient.DefWindowMsgs.maxMsgs     = gSharedInfo.DefWindowMsgs.maxMsgs;
    01716     pUserConnect->siClient.DefWindowMsgs.abMsgs      = CALC_DELTA(DefWindowMsgs.abMsgs);
    01717     pUserConnect->siClient.DefWindowSpecMsgs.maxMsgs = gSharedInfo.DefWindowSpecMsgs.maxMsgs;
    01718     pUserConnect->siClient.DefWindowSpecMsgs.abMsgs  = CALC_DELTA(DefWindowSpecMsgs.abMsgs);
    01719
    01720     for (i = 0; i < (FNID_END - FNID_START + 1); ++i) {
    01721
    01722         pUserConnect->siClient.awmControl[i].maxMsgs = gSharedInfo.awmControl[i].maxMsgs;
    01723
    01724         if (gSharedInfo.awmControl[i].abMsgs)
    01725             pUserConnect->siClient.awmControl[i].abMsgs = CALC_DELTA(awmControl[i].abMsgs);
    01726         else
    01727             pUserConnect->siClient.awmControl[i].abMsgs = NULL;
    01728     }
    01729     return STATUS_SUCCESS;
    01730 }
    01731 /**************************************************************************\
    01732 * InitLoadResources
    01733 *
    01734 *
    01735 * 25-Aug-1995 ChrisWil      Created.
    01736 \**************************************************************************/
    01737
    01738 VOID InitLoadResources()
    01739 {
    01740     PRECT   prc;
    01741
    01742     DISPLAYRESOURCE dr = {
    01743         17,     // Height of vertical thumb
    01744         17,     // Width of horizontal thumb
    01745         2,      // Icon horiz compression factor
    01746         2,      // Icon vert compression factor
    01747         1,      // Cursor horz compression factor
    01748         1,      // Cursor vert compression factor
    01749         0,      // Kanji window height
    01750         1,      // cxBorder (thickness of vertical lines)
    01751         1       // cyBorder (thickness of horizontal lines)
    01752     };
    01753
    01754
    01755     TRACE_INIT(("UserInit: Load Display Resources\n"));
    01756
    01757     if (dr.xCompressIcon > 10) {
    01758
    01759         /*
    01760          * If so, the actual dimensions of icons and cursors are
    01761          * kept in OEMBIN.
    01762          */
    01763         SYSMET(CXICON)   = dr.xCompressIcon;
    01764         SYSMET(CYICON)   = dr.yCompressIcon;
    01765         SYSMET(CXCURSOR) = dr.xCompressCursor;
    01766         SYSMET(CYCURSOR) = dr.yCompressCursor;
    01767
    01768     } else {
    01769
    01770         /*
    01771          * Else, only the ratio of (64/icon dimensions) is kept there.
    01772          */
    01773         SYSMET(CXICON)   = (64 / dr.xCompressIcon);
    01774         SYSMET(CYICON)   = (64 / dr.yCompressIcon);
    01775         SYSMET(CXCURSOR) = (32 / dr.xCompressCursor);
    01776         SYSMET(CYCURSOR) = (32 / dr.yCompressCursor);
    01777     }
    01778
    01779     SYSMET(CXSMICON) = SYSMET(CXICON) / 2;
    01780     SYSMET(CYSMICON) = SYSMET(CYICON) / 2;
    01781
    01782     SYSMET(CYKANJIWINDOW) = dr.yKanji;
    01783
    01784     /*
    01785      * Get border thicknesses.
    01786      */
    01787     SYSMET(CXBORDER) = dr.cxBorder;
    01788     SYSMET(CYBORDER) = dr.cyBorder;
    01789
    01790     /*
    01791      * Edge is two borders.
    01792      */
    01793     SYSMET(CXEDGE) = 2 * SYSMET(CXBORDER);
    01794     SYSMET(CYEDGE) = 2 * SYSMET(CYBORDER);
    01795
    01796     /*
    01797      * Fixed frame is outer edge + border.
    01798      */
    01799     SYSMET(CXDLGFRAME) = SYSMET(CXEDGE) + SYSMET(CXBORDER);
    01800     SYSMET(CYDLGFRAME) = SYSMET(CYEDGE) + SYSMET(CYBORDER);
    01801
    01802     if (gbRemoteSession) {
    01803         return;
    01804     }
    01805
    01806     prc = &GetPrimaryMonitor()->rcMonitor;
    01807     SYSMET(CXFULLSCREEN) = prc->right;
    01808     SYSMET(CYFULLSCREEN) = prc->bottom - SYSMET(CYCAPTION);
    01809
    01810     /*
    01811      * Set the initial cursor position to the center of the primary screen.
    01812      */
    01813     gpsi->ptCursor.x = prc->right / 2;
    01814     gpsi->ptCursor.y = prc->bottom / 2;
    01815 }
    01816
    01817 /***************************************************************************\
    01818 * GetCharDimensions
    01819 *
    01820 * This function loads the Textmetrics of the font currently selected into
    01821 * the hDC and returns the Average char width of the font; Pl Note that the
    01822 * AveCharWidth value returned by the Text metrics call is wrong for
    01823 * proportional fonts.  So, we compute them On return, lpTextMetrics contains
    01824 * the text metrics of the currently selected font.
    01825 *
    01826 * History:
    01827 * 10-Nov-1993 mikeke   Created
    01828 \***************************************************************************/
    01829 int GetCharDimensions(
    01830         HDC          hdc,
    01831         TEXTMETRIC*  lptm,
    01832         LPINT        lpcy
    01833         )
    01834 {
    01835     TEXTMETRIC tm;
    01836
    01837     /*
    01838      * Didn't find it in cache, store the font metrics info.
    01839      */
    01840     if (!_GetTextMetricsW(hdc, &tm)) {
    01841         RIPMSG1(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW failed. hdc %#lx", hdc);
    01842         tm = gpsi->tmSysFont; // damage control
    01843
    01844         if (tm.tmAveCharWidth == 0) {
    01845             RIPMSG0(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW first time failure");
    01846             tm.tmAveCharWidth = 8;
    01847         }
    01848     }
    01849     if (lptm != NULL)
    01850         *lptm = tm;
    01851     if (lpcy != NULL)
    01852         *lpcy = tm.tmHeight;
    01853
    01854     /*
    01855      * If variable_width font
    01856      */
    01857     if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) {
    01858         SIZE size;
    01859         static CONST WCHAR wszAvgChars[] =
    01860                 L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    01861
    01862         /*
    01863          * Change from tmAveCharWidth.  We will calculate a true average
    01864          * as opposed to the one returned by tmAveCharWidth.  This works
    01865          * better when dealing with proportional spaced fonts.
    01866          */
    01867         if (GreGetTextExtentW(
    01868                 hdc, (LPWSTR)wszAvgChars,
    01869                 (sizeof(wszAvgChars) / sizeof(WCHAR)) - 1,
    01870                 &size, GGTE_WIN3_EXTENT)) {
    01871
    01872             UserAssert((((size.cx / 26) + 1) / 2) > 0);
    01873             return ((size.cx / 26) + 1) / 2;    // round up
    01874         } else {
    01875             RIPMSG1(RIP_WARNING, "GetCharDimensions: GreGetTextExtentW failed. hdc %#lx", hdc);
    01876         }
    01877     }
    01878
    01879     UserAssert(tm.tmAveCharWidth > 0);
    01880
    01881     return tm.tmAveCharWidth;
    01882 }
    01883
    01884
    01885 /**************************************************************************\
    01886 * InitVideo
    01887 *
    01888 * Create pmdev.
    01889 *
    01890 * 03-March-1998 CLupu  Moved from UserInitialize code
    01891 \**************************************************************************/
    01892
    01893 PMDEV InitVideo(
    01894     BOOL bReenumerationNeeded)
    01895 {
    01896     PMDEV pmdev;
    01897     LONG  ChangeStatus;
    01898
    01899     /*
    01900      * BUGBUG !!! Need to get a status return from this call.
    01901      */
    01902     DrvInitConsole(bReenumerationNeeded);
    01903
    01904     /*
    01905      * BASEVIDEO may be on or off, whether we are in setup or not.
    01906      */
    01907
    01908     ChangeStatus = DrvChangeDisplaySettings(NULL,
    01909                                             NULL,
    01910                                             NULL,
    01911                                             (PVOID) (GW_DESKTOP_ID),
    01912                                             KernelMode,
    01913                                             FALSE,
    01914                                             TRUE,
    01915                                             NULL,
    01916                                             &pmdev,
    01917                                             GRE_DEFAULT,
    01918                                             TRUE);
    01919
    01920     if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
    01921
    01922         /*
    01923          * If we fail, try BASEVIDEO temporarily
    01924          */
    01925
    01926         DrvSetBaseVideo(TRUE);
    01927
    01928         ChangeStatus = DrvChangeDisplaySettings(NULL,
    01929                                                 NULL,
    01930                                                 NULL,
    01931                                                 (PVOID) (GW_DESKTOP_ID),
    01932                                                 KernelMode,
    01933                                                 FALSE,
    01934                                                 TRUE,
    01935                                                 NULL,
    01936                                                 &pmdev,
    01937                                                 GRE_DEFAULT,
    01938                                                 TRUE);
    01939
    01940         DrvSetBaseVideo(FALSE);
    01941
    01942         /*
    01943          * Give it one last try, not in basevideo, to handle TGA
    01944          * (non-vgacompatible) during GUI-mode setup (BASEVIDEO is on by
    01945          * default)
    01946          */
    01947
    01948         if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
    01949
    01950             ChangeStatus = DrvChangeDisplaySettings(NULL,
    01951                                                     NULL,
    01952                                                     NULL,
    01953                                                     (PVOID) (GW_DESKTOP_ID),
    01954                                                     KernelMode,
    01955                                                     FALSE,
    01956                                                     TRUE,
    01957                                                     NULL,
    01958                                                     &pmdev,
    01959                                                     GRE_DEFAULT,
    01960                                                     TRUE);
    01961
    01962         }
    01963     }
    01964
    01965     if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
    01966         RIPMSG0(RIP_WARNING, "InitVideo: No working display driver found");
    01967         return NULL;
    01968     }
    01969
    01970     gpDispInfo->hDev  = pmdev->hdevParent;
    01971     gpDispInfo->pmdev = pmdev;
    01972
    01973     GreUpdateSharedDevCaps(gpDispInfo->hDev);
    01974
    01975     if (!InitUserScreen()) {
    01976         RIPMSG0(RIP_WARNING, "InitUserScreen failed");
    01977         return NULL;
    01978     }
    01979
    01980     HYDRA_HINT(HH_INITVIDEO);
    01981
    01982     return pmdev;
    01983 }
    01984
    01985 void DrvDriverFailure(void)
    01986 {
    01987     KeBugCheckEx(VIDEO_DRIVER_INIT_FAILURE,
    01988                  0,
    01989                  0,
    01990                  0,
    01991                  USERCURRENTVERSION);
    01992 }
    01993
    01994
    01995 /**************************************************************************\
    01996 * UserInitialize
    01997 *
    01998 * Worker routine for user initialization.
    01999 *
    02000 * 25-Aug-1995 ChrisWil  Created comment block/Multiple desktop support.
    02001 * 15-Dec-1995 BradG     Modified to return MediaChangeEvent Handle.
    02002 \**************************************************************************/
    02003
    02004 NTSTATUS UserInitialize(VOID)
    02005 {
    02006     NTSTATUS Status;
    02007
    02008     /*
    02009      * Allow a trace of all the init stuff going on related to display drivers.
    02010      * Usefull to debug boot time problems related to graphics.
    02011      */
    02012     if (**((PULONG *)&NtGlobalFlag) & FLG_SHOW_LDR_SNAPS)
    02013         TraceInitialization = 1;
    02014
    02015     TRACE_INIT(("Entering UserInitialize\n"));
    02016
    02017     EnterCrit();
    02018
    02019     HYDRA_HINT(HH_USERINITIALIZE);
    02020
    02021     if (ISTS()) {
    02022
    02023         if (gbRemoteSession) {
    02024             swprintf(szWindowStationDirectory, L"%ws\\%ld%ws",
    02025                      SESSION_ROOT, gSessionId, WINSTA_DIR);
    02026         } else {
    02027             wcscpy(szWindowStationDirectory, WINSTA_DIR);
    02028         }
    02029     } else {
    02030         wcscpy(szWindowStationDirectory, WINSTA_DIR);
    02031     }
    02032
    02033     /*
    02034      * Create WindowStation object directory.
    02035      */
    02036     Status = InitCreateObjectDirectory();
    02037
    02038     if (!NT_SUCCESS(Status)) {
    02039         RIPMSG1(RIP_WARNING, "InitCreateObjectDirectory failed with Status %x",
    02040                 Status);
    02041
    02042         goto Exit;
    02043     }
    02044
    02045     /*
    02046      * WinStations get init'ed on the first connect
    02047      */
    02048     if (gbRemoteSession) {
    02049
    02050         /*
    02051          * Create the event for the diconnect desktop creation
    02052          */
    02053         gpEventDiconnectDesktop = CreateKernelEvent(SynchronizationEvent, FALSE);
    02054
    02055         if (gpEventDiconnectDesktop == NULL) {
    02056             RIPMSG0(RIP_WARNING, "Failed to create gpEventDiconnectDesktop");
    02057             Status = STATUS_NO_MEMORY;
    02058             goto Exit;
    02059         }
    02060
    02061         goto SkipRemote;
    02062     }
    02063
    02064     if (InitVideo(TRUE) == NULL) {
    02065         DrvDriverFailure();
    02066     }
    02067
    02068     /*
    02069      * Do this here so power callouts
    02070      * have the pmdev in gpDispInfo set
    02071      */
    02072     gbVideoInitialized = TRUE;
    02073
    02074 SkipRemote:
    02075
    02076     gbUserInitialized = TRUE;
    02077
    02078     /*
    02079      * Now that the system is initialized, allocate
    02080      * a pti for this thread.
    02081      */
    02082     Status = xxxCreateThreadInfo(PsGetCurrentThread(), FALSE);
    02083
    02084     if (!NT_SUCCESS(Status)) {
    02085         RIPMSG1(RIP_WARNING, "xxxCreateThreadInfo failed during UserInitialize with Status",
    02086                 Status);
    02087         goto Exit;
    02088     }
    02089
    02090     /*
    02091      * Initialize Global RIP flags (debug only).
    02092      */
    02093     InitGlobalRIPFlags();
    02094
    02095     /*
    02096      * WinStations get init'ed on the first connect
    02097      */
    02098     if (!gbRemoteSession)
    02099         UserVerify(LW_BrushInit());
    02100
    02101     InitLoadResources();
    02102
    02103 Exit:
    02104     LeaveCrit();
    02105
    02106     TRACE_INIT(("Leaving UserInitialize\n"));
    02107
    02108     return Status;
    02109 }
    02110
    02111 /**************************************************************************\
    02112 * IsDBCSEnabledSystem
    02113 *
    02114 * check if the system is configured as FE Enabled
    02115 *
    02116 * 07-Feb-1997 HiroYama  Created
    02117 \**************************************************************************/
    02118 BOOL IsDBCSEnabledSystem()
    02119 {
    02120     extern BOOLEAN* NlsMbCodePageTag;
    02121     return !!*NlsMbCodePageTag;
    02122 }
    02123
    02124
    02125 BOOL IsIMMEnabledSystem()
    02126 {
    02127     // if the entire system is DBCS enabled, IMM/IME should be activated anyway
    02128     if (IsDBCSEnabledSystem())
    02129         return TRUE;
    02130
    02131     return FastGetProfileDwordW(NULL, PMAP_IMM, TEXT("LoadIMM"), 0);
    02132 }
    02133
    02134 // Get ACP and check if the system is configured as ME Enabled
    02135 BOOL IsMidEastEnabledSystem()
    02136 {
    02137     extern __declspec(dllimport) USHORT NlsAnsiCodePage;
    02138     //1255 Hebrew and 1256 Arabic
    02139     if ((NlsAnsiCodePage == 1255) || (NlsAnsiCodePage == 1256)) {
    02140         return TRUE;
    02141     }
    02142     return FALSE;
    02143 }
    02144
    02145 /***************************************************************************\
    02146 * SetupClassAtoms
    02147 *
    02148 * 10/01/1998   clupu          moved from Win32UserInitialize
    02149 \***************************************************************************/
    02150
    02151 BOOL SetupClassAtoms(
    02152     VOID)
    02153 {
    02154     BOOL fSuccess = TRUE;
    02155     int  ind;
    02156
    02157     /*
    02158      * Set up class atoms
    02159      */
    02160     /*
    02161      * HACK: Controls are registered on the client side so we can't
    02162      * fill in their atomSysClass entry the same way we do for the other
    02163      * classes.
    02164      */
    02165     for (ind = ICLS_BUTTON; ind < ICLS_CTL_MAX; ind++) {
    02166         gpsi->atomSysClass[ind] = UserAddAtom(lpszControls[ind], TRUE);
    02167         fSuccess &= !!gpsi->atomSysClass[ind];
    02168     }
    02169
    02170     gpsi->atomSysClass[ICLS_DIALOG]    = PTR_TO_ID(DIALOGCLASS);
    02171     gpsi->atomSysClass[ICLS_ICONTITLE] = PTR_TO_ID(ICONTITLECLASS);
    02172     gpsi->atomSysClass[ICLS_TOOLTIP]   = PTR_TO_ID(TOOLTIPCLASS);
    02173     gpsi->atomSysClass[ICLS_DESKTOP]   = PTR_TO_ID(DESKTOPCLASS);
    02174     gpsi->atomSysClass[ICLS_SWITCH]    = PTR_TO_ID(SWITCHWNDCLASS);
    02175     gpsi->atomSysClass[ICLS_MENU]      = PTR_TO_ID(MENUCLASS);
    02176
    02177     gpsi->atomContextHelpIdProp = UserAddAtom(szCONTEXTHELPIDPROP, TRUE);
    02178     fSuccess &= !!gpsi->atomContextHelpIdProp;
    02179
    02180     gpsi->atomIconSmProp        = UserAddAtom(szICONSM_PROP_NAME, TRUE);
    02181     fSuccess &= !!gpsi->atomIconSmProp;
    02182
    02183     gpsi->atomIconProp          = UserAddAtom(szICON_PROP_NAME, TRUE);
    02184     fSuccess &= !!gpsi->atomIconProp;
    02185
    02186     gpsi->uiShellMsg            = UserAddAtom(szSHELLHOOK, TRUE);
    02187     fSuccess &= !!gpsi->uiShellMsg;
    02188
    02189     /*
    02190      * Initialize the integer atoms for our magic window properties
    02191      */
    02192     atomCheckpointProp = UserAddAtom(szCHECKPOINT_PROP_NAME, TRUE);
    02193     fSuccess &= !!atomCheckpointProp;
    02194
    02195     atomDDETrack = UserAddAtom(szDDETRACK_PROP_NAME, TRUE);
    02196     fSuccess &= !!atomDDETrack;
    02197
    02198     atomQOS = UserAddAtom(szQOS_PROP_NAME, TRUE);
    02199     fSuccess &= !!atomQOS;
    02200
    02201     atomDDEImp = UserAddAtom(szDDEIMP_PROP_NAME, TRUE);
    02202     fSuccess &= !!atomDDEImp;
    02203
    02204     atomWndObj = UserAddAtom(szWNDOBJ_PROP_NAME, TRUE);
    02205     fSuccess &= !!atomWndObj;
    02206
    02207     atomImeLevel = UserAddAtom(szIMELEVEL_PROP_NAME, TRUE);
    02208     fSuccess &= !!atomImeLevel;
    02209
    02210     atomLayer = UserAddAtom(szLAYER_PROP_NAME, TRUE);
    02211     fSuccess &= !!atomLayer;
    02212
    02213     guiActivateShellWindow = UserAddAtom(szACTIVATESHELLWINDOW, TRUE);
    02214     fSuccess &= !!guiActivateShellWindow;
    02215
    02216     guiOtherWindowCreated = UserAddAtom(szOTHERWINDOWCREATED, TRUE);
    02217     fSuccess &= !!guiOtherWindowCreated;
    02218
    02219     guiOtherWindowDestroyed = UserAddAtom(szOTHERWINDOWDESTROYED, TRUE);
    02220     fSuccess &= !!guiOtherWindowDestroyed;
    02221
    02222     gatomMessage = UserAddAtom(szMESSAGE, TRUE);
    02223     fSuccess &= !!gatomMessage;
    02224
    02225 #ifdef HUNGAPP_GHOSTING
    02226     gatomGhost = UserAddAtom(szGHOST, TRUE);
    02227     fSuccess &= !!gatomGhost;
    02228 #endif // HUNGAPP_GHOSTING
    02229
    02230     gaOleMainThreadWndClass = UserAddAtom(szOLEMAINTHREADWNDCLASS, TRUE);
    02231     fSuccess &= !!gaOleMainThreadWndClass;
    02232
    02233     gaFlashWState = UserAddAtom(szFLASHWSTATE, TRUE);
    02234     fSuccess &= !!gaFlashWState;
    02235
    02236     gatomLastPinned = gaOleMainThreadWndClass;
    02237
    02238     return fSuccess;
    02239 }
    02240
    02241
    02242 /**************************************************************************\
    02243 * Win32UserInitialize
    02244 *
    02245 * Worker routine for user initialization called from Win32k.sys DriverEntry()
    02246 *
    02247 \**************************************************************************/
    02248
    02249 NTSTATUS Win32UserInitialize(VOID)
    02250 {
    02251     NTSTATUS                 Status;
    02252     POBJECT_TYPE_INITIALIZER pTypeInfo;
    02253     LONG                     lTemp;
    02254
    02255     TRACE_INIT(("Entering Win32UserInitialize\n"));
    02256
    02257     /*
    02258      * Create the shared section.
    02259      */
    02260     Status = InitCreateSharedSection();
    02261     if (!NT_SUCCESS(Status)) {
    02262         RIPMSG0(RIP_WARNING, "InitCreateSharedSection failed");
    02263         return Status;
    02264     }
    02265
    02266     EnterCrit();
    02267
    02268     /*
    02269      * Initialize security stuff.
    02270      */
    02271     if (!InitSecurity()) {
    02272         RIPMSG0(RIP_WARNING, "InitSecurity failed");
    02273         goto ExitWin32UserInitialize;
    02274     }
    02275
    02276     /*
    02277      * Fill in windowstation and desktop object types
    02278      */
    02279     pTypeInfo = &(*ExWindowStationObjectType)->TypeInfo;
    02280     pTypeInfo->DefaultNonPagedPoolCharge = sizeof(WINDOWSTATION) + sizeof(KEVENT);
    02281     pTypeInfo->DefaultPagedPoolCharge    = 0;
    02282     pTypeInfo->MaintainHandleCount       = TRUE;
    02283     pTypeInfo->CloseProcedure            = DestroyWindowStation;
    02284     pTypeInfo->DeleteProcedure           = FreeWindowStation;
    02285     pTypeInfo->ParseProcedure            = ParseWindowStation;
    02286     pTypeInfo->OkayToCloseProcedure      = OkayToCloseWindowStation;
    02287     pTypeInfo->ValidAccessMask           = WinStaMapping.GenericAll;
    02288     pTypeInfo->GenericMapping            = WinStaMapping;
    02289
    02290     pTypeInfo = &(*ExDesktopObjectType)->TypeInfo;
    02291     pTypeInfo->DefaultNonPagedPoolCharge = sizeof(DESKTOP);
    02292     pTypeInfo->DefaultPagedPoolCharge    = 0;
    02293     pTypeInfo->MaintainHandleCount       = TRUE;
    02294     pTypeInfo->CloseProcedure            = UnmapDesktop;
    02295     pTypeInfo->OpenProcedure             = MapDesktop;
    02296     pTypeInfo->DeleteProcedure           = FreeDesktop;
    02297     pTypeInfo->OkayToCloseProcedure      = OkayToCloseDesktop;
    02298     pTypeInfo->ValidAccessMask           = DesktopMapping.GenericAll;
    02299     pTypeInfo->GenericMapping            = DesktopMapping;
    02300
    02301     /*
    02302      * Get this process so we can use the profiles.
    02303      */
    02304     gpepInit = PsGetCurrentProcess();
    02305
    02306     Status  = InitQEntryLookaside();
    02307     Status |= InitSMSLookaside();
    02308     Status |= UserRtlCreateAtomTable(USRINIT_ATOMBUCKET_SIZE);
    02309
    02310     if (!NT_SUCCESS(Status)) {
    02311         RIPMSG0(RIP_WARNING, "Initialization failure");
    02312         goto ExitWin32UserInitialize;
    02313     }
    02314
    02315     atomUSER32 = UserAddAtom(szUSER32, TRUE);
    02316
    02317     gatomFirstPinned = atomUSER32;
    02318
    02319     if (gatomFirstPinned == 0) {
    02320         RIPMSG0(RIP_WARNING, "Could not create atomUSER32");
    02321         goto ExitWin32UserInitialize;
    02322     }
    02323
    02324     /*
    02325      * Initialize the user subsystem information.
    02326      */
    02327     if (!InitCreateUserSubsystem()) {
    02328         RIPMSG0(RIP_WARNING, "InitCreateUserSubsystem failed");
    02329         goto ExitWin32UserInitialize;
    02330     }
    02331
    02332     /*
    02333      * Don't bail out if CreateSetupNameArray fails
    02334      * MCostea #326652
    02335      */
    02336     CreateSetupNameArray();
    02337
    02338     /*
    02339      * Allocated shared SERVERINFO structure.
    02340      */
    02341     if ((gpsi = (PSERVERINFO)SharedAlloc(sizeof(SERVERINFO))) == NULL) {
    02342         RIPMSG0(RIP_WARNING, "Could not allocate SERVERINFO");
    02343         goto ExitWin32UserInitialize;
    02344     }
    02345
    02346     /*
    02347      * Set the default rip-flags to rip on just about
    02348      * everything.  We'll truly set this in the InitGlobalRIPFlags()
    02349      * routine.  These are needed so that we can do appropriate ripping
    02350      * during the rest of the init-calls.
    02351      */
    02352
    02353     SET_FLAG(gpsi->wRIPFlags, RIPF_DEFAULT);
    02354
    02355     /*
    02356      * Make sure we will not get a division by zero if the initialization
    02357      * will not complete correctly. Set these to their normal values.
    02358      */
    02359     gpsi->cxMsgFontChar = 6;
    02360     gpsi->cyMsgFontChar = 13;
    02361     gpsi->cxSysFontChar = 8;
    02362     gpsi->cySysFontChar = 16;
    02363
    02364     /*
    02365      * Initialize the DISPLAYINFO structure.
    02366      */
    02367     gpDispInfo = SharedAlloc(sizeof(*gpDispInfo));
    02368     if (!gpDispInfo) {
    02369         RIPMSG0(RIP_WARNING, "Could not allocate gpDispInfo");
    02370         goto ExitWin32UserInitialize;
    02371     }
    02372
    02373     InitDbgTags();
    02374
    02375     SET_OR_CLEAR_SRVIF(SRVIF_DBCS, IsDBCSEnabledSystem());
    02376     SET_OR_CLEAR_SRVIF(SRVIF_IME, IsIMMEnabledSystem());
    02377
    02378     SET_OR_CLEAR_SRVIF(SRVIF_MIDEAST, IsMidEastEnabledSystem());
    02379
    02380 #if DBG
    02381     SET_SRVIF(SRVIF_CHECKED);
    02382
    02383     RIPMSG3(RIP_WARNING, "*** win32k: DBCS:[%d] IME:[%d] MiddleEast:[%d]",
    02384             IS_DBCS_ENABLED(),
    02385             IS_IME_ENABLED(),
    02386             IS_MIDEAST_ENABLED());
    02387 #endif
    02388
    02389     gpsi->dwDefaultHeapSize = gdwDesktopSectionSize * 1024;
    02390
    02391     /*
    02392      * Initialize procedures and message tables.
    02393      * Initialize the class structures for Get/SetClassWord/Long.
    02394      * Initialize message-box strings.
    02395      * Initialize OLE-Formats (performance-hack).
    02396      */
    02397     InitFunctionTables();
    02398     InitMessageTables();
    02399 #if DBG
    02400     VerifySyncOnlyMessages();
    02401 #endif
    02402     if (!InitOLEFormats()) {
    02403         RIPMSG0(RIP_WARNING, "InitOLEFormats failed");
    02404         goto ExitWin32UserInitialize;
    02405     }
    02406
    02407     /*
    02408      * Set up class atoms
    02409      */
    02410     if (!SetupClassAtoms()) {
    02411         RIPMSG0(RIP_WARNING, "SetupClassAtoms failed to register atoms");
    02412         goto ExitWin32UserInitialize;
    02413     }
    02414
    02415     LW_LoadSomeStrings();
    02416
    02417     /*
    02418      * Initialize the handle manager.
    02419      */
    02420     if (!HMInitHandleTable(gpvSharedBase)) {
    02421         RIPMSG0(RIP_WARNING, "HMInitHandleTable failed");
    02422         goto ExitWin32UserInitialize;
    02423     }
    02424
    02425     /*
    02426      * Setup shared info block.
    02427      */
    02428     gSharedInfo.psi = gpsi;
    02429     gSharedInfo.pDispInfo = gpDispInfo;
    02430
    02431     /*
    02432      * Determine if we have unsigned drivers installed
    02433      * Use      2BD63D28D7BCD0E251195AEB519243C13142EBC3 as current key to check.
    02434      * Old key: 300B971A74F97E098B67A4FCEBBBF6B9AE2F404C
    02435      */
    02436     if (NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
    02437             L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3"))
    02438              ||
    02439             NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,
    02440             L"\\Registry\\Machine\\SOFTWARE\\Policies\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3"))) {
    02441
    02442         gfUnsignedDrivers = TRUE;
    02443     }
    02444
    02445     /*
    02446      * Set up a desktop info structure that is visible in all
    02447      * clients.
    02448      */
    02449     lTemp = FastGetProfileDwordW(NULL,
    02450                                  PMAP_WINDOWSM,
    02451                                  L"USERProcessHandleQuota",
    02452                                  gUserProcessHandleQuota);
    02453
    02454     if ((lTemp > MINIMUM_USER_HANDLE_QUOTA) && (lTemp <= INITIAL_USER_HANDLE_QUOTA)) {
    02455         gUserProcessHandleQuota = lTemp;
    02456     }
    02457
    02458     /*
    02459      * The maximum number of posted message for a thread.
    02460      */
    02461     lTemp = FastGetProfileDwordW(NULL,
    02462                                  PMAP_WINDOWSM,
    02463                                  L"USERPostMessageLimit",
    02464                                  gUserPostMessageLimit);
    02465     if (lTemp > MINIMUM_POSTMESSAGE_LIMIT) {
    02466         gUserPostMessageLimit = lTemp;
    02467     } else if (lTemp == 0) {
    02468         /*
    02469          * 0 means (virtually) No Limit.
    02470          */
    02471         gUserPostMessageLimit = ~0;
    02472     } else {
    02473         RIPMSG1(RIP_WARNING, "Win32UserInitialize: USERPostMessageLimit value (%d) is too low.", lTemp);
    02474     }
    02475
    02476     if (!gDrawVersionAlways) {
    02477         gDrawVersionAlways = FastGetProfileDwordW(NULL,
    02478                                                   PMAP_WINDOWSM,
    02479                                                   L"DisplayVersion",
    02480                                                   0);
    02481     }
    02482
    02483     gbSecureDesktop = FastGetProfileDwordW(NULL,
    02484                                            PMAP_WINDOWSM,
    02485                                            L"SecureDesktop",
    02486                                            TRUE);
    02487
    02488     /*
    02489      * Initialize SMWP structure
    02490      */
    02491     if (!AllocateCvr(&gSMWP, 4)) {
    02492         RIPMSG0(RIP_WARNING, "AllocateCvr failed");
    02493         goto ExitWin32UserInitialize;
    02494     }
    02495     LeaveCrit();
    02496
    02497     UserAssert(NT_SUCCESS(Status));
    02498     return Status;
    02499
    02500 ExitWin32UserInitialize:
    02501     LeaveCrit();
    02502
    02503     if (NT_SUCCESS(Status)) {
    02504         Status = STATUS_NO_MEMORY;
    02505     }
    02506
    02507     RIPMSG1(RIP_WARNING, "UserInitialize failed with Status = %x", Status);
    02508     return Status;
    02509 }
    02510
    02511
    02512 /**************************************************************************\
    02513 * UserGetDesktopDC
    02514 *
    02515 * 09-Jan-1992 mikeke created
    02516 *    Dec-1993 andreva changed to support desktops.
    02517 \**************************************************************************/
    02518
    02519 HDC UserGetDesktopDC(
    02520     ULONG type,
    02521     BOOL  bAltType,
    02522     BOOL  bValidate)
    02523 {
    02524     PETHREAD    Thread;
    02525     HDC         hdc;
    02526     PTHREADINFO pti = PtiCurrentShared();  // This is called from outside the crit sec
    02527     HDEV        hdev  = gpDispInfo->hDev;
    02528
    02529     if (bValidate && type != DCTYPE_INFO &&
    02530         IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_HANDLES)) {
    02531
    02532         UserAssert(pti->rpdesk != NULL);
    02533
    02534         if (!ValidateHwnd(PtoH(pti->rpdesk->pDeskInfo->spwnd))) {
    02535             RIPMSG0(RIP_WARNING,
    02536                     "UserGetDesktopDC fails desktop window validation");
    02537             return NULL;
    02538         }
    02539     }
    02540
    02541     /*
    02542      * !!! BUGBUG
    02543      * This is a real nasty trick to get both DCs created on a desktop on
    02544      * a different device to work (for the video applet) and to be able
    02545      * to clip DCs that are actually on the same device ...
    02546      */
    02547     if (pti && pti->rpdesk)
    02548         hdev = pti->rpdesk->pDispInfo->hDev;
    02549
    02550     /*
    02551      * We want to turn this call that was originally OpenDC("Display", ...)
    02552      * into GetDC null call so this DC will be clipped to the current
    02553      * desktop or else the DC can write to any desktop.  Only do this
    02554      * for client apps; let the server do whatever it wants.
    02555      */
    02556     Thread = PsGetCurrentThread();
    02557     if ((type != DCTYPE_DIRECT)  ||
    02558         (hdev != gpDispInfo->hDev) ||
    02559         IS_SYSTEM_THREAD(Thread) ||
    02560         (Thread->ThreadsProcess == gpepCSRSS)) {
    02561
    02562         hdc = GreCreateDisplayDC(hdev, type, bAltType);
    02563
    02564     } else {
    02565
    02566         PDESKTOP pdesk;
    02567
    02568         EnterCrit();
    02569
    02570         if (pdesk = PtiCurrent()->rpdesk) {
    02571
    02572             hdc = _GetDCEx(pdesk->pDeskInfo->spwnd,
    02573                            NULL,
    02574                            DCX_WINDOW | DCX_CACHE | DCX_CREATEDC);
    02575         } else {
    02576             hdc = NULL;
    02577         }
    02578
    02579         LeaveCrit();
    02580     }
    02581
    02582     return hdc;
    02583 }
    02584
    02585
    02586 /**************************************************************************\
    02587 * UserThreadCallout
    02588 *
    02589 *
    02590 * Called by the kernel when a thread starts or ends.
    02591 *
    02592 * Dec-1993 andreva created.
    02593 \**************************************************************************/
    02594
    02595 NTSTATUS UserThreadCallout(
    02596     IN PETHREAD pEThread,
    02597     IN PSW32THREADCALLOUTTYPE CalloutType)
    02598 {
    02599     PTHREADINFO pti;
    02600     NTSTATUS    Status = STATUS_SUCCESS;
    02601
    02602     UserAssert(gpresUser != NULL);
    02603
    02604     switch (CalloutType) {
    02605         case PsW32ThreadCalloutInitialize:
    02606             TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutInitialize\n"));
    02607
    02608             if (gbNoMorePowerCallouts) {
    02609                 RIPMSG0(RIP_WARNING, "No more GUI threads allowed");
    02610                 return STATUS_UNSUCCESSFUL;
    02611             }
    02612
    02613             /*
    02614              * Only create a thread info structure if we're initialized.
    02615              */
    02616             if (gbUserInitialized) {
    02617                 EnterCrit();
    02618                 UserAssert(gpepCSRSS != NULL);
    02619
    02620                 /*
    02621                  * Initialize this thread
    02622                  */
    02623                 Status = xxxCreateThreadInfo(pEThread, FALSE);
    02624
    02625                 LeaveCrit();
    02626             }
    02627             break;
    02628
    02629        case PsW32ThreadCalloutExit:
    02630
    02631             TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutExit\n"));
    02632
    02633             /*
    02634              * If we aren't already inside the critical section, enter it.
    02635              * Because this is the first pass, we remain in the critical
    02636              * section when we return so that our try/finally handlers
    02637              * are protected by the critical section.
    02638              * EnterCrit here before GreUnlockDisplay() provides a pti which
    02639              * may be required if unlocking the display may release some
    02640              * deferred WinEvents, for which a pti is required.
    02641              */
    02642             EnterCrit();
    02643
    02644             pti = (PTHREADINFO)pEThread->Tcb.Win32Thread;
    02645
    02646             /*
    02647              * WinStations that haven't gone through the first connect do not
    02648              * have any of the graphics setup.
    02649              */
    02650             if (!gbRemoteSession || gbVideoInitialized) {
    02651
    02652                 /*
    02653                  * Assert that we did not cleaned up gpDispInfo->hDev
    02654                  */
    02655                 UserAssert(!gbCleanedUpResources);
    02656
    02657                 GreLockDisplay(gpDispInfo->hDev);
    02658                 GreUnlockDisplay(gpDispInfo->hDev);
    02659             }
    02660
    02661
    02662            /*
    02663             * Mark this thread as in the middle of cleanup. This is useful for
    02664             * several problems in USER where we need to know this information.
    02665             */
    02666            pti->TIF_flags |= TIF_INCLEANUP;
    02667
    02668            /*
    02669             * If we died during a full screen switch make sure we cleanup
    02670             * correctly
    02671             */
    02672            FullScreenCleanup();
    02673            /*
    02674             * Cleanup gpDispInfo->hdcScreen - if we crashed while using it,
    02675             * it may have owned objects still selected into it. Cleaning
    02676             * it this way will ensure that gdi doesn't try to delete these
    02677             * objects while they are still selected into this public hdc.
    02678             */
    02679
    02680            /*
    02681             * WinStations that haven't gone through the first connect do not
    02682             * have any of the graphics setup.
    02683             */
    02684            if (!gbRemoteSession || gbVideoInitialized) {
    02685                GreCleanDC(gpDispInfo->hdcScreen);
    02686            }
    02687
    02688            /*
    02689             * This thread is exiting execution; xxxDestroyThreadInfo cleans
    02690             *  up everything that can go now
    02691             */
    02692            UserAssert(pti == PtiCurrent());
    02693            xxxDestroyThreadInfo();
    02694            LeaveCrit();
    02695
    02696            break;
    02697     }
    02698
    02699     TRACE_INIT(("Leaving UserThreadCallout\n"));
    02700
    02701     return Status;
    02702 }
    02703
    02704 /**************************************************************************\
    02705 * NtUserInitialize
    02706 *
    02707 * 01-Dec-1993 andreva created.
    02708 * 01-Dec-1995 BradG   Modified to return handle to Media Change Event
    02709 \**************************************************************************/
    02710
    02711 BOOL TellGdiToGetReady();
    02712
    02713 NTSTATUS NtUserInitialize(
    02714     IN DWORD   dwVersion,
    02715     IN HANDLE  hPowerRequestEvent,
    02716     IN HANDLE  hMediaRequestEvent)
    02717 {
    02718     NTSTATUS Status;
    02719
    02720     TRACE_INIT(("Entering NtUserInitialize\n"));
    02721
    02722     /*
    02723      * Make sure we're not trying to load this twice.
    02724      */
    02725     if (gpepCSRSS != NULL) {
    02726         RIPMSG0(RIP_ERROR, "Can't initialize more than once");
    02727         return STATUS_UNSUCCESSFUL;
    02728     }
    02729
    02730     /*
    02731      * Check version number
    02732      */
    02733     if (dwVersion != USERCURRENTVERSION) {
    02734         KeBugCheckEx(WIN32K_INIT_OR_RIT_FAILURE,
    02735                      0,
    02736                      0,
    02737                      dwVersion,
    02738                      USERCURRENTVERSION);
    02739     }
    02740
    02741     /*
    02742      * Get the session ID from the EPROCESS structure
    02743      */
    02744     gSessionId = PsGetCurrentProcess()->SessionId;
    02745
    02746     UserAssert(gSessionId == 0 || gbRemoteSession == TRUE);
    02747
    02748     /*
    02749      * Initialize the power request list.
    02750      */
    02751     Status = InitializePowerRequestList(hPowerRequestEvent);
    02752     if (!NT_SUCCESS(Status)) {
    02753         return Status;
    02754     }
    02755
    02756     InitializeMediaChange(hMediaRequestEvent);
    02757
    02758     /*
    02759      * Save the system process structure.
    02760      */
    02761     gpepCSRSS = PsGetCurrentProcess();
    02762
    02763     if (!TellGdiToGetReady())
    02764     {
    02765         RIPMSG0(RIP_WARNING, "TellGdiToGetReady failed");
    02766         Status = STATUS_UNSUCCESSFUL;
    02767         return Status;
    02768     }
    02769
    02770     /*
    02771      * Allow CSR to read the screen
    02772      */
    02773     ((PW32PROCESS)gpepCSRSS->Win32Process)->W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED|W32PF_IOWINSTA);
    02774
    02775
    02776     Status = UserInitialize();
    02777
    02778     TRACE_INIT(("Leaving NtUserInitialize\n"));
    02779     return Status;
    02780 }
    02781
    02782 /**************************************************************************\
    02783 * NtUserProcessConnect
    02784 *
    02785 * 01-Dec-1993   Andreva     Created.
    02786 \**************************************************************************/
    02787
    02788 NTSTATUS NtUserProcessConnect(
    02789     IN HANDLE    hProcess,
    02790     IN OUT PVOID pConnectInfo,
    02791     IN ULONG     cbConnectInfo)
    02792 {
    02793     PEPROCESS    Process;
    02794     PUSERCONNECT pucConnect = (PUSERCONNECT)pConnectInfo;
    02795     USERCONNECT  ucLocal;
    02796     NTSTATUS     Status = STATUS_SUCCESS;
    02797
    02798
    02799     TRACE_INIT(("Entering NtUserProcessConnect\n"));
    02800
    02801     if (!pucConnect || (cbConnectInfo != sizeof(USERCONNECT))) {
    02802         return STATUS_UNSUCCESSFUL;
    02803     }
    02804
    02805     try {
    02806         ProbeForWrite(pucConnect, cbConnectInfo, sizeof(DWORD));
    02807
    02808         ucLocal = *pucConnect;
    02809     } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    02810         return GetExceptionCode();
    02811     }
    02812
    02813     /*
    02814      * Check client/server versions.
    02815      */
    02816     if (ucLocal.ulVersion != USERCURRENTVERSION) {
    02817
    02818         RIPMSG2(RIP_ERROR,
    02819             "Client version %lx > server version %lx\n",
    02820             ucLocal.ulVersion, USERCURRENTVERSION);
    02821         return STATUS_UNSUCCESSFUL;
    02822     }
    02823
    02824
    02825
    02826     if (ucLocal.dwDispatchCount != gDispatchTableValues) {
    02827         RIPMSG2(RIP_ERROR,
    02828             "!!!! Client Dispatch info %lX != Server %lX\n",
    02829             ucLocal.dwDispatchCount, gDispatchTableValues);
    02830     }
    02831
    02832
    02833     /*
    02834      * Reference the process.
    02835      */
    02836     Status = ObReferenceObjectByHandle(hProcess,
    02837                                        PROCESS_VM_OPERATION,
    02838                                        *PsProcessType,
    02839                                        UserMode,
    02840                                        &Process,
    02841                                        NULL);
    02842     if (!NT_SUCCESS(Status))
    02843         return Status;
    02844     /*
    02845      * Return client's view of shared data.
    02846      */
    02847     Status = InitMapSharedSection(Process, &ucLocal);
    02848
    02849     if (!NT_SUCCESS(Status)                       &&
    02850         (Status != STATUS_NO_MEMORY)              &&
    02851         (Status != STATUS_PROCESS_IS_TERMINATING) &&
    02852         (Status != STATUS_QUOTA_EXCEEDED)         &&
    02853         (Status != STATUS_COMMITMENT_LIMIT)) {
    02854
    02855         RIPMSG2(RIP_ERROR,
    02856               "Failed to map shared data into client %x, status = %x\n",
    02857               GetCurrentProcessId(), Status);
    02858     }
    02859
    02860     ObDereferenceObject(Process);
    02861
    02862     if (NT_SUCCESS(Status)) {
    02863
    02864         try {
    02865              *pucConnect = ucLocal;
    02866         } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
    02867             Status = GetExceptionCode();
    02868         }
    02869     }
    02870
    02871     TRACE_INIT(("Leaving NtUserProcessConnect\n"));
    02872
    02873     return Status;
    02874 }
    02875
    02876 /**************************************************************************\
    02877 * xxxUserProcessCallout
    02878 *
    02879 * 01-Dec-1993   andreva     Created.
    02880 \**************************************************************************/
    02881
    02882 NTSTATUS xxxUserProcessCallout(
    02883     IN PW32PROCESS Process,
    02884     IN BOOLEAN     Initialize)
    02885 {
    02886     NTSTATUS     Status = STATUS_SUCCESS;
    02887
    02888     if (Initialize) {
    02889
    02890         TRACE_INIT(("Entering xxxUserProcessCallout Initialize\n"));
    02891
    02892         UserAssert(gpresUser != NULL);
    02893         EnterCrit();
    02894
    02895         /*
    02896          * Initialize the important process level stuff.
    02897          */
    02898         Status = xxxInitProcessInfo(Process);
    02899
    02900         LeaveCrit();
    02901
    02902         if (Status == STATUS_SUCCESS) {
    02903
    02904             if (Process->Process &&
    02905                 Process->Process->Job &&
    02906                 Process->Process->Job->UIRestrictionsClass != 0) {
    02907
    02908                 WIN32_JOBCALLOUT_PARAMETERS Parms;
    02909
    02910                 PEJOB Job = Process->Process->Job;
    02911
    02912                 /*
    02913                  * aquire the job's lock and after that enter the user
    02914                  * critical section.
    02915                  */
    02916                 KeEnterCriticalRegion();
    02917                 ExAcquireResourceExclusive(&Job->JobLock, TRUE);
    02918
    02919                 Parms.Job = Job;
    02920                 Parms.CalloutType = PsW32JobCalloutAddProcess;
    02921                 Parms.Data = Process;
    02922
    02923                 UserAssert(Job->SessionId == Process->Process->SessionId);
    02924
    02925                 UserJobCallout(&Parms);
    02926
    02927                 ExReleaseResource(&Job->JobLock);
    02928                 KeLeaveCriticalRegion();
    02929             }
    02930         }
    02931     } else {
    02932
    02933         int  i;
    02934         PHE  phe;
    02935         PDCE *ppdce;
    02936         PDCE pdce;
    02937
    02938         TRACE_INIT(("Entering xxxUserProcessCallout Cleanup\n"));
    02939
    02940         UserAssert(gpresUser != NULL);
    02941
    02942         EnterCrit();
    02943
    02944 #if DBG
    02945         if (Process->Process == gpepCSRSS) {
    02946
    02947             /*
    02948              * CSRSS should be the last to go ...
    02949              */
    02950             UserAssert(gppiList->ppiNextRunning == NULL);
    02951         }
    02952 #endif // DBG
    02953
    02954         if (Process->Process && Process->Process->Job != NULL) {
    02955             RemoveProcessFromJob((PPROCESSINFO)Process);
    02956         }
    02957
    02958         /*
    02959          * DestroyProcessInfo will return TRUE if any threads ever
    02960          * connected.  If nothing ever connected, we needn't do
    02961          * this cleanup.
    02962          */
    02963         if (DestroyProcessInfo(Process)) {
    02964
    02965             /*
    02966              * See if we can compact the handle table.
    02967              */
    02968             i = giheLast;
    02969             phe = &gSharedInfo.aheList[giheLast];
    02970             while ((phe > &gSharedInfo.aheList[0]) && (phe->bType == TYPE_FREE)) {
    02971                 phe--;
    02972                 giheLast--;
    02973             }
    02974
    02975             /*
    02976              * Scan the DC cache to find any DC's that need to be destroyed.
    02977              */
    02978             for (ppdce = &gpDispInfo->pdceFirst; *ppdce != NULL; ) {
    02979
    02980                 pdce = *ppdce;
    02981                 if (pdce->DCX_flags & DCX_DESTROYTHIS)
    02982                     DestroyCacheDC(ppdce, pdce->hdc);
    02983
    02984                 /*
    02985                  * Step to the next DC.  If the DC was deleted, there
    02986                  * is no need to calculate address of the next entry.
    02987                  */
    02988                 if (pdce == *ppdce)
    02989                     ppdce = &pdce->pdceNext;
    02990             }
    02991         }
    02992
    02993         UserAssert(gpresUser != NULL);
    02994
    02995         LeaveCrit();
    02996     }
    02997
    02998     TRACE_INIT(("Leaving xxxUserProcessCallout\n"));
    02999
    03000     return Status;
    03001 }
    03002
    03003 /**************************************************************************\
    03004 * UserGetHDEV
    03005 *
    03006 * Provided as a means for GDI to get a hold of USER's hDev.
    03007 *
    03008 * 01-Jan-1996   ChrisWil    Created.
    03009 \**************************************************************************/
    03010
    03011 HDEV UserGetHDEV(VOID)
    03012 {
    03013
    03014     /*
    03015      * BUGBUG This is busted.
    03016      *        This need to return the device for the current desktop.
    03017      *        The graphics device may not be the same for all desktops.
    03018      *        -Andre
    03019      */
    03020     return gpDispInfo->hDev;
    03021 }
    03022
    03023 /**************************************************************************\
    03024 * _UserGetGlobalAtomTable
    03025 *
    03026 * This function is called by the kernel mode global atom manager to get the
    03027 * address of the current thread's global atom table.
    03028 *
    03029 * Pointer to the global atom table for the current thread or NULL if unable
    03030 * to access it.
    03031 *
    03032 *
    03033 \**************************************************************************/
    03034
    03035 PVOID UserGlobalAtomTableCallout(VOID)
    03036 {
    03037     PETHREAD       Thread;
    03038     PTHREADINFO    pti;
    03039     PWINDOWSTATION pwinsta;
    03040     PW32JOB        pW32Job;
    03041     PEJOB          Job;
    03042     PVOID          GlobalAtomTable = NULL;
    03043
    03044     Thread = PsGetCurrentThread();
    03045
    03046     pti = PtiFromThread(Thread);
    03047
    03048     EnterCrit();
    03049
    03050     /*
    03051      * For restricted threads access the atom table off of the job object
    03052      */
    03053     if (pti != NULL && IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
    03054
    03055         UserAssert(pti->ppi != NULL);
    03056
    03057         pW32Job = pti->ppi->pW32Job;
    03058
    03059         UserAssert(pW32Job != NULL && pW32Job->pAtomTable != NULL);
    03060
    03061         GlobalAtomTable = pW32Job->pAtomTable;
    03062
    03063         goto End;
    03064     }
    03065
    03066     Job = PsGetCurrentProcess()->Job;
    03067
    03068     /*
    03069      * Now handle the case where this si not a GUI thread/process
    03070      * but it is assigned to a job that has JOB_OBJECT_UILIMIT_GLOBALATOMS
    03071      * restrictions set. There is no easy way to convert this thread
    03072      * to GUI.
    03073      */
    03074     if (pti == NULL && Job != NULL &&
    03075         (Job->UIRestrictionsClass & JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
    03076
    03077         /*
    03078          * find the W32JOB in the global list
    03079          */
    03080         pW32Job = gpJobsList;
    03081
    03082         while (pW32Job) {
    03083             if (pW32Job->Job == Job) {
    03084                 break;
    03085             }
    03086             pW32Job = pW32Job->pNext;
    03087         }
    03088
    03089         UserAssert(pW32Job != NULL && pW32Job->pAtomTable != NULL);
    03090
    03091         GlobalAtomTable = pW32Job->pAtomTable;
    03092
    03093         goto End;
    03094     }
    03095
    03096 #if DBG
    03097     pwinsta = NULL;
    03098 #endif
    03099
    03100     if (NT_SUCCESS(ReferenceWindowStation(Thread,
    03101                                     PsGetCurrentProcess()->Win32WindowStation,
    03102                                     WINSTA_ACCESSGLOBALATOMS,
    03103                                     &pwinsta,
    03104                                     TRUE))) {
    03105         UserAssert(pwinsta != NULL);
    03106
    03107         GlobalAtomTable = pwinsta->pGlobalAtomTable;
    03108     }
    03109
    03110 End:
    03111     LeaveCrit();
    03112
    03113 #if DBG
    03114     if (GlobalAtomTable == NULL) {
    03115         RIPMSG1(RIP_WARNING,
    03116                 "_UserGetGlobalAtomTable: NULL Atom Table for pwinsta=0x%x",
    03117                 pwinsta);
    03118     }
    03119 #endif
    03120
    03121     return GlobalAtomTable;
    03122 }