Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3463 lines
98 KiB

/**************************************************************************\
* Module Name: server.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Server support routines for the CSR stuff. This basically performs the
* startup/initialization for USER.
*
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "prefetch.h"
extern WORD gDispatchTableValues;
BOOL gbUserInitialized;
/*
* Initialization Routines (external).
*/
NTSTATUS InitQEntryLookaside(VOID);
NTSTATUS InitSMSLookaside(VOID);
NTSTATUS InitCreateSharedSection(VOID);
NTSTATUS InitCreateObjectDirectory(VOID);
BOOL InitCreateUserSubsystem(VOID);
VOID InitFunctionTables(VOID);
VOID InitMessageTables(VOID);
VOID InitWindowMsgTable(PBYTE*, PUINT, CONST WORD*);
VOID VerifySyncOnlyMessages(VOID);
BOOL InitOLEFormats(VOID);
NTSTATUS Win32UserInitialize(VOID);
#pragma alloc_text(INIT, InitCreateSharedSection)
#pragma alloc_text(INIT, InitCreateUserCrit)
#pragma alloc_text(INIT, InitCreateObjectDirectory)
#pragma alloc_text(INIT, InitCreateUserSubsystem)
#pragma alloc_text(INIT, InitFunctionTables)
#pragma alloc_text(INIT, InitMessageTables)
#pragma alloc_text(INIT, InitWindowMsgTable)
#pragma alloc_text(INIT, VerifySyncOnlyMessages)
#pragma alloc_text(INIT, InitOLEFormats)
#pragma alloc_text(INIT, Win32UserInitialize)
/*
* Constants pertaining to the user-initialization.
*/
#define USRINIT_SHAREDSECT_SIZE 32
#define USRINIT_ATOMBUCKET_SIZE 37
#define USRINIT_WINDOWSECT_SIZE 512
#define USRINIT_NOIOSECT_SIZE 128
#define USRINIT_SHAREDSECT_BUFF_SIZE 640
#define USRINIT_SHAREDSECT_READ_SIZE (USRINIT_SHAREDSECT_BUFF_SIZE-33)
/***************************************************************************\
* Globals stored in the INIT section. These should only be accessed at
* load time!
\***************************************************************************/
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("INIT$Data")
#endif
CONST WCHAR szCHECKPOINT_PROP_NAME[] = L"SysCP";
CONST WCHAR szDDETRACK_PROP_NAME[] = L"SysDT";
CONST WCHAR szQOS_PROP_NAME[] = L"SysQOS";
CONST WCHAR szDDEIMP_PROP_NAME[] = L"SysDDEI";
CONST WCHAR szWNDOBJ_PROP_NAME[] = L"SysWNDO";
CONST WCHAR szIMELEVEL_PROP_NAME[] = L"SysIMEL";
CONST WCHAR szLAYER_PROP_NAME[] = L"SysLayer";
CONST WCHAR szUSER32[] = L"USER32";
CONST WCHAR szCONTEXTHELPIDPROP[] = L"SysCH";
CONST WCHAR szICONSM_PROP_NAME[] = L"SysICS";
CONST WCHAR szICON_PROP_NAME[] = ICON_PROP_NAME;
CONST WCHAR szSHELLHOOK[] = L"SHELLHOOK";
CONST WCHAR szACTIVATESHELLWINDOW[] = L"ACTIVATESHELLWINDOW";
CONST WCHAR szOTHERWINDOWCREATED[] = L"OTHERWINDOWCREATED";
CONST WCHAR szOTHERWINDOWDESTROYED[] = L"OTHERWINDOWDESTROYED";
CONST WCHAR szOLEMAINTHREADWNDCLASS[] = L"OleMainThreadWndClass";
CONST WCHAR szFLASHWSTATE[] = L"FlashWState";
#ifdef HUNGAPP_GHOSTING
CONST WCHAR szGHOST[] = L"Ghost";
#endif
CONST WCHAR szSHADOW[] = L"SysShadow";
/***************************************************************************\
* Message Tables
*
* DefDlgProc
* MenuWndProc
* ScrollBarWndProc
* StaticWndProc
* ButtonWndProc
* ListboxWndProc
* ComboWndProc
* EditWndProc
* DefWindowMsgs
* DefWindowSpecMsgs
*
* These are used in InitMessageTables() to initialize gSharedInfo.awmControl[]
* using the INITMSGTABLE() macro.
*
* 25-Aug-1995 ChrisWil Created comment block.
\***************************************************************************/
CONST WORD gawDefDlgProc[] = {
WM_COMPAREITEM,
WM_VKEYTOITEM,
WM_CHARTOITEM,
WM_INITDIALOG,
WM_QUERYDRAGICON,
WM_CTLCOLOR,
WM_CTLCOLORMSGBOX,
WM_CTLCOLOREDIT,
WM_CTLCOLORLISTBOX,
WM_CTLCOLORBTN,
WM_CTLCOLORDLG,
WM_CTLCOLORSCROLLBAR,
WM_CTLCOLORSTATIC,
WM_ERASEBKGND,
WM_SHOWWINDOW,
WM_SYSCOMMAND,
WM_SYSKEYDOWN,
WM_ACTIVATE,
WM_SETFOCUS,
WM_CLOSE,
WM_NCDESTROY,
WM_FINALDESTROY,
DM_REPOSITION,
DM_SETDEFID,
DM_GETDEFID,
WM_NEXTDLGCTL,
WM_ENTERMENULOOP,
WM_LBUTTONDOWN,
WM_NCLBUTTONDOWN,
WM_GETFONT,
WM_NOTIFYFORMAT,
WM_INPUTLANGCHANGEREQUEST,
0
};
CONST WORD gawMenuWndProc[] = {
WM_NCCREATE,
WM_FINALDESTROY,
WM_PAINT,
WM_NCCALCSIZE,
WM_CHAR,
WM_SYSCHAR,
WM_KEYDOWN,
WM_SYSKEYDOWN,
WM_TIMER,
MN_SETHMENU,
MN_SIZEWINDOW,
MN_OPENHIERARCHY,
MN_CLOSEHIERARCHY,
MN_SELECTITEM,
MN_SELECTFIRSTVALIDITEM,
MN_CANCELMENUS,
MN_FINDMENUWINDOWFROMPOINT,
MN_SHOWPOPUPWINDOW,
MN_BUTTONDOWN,
MN_MOUSEMOVE,
MN_BUTTONUP,
MN_SETTIMERTOOPENHIERARCHY,
WM_ACTIVATE,
MN_GETHMENU,
MN_DBLCLK,
MN_ACTIVATEPOPUP,
MN_ENDMENU,
MN_DODRAGDROP,
WM_ACTIVATEAPP,
WM_MOUSELEAVE,
WM_SIZE,
WM_MOVE,
WM_NCHITTEST,
WM_NCPAINT,
WM_PRINT,
WM_PRINTCLIENT,
WM_ERASEBKGND,
WM_WINDOWPOSCHANGING,
WM_WINDOWPOSCHANGED,
0
};
CONST WORD gawDesktopWndProc[] = {
WM_PAINT,
WM_ERASEBKGND,
0
};
CONST WORD gawScrollBarWndProc[] = {
WM_CREATE,
WM_SETFOCUS,
WM_KILLFOCUS,
WM_ERASEBKGND,
WM_PAINT,
WM_LBUTTONDBLCLK,
WM_LBUTTONDOWN,
WM_KEYUP,
WM_KEYDOWN,
WM_ENABLE,
SBM_ENABLE_ARROWS,
SBM_SETPOS,
SBM_SETRANGEREDRAW,
SBM_SETRANGE,
SBM_SETSCROLLINFO,
SBM_GETSCROLLINFO,
SBM_GETSCROLLBARINFO,
WM_PRINTCLIENT,
WM_MOUSEMOVE,
WM_MOUSELEAVE,
0
};
CONST WORD gawStaticWndProc[] = {
STM_GETICON,
STM_GETIMAGE,
STM_SETICON,
STM_SETIMAGE,
WM_ERASEBKGND,
WM_PAINT,
WM_PRINTCLIENT,
WM_CREATE,
WM_DESTROY,
WM_NCCREATE,
WM_NCDESTROY,
WM_FINALDESTROY,
WM_NCHITTEST,
WM_LBUTTONDOWN,
WM_NCLBUTTONDOWN,
WM_LBUTTONDBLCLK,
WM_NCLBUTTONDBLCLK,
WM_SETTEXT,
WM_ENABLE,
WM_GETDLGCODE,
WM_SETFONT,
WM_GETFONT,
WM_GETTEXT,
WM_TIMER,
WM_INPUTLANGCHANGEREQUEST,
WM_UPDATEUISTATE,
0
};
CONST WORD gawButtonWndProc[] = {
WM_NCHITTEST,
WM_ERASEBKGND,
WM_PRINTCLIENT,
WM_PAINT,
WM_SETFOCUS,
WM_GETDLGCODE,
WM_CAPTURECHANGED,
WM_KILLFOCUS,
WM_LBUTTONDBLCLK,
WM_LBUTTONUP,
WM_MOUSEMOVE,
WM_LBUTTONDOWN,
WM_CHAR,
BM_CLICK,
WM_KEYDOWN,
WM_KEYUP,
WM_SYSKEYUP,
BM_GETSTATE,
BM_SETSTATE,
BM_GETCHECK,
BM_SETCHECK,
BM_SETSTYLE,
WM_SETTEXT,
WM_ENABLE,
WM_SETFONT,
WM_GETFONT,
BM_GETIMAGE,
BM_SETIMAGE,
WM_NCDESTROY,
WM_FINALDESTROY,
WM_NCCREATE,
WM_INPUTLANGCHANGEREQUEST,
WM_UPDATEUISTATE,
0
};
CONST WORD gawListboxWndProc[] = {
LB_GETTOPINDEX,
LB_SETTOPINDEX,
WM_SIZE,
WM_ERASEBKGND,
LB_RESETCONTENT,
WM_TIMER,
WM_MOUSEMOVE,
WM_MBUTTONDOWN,
WM_LBUTTONDOWN,
WM_LBUTTONUP,
WM_LBUTTONDBLCLK,
WM_CAPTURECHANGED,
LBCB_STARTTRACK,
LBCB_ENDTRACK,
WM_PRINTCLIENT,
WM_PAINT,
WM_NCDESTROY,
WM_FINALDESTROY,
WM_SETFOCUS,
WM_KILLFOCUS,
WM_VSCROLL,
WM_HSCROLL,
WM_GETDLGCODE,
WM_CREATE,
WM_SETREDRAW,
WM_ENABLE,
WM_SETFONT,
WM_GETFONT,
WM_DRAGSELECT,
WM_DRAGLOOP,
WM_DRAGMOVE,
WM_DROPFILES,
WM_QUERYDROPOBJECT,
WM_DROPOBJECT,
LB_GETITEMRECT,
LB_GETITEMDATA,
LB_SETITEMDATA,
LB_ADDSTRINGUPPER,
LB_ADDSTRINGLOWER,
LB_ADDSTRING,
LB_INSERTSTRINGUPPER,
LB_INSERTSTRINGLOWER,
LB_INSERTSTRING,
LB_INITSTORAGE,
LB_DELETESTRING,
LB_DIR,
LB_ADDFILE,
LB_SETSEL,
LB_SETCURSEL,
LB_GETSEL,
LB_GETCURSEL,
LB_SELITEMRANGE,
LB_SELITEMRANGEEX,
LB_GETTEXTLEN,
LB_GETTEXT,
LB_GETCOUNT,
LB_SETCOUNT,
LB_SELECTSTRING,
LB_FINDSTRING,
LB_GETLOCALE,
LB_SETLOCALE,
WM_KEYDOWN,
WM_CHAR,
LB_GETSELITEMS,
LB_GETSELCOUNT,
LB_SETTABSTOPS,
LB_GETHORIZONTALEXTENT,
LB_SETHORIZONTALEXTENT,
LB_SETCOLUMNWIDTH,
LB_SETANCHORINDEX,
LB_GETANCHORINDEX,
LB_SETCARETINDEX,
LB_GETCARETINDEX,
LB_SETITEMHEIGHT,
LB_GETITEMHEIGHT,
LB_FINDSTRINGEXACT,
LB_ITEMFROMPOINT,
LB_SETLOCALE,
LB_GETLOCALE,
LBCB_CARETON,
LBCB_CARETOFF,
LB_GETLISTBOXINFO,
WM_NCCREATE,
WM_WINDOWPOSCHANGED,
WM_MOUSEWHEEL,
WM_STYLECHANGED,
WM_STYLECHANGING,
0
};
CONST WORD gawComboWndProc[] = {
CBEC_KILLCOMBOFOCUS,
WM_COMMAND,
WM_CTLCOLORMSGBOX,
WM_CTLCOLOREDIT,
WM_CTLCOLORLISTBOX,
WM_CTLCOLORBTN,
WM_CTLCOLORDLG,
WM_CTLCOLORSCROLLBAR,
WM_CTLCOLORSTATIC,
WM_CTLCOLOR,
WM_GETTEXT,
WM_GETTEXTLENGTH,
WM_CLEAR,
WM_CUT,
WM_PASTE,
WM_COPY,
WM_SETTEXT,
WM_CREATE,
WM_ERASEBKGND,
WM_GETFONT,
WM_PRINT,
WM_PRINTCLIENT,
WM_PAINT,
WM_GETDLGCODE,
WM_SETFONT,
WM_SYSKEYDOWN,
WM_KEYDOWN,
WM_CHAR,
WM_LBUTTONDBLCLK,
WM_LBUTTONDOWN,
WM_CAPTURECHANGED,
WM_LBUTTONUP,
WM_MOUSEMOVE,
WM_NCDESTROY,
WM_FINALDESTROY,
WM_SETFOCUS,
WM_KILLFOCUS,
WM_SETREDRAW,
WM_ENABLE,
WM_SIZE,
CB_GETDROPPEDSTATE,
CB_GETDROPPEDCONTROLRECT,
CB_SETDROPPEDWIDTH,
CB_GETDROPPEDWIDTH,
CB_DIR,
CB_SETEXTENDEDUI,
CB_GETEXTENDEDUI,
CB_GETEDITSEL,
CB_LIMITTEXT,
CB_SETEDITSEL,
CB_ADDSTRING,
CB_DELETESTRING,
CB_INITSTORAGE,
CB_SETTOPINDEX,
CB_GETTOPINDEX,
CB_GETCOUNT,
CB_GETCURSEL,
CB_GETLBTEXT,
CB_GETLBTEXTLEN,
CB_INSERTSTRING,
CB_RESETCONTENT,
CB_GETHORIZONTALEXTENT,
CB_SETHORIZONTALEXTENT,
CB_FINDSTRING,
CB_FINDSTRINGEXACT,
CB_SELECTSTRING,
CB_SETCURSEL,
CB_GETITEMDATA,
CB_SETITEMDATA,
CB_SETITEMHEIGHT,
CB_GETITEMHEIGHT,
CB_SHOWDROPDOWN,
CB_SETLOCALE,
CB_GETLOCALE,
CB_GETCOMBOBOXINFO,
WM_MEASUREITEM,
WM_DELETEITEM,
WM_DRAWITEM,
WM_COMPAREITEM,
WM_NCCREATE,
WM_HELP,
WM_MOUSEWHEEL,
WM_MOUSELEAVE,
WM_STYLECHANGED,
WM_STYLECHANGING,
WM_UPDATEUISTATE,
0
};
CONST WORD gawEditWndProc[] = {
EM_CANUNDO,
EM_CHARFROMPOS,
EM_EMPTYUNDOBUFFER,
EM_FMTLINES,
EM_GETFIRSTVISIBLELINE,
EM_GETFIRSTVISIBLELINE,
EM_GETHANDLE,
EM_GETLIMITTEXT,
EM_GETLINE,
EM_GETLINECOUNT,
EM_GETMARGINS,
EM_GETMODIFY,
EM_GETPASSWORDCHAR,
EM_GETRECT,
EM_GETSEL,
EM_GETWORDBREAKPROC,
EM_SETIMESTATUS,
EM_GETIMESTATUS,
EM_LINEFROMCHAR,
EM_LINEINDEX,
EM_LINELENGTH,
EM_LINESCROLL,
EM_POSFROMCHAR,
EM_REPLACESEL,
EM_SCROLL,
EM_SCROLLCARET,
EM_SETHANDLE,
EM_SETLIMITTEXT,
EM_SETMARGINS,
EM_SETMODIFY,
EM_SETPASSWORDCHAR,
EM_SETREADONLY,
EM_SETRECT,
EM_SETRECTNP,
EM_SETSEL,
EM_SETTABSTOPS,
EM_SETWORDBREAKPROC,
EM_UNDO,
WM_CAPTURECHANGED,
WM_CHAR,
WM_CLEAR,
WM_CONTEXTMENU,
WM_COPY,
WM_CREATE,
WM_CUT,
WM_ENABLE,
WM_ERASEBKGND,
WM_GETDLGCODE,
WM_GETFONT,
WM_GETTEXT,
WM_GETTEXTLENGTH,
WM_HSCROLL,
WM_IME_STARTCOMPOSITION,
WM_IME_ENDCOMPOSITION,
WM_IME_COMPOSITION,
WM_IME_SETCONTEXT,
WM_IME_NOTIFY,
WM_IME_COMPOSITIONFULL,
WM_IME_SELECT,
WM_IME_CHAR,
WM_IME_REQUEST,
WM_INPUTLANGCHANGE,
WM_KEYUP,
WM_KEYDOWN,
WM_KILLFOCUS,
WM_MBUTTONDOWN,
WM_LBUTTONDBLCLK,
WM_LBUTTONDOWN,
WM_LBUTTONUP,
WM_MOUSEMOVE,
WM_NCCREATE,
WM_NCDESTROY,
WM_RBUTTONDOWN,
WM_RBUTTONUP,
WM_FINALDESTROY,
WM_PAINT,
WM_PASTE,
WM_PRINTCLIENT,
WM_SETFOCUS,
WM_SETFONT,
WM_SETREDRAW,
WM_SETTEXT,
WM_SIZE,
WM_STYLECHANGED,
WM_STYLECHANGING,
WM_SYSCHAR,
WM_SYSKEYDOWN,
WM_SYSTIMER,
WM_UNDO,
WM_VSCROLL,
WM_MOUSEWHEEL,
0
};
CONST WORD gawImeWndProc[] = {
WM_ERASEBKGND,
WM_PAINT,
WM_DESTROY,
WM_NCDESTROY,
WM_FINALDESTROY,
WM_CREATE,
WM_IME_SYSTEM,
WM_IME_SELECT,
WM_IME_CONTROL,
WM_IME_SETCONTEXT,
WM_IME_NOTIFY,
WM_IME_COMPOSITION,
WM_IME_STARTCOMPOSITION,
WM_IME_ENDCOMPOSITION,
WM_IME_REQUEST,
WM_COPYDATA,
0
};
/*
* This array is for all the messages that need to be passed straight
* across to the server for handling.
*/
CONST WORD gawDefWindowMsgs[] = {
WM_GETHOTKEY,
WM_SETHOTKEY,
WM_SETREDRAW,
WM_SETTEXT,
WM_PAINT,
WM_CLOSE,
WM_ERASEBKGND,
WM_CANCELMODE,
WM_SETCURSOR,
WM_PAINTICON,
WM_ICONERASEBKGND,
WM_DRAWITEM,
WM_KEYF1,
WM_ISACTIVEICON,
WM_NCCREATE,
WM_SETICON,
WM_NCCALCSIZE,
WM_NCPAINT,
WM_NCACTIVATE,
WM_NCMOUSEMOVE,
WM_NCRBUTTONUP,
WM_NCRBUTTONDOWN,
#ifndef LAME_BUTTON
WM_NCLBUTTONDOWN,
#endif
WM_NCLBUTTONUP,
WM_NCLBUTTONDBLCLK,
WM_KEYUP,
WM_SYSKEYUP,
#ifndef LAME_BUTTON
WM_SYSCHAR,
WM_SYSCOMMAND,
#endif
WM_QUERYDROPOBJECT,
WM_CLIENTSHUTDOWN,
WM_SYNCPAINT,
WM_PRINT,
WM_GETICON,
WM_CONTEXTMENU,
WM_SYSMENU,
WM_INPUTLANGCHANGEREQUEST,
WM_INPUTLANGCHANGE,
WM_UPDATEUISTATE,
WM_NCUAHDRAWCAPTION,
WM_NCUAHDRAWFRAME,
WM_UAHINIT,
0
};
/*
* This array is for all messages that can be handled with some special
* code by the client. DefWindowProcWorker returns 0 for all messages
* that aren't in this array or the one above.
*/
CONST WORD gawDefWindowSpecMsgs[] = {
WM_ACTIVATE,
WM_GETTEXT,
WM_GETTEXTLENGTH,
WM_RBUTTONUP,
WM_QUERYENDSESSION,
WM_QUERYOPEN,
WM_SHOWWINDOW,
WM_MOUSEACTIVATE,
WM_HELP,
WM_VKEYTOITEM,
WM_CHARTOITEM,
WM_KEYDOWN,
#ifdef LAME_BUTTON
WM_SYSCOMMAND,
WM_SYSCHAR,
#endif
WM_SYSKEYDOWN,
WM_UNICHAR,
WM_DROPOBJECT,
WM_WINDOWPOSCHANGING,
WM_WINDOWPOSCHANGED,
WM_KLUDGEMINRECT,
WM_CTLCOLOR,
WM_CTLCOLORMSGBOX,
WM_CTLCOLOREDIT,
WM_CTLCOLORLISTBOX,
WM_CTLCOLORBTN,
WM_CTLCOLORDLG,
WM_CTLCOLORSCROLLBAR,
WM_NCHITTEST,
#ifdef LAME_BUTTON
WM_NCLBUTTONDOWN,
#endif
WM_NCXBUTTONUP,
WM_CTLCOLORSTATIC,
WM_NOTIFYFORMAT,
WM_DEVICECHANGE,
WM_POWERBROADCAST,
WM_MOUSEWHEEL,
WM_XBUTTONUP,
WM_IME_KEYDOWN,
WM_IME_KEYUP,
WM_IME_CHAR,
WM_IME_COMPOSITION,
WM_IME_STARTCOMPOSITION,
WM_IME_ENDCOMPOSITION,
WM_IME_COMPOSITIONFULL,
WM_IME_SETCONTEXT,
WM_IME_CONTROL,
WM_IME_NOTIFY,
WM_IME_SELECT,
WM_IME_SYSTEM,
WM_LPKDRAWSWITCHWND,
WM_QUERYDRAGICON,
WM_CHANGEUISTATE,
WM_QUERYUISTATE,
WM_APPCOMMAND,
0
};
static CONST LPCWSTR lpszOLEFormats[] = {
L"ObjectLink",
L"OwnerLink",
L"Native",
L"Binary",
L"FileName",
L"FileNameW",
L"NetworkName",
L"DataObject",
L"Embedded Object",
L"Embed Source",
L"Custom Link Source",
L"Link Source",
L"Object Descriptor",
L"Link Source Descriptor",
L"OleDraw",
L"PBrush",
L"MSDraw",
L"Ole Private Data",
L"Screen Picture",
L"OleClipboardPersistOnFlush",
L"MoreOlePrivateData"
};
static CONST LPCWSTR lpszControls[] = {
L"Button",
L"Edit",
L"Static",
L"ListBox",
L"ScrollBar",
L"ComboBox",
L"MDIClient",
L"ComboLBox",
L"DDEMLEvent",
L"DDEMLMom",
L"DMGClass",
L"DDEMLAnsiClient",
L"DDEMLUnicodeClient",
L"DDEMLAnsiServer",
L"DDEMLUnicodeServer",
L"IME",
};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif
/***************************************************************************\
* DispatchServerMessage
*
*
* 19-Aug-1992 MikeKe Created
\***************************************************************************/
#define WRAPPFN(pfn, type) \
LRESULT xxxWrap ## pfn( \
PWND pwnd, \
UINT message, \
WPARAM wParam, \
LPARAM lParam, \
ULONG_PTR xParam) \
{ \
UNREFERENCED_PARAMETER(xParam); \
\
return xxx ## pfn((type)pwnd, message, wParam, lParam); \
}
WRAPPFN(SBWndProc, PSBWND)
WRAPPFN(MenuWindowProc, PWND)
WRAPPFN(DesktopWndProc, PWND);
WRAPPFN(RealDefWindowProc, PWND)
WRAPPFN(SwitchWndProc, PWND)
LRESULT xxxWrapSendMessageCallback(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
SNDMSGCALLBACK smcb;
TL tlpwnd;
LRESULT lRet = 0;
NTSTATUS Status = STATUS_SUCCESS;
UserAssert (xParam != 0L);
/*
* Prevent apps from setting hi 16 bits so we can use them internally.
*/
if (message & MSGFLAG_MASK) {
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
return 0;
}
/*
* Probe all read arguments
*/
try {
ProbeForWrite((PVOID)xParam, sizeof(smcb), sizeof(ULONG));
smcb = *(PSNDMSGCALLBACK)xParam;
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
Status = GetExceptionCode();
}
if ( !NT_SUCCESS(Status) ) {
return 0;
}
if (pwnd != PWND_BROADCAST)
ThreadLockAlways(pwnd, &tlpwnd);
lRet = (LRESULT)xxxSendMessageCallback(pwnd,
message,
wParam,
lParam,
smcb.lpResultCallBack,
smcb.dwData,
TRUE);
if (pwnd != PWND_BROADCAST)
ThreadUnlock(&tlpwnd);
return lRet;
}
LRESULT xxxWrapSendNotifyMessage(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
TL tlpwnd;
LRESULT lRet = 0;
UNREFERENCED_PARAMETER(xParam);
if (message & MSGFLAG_MASK) {
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
return 0;
}
if (pwnd != PWND_BROADCAST) {
ThreadLockAlways(pwnd, &tlpwnd);
}
lRet = (LRESULT)xxxSendNotifyMessage(pwnd,
message,
wParam,
lParam);
if (pwnd != PWND_BROADCAST) {
ThreadUnlock(&tlpwnd);
}
return lRet;
}
LRESULT xxxWrapSendMessage(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
UNREFERENCED_PARAMETER(xParam);
return xxxSendMessageTimeout(pwnd,
message,
wParam,
lParam,
SMTO_NORMAL,
0,
NULL);
}
LRESULT xxxWrapSendMessageBSM(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
BROADCASTSYSTEMMSGPARAMS bsmParams;
LRESULT lRet;
try {
ProbeForWriteBroadcastSystemMsgParams((LPBROADCASTSYSTEMMSGPARAMS)xParam);
RtlCopyMemory(&bsmParams, (LPBROADCASTSYSTEMMSGPARAMS)xParam, sizeof(BROADCASTSYSTEMMSGPARAMS));
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return 0;
}
/*
* If this broadcast is going to all desktops, make sure the thread has
* sufficient privileges. Do the check here, so we don't effect kernel
* generated broadcasts (i.e power messages).
*/
if (bsmParams.dwRecipients & (BSM_ALLDESKTOPS)) {
if (!IsPrivileged(&psTcb)) {
bsmParams.dwRecipients &= ~(BSM_ALLDESKTOPS);
try {
RtlCopyMemory((LPBROADCASTSYSTEMMSGPARAMS)xParam, &bsmParams, sizeof(BROADCASTSYSTEMMSGPARAMS));
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
/* empty */
}
}
}
lRet = xxxSendMessageBSM(pwnd,
message,
wParam,
lParam,
&bsmParams);
/*
* If our query was denied, return who denied the query.
*/
if (lRet == 0 && (bsmParams.dwFlags & BSF_QUERY)) {
try {
RtlCopyMemory((LPBROADCASTSYSTEMMSGPARAMS)xParam, &bsmParams, sizeof(BROADCASTSYSTEMMSGPARAMS));
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return 0;
}
}
return lRet;
}
/***************************************************************************\
* xxxUnusedFunctionId
*
* This function is catches attempts to access invalid entries in the server
* side function dispatch table.
*
\***************************************************************************/
LRESULT xxxUnusedFunctionId(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
UNREFERENCED_PARAMETER(pwnd);
UNREFERENCED_PARAMETER(message);
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(xParam);
UserAssert(FALSE);
return 0;
}
/***************************************************************************\
* xxxWrapCallWindowProc
*
* Warning should only be called with valid CallProc Handles or the
* EditWndProc special handlers.
*
*
* 21-Apr-1993 JohnC Created
\***************************************************************************/
LRESULT xxxWrapCallWindowProc(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
ULONG_PTR xParam)
{
PCALLPROCDATA pCPD;
LRESULT lRet = 0;
if (pCPD = HMValidateHandleNoRip((PVOID)xParam, TYPE_CALLPROC)) {
lRet = ScSendMessage(pwnd,
message,
wParam,
lParam,
pCPD->pfnClientPrevious,
gpsi->apfnClientW.pfnDispatchMessage,
(pCPD->wType & CPD_UNICODE_TO_ANSI) ?
SCMS_FLAGS_ANSI : 0);
} else {
/*
* If it is not a real call proc handle it must be a special
* handler for editwndproc or regular EditWndProc
*/
lRet = ScSendMessage(pwnd,
message,
wParam,
lParam,
xParam,
gpsi->apfnClientA.pfnDispatchMessage,
(xParam == (ULONG_PTR)gpsi->apfnClientA.pfnEditWndProc) ?
SCMS_FLAGS_ANSI : 0);
}
return lRet;
}
#if DBG
VOID VerifySyncOnlyMessages(VOID)
{
int i;
TRACE_INIT(("UserInit: Verify Sync Only Messages\n"));
/*
* There are a couple of thunks that just pass parameters. There are other
* thunks besides SfnDWORD that do a straight pass through because they
* do other processing beside the wparam and lparam
*/
/*
* Allow posting of LB_DIR and CB_DIR because DlgDirList allows a DDL_POSTMSGS
* flag that makes the API post the messages. This should be OK as long as we
* don't handle these messages in the kernel. NT 3.51 allowed posting these.
*/
for (i=0; i<WM_USER; i++) {
if ( i != LB_DIR
&& i != CB_DIR
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnDWORD)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnNCDESTROY)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMCHAR)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINWPARAMDBCSCHAR)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnSENTDDEMSG)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnPOWERBROADCAST)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnLOGONNOTIFY)
&& (gapfnScSendMessage[MessageTable[i].iFunction] != SfnINDESTROYCLIPBRD)) {
if (!(TESTSYNCONLYMESSAGE(i,0x8000)))
RIPMSG1(RIP_ERROR, "InitSyncOnly: is this message sync-only 0x%lX", i);
} else {
if (TESTSYNCONLYMESSAGE(i,0))
RIPMSG1(RIP_VERBOSE, "InitSyncOnly: is this message not sync-only 0x%lX", i);
}
}
}
#endif // DBG
/***************************************************************************\
* InitWindowMsgTables
*
* This function generates a bit-array lookup table from a list of messages.
* The lookup table is used to determine whether the message needs to be
* passed over to the server for handling or whether it can be handled
* directly on the client.
*
* LATER: Some memory (a couple hundred bytes per process) could be saved
* by putting this in the shared read-only heap.
*
*
* 27-Mar-1992 DarrinM Created.
* 06-Dec-1993 MikeKe Added support for all of our window procs.
\***************************************************************************/
VOID InitWindowMsgTable(
PBYTE *ppbyte,
PUINT pmax,
CONST WORD *pw)
{
UINT i;
WORD msg;
UINT cbTable;
*pmax = 0;
for (i = 0; (msg = pw[i]) != 0; i++) {
if (msg > *pmax)
*pmax = msg;
}
cbTable = *pmax / 8 + 1;
*ppbyte = SharedAlloc(cbTable);
if (*ppbyte == NULL) {
return;
}
for (i = 0; (msg = pw[i]) != 0; i++) {
(*ppbyte)[msg / 8] |= (BYTE)(1 << (msg & 7));
}
}
/***************************************************************************\
* InitFunctionTables
*
* Initialize the procedures and function tables.
*
*
* 25-Aug-1995 ChrisWil Created comment block.
\***************************************************************************/
VOID InitFunctionTables(
VOID)
{
UINT i;
TRACE_INIT(("UserInit: Initialize Function Tables\n"));
UserAssert(sizeof(CLIENTINFO) <= sizeof(NtCurrentTeb()->Win32ClientInfo));
/*
* This table is used to convert from server procs to client procs.
*/
STOCID(FNID_SCROLLBAR) = (WNDPROC_PWND)xxxSBWndProc;
STOCID(FNID_ICONTITLE) = xxxDefWindowProc;
STOCID(FNID_MENU) = xxxMenuWindowProc;
STOCID(FNID_DESKTOP) = xxxDesktopWndProc;
STOCID(FNID_DEFWINDOWPROC) = xxxDefWindowProc;
STOCID(FNID_MESSAGEWND) = xxxDefWindowProc;
/*
* This table is used to determine the number minimum number of reserved
* windows words required for the server proc.
*/
CBFNID(FNID_SCROLLBAR) = sizeof(SBWND);
CBFNID(FNID_ICONTITLE) = sizeof(WND);
CBFNID(FNID_MENU) = sizeof(MENUWND);
/*
* Initialize this data structure (api function table).
*/
for (i = 0; i < FNID_ARRAY_SIZE; i++) {
FNID((i + FNID_START)) = xxxUnusedFunctionId;
}
FNID(FNID_SCROLLBAR) = xxxWrapSBWndProc;
FNID(FNID_ICONTITLE) = xxxWrapRealDefWindowProc;
FNID(FNID_MENU) = xxxWrapMenuWindowProc;
FNID(FNID_DESKTOP) = xxxWrapDesktopWndProc;
FNID(FNID_DEFWINDOWPROC) = xxxWrapRealDefWindowProc;
FNID(FNID_MESSAGEWND) = xxxWrapRealDefWindowProc;
FNID(FNID_SENDMESSAGE) = xxxWrapSendMessage;
FNID(FNID_HKINLPCWPEXSTRUCT) = fnHkINLPCWPEXSTRUCT;
FNID(FNID_HKINLPCWPRETEXSTRUCT) = fnHkINLPCWPRETEXSTRUCT;
FNID(FNID_SENDMESSAGEFF) = xxxSendMessageFF;
FNID(FNID_SENDMESSAGEEX) = xxxSendMessageEx;
FNID(FNID_CALLWINDOWPROC) = xxxWrapCallWindowProc;
FNID(FNID_SENDMESSAGEBSM) = xxxWrapSendMessageBSM;
FNID(FNID_SWITCH) = xxxWrapSwitchWndProc;
FNID(FNID_SENDNOTIFYMESSAGE) = xxxWrapSendNotifyMessage;
FNID(FNID_SENDMESSAGECALLBACK) = xxxWrapSendMessageCallback;
#if DBG
{
PULONG_PTR pdw;
/*
* Make sure that everyone got initialized.
*/
for (pdw = (PULONG_PTR)&STOCID(FNID_START);
(ULONG_PTR)pdw<(ULONG_PTR)(&STOCID(FNID_WNDPROCEND)); pdw++) {
UserAssert(*pdw);
}
for (pdw=(PULONG_PTR)&FNID(FNID_START);
(ULONG_PTR)pdw<(ULONG_PTR)(&FNID(FNID_WNDPROCEND)); pdw++) {
UserAssert(*pdw);
}
}
#endif
}
/***************************************************************************\
* InitMessageTables
*
* Initialize the message tables.
*
* 25-Aug-1995 ChrisWil Created.
\***************************************************************************/
VOID InitMessageTables(
VOID)
{
TRACE_INIT(("UserInit: Initialize Message Tables\n"));
#define INITMSGTABLE(member, procname) \
InitWindowMsgTable(&(gSharedInfo.member.abMsgs), \
&(gSharedInfo.member.maxMsgs), \
gaw ## procname);
INITMSGTABLE(DefWindowMsgs, DefWindowMsgs);
INITMSGTABLE(DefWindowSpecMsgs, DefWindowSpecMsgs);
INITMSGTABLE(awmControl[FNID_DIALOG - FNID_START], DefDlgProc);
INITMSGTABLE(awmControl[FNID_SCROLLBAR - FNID_START], ScrollBarWndProc);
INITMSGTABLE(awmControl[FNID_MENU - FNID_START], MenuWndProc);
INITMSGTABLE(awmControl[FNID_DESKTOP - FNID_START], DesktopWndProc);
INITMSGTABLE(awmControl[FNID_STATIC - FNID_START], StaticWndProc);
INITMSGTABLE(awmControl[FNID_BUTTON - FNID_START], ButtonWndProc);
INITMSGTABLE(awmControl[FNID_LISTBOX - FNID_START], ListboxWndProc);
INITMSGTABLE(awmControl[FNID_COMBOBOX - FNID_START], ComboWndProc);
INITMSGTABLE(awmControl[FNID_COMBOLISTBOX - FNID_START], ListboxWndProc);
INITMSGTABLE(awmControl[FNID_EDIT - FNID_START], EditWndProc);
INITMSGTABLE(awmControl[FNID_IME - FNID_START], ImeWndProc);
}
/***************************************************************************\
* InitOLEFormats
*
* OLE performance hack. OLE was previously having to call the server 15
* times for clipboard formats and another 15 LPC calls for the global atoms.
* Now we preregister them. We also assert they are in order so OLE only has
* to query the first to know them all. We call AddAtom directly instead of
* RegisterClipboardFormat.
*
* 25-Aug-1995 ChrisWil Created.
\***************************************************************************/
BOOL InitOLEFormats(
VOID)
{
UINT idx;
ATOM a1;
ATOM a2;
BOOL fSuccess = TRUE;
TRACE_INIT(("UserInit: Initialize OLE Formats\n"));
a1 = UserAddAtom(lpszOLEFormats[0], TRUE);
for (idx = 1; idx < ARRAY_SIZE(lpszOLEFormats); idx++) {
a2 = UserAddAtom(lpszOLEFormats[idx], TRUE);
fSuccess &= !!a2;
UserAssert(((a1 + 1) == a2) && (a1 = a2));
}
if (!fSuccess) {
RIPMSG0(RIP_ERROR, "InitOLEFormats: at least one atom not registered");
}
return fSuccess;
}
#if DBG
/***************************************************************************\
* InitGlobalRIPFlags (CHK only).
*
* This initializes the global RIP flags from the registry.
*
* 25-Aug-1995 ChrisWil Created.
\***************************************************************************/
VOID InitGlobalRIPFlags(
VOID)
{
UINT idx;
UINT nCount;
DWORD dwFlag;
static CONST struct {
LPWSTR lpszKey;
DWORD dwDef;
DWORD dwFlag;
} aRIPFlags[] = {
{L"fPromptOnError" , 1, RIPF_PROMPTONERROR},
{L"fPromptOnWarning", 0, RIPF_PROMPTONWARNING},
{L"fPromptOnVerbose", 0, RIPF_PROMPTONVERBOSE},
{L"fPrintError" , 1, RIPF_PRINTONERROR},
{L"fPrintWarning" , 1, RIPF_PRINTONWARNING},
{L"fPrintVerbose" , 0, RIPF_PRINTONVERBOSE},
{L"fPrintFileLine" , 0, RIPF_PRINTFILELINE},
};
TRACE_INIT(("UserInit: Initialize Global RIP Flags\n"));
nCount = ARRAY_SIZE(aRIPFlags);
/*
* Turn off the rip-on-warning bit. This is necessary to prevent the
* FastGetProfileDwordW() routine from breaking into the debugger if an
* entry can't be found. Since we provide default values, there's no sense
* to break.
*/
CLEAR_FLAG(gpsi->dwRIPFlags, RIPF_PROMPTONWARNING);
CLEAR_FLAG(gpsi->dwRIPFlags, RIPF_PRINTONWARNING);
for (idx = 0; idx < nCount; idx++) {
FastGetProfileDwordW(NULL,
PMAP_WINDOWSM,
aRIPFlags[idx].lpszKey,
aRIPFlags[idx].dwDef,
&dwFlag,
0);
SET_OR_CLEAR_FLAG(gpsi->dwRIPFlags, aRIPFlags[idx].dwFlag, dwFlag);
}
}
#else
#define InitGlobalRIPFlags()
#endif
/***************************************************************************\
* _GetTextMetricsW
* _TextOutW
*
* Server shared function thunks.
*
* History:
* 10-Nov-1993 MikeKe Created
\***************************************************************************/
BOOL _GetTextMetricsW(
HDC hdc,
LPTEXTMETRICW ptm)
{
TMW_INTERNAL tmi;
BOOL fret;
fret = GreGetTextMetricsW(hdc, &tmi);
*ptm = tmi.tmw;
return fret;
}
BOOL _TextOutW(
HDC hdc,
int x,
int y,
LPCWSTR lp,
UINT cc)
{
return GreExtTextOutW(hdc, x, y, 0, NULL, (LPWSTR)lp, cc, NULL);
}
#define ROUND_UP_TO_PAGES(SIZE) \
(((ULONG)(SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
/***************************************************************************\
* InitCreateSharedSection
*
* This creates the shared section.
*
*
* 25-Aug-1995 ChrisWil Created comment block.
\***************************************************************************/
NTSTATUS InitCreateSharedSection(
VOID)
{
ULONG ulHeapSize;
ULONG ulHandleTableSize;
NTSTATUS Status;
LARGE_INTEGER SectionSize;
SIZE_T ViewSize;
PVOID pHeapBase;
TRACE_INIT(("UserInit: Create Shared Memory Section\n"));
UserAssert(ghSectionShared == NULL);
ulHeapSize = ROUND_UP_TO_PAGES(USRINIT_SHAREDSECT_SIZE * 1024);
ulHandleTableSize = ROUND_UP_TO_PAGES(0x10000 * sizeof(HANDLEENTRY));
TRACE_INIT(("UserInit: Share: TableSize = %X; HeapSize = %X\n",
ulHandleTableSize, ulHeapSize));
SectionSize.LowPart = ulHeapSize + ulHandleTableSize;
SectionSize.HighPart = 0;
Status = Win32CreateSection(&ghSectionShared,
SECTION_ALL_ACCESS,
NULL,
&SectionSize,
PAGE_EXECUTE_READWRITE,
SEC_RESERVE,
NULL,
NULL,
TAG_SECTION_SHARED);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING,
"MmCreateSection failed in InitCreateSharedSection with Status %x",
Status);
return Status;
}
ViewSize = 0;
gpvSharedBase = NULL;
Status = Win32MapViewInSessionSpace(ghSectionShared, &gpvSharedBase, &ViewSize);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING,
"Win32MapViewInSessionSpace failed with Status %x",
Status);
Win32DestroySection(ghSectionShared);
ghSectionShared = NULL;
return Status;
}
pHeapBase = ((PBYTE)gpvSharedBase + ulHandleTableSize);
TRACE_INIT(("UserInit: Share: BaseAddr = %#p; Heap = %#p, ViewSize = %X\n",
gpvSharedBase, pHeapBase, ViewSize));
/*
* Create shared heap.
*/
if ((gpvSharedAlloc = UserCreateHeap(
ghSectionShared,
ulHandleTableSize,
pHeapBase,
ulHeapSize,
UserCommitSharedMemory)) == NULL) {
RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
RIP_WARNING,
"Can't create shared memory heap.");
Win32UnmapViewInSessionSpace(gpvSharedBase);
Win32DestroySection(ghSectionShared);
gpvSharedAlloc = NULL;
gpvSharedBase = NULL;
ghSectionShared = NULL;
return STATUS_NO_MEMORY;
}
UserAssert(Win32HeapGetHandle(gpvSharedAlloc) == pHeapBase);
return STATUS_SUCCESS;
}
/**************************************************************************\
* InitCreateUserCrit
*
* Create and initialize the user critical sections needed throughout the
* system.
*
* 23-Jan-1996 ChrisWil Created.
\**************************************************************************/
BOOL InitCreateUserCrit(
VOID)
{
TRACE_INIT(("Win32UserInit: InitCreateUserCrit()\n"));
/*
* Initialize a critical section structure that will be used to protect
* all of the User Server's critical sections (except a few special
* cases like the RIT -- see below).
*/
gpresUser = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERESOURCE),
TAG_ERESOURCE);
if (!gpresUser) {
goto InitCreateUserCritExit;
}
if (!NT_SUCCESS(ExInitializeResourceLite(gpresUser))) {
goto InitCreateUserCritExit;
}
/*
* Initialize a critical section to be used in [Un]QueueMouseEvent
* to protect the queue of mouse input events that the desktop thread
* uses to pass input on to the RIT, after having moved the cursor
* without obtaining gpresUser itself.
*/
gpresMouseEventQueue = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERESOURCE),
TAG_ERESOURCE);
if (!gpresMouseEventQueue) {
goto InitCreateUserCritExit;
}
if (!NT_SUCCESS(ExInitializeResourceLite(gpresMouseEventQueue))) {
goto InitCreateUserCritExit;
}
/*
* Initialize a critical section to protect the list of DEVICEINFO structs
* kept under gpDeviceInfoList. This is used by the RIT when reading kbd
* input, the desktop thread when reading mouse input, and the PnP callback
* routines DeviceClassNotify() and DeviceNotify() when devices come and go.
*/
gpresDeviceInfoList = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERESOURCE),
TAG_ERESOURCE);
if (!gpresDeviceInfoList) {
goto InitCreateUserCritExit;
}
if (!NT_SUCCESS(ExInitializeResourceLite(gpresDeviceInfoList))) {
goto InitCreateUserCritExit;
}
/*
* Create the handle flag mutex. We'll need this once we start creating
* windowstations and desktops.
*/
gpHandleFlagsMutex = ExAllocatePoolWithTag(NonPagedPool,
sizeof(FAST_MUTEX),
TAG_SYSTEM);
if (gpHandleFlagsMutex == NULL) {
goto InitCreateUserCritExit;
}
ExInitializeFastMutex(gpHandleFlagsMutex);
TRACE_INIT(("Win32UserInit: gpHandleFlagsMutex = %#p\n", gpHandleFlagsMutex));
TRACE_INIT(("Win32UserInit: gpresDeviceInfoList = %#p\n", gpresDeviceInfoList));
TRACE_INIT(("Win32UserInit: gpresMouseEventQueue = %#p\n", gpresMouseEventQueue));
TRACE_INIT(("Win32UserInit: gpresUser = %#p\n", gpresUser));
TRACE_INIT(("Win32UserInit: exit InitCreateUserCrit()\n"));
return TRUE;
InitCreateUserCritExit:
RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
RIP_WARNING,
"Win32UserInit: InitCreateUserCrit failed");
if (gpresUser) {
ExFreePool(gpresUser);
}
if (gpresMouseEventQueue) {
ExFreePool(gpresMouseEventQueue);
}
if (gpresDeviceInfoList) {
ExFreePool(gpresDeviceInfoList);
}
return FALSE;
}
/**************************************************************************\
* InitCreateObjectDirectory
*
* Create and initialize the user critical sections needed throughout the
* system.
*
* 23-Jan-1996 ChrisWil Created.
\**************************************************************************/
NTSTATUS InitCreateObjectDirectory(VOID)
{
HANDLE hDir;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UnicodeString;
ULONG attributes = OBJ_CASE_INSENSITIVE | OBJ_PERMANENT;
TRACE_INIT(("UserInit: Create User Object-Directory\n"));
RtlInitUnicodeString(&UnicodeString, szWindowStationDirectory);
if (gbRemoteSession) {
/*
* Remote sessions don't use this flag
*/
attributes &= ~OBJ_PERMANENT;
}
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeString,
attributes,
NULL,
gpsdInitWinSta);
Status = ZwCreateDirectoryObject(&hDir,
DIRECTORY_CREATE_OBJECT,
&ObjectAttributes);
UserFreePool(gpsdInitWinSta);
/*
* Do not close this handle for remote session because
* if we do close it then the directory will go away and
* we don't want that to happen. When CSRSS will go away
* this handle will be freed also.
*/
if (!gbRemoteSession)
ZwClose(hDir);
gpsdInitWinSta = NULL;
return Status;
}
/**************************************************************************\
* InitCreateUserSubsystem
*
* Create and initialize the user subsystem stuff.
* system.
*
* 23-Jan-1996 ChrisWil Created.
\**************************************************************************/
BOOL
InitCreateUserSubsystem()
{
LPWSTR lpszSubSystem;
LPWSTR lpszT;
UNICODE_STRING strSize;
TRACE_INIT(("UserInit: Create User SubSystem\n"));
/*
* Initialize the subsystem section. This identifies the default
* user-heap size.
*/
lpszSubSystem = UserAllocPoolWithQuota(USRINIT_SHAREDSECT_BUFF_SIZE * sizeof(WCHAR),
TAG_SYSTEM);
if (lpszSubSystem == NULL) {
return FALSE;
}
if (FastGetProfileStringW(NULL,
PMAP_SUBSYSTEMS,
L"Windows",
L"SharedSection=,3072",
lpszSubSystem,
USRINIT_SHAREDSECT_READ_SIZE,
0) == 0) {
RIPMSG0(RIP_WARNING,
"UserInit: Windows subsystem definition not found");
UserFreePool(lpszSubSystem);
return FALSE;
}
/*
* Locate the SharedSection portion of the definition and extract
* the second value.
*/
gdwDesktopSectionSize = USER_WINDOWSECT_SIZE;
gdwNOIOSectionSize = USER_NOIOSECT_SIZE;
if (lpszT = wcsstr(lpszSubSystem, L"SharedSection")) {
*(lpszT + 32) = UNICODE_NULL;
if (lpszT = wcschr(lpszT, L',')) {
RtlInitUnicodeString(&strSize, ++lpszT);
RtlUnicodeStringToInteger(&strSize, 0, &gdwDesktopSectionSize);
/*
* Assert this logic doesn't need to change.
*/
UserAssert(gdwDesktopSectionSize >= USER_WINDOWSECT_SIZE);
gdwDesktopSectionSize = max(USER_WINDOWSECT_SIZE, gdwDesktopSectionSize);
gdwNOIOSectionSize = gdwDesktopSectionSize;
/*
* Now see if the optional non-interactive desktop
* heap size was specified.
*/
if (lpszT = wcschr(lpszT, L',')) {
RtlInitUnicodeString(&strSize, ++lpszT);
RtlUnicodeStringToInteger(&strSize, 0, &gdwNOIOSectionSize);
UserAssert(gdwNOIOSectionSize >= USER_NOIOSECT_SIZE);
gdwNOIOSectionSize = max(USER_NOIOSECT_SIZE, gdwNOIOSectionSize);
}
}
}
UserFreePool(lpszSubSystem);
return TRUE;
}
extern UNICODE_STRING *gpastrSetupExe; // These are used in
extern int giSetupExe; // SetAppImeCompatFlags in
// queue.c
WCHAR* glpSetupPrograms;
/**************************************************************************\
* CreateSetupNameArray
*
* Create and initialize the arrary of setup app names. We inherited this
* hack From Chicago. See queue.c for more details.
\**************************************************************************/
BOOL CreateSetupNameArray(
VOID)
{
DWORD dwProgNames;
int iSetupProgramCount = 0;
WCHAR* lpTemp;
int ic, icnt, icMax;
dwProgNames = FastGetProfileValue(NULL,
PMAP_SETUPPROGRAMNAMES,
L"SetupProgramNames",
NULL,
NULL,
0,
0);
/*
* This key is a multi-string, so is best to read as a value.
* First, get the length and create the buffer to hold all of
* the strings.
*/
if (dwProgNames == 0) {
return FALSE;
}
glpSetupPrograms = UserAllocPoolWithQuota(dwProgNames,
TAG_SYSTEM);
if (glpSetupPrograms == NULL) {
RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
return FALSE;
}
FastGetProfileValue(NULL,
PMAP_SETUPPROGRAMNAMES,
L"SetupProgramNames",
NULL,
(PBYTE)glpSetupPrograms,
dwProgNames,
0);
lpTemp = glpSetupPrograms;
icMax = dwProgNames/2;
ic = 0; icnt=0;
/*
* Now count the strings.
*/
while (ic < icMax) {
if (*(lpTemp+ic) == 0) {
ic++;
continue;
}
ic += wcslen(lpTemp+ic)+1;
icnt++;
}
/*
* gpastrSetupExe is a pointer to an array of UNICODE_STRING structures.
* Each structure is the name of one setup program.
*/
giSetupExe = icnt;
gpastrSetupExe = UserAllocPoolWithQuota(giSetupExe * sizeof(UNICODE_STRING),
TAG_SYSTEM);
if (gpastrSetupExe == NULL) {
RIPMSG0(RIP_WARNING, "CreateSetupNameArray: Memory allocation failure");
giSetupExe = 0;
UserFreePool(glpSetupPrograms);
glpSetupPrograms = NULL;
return FALSE;
}
ic = 0; icnt=0;
while (ic < icMax) {
if (*(lpTemp+ic) == 0) {
ic++;
continue;
}
gpastrSetupExe[icnt].Buffer = lpTemp+ic;
gpastrSetupExe[icnt].Length = sizeof(WCHAR)*wcslen(lpTemp+ic);
gpastrSetupExe[icnt].MaximumLength = gpastrSetupExe[icnt].Length + sizeof(WCHAR);
ic += wcslen(lpTemp+ic)+1;
icnt++;
}
return TRUE;
}
#define CALC_DELTA(element) \
(PVOID)((PBYTE)pClientBase + \
((PBYTE)gSharedInfo.element - \
(PBYTE)gpvSharedBase))
/***************************************************************************\
* InitMapSharedSection
*
* This maps the shared section.
*
*
* 25-Aug-1995 ChrisWil Created comment block.
\***************************************************************************/
NTSTATUS InitMapSharedSection(
PEPROCESS Process,
PUSERCONNECT pUserConnect)
{
int i;
PVOID pClientBase = NULL;
ULONG_PTR ulSharedDelta;
PW32PROCESS pw32p;
TRACE_INIT(("UserInit: Map Shared Memory Section\n"));
UserAssert(ghSectionShared != NULL);
ValidateProcessSessionId(Process);
/*
* Check to see if we haven't already mapped the section
* This might happen for multiple LoadLibrary()/FreeLibrary calls
* in one process. MCostea #56946
*/
pw32p = PsGetProcessWin32Process(Process);
if (pw32p == NULL ||
((PPROCESSINFO)pw32p)->pClientBase == NULL) {
SIZE_T ViewSize;
LARGE_INTEGER liOffset;
NTSTATUS Status;
ViewSize = 0;
liOffset.QuadPart = 0;
Status = MmMapViewOfSection(ghSectionShared,
Process,
&pClientBase,
0,
0,
&liOffset,
&ViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ);
if (NT_SUCCESS(Status)) {
TRACE_INIT(("UserInit: Map: Client SharedInfo Base = %#p\n", pClientBase));
UserAssert(gpvSharedBase > pClientBase);
pw32p = PsGetProcessWin32Process(Process);
if (pw32p != NULL) {
((PPROCESSINFO)pw32p)->pClientBase = pClientBase;
}
} else {
return Status;
}
} else {
pClientBase = ((PPROCESSINFO)PsGetProcessWin32Process(Process))->pClientBase;
}
ulSharedDelta = (PBYTE)gpvSharedBase - (PBYTE)pClientBase;
pUserConnect->siClient.ulSharedDelta = ulSharedDelta;
pUserConnect->siClient.psi = CALC_DELTA(psi);
pUserConnect->siClient.aheList = CALC_DELTA(aheList);
pUserConnect->siClient.pDispInfo = CALC_DELTA(pDispInfo);
pUserConnect->siClient.DefWindowMsgs.maxMsgs = gSharedInfo.DefWindowMsgs.maxMsgs;
pUserConnect->siClient.DefWindowMsgs.abMsgs = CALC_DELTA(DefWindowMsgs.abMsgs);
pUserConnect->siClient.DefWindowSpecMsgs.maxMsgs = gSharedInfo.DefWindowSpecMsgs.maxMsgs;
pUserConnect->siClient.DefWindowSpecMsgs.abMsgs = CALC_DELTA(DefWindowSpecMsgs.abMsgs);
for (i = 0; i < (FNID_END - FNID_START + 1); ++i) {
pUserConnect->siClient.awmControl[i].maxMsgs = gSharedInfo.awmControl[i].maxMsgs;
if (gSharedInfo.awmControl[i].abMsgs)
pUserConnect->siClient.awmControl[i].abMsgs = CALC_DELTA(awmControl[i].abMsgs);
else
pUserConnect->siClient.awmControl[i].abMsgs = NULL;
}
return STATUS_SUCCESS;
}
/**************************************************************************\
* InitLoadResources
*
*
* 25-Aug-1995 ChrisWil Created.
\**************************************************************************/
VOID InitLoadResources()
{
PRECT prc;
DISPLAYRESOURCE dr = {
17, // Height of vertical thumb
17, // Width of horizontal thumb
2, // Icon horiz compression factor
2, // Icon vert compression factor
2, // Cursor horz compression factor
2, // Cursor vert compression factor
0, // Kanji window height
1, // cxBorder (thickness of vertical lines)
1 // cyBorder (thickness of horizontal lines)
};
TRACE_INIT(("UserInit: Load Display Resources\n"));
/*
* For high-DPI systems, don't compress the cursor as much.
* This really should be a more configurable method, such as a System
* Parameter Info setting or something. But for now, we'll hard-code
* 150dpi to be the threshhold at which we'll double the cursor size.
*/
if (gpsi->dmLogPixels >= 150) {
dr.xCompressCursor = 1;
dr.yCompressCursor = 1;
}
if (dr.xCompressIcon > 10) {
/*
* If so, the actual dimensions of icons and cursors are
* kept in OEMBIN.
*/
SYSMET(CXICON) = dr.xCompressIcon;
SYSMET(CYICON) = dr.yCompressIcon;
SYSMET(CXCURSOR) = dr.xCompressCursor;
SYSMET(CYCURSOR) = dr.yCompressCursor;
} else {
/*
* Else, only the ratio of (64/icon dimensions) is kept there.
*/
SYSMET(CXICON) = (64 / dr.xCompressIcon);
SYSMET(CYICON) = (64 / dr.yCompressIcon);
SYSMET(CXCURSOR) = (64 / dr.xCompressCursor);
SYSMET(CYCURSOR) = (64 / dr.yCompressCursor);
}
SYSMET(CXSMICON) = SYSMET(CXICON) / 2;
SYSMET(CYSMICON) = SYSMET(CYICON) / 2;
SYSMET(CYKANJIWINDOW) = dr.yKanji;
/*
* Get border thicknesses.
*/
SYSMET(CXBORDER) = dr.cxBorder;
SYSMET(CYBORDER) = dr.cyBorder;
/*
* Edge is two borders.
*/
SYSMET(CXEDGE) = 2 * SYSMET(CXBORDER);
SYSMET(CYEDGE) = 2 * SYSMET(CYBORDER);
/*
* Fixed frame is outer edge + border.
*/
SYSMET(CXDLGFRAME) = SYSMET(CXEDGE) + SYSMET(CXBORDER);
SYSMET(CYDLGFRAME) = SYSMET(CYEDGE) + SYSMET(CYBORDER);
if (gbRemoteSession) {
return;
}
prc = &GetPrimaryMonitor()->rcMonitor;
SYSMET(CXFULLSCREEN) = prc->right;
SYSMET(CYFULLSCREEN) = prc->bottom - SYSMET(CYCAPTION);
/*
* Set the initial cursor position to the center of the primary screen.
*/
gpsi->ptCursor.x = prc->right / 2;
gpsi->ptCursor.y = prc->bottom / 2;
}
/***************************************************************************\
* GetCharDimensions
*
* This function loads the Textmetrics of the font currently selected into
* the hDC and returns the Average char width of the font; Pl Note that the
* AveCharWidth value returned by the Text metrics call is wrong for
* proportional fonts. So, we compute them On return, lpTextMetrics contains
* the text metrics of the currently selected font.
*
* History:
* 10-Nov-1993 mikeke Created
\***************************************************************************/
int GetCharDimensions(
HDC hdc,
TEXTMETRIC* lptm,
LPINT lpcy
)
{
TEXTMETRIC tm;
/*
* Didn't find it in cache, store the font metrics info.
*/
if (!_GetTextMetricsW(hdc, &tm)) {
RIPMSG1(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW failed. hdc %#lx", hdc);
tm = gpsi->tmSysFont; // damage control
if (tm.tmAveCharWidth == 0) {
RIPMSG0(RIP_WARNING, "GetCharDimensions: _GetTextMetricsW first time failure");
tm.tmAveCharWidth = 8;
}
}
if (lptm != NULL)
*lptm = tm;
if (lpcy != NULL)
*lpcy = tm.tmHeight;
/*
* If variable_width font
*/
if (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) {
SIZE size;
static CONST WCHAR wszAvgChars[] =
L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/*
* Change from tmAveCharWidth. We will calculate a true average
* as opposed to the one returned by tmAveCharWidth. This works
* better when dealing with proportional spaced fonts.
*/
if (GreGetTextExtentW(
hdc, (LPWSTR)wszAvgChars,
(sizeof(wszAvgChars) / sizeof(WCHAR)) - 1,
&size, GGTE_WIN3_EXTENT)) {
UserAssert((((size.cx / 26) + 1) / 2) > 0);
return ((size.cx / 26) + 1) / 2; // round up
} else {
RIPMSG1(RIP_WARNING, "GetCharDimensions: GreGetTextExtentW failed. hdc %#lx", hdc);
}
}
UserAssert(tm.tmAveCharWidth > 0);
return tm.tmAveCharWidth;
}
/**************************************************************************\
* InitVideo
*
* Create pmdev.
*
* 03-March-1998 CLupu Moved from UserInitialize code
\**************************************************************************/
PMDEV InitVideo(
BOOL bReenumerationNeeded)
{
PMDEV pmdev;
LONG ChangeStatus;
/*
* NOTE: Need to get a status return from this call.
* DrvInitConsole doesn't return failure, if or when it does we
* should check for it and return NULL. However there seem to be
* no known problems related to this.
*/
DrvInitConsole(bReenumerationNeeded);
/*
* BASEVIDEO may be on or off, whether we are in setup or not.
*/
ChangeStatus = DrvChangeDisplaySettings(NULL,
NULL,
NULL,
(PVOID)GW_DESKTOP_ID,
KernelMode,
FALSE,
TRUE,
NULL,
&pmdev,
GRE_DEFAULT,
TRUE);
if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
/*
* If we fail, try BASEVIDEO temporarily.
*/
DrvSetBaseVideo(TRUE);
ChangeStatus = DrvChangeDisplaySettings(NULL,
NULL,
NULL,
(PVOID)GW_DESKTOP_ID,
KernelMode,
FALSE,
TRUE,
NULL,
&pmdev,
GRE_DEFAULT,
TRUE);
DrvSetBaseVideo(FALSE);
/*
* Give it one last try, not in basevideo, to handle TGA
* (non-vgacompatible) during GUI-mode setup (BASEVIDEO is on by
* default)
*/
if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
ChangeStatus = DrvChangeDisplaySettings(NULL,
NULL,
NULL,
(PVOID)GW_DESKTOP_ID,
KernelMode,
FALSE,
TRUE,
NULL,
&pmdev,
GRE_DEFAULT,
TRUE);
}
}
if (ChangeStatus != GRE_DISP_CHANGE_SUCCESSFUL) {
RIPMSG0(RIP_WARNING, "InitVideo: No working display driver found");
return NULL;
}
/*
* Remove the basevideo flag. We want it set only on the first modeset.
*/
DrvSetBaseVideo(FALSE);
gpDispInfo->hDev = pmdev->hdevParent;
gpDispInfo->pmdev = pmdev;
GreUpdateSharedDevCaps(gpDispInfo->hDev);
if (!InitUserScreen()) {
RIPMSG0(RIP_WARNING, "InitUserScreen failed");
return NULL;
}
HYDRA_HINT(HH_INITVIDEO);
return pmdev;
}
VOID DrvDriverFailure(
VOID)
{
KeBugCheckEx(VIDEO_DRIVER_INIT_FAILURE,
0,
0,
0,
USERCURRENTVERSION);
}
/***************************************************************************\
* BeginBootPhase
*
* Let's kernel know of boot progress on the console.
*
* 10-Apr-2001 Cenke Created.
\***************************************************************************/
NTSTATUS BeginBootPhase(
PF_BOOT_PHASE_ID Phase)
{
PREFETCHER_INFORMATION PrefetcherInformation;
NTSTATUS Status;
/*
* We should be called only on the console.
*/
UserAssert(gSessionId == 0);
/*
* Setup the structure that will be passed to system call.
*/
PrefetcherInformation.Magic = PF_SYSINFO_MAGIC_NUMBER;
PrefetcherInformation.Version = PF_CURRENT_VERSION;
PrefetcherInformation.PrefetcherInformationClass = PrefetcherBootPhase;
PrefetcherInformation.PrefetcherInformation = &Phase;
PrefetcherInformation.PrefetcherInformationLength = sizeof(Phase);
/*
* Call system and return status to caller.
*/
Status = ZwSetSystemInformation(SystemPrefetcherInformation,
&PrefetcherInformation,
sizeof(PrefetcherInformation));
return Status;
}
/**************************************************************************\
* ReserveUserSessionViews
*
* Reserve user needed session views beforhand to prevert GDI from eating
* uo the session view space when hardware acceleration is turned off.
*
* 27-Nov-2001 MSadek Created it
\**************************************************************************/
NTSTATUS
ReserveUserSessionViews(
PHANDLE phSection,
PPVOID ppMapBase)
{
LARGE_INTEGER SectionSize;
ULONG ulSectionSize;
SIZE_T ulViewSize;
NTSTATUS Status;
/*
* We need to reserve session view space for:
* - Winlogon desktop heap.
* - Disconnect desktop heap.
* - Winlogon desktop heap.
* - Services desktops heap (how many?, let's have a factor of safety here).
*/
ulSectionSize = GetDesktopHeapSize(DHS_LOGON) +
GetDesktopHeapSize(DHS_DISCONNECT) +
GetDesktopHeapSize(0) +
GetDesktopHeapSize(DHS_NOIO) * NOIO_DESKTOP_NUMBER;
SectionSize.QuadPart = ulSectionSize;
Status = Win32CreateSection(phSection,
SECTION_ALL_ACCESS,
(POBJECT_ATTRIBUTES)NULL,
&SectionSize,
PAGE_EXECUTE_READWRITE,
SEC_RESERVE,
(HANDLE)NULL,
NULL,
TAG_SECTION_DESKTOP);
if (!NT_SUCCESS( Status )) {
RIPNTERR0(Status,
RIP_WARNING,
"Can't create section for reserved session views.");
return Status;
}
ulViewSize = ulSectionSize;
*ppMapBase = NULL;
Status = Win32MapViewInSessionSpace(*phSection, ppMapBase, &ulViewSize);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status,
RIP_WARNING,
"Can't map section for for reserved session views into session space.");
Win32DestroySection(&phSection);
}
return Status;
}
/**************************************************************************\
* UserInitialize
*
* Worker routine for user initialization.
*
* 25-Aug-1995 ChrisWil Created comment block/Multiple desktop support.
* 15-Dec-1995 BradG Modified to return MediaChangeEvent Handle.
\**************************************************************************/
NTSTATUS
UserInitialize(
VOID)
{
NTSTATUS Status;
DWORD dwData;
HANDLE hSection;
PVOID pSectionBase;
#if DBG
/*
* Allow a trace of all the init stuff going on related to display
* drivers. Useful to debug boot time problems related to graphics.
*/
if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) {
TraceInitialization = 1;
}
#endif
TRACE_INIT(("Entering UserInitialize\n"));
EnterCrit();
HYDRA_HINT(HH_USERINITIALIZE);
if (ISTS() && gbRemoteSession) {
swprintf(szWindowStationDirectory, L"%ws\\%ld%ws",
SESSION_ROOT, gSessionId, WINSTA_DIR);
} else {
wcscpy(szWindowStationDirectory, WINSTA_DIR);
}
/*
* Create WindowStation object directory.
*/
Status = InitCreateObjectDirectory();
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "InitCreateObjectDirectory failed with Status %x",
Status);
goto Exit;
}
/*
* Create the event for PnP RequestDeviceChangeSyncronization
*/
gpEventPnPWainting = CreateKernelEvent(SynchronizationEvent, TRUE);
if (gpEventPnPWainting == NULL) {
RIPMSG0(RIP_WARNING, "Failed to create gpEventPnPWainting");
Status = STATUS_NO_MEMORY;
goto Exit;
}
/*
* Read the registry configuration for the multimon snapsot flag
*/
if (FastGetProfileIntFromID(NULL,PMAP_TS, STR_SNAPSHOTMONITORS, 1, &dwData, 0)) {
if (dwData != 0) {
gbSnapShotWindowsAndMonitors = TRUE;
} else {
gbSnapShotWindowsAndMonitors = FALSE;
}
} else{
gbSnapShotWindowsAndMonitors = TRUE;
}
/*
* Create the event for the diconnect desktop creation
*/
gpEventDiconnectDesktop = CreateKernelEvent(SynchronizationEvent, FALSE);
if (gpEventDiconnectDesktop == NULL) {
RIPMSG0(RIP_WARNING, "Failed to create gpEventDiconnectDesktop");
Status = STATUS_NO_MEMORY;
goto Exit;
}
/*
* WinStations get init'ed on the first connect.
*/
if (!gbRemoteSession) {
BeginBootPhase(PfVideoInitPhase);
/* If hardware acceleration is turned off, GDI will map huge sections for the panning
* surfaces. We might end up exceeding the session view size quota before mapping the heap
* section for critical desktops.
* Let's pre-reserve approximately what we need now.
*/
Status = ReserveUserSessionViews(&hSection, &pSectionBase);
if (!NT_SUCCESS(Status)) {
goto Exit;
}
if (InitVideo(TRUE) == NULL) {
DrvDriverFailure();
}
Status = Win32UnmapViewInSessionSpace(pSectionBase);
Win32DestroySection(hSection);
BeginBootPhase(PfPostVideoInitPhase);
/*
* Do this here so power callouts
* have the pmdev in gpDispInfo set
*/
gbVideoInitialized = TRUE;
}
gbUserInitialized = TRUE;
/*
* Now that the system is initialized, allocate a pti for this thread.
*/
Status = xxxCreateThreadInfo(PsGetCurrentThread());
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING,
"xxxCreateThreadInfo failed during UserInitialize with Status 0x%x",
Status);
goto Exit;
}
/*
* Initialize Global RIP flags (debug only).
*/
InitGlobalRIPFlags();
/*
* WinStations get init'ed on the first connect.
*/
if (!gbRemoteSession) {
UserVerify(LW_BrushInit());
}
InitLoadResources();
Exit:
LeaveCrit();
TRACE_INIT(("Leaving UserInitialize\n"));
return Status;
}
/**************************************************************************\
* IsDBCSEnabledSystem
*
* check if the system is configured as FE Enabled
*
* 07-Feb-1997 HiroYama Created
\**************************************************************************/
__inline BOOL IsDBCSEnabledSystem(
VOID)
{
return !!NLS_MB_CODE_PAGE_TAG;
}
BOOL IsIMMEnabledSystem(
VOID)
{
DWORD dwRet = 0;
/*
* If the entire system is DBCS enabled, IMM/IME should be activated
* anyway.
*/
if (IsDBCSEnabledSystem()) {
return TRUE;
}
FastGetProfileDwordW(NULL, PMAP_IMM, TEXT("LoadIMM"), 0, &dwRet, 0);
return dwRet;
}
#ifdef CUAS_ENABLE
BOOL IsCTFIMEEnabledSystem(
VOID)
{
DWORD dwRet = 0;
FastGetProfileDwordW(NULL, PMAP_IMM, TEXT("DontLoadCTFIME"), 0, &dwRet, 0);
if (dwRet)
return FALSE;
return IsIMMEnabledSystem();
}
#endif
/*
* Get ACP and check if the system is configured as ME Enabled.
*/
BOOL IsMidEastEnabledSystem(
VOID)
{
extern __declspec(dllimport) USHORT NlsAnsiCodePage;
/*
* 1255 == Hebrew and 1256 == Arabic.
*/
if (NlsAnsiCodePage == 1255 || NlsAnsiCodePage == 1256) {
return TRUE;
}
return FALSE;
}
/***************************************************************************\
* SetupClassAtoms
*
* 10/01/1998 clupu moved from Win32UserInitialize
\***************************************************************************/
BOOL SetupClassAtoms(
VOID)
{
BOOL fSuccess = TRUE;
int ind;
/*
* Set up class atoms.
*
* HACK: Controls are registered on the client side so we can't fill in
* their atomSysClass entry the same way we do for the other classes.
*/
for (ind = ICLS_BUTTON; ind < ICLS_CTL_MAX; ind++) {
gpsi->atomSysClass[ind] = UserAddAtom(lpszControls[ind], TRUE);
fSuccess &= !!gpsi->atomSysClass[ind];
}
gpsi->atomSysClass[ICLS_DIALOG] = PTR_TO_ID(DIALOGCLASS);
gpsi->atomSysClass[ICLS_ICONTITLE] = PTR_TO_ID(ICONTITLECLASS);
gpsi->atomSysClass[ICLS_TOOLTIP] = PTR_TO_ID(TOOLTIPCLASS);
gpsi->atomSysClass[ICLS_DESKTOP] = PTR_TO_ID(DESKTOPCLASS);
gpsi->atomSysClass[ICLS_SWITCH] = PTR_TO_ID(SWITCHWNDCLASS);
gpsi->atomSysClass[ICLS_MENU] = PTR_TO_ID(MENUCLASS);
gpsi->atomContextHelpIdProp = UserAddAtom(szCONTEXTHELPIDPROP, TRUE);
fSuccess &= !!gpsi->atomContextHelpIdProp;
gpsi->atomIconSmProp = UserAddAtom(szICONSM_PROP_NAME, TRUE);
fSuccess &= !!gpsi->atomIconSmProp;
gpsi->atomIconProp = UserAddAtom(szICON_PROP_NAME, TRUE);
fSuccess &= !!gpsi->atomIconProp;
gpsi->uiShellMsg = UserAddAtom(szSHELLHOOK, TRUE);
fSuccess &= !!gpsi->uiShellMsg;
/*
* Initialize the integer atoms for our magic window properties
*/
atomCheckpointProp = UserAddAtom(szCHECKPOINT_PROP_NAME, TRUE);
fSuccess &= !!atomCheckpointProp;
atomDDETrack = UserAddAtom(szDDETRACK_PROP_NAME, TRUE);
fSuccess &= !!atomDDETrack;
atomQOS = UserAddAtom(szQOS_PROP_NAME, TRUE);
fSuccess &= !!atomQOS;
atomDDEImp = UserAddAtom(szDDEIMP_PROP_NAME, TRUE);
fSuccess &= !!atomDDEImp;
atomWndObj = UserAddAtom(szWNDOBJ_PROP_NAME, TRUE);
fSuccess &= !!atomWndObj;
atomImeLevel = UserAddAtom(szIMELEVEL_PROP_NAME, TRUE);
fSuccess &= !!atomImeLevel;
atomLayer = UserAddAtom(szLAYER_PROP_NAME, TRUE);
fSuccess &= !!atomLayer;
guiActivateShellWindow = UserAddAtom(szACTIVATESHELLWINDOW, TRUE);
fSuccess &= !!guiActivateShellWindow;
guiOtherWindowCreated = UserAddAtom(szOTHERWINDOWCREATED, TRUE);
fSuccess &= !!guiOtherWindowCreated;
guiOtherWindowDestroyed = UserAddAtom(szOTHERWINDOWDESTROYED, TRUE);
fSuccess &= !!guiOtherWindowDestroyed;
gatomMessage = UserAddAtom(szMESSAGE, TRUE);
fSuccess &= !!gatomMessage;
#ifdef HUNGAPP_GHOSTING
gatomGhost = UserAddAtom(szGHOST, TRUE);
fSuccess &= !!gatomGhost;
#endif
gatomShadow = UserAddAtom(szSHADOW, TRUE);
fSuccess &= !!gatomShadow;
gaOleMainThreadWndClass = UserAddAtom(szOLEMAINTHREADWNDCLASS, TRUE);
fSuccess &= !!gaOleMainThreadWndClass;
gaFlashWState = UserAddAtom(szFLASHWSTATE, TRUE);
fSuccess &= !!gaFlashWState;
gatomLastPinned = gaOleMainThreadWndClass;
return fSuccess;
}
/**************************************************************************\
* IsDesktopHeapLoggingOn
*
* Checks the registry to determine if we should write a message to the
* event log on desktop heap allocation failures.
*
* 05-19-2002 JasonSch Created.
\**************************************************************************/
BOOL IsDesktopHeapLoggingOn(
VOID)
{
DWORD dwDesktopHeapLogging;
FastGetProfileDwordW(NULL,
PMAP_WINDOWSM,
L"DesktopHeapLogging",
0,
&dwDesktopHeapLogging,
0);
return (dwDesktopHeapLogging != 0);
}
/**************************************************************************\
* Win32UserInitialize
*
* Worker routine for user initialization called from Win32k's DriverEntry.
\**************************************************************************/
NTSTATUS Win32UserInitialize(
VOID)
{
NTSTATUS Status;
POBJECT_TYPE_INITIALIZER pTypeInfo;
LONG lTemp;
TRACE_INIT(("Entering Win32UserInitialize\n"));
/*
* Create the shared section.
*/
Status = InitCreateSharedSection();
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING,
"InitCreateSharedSection failed with Status 0x%x",
Status);
return Status;
}
EnterCrit();
/*
* Initialize security stuff.
*/
if (!InitSecurity()) {
RIPMSG0(RIP_WARNING, "InitSecurity failed");
goto ExitWin32UserInitialize;
}
/*
* Fill in windowstation and desktop object types
*/
pTypeInfo = &(*ExWindowStationObjectType)->TypeInfo;
pTypeInfo->DefaultNonPagedPoolCharge = sizeof(WINDOWSTATION) + sizeof(KEVENT);
pTypeInfo->DefaultPagedPoolCharge = 0;
pTypeInfo->MaintainHandleCount = TRUE;
pTypeInfo->ValidAccessMask = WinStaMapping.GenericAll;
pTypeInfo->GenericMapping = WinStaMapping;
pTypeInfo = &(*ExDesktopObjectType)->TypeInfo;
pTypeInfo->DefaultNonPagedPoolCharge = sizeof(DESKTOP);
pTypeInfo->DefaultPagedPoolCharge = 0;
pTypeInfo->MaintainHandleCount = TRUE;
pTypeInfo->ValidAccessMask = DesktopMapping.GenericAll;
pTypeInfo->GenericMapping = DesktopMapping;
/*
* Get this process so we can use the profiles.
*/
gpepInit = PsGetCurrentProcess();
Status = InitQEntryLookaside();
Status |= InitSMSLookaside();
Status |= UserRtlCreateAtomTable(USRINIT_ATOMBUCKET_SIZE);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING,
"Initialization failure (Status = 0x%x)",
Status);
goto ExitWin32UserInitialize;
}
atomUSER32 = UserAddAtom(szUSER32, TRUE);
gatomFirstPinned = atomUSER32;
if (gatomFirstPinned == 0) {
RIPMSG0(RIP_WARNING, "Could not create atomUSER32");
goto ExitWin32UserInitialize;
}
/*
* Initialize the user subsystem information.
*/
if (!InitCreateUserSubsystem()) {
RIPMSG0(RIP_WARNING, "InitCreateUserSubsystem failed");
goto ExitWin32UserInitialize;
}
/*
* Don't bail out if CreateSetupNameArray fails.
*/
CreateSetupNameArray();
/*
* Allocated shared SERVERINFO structure.
*/
if ((gpsi = (PSERVERINFO)SharedAlloc(sizeof(SERVERINFO))) == NULL) {
RIPMSG0(RIP_WARNING, "Could not allocate SERVERINFO");
goto ExitWin32UserInitialize;
}
/*
* Set the default rip-flags to rip on just about everything. We'll
* truly set this in the InitGlobalRIPFlags() routine. These are needed
* so that we can do appropriate ripping during the rest of the init
* calls.
*/
#if DBG
SET_FLAG(gpsi->dwRIPFlags, RIPF_DEFAULT);
#endif
/*
* Make sure we will not get a division by zero if the initialization
* will not complete correctly. Set these to their normal values.
*/
gpsi->cxMsgFontChar = 6;
gpsi->cyMsgFontChar = 13;
gpsi->cxSysFontChar = 8;
gpsi->cySysFontChar = 16;
/*
* Initialize the last time we updated system-wide LastSystemRITEventTickCount
* on system shared page.
*/
gpsi->dwLastSystemRITEventTickCountUpdate = 0;
/*
* Initialize the DISPLAYINFO structure.
*/
gpDispInfo = SharedAlloc(sizeof(*gpDispInfo));
if (!gpDispInfo) {
RIPMSG0(RIP_WARNING, "Could not allocate gpDispInfo");
goto ExitWin32UserInitialize;
}
InitDbgTags();
SET_OR_CLEAR_SRVIF(SRVIF_LOGDESKTOPHEAPFAILURE, IsDesktopHeapLoggingOn());
SET_OR_CLEAR_SRVIF(SRVIF_DBCS, IsDBCSEnabledSystem());
SET_OR_CLEAR_SRVIF(SRVIF_IME, IsIMMEnabledSystem());
#ifdef CUAS_ENABLE
SET_OR_CLEAR_SRVIF(SRVIF_CTFIME_ENABLED, IsCTFIMEEnabledSystem());
#endif // CUAS_ENABLE
SET_OR_CLEAR_SRVIF(SRVIF_MIDEAST, IsMidEastEnabledSystem());
#if DBG
SET_SRVIF(SRVIF_CHECKED);
#if !defined(CUAS_ENABLE)
RIPMSG3(RIP_WARNING, "*** win32k: DBCS:[%d] IME:[%d] MiddleEast:[%d]",
IS_DBCS_ENABLED(),
IS_IME_ENABLED(),
IS_MIDEAST_ENABLED());
#else
RIPMSG4(RIP_WARNING, "*** win32k: DBCS:[%d] IME:[%d] MiddleEast:[%d] CTFIME:[%d]",
IS_DBCS_ENABLED(),
IS_IME_ENABLED(),
IS_MIDEAST_ENABLED(),
IS_CICERO_ENABLED());
#endif
#endif
gpsi->dwDefaultHeapSize = gdwDesktopSectionSize * 1024;
/*
* Initialize procedures and message tables.
* Initialize the class structures for Get/SetClassWord/Long.
* Initialize message-box strings.
* Initialize OLE-Formats (performance-hack).
*/
InitFunctionTables();
InitMessageTables();
#if DBG
VerifySyncOnlyMessages();
#endif
if (!InitOLEFormats()) {
RIPMSG0(RIP_WARNING, "InitOLEFormats failed");
goto ExitWin32UserInitialize;
}
/*
* Set up class atoms
*/
if (!SetupClassAtoms()) {
RIPMSG0(RIP_WARNING, "SetupClassAtoms failed to register atoms");
goto ExitWin32UserInitialize;
}
/*
* Initialize the handle manager.
*/
if (!HMInitHandleTable(gpvSharedBase)) {
RIPMSG0(RIP_WARNING, "HMInitHandleTable failed");
goto ExitWin32UserInitialize;
}
/*
* Setup shared info block.
*/
gSharedInfo.psi = gpsi;
gSharedInfo.pDispInfo = gpDispInfo;
/*
* Determine if we have unsigned drivers installed
* Use 2BD63D28D7BCD0E251195AEB519243C13142EBC3 as current key to check.
* Old key: 300B971A74F97E098B67A4FCEBBBF6B9AE2F404C
*/
if (NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\SOFTWARE\\Policies\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3")) ||
NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3")) ||
NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_USER, L"\\SOFTWARE\\Microsoft\\SystemCertificates\\Root\\Certificates\\2BD63D28D7BCD0E251195AEB519243C13142EBC3"))) {
gfUnsignedDrivers = TRUE;
}
FastGetProfileDwordW(NULL,
PMAP_WINDOWSM,
L"USERProcessHandleQuota",
DEFAULT_USER_HANDLE_QUOTA,
&lTemp,
0);
gUserProcessHandleQuota = lTemp;
/*
* The maximum number of posted message for a thread.
*/
FastGetProfileDwordW(NULL,
PMAP_WINDOWSM,
L"USERPostMessageLimit",
DEFAULT_POSTMESSAGE_LIMIT,
&lTemp,
0);
if (lTemp == 0) {
/*
* 0 means (virtually) no limit.
*/
gUserPostMessageLimit = ~0;
} else {
gUserPostMessageLimit = lTemp;
}
if (!gDrawVersionAlways) {
FastGetProfileDwordW(NULL,
PMAP_WINDOWSM,
L"DisplayVersion",
0,
&gDrawVersionAlways,
0);
}
FastGetProfileDwordW(NULL,
PMAP_TS_EXCLUDE_DESKTOP_VERSION,
L"TSExcludeDesktopVersion",
0,
&gdwTSExcludeDesktopVersion,
0);
FastGetProfileDwordW(NULL,
PMAP_TABLETPC,
L"Installed",
0,
&SYSMET(TABLETPC),
0);
FastGetProfileDwordW(NULL,
PMAP_MEDIACENTER,
L"Installed",
0,
&SYSMET(MEDIACENTER),
0);
/*
* Initialize SMWP structure.
*/
if (!AllocateCvr(&gSMWP, 4)) {
RIPMSG0(RIP_WARNING, "AllocateCvr failed");
goto ExitWin32UserInitialize;
}
LeaveCrit();
UserAssert(NT_SUCCESS(Status));
return Status;
ExitWin32UserInitialize:
LeaveCrit();
if (NT_SUCCESS(Status)) {
Status = STATUS_NO_MEMORY;
}
RIPMSG1(RIP_WARNING, "UserInitialize failed with Status = 0x%x", Status);
return Status;
}
/**************************************************************************\
* UserGetDesktopDC
*
* 09-Jan-1992 mikeke created
* Dec-1993 andreva changed to support desktops.
\**************************************************************************/
HDC UserGetDesktopDC(
ULONG type,
BOOL bAltType,
BOOL bValidate)
{
PETHREAD Thread;
HDC hdc;
PTHREADINFO pti = PtiCurrentShared(); // This is called from outside the crit sec
HDEV hdev = gpDispInfo->hDev;
if (bValidate && type != DCTYPE_INFO &&
IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_HANDLES)) {
UserAssert(pti->rpdesk != NULL);
if (!ValidateHwnd(PtoH(pti->rpdesk->pDeskInfo->spwnd))) {
RIPMSG0(RIP_WARNING,
"UserGetDesktopDC fails desktop window validation");
return NULL;
}
}
/*
* NOTE:
* This is a real nasty trick to get both DCs created on a desktop on
* a different device to work (for the video applet) and to be able
* to clip DCs that are actually on the same device ...
*/
if (pti && pti->rpdesk)
hdev = pti->rpdesk->pDispInfo->hDev;
/*
* We want to turn this call that was originally OpenDC("Display", ...)
* into GetDC null call so this DC will be clipped to the current
* desktop or else the DC can write to any desktop. Only do this
* for client apps; let the server do whatever it wants.
*/
Thread = PsGetCurrentThread();
if ((type != DCTYPE_DIRECT) ||
(hdev != gpDispInfo->hDev) ||
PsIsSystemThread(Thread) ||
(PsGetThreadProcess(Thread) == gpepCSRSS)) {
hdc = GreCreateDisplayDC(hdev, type, bAltType);
} else {
PDESKTOP pdesk;
EnterCrit();
if (pdesk = PtiCurrent()->rpdesk) {
hdc = _GetDCEx(pdesk->pDeskInfo->spwnd,
NULL,
DCX_WINDOW | DCX_CACHE | DCX_CREATEDC);
} else {
hdc = NULL;
}
LeaveCrit();
}
return hdc;
}
/**************************************************************************\
* UserThreadCallout
*
*
* Called by the kernel when a thread starts or ends.
*
* Dec-1993 andreva created.
\**************************************************************************/
NTSTATUS UserThreadCallout(
IN PETHREAD pEThread,
IN PSW32THREADCALLOUTTYPE CalloutType)
{
PTHREADINFO pti;
NTSTATUS Status = STATUS_SUCCESS;
UserAssert(gpresUser != NULL);
switch (CalloutType) {
case PsW32ThreadCalloutInitialize:
TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutInitialize\n"));
if (gbNoMorePowerCallouts) {
RIPMSG0(RIP_WARNING, "No more GUI threads allowed");
return STATUS_UNSUCCESSFUL;
}
/*
* Only create a thread info structure if we're initialized.
*/
if (gbUserInitialized) {
EnterCrit();
UserAssert(gpepCSRSS != NULL);
/*
* Initialize this thread
*/
Status = xxxCreateThreadInfo(pEThread);
LeaveCrit();
}
break;
case PsW32ThreadCalloutExit:
TRACE_INIT(("Entering UserThreadCallout PsW32ThreadCalloutExit\n"));
/*
* If we aren't already inside the critical section, enter it.
* Because this is the first pass, we remain in the critical
* section when we return so that our try/finally handlers
* are protected by the critical section.
* EnterCrit here before GreUnlockDisplay() provides a pti which
* may be required if unlocking the display may release some
* deferred WinEvents, for which a pti is required.
*/
EnterCrit();
pti = (PTHREADINFO)PsGetThreadWin32Thread(pEThread);
/*
* Mark this thread as in the middle of cleanup. This is useful for
* several problems in USER where we need to know this information.
*/
pti->TIF_flags |= TIF_INCLEANUP;
/*
* If we died during a full screen switch make sure we cleanup
* correctly
*/
FullScreenCleanup();
/*
* Cleanup gpDispInfo->hdcScreen - if we crashed while using it,
* it may have owned objects still selected into it. Cleaning
* it this way will ensure that gdi doesn't try to delete these
* objects while they are still selected into this public hdc.
*/
/*
* WinStations that haven't gone through the first connect do not
* have any of the graphics setup.
*/
if (!gbRemoteSession || gbVideoInitialized) {
GreCleanDC(gpDispInfo->hdcScreen);
}
/*
* This thread is exiting execution; xxxDestroyThreadInfo cleans
* up everything that can go now
*/
UserAssert(pti == PtiCurrent());
xxxDestroyThreadInfo();
LeaveCrit();
break;
}
TRACE_INIT(("Leaving UserThreadCallout\n"));
return Status;
}
/**************************************************************************\
* NtUserInitialize
*
* 01-Dec-1993 andreva created.
* 01-Dec-1995 BradG Modified to return handle to Media Change Event
\**************************************************************************/
BOOL TellGdiToGetReady();
NTSTATUS NtUserInitialize(
IN DWORD dwVersion,
IN HANDLE hPowerRequestEvent,
IN HANDLE hMediaRequestEvent)
{
NTSTATUS Status;
TRACE_INIT(("Entering NtUserInitialize\n"));
/*
* Make sure we're not trying to load this twice.
*/
if (gpepCSRSS != NULL) {
RIPMSG0(RIP_WARNING, "Can't initialize more than once");
return STATUS_UNSUCCESSFUL;
}
/*
* Check version number
*/
if (dwVersion != USERCURRENTVERSION) {
KeBugCheckEx(WIN32K_INIT_OR_RIT_FAILURE,
0,
0,
dwVersion,
USERCURRENTVERSION);
}
/*
* Get the session ID from the EPROCESS structure
*/
gSessionId = PsGetCurrentProcessSessionId();
UserAssert(gSessionId == 0 || gbRemoteSession == TRUE);
Status = InitializePowerRequestList(hPowerRequestEvent);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = InitializeMediaChange(hMediaRequestEvent);
if (!NT_SUCCESS(Status)) {
return Status;
}
/*
* Save the system process structure.
*/
gpepCSRSS = PsGetCurrentProcess();
ObReferenceObject(gpepCSRSS);
if (!TellGdiToGetReady()) {
RIPMSG0(RIP_WARNING, "TellGdiToGetReady failed");
Status = STATUS_UNSUCCESSFUL;
return Status;
}
/*
* Allow CSR to read the screen
*/
((PW32PROCESS)PsGetProcessWin32Process(gpepCSRSS))->W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED|W32PF_IOWINSTA);
Status = UserInitialize();
TRACE_INIT(("Leaving NtUserInitialize\n"));
return Status;
}
/**************************************************************************\
* NtUserProcessConnect
*
* 01-Dec-1993 Andreva Created.
\**************************************************************************/
NTSTATUS NtUserProcessConnect(
IN HANDLE hProcess,
IN OUT PVOID pConnectInfo,
IN ULONG cbConnectInfo)
{
PEPROCESS Process;
PUSERCONNECT pucConnect = (PUSERCONNECT)pConnectInfo;
USERCONNECT ucLocal;
NTSTATUS Status = STATUS_SUCCESS;
TRACE_INIT(("Entering NtUserProcessConnect\n"));
if (!pucConnect || (cbConnectInfo != sizeof(USERCONNECT))) {
return STATUS_UNSUCCESSFUL;
}
try {
ProbeForWrite(pucConnect, cbConnectInfo, sizeof(DWORD));
ucLocal = *pucConnect;
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
return GetExceptionCode();
}
/*
* Check client/server versions.
*/
if (ucLocal.ulVersion != USERCURRENTVERSION) {
RIPMSG2(RIP_ERROR,
"Client version %lx > server version %lx\n",
ucLocal.ulVersion, USERCURRENTVERSION);
return STATUS_UNSUCCESSFUL;
}
if (ucLocal.dwDispatchCount != gDispatchTableValues) {
RIPMSG2(RIP_ERROR,
"!!!! Client Dispatch info %lX != Server %lX\n",
ucLocal.dwDispatchCount, gDispatchTableValues);
}
/*
* Reference the process.
*/
Status = ObReferenceObjectByHandle(hProcess,
PROCESS_VM_OPERATION,
*PsProcessType,
UserMode,
&Process,
NULL);
if (!NT_SUCCESS(Status))
return Status;
/*
* Return client's view of shared data.
*/
EnterCrit();
Status = InitMapSharedSection(Process, &ucLocal);
LeaveCrit();
if (!NT_SUCCESS(Status)) {
RIPMSG2(RIP_WARNING,
"Failed to map shared data into client %x, status = %x\n",
PsGetCurrentProcessId(), Status);
}
ObDereferenceObject(Process);
if (NT_SUCCESS(Status)) {
try {
*pucConnect = ucLocal;
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
Status = GetExceptionCode();
}
}
TRACE_INIT(("Leaving NtUserProcessConnect\n"));
return Status;
}
/**************************************************************************\
* xxxUserProcessCallout
*
* 01-Dec-1993 andreva Created.
\**************************************************************************/
NTSTATUS xxxUserProcessCallout(
IN PW32PROCESS Process,
IN BOOLEAN Initialize)
{
NTSTATUS Status = STATUS_SUCCESS;
if (Initialize) {
TRACE_INIT(("Entering xxxUserProcessCallout Initialize\n"));
UserAssert(gpresUser != NULL);
EnterCrit();
/*
* Initialize the important process level stuff.
*/
Status = xxxInitProcessInfo(Process);
LeaveCrit();
if (Status == STATUS_SUCCESS) {
PEJOB Job = PsGetProcessJob(Process->Process);
if (Job != NULL &&
PsGetJobUIRestrictionsClass(Job) != 0) {
WIN32_JOBCALLOUT_PARAMETERS Parms;
/*
* aquire the job's lock and after that enter the user
* critical section.
*/
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(PsGetJobLock(Job), TRUE);
Parms.Job = Job;
Parms.CalloutType = PsW32JobCalloutAddProcess;
Parms.Data = Process;
UserAssert(PsGetJobSessionId(Job) == PsGetProcessSessionId(Process->Process));
UserJobCallout(&Parms);
ExReleaseResourceLite(PsGetJobLock(Job));
KeLeaveCriticalRegion();
}
}
} else {
int i;
PHE phe;
PDCE *ppdce;
PDCE pdce;
TRACE_INIT(("Entering xxxUserProcessCallout Cleanup\n"));
UserAssert(gpresUser != NULL);
EnterCrit();
#if DBG
if (Process->Process == gpepCSRSS) {
/*
* CSRSS should be the last to go ...
*/
UserAssert(gppiList->ppiNextRunning == NULL);
}
#endif // DBG
if (Process->Process && PsGetProcessJob(Process->Process) != NULL) {
RemoveProcessFromJob((PPROCESSINFO)Process);
}
/*
* DestroyProcessInfo will return TRUE if any threads ever
* connected. If nothing ever connected, we needn't do
* this cleanup.
*/
if (DestroyProcessInfo(Process)) {
/*
* See if we can compact the handle table.
*/
i = giheLast;
phe = &gSharedInfo.aheList[giheLast];
while ((phe > &gSharedInfo.aheList[0]) && (phe->bType == TYPE_FREE)) {
phe--;
giheLast--;
}
/*
* Scan the DC cache to find any DC's that need to be destroyed.
*/
for (ppdce = &gpDispInfo->pdceFirst; *ppdce != NULL; ) {
pdce = *ppdce;
if (pdce->DCX_flags & DCX_DESTROYTHIS)
DestroyCacheDC(ppdce, pdce->hdc);
/*
* Step to the next DC. If the DC was deleted, there
* is no need to calculate the address of the next entry.
*/
if (pdce == *ppdce)
ppdce = &pdce->pdceNext;
}
}
UserAssert(gpresUser != NULL);
LeaveCrit();
}
TRACE_INIT(("Leaving xxxUserProcessCallout\n"));
return Status;
}
/**************************************************************************\
* UserGetHDEV
*
* Provided as a means for GDI to get a hold of USER's hDev.
*
* 01-Jan-1996 ChrisWil Created.
\**************************************************************************/
HDEV UserGetHDEV(VOID)
{
/*
* NOTE: This is busted.
* This need to return the device for the current desktop.
* The graphics device may not be the same for all desktops.
* -Andre
*/
return gpDispInfo->hDev;
}
/**************************************************************************\
* _UserGetGlobalAtomTable
*
* This function is called by the kernel mode global atom manager to get the
* address of the current thread's global atom table.
*
* Pointer to the global atom table for the current thread or NULL if unable
* to access it.
\**************************************************************************/
PVOID UserGlobalAtomTableCallout(
VOID)
{
PETHREAD Thread;
PTHREADINFO pti;
PWINDOWSTATION pwinsta;
PW32JOB pW32Job;
PEJOB Job;
PVOID GlobalAtomTable = NULL;
Thread = PsGetCurrentThread();
pti = PtiFromThread(Thread);
EnterCrit();
/*
* For restricted threads access the atom table off of the job object
*/
if (pti != NULL && IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
TAGMSG1(DBGTAG_Callout, "Retrieving global atom table for pti 0x%p", pti);
pW32Job = pti->ppi->pW32Job;
UserAssert(pW32Job->pAtomTable != NULL);
GlobalAtomTable = pW32Job->pAtomTable;
goto End;
}
Job = PsGetProcessJob(PsGetCurrentProcess());
/*
* Now handle the case where this is not a GUI thread/process
* but it is assigned to a job that has JOB_OBJECT_UILIMIT_GLOBALATOMS
* restrictions set. There is no easy way to convert this thread
* to GUI.
*/
if (pti == NULL && Job != NULL &&
(PsGetJobUIRestrictionsClass(Job) & JOB_OBJECT_UILIMIT_GLOBALATOMS)) {
/*
* find the W32JOB in the global list
*/
pW32Job = gpJobsList;
while (pW32Job) {
if (pW32Job->Job == Job) {
break;
}
pW32Job = pW32Job->pNext;
}
UserAssert(pW32Job != NULL && pW32Job->pAtomTable != NULL);
GlobalAtomTable = pW32Job->pAtomTable;
goto End;
}
#if DBG
pwinsta = NULL;
#endif
if (NT_SUCCESS(ReferenceWindowStation(Thread,
PsGetCurrentProcessWin32WindowStation(),
WINSTA_ACCESSGLOBALATOMS,
&pwinsta,
TRUE))) {
UserAssert(pwinsta != NULL);
GlobalAtomTable = pwinsta->pGlobalAtomTable;
}
End:
LeaveCrit();
#if DBG
if (GlobalAtomTable == NULL) {
RIPMSG1(RIP_WARNING,
"_UserGetGlobalAtomTable: NULL Atom Table for pwinsta=%#p",
pwinsta);
}
#endif
return GlobalAtomTable;
}