/****************************** Module Header ******************************\
* Module Name: userk.h
*
* Copyright (c) 1985 - 2001, Microsoft Corporation
*
* Typedefs, defines, and prototypes that are used exclusively by the User
* kernel-mode code.
*
* History:
* 04-28-91 DarrinM      Created from PROTO.H, MACRO.H, and STRTABLE.H
* 01-25-95 JimA         Prepped for kernel-mode
\***************************************************************************/

#ifndef _USERK_
#define _USERK_

#ifndef _WINBASE_
#include <wbasek.h>
#endif // _WINBASE_

#include <csrmsg.h>
#include <heap.h>

/*
 * BltColor() flags.
 */
#define BC_INVERT             0x00000001
#define BC_NOMIRROR           0x00000002

#define MIRRORED_HDC(hdc)     (GreGetLayout(hdc) & LAYOUT_RTL)

#define OEMRESOURCE 1

#define CCACHEDCAPTIONS 5

#define RIT_PROCESSINPUT  0x01
#define RIT_STOPINPUT     0x02

#define GETMOUSETRAILS()        (IsRemoteConnection() ? 0 : gMouseTrails)
#define MOUSE_TRAILS_FREQ       50

#include <winnls.h>
#include <wincon.h>

#include <winuser.h>
#include <winuserp.h>
#include <wowuserp.h>
#include "ntddvdeo.h"

#ifdef GENERIC_INPUT
#include <hidpddi.h>
#include <hidpi.h>
#include <hidclass.h>
#endif

#include <user.h>

PTHREADINFO _ptiCrit(VOID);
PTHREADINFO _ptiCritShared(VOID);

#if DBG
    #define PtiCurrent()  _ptiCrit()
    #define PtiCurrentShared() _ptiCritShared()
#else // DBG
    #define PtiCurrent()  (gptiCurrent)
    #define PtiCurrentShared() ((PTHREADINFO)(W32GetCurrentThread()))
#endif // DBG

extern HANDLE CsrApiPort;

#if DEBUGTAGS
    void CheckPtiSysPeek(int where, PQ pq, ULONG_PTR newIdSysPeek);
    void CheckSysLock(int where, PQ pq, PTHREADINFO pti);
#else // DEBUGTAGS
    #define CheckPtiSysPeek(where, pq, newIdSysPeek)
    #define CheckSysLock(where, pq, pti)
#endif // DEBUGTAGS

/*
 * ShutdownProcessRoutine return values
 */
#define SHUTDOWN_KNOWN_PROCESS   1
#define SHUTDOWN_UNKNOWN_PROCESS 2
#define SHUTDOWN_CANCEL          3

/*
 * Macros to get address of current thread and process information.
 */

#define PpiCurrent() \
    ((PPROCESSINFO)(W32GetCurrentProcess()))

#define PtiFromThread(Thread) ((PTHREADINFO)(PsGetThreadWin32Thread(Thread)))

#if DBG
    #define GetNestedCallsCounter() (PtiCurrentShared()->cNestedCalls)
#else // DBG
    #define GetNestedCallsCounter()
#endif // DBG

#define PpiFromProcess(Process)                                           \
        ((PPROCESSINFO)(PsGetProcessWin32Process(Process)))

#define GetCurrentProcessId() PsGetCurrentProcessId()

#define ISCSRSS() (PsGetCurrentProcess() == gpepCSRSS)

BOOL CSTPush(UINT uThreadID, PVOID pParam, HANDLE UniqueProcessId, BOOL bRemoteThreadStack);

void CSTCleanupStack(BOOL bRemoteThreadStack);

__inline BOOL InitCreateSystemThreadsMsg(PUSER_API_MSG pMsg, UINT ThreadID, PVOID pVoid, HANDLE UniqueProcessId, BOOL bRemoteThread)
{
    UserAssert(CsrApiPort != NULL);
    if (!CSTPush(ThreadID, pVoid, UniqueProcessId, bRemoteThread)) {
        return FALSE;
    }
    pMsg->h.u1.s1.DataLength  = (USHORT) (sizeof(USER_API_MSG) - sizeof( PORT_MESSAGE ));
    pMsg->h.u1.s1.TotalLength = (USHORT) (sizeof(USER_API_MSG));
    pMsg->h.u2.ZeroInit = 0;
    pMsg->CaptureBuffer = NULL;
    pMsg->ApiNumber = CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpCreateSystemThreads);
    pMsg->u.CreateSystemThreads.bRemoteThread = bRemoteThread;
    return TRUE;
}

NTSTATUS OpenEffectiveToken(
    PHANDLE phToken);

NTSTATUS GetProcessLuid(
    PETHREAD Thread OPTIONAL,
    PLUID LuidProcess);

BOOLEAN IsRestricted(
    PETHREAD Thread);

NTSTATUS CreateSystemThread(
    PKSTART_ROUTINE lpThreadAddress,
    PVOID pvContext,
    PHANDLE phThread);

NTSTATUS InitSystemThread(
    PUNICODE_STRING pstrThreadName);

#define INITCLIENTINFO(pti)                                     \
{                                                               \
    pti->pClientInfo->dwExpWinVer = pti->dwExpWinVer;           \
    pti->pClientInfo->dwTIFlags   = pti->TIF_flags;             \
                                                                \
    if (pti->spklActive) {                                      \
        pti->pClientInfo->CodePage = pti->spklActive->CodePage; \
        pti->pClientInfo->hKL = pti->spklActive->hkl;           \
    } else {                                                    \
        pti->pClientInfo->CodePage = CP_ACP;                    \
        pti->pClientInfo->hKL = 0;                              \
    }                                                           \
                                                                \
}

PKEVENT CreateKernelEvent(
    IN EVENT_TYPE Type,
    IN BOOLEAN State);

NTSTATUS ProtectHandle(
    IN HANDLE       Handle,
    IN POBJECT_TYPE pObjectType,
    IN BOOLEAN      Protect);

__inline VOID FreeKernelEvent(PVOID* pp)
{
    UserFreePool(*pp);
    *pp = NULL;
}


extern BOOL  gfSwitchInProgress;
extern PKEVENT gpevtVideoportCallout;

__inline VOID SetConsoleSwitchInProgress(BOOL fSwitchInProgress)
{
    gfSwitchInProgress = fSwitchInProgress;
    if (fSwitchInProgress) {
        KeResetEvent(gpevtVideoportCallout);
    } else {
        KeSetEvent(gpevtVideoportCallout, EVENT_INCREMENT, FALSE);
    }
}

/*
 * Object types exported from the kernel.
 */
extern POBJECT_TYPE *ExWindowStationObjectType;
extern POBJECT_TYPE *ExDesktopObjectType;
extern POBJECT_TYPE *ExEventObjectType;
extern POBJECT_TYPE *IoDriverObjectType;

#ifndef DWORD_ALIGN
#define DWORD_ALIGN(x) ((x+3)&~3)
#endif // !DWORD_ALIGN

/*
 * Private probing macros
 */

#if defined(_X86_)
#define DATAALIGN sizeof(BYTE)
#define CHARALIGN sizeof(BYTE)
#else
#define DATAALIGN sizeof(DWORD)
#define CHARALIGN sizeof(WCHAR)
#endif

#define ProbeForReadBuffer(Address, Count, Alignment) {                     \
    if ((ULONG)(Count) > (ULONG)(MAXULONG / sizeof(*(Address)))) {          \
        ExRaiseAccessViolation();                                           \
    }                                                                       \
    ProbeForRead(Address, (ULONG)(Count) * sizeof(*(Address)), Alignment);  \
}

#define ProbeForWriteBuffer(Address, Count, Alignment) {                    \
    if ((ULONG)(Count) > (ULONG)(MAXULONG / sizeof(*(Address)))) {          \
        ExRaiseAccessViolation();                                           \
    }                                                                       \
    ProbeForWrite(Address, (ULONG)(Count) * sizeof(*(Address)), Alignment); \
}

#define ProbeAndReadSize(Address)                         \
    (((Address) >= (SIZE * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile SIZE * const)MM_USER_PROBE_ADDRESS) : (*(volatile SIZE *)(Address)))


#define ProbeAndReadBlendfunction(Address)                         \
    (((Address) >= (BLENDFUNCTION * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile BLENDFUNCTION * const)MM_USER_PROBE_ADDRESS) : (*(volatile BLENDFUNCTION *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadPoint(
//     IN PPOINT Address
//     )
//
//--

#define ProbePoint(Address)                                \
    (((Address) >= (POINT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DWORD * const)MM_USER_PROBE_ADDRESS) : (*(volatile DWORD *)(Address)))

#define ProbeAndReadPoint(Address)                         \
    (((Address) >= (POINT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile POINT * const)MM_USER_PROBE_ADDRESS) : (*(volatile POINT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadRect(
//     IN PRECT Address
//     )
//
//--

#define ProbeRect(Address)                                \
    (((Address) >= (RECT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DWORD * const)MM_USER_PROBE_ADDRESS) : (*(volatile DWORD *)(Address)))

#define ProbeAndReadRect(Address)                         \
    (((Address) >= (RECT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile RECT * const)MM_USER_PROBE_ADDRESS) : (*(volatile RECT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadMessage(
//     IN PMSG Address
//     )
//
//--

#define ProbeMessage(Address)                            \
    (((Address) >= (MSG * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DWORD * const)MM_USER_PROBE_ADDRESS) : (*(volatile DWORD *)(Address)))

#define ProbeAndReadMessage(Address)                     \
    (((Address) >= (MSG * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MSG * const)MM_USER_PROBE_ADDRESS) : (*(volatile MSG *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadLargeString(
//     IN PLARGE_STRING Address
//     )
//
//--

#define ProbeAndReadLargeString(Address)                          \
    (((Address) >= (LARGE_STRING * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile LARGE_STRING * const)MM_USER_PROBE_ADDRESS) : (*(volatile LARGE_STRING *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadWindowPlacement(
//     IN PWINDOWPLACEMENT Address
//     )
//
//--

#define ProbeAndReadWindowPlacement(Address)                         \
    (((Address) >= (WINDOWPLACEMENT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile WINDOWPLACEMENT * const)MM_USER_PROBE_ADDRESS) : (*(volatile WINDOWPLACEMENT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadMenuItem(
//     IN PMENUITEMINFO Address
//     )
//
//--

#define ProbeAndReadMenuItem(Address)                             \
    (((Address) >= (MENUITEMINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MENUITEMINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile MENUITEMINFO *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadMenuInfo(
//     IN PMENUINFO Address
//     )
//
//--

#define ProbeAndReadMenuInfo(Address)                             \
    (((Address) >= (MENUINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MENUINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile MENUINFO *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadScrollInfo(
//     IN PSCROLLINFO Address
//     )
//
//--

#define ProbeAndReadScrollInfo(Address)                         \
    (((Address) >= (SCROLLINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile SCROLLINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile SCROLLINFO *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadPopupParams(
//     IN PTPMPARAMS Address
//     )
//
//--

#define ProbeAndReadPopupParams(Address)                       \
    (((Address) >= (TPMPARAMS * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile TPMPARAMS * const)MM_USER_PROBE_ADDRESS) : (*(volatile TPMPARAMS *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadPaintStruct(
//     IN PPAINTSTRUCT Address
//     )
//
//--

#define ProbeAndReadPaintStruct(Address)                         \
    (((Address) >= (PAINTSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile PAINTSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile PAINTSTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCreateStruct(
//     IN PCREATESTRUCTW Address
//     )
//
//--

#define ProbeAndReadCreateStruct(Address)                          \
    (((Address) >= (CREATESTRUCTW * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile CREATESTRUCTW * const)MM_USER_PROBE_ADDRESS) : (*(volatile CREATESTRUCTW *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadMDICreateStruct(
//     IN PMDICREATESTRUCT Address
//     )
//
//--

#define ProbeAndReadMDICreateStruct(Address)                         \
    (((Address) >= (MDICREATESTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MDICREATESTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile MDICREATESTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCopyDataStruct(
//     IN PCOPYDATASTRUCT Address
//     )
//
//--

#define ProbeAndReadCopyDataStruct(Address)                         \
    (((Address) >= (COPYDATASTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile COPYDATASTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile COPYDATASTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCompareItemStruct(
//     IN PCOMPAREITEMSTRUCT Address
//     )
//
//--

#define ProbeAndReadCompareItemStruct(Address)                         \
    (((Address) >= (COMPAREITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile COMPAREITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile COMPAREITEMSTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadDeleteItemStruct(
//     IN PDELETEITEMSTRUCT Address
//     )
//
//--

#define ProbeAndReadDeleteItemStruct(Address)                         \
    (((Address) >= (DELETEITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DELETEITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile DELETEITEMSTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadHelp(
//     IN PHLP Address
//     )
//
//--

#define ProbeAndReadHelp(Address)                        \
    (((Address) >= (HLP * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile HLP * const)MM_USER_PROBE_ADDRESS) : (*(volatile HLP *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadHelpInfo(
//     IN PHELPINFO Address
//     )
//
//--

#define ProbeAndReadHelpInfo(Address)                         \
    (((Address) >= (HELPINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile HELPINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile HELPINFO *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadDrawItemStruct(
//     IN PDRAWITEMSTRUCT Address
//     )
//
//--

#define ProbeAndReadDrawItemStruct(Address)                         \
    (((Address) >= (DRAWITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DRAWITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile DRAWITEMSTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadHookInfo(
//     IN PDEBUGHOOKINFO Address
//     )
//
//--

#define ProbeAndReadHookInfo(Address)                              \
    (((Address) >= (DEBUGHOOKINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile DEBUGHOOKINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile DEBUGHOOKINFO *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCBTActivateStruct(
//     IN PCBTACTIVATESTRUCT Address
//     )
//
//--

#define ProbeAndReadCBTActivateStruct(Address)                         \
    (((Address) >= (CBTACTIVATESTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile CBTACTIVATESTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile CBTACTIVATESTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadKbdHook(
//     IN PKBDHOOKSTRUCT Address
//     )
//
//--

#define ProbeAndReadKbdHook(Address)                               \
    (((Address) >= (KBDLLHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile KBDLLHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile KBDLLHOOKSTRUCT *)(Address)))
//++
//
// BOOLEAN
// ProbeAndReadMsllHook(
//     IN PMSLLHOOKSTRUCT Address
//     )
//
//--

#define ProbeAndReadMsllHook(Address)                               \
    (((Address) >= (MSLLHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MSLLHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile MSLLHOOKSTRUCT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadMouseHook(
//     IN PMOUSEHOOKSTRUCTEX Address
//     )
//
//--

#define ProbeAndReadMouseHook(Address)                               \
    (((Address) >= (MOUSEHOOKSTRUCTEX * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MOUSEHOOKSTRUCTEX * const)MM_USER_PROBE_ADDRESS) : (*(volatile MOUSEHOOKSTRUCTEX *)(Address)))


#ifdef REDIRECTION

//++
//
// BOOLEAN
// ProbeAndReadHTHook(
//     IN PHTHOOKSTRUCT Address
//     )
//
//--

#define ProbeAndReadHTHook(Address)                               \
    (((Address) >= (HTHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile HTHOOKSTRUCT * const)MM_USER_PROBE_ADDRESS) : (*(volatile HTHOOKSTRUCT *)(Address)))

#endif // REDIRECTION

//++
//
// BOOLEAN
// ProbeAndReadCBTCreateStruct(
//     IN PCBT_CREATEWND Address
//     )
//
//--

#define ProbeAndReadCBTCreateStruct(Address)                       \
    (((Address) >= (CBT_CREATEWND * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile CBT_CREATEWND * const)MM_USER_PROBE_ADDRESS) : (*(volatile CBT_CREATEWND *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadTrackMouseEvent(
//     IN LPTRACKMOUSEEVENT Address
//     )
//
//--

#define ProbeAndReadTrackMouseEvent(Address) \
    (((Address) >= (TRACKMOUSEEVENT * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile TRACKMOUSEEVENT * const)MM_USER_PROBE_ADDRESS) : (*(volatile TRACKMOUSEEVENT *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadWindowPos(
//     IN PWINDOWPOS Address
//     )
//
//--

#define ProbeAndReadWindowPos(Address) \
    (((Address) >= (WINDOWPOS * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile WINDOWPOS * const)MM_USER_PROBE_ADDRESS) : (*(volatile WINDOWPOS *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCursorFind(
//     IN PCURSORFIND Address
//     )
//
//--

#define ProbeAndReadCursorFind(Address) \
    (((Address) >= (CURSORFIND * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile CURSORFIND * const)MM_USER_PROBE_ADDRESS) : (*(volatile CURSORFIND *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadSetClipBData(
//     IN PSETCLIPBDATA Address
//     )
//
//--

#define ProbeAndReadSetClipBData(Address) \
    (((Address) >= (SETCLIPBDATA * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile SETCLIPBDATA * const)MM_USER_PROBE_ADDRESS) : (*(volatile SETCLIPBDATA *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadBroadcastSystemMsgParams(
//     IN LPBROADCASTSYSTEMMSGPARAMS Address
//     )
//
//--

#define ProbeAndReadBroadcastSystemMsgParams(Address) \
    (((Address) >= (BROADCASTSYSTEMMSGPARAMS * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile BROADCASTSYSTEMMSGPARAMS * const)MM_USER_PROBE_ADDRESS) : (*(volatile BROADCASTSYSTEMMSGPARAMS *)(Address)))

//++
//
// BOOLEAN
// ProbeAndReadCursorData(
//     IN PCURSORDATA Address
//     )
//
//--

#define ProbeAndReadCursorData(Address) \
    (((Address) >= (CURSORDATA * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile CURSORDATA * const)MM_USER_PROBE_ADDRESS) : (*(volatile CURSORDATA *)(Address)))

//++
//
// BOOLEAN
// ProbeForReadUnicodeStringBuffer(
//     IN UNICODE_STRING String
//     )
//
//--

#if defined(_X86_)
#define ProbeForReadUnicodeStringBuffer(String)                                                          \
    if (((ULONG_PTR)((String).Buffer) & (sizeof(BYTE) - 1)) != 0) {                                   \
        ExRaiseDatatypeMisalignment();                                                            \
    } else if ((((ULONG_PTR)((String).Buffer) + ((String).Length) + sizeof(UNICODE_NULL)) < (ULONG_PTR)((String).Buffer)) ||     \
               (((ULONG_PTR)((String).Buffer) + ((String).Length) + sizeof(UNICODE_NULL)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \
        ExRaiseAccessViolation();                                                                 \
    } else if (((String).Length) > ((String).MaximumLength)) {                                    \
        ExRaiseAccessViolation();                                                                 \
    }
#else
#define ProbeForReadUnicodeStringBuffer(String)                                                          \
    if (((ULONG_PTR)((String).Buffer) & (sizeof(WCHAR) - 1)) != 0) {                                  \
        ExRaiseDatatypeMisalignment();                                                            \
    } else if ((((ULONG_PTR)((String).Buffer) + ((String).Length) + sizeof(UNICODE_NULL)) < (ULONG_PTR)((String).Buffer)) ||     \
               (((ULONG_PTR)((String).Buffer) + ((String).Length) + sizeof(UNICODE_NULL)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \
        ExRaiseAccessViolation();                                                                 \
    } else if (((String).Length) > ((String).MaximumLength)) {                                    \
        ExRaiseAccessViolation();                                                                 \
    }
#endif

#if defined(_X86_)
#define ProbeForReadUnicodeStringFullBuffer(String)                                                          \
    if (((ULONG_PTR)((String).Buffer) & (sizeof(BYTE) - 1)) != 0) {                                   \
        ExRaiseDatatypeMisalignment();                                                            \
    } else if ((((ULONG_PTR)((String).Buffer) + ((String).MaximumLength)) < (ULONG_PTR)((String).Buffer)) ||     \
               (((ULONG_PTR)((String).Buffer) + ((String).MaximumLength)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \
        ExRaiseAccessViolation();                                                                 \
    } else if (((String).Length) > ((String).MaximumLength)) {                                    \
        ExRaiseAccessViolation();                                                                 \
    }
#else
#define ProbeForReadUnicodeStringFullBuffer(String)                                                          \
    if (((ULONG_PTR)((String).Buffer) & (sizeof(WCHAR) - 1)) != 0) {                                  \
        ExRaiseDatatypeMisalignment();                                                            \
    } else if ((((ULONG_PTR)((String).Buffer) + ((String).MaximumLength)) < (ULONG_PTR)((String).Buffer)) ||     \
               (((ULONG_PTR)((String).Buffer) + ((String).MaximumLength)) > (ULONG_PTR)MM_USER_PROBE_ADDRESS)) { \
        ExRaiseAccessViolation();                                                                 \
    } else if (((String).Length) > ((String).MaximumLength)) {                                    \
        ExRaiseAccessViolation();                                                                 \
    }
#endif

//++
//
// BOOLEAN
// ProbeForReadUnicodeStringBufferOrId(
//     IN UNICODE_STRING String
//     )
//
//--

#define ProbeForReadUnicodeStringBufferOrId(String) \
    if (IS_PTR((String).Buffer)) {           \
        ProbeForReadUnicodeStringBuffer(String);    \
    }

    //++
    //
    // BOOLEAN
    // ProbeAndReadCandidateForm(
    //     IN PCANDIDATEFORM Address
    //     )
    //
    //--

    #define ProbeAndReadCandidateForm(Address) \
        (((Address) >= (CANDIDATEFORM * const)MM_USER_PROBE_ADDRESS) ? \
            (*(volatile CANDIDATEFORM * const)MM_USER_PROBE_ADDRESS) : (*(volatile CANDIDATEFORM *)(Address)))

    //++
    //
    // BOOLEAN
    // ProbeAndReadCompositionForm(
    //     IN PCANDIDATEFORM Address
    //     )
    //
    //--

    #define ProbeAndReadCompositionForm(Address) \
        (((Address) >= (COMPOSITIONFORM * const)MM_USER_PROBE_ADDRESS) ? \
            (*(volatile COMPOSITIONFORM * const)MM_USER_PROBE_ADDRESS) : (*(volatile COMPOSITIONFORM *)(Address)))

    //++
    //
    // BOOLEAN
    // ProbeAndReadLogFontW(
    //     IN PLOGFONTA Address
    //     )
    //
    //--

    #define ProbeAndReadLogFontW(Address) \
        (((Address) >= (LOGFONTW * const)MM_USER_PROBE_ADDRESS) ? \
            (*(volatile LOGFONTW * const)MM_USER_PROBE_ADDRESS) : (*(volatile LOGFONTW *)(Address)))


//++
//
// VOID
// ProbeForWritePoint(
//     IN PPOINT Address
//     )
//
//--

#define ProbeForWritePoint(Address) {                                        \
    if ((Address) >= (POINT * const)MM_USER_PROBE_ADDRESS) {                 \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile POINT *)(Address) = *(volatile POINT *)(Address);             \
}

//++
//
// VOID
// ProbeForWriteRect(
//     IN PRECT Address
//     )
//
//--

#define ProbeForWriteRect(Address) {                                         \
    if ((Address) >= (RECT * const)MM_USER_PROBE_ADDRESS) {                  \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile RECT *)(Address) = *(volatile RECT *)(Address);               \
}

//++
//
// VOID
// ProbeForWriteMessage(
//     IN PMSG Address
//     )
//
//--

#define ProbeForWriteMessage(Address) {                                      \
    if ((Address) >= (MSG * const)MM_USER_PROBE_ADDRESS) {                   \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile MSG *)(Address) = *(volatile MSG *)(Address);                 \
}

//++
//
// VOID
// ProbeForWritePaintStruct(
//     IN PPAINTSTRUCT Address
//     )
//
//--

#define ProbeForWritePaintStruct(Address) {                                  \
    if ((Address) >= (PAINTSTRUCT * const)MM_USER_PROBE_ADDRESS) {           \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile PAINTSTRUCT *)(Address) = *(volatile PAINTSTRUCT *)(Address); \
}

//++
//
// VOID
// ProbeForWriteDropStruct(
//     IN PDROPSTRUCT Address
//     )
//
//--

#define ProbeForWriteDropStruct(Address) {                                   \
    if ((Address) >= (DROPSTRUCT * const)MM_USER_PROBE_ADDRESS) {            \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile DROPSTRUCT *)(Address) = *(volatile DROPSTRUCT *)(Address);   \
}

//++
//
// VOID
// ProbeForWriteScrollInfo(
//     IN PSCROLLINFO Address
//     )
//
//--

#define ProbeForWriteScrollInfo(Address) {                                   \
    if ((Address) >= (SCROLLINFO * const)MM_USER_PROBE_ADDRESS) {            \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile SCROLLINFO *)(Address) = *(volatile SCROLLINFO *)(Address);   \
}

//++
//
// VOID
// ProbeForWriteStyleStruct(
//     IN PSTYLESTRUCT Address
//     )
//
//--

#define ProbeForWriteStyleStruct(Address) {                                  \
    if ((Address) >= (STYLESTRUCT * const)MM_USER_PROBE_ADDRESS) {           \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile STYLESTRUCT *)(Address) = *(volatile STYLESTRUCT *)(Address); \
}

//++
//
// VOID
// ProbeForWriteMeasureItemStruct(
//     IN PMEASUREITEMSTRUCT Address
//     )
//
//--

#define ProbeForWriteMeasureItemStruct(Address) {                                       \
    if ((Address) >= (MEASUREITEMSTRUCT * const)MM_USER_PROBE_ADDRESS) {                \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                             \
    }                                                                                   \
                                                                                        \
    *(volatile MEASUREITEMSTRUCT *)(Address) = *(volatile MEASUREITEMSTRUCT *)(Address);\
}

//++
//
// VOID
// ProbeForWriteCreateStruct(
//     IN PCREATESTRUCTW Address
//     )
//
//--

#define ProbeForWriteCreateStruct(Address) {                                    \
    if ((Address) >= (CREATESTRUCTW * const)MM_USER_PROBE_ADDRESS) {            \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                     \
    }                                                                           \
                                                                                \
    *(volatile CREATESTRUCTW *)(Address) = *(volatile CREATESTRUCTW *)(Address);\
}

//++
//
// VOID
// ProbeForWriteEvent(
//     IN PEVENTMSGMSG Address
//     )
//
//--

#define ProbeForWriteEvent(Address) {                                        \
    if ((Address) >= (EVENTMSG * const)MM_USER_PROBE_ADDRESS) {              \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile EVENTMSG *)(Address) = *(volatile EVENTMSG *)(Address);       \
}

//++
//
// VOID
// ProbeForWriteWindowPlacement(
//     IN PWINDOWPLACEMENT Address
//     )
//
//--

#define ProbeForWriteWindowPlacement(Address) {                                     \
    if ((Address) >= (WINDOWPLACEMENT * const)MM_USER_PROBE_ADDRESS) {              \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile WINDOWPLACEMENT *)(Address) = *(volatile WINDOWPLACEMENT *)(Address);\
}

//++
//
// VOID
// ProbeForWriteGetClipData(
//     IN PGETCLIPBDATA Address
//     )
//
//--

#define ProbeForWriteGetClipData(Address) {                                   \
    if ((Address) >= (GETCLIPBDATA * const)MM_USER_PROBE_ADDRESS) {           \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                   \
    }                                                                         \
                                                                              \
    *(volatile GETCLIPBDATA *)(Address) = *(volatile GETCLIPBDATA *)(Address);\
}

//++
//
// VOUD
// ProbeForWriteBroadcastSystemMsgParams(
//     IN LPBROADCASTSYSTEMMSGPARAMS Address
//     )
//
//--

#define ProbeForWriteBroadcastSystemMsgParams(Address) {                                                \
    if ((Address) >= (BROADCASTSYSTEMMSGPARAMS * const)MM_USER_PROBE_ADDRESS) {                         \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                                             \
    }                                                                                                   \
                                                                                                        \
    *(volatile BROADCASTSYSTEMMSGPARAMS *)(Address) = *(volatile BROADCASTSYSTEMMSGPARAMS *)(Address);  \
}

//++
//
// VOID
// ProbeForWriteMDINextMenu(
//     IN PMDINEXTMENU Address
//     )
//
//--

#define ProbeForWriteMDINextMenu(Address) {                                  \
    if ((Address) >= (MDINEXTMENU * const)MM_USER_PROBE_ADDRESS) {           \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                  \
    }                                                                        \
                                                                             \
    *(volatile MDINEXTMENU *)(Address) = *(volatile MDINEXTMENU *)(Address); \
}

//++
//
// VOID
// ProbeForWritePoint5(
//     IN PPOINT5 Address
//     )
//
//--

#define ProbeForWritePoint5(Address) {                                     \
    if ((Address) >= (POINT5 * const)MM_USER_PROBE_ADDRESS) {              \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile POINT5 *)(Address) = *(volatile POINT5 *)(Address);\
}

//++
//
// VOID
// ProbeForWriteNCCalcSize(
//     IN PNCCALCSIZE_PARAMS Address
//     )
//
//--

#define ProbeForWriteNCCalcSize(Address) {                                     \
    if ((Address) >= (NCCALCSIZE_PARAMS * const)MM_USER_PROBE_ADDRESS) {              \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile NCCALCSIZE_PARAMS *)(Address) = *(volatile NCCALCSIZE_PARAMS *)(Address);\
}

//++
//
// VOID
// ProbeForWriteWindowPos(
//     IN PWINDOWPOS Address
//     )
//
//--

#define ProbeForWriteWindowPos(Address) {                                     \
    if ((Address) >= (WINDOWPOS * const)MM_USER_PROBE_ADDRESS) {              \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile WINDOWPOS *)(Address) = *(volatile WINDOWPOS *)(Address);\
}

#define ProbeForWriteComboBoxInfo(Address) {                                        \
    if ((Address) >= (COMBOBOXINFO * const)MM_USER_PROBE_ADDRESS) {                 \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile COMBOBOXINFO *)(Address) = *(volatile COMBOBOXINFO *)(Address);      \
}

#define ProbeForWriteScrollBarInfo(Address) {                                       \
    if ((Address) >= (SCROLLBARINFO * const)MM_USER_PROBE_ADDRESS) {                \
        *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
    }                                                                               \
                                                                                    \
    *(volatile SCROLLBARINFO *)(Address) = *(volatile SCROLLBARINFO *)(Address);    \
}


    //++
    //
    // VOID
    // ProbeForWriteCandidateForm(
    //     IN PCANDIDATEFORM Address
    //     )
    //
    //--

    #define ProbeForWriteCandidateForm(Address) {                                     \
        if ((Address) >= (CANDIDATEFORM * const)MM_USER_PROBE_ADDRESS) {              \
            *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                       \
        }                                                                             \
                                                                                      \
        *(volatile CANDIDATEFORM *)(Address) = *(volatile CANDIDATEFORM *)(Address);  \
    }

    //++
    //
    // VOID
    // ProbeForWriteCompositionForm(
    //     IN PCOMPOSITIONFORM Address
    //     )
    //
    //--

    #define ProbeForWriteCompositionForm(Address) {                                     \
        if ((Address) >= (COMPOSITIONFORM * const)MM_USER_PROBE_ADDRESS) {              \
            *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                         \
        }                                                                               \
                                                                                        \
        *(volatile COMPOSITIONFORM *)(Address) = *(volatile COMPOSITIONFORM *)(Address);\
    }

    //++
    //
    // VOID
    // ProbeForWriteLogFontW(
    //     IN PLOGFONTW Address
    //     )
    //
    //--

    #define ProbeForWriteLogFontW(Address) {                                   \
        if ((Address) >= (LOGFONTW * const)MM_USER_PROBE_ADDRESS) {            \
            *(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0;                \
        }                                                                      \
                                                                               \
        *(volatile LOGFONTW *)(Address) = *(volatile LOGFONTW *)(Address);     \
    }

//++
//
// VOID
// ProbeForWriteReconvertString(IN PRECONVERTSTRING Address)
//
//--

#define ProbeForWriteReconvertString(Address) { \
    if ((Address) >= (RECONVERTSTRING* const)MM_USER_PROBE_ADDRESS) {           \
        *(volatile ULONG* const)MM_USER_PROBE_ADDRESS = 0;                      \
    }                                                                           \
                                                                                \
    *(volatile RECONVERTSTRING*)(Address) = *(volatile RECONVERTSTRING*)(Address); \
    *((volatile BYTE*)(Address) + (Address)->dwSize) = *((volatile BYTE*)(Address) + (Address)->dwSize); \
}

#define ProbeForReadReconvertString(pReconv) \
    ProbeForRead((pReconv), (pReconv)->dwSize, 1)


//++
//
// VOID
// ProbeForWriteImeCharPosition(IN LPPrivateIMECHARPOSITION Address)
//
//--

#define ProbeForWriteImeCharPosition(Address) { \
    if ((Address) >= (PrivateIMECHARPOSITION* const)MM_USER_PROBE_ADDRESS) {    \
        *(volatile ULONG* const)MM_USER_PROBE_ADDRESS = 0;                      \
    }                                                                           \
                                                                                \
    *(volatile PrivateIMECHARPOSITION*)(Address) = *(volatile PrivateIMECHARPOSITION*)(Address); \
}



//++
//
// VOID
// ProbeAndReadMenuGetObjectInfo(
//     IN PMENUGETOBJECTINFO Address
//     )
//
//--

#define ProbeAndReadMenuGetObjectInfo(Address) \
    (((Address) >= (MENUGETOBJECTINFO * const)MM_USER_PROBE_ADDRESS) ? \
        (*(volatile MENUGETOBJECTINFO * const)MM_USER_PROBE_ADDRESS) : (*(volatile MENUGETOBJECTINFO *)(Address)))


/*
 * This macro makes sure an object is thread locked. DEBUG only.
 */
#if DBG
    VOID CheckLock(PVOID pobj);
#else // DBG
    #define CheckLock(p)
#endif // DBG

/*
 * Debug macros
 */
#if DBG

    #define TRACE_INIT(str)    { if (TraceInitialization > 0) {  KdPrint(str); }}
    #define TRACE_SWITCH(str)  { if (TraceFullscreenSwitch > 0)  {  KdPrint(str); }}

    extern PCSZ apszSimpleCallNames[];

    #define TRACE(s)            TAGMSG2(DBGTAG_StubReturn, "%s, retval = %x", (s), retval)
    #define TRACEVOID(s)        TAGMSG1(DBGTAG_StubReturn, "%s", (s))

    #define TRACETHUNK(t)                                                       \
                TAGMSG3(DBGTAG_StubThunk,                                       \
                        "Thunk %s, %s(%s)",                                     \
                        (t),                                                    \
                        (xpfnProc >= FNID_START && xpfnProc <= FNID_END ?       \
                                gapszFNID[xpfnProc - FNID_START] : "Unknown"),  \
                        (msg >= WM_USER ? "WM_USER" : gapszMessage[msg]))

    #define TRACECALLBACK(s)    TAGMSG2(DBGTAG_StubCallback, "%s, retval = %x", (s), retval)

    #define TRACECALLBACKMSG(s)                                                         \
                TAGMSG4(DBGTAG_StubCallback,                                            \
                        "Callback %s, %s(%s), retval = %x",                             \
                        (s),                                                            \
                        (xpfnProc >= (PROC)FNID_START && xpfnProc <= (PROC)FNID_END ?   \
                            gapszFNID[(ULONG_PTR)xpfnProc - FNID_START] : "Unknown"),    \
                        (msg >= WM_USER ? "WM_USER" : gapszMessage[msg]),               \
                        retval)
#else // DBG

    #define TRACE_INIT(str) {}
    #define TRACE_SWITCH(str) {}
    #define TRACE(s)
    #define TRACEVOID(s)
    #define TRACETHUNK(t)
    #define TRACECALLBACK(t)
    #define TRACECALLBACKMSG(t)

#endif // DBG

/*
 * Statistics for performance counter
 */

typedef struct tagPERFINFO {
    LONG               lCount;
    LONG               lMaxCount;
    LONG               lTotalCount;
    SIZE_T             lSize;
} PERFHANDLEINFO, *PPERFHANDLEINFO;

typedef struct _HANDLEPAGE {
    ULONG_PTR iheLimit;    /* first handle index past the end of the page */
    ULONG_PTR iheFreeEven; /* first even free handle in the page -- window objects */
    ULONG_PTR iheFreeOdd;  /* first even odd handle in the page */
} HANDLEPAGE, *PHANDLEPAGE;


#if DBG
VOID  HMCleanUpHandleTable(VOID);
DWORD DbgDumpHandleTable(VOID);
#endif

BOOL     HMInitHandleTable(PVOID pBase);
PVOID    HMAllocObject(PTHREADINFO pti, PDESKTOP pdesk, BYTE btype, DWORD size);
BOOL     HMFreeObject(PVOID pobj);
BOOL     HMMarkObjectDestroy(PVOID pobj);
BOOL     HMDestroyObject(PVOID pobj);
PVOID FASTCALL HMAssignmentLock(PVOID *ppobj, PVOID pobj);
PVOID FASTCALL HMAssignmentUnlock(PVOID *ppobj);
NTSTATUS HMGetStats(HANDLE hProcess, int iPidType, PVOID pResults, UINT cjResultSize);
HANDLE   KernelPtoH(PVOID pObj);
void     HMDestroyUnlockedObject(PHE phe);

void     HMCleanupGrantedHandle(HANDLE h);

/*
 * Validation, handle mapping, etc.
 */
#define RevalidateHwnd(hwnd)   HMValidateHandleNoSecure(hwnd, TYPE_WINDOW)
#define RevalidateCatHwnd(hwnd)   HMValidateCatHandleNoSecure(hwnd, TYPE_WINDOW)

#define HtoPq(h)    ((PVOID)HMObjectFromHandle(h))
#define HtoPqCat(h)    ((PVOID)HMCatObjectFromHandle(h))
#define HtoP(h)     ((PVOID)HMObjectFromHandle(h))
#define HtoPCat(h)     ((PVOID)HMCatObjectFromHandle(h))
#define PW(hwnd)    ((PWND)HtoP(hwnd))
#define PWCat(hwnd)    ((PWND)HtoPCat(hwnd))
#define TID(pti)    HandleToUlong((pti) == NULL ? NULL : (PsGetThreadId((pti)->pEThread)))
#define TIDq(pti)   HandleToUlong(PsGetThreadId((pti)->pEThread))

/*
 * Assignment lock macro -> used for locking objects embedded in structures
 * and globals. Threadlocks used for locking objects across callbacks.
 */
#define Lock(ppobj, pobj) HMAssignmentLock((PVOID *)ppobj, (PVOID)pobj)
#define Unlock(ppobj)     HMAssignmentUnlock((PVOID *)ppobj)

PVOID HMUnlockObjectInternal(PVOID pobj);

#define HMUnlockObject(pobj) \
    ( (--((PHEAD)pobj)->cLockObj == 0) ? HMUnlockObjectInternal(pobj) : pobj )

VOID HMChangeOwnerThread(PVOID pobj, PTHREADINFO pti);
VOID HMChangeOwnerPheProcess(PHE phe, PTHREADINFO pti);
#define HMChangeOwnerProcess(pobj, pti) HMChangeOwnerPheProcess(HMPheFromObject(pobj), pti)

#if DBG
    VOID  HMLockObject(PVOID pobj);
    BOOL  HMRelocateLockRecord(PVOID ppobjOld, LONG_PTR cbDelta);
#else // DBG
    #define HMLockObject(p)     (((PHEAD)p)->cLockObj++)
#endif // DBG

#if DBG
    VOID ThreadLock(PVOID pobj, PTL ptl);
#else // DBG
    #define ThreadLock(_pobj_, _ptl_)          \
    {                                          \
        PTHREADINFO _pti_;                     \
        PVOID __pobj_ = (_pobj_);              \
                                               \
        _pti_ = PtiCurrent();                  \
        (_ptl_)->next = _pti_->ptl;            \
        _pti_->ptl = (_ptl_);                  \
        (_ptl_)->pobj = __pobj_;              \
        if (__pobj_ != NULL) {                \
            HMLockObject(__pobj_);            \
        }                                      \
    }
#endif // DBG

#if DBG
    #define ThreadLockAlways(_pobj_, _ptl_)    \
    {                                          \
        PVOID __pobj_ = (_pobj_);              \
        UserAssert(__pobj_ != NULL);          \
        ThreadLock(__pobj_, _ptl_);             \
    }
#else // DBG
    #define ThreadLockAlways(_pobj_, _ptl_)    \
    {                                          \
        PTHREADINFO _pti_;                     \
        PVOID __pobj_ = (_pobj_);              \
                                               \
        _pti_ = PtiCurrent();                  \
        (_ptl_)->next = _pti_->ptl;            \
        _pti_->ptl = (_ptl_);                  \
        (_ptl_)->pobj = __pobj_;              \
        HMLockObject(__pobj_);                \
    }
#endif // DBG

#if DBG
    #define ThreadLockNever(_ptl_)             \
    {                                          \
        ThreadLock(NULL, _ptl_);               \
    }
#else // DBG
    #define ThreadLockNever(_ptl_)             \
    {                                          \
        PTHREADINFO _pti_;                     \
                                               \
        _pti_ = PtiCurrent();                  \
        (_ptl_)->next = _pti_->ptl;            \
        _pti_->ptl = (_ptl_);                  \
        (_ptl_)->pobj = NULL;                  \
    }
#endif // DBG

#if DBG
    #define ThreadLockAlwaysWithPti(_pti_, _pobj_, _ptl_)  \
    {                                          \
        PVOID __pobj_ = (_pobj_);              \
        UserAssert(_pti_ == PtiCurrentShared());     \
        UserAssert(__pobj_ != NULL);          \
        ThreadLock(__pobj_, _ptl_);             \
    }
#else // DBG
    #define ThreadLockAlwaysWithPti(_pti_, _pobj_, _ptl_)  \
    {                                          \
        PVOID __pobj_ = (_pobj_);              \
        (_ptl_)->next = _pti_->ptl;            \
        _pti_->ptl = (_ptl_);                  \
        (_ptl_)->pobj = __pobj_;              \
        HMLockObject(__pobj_);                \
    }
#endif // DBG

#if DBG
    #define ThreadLockNeverWithPti(_pti_, _ptl_)    \
    {                                               \
        UserAssert(_pti_ == PtiCurrentShared());    \
        ThreadLock(NULL, _ptl_);                    \
    }
#else // DBG
    #define ThreadLockNeverWithPti(_pti_, _ptl_)    \
    {                                               \
        (_ptl_)->next = _pti_->ptl;                 \
        _pti_->ptl = (_ptl_);                       \
        (_ptl_)->pobj = NULL;                       \
    }
#endif // DBG

#if DBG
    #define ThreadLockWithPti(_pti_, _pobj_, _ptl_) \
    {                                               \
        PVOID __pobj_ = (_pobj_);              \
        UserAssert(_pti_ == PtiCurrentShared());    \
        ThreadLock(__pobj_, _ptl_);                  \
    }
#else // DBG
    #define ThreadLockWithPti(_pti_, _pobj_, _ptl_) \
    {                                               \
        PVOID __pobj_ = (_pobj_);              \
        (_ptl_)->next = _pti_->ptl;                 \
        _pti_->ptl = (_ptl_);                       \
        (_ptl_)->pobj = __pobj_;                   \
        if (__pobj_ != NULL) {                     \
            HMLockObject(__pobj_);                 \
        }                                           \
    }
#endif // DBG

#if DBG
    PVOID ThreadLockExchange(PVOID pobj, PTL ptl);
#else // DBG
    __inline PVOID ThreadLockExchange(PVOID pobj, PTL ptl)
    {
        PVOID   pobjOld;

        pobjOld = ptl->pobj;
        ptl->pobj = pobj;
        if (pobj) {
            HMLockObject(pobj);
        }

        if (pobjOld) {
            pobjOld = HMUnlockObject((PHEAD)pobjOld);
        }

        return pobjOld;
    }
#endif // DBG

#if DBG
    #define ThreadLockExchangeAlways(_pobj_, _ptl_)    \
    {                                                  \
        PVOID __pobj_ = (_pobj_);              \
        UserAssert(__pobj_ != NULL);                  \
        ThreadLockExchange(__pobj_, _ptl_);             \
    }
#else // DBG
    __inline PVOID ThreadLockExchangeAlways(PVOID pobj, PTL ptl)
    {
        PVOID   pobjOld;

        pobjOld = ptl->pobj;
        ptl->pobj = pobj;
        HMLockObject(pobj);
        if (pobjOld) {
            pobjOld = HMUnlockObject((PHEAD)pobjOld);
        }

        return pobjOld;
    }
#endif // DBG

#if DBG
    PVOID ThreadUnlock1(PTL ptl);
    #define ThreadUnlock(ptl) ThreadUnlock1(ptl)
#else // DBG
    PVOID ThreadUnlock1(VOID);
    #define ThreadUnlock(ptl) ThreadUnlock1()
#endif // DBG

/*
 * Define this only if you want to track down lock/unlock mismatches
 * for desktop objects.
 */
#if DBG
// #define LOGDESKTOPLOCKS
#endif // DBG

#ifdef LOGDESKTOPLOCKS

/*
 * this is the structure used by the desktop logging stuff
 */
typedef struct tagLogD {
    WORD   tag;         // tag
    WORD   type;        // lock | unlock
    ULONG_PTR extra;    // extra information to identify the lock/unlock
    PVOID  trace[6];    // stack trace
} LogD, *PLogD;

/*
 * Tags for LOCK/UNLOCK REFERENCE/DEREFERENCE calls for
 * desktop objects
 */

#define LDU_CLS_DESKPARENT1                 1
#define LDL_CLS_DESKPARENT1                 2

#define LDU_CLS_DESKPARENT2                 3
#define LDL_CLS_DESKPARENT2                 5

#define LDU_FN_DESTROYCLASS                 6
#define LDL_FN_DESTROYCLASS                 7

#define LDU_FN_DESTROYMENU                  8
#define LDL_FN_DESTROYMENU                  9

#define LDU_FN_DESTROYTHREADINFO            10
#define LDL_FN_DESTROYTHREADINFO            11

#define LDU_FN_DESTROYWINDOWSTATION         12
#define LDL_FN_DESTROYWINDOWSTATION         13

#define LDU_DESKDISCONNECT                  14
#define LDL_DESKDISCONNECT                  15

#define LDU_DESK_DESKNEXT                   16
#define LDL_DESK_DESKNEXT1                  17

#define LDU_OBJ_DESK                        18
#define LDL_OBJ_DESK                        19
#define LDL_MOTHERDESK_DESK1                20

#define LDL_PTI_DESK                        21
#define LDL_DT_DESK                         23

#define LDU_PTI_DESK                        24

#define LDU_PPI_DESKSTARTUP1                26
#define LDU_PPI_DESKSTARTUP2                27
#define LDU_PPI_DESKSTARTUP3                28
#define LDL_PPI_DESKSTARTUP1                29
#define LDL_PPI_DESKSTARTUP2                30

#define LDU_DESKLOGON                       31
#define LDL_DESKLOGON                       32

#define LDUT_FN_FREEWINDOW                  33
#define LDLT_FN_FREEWINDOW                  34

#define LDUT_FN_DESKTOPTHREAD_DESK          35
#define LDLT_FN_DESKTOPTHREAD_DESK          36

#define LDUT_FN_DESKTOPTHREAD_DESKTEMP      37
#define LDLT_FN_DESKTOPTHREAD_DESKTEMP      38

#define LDUT_FN_SETDESKTOP                  39
#define LDLT_FN_SETDESKTOP                  40

#define LDUT_FN_NTUSERSWITCHDESKTOP         41
#define LDLT_FN_NTUSERSWITCHDESKTOP         42

#define LDUT_FN_SENDMESSAGEBSM1             43
#define LDUT_FN_SENDMESSAGEBSM2             44
#define LDLT_FN_SENDMESSAGEBSM              45

#define LDUT_FN_SYSTEMBROADCASTMESSAGE      46
#define LDLT_FN_SYSTEMBROADCASTMESSAGE      47

#define LDUT_FN_CTXREDRAWSCREEN             48
#define LDLT_FN_CTXREDRAWSCREEN             49

#define LDUT_FN_CTXDISABLESCREEN            50
#define LDLT_FN_CTXDISABLESCREEN            51

#define LD_DEREF_FN_CREATEDESKTOP1          52
#define LD_DEREF_FN_CREATEDESKTOP2          53
#define LD_DEREF_FN_CREATEDESKTOP3          54
#define LD_REF_FN_CREATEDESKTOP             55

#define LD_DEREF_FN_OPENDESKTOP             56
#define LD_REF_FN_OPENDESKTOP               57

#define LD_DEREF_FN_SETDESKTOP              58
#define LD_REF_FN_SETDESKTOP                59

#define LD_DEREF_FN_GETTHREADDESKTOP        60
#define LD_REF_FN_GETTHREADDESKTOP          61

#define LD_DEREF_FN_CLOSEDESKTOP1           62
#define LD_DEREF_FN_CLOSEDESKTOP2           63
#define LD_REF_FN_CLOSEDESKTOP              64

#define LD_DEREF_FN_RESOLVEDESKTOP          65
#define LD_REF_FN_RESOLVEDESKTOP            66

#define LD_DEREF_VALIDATE_HDESK1            67
#define LD_DEREF_VALIDATE_HDESK2            68
#define LD_DEREF_VALIDATE_HDESK3            69
#define LD_DEREF_VALIDATE_HDESK4            70
#define LDL_VALIDATE_HDESK                  71

#define LDUT_FN_CREATETHREADINFO1           72
#define LDUT_FN_CREATETHREADINFO2           73
#define LDLT_FN_CREATETHREADINFO            74

#define LD_DEREF_FN_SETCSRSSTHREADDESKTOP1  75
#define LD_DEREF_FN_SETCSRSSTHREADDESKTOP2  76
#define LD_REF_FN_SETCSRSSTHREADDESKTOP     77

#define LD_DEREF_FN_CONSOLECONTROL1         78
#define LD_REF_FN_CONSOLECONTROL1           79

#define LD_DEREF_FN_CONSOLECONTROL2         80
#define LD_REF_FN_CONSOLECONTROL2           81

#define LD_DEREF_FN_GETUSEROBJECTINFORMATION 82
#define LD_REF_FN_GETUSEROBJECTINFORMATION   83

#define LD_DEREF_FN_SETUSEROBJECTINFORMATION 84
#define LD_REF_FN_SETUSEROBJECTINFORMATION   85

#define LD_DEREF_FN_CREATEWINDOWSTATION     86
#define LD_REF_FN_CREATEWINDOWSTATION       87

#define LDL_TERM_DESKDESTROY1               88
#define LDL_TERM_DESKDESTROY2               89

#define LDL_MOTHERDESK_DESK2                92

#define LDL_WINSTA_DESKLIST2                93
#define LDL_WINSTA_DESKLIST1                94

#define LDL_DESKRITINPUT                    95
#define LDU_DESKRITINPUT                    96

#define LD_DEREF_FN_2CREATEDESKTOP          97

#define LDL_DESK_DESKNEXT2                  98

#define LDL_DESKSHOULDBEFOREGROUND1         99
#define LDL_DESKSHOULDBEFOREGROUND2         100
#define LDL_DESKSHOULDBEFOREGROUND3         101

#define LDL_HOOK_DESK                       102
#define LDU_HOOK_DESK                       103

#define LDU_DESKSHOULDBEFOREGROUND          105

#define LDU_MOTHERDESK_DESK                 106

void LogDesktop(PDESKTOP pdesk, DWORD tag, BOOL bLock, ULONG_PTR extra);

#else
    #define LogDesktop(pdesk, tag, bLock, extra)
#endif // LOGDESKTOPLOCKS

/*
 * Routines for referencing and assigning kernel objects.
 */
#ifdef LOGDESKTOPLOCKS
    VOID LockObjectAssignment(PVOID*, PVOID, DWORD, ULONG_PTR);
    VOID UnlockObjectAssignment(PVOID*, DWORD, ULONG_PTR);
#else
    VOID LockObjectAssignment(PVOID*, PVOID);
    VOID UnlockObjectAssignment(PVOID*);
#endif

VOID UserDereferenceObject(PVOID pobj);

#define ThreadLockObject(pobj, ptl)                                                 \
{                                                                                   \
    UserAssert(!(PpiCurrent()->W32PF_Flags & W32PF_TERMINATED));                    \
    UserAssert(pobj == NULL || OBJECT_TO_OBJECT_HEADER(pobj)->PointerCount != 0);   \
    PushW32ThreadLock(pobj, ptl, UserDereferenceObject);                            \
    if (pobj != NULL) {                                                             \
        ObReferenceObject(pobj);                                                    \
    }                                                                               \
}

#define ThreadLockExchangeObject(pobj, ptl)                                         \
{                                                                                   \
    UserAssert(!(PpiCurrent()->W32PF_Flags & W32PF_TERMINATED));                    \
    UserAssert(pobj == NULL || OBJECT_TO_OBJECT_HEADER(pobj)->PointerCount != 0);   \
    if (pobj != NULL) {                                                             \
        ObReferenceObject(pobj);                                                    \
    }                                                                               \
    ExchangeW32ThreadLock(pobj, ptl);                                               \
}

#define ThreadUnlockObject(ptl)                                                     \
{                                                                                   \
    PopAndFreeW32ThreadLock(ptl);                                                   \
}                                                                                   \

#ifdef LOGDESKTOPLOCKS

    #define UnlockWinSta(ppwinsta) \
            UnlockObjectAssignment(ppwinsta, 0, 0)

    #define LockWinSta(ppwinsta, pwinsta) \
    {                                                                                           \
        if (pwinsta != NULL)                                                                    \
        {                                                                                       \
            UserAssert(OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *ExWindowStationObjectType);   \
        }                                                                                       \
        LockObjectAssignment(ppwinsta, pwinsta, 0, 0);                                                \
    }

    #define LockDesktop(ppdesk, pdesk, tag, extra) \
    {                                                                                           \
        if (pdesk != NULL)                                                                      \
        {                                                                                       \
            UserAssert(OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);           \
        }                                                                                       \
        LockObjectAssignment(ppdesk, pdesk, tag, extra);                                        \
    }

    #define UnlockDesktop(ppdesk, tag, extra) \
            UnlockObjectAssignment(ppdesk, tag, extra)

    #define ThreadLockDesktop(pti, pdesk, ptl, tag) \
    {                                                                                           \
        UserAssert(pdesk == NULL || OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);\
        ThreadLockObject(pdesk, ptl);                                                           \
        LogDesktop(pdesk, tag, TRUE, (ULONG_PTR)PtiCurrent());                                      \
    }

    #define ThreadLockExchangeDesktop(pti, pdesk, ptl, tag) \
    {                                                                                           \
        UserAssert(pdesk == NULL || OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);\
        ThreadLockExchangeObject(pdesk, ptl);                                                   \
        LogDesktop(pdesk, tag, TRUE, (ULONG_PTR)PtiCurrent());                                  \
    }

    #define ThreadUnlockDesktop(pti, ptl, tag)                                                  \
    {                                                                                           \
        LogDesktop((PDESKTOP)(((PTL)ptl)->pobj), tag, FALSE, (ULONG_PTR)PtiCurrent());                \
        ThreadUnlockObject(ptl);                                                                \
    }

#else

    #define UnlockWinSta(ppwinsta) \
            UnlockObjectAssignment(ppwinsta)

    #define LockWinSta(ppwinsta, pwinsta) \
    {                                                                                           \
        if (pwinsta != NULL)                                                                    \
        {                                                                                       \
            UserAssert(OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *ExWindowStationObjectType);   \
        }                                                                                       \
        LockObjectAssignment(ppwinsta, pwinsta);                                                \
    }

    #define LockDesktop(ppdesk, pdesk, tag, extra) \
    {                                                                                           \
        if (pdesk != NULL)                                                                      \
        {                                                                                       \
            UserAssert(OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);           \
        }                                                                                       \
        LockObjectAssignment(ppdesk, pdesk);                                                    \
    }

    #define UnlockDesktop(ppdesk, tag, extra) \
            UnlockObjectAssignment(ppdesk)

    #define ThreadLockDesktop(pti, pdesk, ptl, tag) \
    {                                                                                           \
        UserAssert(pdesk == NULL || OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);\
        ThreadLockObject(pdesk, ptl);                                                           \
    }

    #define ThreadLockExchangeDesktop(pti, pdesk, ptl, tag) \
    {                                                                                           \
        UserAssert(pdesk == NULL || OBJECT_TO_OBJECT_HEADER(pdesk)->Type == *ExDesktopObjectType);\
        ThreadLockExchangeObject(pdesk, ptl);                                                   \
    }

    #define ThreadUnlockDesktop(pti, ptl, tag) ThreadUnlockObject(ptl)

#endif // LOGDESKTOPLOCKS

#define ThreadLockWinSta(pti, pwinsta, ptl) \
{                                                                                           \
    UserAssert(pwinsta == NULL || OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *ExWindowStationObjectType);\
    ThreadLockObject(pwinsta, ptl);                                                         \
}

#define ThreadLockExchangeWinSta(pti, pwinsta, ptl) \
{                                                                                           \
    UserAssert(pwinsta == NULL || OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *ExWindowStationObjectType);\
    ThreadLockExchangeObject(pwinsta, ptl);                                                 \
}

#define _ThreadLockPti(pti, pobj, ptl) LockW32Thread((PW32THREAD)pobj, ptl)
#if DBG
#define ThreadLockPti(pti, pobj, ptl) \
{ \
    if ((pobj != NULL) \
            && (pobj->TIF_flags & TIF_INCLEANUP) \
            && (pobj != PtiCurrent())) { \
        RIPMSG1(RIP_ERROR, "ThreadLockPti: dead thread %#p", pobj); \
    } \
    _ThreadLockPti(pti, pobj, ptl); \
}
#else
#define ThreadLockPti(pti, pobj, ptl) \
{ \
    _ThreadLockPti(pti, pobj, ptl); \
}
#endif

#define ThreadLockExchangePti(pobj, ptl) LockExchangeW32Thread((PW32THREAD)pobj, ptl)

#define ThreadUnlockWinSta(pti, ptl) ThreadUnlockObject(ptl)
#define ThreadUnlockPti(pti, ptl) UnlockW32Thread(ptl)

/*
 * Macros for locking pool allocations
 */
#define ThreadLockPool(_pti_, _ppool_, _ptl_)  \
        PushW32ThreadLock(_ppool_, _ptl_, UserFreePool)

#define ThreadUnlockPool(_pti_, _ptl_)  \
        PopW32ThreadLock(_ptl_)

#define ThreadUnlockAndFreePool(_pti_, _ptl_)  \
        PopAndFreeAlwaysW32ThreadLock(_ptl_)

#define ThreadLockPoolCleanup(_pti_, _ppool_, _ptl_, _pfn_)  \
        PushW32ThreadLock(_ppool_, _ptl_, _pfn_)

#define ThreadUnlockPoolCleanup(_pti_, _ptl_)  \
        PopW32ThreadLock(_ptl_)

#define ThreadUnlockAndCleanupPool(_pti_, _ptl_)  \
        PopAndFreeAlwaysW32ThreadLock(_ptl_)

#define ThreadLockDesktopHandle(_pti, _ptl_, _hdesk_)   \
        PushW32ThreadLock(_hdesk_, _ptl_, CloseProtectedHandle)

#define ThreadUnlockDesktopHandle(_ptl_)   \
        PopAndFreeAlwaysW32ThreadLock(_ptl_)

void CleanupDecSFWLockCount(PVOID pIgnore);
#define ThreadLockSFWLockCount(_ptl_) \
        { \
            IncSFWLockCount(); \
            /* Pass a fake pObj or the cleanup function won't be called */ \
            PushW32ThreadLock(&guSFWLockCount, _ptl_, CleanupDecSFWLockCount); \
        }

#define ThreadUnlockSFWLockCount(_ptl_) \
    { \
        DecSFWLockCount(); \
        PopW32ThreadLock(_ptl_); \
    }

/*
 * special handle that signifies we have a rle bitmap for the wallpaper
 */
#define HBITMAP_RLE ((HBITMAP)0xffffffff)

typedef struct tagWPINFO {
    int xsize, ysize;
    PBITMAPINFO pbmi;
    PBYTE pdata;
    PBYTE pbmfh;
} WPINFO;

/*
 * Defines used by GetMouseMovePointsEx API
 */

#define MAX_MOUSEPOINTS 64

#define PREVPOINT(i)    \
    ((i == 0) ? (MAX_MOUSEPOINTS - 1) : ((i - 1) % MAX_MOUSEPOINTS))

#define NEXTPOINT(i)    \
    ((i + 1) % MAX_MOUSEPOINTS)

#define NEXTPOINTCOUNT(c)           \
    {                               \
        if (c < MAX_MOUSEPOINTS)    \
            c++;                    \
    }

#define SAVEPOINT(xc, yc, _resX, _resY, t, e)                            \
{                                                                        \
    /*                                                                   \
     * (xc, yc) is the point and (resX, resY) is the resolution          \
     */                                                                  \
    gaptMouse[gptInd].x           = MAKELONG(LOWORD(xc), LOWORD(_resX)); \
    gaptMouse[gptInd].y           = MAKELONG(LOWORD(yc), LOWORD(_resY)); \
    gaptMouse[gptInd].time        = t;                                   \
    gaptMouse[gptInd].dwExtraInfo = e;                                   \
                                                                         \
    gptInd = NEXTPOINT(gptInd);                                          \
}


/*
 * Structure used for getting the stack traces for user critical section
 */

#define MAX_STACK_CALLS 8

typedef struct tagCRITSTACK {
struct tagCRITSTACK* pNext;
    PETHREAD         thread;
    int              nFrames;
    PVOID            trace[MAX_STACK_CALLS];
} CRITSTACK, *PCRITSTACK;


/*
 * Macros for User Server and Raw Input Thread critical sections.
 */
#if DBG
    #define KeUserModeCallback(api, pIn, cb, pOut, pcb)    _KeUserModeCallback(api, pIn, cb, pOut, pcb);
    #define CheckCritIn()                _AssertCritIn()
    #define CheckDeviceInfoListCritIn()  _AssertDeviceInfoListCritIn()
    #define CheckCritInShared()          _AssertCritInShared()
    #define CheckCritOut()               _AssertCritOut()
    #define CheckDeviceInfoListCritOut() _AssertDeviceInfoListCritOut()

    void    BeginAtomicCheck();
    void    BeginAtomicDeviceInfoListCheck();
    void    EndAtomicCheck();
    void    EndAtomicDeviceInfoListCheck();
    #define BEGINATOMICCHECK()     BeginAtomicCheck();                              \
                                    { DWORD dwCritSecUseSave = gdwCritSecUseCount;

    #define ENDATOMICCHECK()        UserAssert(dwCritSecUseSave == gdwCritSecUseCount);  \
                                    } EndAtomicCheck();
    #define BEGINATOMICDEVICEINFOLISTCHECK() \
            BeginAtomicDeviceInfoListCheck(); \
            { DWORD dwDeviceInfoListCritSecUseSave = gdwDeviceInfoListCritSecUseCount;

    #define ENDATOMICDEVICEINFOLISTCHECK() \
            UserAssert(dwDeviceInfoListCritSecUseSave == gdwDeviceInfoListCritSecUseCount);  \
            } EndAtomicDeviceInfoListCheck();

    // Use this to jump/return out of scope of dwCritSecUseSave (eg: error handling)
    #define EXITATOMICCHECK()       UserAssert(dwCritSecUseSave == gdwCritSecUseCount);  \
                                    EndAtomicCheck();
    #define ISATOMICCHECK()         (gdwInAtomicOperation != 0)
    #define ISATOMICDEVICEINFOLISTCHECK() (gdwInAtomicDeviceInfoListOperation != 0)

#else // DBG
    #define CheckCritIn()
    #define CheckDeviceInfoListCritIn()
    #define CheckCritInShared()
    #define CheckCritOut()
    #define CheckDeviceInfoListCritOut()
    #define BEGINATOMICCHECK()
    #define BEGINATOMICDEVICEINFOLISTCHECK()
    #define BeginAtomicCheck()
    #define BeginAtomicDeviceInfoListCheck()
    #define ENDATOMICCHECK()
    #define ENDATOMICDEVICEINFOLISTCHECK()
    #define EndAtomicCheck()
    #define EndAtomicDeviceInfoListCheck()
    #define EXITATOMICCHECK()
    #define ISATOMICCHECK()
    #define ISATOMICDEVICEINFOLISTCHECK()
#endif // DBG


#define DIAGNOSE_IO 1
#ifdef DIAGNOSE_IO
ULONG MonotonicTick();
#define LOGTIME(gt) gt = MonotonicTick();
#else
#define LOGTIME(gt)
#endif

/*
 * #defines used for mouse/keyboard read buffer
 */
#define MAXIMUM_ITEMS_READ      10
#define NELEM_BUTTONQUEUE       16

/*
 * Number of times to retry reading a device after a read attempt fails
 */
#define MAXIMUM_READ_RETRIES 5

typedef struct tagGENERIC_DEVICE_INFO {
#ifdef GENERIC_INPUT
    HEAD                 head;
#endif
    struct tagDEVICEINFO *pNext;
    BYTE                 type;
    BYTE                 bFlags;
    USHORT               usActions;
    BYTE                 nRetryRead;
    UNICODE_STRING       ustrName;
    HANDLE               handle;
    PVOID                NotificationEntry;
    PKEVENT              pkeHidChangeCompleted; // wake RequestDeviceChange()
    IO_STATUS_BLOCK      iosb;
    NTSTATUS             ReadStatus;

#ifdef DIAGNOSE_IO
    HANDLE               OpenerProcess;
    NTSTATUS             OpenStatus;
    NTSTATUS             AttrStatus;
    ULONG                timeStartRead;     // tick before ZwReadFile
    ULONG                timeEndRead;       // tick after ZwReadFile
    int                  nReadsOutstanding; // ZwReadFile ++, consume data --
#endif
} GENERIC_DEVICE_INFO, *PGENERIC_DEVICE_INFO;

// valuse for GENERIC_DEVICE_INFO.type
#define DEVICE_TYPE_MOUSE    0
#define DEVICE_TYPE_KEYBOARD 1
#ifdef GENERIC_INPUT
#define DEVICE_TYPE_HID      2
#define DEVICE_TYPE_MAX      2
#else
#define DEVICE_TYPE_MAX      1
#endif

// values for GENERIC_DEVICE_INFO.usActions and SignalDeviceChange()
#define GDIAF_ARRIVED         (USHORT)0x0001 // open & start reading
#define GDIAF_QUERYREMOVE     (USHORT)0x0002 // close the device
#define GDIAF_REMOVECANCELLED (USHORT)0x0004 // reopen the device
#define GDIAF_DEPARTED        (USHORT)0x0008 // close and free the device
#define GDIAF_IME_STATUS      (USHORT)0x0010 // ???
#define GDIAF_REFRESH_MOUSE   (USHORT)0x0020 // ???
#define GDIAF_FREEME          (USHORT)0x0080 // Request to Free the DeviceInfo
#define GDIAF_PNPWAITING      (USHORT)0x0100 // a PnP thread is waiting
#define GDIAF_RETRYREAD       (USHORT)0x0200 // Retry the read
#define GDIAF_RECONNECT       (USHORT)0x0400 // The session reconnected
#ifdef GENERIC_INPUT
#define GDIAF_STARTREAD       (USHORT)0x0800 // The device needs to be started
#define GDIAF_STOPREAD        (USHORT)0x1000 // The device needs to be stopped
#endif

// values for GENERIC_DEVICE_INFO.bFlags;
#define GDIF_NOTPNP         0x01 // Not a PnP device (eg: PS/2)
#define GDIF_READING        0x02 // Read may be pending (don't free DeviceInfo).
#if DIAGNOSE_IO
#define GDIF_READERMUSTFREE 0x04 // "Free Device" while read pending
#define GDIF_PNPMUSTFREE    0x08 // "Free Device" while PnP notification pending
#endif
#define GDIF_DBGREAD        0x10 // Verbose dbg output about this device

typedef struct tagMOUSE_DEVICE_INFO {    // DEVICE_TYPE_MOUSE
    MOUSE_ATTRIBUTES     Attr;
    MOUSE_INPUT_DATA     Data[MAXIMUM_ITEMS_READ];
} MOUSE_DEVICE_INFO, *PMOUSE_DEVICE_INFO;

#ifdef GENERIC_INPUT
#define INVALID_UNIT_ID     ((USHORT)0xffff)
#define INJECTED_UNIT_ID    ((USHORT)0xfffe)
#endif


typedef struct tagKEYBOARD_DEVICE_INFO { // DEVICE_TYPE_KEYBOARD
    KEYBOARD_ATTRIBUTES  Attr;
    KEYBOARD_ID_EX IdEx;
    KEYBOARD_INPUT_DATA  Data[MAXIMUM_ITEMS_READ];
} KEYBOARD_DEVICE_INFO, *PKEYBOARD_DEVICE_INFO;

#define GET_KEYBOARD_DEVINFO_ID(pDeviceInfo)        ((pDeviceInfo)->keyboard.IdEx)
#define GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo)      ((pDeviceInfo)->keyboard.IdEx.Type)
#define GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo)   ((pDeviceInfo)->keyboard.IdEx.Subtype)


#ifdef GENERIC_INPUT
/*
 * HID Descriptor
 * allocated as a handle, type == TAG_HIDDESC
 */
typedef struct tagHIDDESC {
    IO_STATUS_BLOCK iob;

    PVOID pPreparsedData;   // the size is in hidCollectionInfo.DescriptorSize
    PVOID pInputBuffer;     // the size is in hidpCaps.

    HIDP_CAPS hidpCaps;
    HID_COLLECTION_INFORMATION hidCollectionInfo;
} HIDDESC, *PHIDDESC;

/*
 * HID Top Level Collection Information
 */
typedef struct tagHID_TLC_INFO {
    LIST_ENTRY link;
    // Toplevel collection
    USHORT usUsagePage;
    USHORT usUsage;
    /*
     * Reference counters
     */
    UINT cDevices;              // # of devices currently attached
    UINT cDirectRequest;        // Reference count of direct request to this device type (# of processes)
    UINT cUsagePageRequest;     // Reference count of UsagePage only request
    UINT cExcludeRequest;       // Reference count of Exclude request
    UINT cExcludeOrphaned;      // Orphaned count of Exclude request
#if defined(GI_SINK) && defined(LATER)
    UINT cSinkable;             // LATER...
#endif
} HID_TLC_INFO, *PHID_TLC_INFO;

/*
 * HID global PageOnly request
 */
typedef struct tagHID_PAGEONLY_REQUEST {
    LIST_ENTRY link;
    USHORT usUsagePage;
    UINT cRefCount;
#if defined(GI_SINK) && defined(LATER)
    UINT cSinkable;
#endif
} HID_PAGEONLY_REQUEST, *PHID_PAGEONLY_REQUEST;

/*
 * Global HID Request
 */
typedef struct tagHID_REQUEST_TABLE {
    /*
     * HID_TLC_INFO
     */
    LIST_ENTRY TLCInfoList;
    /*
     * HID_PAGEONLY_REQUEST
     */
    LIST_ENTRY UsagePageList;

#ifdef GI_SINK
    /*
     * PROCESS_HID_TABLE
     */
    LIST_ENTRY ProcessRequestList;
#endif
} HID_REQUEST_TABLE, *PHID_REQUEST_TABLE;

extern HID_REQUEST_TABLE gHidRequestTable;
extern int gnHidProcess;

/*
 * Per process hid device request list
 */
typedef struct tagPROCESS_HID_REQUEST {
    LIST_ENTRY link;
    // Toplevel collection
    USHORT usUsagePage;
    USHORT usUsage;
#ifdef GI_SINK
    BOOL fSinkable : 1;
#endif
    BOOL fExclusiveOrphaned : 1;
    union {
        PHID_TLC_INFO    pTLCInfo;
        PHID_PAGEONLY_REQUEST   pPORequest;
        LPVOID                  ptr;
    };
    PWND spwndTarget;
} PROCESS_HID_REQUEST, *PPROCESS_HID_REQUEST;

/*
 * Per-process HID request table
 */
typedef struct tagPROCESS_HID_TABLE {
    /*
     * Link to the next process HID table.
     */
    LIST_ENTRY link;

    /*
     * Those LIST_ENTRYs point PROCESS_HID_REQUEST
     */
    LIST_ENTRY InclusionList;
    LIST_ENTRY UsagePageList;
    LIST_ENTRY ExclusionList;

    /*
     * Target windows for the legacy devices
     */
    PWND spwndTargetMouse;
    PWND spwndTargetKbd;

#ifdef GI_SINK
    /*
     * Number of Sinks in this process.
     * N.b. this does not include the legacy device sinks to
     * save clocks walking through the list, if sink requests
     * are only for the legacy devices.
     */
    int nSinks;
#endif

    /*
     * Cache of the last matching request.
     */
    PPROCESS_HID_REQUEST pLastRequest;
    USAGE UsagePageLast;
    USAGE UsageLast;

    /*
     *  Legacy Mode flags
     */
    BOOL fRawMouse : 1;
    BOOL fNoLegacyMouse : 1;
#ifdef GI_SINK
    BOOL fRawMouseSink : 1;
#endif
    BOOL fRawKeyboard : 1;
    BOOL fNoLegacyKeyboard : 1;
#ifdef GI_SINK
    BOOL fRawKeyboardSink : 1;
#endif
    BOOL fCaptureMouse : 1;     // "Own" a mouse...
    BOOL fNoHotKeys : 1;
    BOOL fAppKeys: 1;
} PROCESS_HID_TABLE, *PPROCESS_HID_TABLE;

#define TestRawInputMode(pti, mode) \
    ((pti) && (pti)->ppi && (pti)->ppi->pHidTable && (pti)->ppi->pHidTable->f##mode)

#define TestRawInputModeNoCheck(pti, mode) \
    ((pti)->ppi->pHidTable->f##mode)

#ifdef GI_SINK
typedef struct tagHID_COUNTERS {
    DWORD cKbdSinks;
    DWORD cMouseSinks;
    DWORD cHidSinks;
} HID_COUNTERS;

extern HID_COUNTERS gHidCounters;

#define IsKeyboardSinkPresent() (gHidCounters.cKbdSinks > 0)
#define IsMouseSinkPresent()    (gHidCounters.cMouseSinks > 0)
#endif


#define HID_INCLUDE     0x01
#define HID_PAGEONLY    0x02
#define HID_EXCLUDE     0x03

/*
 * HID Device info
 */
typedef struct tagHID_DEVICE_INFO {
    PHIDDESC pHidDesc;
    PHID_TLC_INFO pTLCInfo;
} HID_DEVICE_INFO, *PHID_DEVICE_INFO;

#endif  // GENERIC_INPUT

typedef struct tagDEVICEINFO {
    GENERIC_DEVICE_INFO;
    union {
        MOUSE_DEVICE_INFO    mouse;
        KEYBOARD_DEVICE_INFO keyboard;
#ifdef GENERIC_INPUT
        HID_DEVICE_INFO hid;
#endif
    };
} DEVICEINFO, *PDEVICEINFO;

typedef struct tagDEVICE_TEMPLATE {
    SIZE_T cbDeviceInfo;        // bytes to allocate for DEVICEINFO
    const GUID *pClassGUID;     // GUID of the class
    UINT   uiRegistrySection;   // Parameters for class (HKLM\SYSTEM\CurrentControlSet\Services\*\Parameters)
    LPWSTR pwszClassName;       // Class name (eg: L"mouclass")
    LPWSTR pwszDefDevName;      // Default Device Name
    LPWSTR pwszLegacyDevName;   // Legacy Device Name (eg: "PointerClassLegacy0")
    ULONG  IOCTL_Attr;          // IOCTL_*_QUERY_ATTRIBUTES
    UINT   offAttr;             // offset of *_ATTRIBUTES struct within DEVICEINFO
    ULONG  cbAttr;              // sizeof *_ATTRIBUTES struct
    UINT   offData;             // offset of *_INPUT_DATA buffer within DEVICEINFO
    ULONG  cbData;              // sizeof *_INPUT_DATA buffer
    VOID   (*DeviceRead)(PDEVICEINFO); // routine to read the device
    PKEVENT pkeHidChange;       // event to signal changes to this sort of device

#ifdef GENERIC_INPUT
    DWORD dwFlags;              // Flags...
#endif
} DEVICE_TEMPLATE, *PDEVICE_TEMPLATE;


#ifdef GENERIC_INPUT
#define DT_HID          0x00000001
#endif

extern DEVICE_TEMPLATE aDeviceTemplate[]; // in pnp.c

typedef struct tagMOUSEEVENT {
    USHORT  ButtonFlags;
    USHORT  ButtonData;
    ULONG_PTR ExtraInfo;
    POINT   ptPointer;
    LONG    time;
    BOOL    bInjected;
#ifdef GENERIC_INPUT
    HANDLE  hDevice;

    /*
     * The raw mouse information comes here.
     */
    MOUSE_INPUT_DATA rawData;
#endif
} MOUSEEVENT, *PMOUSEEVENT;


#ifdef GENERIC_INPUT
/*
 * RawInput
 */
typedef struct tagHIDDATA {
    THROBJHEAD head;
    PWND spwndTarget;
    RAWINPUT rid;   // raw input data, variable length
                    // rid needs to be the last member in HIDDATA
} HIDDATA, *PHIDDATA;

/*
 * Global request list manipulation.
 */
void InitializeHidRequestList();
void CleanupHidRequestList();

/*
 * DeviceType request
 */
VOID FreeHidTLCInfo(
    PHID_TLC_INFO pHidRequest);

/*
 * HID specific device info
 */
PHIDDESC xxxHidCreateDeviceInfo(PDEVICEINFO pDeviceInfo);

/*
 * HID specific information (managed by HM),
 * linked from DEVICEINFO
 */
/* N.b. AllocateHidDesc is only called within hidevice.c */
void FreeHidDesc(PHIDDESC);

/*
 * The handle in WM_INPUT
 */
PHIDDATA AllocateHidData(HANDLE hDevice, DWORD dwType, DWORD dwSize, WPARAM wParam, PWND pwnd);
void FreeHidData(PHIDDATA pData);

#ifdef GI_SINK
#define GI_SINK_PARAM(x)    ,x
#else
#define GI_SINK_PARAM(x)
#endif

void FreeHidProcessRequest(
    PPROCESS_HID_REQUEST pHid,
    DWORD dwFlags,
    PPROCESS_HID_TABLE pHidTable);


/*
 * HID specific read call back (called from InputApc)
 */
VOID ProcessHidInput(PDEVICEINFO pDeviceInfo);

/*
 * API helper
 */
BOOL _RegisterRawInputDevices(PCRAWINPUTDEVICE, UINT uiNumDevices);
UINT _GetRegisteredRawInputDevices(PRAWINPUTDEVICE, PUINT puiNumDevices);

/*
 * UserCriticalSection...
 */
#define BESURE_IN_USERCRIT(cond) \
    { \
        BOOLEAN fHasToLeaveUserCrit = FALSE; \
        if ((cond) && !ExIsResourceAcquiredExclusiveLite(gpresUser)) { \
            CheckDeviceInfoListCritOut(); \
            fHasToLeaveUserCrit = TRUE; \
            EnterCrit(); \
            TAGMSG0(DBGTAG_PNP, "BESURE_IN_USERCRIT: entering the user crit"); \
        }

#define END_IN_USERCRIT() \
        if (fHasToLeaveUserCrit) { \
            CheckDeviceInfoListCritOut(); \
            TAGMSG0(DBGTAG_PNP, "END_IN_USERCRIT: leaving the user crit"); \
            LeaveCrit(); \
        }\
    }

/*
 * Acquire input device lock while making sure there is no pending PnP callout
 * rewuesting to process a device change.
 */
#define PNP_SAFE_DEVICECRIT_IN() \
{\
    CheckCritIn();\
    CheckDeviceInfoListCritIn();\
    while (TRUE) {\
        if (gbPnPWaiting) {\
            LeaveDeviceInfoListCrit();\
            LeaveCrit(); \
            Status = KeWaitForSingleObject(gpEventPnPWainting, Executive, KernelMode, FALSE, NULL); \
            EnterCrit();\
            EnterDeviceInfoListCrit();\
            UserAssert(Status == STATUS_SUCCESS);\
            continue;\
        }else {  \
            break; \
        } \
    }  \
}


/*
 * Check if this device type is active to read
 */
__inline DWORD HidValidExclusive(PHID_TLC_INFO pTLCInfo)
{
    UserAssert(pTLCInfo);
    UserAssert(pTLCInfo->cExcludeRequest >= pTLCInfo->cExcludeOrphaned);
    return pTLCInfo->cExcludeRequest - pTLCInfo->cExcludeOrphaned;
}

__inline BOOL HidTLCActive(PHID_TLC_INFO pTLCInfo)
{
    UserAssert(pTLCInfo);
    return pTLCInfo->cDirectRequest > 0 || pTLCInfo->cUsagePageRequest > HidValidExclusive(pTLCInfo);
}

/*
 * Allocate and free process device type request table.
 */
PPROCESS_HID_TABLE AllocateProcessHidTable(void);
void FreeProcessHidTable(PPROCESS_HID_TABLE pHidTable);

void DestroyProcessHidRequests(PPROCESSINFO ppi);
void DestroyThreadHidObjects(PTHREADINFO pti);

#if DBG
void CheckupHidLeak(void);
#endif

#endif  // GENERIC_INPUT


VOID ProcessKeyboardInput(PDEVICEINFO pDeviceInfo);
VOID ProcessMouseInput(PDEVICEINFO pDeviceInfo);
VOID RequestDeviceChange(
    PDEVICEINFO pDeviceInfo,
    USHORT usAction,
    BOOL fInDeviceInfoListCrit);

VOID RetryReadInput();

VOID NTAPI InputApc(
    IN PVOID ApcContext,
    IN PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG Reserved);

ULONG GetDeviceChangeInfo(VOID);
VOID InitializeMediaChange(HANDLE);
VOID CleanupMediaChange(VOID);

/*
 * Hard error information
 */
typedef struct tagHARDERRORHANDLER {
    PTHREADINFO pti;
    PQ pqAttach;
} HARDERRORHANDLER, *PHARDERRORHANDLER;

/*
 * Terminal Structure.
 *
 *   This structure is only viewable from the kernel.
 */

#define TEST_GTERMF(f)               TEST_FLAG(gdwGTERMFlags, f)
#define TEST_BOOL_GTERMF(f)          TEST_BOOL_FLAG(gdwGTERMFlags, f)
#define SET_GTERMF(f)                SET_FLAG(gdwGTERMFlags, f)
#define CLEAR_GTERMF(f)              CLEAR_FLAG(gdwGTERMFlags, f)
#define SET_OR_CLEAR_GTERMF(f, fSet) SET_OR_CLEAR_FLAG(gdwGTERMFlags, f, fSet)
#define TOGGLE_GTERMF(f)             TOGGLE_FLAG(gdwGTERMFlags, f)

#define GTERMF_MOUSE        0x00000001


#define TERMF_INITIALIZED       0x00000001
#define TERMF_NOIO              0x00000002
#define TERMF_STOPINPUT         0x00000004
#define TERMF_DTINITSUCCESS     0x00000008
#define TERMF_DTINITFAILED      0x00000010
#define TERMF_DTDESTROYED       0x00000020

typedef struct tagTERMINAL {

    DWORD               dwTERMF_Flags;      // terminal flags

    /*
     * System Information
     */
    PWND                spwndDesktopOwner;  // mother desktop


    PTHREADINFO         ptiDesktop;
#ifdef BUG365290
    PTHREADINFO         ptiDesktopTemp;
#endif //BUG365290
    PQ                  pqDesktop;

    PKEVENT             pEventTermInit;
    PKEVENT             pEventDestroyDesktop;   // Used for destroying desktops

    PDESKTOP            rpdeskDestroy;          // Desktop destroy list.

    PKEVENT             pEventInputReady;   // input ready event. This is created in
                                            // CreateTerminal. RIT and the desktop thread
                                            // will wait for it. It will be set when the
                                            // first desktop in that terminal will be created.
    PKEVENT             pEventDTExit;

} TERMINAL, *PTERMINAL;

/*
 * Pool allocation tags and macros
 */

/*
 * Define tags. To add tags, add them to ntuser\kernel\ptag.lst
 */
#define DEFINE_POOLTAG(value, index) value

#define DECLARE_POOLTAG(name, value, index)

#include "ptag.h"

NTSTATUS UserCommitDesktopMemory(
    PVOID  pBase,
    PVOID *ppCommit,
    PSIZE_T pCommitSize);

NTSTATUS UserCommitSharedMemory(
    PVOID  pBase,
    PVOID *ppCommit,
    PSIZE_T pCommitSize);

PWIN32HEAP UserCreateHeap(
    HANDLE                   hSection,
    ULONG                    ulViewOffset,
    PVOID                    pvBaseAddress,
    DWORD                    dwSize,
    PRTL_HEAP_COMMIT_ROUTINE pfnCommit);

#define IsValidTag(p, tag)      TRUE

#define RECORD_STACK_TRACE_SIZE 6

/*
 * Pool allocation flags
 */

#define POOL_HEAVY_ALLOCS       0x00000001  // use HeavyAllocPool
#define POOL_CAPTURE_STACK      0x00000002  // stack traces are captured
#define POOL_FAIL_ALLOCS        0x00000004  // fail pool allocations
#define POOL_FAIL_BY_INDEX      0x00000008  // fail allocations by index
#define POOL_TAIL_CHECK         0x00000010  // append tail string
#define POOL_KEEP_FREE_RECORD   0x00000020  // keep a list with last x frees
#define POOL_KEEP_FAIL_RECORD   0x00000040  // keep a list with last x failed allocations
#define POOL_BREAK_FOR_LEAKS    0x00000080  // break on pool leaks (remote sessions)

typedef struct tagWin32AllocStats {
    SIZE_T dwMaxMem;             // max pool memory allocated
    SIZE_T dwCrtMem;             // current pool memory used
    DWORD  dwMaxAlloc;           // max number of pool allocations made
    DWORD  dwCrtAlloc;           // current pool allocations

    PWin32PoolHead pHead;        // pointer to the link list with the allocations

} Win32AllocStats, *PWin32AllocStats;

typedef struct tagPOOLRECORD {
    PVOID   ExtraData;           // the tag
    SIZE_T  size;
    PVOID   trace[RECORD_STACK_TRACE_SIZE];
} POOLRECORD, *PPOOLRECORD;

#ifdef POOL_INSTR_API

    BOOL _Win32PoolAllocationStats(
        LPDWORD  parrTags,
        SIZE_T   tagsCount,
        SIZE_T*  lpdwMaxMem,
        SIZE_T*  lpdwCrtMem,
        LPDWORD  lpdwMaxAlloc,
        LPDWORD  lpdwCrtAlloc);

#endif // POOL_INSTR_API

#ifdef POOL_INSTR

    void CleanupPoolAllocations(void);
    NTSTATUS InitPoolLimitations();
    void CleanUpPoolLimitations();
#else
    #define CleanupPoolAllocations()
    #define InitPoolLimitations()   STATUS_SUCCESS
    #define CleanUpPoolLimitations()

#endif // POOL_INSTR

#ifndef TRACE_MAP_VIEWS
    #define InitSectionTrace()      STATUS_SUCCESS
    #define CleanUpSections()
#else
    NTSTATUS InitSectionTrace(VOID);
    void CleanUpSections(void);
#endif // TRACE_MAP_VIEWS

extern PWIN32HEAP gpvSharedAlloc;

__inline PVOID
SharedAlloc(ULONG cb)
{
    return Win32HeapAlloc(gpvSharedAlloc, cb, 0, 0);
}

__inline BOOL
SharedFree(PVOID pv)
{
    return Win32HeapFree(gpvSharedAlloc, pv);
}

NTSTATUS CommitReadOnlyMemory(HANDLE hSection, PSIZE_T pulCommit,
                              DWORD dwCommitOffset, int* pdCommit);

/*
 * Height and Width of the desktop pattern bitmap.
 */
#define CXYDESKPATTERN      8

/*
 * LATER: these things are not defined yet
 */
#define CheckHwnd(x)        TRUE
#define CheckHwndNull(x)    TRUE

/***************************************************************************\
* Typedefs and Macros
*
* Here are defined all types and macros that are shared across the User's
* server-side code modules. Types and macros that are unique to a single
* module should be defined at the head of that module, not in this file.
*
\***************************************************************************/


// Window Proc Window Validation macro

#define VALIDATECLASSANDSIZE(pwnd, message, wParam, lParam, inFNID, initmessage)          \
    if ((pwnd)->fnid != (inFNID)) {                                                       \
        switch ((pwnd)->fnid) {                                                           \
        DWORD cb;                                                                         \
        case 0:                                                                           \
                                                                                          \
            if ((cb = pwnd->cbwndExtra + sizeof(WND)) < (DWORD)(CBFNID(inFNID))) {        \
                RIPMSG3(RIP_WARNING,                                                      \
                       "(%#p %lX) needs at least (%ld) window words for this proc",       \
                        pwnd, cb - sizeof(WND),                                           \
                        (DWORD)(CBFNID(inFNID)) - sizeof(WND));                           \
                return 0;                                                                 \
            }                                                                             \
            /*                                                                            \
             * If this is not the initialization message, we cannot set the fnid;         \
             *  otherwise, we'll probably fault working on this pwnd's private            \
             *  uninitialized data                                                        \
             */                                                                           \
            if ((message) != (initmessage)) {                                             \
                if (((message) != WM_NCCREATE) && ((message) != WM_NCCALCSIZE)  && ((message) != WM_GETMINMAXINFO)) {         \
                    RIPMSG3(RIP_WARNING,                                                  \
                        "Default processing message %#lx for pwnd %#p. fnid %#lx not set",\
                        (message), (pwnd), (DWORD)(inFNID));                              \
                }                                                                         \
                return xxxDefWindowProc((pwnd), (message), (wParam), (lParam));           \
            }                                                                             \
                                                                                          \
            /*                                                                            \
             * Remember what window class this window belongs to. Can't use              \
             * the real class because any app can call CallWindowProc()                   \
             * directly no matter what the class is!                                      \
             */                                                                           \
            (pwnd)->fnid = (WORD)(inFNID);                                                \
            break;                                                                        \
                                                                                          \
        default:                                                                          \
            RIPMSG3(RIP_WARNING, "Window (%#p) not of correct class; fnid = %lX not %lX", \
                    (pwnd), (DWORD)((pwnd)->fnid), (DWORD)(inFNID));                      \
                                                                                          \
            /* Fall through */                                                            \
                                                                                          \
        case (inFNID | FNID_CLEANEDUP_BIT):                                               \
        case (inFNID | FNID_DELETED_BIT):                                                 \
        case (inFNID | FNID_STATUS_BITS):                                                 \
            return 0;                                                                     \
        }                                                                                 \
    }

/*
 * Handy Region helper macros
 */
#define CopyRgn(hrgnDst, hrgnSrc) \
            GreCombineRgn(hrgnDst, hrgnSrc, NULL, RGN_COPY)
#define IntersectRgn(hrgnResult, hrgnA, hrgnB) \
            GreCombineRgn(hrgnResult, hrgnA, hrgnB, RGN_AND)
#define SubtractRgn(hrgnResult, hrgnA, hrgnB) \
            GreCombineRgn(hrgnResult, hrgnA, hrgnB, RGN_DIFF)
#define UnionRgn(hrgnResult, hrgnA, hrgnB) \
            GreCombineRgn(hrgnResult, hrgnA, hrgnB, RGN_OR)
#define XorRgn(hrgnResult, hrgnA, hrgnB) \
            GreCombineRgn(hrgnResult, hrgnA, hrgnB, RGN_XOR)

void DeleteMaybeSpecialRgn(HRGN hrgn);

BOOL zzzInvalidateDCCache(PWND pwndInvalid, DWORD flags);

#define IDC_DEFAULT         0x0001
#define IDC_CHILDRENONLY    0x0002
#define IDC_CLIENTONLY      0x0004
#define IDC_MOVEBLT         0x0008
#define IDC_NOMOUSE         0x0010

/*
 * RestoreSpb return Flags
 */

#define RSPB_NO_INVALIDATE      0   // nothing invalidated by restore
#define RSPB_INVALIDATE         1   // restore invalidate some area
#define RSPB_INVALIDATE_SSB     2   // restore called SaveScreenBits which invalidated

// Calls Proc directly without doing any messages translation

#define SCMS_FLAGS_ANSI         0x0001
#define SCMS_FLAGS_INONLY       0x0002      // Message should be one way (hooks)

#define CallClientProcA(pwnd, msg, wParam, lParam, xpfn) \
            SfnDWORD(pwnd, msg, wParam, lParam, xpfn,          \
                ((PROC)(gpsi->apfnClientW.pfnDispatchMessage)), TRUE, NULL)
#define CallClientProcW(pwnd, msg, wParam, lParam, xpfn) \
            SfnDWORD(pwnd, msg, wParam, lParam, xpfn,          \
                ((PROC)(gpsi->apfnClientW.pfnDispatchMessage)), TRUE, NULL)
#define CallClientWorkerProc(pwnd, msg, wParam, lParam, xpfn) \
            SfnDWORD(pwnd, msg, wParam, lParam, 0, xpfn, TRUE, NULL)
#define ScSendMessageSMS(pwnd, msg, wParam, lParam, xParam, xpfn, dwSCMSFlags, psms) \
        (((msg) & ~MSGFLAG_MASK) >= WM_USER) ? \
        SfnDWORD(pwnd, msg, wParam, lParam, xParam, xpfn, dwSCMSFlags, psms) : \
        gapfnScSendMessage[MessageTable[msg & 0xffff].iFunction](pwnd, msg, wParam, lParam, xParam, xpfn, dwSCMSFlags, psms)
#define ScSendMessage(pwnd, msg, wParam, lParam, xParam, xpfn, dwSCMSFlags) \
        ScSendMessageSMS(pwnd, msg, wParam, lParam, xParam, xpfn, dwSCMSFlags, NULL)

/*
 * Server-side routines for loading cursors/icons/strings/menus from server.
 */
#define SERVERSTRINGMAXSIZE  40
void RtlInitUnicodeStringOrId(PUNICODE_STRING pstrName, LPWSTR lpstrName);
int RtlLoadStringOrError(UINT, LPTSTR, int, WORD);
#define ServerLoadString(hmod, id, p, cch)\
        RtlLoadStringOrError(id, p, cch, 0)
#define ServerLoadStringEx(hmod, id, p, cch, wLang)\
        RtlLoadStringOrError(id, p, cch, wLang)

/*
 * Callback routines for loading resources from client.
 */
HANDLE xxxClientLoadImage(
    PUNICODE_STRING pstrName,
    ATOM atomModName,
    WORD wImageType,
    int cxSize,
    int cySize,
    UINT LR_flags,
    BOOL fWallpaper);

HANDLE xxxClientCopyImage(
    IN HANDLE          hImage,
    IN UINT            uImageType,
    IN int             cxDesired,
    IN int             cyDesired,
    IN UINT            LR_flags);

PMENU xxxClientLoadMenu(
    HANDLE hmod,
    PUNICODE_STRING pstrName);

int xxxClientAddFontResourceW(PUNICODE_STRING, DWORD, DESIGNVECTOR*);

VOID ClientFontSweep(VOID);
VOID ClientLoadLocalT1Fonts();
VOID ClientLoadRemoteT1Fonts();

/*
 * Server-side routine for thread initialization.
 */
NTSTATUS InitializeClientPfnArrays(
    CONST PFNCLIENT *ppfnClientA,
    CONST PFNCLIENT *ppfnClientW,
    CONST PFNCLIENTWORKER *ppfnClientWorker,
    HANDLE hModUser);

//VOID _SetDebugErrorLevel(DWORD);
VOID _SetRipFlags(DWORD, DWORD);
VOID _SetDbgTag(int, DWORD);


/*
 * xxxActivateWindow() commands
 */
#define AW_USE       1
#define AW_TRY       2
#define AW_SKIP      3
#define AW_TRY2      4
#define AW_SKIP2     5      /* used internally in xxxActivateWindow() */
#define AW_USE2      6      /* nc mouse activation added by craigc */

/*
 * Structure for WM_ACTIVATEAPP EnumWindows() callback.
 */
typedef struct tagAAS {
    PTHREADINFO ptiNotify;
    DWORD tidActDeact;
    UINT fActivating  : 1;
    UINT fQueueNotify : 1;
} AAS;

/*
 * Declaration for EnumWindows() callback function.
 */
BOOL xxxActivateApp(PWND pwnd, AAS *paas);

#define GETDESKINFO(pti)  ((pti)->pDeskInfo)

#define SET_TIME_LAST_READ(pti)     ((pti)->pcti->timeLastRead = NtGetTickCount())
#define GET_TIME_LAST_READ(pti)     ((pti)->pcti->timeLastRead)


/*
 * General purpose helper macros
 */
#define abs(A)      (((A) < 0)? -(A) : (A))

#define N_ELEM(a)     (sizeof(a)/sizeof(a[0]))
#define LAST_ELEM(a)  ( (a) [ N_ELEM(a) - 1 ] )
#define PLAST_ELEM(a) (&LAST_ELEM(a))


/*
 * General purpose access check macro
 */
#define RETURN_IF_ACCESS_DENIED(amGranted, amRequested, r) \
        if (!CheckGrantedAccess((amGranted), (amRequested))) return r

/*
 * Lock record structure for tracking locks (debug only)
 */

#define LOCKRECORD_STACK    8
#define LOCKRECORD_MARKDESTROY  IntToPtr( 0xFFFFFFFF )

typedef struct _LOCKRECORD {
    PLR    plrNext;
    DWORD  cLockObj;
    PVOID  ppobj;
    PVOID  trace[LOCKRECORD_STACK];
} LOCKRECORD;

/*
 * We limit recursion until we have only this much stack left.
 * We have to leave room for kernel interupts
 */
#define KERNEL_STACK_MINIMUM_RESERVE  (4*1024)

/*
 * And this much of Back storing in IA64
 */
#if defined(_IA64_)
#define KERNEL_BSTORE_MINIMUM_RESERVE (4*1024)
#define GET_CURRENT_BSTORE() ((ULONG_PTR)PsGetCurrentThreadStackBase() + KERNEL_LARGE_BSTORE_SIZE - __getReg(CV_IA64_RsBSP))
#endif // _IA64_

#if DBG
#if defined(_IA64_)
#define GET_USED_BSTORE_SIZE()  (__getReg(CV_IA64_RsBSP) - (ULONG_PTR)PsGetCurrentThreadStackBase())
#define ASSERT_BSTORE()  UserAssert(GET_CURRENT_BSTORE() > KERNEL_BSTORE_MINIMUM_RESERVE)
#else // _IA64_
#define ASSERT_BSTORE()
#endif // _IA64_

#define ASSERT_STACK() \
    UserAssert(IoGetRemainingStackSize() > KERNEL_STACK_MINIMUM_RESERVE); \
    ASSERT_BSTORE()

__inline ULONG_PTR GET_USED_STACK_SIZE(
    VOID)
{
    ULONG_PTR uLocVer;
    return ((ULONG_PTR)PsGetCurrentThreadStackBase() - (ULONG_PTR)&uLocVer);
}
#endif // DBG

/*
 * The following is a LOCK structure. This structure is recorded for
 * each threadlock so unlocks can occur at cleanup time.
 */
typedef struct _LOCK {
    PTHREADINFO pti;
    PVOID pobj;
    PTL ptl;
#if DBG
    PVOID pfn;                      // for debugging purposes only
    int ilNext;                     // for debugging purposes only
    int iilPrev;                    // for debugging purposes only
#endif // DBG
} LOCK, *PLOCK;

#define NEEDSSYNCPAINT(pwnd) TestWF(pwnd, WFSENDERASEBKGND | WFSENDNCPAINT)

typedef struct tagCVR       // cvr
{
    WINDOWPOS   pos;        // MUST be first field of CVR!
    int         xClientNew; // New client rectangle
    int         yClientNew;
    int         cxClientNew;
    int         cyClientNew;
    RECT        rcBlt;
    int         dxBlt;      // Distance blt rectangle is moving
    int         dyBlt;
    UINT        fsRE;       // RE_ flags: whether hrgnVisOld is empty or not
    HRGN        hrgnVisOld; // Previous visrgn
    PTHREADINFO pti;        // The thread this SWP should be processed on
    HRGN        hrgnClip;   // Window clipping region
    HRGN        hrgnInterMonitor;  // multimon support
} CVR, *PCVR;

/*
 * CalcValidRects() "Region Empty" flag values
 * A set bit indicates the corresponding region is empty.
 */
#define RE_VISNEW       0x0001  // CVR "Region Empty" flag values
#define RE_VISOLD       0x0002  // A set bit indicates the
#define RE_VALID        0x0004  // corresponding region is empty.
#define RE_INVALID      0x0008
#define RE_SPB          0x0010
#define RE_VALIDSUM     0x0020
#define RE_INVALIDSUM   0x0040

typedef struct tagSMWP {    // smwp
    HEAD           head;
    UINT           bShellNotify:1; // The acvr list contains shell notify flags
    UINT           bHandle:1;   // This is an HM object allocation -- See -BeginDeferWindowPos
    /*
     * All fields AFTER ccvr are preserved when reusing the global SMWP structure.
     */
    int            ccvr;        // Number of CVRs in the SWMP
    int            ccvrAlloc;   // Number of actual CVRs allocated in the SMWP
    PCVR           acvr;        // Pointer to array of CVR structures
} SMWP, *PSMWP;

void DestroySMWP(PSMWP psmwp);

/*
 * Clipboard data object definition
 */
typedef struct tagCLIPDATA {
    HEAD    head;
    DWORD   cbData;
    BYTE    abData[0];
} CLIPDATA, *PCLIPDATA;

/*
 * Private User Startupinfo
 */
typedef struct tagUSERSTARTUPINFO {
    DWORD   cb;
    DWORD   dwX;
    DWORD   dwY;
    DWORD   dwXSize;
    DWORD   dwYSize;
    DWORD   dwFlags;
    WORD    wShowWindow;
    WORD    cbReserved2;
} USERSTARTUPINFO, *PUSERSTARTUPINFO;

/*
 * TLBLOCK structure for multiple threads locking.
 */
#define THREADS_PER_TLBLOCK 16

typedef struct tagTLBLOCK {
    struct      tagTLBLOCK *ptlBlockPrev;
    struct {
        PTHREADINFO pti;
        TL          tlpti;
        DWORD       dwFlags;
#if DBG
        DWORD       dwUnlockedCount;
#endif
    } list[THREADS_PER_TLBLOCK];
} TLBLOCK, *PTLBLOCK;

/*
 * Keyboard File object
 */
typedef struct tagKBDFILE {
    HEAD               head;
    struct tagKBDFILE *pkfNext;   // next keyboard file
    HANDLE             hBase;     // base address of data
    PKBDTABLES         pKbdTbl;   // pointer to kbd layout data.
    ULONG              Size;      // Size of pKbdTbl
    PKBDNLSTABLES      pKbdNlsTbl; // pointer to kbd nls layout data.
    WCHAR              awchDllName[32];
#ifdef LATER
    LANGID             langId;    // Default language ID of this layout
#endif
} KBDFILE, *PKBDFILE;

/*
 * Keyboard Layout object
 */
typedef struct tagKL {   /* kl */
    HEAD          head;
    struct tagKL *pklNext;     // next in layout cycle
    struct tagKL *pklPrev;     // prev in layout cycle
    DWORD         dwKL_Flags;  // KL_* flags
    HKL           hkl;         // (Layout ID | Base Language ID)
    KBDFILE      *spkf;        // Keyboard Layout File
    KBDFILE      *spkfPrimary; // Primary keyboard layout file
    DWORD         dwFontSigs;  // mask of FS_xxx bits - fonts that layout is good for
    UINT          iBaseCharset;// Charset value (Win95 compat) eg: ANSI_CHARSET
    WORD          CodePage;    // Windows Codepage of kbd layout, eg: 1252, 1250
    WCHAR         wchDiacritic;// Dead key saved here until next keystroke
    PIMEINFOEX    piiex;       // Extended information for IME based layout
    UINT          uNumTbl;     // number of tables in pKbdTbl
    PKBDFILE     *pspkfExtra;  // extra layout file in this
    DWORD         dwLastKbdType;
    DWORD         dwLastKbdSubType;
    DWORD         dwKLID;      // base keyboard layout ID
} KL, *PKL;

/*
 * Flag values for KL dwFlags
 */
#define KL_UNLOADED 0x20000000
#define KL_RESET    0x40000000


PKL HKLtoPKL(PTHREADINFO pti, HKL hkl);

typedef struct tagKBDLANGTOGGLE
{
    BYTE bVkey;
    BYTE bScan;
    int  iBitPosition;
} KBDLANGTOGGLE;

/*
 * These constants are derived from combinations of
 * iBitPosition (refer to the LangToggle array defined
 * in globals.c).
 */

/*
 * This bit is used for both control and alt keys
 */
#define KLT_ALT              1

/*
 * This bit is used for the left shift key
 */
#define KLT_LEFTSHIFT        2

/*
 * This combination denotes ctrl/alt and the left shift key
 */
#define KLT_ALTLEFTSHIFT     3

/*
 * This bit is used for the right shift key
 */
#define KLT_RIGHTSHIFT       4

/*
 * This combination denotes ctrl/alt and the right shift key
 */
#define KLT_ALTRIGHTSHIFT    5

/*
 * This combination denotes ctrl/alt and both the shift keys
 */
#define KLT_ALTBOTHSHIFTS    7

/*
 * This value is used to mark invalid toggle key sequence
 */
#define KLT_NONE             8


/*
 * Key Event (KE) structure
 * Stores a Virtual Key event
 */
typedef struct tagKE {
    union {
        BYTE bScanCode;    // Virtual Scan Code (Set 1)
        WCHAR wchInjected; // Unicode char from SendInput()
    };
    USHORT usFlaggedVk;    // Vk | Flags
    DWORD  dwTime;         // time in milliseconds
#ifdef GENERIC_INPUT
    HANDLE hDevice;
    KEYBOARD_INPUT_DATA data;
#endif
} KE, *PKE;

/*
 * Misc. keyboard stuff moved from oak/inc/kbd.h
 */
typedef BOOL (* KEPROC)(PKE pKe);
typedef BOOL (* NLSKEPROC)(PKE pKe, ULONG_PTR dwExtraInfo, ULONG dwParam);
typedef BOOL (* NLSVKFPROC)(PVK_F pVkToF, PKE pKe, ULONG_PTR dwExtraInfo);

/*
 * OEM-specific special processing (keystroke simulators and filters)
 */
extern KEPROC aKEProcOEM[];


/*
 * Key message lParam bits
 */
#define EXTENDED_BIT   0x01000000
#define DONTCARE_BIT   0x02000000
#define FAKE_KEYSTROKE 0x02000000
#define ALTNUMPAD_BIT  0x04000000 // copied from windows\inc\wincon.w

/*
 * For handy diacritics
 */
#define IDS_FROM_SCANCODE(prefix, base) \
        (0xc000 + ((0x ## prefix) >= 0xE0 ? 0x100 : 0) + (0x ## base))

//
// NLS Keyboard functions
//
VOID NlsKbdInitializePerSystem(VOID);
VOID NlsKbdSendIMENotification(DWORD dwImeOpen, DWORD dwImeConversion);

/*
 * Desktop flags
 */
#define DF_DYING            0x80000000
#define DF_DESKWNDDESTROYED 0x40000000
#define DF_DESTROYED        0x20000000
#define DF_HOTTRACKING      0x10000000
#define DF_TOOLTIPSHOWING   0x08000000
#define DF_TOOLTIPACTIVE    0x04000000
#define DF_TOOLTIP          (DF_TOOLTIPACTIVE | DF_TOOLTIPSHOWING)
#define DF_TRACKMOUSELEAVE  0x02000000
#define DF_TRACKMOUSEHOVER  0x01000000
#define DF_TRACKMOUSEEVENT  (DF_TRACKMOUSELEAVE | DF_TRACKMOUSEHOVER)
#define DF_MOUSEMOVETRK     (DF_HOTTRACKING | DF_TOOLTIPACTIVE | DF_TRACKMOUSELEAVE | DF_TRACKMOUSEHOVER)
#define DF_MENUINUSE        0x00800000
#define DF_NEWDISPLAYSETTINGS 0x00400000
#define DF_DESKCREATED      0x00200000
#define DF_REDIRECTED       0x00100000
#ifdef BUG365290
#define DF_QUITUNLOCK       0x00080000
#define DF_NOTRITUNLOCK     0x00040000
#define DF_ZOMBIE           0x00020000
#define DF_ACTIVEONDESTROY  0X00010000
#define DF_DTNONEWDESKTOP   0x00008000
#define DF_SKIPSWITCHDESKTOP 0x00004000
#endif //BUG365290


#define CAPTIONTOOLTIPLEN   100

/*
 * Used to identify desktops uniquely for GDI
 */

#define GW_DESKTOP_ID 1

// #define DESKTOP_ALLOC_TRACE
#define DESKTOP_ALLOC_TRACE_SIZE    6

#if DBG
    typedef struct tagDbgAllocHead {
        DWORD    mark;
        DWORD    tag;
        PDESKTOP pdesk;
        SIZE_T   size;                  // the size of the allocation (doesn't include
                                        // this structure

        struct tagDbgAllocHead* pPrev;  // pointer to the previous allocation of this tag
        struct tagDbgAllocHead* pNext;  // pointer to the next allocation of this tag

#ifdef DESKTOP_ALLOC_TRACE
        PVOID  trace[DESKTOP_ALLOC_TRACE_SIZE];
#endif // DESKTOP_ALLOC_TRACE

    } DbgAllocHead, *PDbgAllocHead;
#endif // DBG

#define DTAG_CLASS              0x0001
#define DTAG_DESKTOPINFO        0x0002
#define DTAG_CLIENTTHREADINFO   0x0003
#define DTAG_TEXT               0x0004
#define DTAG_HANDTABL           0x0005
#define DTAG_SBINFO             0x0006
#define DTAG_MENUITEM           0x0007
#define DTAG_MENUTEXT           0x0008
#define DTAG_IMETEXT            0x0009
#define DTAG_PROPLIST           0x000A

/*
 * Desktop Structure.
 *
 *   This structure is only viewable from the kernel. If any desktop
 *   information is needed in the client, then they should reference off
 *   the pDeskInfo field (i.e. pti->pDeskInfo).
 */
typedef struct tagDESKTOP {

    DWORD                   dwSessionId;       // Terminal Server SessionId. This has to be first field in the structure
    PDESKTOPINFO            pDeskInfo;         // Desktop information
    PDISPLAYINFO            pDispInfo;         //

    PDESKTOP                 rpdeskNext;       // Next desktop in list
    PWINDOWSTATION           rpwinstaParent;   // Windowstation owner

    DWORD                   dwDTFlags;         // Desktop flags
    ULONG                   dwDesktopId;       // Needed by GDI to tag display devices

    PWND                     spwndMenu;        //
    PMENU                    spmenuSys;        //
    PMENU                    spmenuDialogSys;  //
    PMENU                    spmenuHScroll;
    PMENU                    spmenuVScroll;
    PWND                     spwndForeground;  //
    PWND                     spwndTray;
    PWND                     spwndMessage;
    PWND                     spwndTooltip;

    HANDLE                  hsectionDesktop;   //
    PWIN32HEAP              pheapDesktop;      //
    DWORD                   dwConsoleThreadId; //
    DWORD                   dwConsoleIMEThreadId;
    CONSOLE_CARET_INFO      cciConsole;
    LIST_ENTRY              PtiList;           //

    PWND                    spwndTrack;        // xxxTrackMouseMove data
    int                     htEx;
    RECT                    rcMouseHover;
    DWORD                   dwMouseHoverTime;


#ifdef LOGDESKTOPLOCKS
    int                     nLockCount;
    int                     nLogMax;
    int                     nLogCrt;
    PLogD                   pLog;
#endif // LOGDESKTOPLOCKS

} DESKTOP;

typedef struct tagDESKWND {
    WND   wnd;
    DWORD idProcess;
    DWORD idThread;
} DESKWND, *PDESKWND;

PVOID DesktopAlloc(PDESKTOP pdesk, UINT uSize,DWORD tag);

#define DesktopAllocAlways(pdesk, uSize, tag)   \
            Win32HeapAlloc(pdesk->pheapDesktop, uSize, tag, 0)

#define DesktopFree(pdesk, p)   Win32HeapFree(pdesk->pheapDesktop, p)

/*
 * Windowstation structure
 */
#define WSF_SWITCHLOCK          0x0001
#define WSF_OPENLOCK            0x0002
#define WSF_NOIO                0x0004
#define WSF_SHUTDOWN            0x0008
#define WSF_DYING               0x0010
#define WSF_REALSHUTDOWN        0x0020

typedef struct tagWINDOWSTATION {
    /*
     * Terminal Server SessionId. This has to be first field in the structure.
     */
    DWORD                dwSessionId;
    PWINDOWSTATION       rpwinstaNext;
    PDESKTOP             rpdeskList;

    PTERMINAL            pTerm;

    DWORD                dwWSF_Flags;
    struct tagKL         *spklList;

    /*
     * Clipboard variables
     */
    PTHREADINFO          ptiClipLock;
    PTHREADINFO          ptiDrawingClipboard;
    PWND                 spwndClipOpen;
    PWND                 spwndClipViewer;
    PWND                 spwndClipOwner;
    struct tagCLIP       *pClipBase;
    int                  cNumClipFormats;
    UINT                 iClipSerialNumber;
    UINT                 iClipSequenceNumber;
    UINT                 fClipboardChanged : 1;
    UINT                 fInDelayedRendering : 1;

    /*
     * Global Atom table
     */
    PVOID                pGlobalAtomTable;

    LUID                 luidEndSession;
    LUID                 luidUser;
    PSID                 psidUser;
    PQ                   pqDesktop;

    /*
     * Pointer to the currently active desktop for the window station.
     */
#if DBG
    PDESKTOP             pdeskCurrent;
#endif // DBG

} WINDOWSTATION;

typedef struct tagCAPTIONCACHE {
    PCURSOR         spcursor;
    POEMBITMAPINFO  pOem;
#if DBG
    HICON           hico;
#endif // DBG
} CAPTIONCACHE;

/*
 * Configurable icon and cursor stuff
 */
    typedef struct tagSYSCFGICO
    {
        WORD    Id;     // configurable id (OIC_ or OCR_ value)
        WORD    StrId;  // String ID for registry key name
        PCURSOR spcur;  // perminant cursor/icon pointer
    } SYSCFGICO;

    #define SYSICO(name) (gasysico[OIC_##name##_DEFAULT - OIC_FIRST_DEFAULT].spcur)
    #define SYSCUR(name) (gasyscur[OCR_##name##_DEFAULT - OCR_FIRST_DEFAULT].spcur)


/*
 * Accelerator Table structure
 */
typedef struct tagACCELTABLE {
    PROCOBJHEAD head;
    UINT        cAccel;
    ACCEL       accel[1];
} ACCELTABLE, *LPACCELTABLE;

/*
 * Besides the desktop window used by the current thread, we also
 * need to get the desktop window of a window and the input desktop
 * window.
 */
#define PWNDDESKTOP(p)      ((p)->head.rpdesk->pDeskInfo->spwnd)
#define PWNDMESSAGE(p)      ((p)->head.rpdesk->spwndMessage)
#define PWNDTOOLTIP(p)      ((p)->head.rpdesk->spwndTooltip)

/*
 * During window destruction, even a locked window can have a
 * NULL parent so use this macro where a NULL parent is a problem.
 */
#define PWNDPARENT(p) (p->spwndParent ? p->spwndParent : PWNDDESKTOP(p))

#define ISAMENU(pwwnd)       \
        (GETFNID(pwnd) == FNID_MENU)


/* NEW MENU STUFF */
typedef struct tagPOPUPMENU
{

  DWORD  fIsMenuBar:1;       /* This is a hacked struct which refers to the
                              * menu bar associated with a app. Only true if
                              * in the root ppopupMenuStruct.
                              */
  DWORD  fHasMenuBar:1;      /* This popup is part of a series which has a
                              * menu bar (either a sys menu or top level menu
                              * bar)
                              */
  DWORD  fIsSysMenu:1;    /* The system menu is here. */
  DWORD  fIsTrackPopup:1;    /* Is TrackPopup popup menu */
  DWORD  fDroppedLeft:1;
  DWORD  fHierarchyDropped:1;/* If true, a submenu has been dropped off this popup */
  DWORD  fRightButton:1;     /* Allow right button in menu */
  DWORD  fToggle:1;          /* If TRUE, button up cancels the popup */
  DWORD  fSynchronous:1;     /* For synchronous return value of cmd chosen */
  DWORD  fFirstClick:1;      /* Keep track if this was the first click on the
                              * top level menu bar item. If the user down/up
                              * clicks on a top level menu bar item twice, we
                              * want to cancel menu mode.
                              */
  DWORD  fDropNextPopup:1;   /* Should we drop hierarchy of next menu item w/ popup? */
  DWORD  fNoNotify:1;        /* Don't send WM_ msgs to owner, except WM_COMMAND  */
  DWORD  fAboutToHide:1;     // Same purpose as fHideTimer?
  DWORD  fShowTimer:1;       // TRUE if the IDSYS_MNSHOW timer is set
  DWORD  fHideTimer:1;       // TRUE if the IDSYS_MNHIDE timer is set

  DWORD  fDestroyed:1;       /* Set when the owner menu window has been destroyed
                              *  so the popup can be freed once it's no longer needed
                              * Also set in root popupmenu when menu mode must end
                              */

  DWORD  fDelayedFree:1;    /* Avoid freeing the popup when the owner menu
                             *  window is destroyed.
                             * If set, it must be a root popupmenu or must
                             *  be linked in ppmDelayedFree
                             * This is eventually set for all hierarchical popups
                             */

  DWORD  fFlushDelayedFree:1; /* Used in root popupmenus only.
                               * Set when a hierarchical popup marked as fDelayedFree
                               *  has been destroyed.
                               */


  DWORD  fFreed:1;           /* Popup has been freed. Used for debug only */

  DWORD  fInCancel:1;        /* Popup has been passed to xxxMNCancel */

  DWORD  fTrackMouseEvent:1; /* TrackMouseEvent has been called */
  DWORD  fSendUninit:1;      /* Send WM_UNINITMENUPOPUP */
  DWORD  fRtoL:1;            /* For going backwards with the keys */
  DWORD  fDesktopMenu:1;     /* Set if this popup belons to the pdesk->spwndMenu window */
  DWORD  iDropDir:5;         /* Animation direction */


  PWND           spwndNotify;
                        /* Window who gets the notification messages. If this
                         * is a window with a menu bar, then this is the same
                         * as hwndPopupMenu.
                         */
  PWND           spwndPopupMenu;
                        /* The window associated with this ppopupMenu struct.
                         * If this is a top level menubar, then hwndPopupMenu
                         * is the window the menu bar. ie. it isn't really a
                         * popup menu window.
                         */
  PWND           spwndNextPopup;
                        /* The next popup in the hierarchy. Null if the last
                         * in chain
                         */
  PWND           spwndPrevPopup;
                        /* The previous popup in the hierarchy. NULL if at top
                         */
  PMENU          spmenu;/* The PMENU displayed in this window
                         */
  PMENU          spmenuAlternate;
                        /* Alternate PMENU. If the system menu is displayed,
                         * and a menubar menu exists, this will contain the
                         * menubar menu. If menubar menu is displayed, this
                         * will contain the system menu. Use only on top level
                         * ppopupMenu structs so that we can handle windows
                         * with both a system menu and a menu bar menu. Only
                         * used in the root ppopupMenuStruct.
                         */

  PWND           spwndActivePopup; /* This is the popup the mouse/"keyboard focus" is on */

  PPOPUPMENU     ppopupmenuRoot;

  PPOPUPMENU     ppmDelayedFree;       /* List of hierarchical popups marked
                                        *  as fDelayedFree.
                                        */

  UINT   posSelectedItem;  /* Position of the selected item in this menu
                            */
  UINT   posDropped;

} POPUPMENU;

typedef struct tagMENUWND {
    WND wnd;
    PPOPUPMENU ppopupmenu;
} MENUWND, *PMENUWND;

/*
 * CheckPoint structure
 */
typedef struct tagCHECKPOINT {
    RECT rcNormal;
    POINT ptMin;
    POINT ptMax;
    DWORD fDragged:1;
    DWORD fWasMaximizedBeforeMinimized:1;
    DWORD fWasMinimizedBeforeMaximized:1;
    DWORD fMinInitialized:1;
    DWORD fMaxInitialized:1;
} CHECKPOINT, *PCHECKPOINT;

typedef struct tagCLIP {
    UINT    fmt;
    HANDLE  hData;
    BOOL    fGlobalHandle;
} CLIP, *PCLIP;

/*
 * DDEML instance structure
 */
typedef struct tagSVR_INSTANCE_INFO {
    THROBJHEAD head;
    struct tagSVR_INSTANCE_INFO *next;
    struct tagSVR_INSTANCE_INFO *nextInThisThread;
    DWORD afCmd;
    PWND spwndEvent;
    PVOID pcii;
} SVR_INSTANCE_INFO, *PSVR_INSTANCE_INFO;

typedef struct tagPUBOBJ {
    struct tagPUBOBJ *next;
    HANDLE hObj;
    int count;
    W32PID pid;
} PUBOBJ, *PPUBOBJ;

/*
 * Defines for Menu focus
 */
#define FREEHOLD    0
#define MOUSEHOLD  -1 /* Mouse button held down and dragging */
#define KEYBDHOLD   1

/*
 * Structure definition for messages as they exist on a Q. Same as MSG
 * structure except for the link-pointer and flags at the end.
 */
typedef struct tagQMSG {
    PQMSG           pqmsgNext;
    PQMSG           pqmsgPrev;
    MSG             msg;
    LONG_PTR        ExtraInfo;
    DWORD           dwQEvent;
    PTHREADINFO     pti;
} QMSG;

/*
 * dwQEvent values for QMSG structure.
 */
#define QEVENT_SHOWWINDOW           0x0001
#define QEVENT_CANCELMODE           0x0002
#define QEVENT_SETWINDOWPOS         0x0003
#define QEVENT_UPDATEKEYSTATE       0x0004
#define QEVENT_DEACTIVATE           0x0005
#define QEVENT_ACTIVATE             0x0006
#define QEVENT_POSTMESSAGE          0x0007  // Chicago
#define QEVENT_EXECSHELL            0x0008  // Chicago
#define QEVENT_CANCELMENU           0x0009  // Chicago
#define QEVENT_DESTROYWINDOW        0x000A
#define QEVENT_ASYNCSENDMSG         0x000B
#define QEVENT_HUNGTHREAD           0x000C
#define QEVENT_CANCELMOUSEMOVETRK   0x000D
#define QEVENT_NOTIFYWINEVENT       0x000E
#define QEVENT_RITACCESSIBILITY     0x000F
#define QEVENT_RITSOUND             0x0010
#define QEVENT_APPCOMMAND           0x0011

#define RITSOUND_UPSIREN            0x0000
#define RITSOUND_DOWNSIREN          0x0001
#define RITSOUND_LOWBEEP            0x0002
#define RITSOUND_HIGHBEEP           0x0003
#define RITSOUND_KEYCLICK           0x0004
#define RITSOUND_DOBEEP             0x0005

/*
 * xxxProcessEventMessage flags
 */
#define PEM_ACTIVATE_RESTORE        0x0001
#define PEM_ACTIVATE_NOZORDER       0x0002

typedef struct _MOVESIZEDATA {
    PWND            spwnd;
    RECT            rcDrag;
    RECT            rcDragCursor;
    RECT            rcParent;
    POINT           ptMinTrack;
    POINT           ptMaxTrack;
    RECT            rcWindow;
    int             dxMouse;
    int             dyMouse;
    int             cmd;
    int             impx;
    int             impy;
    POINT           ptRestore;
    UINT            fInitSize         : 1;    // should we initialize cursor pos
    UINT            fmsKbd            : 1;    // who knows
    UINT            fLockWindowUpdate : 1;    // whether screen was locked ok
    UINT            fTrackCancelled   : 1;    // Set if tracking ended by other thread.
    UINT            fForeground       : 1;    // whether the tracking thread is foreground
                                              //  and if we should draw the drag-rect
    UINT            fDragFullWindows  : 1;
    UINT            fOffScreen        : 1;
} MOVESIZEDATA, *PMOVESIZEDATA;

/*
 * DrawDragRect styles.
 */
#define DDR_START     0     // - start drag.
#define DDR_ENDACCEPT 1     // - end and accept
#define DDR_ENDCANCEL 2     // - end and cancel.


/*
 * Pseudo Event stuff. (fManualReset := TRUE, fInitState := FALSE)
 */

DWORD WaitOnPseudoEvent(HANDLE *phE, DWORD dwMilliseconds);

#define PSEUDO_EVENT_ON     ((HANDLE)IntToPtr( 0xFFFFFFFF ))
#define PSEUDO_EVENT_OFF    ((HANDLE)IntToPtr( 0x00000000 ))
#define INIT_PSEUDO_EVENT(ph) *ph = PSEUDO_EVENT_OFF;

#define SET_PSEUDO_EVENT(phE)                                   \
    CheckCritIn();                                              \
    if (*(phE) == PSEUDO_EVENT_OFF) *(phE) = PSEUDO_EVENT_ON;   \
    else if (*(phE) != PSEUDO_EVENT_ON) {                       \
        KeSetEvent(*(phE), EVENT_INCREMENT, FALSE);             \
        ObDereferenceObject(*(phE));                            \
        *(phE) = PSEUDO_EVENT_ON;                               \
    }

#define RESET_PSEUDO_EVENT(phE)                                 \
    CheckCritIn();                                              \
    if (*(phE) == PSEUDO_EVENT_ON) *(phE) = PSEUDO_EVENT_OFF;   \
    else if (*(phE) != PSEUDO_EVENT_OFF) {                      \
        KeClearEvent(*(phE));                                   \
    }

#define CLOSE_PSEUDO_EVENT(phE)                                 \
    CheckCritIn();                                              \
    if (*(phE) == PSEUDO_EVENT_ON) *(phE) = PSEUDO_EVENT_OFF;   \
    else if (*(phE) != PSEUDO_EVENT_OFF) {                      \
        KeSetEvent(*(phE), EVENT_INCREMENT, FALSE);             \
        ObDereferenceObject(*(phE));                            \
        *(phE) = PSEUDO_EVENT_OFF;                              \
    }

typedef struct tagMLIST {
    PQMSG pqmsgRead;        // next message to be read. This is a FIFO queue
    PQMSG pqmsgWriteLast;   // last message  added to the queue. Used mainly for coalescing
    DWORD cMsgs;            // Count of messages. Used for optimizations and to enforce a max.
} MLIST, *PMLIST;

/*
 * Message Queue structure.
 *
 * Note, if you need to add a WORD sized value,
 * do so after xbtnDblClk.
 */
typedef struct tagQ {
    MLIST       mlInput;            // raw mouse and key message list.

    PTHREADINFO ptiSysLock;         // Thread currently allowed to process input
    ULONG_PTR    idSysLock;          // Last message removed or to be removed before unlocking
    ULONG_PTR    idSysPeek;          // Last message peeked

    PTHREADINFO ptiMouse;           // Last thread to get mouse msg.
    PTHREADINFO ptiKeyboard;

    PWND        spwndCapture;
    PWND        spwndFocus;
    PWND        spwndActive;
    PWND        spwndActivePrev;

    UINT        codeCapture;        // type of captue. See *_CAP* defines in this file
    UINT        msgDblClk;          // last mouse down message removed
    WORD        xbtnDblClk;         // last xbutton down
    DWORD       timeDblClk;         // max time for next button down to be taken as double click
    HWND        hwndDblClk;         // window that got last button down
    POINT       ptDblClk;           // last button down position. See SYSMET(C?DOUBLECLK)

    BYTE        afKeyRecentDown[CBKEYSTATERECENTDOWN];
    BYTE        afKeyState[CBKEYSTATE];

    CARET       caret;

    PCURSOR     spcurCurrent;
    int         iCursorLevel;       // show/hide count. < 0 if the cursor is not visible

    DWORD       QF_flags;            // QF_ flags go here

    USHORT      cThreads;            // Count of threads using this queue
    USHORT      cLockCount;          // Count of threads that don't want this queue freed

    UINT        msgJournal;         // See SetJournalTimer. Journal message to be delivered when timer goes off
    LONG_PTR    ExtraInfo;          // Extra info for last qmsg read. See GetMessageExtraInfo
} Q;

/*
 * Used for zzzAttachThreadInput()
 */
typedef struct tagATTACHINFO {
    struct tagATTACHINFO *paiNext;
    PTHREADINFO pti1;
    PTHREADINFO pti2;
} ATTACHINFO, *PATTACHINFO;

#define POLL_EVENT_CNT 5

#define IEV_IDLE    0
#define IEV_INPUT   1
#define IEV_EXEC    2
#define IEV_TASK    3
#define IEV_WOWEXEC 4


typedef struct tagWOWTHREADINFO {
    struct tagWOWTHREADINFO *pwtiNext;
    DWORD    idTask;                // WOW task id
    ULONG_PTR idWaitObject;          // pseudo handle returned to parent
    DWORD    idParentProcess;       // process that called CreateProcess
    PKEVENT  pIdleEvent;            // event that WaitForInputIdle will wait on
} WOWTHREADINFO, *PWOWTHREADINFO;

/*
 * Task Data Block structure.
 */
typedef struct tagTDB {
    PTDB            ptdbNext;
    int             nEvents;
    int             nPriority;
    PTHREADINFO     pti;
    PWOWTHREADINFO  pwti;               // per thread info for shared Wow
    WORD            hTaskWow;           // Wow cookie to find apps during shutdown
    WORD            TDB_Flags;             //  bit 0 means setup app
} TDB;

#define TDBF_SETUP 1


/*
 * Hack message for shell to tell them a setup app is exiting.
 * This message is defined in \nt\private\shell\inc, but I really
 * don't want to introduce that dependency in the build. DavidDS
 * has put a check in that file to make sure that the value does not
 * change and refers to this usage. FritzS
 */
#define DTM_SETUPAPPRAN (WM_USER+90)

/*
 * Menu animation GDI objects.
 */
typedef struct tagMENUANIDC
{
    HDC     hdcAni;         // Scratch dc for animation
} MENUANIDC;

/*
 * Menu Control Structure
 */
typedef struct tagMENUSTATE {
    PPOPUPMENU pGlobalPopupMenu;
    DWORD   fMenuStarted : 1;
    DWORD   fIsSysMenu : 1;
    DWORD   fInsideMenuLoop : 1;
    DWORD   fButtonDown:1;
    DWORD   fInEndMenu:1;
    DWORD   fUnderline:1;               /* Shorcut key underlines are shown */
    DWORD   fButtonAlwaysDown:1;        /* The mouse has always been down since the menu started */
    DWORD   fDragging:1;                /* Dragging (in DoDragDrop) or about to */
    DWORD   fModelessMenu:1;            /* No modal loop */
    DWORD   fInCallHandleMenuMessages:1;/* processing a msg from CallHandleMM */
    DWORD   fDragAndDrop:1;             /* This menu can do drag and drop */
    DWORD   fAutoDismiss:1;             /* This menu goes away on its own if mouse is off for certain time */
    DWORD   fAboutToAutoDismiss:1;      /* Autodismiss will take place when timer goes off */
    DWORD   fIgnoreButtonUp:1;          /* Eat next button up, i.e, cancel dragging */
    DWORD   fMouseOffMenu:1;            /* Mouse is off the menu - modeless menus only */
    DWORD   fInDoDragDrop:1;            /* in a WM_MENUDODRAGDROP callback */
    DWORD   fActiveNoForeground:1;      /* A menu window is active but we're not in the foreground */
    DWORD   fNotifyByPos:1;             /* Use WM_MENUCOMMAND */
    DWORD   fSetCapture:1;              /* True if the menu mode set capture */
    DWORD   iAniDropDir:5;              /* direction of animation */

    POINT   ptMouseLast;
    int     mnFocus;
    int     cmdLast;
    PTHREADINFO ptiMenuStateOwner;

    DWORD   dwLockCount;

    struct tagMENUSTATE *pmnsPrev;      /* Previous menustate for nested/context menus */

    POINT   ptButtonDown;               /* Mouse down position (begin drag position) */
    ULONG_PTR uButtonDownHitArea;        /* Return from xxxMNFindWindowFromPoint on button down */
    UINT    uButtonDownIndex;           /* Index of the item being dragged */

    int     vkButtonDown;               /* Mouse button being dragged */

    ULONG_PTR uDraggingHitArea;          /* Last hit area while InDoDragDrop */
    UINT    uDraggingIndex;             /* Last index  */
    UINT    uDraggingFlags;             /* Gap flags */

    HDC     hdcWndAni;      // window DC while animating
    DWORD   dwAniStartTime; // starting time of animation
    int     ixAni;          // current x-step in animation
    int     iyAni;          // current y-step in animation
    int     cxAni;          // total x in animation
    int     cyAni;          // total y in animation
    HBITMAP hbmAni;         // Scratch bmp for animation.

    /*
     * Important: The following structure must be the last
     *  thing in tagMENUSTATE. MNAllocMenuState doesn't NULL out
     *  this structure
     */
    MENUANIDC;

} MENUSTATE, *PMENUSTATE;

typedef struct tagLASTINPUT {  /* linp */
    DWORD timeLastInputMessage;
    DWORD dwFlags;
    PTHREADINFO ptiLastWoken;  /* Last thread woken by key or click  */
                               /* It can be NULL                     */
    POINT ptLastClick;         /* point of the last mouse click      */
} LASTINPUT, PLASTINPUT;

#define LINP_KEYBOARD       0x00000001
#define LINP_SCREENSAVER    0x00000002
#define LINP_LOWPOWER       0x00000004
#define LINP_POWEROFF       0x00000008
#define LINP_JOURNALLING    0x00000010
#define LINP_INPUTSOURCES   (LINP_KEYBOARD | LINP_JOURNALLING)
#define LINP_POWERTIMEOUTS  (LINP_LOWPOWER | LINP_POWEROFF)
#define LINP_INPUTTIMEOUTS  (LINP_SCREENSAVER | LINP_LOWPOWER | LINP_POWEROFF)

/*
 * Menu data to be passed to xxxRealDrawMenuItem from xxxDrawState
 */
typedef struct {
    PMENU pMenu;
    PITEM pItem;
} GRAYMENU;
typedef GRAYMENU *PGRAYMENU;


#define IS_THREAD_RESTRICTED(pti, r)                            \
    ((pti->TIF_flags & TIF_RESTRICTED) ?                        \
        (pti->ppi->pW32Job->restrictions & (r)) :               \
        FALSE)

#define IS_CURRENT_THREAD_RESTRICTED(r)                         \
    ((PtiCurrent()->TIF_flags & TIF_RESTRICTED) ?               \
        (PtiCurrent()->ppi->pW32Job->restrictions & (r)) :      \
        FALSE)

/*
 * These types are needed before they are fully defined.
 */
typedef struct tagSMS               * KPTR_MODIFIER PSMS;

/*
 * Make sure this structure matches up with W32THREAD, since they're
 * really the same thing.
 */

/*
 * NOTE -- this structure has been sorted (roughly) in order of use
 * of the fields. The x86 code set allows cheaper access to fields
 * that are in the first 0x80 bytes of a structure. Please attempt
 * to ensure that frequently-used fields are below this boundary.
 *          FritzS
 */

typedef struct tagTHREADINFO {
    W32THREAD;

//***************************************** begin: USER specific fields

    PTL             ptl;                // Listhead for thread lock list

    PPROCESSINFO    ppi;                // process info struct for this thread

    PQ              pq;                 // keyboard and mouse input queue

    PKL             spklActive;         // active keyboard layout for this thread

    PCLIENTTHREADINFO pcti;             // Info that must be visible from client

    PDESKTOP        rpdesk;
    PDESKTOPINFO    pDeskInfo;          // Desktop info visible to client
    PCLIENTINFO     pClientInfo;        // Client info stored in TEB

    DWORD           TIF_flags;          // TIF_ flags go here.

    PUNICODE_STRING pstrAppName;        // Application module name.

    PSMS            psmsSent;           // Most recent SMS this thread has sent
    PSMS            psmsCurrent;        // Received SMS this thread is currently processing
    PSMS            psmsReceiveList;    // SMSs to be processed

    LONG            timeLast;           // Time and ID of last message
    ULONG_PTR       idLast;

    int             exitCode;

    HDESK           hdesk;              // Desktop handle
    int             cPaintsReady;
    UINT            cTimersReady;

    PMENUSTATE      pMenuState;

    union {
        PTDB            ptdb;           // Win16Task Schedule data for WOW thread
        PWINDOWSTATION  pwinsta;        // Window station for SYSTEM thread
    };

    PSVR_INSTANCE_INFO psiiList;        // thread DDEML instance list
    DWORD           dwExpWinVer;
    DWORD           dwCompatFlags;      // The Win 3.1 Compat flags
    DWORD           dwCompatFlags2;     // new DWORD to extend compat flags for NT5+ features

    PQ              pqAttach;           // calculation variabled used in
                                        // zzzAttachThreadInput()

    PTHREADINFO     ptiSibling;         // pointer to sibling thread info

    PMOVESIZEDATA   pmsd;

    DWORD           fsHooks;                // WHF_ Flags for which hooks are installed
    PHOOK           sphkCurrent;            // Hook this thread is currently processing

    PSBTRACK        pSBTrack;

    HANDLE          hEventQueueClient;
    PKEVENT         pEventQueueServer;
    LIST_ENTRY      PtiLink;            // Link to other threads on desktop
    int             iCursorLevel;       // keep track of each thread's level
    POINT           ptLast;             // Position of last message

    PWND            spwndDefaultIme;    // Default IME Window for this thread
    PIMC            spDefaultImc;       // Default input context for this thread
    HKL             hklPrev;            // Previous active keyboard layout
    int             cEnterCount;
    MLIST           mlPost;             // posted message list.
    USHORT          fsChangeBitsRemoved;// Bits removed during PeekMessage
    WCHAR           wchInjected;        // character from last VK_PACKET
    DWORD           fsReserveKeys;      // Keys that must be sent to the active
                                        // active console window.
    PKEVENT        *apEvent;            // Wait array for xxxPollAndWaitForSingleObject
    ACCESS_MASK     amdesk;             // Granted desktop access
    UINT            cWindows;           // Number of windows owned by this thread
    UINT            cVisWindows;        // Number of visible windows on this thread

    PHOOK           aphkStart[CWINHOOKS];   // Hooks registered for this thread
    CLIENTTHREADINFO  cti;              // Use this when no desktop is available

#ifdef GENERIC_INPUT
    HANDLE          hPrevHidData;
#endif
#if DBG
    UINT            cNestedCalls;
#endif
} THREADINFO;

#define PWNDTOPSBTRACK(pwnd) (((GETPTI(pwnd)->pSBTrack)))

/*
 * The number of library module handles we can store in the dependency
 * tables. If this exceeds 32, the load mask implementation must be
 * changed.
 */
#define CLIBS           32

/*
 * Process Info structure.
 */
typedef struct tagWOWPROCESSINFO {
    struct tagWOWPROCESSINFO *pwpiNext; // List of WOW ppi's, gppiFirstWow is head
    PTHREADINFO ptiScheduled;           // current thread in nonpreemptive scheduler
    DWORD       nTaskLock;              // nonpreemptive scheduler task lock count
    PTDB        ptdbHead;               // list of this process's WOW tasks
    PVOID       lpfnWowExitTask;        // func addr for wow exittask callback
    PKEVENT     pEventWowExec;          // WowExec Virt HWint scheduler event
    HANDLE      hEventWowExecClient;    // client handle value for wowexec
    DWORD       nSendLock;              // Send Scheduler inter process Send count
    DWORD       nRecvLock;              // Send Scheduler inter process Receive count
    PTHREADINFO CSOwningThread;         // Pseudo Wow CritSect ClientThreadId
    LONG        CSLockCount;            // Pseudo Wow CritSect LockCount
}WOWPROCESSINFO, *PWOWPROCESSINFO;

typedef struct tagDESKTOPVIEW {
    struct tagDESKTOPVIEW *pdvNext;
    PDESKTOP              pdesk;
    ULONG_PTR              ulClientDelta;
} DESKTOPVIEW, *PDESKTOPVIEW;


/*
 * number of DWORDs in ppi->pgh
 */
#define GH_SIZE  8

/*
 * The delta allocation for ppiTable array in W32JOB structure.
 */
#define JP_DELTA  4

/*
 * W32JOB structure
 */
typedef struct tagW32JOB {
    struct tagW32JOB*  pNext;           // next W32JOB structure
    PEJOB              Job;             // pointer to the EJOB structure
    PVOID              pAtomTable;      // the atom table for the job object
    DWORD              restrictions;    // UI restrictions
    UINT               uProcessCount;   // number of processes in ppiTable
    UINT               uMaxProcesses;   // how much room is in ppiTable
    PPROCESSINFO*      ppiTable;        // the array of processes contained in the job
    UINT               ughCrt;          // crt number of handles in pgh
    UINT               ughMax;          // number of handles pgh can store
    PULONG_PTR         pgh;             // the granted handles table
} W32JOB, *PW32JOB;

#ifdef REDIRECTION
#define PF_REDIRECTED            0x00000001
#define PF_REDIRECTIONHOST       0x00000002
#endif // REDIRECTION

/*
 * Make sure this structure matches up with W32PROCESS, since they're
 * really the same thing.
 */

/*
 * NOTE -- this structure has been sorted (roughly) in order of use
 * of the fields. The x86 code set allows cheaper access to fields
 * that are in the first 0x80 bytes of a structure. Please attempt
 * to ensure that frequently-used fields are below this boundary.
 */

typedef struct tagPROCESSINFO {
    W32PROCESS;
//***************************************** begin: USER specific fields
    PTHREADINFO     ptiList;                    // threads in this process
    PTHREADINFO     ptiMainThread;              // pti of "main thread"
    PDESKTOP        rpdeskStartup;              // initial desktop
    PCLS            pclsPrivateList;            // this processes' private classes
    PCLS            pclsPublicList;             // this processes' public classes
    PWOWPROCESSINFO pwpi;                       // Wow PerProcess Info

    PPROCESSINFO    ppiNext;                    // next ppi structure in start list
    PPROCESSINFO    ppiNextRunning;
    int             cThreads;                   // count of threads using this process info
    HDESK           hdeskStartup;               // initial desktop handle
    UINT            cSysExpunge;                // sys expunge counter
    DWORD           dwhmodLibLoadedMask;        // bits describing loaded hook dlls
    HANDLE          ahmodLibLoaded[CLIBS];      // process unique hmod array for hook dlls
    struct          tagWINDOWSTATION *rpwinsta; // process windowstation
    HWINSTA         hwinsta;                    // windowstation handle
    ACCESS_MASK     amwinsta;                   // windowstation accesses

    DWORD           dwHotkey;                   // hot key from progman
    HMONITOR        hMonitor;                   // monitor handle from CreateProcess
    PDESKTOPVIEW    pdvList;                    // list of desktop views
    UINT            iClipSerialNumber;          // clipboard serial number
    RTL_BITMAP      bmHandleFlags;              // per handle flags
    PCURSOR         pCursorCache;               // process cursor/icon cache
    PVOID           pClientBase;                // LEAVE THIS FOR HYDRA; offset to the shared section
    DWORD           dwLpkEntryPoints;           // user mode language pack installed

    PW32JOB         pW32Job;                    // pointer to the W32JOB structure

    DWORD           dwImeCompatFlags;           // per-process Ime Compatibility flags
    LUID            luidSession;                // logon session id
    USERSTARTUPINFO usi;                        // process startup info

#ifdef VALIDATEHANDLEQUOTA
    LONG lHandles;
#endif

    DWORD           dwLayout;                   // the default Window orientation for this process

#ifdef GENERIC_INPUT
    PPROCESS_HID_TABLE pHidTable;               // per process device request list
#endif

#ifdef REDIRECTION
    DWORD           dwRedirection;             // redirection mode for this process
#endif // REDIRECTION
    DWORD           fDisableWindowsGhosting : 1;
} PROCESSINFO;

/*
 * Bit definitions for dwLpkEntryPoints in the processinfo structure.
 * These are passed from the client side when an lpk is registered.
 * The kernel determines when to perform callbacks based on which
 * entry points an lpk supports.
 */
#define LPK_TABBEDTEXTOUT 0x01
#define LPK_PSMTEXTOUT    0x02
#define LPK_DRAWTEXTEX    0x04
#define LPK_EDITCONTROL   0x08
#define LPK_INSTALLED     0x0f

#define CALL_LPK(ptiCurrent)  ((PpiCurrent()->dwLpkEntryPoints & LPK_INSTALLED) && \
                               !((ptiCurrent)->TIF_flags & TIF_INCLEANUP))

/*
 * This is used to send cool switch windows information
 * to the lpk
 */
typedef struct _LPKDRAWSWITCHWND {
    RECT rcRect;
    LARGE_UNICODE_STRING strName;
} LPKDRAWSWITCHWND;

/*
 * DC cache entry structure (DCE)
 *
 *   This structure identifies an entry in the DCE cache. It is
 *   usually initialized at GetDCEx() and cleanded during RelaseCacheDC
 *   calls.
 *
 *   Field
 *   -----
 *
 *   pdceNext       - Pointer to the next DCE entry.
 *
 *
 *   hdc            - GDI DC handle for the dce entry. This will have
 *                    the necessary clipping regions selected into it.
 *
 *   pwndOrg        - Identifies the window in the GetDCEx() call which owns
 *                    the DCE Entry.
 *
 *   pwndClip       - Identifies the window by which the DC is clipped to.
 *                    This is usually done for PARENTDC windows.
 *
 *   hrgnClip       - This region is set if the caller to GetDCEx() passes a
 *                    clipping region in which to intersect with the visrgn.
 *                    This is used when we need to recalc the visrgn for the
 *                    DCE entry. This will be freed at ReleaseCacheDC()
 *                    time if the flag doesn't have DCX_NODELETERGN set.
 *
 *   hrgnClipPublic - This is a copy of the (hrgnClip) passed in above. We
 *                    make a copy and set it as PUBLIC ownership so that
 *                    we can use it in computations during the UserSetDCVisRgn
 *                    call. This is necessary for Full-Hung-Draw where we
 *                    are drawing from a different process then the one
 *                    who created the (hrgnClip). This is always deleted
 *                    in the ReleaseCacheDC() call.
 *
 *   hrgnSavedVis   - This is a copy of the saved visrgn for the DCE entry.
 *
 *   flags          - DCX_ flags.
 *
 *   ptiOwner       - Thread owner of the DCE entry.
 *
 */
typedef struct tagDCE {
    PDCE                 pdceNext;
    HDC                  hdc;
    PWND                 pwndOrg;
    PWND                 pwndClip;
    HRGN                 hrgnClip;
    HRGN                 hrgnClipPublic;
    HRGN                 hrgnSavedVis;
    DWORD                DCX_flags;
    PTHREADINFO          ptiOwner;
    PMONITOR             pMonitor;
} DCE;

#define DCE_SIZE_CACHEINIT        5    // Initial number of DCEs in the cache.
#define DCE_SIZE_CACHETHRESHOLD  32    // Number of dce's as a threshold.

#define DCE_RELEASED              0    // ReleaseDC released
#define DCE_FREED                 1    // ReleaseDC freed
#define DCE_NORELEASE             2    // ReleaseDC in-use.

/*
 * CalcVisRgn DC type bits
 */
#define DCUNUSED        0x00        /* Unused cache entry */
#define DCC             0x01        /* Client area */
#define DCW             0x02        /* Window area */
#define DCSAVEDVISRGN   0x04
#define DCCLIPRGN       0x08
#define DCNOCHILDCLIP   0x10        /* Nochildern clip */
#define DCSAVEVIS       0x20        /* Save visrgn before calculating */
#define DCCACHE         0x40

/*
 * Window List Structure
 */
typedef struct tagBWL {
    struct tagBWL *pbwlNext;
    HWND          *phwndNext;
    HWND          *phwndMax;
    PTHREADINFO   ptiOwner;
    HWND          rghwnd[1];
} BWL, *PBWL;

/*
 * Numbers of HWND slots to to start with and to increase by.
 */
#define BWL_CHWNDINIT      32     /* initial # slots pre-allocated */
#define BWL_CHWNDMORE       8     /* # slots to obtain when required */

#define BWL_ENUMCHILDREN    1
#define BWL_ENUMLIST        2
#define BWL_ENUMOWNERLIST   4

#define BWL_ENUMIMELAST     0x08
#define BWL_REMOVEIMECHILD  0x10

/*
 * Saved Popup Bits structure
 */
typedef struct tagSPB {
    struct tagSPB *pspbNext;
    PWND          spwnd;
    HBITMAP       hbm;
    RECT          rc;
    HRGN          hrgn;
    DWORD         flags;
    ULONG_PTR     ulSaveId;
} SPB;

#define SPB_SAVESCREENBITS  0x0001  // GreSaveScreenBits() was called
#define SPB_LOCKUPDATE      0x0002  // LockWindowUpdate() SPB
#define SPB_DRAWBUFFER      0x0004  // BeginDrawBuffer() SPB

#define AnySpbs()   (gpDispInfo->pspbFirst != NULL)     // TRUE if there are any SPBs

/*
 * Macro to check if the journal playback hook is installed.
 */
#define FJOURNALRECORD()    (GETDESKINFO(PtiCurrent())->aphkStart[WH_JOURNALRECORD + 1] != NULL)
#define FJOURNALPLAYBACK()  (GETDESKINFO(PtiCurrent())->aphkStart[WH_JOURNALPLAYBACK + 1] != NULL)

#define TESTHMODLOADED(pti, x)       ((pti)->ppi->dwhmodLibLoadedMask & (1 << (x)))
#define SETHMODLOADED(pti, x, hmod)  ((pti)->ppi->ahmodLibLoaded[x] = hmod, \
                                      (pti)->ppi->dwhmodLibLoadedMask |= (1 << (x)))
#define CLEARHMODLOADED(pti, x)      ((pti)->ppi->ahmodLibLoaded[x] = NULL, \
                                      (pti)->ppi->dwhmodLibLoadedMask &= ~(1 << (x)))
#define PFNHOOK(phk) (phk->ihmod == -1 ? (PROC)phk->offPfn : \
        (PROC)(((ULONG_PTR)(PtiCurrent()->ppi->ahmodLibLoaded[phk->ihmod])) + \
        ((ULONG_PTR)(phk->offPfn))))

/*
 * Extended structures for message thunking.
 */
typedef struct _CREATESTRUCTEX {
    CREATESTRUCT cs;
    LARGE_STRING strName;
    LARGE_STRING strClass;
} CREATESTRUCTEX, *PCREATESTRUCTEX;

typedef struct _MDICREATESTRUCTEX {
    MDICREATESTRUCT mdics;
    LARGE_STRING strTitle;
    LARGE_STRING strClass;
} MDICREATESTRUCTEX, *PMDICREATESTRUCTEX;

typedef struct _CWPSTRUCTEX {
    struct tagCWPSTRUCT;
    PSMS            psmsSender;
} CWPSTRUCTEX, *PCWPSTRUCTEX;

typedef struct _CWPRETSTRUCTEX {
    LRESULT         lResult;
    struct tagCWPSTRUCT;
    PSMS            psmsSender;
} CWPRETSTRUCTEX, *PCWPRETSTRUCTEX;

/*
 * SendMessage structure and defines.
 */
typedef struct tagSMS {   /* sms */
    PSMS            psmsNext;          // link in global psmsList
#if DBG
    PSMS            psmsSendList;      // head of queue's SendMessage chain
    PSMS            psmsSendNext;      // link in queue's SendMessage chain
#endif // DBG
    PSMS            psmsReceiveNext;   // link in queue's ReceiveList
    DWORD           tSent;              // time message was sent
    PTHREADINFO     ptiSender;          // sending thread
    PTHREADINFO     ptiReceiver;        // receiving thread

    SENDASYNCPROC   lpResultCallBack;   // function to receive the SendMessageCallback return value
    ULONG_PTR        dwData;             // value to be passed back to the lpResultCallBack function
    PTHREADINFO     ptiCallBackSender;  // sending thread

    LRESULT         lRet;               // message return value
    UINT            flags;              // SMF_ flags
    WPARAM          wParam;             // message fields...
    LPARAM          lParam;
    UINT            message;
    PWND            spwnd;
    PVOID           pvCapture;          // captured argument data
} SMS;

#define SMF_REPLY                   0x0001      // message has been replied to
#define SMF_RECEIVERDIED            0x0002      // receiver has died
#define SMF_SENDERDIED              0x0004      // sender has died
#define SMF_RECEIVERFREE            0x0008      // receiver should free sms when done
#define SMF_RECEIVEDMESSAGE         0x0010      // sms has been received
#define SMF_CB_REQUEST              0x0100      // SendMessageCallback requested
#define SMF_CB_REPLY                0x0200      // SendMessageCallback reply
#define SMF_CB_CLIENT               0x0400      // Client process request
#define SMF_CB_SERVER               0x0800      // Server process request
#define SMF_WOWRECEIVE              0x1000      // wow sched has incr recv count
#define SMF_WOWSEND                 0x2000      // wow sched has incr send count
#define SMF_RECEIVERBUSY            0x4000      // reciver is processing this msg

/*
 * InterSendMsgEx parameter used for SendMessageCallback and TimeOut
 */
typedef struct tagINTERSENDMSGEX {   /* ism */
    UINT   fuCall;                      // callback or timeout call

    SENDASYNCPROC lpResultCallBack;     // function to receive the send message value
    ULONG_PTR dwData;                    // Value to be passed back to the SendResult call back function
    LRESULT lRet;                       // return value from the send message

    UINT fuSend;                        // how to send the message, SMTO_BLOCK, SMTO_ABORTIFHUNG
    UINT uTimeout;                      // time-out duration
    PULONG_PTR lpdwResult;               // the return value for a syncornis call
} INTRSENDMSGEX, *PINTRSENDMSGEX;

#define ISM_CALLBACK        0x0001      // callback function request
#define ISM_TIMEOUT         0x0002      // timeout function request
#define ISM_REQUEST         0x0010      // callback function request message
#define ISM_REPLY           0x0020      // callback function reply message
#define ISM_CB_CLIENT       0x0100      // client process callback function

/*
 * Event structure to handle broadcasts of notification messages.
 */
typedef struct tagASYNCSENDMSG {
    WPARAM  wParam;
    LPARAM  lParam;
    UINT    message;
    HWND    hwnd;
} ASYNCSENDMSG, *PASYNCSENDMSG;

/*
 * HkCallHook() structure
 */
#define IsHooked(pti, fsHook) \
    ((fsHook & (pti->fsHooks | pti->pDeskInfo->fsHooks)) != 0)

#define IsGlobalHooked(pti, fsHook) \
    ((fsHook & pti->pDeskInfo->fsHooks) != 0)

typedef struct tagHOOKMSGSTRUCT { /* hch */
    PHOOK   phk;
    int     nCode;
    LPARAM  lParam;
} HOOKMSGSTRUCT, *PHOOKMSGSTRUCT;

/*
 * BroadcastMessage() commands.
 */
#define BMSG_SENDMSG                0x0000
#define BMSG_SENDNOTIFYMSG          0x0001
#define BMSG_POSTMSG                0x0002
#define BMSG_SENDMSGCALLBACK        0x0003
#define BMSG_SENDMSGTIMEOUT         0x0004
#define BMSG_SENDNOTIFYMSGPROCESS   0x0005

/*
 * xxxBroadcastMessage parameter used for SendMessageCallback and TimeOut
 */
typedef union tagBROADCASTMSG {   /* bcm */
     struct {                               // for callback broadcast
         SENDASYNCPROC lpResultCallBack;    // function to receive the send message value
         ULONG_PTR dwData;                   // Value to be passed back to the SendResult call back function
         BOOL bClientRequest;               // if a cliet or server callback request
     } cb;
     struct {                               // for timeout broadcast
         UINT fuFlags;                      // timeout type flags
         UINT uTimeout;                     // timeout length
         PULONG_PTR lpdwResult;              // where to put the return value
     } to;
} BROADCASTMSG, *PBROADCASTMSG;

/*
 * Internal hotkey structures and defines.
 */
typedef struct tagHOTKEY {
    PTHREADINFO pti;
    PWND    spwnd;
    WORD    fsModifiers; // MOD_SHIFT, MOD_ALT, MOD_CONTROL, MOD_WIN
    WORD    wFlags;      // MOD_SAS
    UINT    vk;
    int     id;
    struct tagHOTKEY *phkNext;
} HOTKEY, *PHOTKEY;

#define PWND_INPUTOWNER (PWND)1    // Means send WM_HOTKEY to input owner.
#define PWND_FOCUS      (PWND)NULL // Means send WM_HOTKEY to queue's pwndFocus.
#define PWND_TOP        (PWND)0
#define PWND_BOTTOM     (PWND)1
#define PWND_GROUPTOTOP ((PWND)-1)
#define PWND_TOPMOST    ((PWND)-1)
#define PWND_NOTOPMOST  ((PWND)-2)
#define PWND_BROADCAST  ((PWND)-1)

#define IDHOT_DEBUG         (-5)
#define IDHOT_DEBUGSERVER   (-6)
#define IDHOT_WINDOWS       (-7)

/*
 * xPos, yPos for WM_CONTEXTMENU from keyboard
 */
#define KEYBOARD_MENU   ((LPARAM)-1)    // Keyboard generated menu

/*
 * Capture codes
 */
#define NO_CAP_CLIENT           0   /* no capture; in client area */
#define NO_CAP_SYS              1   /* no capture; in sys area */
#define CLIENT_CAPTURE          2   /* client-relative capture */
#define WINDOW_CAPTURE          3   /* window-relative capture */
#define SCREEN_CAPTURE          4   /* screen-relative capture */
#define FULLSCREEN_CAPTURE      5   /* capture entire machine */
#define CLIENT_CAPTURE_INTERNAL 6   /* client-relative capture (Win 3.1 style; won't release) */

#define CH_HELPPREFIX   0x08

#ifdef KANJI
    #define CH_KANJI1       0x1D
    #define CH_KANJI2       0x1E
    #define CH_KANJI3       0x1F
#endif // KANJI

#define xxxRedrawScreen() \
        xxxInternalInvalidate(PtiCurrent()->rpdesk->pDeskInfo->spwnd, \
        HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN)

/*
 * Preallocated buffer for use during SetWindowPos to prevent memory
 * allocation failures.
 */
#define CCVR_WORKSPACE      4

/*
 * DrawIconCallBack data, global only for state data in tmswitch.c
 */
typedef struct tagDRAWICONCB {   /* dicb */
    PWND   pwndTop;                     // Window being drawn
    UINT   cx;                          // x offset for icon
    UINT   cy;                          // y offset for icon
} DRAWICONCB, *PDRAWICONCB;

/*
 * The following defines the components of nKeyboardSpeed
 */
#define KSPEED_MASK     0x001F          // Defines the key repeat speed.
#define KDELAY_MASK     0x0060          // Defines the keyboard delay.
#define KDELAY_SHIFT    5

/*
 * Property list checkpoint int
 */
#define PROP_CHECKPOINT     MAKEINTATOM(atomCheckpointProp)
#define PROP_DDETRACK       MAKEINTATOM(atomDDETrack)
#define PROP_QOS            MAKEINTATOM(atomQOS)
#define PROP_DDEIMP         MAKEINTATOM(atomDDEImp)
#define PROP_WNDOBJ         MAKEINTATOM(atomWndObj)
#define PROP_IMELEVEL       MAKEINTATOM(atomImeLevel)
#define PROP_LAYER          MAKEINTATOM(atomLayer)

#define WinFlags    ((WORD)(&__WinFlags))

/*
 * ntinput.c
 */
BOOL xxxInternalKeyEventDirect(
    BYTE  bVk,
    WORD  wScan,
    DWORD dwFlags,
    DWORD dwTime,
    ULONG_PTR dwExtraInfo);

UINT xxxSendInput(
    UINT    nInputs,
    LPINPUT pInputs);

BOOL _BlockInput(
    BOOL    fBlockIt);

int _GetMouseMovePointsEx(
    CONST MOUSEMOVEPOINT* ppt,
    MOUSEMOVEPOINT*       pptBuf,
    UINT                  nPoints,
    DWORD                 resolution);


VOID xxxProcessKeyEvent(
   PKE       pke,
   ULONG_PTR ExtraInformation,
   BOOL      bInjected);

VOID xxxButtonEvent(
    DWORD ButtonNumber,
    POINT ptPointer,
    BOOL  fBreak,
    DWORD time,
    ULONG_PTR ExtraInfo,
#ifdef GENERIC_INPUT
    HANDLE hDevice,
    PMOUSE_INPUT_DATA pmei,
#endif
    BOOL  bInjected,
    BOOL  fDblClk);

VOID xxxMoveEvent(
    LONG         dx,
    LONG         dy,
    DWORD        dwFlags,
    ULONG_PTR    dwExtraInfo,
#ifdef GENERIC_INPUT
    HANDLE       hDevice,
    PMOUSE_INPUT_DATA pmei,
#endif
    DWORD        time,
    BOOL         bInjected
    );

typedef struct _RIT_INIT {
    PTERMINAL pTerm;
    PKEVENT   pRitReadyEvent;
} RIT_INIT, *PRIT_INIT;

PDEVICEINFO StartDeviceRead(PDEVICEINFO pDeviceInfo);

NTSTATUS DeviceNotify(
    IN PPLUGPLAY_NOTIFY_HDR pNotification,
    IN PDEVICEINFO pDeviceInfo);

#define MOUSE_SENSITIVITY_MIN     1
#define MOUSE_SENSITIVITY_DEFAULT 10
#define MOUSE_SENSITIVITY_MAX     20
LONG CalculateMouseSensitivity(LONG lSens);

PDEVICEINFO FreeDeviceInfo(PDEVICEINFO pMouseInfo);


__inline PTHREADINFO PtiKbdFromQ(PQ pq)
{
    if (pq->spwndActive) {
        return GETPTI(pq->spwndActive);
    }
    UserAssert(pq->ptiKeyboard);
    return pq->ptiKeyboard;
}

__inline PTHREADINFO ValidatePtiKbd(PQ pq)
{
    if (pq == NULL) {
        return NULL;
    }
    return PtiKbdFromQ(pq);
}

__inline PTHREADINFO PtiMouseFromQ(PQ pq)
{
    if (pq->spwndCapture) {
        return GETPTI(pq->spwndCapture);
    }
    UserAssert(pq->ptiMouse);
    return pq->ptiMouse;
}

__inline PTHREADINFO ValidatePtiMouse(PQ pq)
{
    if (pq == NULL) {
        return NULL;
    }
    return PtiMouseFromQ(pq);
}


VOID QueueMouseEvent(
    USHORT       ButtonFlags,
    USHORT       ButtonData,
    ULONG_PTR    ExtraInfo,
    POINT        ptMouse,
    LONG         time,
#ifdef GENERIC_INPUT
    HANDLE       hDevice,
    PMOUSE_INPUT_DATA pmei,
#endif
    BOOL         bInjected,
    BOOL         bWakeRIT
    );

typedef struct {
    DWORD dwVersion;
    DWORD dwFlags;
    DWORD dwMapCount;
    DWORD dwMap[0];
} SCANCODEMAP, *PSCANCODEMAP;


#ifndef SCANCODE_NUMPAD_PLUS
#define SCANCODE_NUMPAD_PLUS    (0x4e)
#endif
#ifndef SCANCODE_NUMPAD_DOT
#define SCANCODE_NUMPAD_DOT     (0x53)
#endif

/*
 * Flag (LowLevel and HighLevel) for
 * hex Alt+Numpad mode.
 * If you need to add a new flag for gfInNumpadHexInput,
 * note the variable is BYTE.
 */
#define NUMPAD_HEXMODE_LL       (1)
#define NUMPAD_HEXMODE_HL       (2)

#define MODIFIER_FOR_ALT_NUMPAD(wModBit) \
    (((wModBits) == KBDALT) || ((wModBits) == (KBDALT | KBDSHIFT)) || \
     ((wModBits) == (KBDKANA | KBDALT)) || ((wModBits) == (KBDKANA | KBDALT | KBDSHIFT)))


BOOL UnqueueMouseEvent(PMOUSEEVENT pme);

BYTE    VKFromVSC(PKE pke, BYTE bPrefix, LPBYTE afKeyState);
BOOL    KEOEMProcs(PKE pke);
BOOL    xxxKELocaleProcs(PKE pke);
BOOL    xxxKENLSProcs(PKE pke, ULONG_PTR dwExtraInformation);

VOID    xxxKeyEvent(USHORT usVk, WORD wScanCode, DWORD time, ULONG_PTR ExtraInfo,
#ifdef GENERIC_INPUT
                    HANDLE hDevice,
                    PKEYBOARD_INPUT_DATA pkei,
#endif
                    BOOL bInjected);

typedef BITMAPINFOHEADER *PBMPHEADER, *LPBMPHEADER;

/*
 * Defines for WinOldAppHackoMatic flags which win386 oldapp can send to us.
 * These are kept in user's global variable winOldAppHackoMaticFlags
 */
#define WOAHACK_CHECKALTKEYSTATE 1
#define WOAHACK_IGNOREALTKEYDOWN 2

void xxxSimpleDoSyncPaint(PWND pwnd);
VOID xxxDoSyncPaint(PWND pwnd, DWORD flags);
void xxxInternalDoSyncPaint(PWND pwnd, DWORD flags);

/*
 * NOTE: the first 4 values must be as defined for backward compatibility
 * reasons. They are sent as parameters to the WM_SYNCPAINT message.
 * They used to be hard-coded constants.
 *
 * Only ENUMCLIPPEDCHILDREN, ALLCHILDREN, and NOCHECKPARENTS are passed on
 * during recursion. The other bits reflect the current window only.
 */
#define DSP_ERASE               0x0001  // Send WM_ERASEBKGND
#define DSP_FRAME               0x0002  // Send WM_NCPAINT
#define DSP_ENUMCLIPPEDCHILDREN 0x0004  // Enum children if WS_CLIPCHILDREN
#define DSP_WM_SYNCPAINT        0x0008  // Called from WM_SYNCPAINT handler
#define DSP_NOCHECKPARENTS      0x0010  // Don't check parents for update region
#define DSP_ALLCHILDREN         0x0020  // Enumerate all children.

BOOL xxxDrawAnimatedRects(
    PWND pwndClip,
    int idAnimation,
    LPRECT lprcStart,
    LPRECT lprcEnd);

typedef struct tagTIMER {           // tmr
    HEAD            head;
    struct tagTIMER *ptmrNext;
    struct tagTIMER *ptmrPrev;
    PTHREADINFO     pti;
    struct tagWND * spwnd;
    UINT_PTR        nID;
    DWORD           cmsCountdown;
    DWORD           cmsRate;
    UINT            flags;
    TIMERPROC_PWND  pfn;
    PTHREADINFO     ptiOptCreator;     // used for journal playback
                                       // will be NULL if timer was created by non-GUI thread
} TIMER, *PTIMER;

UINT_PTR InternalSetTimer(PWND pwnd, UINT_PTR nIDEvent, UINT dwElapse,
        TIMERPROC_PWND pTimerFunc, UINT flags);

VOID FreeTimer(PTIMER ptmr);
BOOL ValidateTimerCallback(PTHREADINFO, PWND, WPARAM, LPARAM);

/*
 * Call FindTimer() with fKill == TRUE and TMRF_RIT. This will basically
 * delete the timer.
 */
#define KILLRITTIMER(pwnd, nID) FindTimer(pwnd, nID, TMRF_RIT, TRUE)

/*
 * Raster Ops
 */
#define PATOR 0x00FA0089L  /* destination, pattern, or */

/*
 * Message thunks.
 */
typedef LRESULT (APIENTRY *SFNSCSENDMESSAGE)(PWND, UINT, WPARAM, LPARAM,
        ULONG_PTR, PROC, DWORD, PSMS);

#define SMESSAGEPROTO(func) \
     LRESULT CALLBACK Sfn ## func(                              \
        PWND pwnd, UINT msg, WPARAM wParam, LPARAM lParam,      \
        ULONG_PTR xParam, PROC xpfnWndProc, DWORD dwSCMSFlags, PSMS psms)

SMESSAGEPROTO(SENTDDEMSG);
SMESSAGEPROTO(DDEINIT);
SMESSAGEPROTO(DWORD);
SMESSAGEPROTO(NCDESTROY);
SMESSAGEPROTO(INWPARAMCHAR);
SMESSAGEPROTO(INWPARAMDBCSCHAR);

SMESSAGEPROTO(GETTEXTLENGTHS);

SMESSAGEPROTO(GETDBCSTEXTLENGTHS);
SMESSAGEPROTO(INLPCREATESTRUCT);
SMESSAGEPROTO(INLPDROPSTRUCT);
SMESSAGEPROTO(INOUTLPPOINT5);
SMESSAGEPROTO(INOUTLPSCROLLINFO);
SMESSAGEPROTO(INOUTLPRECT);
SMESSAGEPROTO(INOUTNCCALCSIZE);
SMESSAGEPROTO(OUTLPRECT);
SMESSAGEPROTO(INLPMDICREATESTRUCT);
SMESSAGEPROTO(INLPCOMPAREITEMSTRUCT);
SMESSAGEPROTO(INLPDELETEITEMSTRUCT);
SMESSAGEPROTO(INLPHLPSTRUCT);
SMESSAGEPROTO(INLPHELPINFOSTRUCT);      // WINHELP4
SMESSAGEPROTO(INLPDRAWITEMSTRUCT);
SMESSAGEPROTO(INOUTLPMEASUREITEMSTRUCT);
SMESSAGEPROTO(INSTRING);
SMESSAGEPROTO(INPOSTEDSTRING);
SMESSAGEPROTO(INSTRINGNULL);
SMESSAGEPROTO(OUTSTRING);
SMESSAGEPROTO(INCNTOUTSTRING);
SMESSAGEPROTO(POUTLPINT);
SMESSAGEPROTO(POPTINLPUINT);
SMESSAGEPROTO(INOUTLPWINDOWPOS);
SMESSAGEPROTO(INLPWINDOWPOS);
SMESSAGEPROTO(INLBOXSTRING);
SMESSAGEPROTO(OUTLBOXSTRING);
SMESSAGEPROTO(INCBOXSTRING);
SMESSAGEPROTO(OUTCBOXSTRING);
SMESSAGEPROTO(INCNTOUTSTRINGNULL);
SMESSAGEPROTO(INOUTDRAG);
SMESSAGEPROTO(FULLSCREEN);
SMESSAGEPROTO(INPAINTCLIPBRD);
SMESSAGEPROTO(INSIZECLIPBRD);
SMESSAGEPROTO(OUTDWORDDWORD);
SMESSAGEPROTO(OUTDWORDINDWORD);
SMESSAGEPROTO(OPTOUTLPDWORDOPTOUTLPDWORD);
SMESSAGEPROTO(DWORDOPTINLPMSG);
SMESSAGEPROTO(COPYGLOBALDATA);
SMESSAGEPROTO(COPYDATA);
SMESSAGEPROTO(INDESTROYCLIPBRD);
SMESSAGEPROTO(INOUTNEXTMENU);
SMESSAGEPROTO(INOUTSTYLECHANGE);
SMESSAGEPROTO(IMAGEIN);
SMESSAGEPROTO(IMAGEOUT);
SMESSAGEPROTO(INDEVICECHANGE);
SMESSAGEPROTO(INOUTMENUGETOBJECT);
SMESSAGEPROTO(POWERBROADCAST);
SMESSAGEPROTO(LOGONNOTIFY);
SMESSAGEPROTO(IMECONTROL);
SMESSAGEPROTO(IMEREQUEST);
SMESSAGEPROTO(INLPKDRAWSWITCHWND);
SMESSAGEPROTO(OUTLPCOMBOBOXINFO);
SMESSAGEPROTO(OUTLPSCROLLBARINFO);

/***************************************************************************\
* Function Prototypes
*
* NOTE: Only prototypes for GLOBAL (across module) functions should be put
* here. Prototypes for functions that are global to a single module should
* be put at the head of that module.
*
* LATER: There's still lots of bogus trash in here to be cleaned out.
*
\***************************************************************************/

/*
 * Random prototypes.
 */
DWORD _GetWindowContextHelpId(
    PWND pwnd);

BOOL _SetWindowContextHelpId(
    PWND pwnd,
    DWORD dwContextId);

void xxxSendHelpMessage(
    PWND   pwnd,
    int    iType,
    int    iCtrlId,
    HANDLE hItemHandle,
    DWORD  dwContextId);

HPALETTE _SelectPalette(
    HDC hdc,
    HPALETTE hpalette,
    BOOL fForceBackground);

int xxxRealizePalette(
    HDC hdc);

VOID xxxFlushPalette(
    PWND pwnd);

VOID xxxBroadcastPaletteChanged(
    PWND pwnd,
    BOOL fForceDesktop);

PCURSOR SearchIconCache(
    PCURSOR         pCursorCache,
    ATOM            atomModName,
    PUNICODE_STRING pstrResName,
    PCURSOR         pCursorSrc,
    PCURSORFIND     pcfSearch);

VOID ZombieCursor(PCURSOR pcur);

BOOL IsSmallerThanScreen(PWND pwnd);

BOOL zzzSetSystemCursor(
    PCURSOR pcur,
    DWORD   id);

BOOL zzzSetSystemImage(
    PCURSOR pcur,
    PCURSOR pcurOld);

BOOL _InternalGetIconInfo(
    IN  PCURSOR                  pcur,
    OUT PICONINFO                piconinfo,
    OUT OPTIONAL PUNICODE_STRING pstrModName,
    OUT OPTIONAL PUNICODE_STRING pstrResName,
    OUT OPTIONAL LPDWORD         pbpp,
    IN  BOOL                     fInternalCursor);

VOID LinkCursor(
    PCURSOR pcur);

BOOL _SetCursorIconData(
    PCURSOR         pcur,
    PUNICODE_STRING pstrModName,
    PUNICODE_STRING pstrResName,
    PCURSORDATA     pData,
    DWORD           cbData);

PCURSOR _GetCursorFrameInfo(
    PCURSOR pcur,
    int     iFrame,
    PJIF    pjifRate,
    LPINT   pccur);

BOOL zzzSetSystemCursor(
    PCURSOR pcur,
    DWORD id);

PCURSOR _FindExistingCursorIcon(
    ATOM            atomModName,
    PUNICODE_STRING pstrResName,
    PCURSOR         pcurSrc,
    PCURSORFIND     pcfSearch);

HCURSOR _CreateEmptyCursorObject(
    BOOL fPublic);

BOOL _GetUserObjectInformation(HANDLE h,
    int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded);
BOOL _SetUserObjectInformation(HANDLE h,
    int nIndex, PVOID pvInfo, DWORD nLength);
DWORD xxxWaitForInputIdle(ULONG_PTR idProcess, DWORD dwMilliseconds,
        BOOL fSharedWow);
VOID StartScreenSaver(BOOL bOnlyIfSecure);
UINT InternalMapVirtualKeyEx(UINT wCode, UINT wType, PKBDTABLES pKbdTbl);
SHORT InternalVkKeyScanEx(WCHAR cChar, PKBDTABLES pKbdTbl);



PWND ParentNeedsPaint(PWND pwnd);
VOID SetHungFlag(PWND pwnd, WORD wFlag);
VOID ClearHungFlag(PWND pwnd, WORD wFlag);

BOOL _DdeSetQualityOfService(PWND pwndClient,
        CONST PSECURITY_QUALITY_OF_SERVICE pqosNew,
        PSECURITY_QUALITY_OF_SERVICE pqosOld);
BOOL _DdeGetQualityOfService(PWND pwndClient,
        PWND pwndServer, PSECURITY_QUALITY_OF_SERVICE pqos);

BOOL QueryTrackMouseEvent(LPTRACKMOUSEEVENT lpTME);
void CancelMouseHover(PQ pq);
void ResetMouseTracking(PQ pq, PWND pwnd);

void _SetIMEShowStatus(BOOL fShow);
BOOL _GetIMEShowStatus(VOID);

/*
 * Prototypes for internal version of APIs.
 */
PWND _FindWindowEx(PWND pwndParent, PWND pwndChild,
                              LPCWSTR pszClass, LPCWSTR pszName, DWORD dwType);
UINT APIENTRY GreSetTextAlign(HDC, UINT);
UINT APIENTRY GreGetTextAlign(HDC);

/*
 * Prototypes for validation, RIP, error handling, etc functions.
 */
PWND FASTCALL   ValidateHwnd(HWND hwnd);

NTSTATUS ValidateHwinsta(HWINSTA, KPROCESSOR_MODE, ACCESS_MASK, PWINDOWSTATION*);
NTSTATUS ValidateHdesk(HDESK, KPROCESSOR_MODE, ACCESS_MASK, PDESKTOP*);

PMENU           ValidateHmenu(HMENU hmenu);
PMONITOR        ValidateHmonitor(HMONITOR hmonitor);
HRGN            UserValidateCopyRgn(HRGN);

BOOL    ValidateHandleSecure(HANDLE h);

NTSTATUS UserJobCallout(PKWIN32_JOBCALLOUT_PARAMETERS Parm);

BOOL RemoveProcessFromJob(PPROCESSINFO ppi);


BOOL    xxxActivateDebugger(UINT fsModifiers);

void ClientDied(void);

VOID    SendMsgCleanup(PTHREADINFO ptiCurrent);
VOID    ReceiverDied(PSMS psms, PSMS *ppsmsUnlink);
LRESULT xxxInterSendMsgEx(PWND, UINT, WPARAM, LPARAM, PTHREADINFO, PTHREADINFO, PINTRSENDMSGEX );
VOID    ClearSendMessages(PWND pwnd);
PPCLS   GetClassPtr(ATOM atom, PPROCESSINFO ppi, HANDLE hModule);
BOOL    ReferenceClass(PCLS pcls, PWND pwnd);
VOID    DereferenceClass(PWND pwnd);
ULONG_PTR MapClientToServerPfn(ULONG_PTR dw);


VOID xxxReceiveMessage(PTHREADINFO);
#define xxxReceiveMessages(pti) \
    while ((pti)->pcti->fsWakeBits & QS_SENDMESSAGE) { xxxReceiveMessage((pti)); }

PBWL     BuildHwndList(PWND pwnd, UINT flags, PTHREADINFO ptiOwner);
VOID     FreeHwndList(PBWL pbwl);

#define  MINMAX_KEEPHIDDEN 0x1
#define  MINMAX_ANIMATE    0x10000

PWND     xxxMinMaximize(PWND pwnd, UINT cmd, DWORD dwFlags);
void     xxxMinimizeHungWindow(PWND pwnd);
VOID     xxxInitSendValidateMinMaxInfo(PWND pwnd, LPMINMAXINFO lpmmi);
HRGN     CreateEmptyRgn(void);
HRGN     CreateEmptyRgnPublic(void);
HRGN     SetOrCreateRectRgnIndirectPublic(HRGN * phrgn, LPCRECT lprc);
BOOL     SetEmptyRgn(HRGN hrgn);
BOOL     SetRectRgnIndirect(HRGN hrgn, LPCRECT lprc);
void     RegisterCDROMNotify(void);
NTSTATUS xxxRegisterForDeviceClassNotifications();
VOID     xxxUnregisterDeviceClassNotifications();
BOOL     xxxInitInput(PTERMINAL);
VOID     InitMice();
void     UpdateMouseInfo(void);
BOOL     OpenMouse(PDEVICEINFO pMouseInfo);
void     ProcessDeviceChanges(DWORD DeviceType);
PDEVICEINFO CreateDeviceInfo(DWORD DeviceType, PUNICODE_STRING SymbolicLinkName, BYTE bFlags);
void     InitKeyboard(void);
void     InitKeyboardState(void);
UINT     xxxHardErrorControl(DWORD, HANDLE, PDESKRESTOREDATA);



#define UPDATE_KBD_TYPEMATIC 1
#define UPDATE_KBD_LEDS      2

VOID     SetKeyboardRate(UINT nKeySpeed);
VOID     RecolorDeskPattern();
BOOL     xxxInitWindowStation(PWINDOWSTATION);
VOID     zzzInternalSetCursorPos(int x, int y);
VOID     UpdateKeyLights(BOOL bInjected);
VOID     SetDebugHotKeys();
VOID     BoundCursor(LPPOINT lppt);

void     DestroyKF(PKBDFILE pkf);
VOID     DestroyKL(PKL pkl);
VOID     CleanupKeyboardLayouts();

BOOL     xxxSetDeskPattern(PUNICODE_STRING pProfileUserName,LPWSTR lpPat, BOOL fCreation);
BOOL     xxxSetDeskWallpaper(PUNICODE_STRING pProfileUserName,LPWSTR lpszFile);
HPALETTE CreateDIBPalette(LPBITMAPINFOHEADER pbmih, UINT colors);
BOOL     CalcVisRgn(HRGN* hrgn, PWND pwndOrg, PWND pwndClip, DWORD flags);

NTSTATUS xxxCreateThreadInfo(PETHREAD, BOOL);

BOOL     DestroyProcessInfo(PW32PROCESS);

#if DBG
PWCHAR GetDesktopName(PDESKTOP pdesk);
#endif // DBG


VOID    RawInputThread(PVOID pVoid);
HANDLE  GetRemoteProcessId(void);
void    HandleSystemThreadCreationFailure(BOOL bRemoteThread);
void    xxxCreateSystemThreads(BOOL bRemoteThread);

VOID     xxxDesktopThread(PTERMINAL pTerm);
VOID     ForceEmptyClipboard(PWINDOWSTATION);

NTSTATUS zzzInitTask(UINT dwExpWinVer, DWORD dwAppCompatFlags, DWORD dwUserWOWCompatFlags,
                PUNICODE_STRING pstrModName, PUNICODE_STRING pstrBaseFileName,
                DWORD hTaskWow, DWORD dwHotkey, DWORD idTask,
                DWORD dwX, DWORD dwY, DWORD dwXSize, DWORD dwYSize);
VOID    DestroyTask(PPROCESSINFO ppi, PTHREADINFO ptiToRemove);
BOOL    PostInputMessage(PQ pq, PWND pwnd, UINT message, WPARAM wParam,
                LPARAM lParam, DWORD time, ULONG_PTR dwExtraInfo);
PWND    PwndForegroundCapture(VOID);
BOOL    xxxSleepThread(UINT fsWakeMask, DWORD Timeout, BOOL fForegroundIdle);
VOID    SetWakeBit(PTHREADINFO pti, UINT wWakeBit);
VOID    WakeSomeone(PQ pq, UINT message, PQMSG pqmsg);
VOID    ClearWakeBit(PTHREADINFO pti, UINT wWakeBit, BOOL fSysCheck);
NTSTATUS xxxInitProcessInfo(PW32PROCESS);

PTHREADINFO PtiFromThreadId(DWORD idThread);
BOOL    zzzAttachThreadInput(PTHREADINFO ptiAttach, PTHREADINFO ptiAttachTo, BOOL fAttach);
BOOL    zzzReattachThreads(BOOL fJournalAttach);
PQ      AllocQueue(PTHREADINFO, PQ);
VOID    FreeQueue(PQ pq);


VOID    FreeCachedQueues(VOID);
VOID    CleanupGDI(VOID);
VOID    CleanupResources(VOID);

VOID    zzzDestroyQueue(PQ pq, PTHREADINFO pti);
PQMSG   AllocQEntry(PMLIST pml);
__inline VOID FreeQEntry(PQMSG pqmsg)
{
    extern PPAGED_LOOKASIDE_LIST QEntryLookaside;
    ExFreeToPagedLookasideList(QEntryLookaside, pqmsg);
}

VOID    DelQEntry(PMLIST pml, PQMSG pqmsg);
VOID    zzzAttachToQueue(PTHREADINFO pti, PQ pqAttach, PQ pqJournal,
        BOOL fJoiningForeground);
VOID    xxxProcessEventMessage(PTHREADINFO ptiCurrent, PQMSG pqmsg);
VOID    xxxProcessSetWindowPosEvent(PSMWP psmwpT);
VOID    xxxProcessAsyncSendMessage(PASYNCSENDMSG pmsg);
BOOL    PostEventMessage(PTHREADINFO pti, PQ pq, DWORD dwQEvent, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);

BOOL    xxxDoPaint(PWND pwndFilter, LPMSG lpMsg);
BOOL    DoTimer(PWND pwndFilter);
BOOL    CheckPwndFilter(PWND pwnd, PWND pwndFilter);

#define WHT_IGNOREDISABLED      0x00000001

#ifdef REDIRECTION

#define WHT_FAKESPEEDHITTEST    0x00000002

PWND    xxxCallSpeedHitTestHook(POINT* ppt);
VOID    PushMouseMove(PQ pq, POINT pt);
VOID    PopMouseMove(PQ pq, POINT* ppt);

#endif // REDIRECTION

BOOL    xxxGetCursorPos(LPPOINT lpPt);
HWND    xxxWindowHitTest(PWND pwnd,  POINT pt, int *pipos, DWORD dwHitTestFlags);
HWND    xxxWindowHitTest2(PWND pwnd, POINT pt, int *pipos, DWORD dwHitTestFlags);

PWND    SpeedHitTest(PWND pwndParent, POINT pt);
VOID    xxxDeactivate(PTHREADINFO pti, DWORD tidSetForeground);

#define SFW_STARTUP             0x0001
#define SFW_SWITCH              0x0002
#define SFW_NOZORDER            0x0004
#define SFW_SETFOCUS            0x0008
#define SFW_ACTIVATERESTORE     0x0010

BOOL    xxxSetForegroundWindow2(PWND pwnd, PTHREADINFO ptiCurrent, DWORD fFlags);
VOID    SetForegroundThread(PTHREADINFO pti);
VOID    xxxSendFocusMessages(PTHREADINFO pti, PWND pwndReceive);

#define ATW_MOUSE               0x0001
#define ATW_SETFOCUS            0x0002
#define ATW_ASYNC               0x0004
#define ATW_NOZORDER            0x0008

BOOL    FBadWindow(PWND pwnd);
BOOL    xxxActivateThisWindow(PWND pwnd, DWORD tidLoseForeground, DWORD fFlags);
BOOL    xxxActivateWindow(PWND pwnd, UINT cmd);

#define NTW_PREVIOUS         1
#define NTW_IGNORETOOLWINDOW 2
PWND    NextTopWindow(PTHREADINFO pti, PWND pwnd, PWND pwndSkip, DWORD flags);

int     xxxMouseActivate(PTHREADINFO pti, PWND pwnd, UINT message, WPARAM wParam, LPPOINT lppt, int ht);
int     UT_GetParentDCClipBox(PWND pwnd, HDC hdc, LPRECT lprc);
VOID    UpdateAsyncKeyState(PQ pq, UINT wVK, BOOL fBreak);
void    PostUpdateKeyStateEvent(PQ pq);
void    ProcessUpdateKeyStateEvent(PQ pq, CONST PBYTE pbKeyState, CONST PBYTE pbRecentDown);

BOOL    InternalSetProp(PWND pwnd, LPWSTR pszKey, HANDLE hData, DWORD dwFlags);
HANDLE  InternalRemoveProp(PWND pwnd, LPWSTR pszKey, BOOL fInternal);
VOID    DeleteProperties(PWND pwnd);
CHECKPOINT *CkptRestore(PWND pwnd, LPCRECT lprcWindow);
UINT_PTR _SetTimer(PWND pwnd, UINT_PTR nIDEvent, UINT dwElapse, TIMERPROC_PWND pTimerFunc);
BOOL    KillTimer2(PWND pwnd, UINT_PTR nIDEvent, BOOL fSystemTimer);
VOID    DestroyThreadsTimers(PTHREADINFO pti);
VOID    DecTimerCount(PTHREADINFO pti);
VOID    zzzInternalShowCaret();
VOID    zzzInternalHideCaret();
VOID    zzzInternalDestroyCaret();
VOID    ChangeAcquireResourceType(VOID);
VOID    EnterCrit(VOID);
VOID    EnterSharedCrit(VOID);
VOID    LeaveCrit(VOID);
VOID    _AssertCritIn(VOID);
VOID    _AssertDeviceInfoListCritIn(VOID);
VOID    _AssertCritInShared(VOID);
VOID    _AssertCritOut(VOID);
VOID    _AssertDeviceInfoListCritOut(VOID);
NTSTATUS _KeUserModeCallback (IN ULONG ApiNumber, IN PVOID InputBuffer,
    IN ULONG InputLength, OUT PVOID *OutputBuffer, OUT PULONG OutputLength);

#define UnlockProcess           ObDereferenceObject
#define UnlockThread            ObDereferenceObject

extern ULONG gSessionId;

#if DBG
    #define ValidateProcessSessionId(pEProcess)  \
        UserAssert(PsGetProcessSessionId(pEProcess) == gSessionId)

    #define ValidateThreadSessionId(pEThread)  \
        UserAssert(PsGetThreadSessionId(pEThread) == gSessionId)
#else
    #define ValidateProcessSessionId(pEProcess)
    #define ValidateThreadSessionId(pEThread)
#endif


__inline NTSTATUS LockProcessByClientId(
    HANDLE dwProcessId,
    PEPROCESS* ppEProcess)
{
    NTSTATUS Status;

    CheckCritOut();

    Status = PsLookupProcessByProcessId(dwProcessId, ppEProcess);

    if (NT_SUCCESS(Status) && (PsGetProcessSessionId(*ppEProcess) != gSessionId)) {
        UnlockProcess(*ppEProcess);
        return STATUS_UNSUCCESSFUL;
    }

    return Status;
}

__inline NTSTATUS LockThreadByClientId(
    HANDLE dwThreadId,
    PETHREAD* ppEThread)
{
    NTSTATUS Status;

    Status = PsLookupThreadByThreadId(dwThreadId, ppEThread);

    if (NT_SUCCESS(Status) && (PsGetThreadSessionId(*ppEThread) != gSessionId)) {
        UnlockThread(*ppEThread);
        return STATUS_UNSUCCESSFUL;
    }

    return Status;
}

BOOL    IsSAS(BYTE vk, UINT* pfsModifiers);
BOOL    xxxDoHotKeyStuff(UINT vk, BOOL fBreak, DWORD fsReserveKeys);
PHOTKEY IsHotKey(UINT fsModifiers, UINT vk);
void    ClearCachedHotkeyModifiers(void);

/*
 * Server.c
 */
BOOL InitCreateUserCrit(VOID);
PMDEV InitVideo(
    BOOL bReenumerationNeeded);

/*
 * DRVSUP.C
 */
BOOL InitUserScreen();

VOID InitLoadResources();

typedef struct tagDISPLAYRESOURCE {
    WORD cyThunb;
    WORD cxThumb;
    WORD xCompressIcon;
    WORD yCompressIcon;
    WORD xCompressCursor;
    WORD yCompressCursor;
    WORD yKanji;
    WORD cxBorder;
    WORD cyBorder;
} DISPLAYRESOURCE, *PDISPLAYRESOURCE;



VOID xxxUserResetDisplayDevice(VOID);

/*
 * Object management and security
 */
#define DEFAULT_WINSTA  L"\\Windows\\WindowStations\\WinSta0"

#define POBJECT_NAME(pobj) (OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(pobj)) ? \
    &(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(pobj))->Name) : NULL)

PSECURITY_DESCRIPTOR CreateSecurityDescriptor(PACCESS_ALLOWED_ACE paceList,
        DWORD cbAce, BOOLEAN fDaclDefaulted);
PACCESS_ALLOWED_ACE AllocAce(PACCESS_ALLOWED_ACE pace, BYTE bType,
        BYTE bFlags, ACCESS_MASK am, PSID psid, LPDWORD lpdwLength);
BOOL CheckGrantedAccess(ACCESS_MASK, ACCESS_MASK);
BOOL AccessCheckObject(PVOID, ACCESS_MASK, KPROCESSOR_MODE, CONST GENERIC_MAPPING *);
BOOL InitSecurity(VOID);
BOOL IsPrivileged(PPRIVILEGE_SET ppSet);
BOOL CheckWinstaWriteAttributesAccess(void);

NTSTATUS xxxUserDuplicateObject(HANDLE SourceProcessHandle, HANDLE SourceHandle,
        HANDLE TargetProcessHandle, PHANDLE TargetHandle, ACCESS_MASK DesiredAccess,
        ULONG HandleAttributes, ULONG Options);
HWINSTA xxxConnectService(PUNICODE_STRING, HDESK *);
NTSTATUS TestForInteractiveUser(PLUID pluidCaller);
NTSTATUS _UserTestForWinStaAccess( PUNICODE_STRING pstrWinSta, BOOL fInherit);
HDESK xxxResolveDesktop(HANDLE hProcess, PUNICODE_STRING pstrDesktop,
    HWINSTA *phwinsta, BOOL fInherit, BOOL* pbShutDown);

/* NEW CODE */
NTSTATUS xxxResolveDesktopForWOW (
    IN OUT PUNICODE_STRING pstrDesktop);

WORD xxxClientWOWGetProcModule(WNDPROC_PWND pfn);
DWORD xxxClientWOWTask16SchedNotify(DWORD NotifyParm,DWORD dwParam);

PVOID _MapDesktopObject(HANDLE h);
PDESKTOPVIEW GetDesktopView(PPROCESSINFO ppi, PDESKTOP pdesk);
VOID TerminateConsole(PDESKTOP);


/*
 * Object manager callouts for windowstations
 */
NTSTATUS DestroyWindowStation(
     PKWIN32_CLOSEMETHOD_PARAMETERS pCloseParams );

NTSTATUS FreeWindowStation(
     PKWIN32_DELETEMETHOD_PARAMETERS pDeleteParams );

NTSTATUS ParseWindowStation(
     PKWIN32_PARSEMETHOD_PARAMETERS pParseParams );

NTSTATUS OkayToCloseWindowStation(
     PKWIN32_OKAYTOCLOSEMETHOD_PARAMETERS pOkCloseParams);

NTSTATUS WindowStationOpenProcedure(
     PKWIN32_OPENMETHOD_PARAMETERS pOpenParams);

/*
 * Object manager callouts for desktops
 */
NTSTATUS DesktopOpenProcedure(
    PKWIN32_OPENMETHOD_PARAMETERS pOpenParams);

NTSTATUS MapDesktop(
     PKWIN32_OPENMETHOD_PARAMETERS pOpenParams );

NTSTATUS UnmapDesktop(
     PKWIN32_CLOSEMETHOD_PARAMETERS pCloseParams );

NTSTATUS FreeDesktop(
    PKWIN32_DELETEMETHOD_PARAMETERS pDeleteParams );

NTSTATUS ParseDesktop(
    IN PVOID ParseObject,
    IN PVOID ObjectType,
    IN OUT PACCESS_STATE AccessState,
    IN KPROCESSOR_MODE AccessMode,
    IN ULONG Attributes,
    IN OUT PUNICODE_STRING CompleteName,
    IN OUT PUNICODE_STRING RemainingName,
    IN OUT PVOID Context OPTIONAL,
    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    OUT PVOID *Object);

NTSTATUS OkayToCloseDesktop(
    PKWIN32_OKAYTOCLOSEMETHOD_PARAMETERS pOkCloseParams);

/*
 * Routines pilfered from kernel32
 */
VOID UserSleep(DWORD dwMilliseconds);
BOOL UserBeep(DWORD dwFreq, DWORD dwDuration);
NTSTATUS UserRtlCreateAtomTable(ULONG NumberOfBuckets);
ATOM UserAddAtom(LPCWSTR lpAtom, BOOL bPin);
ATOM UserFindAtom(LPCWSTR lpAtom);
ATOM UserDeleteAtom(ATOM atom);
UINT UserGetAtomName(ATOM atom, LPWSTR lpch, int cchMax);

#define FindClassAtom(lpszClassName) \
    (IS_PTR(lpszClassName) ? UserFindAtom(lpszClassName) : PTR_TO_ID(lpszClassName))

/*
 * Keyboard Layouts
 */
void SetGlobalKeyboardTableInfo(PKL pklNew);
VOID ChangeForegroundKeyboardTable(PKL pklOld, PKL pklNew);
HKL  xxxLoadKeyboardLayoutEx(PWINDOWSTATION, HANDLE, HKL, UINT,
                             PKBDTABLE_MULTI_INTERNAL,
                             LPCWSTR, UINT, UINT);
HKL  xxxActivateKeyboardLayout(PWINDOWSTATION pwinsta, HKL hkl, UINT Flags, PWND pwnd);
HKL  xxxInternalActivateKeyboardLayout(PKL pkl, UINT Flags, PWND pwnd);
BOOL GetKbdLangSwitch(PUNICODE_STRING pProfileUserName);

BOOL xxxUnloadKeyboardLayout(PWINDOWSTATION, HKL);
VOID RemoveKeyboardLayoutFile(PKBDFILE pkf);
HKL  _GetKeyboardLayout(DWORD idThread);
UINT _GetKeyboardLayoutList(PWINDOWSTATION pwinsta, UINT nItems, HKL *lpBuff);
VOID xxxFreeKeyboardLayouts(PWINDOWSTATION, BOOL bUnlock);

DWORD xxxDragObject(PWND pwndParent, PWND xhwndFrom, UINT wFmt,
        ULONG_PTR dwData, PCURSOR xpcur);
BOOL xxxDragDetect(PWND pwnd, POINT pt);
BOOL xxxIsDragging(PWND pwnd, POINT ptScreen, UINT uMsg);

HKL GetActiveHKL();

#define DMI_INVERT         0x00000001
#define DMI_GRAYED         0x00000002

VOID xxxDrawMenuItem(HDC hdc, PMENU pMenu, PITEM pItem, DWORD dwFlags);
BOOL xxxRealDrawMenuItem(HDC hdc, PGRAYMENU lpGray, int cx, int cy);
VOID xxxDrawMenuBarUnderlines(PWND pwnd, BOOL fShow);
UINT MNItemHitTest(PMENU pMenu, PWND pwnd, POINT pt);


/*
 * Menu macros
 */
__inline BOOL IsRootPopupMenu(PPOPUPMENU ppopupmenu)
{
    return (ppopupmenu == ppopupmenu->ppopupmenuRoot);
}
__inline BOOL ExitMenuLoop (PMENUSTATE pMenuState, PPOPUPMENU ppopupmenu)
{
    return  (!pMenuState->fInsideMenuLoop || ppopupmenu->fDestroyed);
}
__inline PMENUSTATE GetpMenuState (PWND pwnd)
{
    return (GETPTI(pwnd)->pMenuState);
}
__inline PPOPUPMENU GetpGlobalPopupMenu (PWND pwnd)
{
    return (GetpMenuState(pwnd) ? GetpMenuState(pwnd)->pGlobalPopupMenu : NULL);
}
__inline BOOL IsInsideMenuLoop(PTHREADINFO pti)
{
    return ((pti->pMenuState != NULL) && pti->pMenuState->fInsideMenuLoop);
}
__inline BOOL IsMenuStarted(PTHREADINFO pti)
{
    return ((pti->pMenuState != NULL) && pti->pMenuState->fMenuStarted);
}
__inline PITEM MNGetToppItem(PMENU pMenu)
{
    return pMenu->rgItems + pMenu->iTop;
}
__inline BOOL MNIsItemSelected(PPOPUPMENU ppopupmenu)
{
    return ((int)ppopupmenu->posSelectedItem >= 0);
}
__inline PITEM MNGetSelectedpitem(PPOPUPMENU ppopupmenu)
{
    return ppopupmenu->spmenu->rgItems + ppopupmenu->posSelectedItem;
}
__inline BOOL MNIsScrollArrowSelected(PPOPUPMENU ppopupmenu)
{
    return ((ppopupmenu->posSelectedItem == MFMWFP_UPARROW)
            || (ppopupmenu->posSelectedItem == MFMWFP_DOWNARROW));
}
__inline BOOL IsModelessMenuNotificationWindow (PWND pwnd)
{
    PMENUSTATE pMenuState;
    return (((pMenuState = GetpMenuState(pwnd)) != NULL)
                && pMenuState->fModelessMenu
                && (pMenuState->pGlobalPopupMenu->spwndNotify == pwnd));
}
__inline BOOL IsRecursedMenuState(PMENUSTATE pMenuState, PPOPUPMENU ppopupmenu)
{
    return (pMenuState->pGlobalPopupMenu != ppopupmenu->ppopupmenuRoot);
}

__inline BOOL IsMDIItem (PITEM pitem)
{
   return (TestMFS(pitem, MFS_CACHEDBMP)
      && (pitem->hbmp != NULL)
      && (pitem->hbmp <= HBMMENU_MBARLAST));
}

/*
 * This definition for CM_MODE_TRANSITION must match the one in ntcon\inc\server.h
 */

#define CM_MODE_TRANSITION       (WM_USER+6)

#define MNXBORDER (SYSMET(CXBORDER) + SYSMET(CXEDGE))
#define MNYBORDER (SYSMET(CYBORDER) + SYSMET(CYEDGE))
#define MNXSPACE  (SYSMET(CXEDGE))
#define MNLEFTMARGIN (SYSMET(CXEDGE))

/*
 * xxxMNUpdateShownMenu flags
 */
#define MNUS_DEFAULT      0x00000001
#define MNUS_DELETE       0x00000002
#define MNUS_DRAWFRAME    0x00000004

/* This tells xxxMNItemSize that the bitamp size is not avilable */
#define MNIS_MEASUREBMP -1


/*
 * MN_SIZEWINDOW wParam flag. xxxMNUpdateShownMenu sends this
 *  message, so keep MNSW_ and MNUS_ in sync.
 */
#define MNSW_RETURNSIZE  0
#define MNSW_SIZE        MNUS_DEFAULT
#define MNSW_DRAWFRAME   MNUS_DRAWFRAME

/*
 * Animation flags (pMenuState->iAniDropDir)
 */
#define PAS_RIGHT       (TPM_HORPOSANIMATION >> TPM_FIRSTANIBITPOS)
#define PAS_LEFT        (TPM_HORNEGANIMATION >> TPM_FIRSTANIBITPOS)
#define PAS_DOWN        (TPM_VERPOSANIMATION >> TPM_FIRSTANIBITPOS)
#define PAS_UP          (TPM_VERNEGANIMATION >> TPM_FIRSTANIBITPOS)
#define PAS_OUT         0x10
#define PAS_HORZ        (PAS_LEFT | PAS_RIGHT)
#define PAS_VERT        (PAS_UP | PAS_DOWN)

#if (PAS_HORZ + PAS_VERT >= PAS_OUT)
#error PAS_ & TPM_*ANIMATION conflict.
#endif

#define CXMENU3DEDGE 1
#define CYMENU3DEDGE 1

/*
 * Scrollbar initialization types
 */
#define SCROLL_NORMAL   0
#define SCROLL_DIRECT   1
#define SCROLL_MENU     2

/*
 * movesize.c
 */
void xxxDrawDragRect(PMOVESIZEDATA pmsd, LPRECT lprc, UINT flags);
void GetMonitorMaxArea(PWND pwnd, PMONITOR pMonitor, LPRECT * pprc);

/*
 * focusact.c
 */
VOID SetForegroundPriorityProcess(PPROCESSINFO ppi, PTHREADINFO pti, BOOL fSetForegound);
VOID SetForegroundPriority(PTHREADINFO pti, BOOL fSetForeground);
void xxxUpdateTray(PWND pwnd);


//
// mnchange.c
//
void xxxMNUpdateShownMenu(PPOPUPMENU ppopup, PITEM pItem, UINT uFlags);

//
// mnkey.c
//
UINT xxxMNFindChar(PMENU pMenu, UINT ch, INT idxC, INT *lpr);
UINT MNFindItemInColumn(PMENU pMenu, UINT idxB, int dir, BOOL fRoot);

//
// mndraw.c
//
void MNAnimate(PMENUSTATE pMenuState, BOOL fIterate);
void MNDrawFullNC(PWND pwnd, HDC hdcIn, PPOPUPMENU ppopup);
void MNDrawArrow(HDC hdcIn, PPOPUPMENU ppopup, UINT uArrow);
void MNEraseBackground (HDC hdc, PMENU pmenu, int x, int y, int cx, int cy);
void MNDrawEdge(PMENU pmenu, HDC hdc, RECT * prcDraw, UINT nFlags);


//
// mnstate.c
//
PMENUSTATE xxxMNAllocMenuState(PTHREADINFO ptiCurrent, PTHREADINFO ptiNotify, PPOPUPMENU ppopupmenuRoot);
void xxxMNEndMenuState(BOOL fFreePopup);
BOOL MNEndMenuStateNotify (PMENUSTATE pMenuState);
void MNFlushDestroyedPopups (PPOPUPMENU ppopupmenu, BOOL fUnlock);
BOOL MNSetupAnimationDC (PMENUSTATE pMenuState);
BOOL MNCreateAnimationBitmap(PMENUSTATE pMenuState, UINT cx, UINT cy);
void MNDestroyAnimationBitmap(PMENUSTATE pMenuState);
PMENUSTATE xxxMNStartMenuState(PWND pwnd, DWORD cmd, LPARAM lParam);
__inline VOID LockMenuState(
    PMENUSTATE pMenuState)
{
    (pMenuState->dwLockCount)++;
}
BOOL xxxUnlockMenuState (PMENUSTATE pMenuState);

//
// menu.c
//
#if DBG
    VOID Validateppopupmenu(PPOPUPMENU ppopupmenu);
#else // DBG
    #define Validateppopupmenu(ppopupmenu)
#endif // DBG

#if DBG
    #define MNGetpItemIndex DBGMNGetpItemIndex
UINT DBGMNGetpItemIndex(PMENU pmenu, PITEM pitem);
#else // DBG
    #define MNGetpItemIndex _MNGetpItemIndex
#endif // DBG

__inline UINT _MNGetpItemIndex(
    PMENU pmenu,
    PITEM pitem)
{
    return (UINT)(((ULONG_PTR)pitem - (ULONG_PTR)pmenu->rgItems) / sizeof(ITEM));
}

VOID xxxMNDismiss(PMENUSTATE pMenuState);
PITEM MNGetpItem(PPOPUPMENU ppopup, UINT uIndex);
VOID xxxMNSetCapture(PPOPUPMENU ppopup);
VOID xxxMNReleaseCapture(VOID);
VOID MNCheckButtonDownState(PMENUSTATE pMenuState);
PWND GetMenuStateWindow(PMENUSTATE pMenuState);
PVOID LockPopupMenu(PPOPUPMENU ppopup, PMENU * pspmenu, PMENU pmenu);
PVOID UnlockPopupMenu(PPOPUPMENU ppopup, PMENU * pspmenu);
PVOID LockWndMenu(PWND pwnd, PMENU * pspmenu, PMENU pmenu);
PVOID UnlockWndMenu(PWND pwnd, PMENU * pspmenu);
UINT MNSetTimerToCloseHierarchy(PPOPUPMENU ppopup);
BOOL xxxMNSetTop(PPOPUPMENU ppopup, int iNewTop);
LRESULT xxxMenuWindowProc(PWND, UINT, WPARAM, LPARAM);
VOID xxxMNButtonUp(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT posItemHit, LPARAM lParam);
VOID xxxMNButtonDown(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT posItemHit, BOOL fClick);
PITEM xxxMNSelectItem(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT itemPos);
BOOL xxxMNSwitchToAlternateMenu(PPOPUPMENU ppopupMenu);
VOID xxxMNCancel(PMENUSTATE pMenuState, UINT uMsg, UINT cmd, LPARAM lParam);
VOID xxxMNKeyDown(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT key);
BOOL xxxMNDoubleClick(PMENUSTATE pMenuState, PPOPUPMENU ppopup, int idxItem);
VOID xxxMNCloseHierarchy(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState);
PWND xxxMNOpenHierarchy(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState);
VOID LockMFMWFPWindow (PULONG_PTR puHitArea, ULONG_PTR uNewHitArea);
VOID UnlockMFMWFPWindow (PULONG_PTR puHitArea);
BOOL IsMFMWFPWindow (ULONG_PTR uHitArea);
LONG_PTR xxxMNFindWindowFromPoint(PPOPUPMENU ppopupMenu, PUINT pIndex, POINTS screenPt);
VOID xxxMNMouseMove(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, POINTS screenPt);
int xxxMNCompute(PMENU pMenu, PWND pwndNotify, DWORD yMenuTop,
        DWORD xMenuLeft,DWORD cxMax, LPDWORD lpdwHeight);
VOID xxxMNRecomputeBarIfNeeded(PWND pwndNotify, PMENU pMenu);
VOID xxxMenuDraw(HDC hdc, PMENU pMenu);
UINT  MNFindNextValidItem(PMENU pMenu, int i, int dir, UINT flags);
VOID MNFreeItem(PMENU pMenu, PITEM pItem, BOOL fFreeItemPopup);
BOOL   xxxMNStartMenu(PPOPUPMENU ppopupMenu, int mn);
VOID MNPositionSysMenu(PWND pwnd, PMENU pSysMenu);

PITEM xxxMNInvertItem(PPOPUPMENU ppopupmenu, PMENU pMenu,int itemNumber,PWND pwndNotify, BOOL fOn);

VOID   xxxSendMenuSelect(PWND pwndNotify, PWND pwndMenu, PMENU pMenu, int idx);
#define SMS_NOMENU      (PMENU)(-1)


BOOL   xxxSetSystemMenu(PWND pwnd, PMENU pMenu);
BOOL   xxxSetDialogSystemMenu(PWND pwnd);

VOID xxxMNChar(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT character);
PPOPUPMENU MNAllocPopup(BOOL fForceAlloc);
VOID MNFreePopup(PPOPUPMENU ppopupmenu);

/*
 * Menu entry points used by the rest of USER
 */
VOID xxxMNKeyFilter(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, UINT ch);
int  xxxMenuBarCompute(PMENU pMenu, PWND pwndNotify, DWORD yMenuTop,
        DWORD xMenuLeft, int cxMax);
VOID xxxEndMenu(PMENUSTATE pMenuState);
BOOL xxxCallHandleMenuMessages(PMENUSTATE pMenuState, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL xxxHandleMenuMessages(LPMSG lpmsg, PMENUSTATE pMenuState, PPOPUPMENU ppopupmenu);
void xxxEndMenuLoop (PMENUSTATE pMenuState, PPOPUPMENU ppopupmenu);
int  xxxMNLoop(PPOPUPMENU ppopupMenu, PMENUSTATE pMenuState, LPARAM lParam, BOOL fDblClk);
VOID xxxSetSysMenu(PWND pwnd);
PMENU xxxGetSysMenuHandle(PWND pwnd);
PMENU xxxGetSysMenu(PWND pwnd, BOOL fSubMenu);
PMENU MakeMenuRtoL(PMENU pMenu, BOOL bRtoL);
HDC CreateCompatiblePublicDC(HDC hdc, HBITMAP *pbmDCGray);
void xxxPSMTextOut(HDC hdc, int xLeft, int yTop, LPWSTR lpsz, int cch, DWORD dwFlags);
BOOL xxxPSMGetTextExtent(HDC hdc, LPWSTR lpstr, int cch, PSIZE psize);

/*
 * LPK callbacks
 */
void xxxClientPSMTextOut(HDC hdc, int xLeft, int yTop, PUNICODE_STRING lpsz, int cch, DWORD dwFlags);
int  xxxClientLpkDrawTextEx(HDC hdc, int xLeft, int yTop, LPCWSTR lpsz, int nCount,
        BOOL fDraw, UINT wFormat, LPDRAWTEXTDATA lpDrawInfo, UINT bAction, int iCharSet);
BOOL xxxClientExtTextOutW(HDC hdc, int x, int y, int flOpts, RECT *prcl,
        LPCWSTR pwsz, UINT cwc, INT *pdx);
BOOL xxxClientGetTextExtentPointW(HDC hdc, LPCWSTR lpstr, int cch, PSIZE psize);

/*
 * Menu Drag and Drop
 */
NTSTATUS xxxClientRegisterDragDrop (HWND hwnd);
NTSTATUS xxxClientRevokeDragDrop (HWND hwnd);
NTSTATUS xxxClientLoadOLE(VOID);
void xxxMNSetGapState (ULONG_PTR uHitArea, UINT uIndex, UINT uFlags, BOOL fSet);
BOOL xxxMNDragOver(POINT * ppt, PMNDRAGOVERINFO pmndoi);
BOOL xxxMNDragLeave(VOID);
void xxxMNUpdateDraggingInfo (PMENUSTATE pMenuState, ULONG_PTR uHitArea, UINT uIndex);

/*
 * Scroll bar entry points
 */
VOID xxxSBTrackInit(PWND pwnd, LPARAM lParam, int curArea, UINT uType);
VOID SBCtlSetup(PSBWND psbwnd);
void CalcSBStuff(PWND pwnd, PSBCALC pSBCalc, BOOL fVert);
void CalcSBStuff2(PSBCALC  pSBCalc, LPRECT lprc, CONST PSBDATA pw, BOOL fVert);
BOOL xxxEnableScrollBar(PWND pwnd, UINT wSBflags, UINT wArrows);
void DrawSize(PWND pwnd, HDC hdc, int cxFrame, int cyFrame);
int xxxScrollWindowEx(PWND pwnd, int dx, int dy, LPRECT prcScroll,
        LPRECT prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, DWORD flags);
void xxxDoScrollMenu(PWND pwndNotify, PWND pwndSB, BOOL fVert, LPARAM lParam);

/*
 * ICONS.C
 */
BOOL xxxInternalEnumWindow(PWND pwndNext, WNDENUMPROC_PWND lpfn, LPARAM lParam, UINT fEnumChildren);
VOID ISV_InitMinMaxInfo(PWND pwnd, PPOINT aptMinMaxWnd);
VOID ISV_ValidateMinMaxInfo(PWND pwnd, PPOINT aptMinMaxWnd);
/*
 * GETSET.C
 */
WORD  _SetWindowWord(PWND pwnd, int index, WORD value);
DWORD xxxSetWindowLong(PWND pwnd, int index, DWORD value, BOOL bAnsi);
ULONG_PTR xxxSetWindowData(PWND pwnd, int index, ULONG_PTR dwData, BOOL bAnsi);
LONG  xxxSetWindowStyle(PWND pwnd, int gwl, DWORD styleNew);
BOOL FCallerOk(PWND pwnd);

int IntersectVisRect(HDC, int, int, int, int);  // Imported from GDI
PCURSOR xxxGetWindowSmIcon(PWND pwnd, BOOL fDontSendMsg);
VOID xxxDrawCaptionBar(PWND pwnd, HDC hdc, UINT fFlags);
VOID xxxDrawScrollBar(PWND pwnd, HDC hdc, BOOL fVert);
VOID xxxTrackBox(PWND, UINT, WPARAM, LPARAM, PSBCALC);
VOID xxxTrackThumb(PWND, UINT, WPARAM, LPARAM, PSBCALC);
VOID xxxEndScroll(PWND pwnd, BOOL fCancel);
VOID xxxDrawWindowFrame(PWND pwnd, HDC hdc, UINT wFlags);
BOOL xxxInternalPaintDesktop(PWND pwnd, HDC hdc, BOOL fPaint);
VOID xxxSysCommand(PWND pwnd, DWORD cmd, LPARAM lParam);
VOID xxxHandleNCMouseGuys(PWND pwnd, UINT message, int htArea, LPARAM lParam);
void xxxCreateClassSmIcon(PCLS pcls);
HICON xxxCreateWindowSmIcon(PWND pwnd, HICON hIconBig, BOOL fCopyFromRes);
BOOL DestroyWindowSmIcon(PWND pwnd);
BOOL DestroyClassSmIcon(PCLS pcls);
UINT DWP_GetHotKey(PWND);
UINT DWP_SetHotKey(PWND, DWORD);
PWND HotKeyToWindow(DWORD);

VOID xxxDWP_DoNCActivate(PWND pwnd, DWORD dwFlags, HRGN hrgnClip);
#define NCA_ACTIVE          0x00000001
#define NCA_FORCEFRAMEOFF   0x00000002

VOID xxxDWP_ProcessVirtKey(UINT key);
BOOL xxxDWP_EraseBkgnd(PWND pwnd, UINT msg, HDC hdc);
VOID SetTiledRect(PWND pwnd, LPRECT lprc, PMONITOR pMonitor);
VOID LinkWindow(PWND pwnd, PWND pwndInsert, PWND pwndParent);
VOID UnlinkWindow(PWND pwndUnlink, PWND pwndParent);
VOID xxxDW_DestroyOwnedWindows(PWND pwndParent);
VOID xxxDW_SendDestroyMessages(PWND pwnd);
VOID xxxFreeWindow(PWND pwnd, PTL ptlpwndFree);
VOID xxxFW_DestroyAllChildren(PWND pwnd);

PHOTKEY FindHotKey(PTHREADINFO pti, PWND pwnd, int id, UINT fsModifiers, UINT vk,
        BOOL fUnregister, PBOOL pfKeysExist);

NTSTATUS _BuildNameList(
        PWINDOWSTATION pwinsta,
        PNAMELIST pNameList,
        UINT cbNameList,
        PUINT pcbNeeded);

VOID xxxHelpLoop(PWND pwnd);

NTSTATUS _BuildPropList(PWND pwnd, PROPSET aPropSet[], UINT cPropMax, PUINT pcPropReturned);
BOOL xxxSendEraseBkgnd(PWND pwnd, HDC hdcBeginPaint, HRGN hrgnUpdate);
LONG xxxSetScrollBar(PWND pwnd, int code, LPSCROLLINFO lpsi, BOOL fRedraw);
VOID IncPaintCount(PWND pwnd);
VOID DecPaintCount(PWND pwnd);
PPROP CreateProp(PWND pwnd);

/*
 * METRICS.C
 */
VOID xxxRecreateSmallIcons(PWND pwnd);

VOID   TransferWakeBit(PTHREADINFO pti, UINT message);
BOOL   SysHasKanji(VOID);
LONG   xxxBroadcastMessage(PWND, UINT, WPARAM, LPARAM, UINT, PBROADCASTMSG );

VOID   zzzSetFMouseMoved();

VOID   TimersProc(VOID);

VOID   PostMove(PQ pq);
VOID   DestroyWindowsTimers(PWND pwnd);

UINT_PTR StartTimers(VOID);

/*==========================================================================*/
/*                                                                          */
/*  Internal Function Declarations                                          */
/*                                                                          */
/*==========================================================================*/

LRESULT xxxTooltipWndProc(PWND, UINT, WPARAM, LPARAM);
LRESULT xxxSwitchWndProc(PWND, UINT, WPARAM, LPARAM);
LRESULT xxxDesktopWndProc(PWND, UINT, WPARAM, LPARAM);

LRESULT xxxSBWndProc(PSBWND, UINT, WPARAM, LPARAM);

VOID   DrawThumb2(PWND, PSBCALC, HDC, HBRUSH, BOOL, UINT);
UINT   GetWndSBDisableFlags(PWND, BOOL);

HANDLE _ConvertMemHandle(LPBYTE lpData, UINT cbData);

VOID zzzRegisterSystemThread (DWORD flags, DWORD reserved);

VOID zzzUpdateCursorImage();
void zzzCalcStartCursorHide(PW32PROCESS Process, DWORD timeAdd);
BOOL FinalUserInit();
BOOL LW_RegisterWindows(BOOL fSystem);

BOOL xxxSystemParametersInfo(UINT wFlag, DWORD wParam, LPVOID lParam, UINT flags);

PWINDOWSTATION CheckClipboardAccess(void);
PCLIP FindClipFormat(PWINDOWSTATION pwinsta, UINT format);
BOOL InternalSetClipboardData(PWINDOWSTATION pwinsta, UINT format,
        HANDLE hData, BOOL fGlobalHandle, BOOL fIncSerialNumber);
VOID DisownClipboard(PWND pwndClipOwner);

VOID CaretBlinkProc(PWND pwnd, UINT message, UINT_PTR id, LPARAM lParam);
VOID xxxRedrawFrame(PWND pwnd);
VOID xxxRedrawFrameAndHook(PWND pwnd);
VOID BltColor(HDC, HBRUSH, HDC, int, int, int, int, int, int, UINT);
VOID StoreMessage(LPMSG pmsg, PWND pwnd, UINT message, WPARAM wParam,
        LPARAM lParam, DWORD time);
VOID StoreQMessage(PQMSG pqmsg, PWND pwnd, UINT message, WPARAM wParam,
        LPARAM lParam, DWORD time, DWORD dwQEvent, ULONG_PTR dwExtraInfo);

#ifdef REDIRECTION
__inline VOID StoreQMessagePti(
    PQMSG pqmsg,
    PTHREADINFO pti)
{
    if (pqmsg->msg.message >= WM_MOUSEFIRST && pqmsg->msg.message <= WM_MOUSELAST) {
        pqmsg->msg.pt.x = LOWORD(pqmsg->msg.lParam);
        pqmsg->msg.pt.y = HIWORD(pqmsg->msg.lParam);
    } else {
        if (pti != NULL)
            pqmsg->msg.pt = pti->ptLast;
    }
    pqmsg->pti = pti;
}
#else
__inline VOID StoreQMessagePti(
    PQMSG pqmsg,
    PTHREADINFO pti)
{
    pqmsg->pti = pti;
}
#endif // REDIRECTION

VOID xxxSendSizeMessage(PWND pwnd, UINT cmdSize);

VOID xxxCheckFocus(PWND pwnd);
VOID OffsetChildren(PWND pwnd, int dx, int dy, LPRECT prcHitTest);

VOID xxxMoveSize(PWND pwnd, UINT cmdMove, DWORD wptStart);
VOID xxxShowOwnedWindows(PWND pwndOwner, UINT cmdShow, HRGN hrgnHung);
VOID xxxAdjustSize(PWND pwnd, LPINT lpcx, LPINT lpcy);

VOID xxxNextWindow(PQ pq, DWORD wParam);
VOID xxxOldNextWindow(UINT flags);
VOID xxxCancelCoolSwitch(void);

VOID xxxCancelTracking(VOID);
VOID xxxCancelTrackingForThread(PTHREADINFO ptiCancel);
VOID xxxCapture(PTHREADINFO pti, PWND pwnd, UINT code);
UINT SystoChar(UINT message, LPARAM lParam);

PHOOK PhkFirstValid(PTHREADINFO pti, int nFilterType);
PHOOK PhkFirstGlobalValid(PTHREADINFO pti, int nFilterType);
VOID  FreeHook(PHOOK phk);
int   xxxCallHook(int, WPARAM, LPARAM, int);
LRESULT xxxCallHook2(PHOOK, int, WPARAM, LPARAM, LPBOOL);
BOOL  xxxCallMouseHook(UINT message, PMOUSEHOOKSTRUCTEX pmhs, BOOL fRemove);
VOID  xxxCallJournalRecordHook(PQMSG pqmsg);
DWORD xxxCallJournalPlaybackHook(PQMSG pqmsg);
VOID  SetJournalTimer(DWORD dt, UINT msgJournal);
VOID  FreeThreadsWindowHooks(VOID);

BOOL xxxSnapWindow(PWND pwnd);

BOOL    DefSetText(PWND pwnd, PLARGE_STRING pstrText);
PWND    DSW_GetTopLevelCreatorWindow(PWND pwnd);
VOID    xxxCalcClientRect(PWND pwnd, LPRECT lprc, BOOL fHungRedraw);
VOID    xxxUpdateClientRect(PWND pwnd);

BOOL   AllocateUnicodeString(PUNICODE_STRING pstrDst, PUNICODE_STRING pstrSrc);

HANDLE CreateDesktopHeap(PWIN32HEAP* ppheapRet, ULONG ulHeapSize);

BOOL xxxSetInternalWindowPos(PWND pwnd, UINT cmdShow, LPRECT lprcWin,
            LPPOINT lpptMin);
VOID xxxMetricsRecalc(UINT wFlags, int dx, int dy, int dyCaption, int dyMenu);

VOID xxxBroadcastDisplaySettingsChange(PDESKTOP, BOOL);


/*
 * This is for SPI_GET/SETUSERPREFERENCE.
 * Currently it's for DWORD values only. A type field will be added so all new
 * settings will be mostly handled through common SystemParametersInfo code.
 */
typedef struct tagPROFILEVALUEINFO {
    DWORD       dwValue;
    UINT        uSection;
    LPCWSTR     pwszKeyName;
} PROFILEVALUEINFO, *PPROFILEVALUEINFO;

/*
 *  SystemParametersInfo UserPreferences manipulation macros.
 *  SPI_ values in the BOOL or DWORD ranges (see winuser.w) are stored in
 *   gpdwCPUserPreferencesMask (BOOL) and gpviCPUserPreferences (DOWRD) (see kernel\globals.c).
 *  The following macros use the actual SPI_ value to determine the
 *   location of a given bit (BOOL mask) or DWORD in those  globals.
 *
 *  Macros to access DWORDs stored in gpviCPUserPreferences.
 *
 */
#define UPIsDWORDRange(uSetting)    \
            ((uSetting) >= SPI_STARTDWORDRANGE && (uSetting) < SPI_MAXDWORDRANGE)

/*
 * The first entry in gpviCPUserPreferences is reserved for the bitmask, so add 1.
 * Each setting has SPI_GET and SPI_SET, so divide by 2 to get the index
 */
#define UPDWORDIndex(uSetting)    \
            (1 + (((uSetting) - SPI_STARTDWORDRANGE) / 2))

/*
 * Macros to access BOOLs stored in gpdwCPUserPreferencesMask.
 */
#define UPIsBOOLRange(uSetting) \
    ((uSetting) >= SPI_STARTBOOLRANGE && (uSetting) < SPI_MAXBOOLRANGE)

/*
 * Each setting has SPI_GET and SPI_SET, so divide by 2 to get the index
 */
#define UPBOOLIndex(uSetting) \
    (((uSetting) - SPI_STARTBOOLRANGE) / 2)

/*
 * Returns a pointer to the DWORD that contains the bit corresponding to uSetting
 */
#define UPBOOLPointer(pdw, uSetting)    \
    (pdw + (UPBOOLIndex(uSetting) / 32))

/*
 * Returns the DWORD mask needed to test/set/clear the bit corresponding to uSetting
 */
#define UPBOOLMask(uSetting)    \
    (1 << (UPBOOLIndex(uSetting) - ((UPBOOLIndex(uSetting) / 32) * 32)))

#define TestUPBOOL(pdw, uSetting)   \
    (*UPBOOLPointer(pdw, uSetting) & UPBOOLMask(uSetting))

#define SetUPBOOL(pdw, uSetting)    \
    (*UPBOOLPointer(pdw, uSetting) |= UPBOOLMask(uSetting))

#define ClearUPBOOL(pdw, uSetting)                              \
{                                                               \
    UserAssert(UPIsBOOLRange(uSetting));                        \
    *UPBOOLPointer(pdw, uSetting) &= ~UPBOOLMask(uSetting);     \
}

/*
 * Use these macros ONLY if UPIsBOOLRange(SPI_GET ## uSetting) is TRUE
 */
#define TestUP(uSetting)    TestUPBOOL(gpdwCPUserPreferencesMask, SPI_GET ## uSetting)
#define SetUP(uSetting)     SetUPBOOL(gpdwCPUserPreferencesMask, SPI_GET ## uSetting)
#define ClearUP(uSetting)   ClearUPBOOL(gpdwCPUserPreferencesMask, SPI_GET ## uSetting)

#define IndexUP(uSetting) \
    (1 << (((uSetting) - SPI_STARTBOOLRANGE) / 2))

/*
 * Some settings (ie, UI Effects) are disabled when TestUP(UISETTINGS) is FALSE.
 */
#define TestEffectUP(uSetting)                                          \
    ((*gpdwCPUserPreferencesMask &                                      \
     (IndexUP(SPI_GET ## uSetting) | IndexUP(SPI_GETUIEFFECTS))) ==     \
     (IndexUP(SPI_GET ## uSetting) | IndexUP(SPI_GETUIEFFECTS)))

/*
 * Some UI effects have an "inverted" disabled value (ie, disabled is TRUE).
 */
#define TestEffectInvertUP(uSetting) (TestUP(uSetting) || !TestUP(UIEFFECTS))

/*
 * Some of these BOOL values are needed in the client side. This macro
 * propagates them to gpsi->PUSIFlags. Note that the SI_ value must match the
 * UPBOOLMask value for this to work fine.
 */
#define PropagetUPBOOLTogpsi(uSetting) \
    UserAssert((DWORD)(PUSIF_ ## uSetting) == (DWORD)UPBOOLMask(SPI_GET ## uSetting)); \
    COPY_FLAG(gpsi->PUSIFlags, TestUP(## uSetting), PUSIF_ ## uSetting)



/*
 * Test if a TS session is connected remotly or locally through the console
 * terminal.
 */
#define IsRemoteConnection() (gProtocolType != PROTOCOL_CONSOLE)
#define IsMultimon()  ((gpDispInfo != NULL)  && (gpDispInfo->cMonitors > 1))
#define GETCONSOLEHDEV() (gfRemotingConsole?gConsoleShadowhDev:gpDispInfo->hDev)

#ifdef IMM_PER_LOGON
BOOL UpdatePerUserImmEnabling(VOID);
#endif
BOOL xxxUpdatePerUserSystemParameters(DWORD dwFlags);
VOID SaveVolatileUserSettings(VOID);

VOID MenuRecalc(VOID);

#define UNDERLINE_RECALC    0x7FFFFFFF      // MAXINT; tells us to recalc underline position


/*
 * Library management routines.
 */
int GetHmodTableIndex(PUNICODE_STRING pstrName);
VOID AddHmodDependency(int iatom);
VOID RemoveHmodDependency(int iatom);
HANDLE xxxLoadHmodIndex(int iatom);
VOID xxxDoSysExpunge(PTHREADINFO pti);


VOID DestroyThreadsObjects(VOID);
VOID MarkThreadsObjects(PTHREADINFO pti);

VOID FreeMessageList(PMLIST pml);
VOID DestroyThreadsHotKeys(VOID);
VOID DestroyWindowsHotKeys(PWND pwnd);

VOID DestroyClass(PPCLS ppcls);
VOID PatchThreadWindows(PTHREADINFO);
VOID DestroyCacheDCEntries(PTHREADINFO);

VOID DestroyProcessesClasses(PPROCESSINFO);

/*
 *  Win16 Task Apis Taskman.c
 */

VOID InsertTask(PPROCESSINFO ppi, PTDB ptdbNew);

BOOL xxxSleepTask(BOOL fInputIdle, HANDLE);

BOOL xxxUserYield(PTHREADINFO pti);
VOID xxxDirectedYield(DWORD dwThreadId);
VOID DirectedScheduleTask(PTHREADINFO ptiOld, PTHREADINFO ptiNew, BOOL bSendMsg, PSMS psms);
VOID WakeWowTask(PTHREADINFO Pti);

/*
 *  WowScheduler assertion for multiple wow tasks running simultaneously
 */

_inline
VOID
EnterWowCritSect(
    PTHREADINFO pti,
    PWOWPROCESSINFO pwpi
)
{
   if (!++pwpi->CSLockCount) {
       pwpi->CSOwningThread = pti;
   } else {
       RIPMSG2(RIP_ERROR,
              "MultipleWowTasks running simultaneously %x %x\n",
              pwpi->CSOwningThread,
              pwpi->CSLockCount);
   }
}

_inline
VOID
ExitWowCritSect(
    PTHREADINFO pti,
    PWOWPROCESSINFO pwpi
)
{
   if (pti == pwpi->CSOwningThread) {
       pwpi->CSOwningThread = NULL;
       pwpi->CSLockCount--;
   }
}


////////////////////////////////////////////////////////////////////////////
//
// These are internal USER functions called from inside and outside the
// critical section (from server & client side). They are a private 'API'.
//
// The prototypes appear in pairs:
//    as called from outside the critsect (from client-side)
//    as called from inside the critsect (from server-side)
// there must be layer code for the 1st function of each pair which validates
// handles, enters the critsect, calls the 2nd of the pair of functions, and
// leaves the critsect again.
//
// Things may have to change when we go client server: InitPwSB() mustn't
// return a pointer to global (server) data! etc.
//
////////////////////////////////////////////////////////////////////////////

BOOL  xxxFillWindow(PWND pwndBrush, PWND pwndPaint, HDC hdc, HBRUSH hbr);
HBRUSH xxxGetControlBrush(PWND pwnd, HDC hdc, UINT msg);
HBRUSH xxxGetControlColor(PWND pwndParent, PWND pwndCtl, HDC hdc, UINT message);
PSBINFO  _InitPwSB(PWND);
BOOL  _KillSystemTimer(PWND pwnd, UINT_PTR nIDEvent);
BOOL  xxxPaintRect(PWND, PWND, HDC, HBRUSH, LPRECT);

////////////////////////////////////////////////////////////////////////////
//
// these are called from stubs.c in the client so will probably go away
//
////////////////////////////////////////////////////////////////////////////


/*
 * From CLASS.C
 */

typedef struct tagWNDCLASSVEREX {
    WNDCLASSEXW;
    LPCWSTR     lpszClassNameVer;
} WNDCLASSVEREX, *LPWNDCLASSVEREX;


PCLS InternalRegisterClassEx(
        LPWNDCLASSVEREX lpwndcls,
        WORD fnid,
        DWORD flags
        );

PCURSOR GetClassIcoCur(PWND pwnd, int index);
PCURSOR xxxSetClassIcon(PWND pwnd, PCLS pcls, PCURSOR pCursor, int gcw);
ULONG_PTR xxxSetClassData(PWND pwnd, int index, ULONG_PTR dwData, BOOL bAnsi);
ULONG_PTR SetClassCursor(PWND pwnd, PCLS pcls, DWORD index, ULONG_PTR dwData);

/*
 * CREATEW.C
 */

#define xxxNVCreateWindowEx(dwStyle, pstrClass, pstrName, style,        \
        x, y, cx, cy, pwndParent, pmenu, hModule, pCreateParams,        \
        dwExpWinVerAndFlags)                                            \
        xxxCreateWindowEx(dwStyle, pstrClass, pstrClass, pstrName,      \
        style, x, y, cx, cy, pwndParent, pmenu, hModule, pCreateParams, \
        dwExpWinVerAndFlags, NULL)

PWND xxxCreateWindowEx(DWORD dwStyle, PLARGE_STRING pstrNVClass, PLARGE_STRING pstrClass,
        PLARGE_STRING pstrName, DWORD style, int x, int y, int cx,
        int cy, PWND pwndParent, PMENU pmenu, HANDLE hModule,
        LPVOID pCreateParams, DWORD dwExpWinVerAndFlags, PACTIVATION_CONTEXT pActCtx);
BOOL xxxDestroyWindow(PWND pwnd);

/*
 * SENDMSG.C
 */
LRESULT xxxSendMessageFF(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR xParam);
LONG xxxSendMessageBSM(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam,
        LPBROADCASTSYSTEMMSGPARAMS pbsmParams);
LRESULT xxxSendMessageEx(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR xParam);
LRESULT xxxSendMessage(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT xxxSendMessageTimeout(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam,
        UINT fuFlags, UINT uTimeout, PLONG_PTR lpdwResult);
BOOL xxxSendNotifyMessage(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);
void QueueNotifyMessage(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL xxxSendMessageCallback(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam,
        SENDASYNCPROC lpResultCallBack, ULONG_PTR dwData, BOOL bClientReqest );
BOOL _ReplyMessage(LRESULT lRet);

/*
 * MN*.C
 */
int xxxTranslateAccelerator(PWND pwnd, LPACCELTABLE pat, LPMSG lpMsg);
BOOL  xxxSetMenu(PWND pwnd, PMENU pmenu, BOOL fRedraw);
VOID  ChangeMenuOwner(PMENU pMenu, PPROCESSINFO ppi);
int   xxxMenuBarDraw(PWND pwnd, HDC hdc, int cxFrame, int cyFrame);
BOOL  xxxDrawMenuBar(PWND pwnd);

UINT xxxPaintMenuBar(PWND pwnd, HDC hdc, int iLeftOffset, int iRightOffset, int iTopOffset, DWORD dwFlags);
UINT xxxCalcMenuBar(PWND pwnd, int iLeftOffset, int iRightOffset, int iTopOffset, LPCRECT prcWnd);

BOOL xxxSetMenuItemInfo(PMENU pMenu, UINT nPos, BOOL fByPosition,
    LPMENUITEMINFOW lpmii, PUNICODE_STRING pstrItem);
BOOL _SetMenuContextHelpId(PMENU pMenu, DWORD dwContextHelpId);
BOOL _SetMenuFlagRtoL(PMENU pMenu);
BOOL xxxInsertMenuItem(PMENU pMenu, UINT wIndex, BOOL fByPosition,
        LPMENUITEMINFOW lpmii, PUNICODE_STRING pstrItem);
BOOL  xxxRemoveMenu(PMENU pMenu, UINT nPos, UINT dwFlags);
BOOL  xxxDeleteMenu(PMENU pMenu, UINT nPos, UINT dwFlags);
BOOL  xxxSetMenuInfo(PMENU pMenu, LPCMENUINFO lpmi);
BOOL  xxxTrackPopupMenuEx(PMENU pmenu, UINT dwFlags, int x, int y,
        PWND pwnd, CONST TPMPARAMS *pparams);
LONG FindBestPos(int x, int y, int cx, int cy, LPRECT prcExclude,
                UINT wFlags, PPOPUPMENU ppopupmenu, PMONITOR pMonitor);
BOOL _SetMenuDefaultItem(PMENU pMenu, UINT wId, BOOL fByPosition);
int xxxMenuItemFromPoint(PWND pwnd, PMENU pMenu, POINT ptScreen);
BOOL xxxGetMenuItemRect(PWND pwnd, PMENU pMenu, UINT uIndex, LPRECT lprcScreen);
PPOPUPMENU MNGetPopupFromMenu(PMENU pMenu, PMENUSTATE *ppMenuState);
PVOID LockDesktopMenu(PMENU * ppmenu, PMENU pmenu);
PVOID UnlockDesktopMenu(PMENU * ppmenu);
#ifdef LAME_BUTTON
PMENU xxxLoadSysDesktopMenu (PMENU * ppmenu, UINT uMenuId, PWND pwnd);
#else
PMENU xxxLoadSysDesktopMenu (PMENU * ppmenu, UINT uMenuId);
#endif // LAME_BUTTON
__inline PVOID UnlockDesktopSysMenu(
    PMENU * ppmenu)
{
    ClearMF(*ppmenu, MFSYSMENU);
    return UnlockDesktopMenu(ppmenu);
}

/*
 * SHOWWIN.C
 */
BOOL xxxShowWindow(PWND pwnd, DWORD cmdShowAnimate);
BOOL _ShowWindowAsync(PWND pwnd, int cmdShow, UINT uWPFlags);
BOOL xxxShowOwnedPopups(PWND pwndOwner, BOOL fShow);

#define RDW_HASWINDOWRGN        0x8000
BOOL xxxSetWindowRgn(PWND pwnd, HRGN hrgn, BOOL fRedraw);

/*
 * SWP.C
 */
void SelectWindowRgn(PWND pwnd, HRGN hrgnClip);
PWND GetTopMostInsertAfter (PWND pwnd);

#define GETTOPMOSTINSERTAFTER(pwnd) \
    (gHardErrorHandler.pti == NULL ? NULL : GetTopMostInsertAfter(pwnd))

__inline BOOL FSwpTopmost(
   PWND pwnd)
{
    return (!!TestWF(pwnd, WEFTOPMOST) ^ !!TestWF(pwnd, WFTOGGLETOPMOST));
}


PWND CalcForegroundInsertAfter(PWND pwnd);
BOOL xxxSetWindowPos(PWND pwnd, PWND pwndInsertAfter, int x, int y,
        int cx, int cy, UINT flags);
PSMWP InternalBeginDeferWindowPos(int cwndGuess);
BOOL AllocateCvr (PSMWP psmwp, int cwndHint);
PSMWP _BeginDeferWindowPos(int cwndGuess);
PSMWP _DeferWindowPos(PSMWP psmwp, PWND pwnd, PWND pwndInsertAfter,
        int x, int y, int cx, int cy, UINT rgf);
BOOL xxxEndDeferWindowPosEx(PSMWP psmwp, BOOL fAsync);
BOOL xxxMoveWindow(PWND pwnd, int x, int y, int cx, int cy, BOOL fRedraw);
PWND GetLastTopMostWindow(VOID);
VOID xxxHandleWindowPosChanged(PWND pwnd, PWINDOWPOS ppos);
VOID IncVisWindows(PWND pwnd);
VOID DecVisWindows(PWND pwnd);
BOOL FVisCountable(PWND pwnd);
VOID SetVisible(PWND pwnd, UINT flags);
VOID ClrFTrueVis(PWND pwnd);

VOID SetWindowState(PWND pwnd, DWORD flags);
VOID ClearWindowState(PWND pwnd, DWORD flags);

BOOL xxxUpdateWindows(PWND pwnd, HRGN hrgn);

VOID SetMinimize(PWND pwnd, UINT uFlags);
#define SMIN_CLEAR            0
#define SMIN_SET              1

PWND NextOwnedWindow(PWND pwnd, PWND pwndOwner, PWND pwndParent);

/*
 * DWP.C
 */
LRESULT xxxDefWindowProc(PWND, UINT, WPARAM, LPARAM);
LRESULT xxxRealDefWindowProc(PWND, UINT, WPARAM, LPARAM);
PWND DWP_GetEnabledPopup(PWND pwndStart);


/*
 * INPUT.C
 */
#ifdef MESSAGE_PUMP_HOOK

BOOL xxxWaitMessageEx(UINT fsWakeMask, DWORD Timeout);
__inline BOOL xxxWaitMessage(
    VOID)
{
    return xxxWaitMessageEx(QS_ALLINPUT | QS_EVENT, 0);
}
BOOL xxxRealWaitMessageEx(UINT fsWakeMask, DWORD Timeout);

#else

BOOL xxxWaitMessage(VOID);

#endif

VOID DBGValidateQueueStates(PDESKTOP pdesk);
VOID IdleTimerProc(VOID);
VOID zzzWakeInputIdle(PTHREADINFO pti);
VOID SleepInputIdle(PTHREADINFO pti);
BOOL xxxInternalGetMessage(LPMSG lpmsg, HWND hwnd, UINT wMsgFilterMin,
        UINT wMsgFilterMax, UINT wRemoveMsg, BOOL fGetMessage);

#ifdef MESSAGE_PUMP_HOOK
BOOL xxxRealInternalGetMessage(LPMSG lpMsg, HWND hwndFilter, UINT msgMin,
        UINT msgMax, UINT flags, BOOL fGetMessage);
#endif

#define xxxPeekMessage(lpmsg, hwnd, wMsgMin, wMsgMax, wRemoveMsg) \
    xxxInternalGetMessage(lpmsg, hwnd, wMsgMin, wMsgMax, wRemoveMsg, FALSE)
#define xxxGetMessage(lpmsg, hwnd, wMsgMin, wMsgMax) \
    xxxInternalGetMessage(lpmsg, hwnd, wMsgMin, wMsgMax, PM_REMOVE, TRUE)
DWORD _GetMessagePos(VOID);
LRESULT xxxDispatchMessage(LPMSG lpmsg);
UINT GetMouseKeyFlags(PQ pq);
BOOL _PostMessage(PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL IPostQuitMessage(PTHREADINFO pti, int nExitCode);
BOOL _PostQuitMessage(int nExitCode);
BOOL _PostThreadMessage(PTHREADINFO pti, UINT message, WPARAM wParam, LPARAM lParam);
BOOL xxxTranslateMessage(LPMSG pmsg, UINT flags);
BOOL _GetInputState(VOID);
DWORD _GetQueueStatus(UINT);
typedef VOID (CALLBACK* MSGWAITCALLBACK)(DWORD DeviceType);
DWORD xxxMsgWaitForMultipleObjects(DWORD nCount, PVOID *apObjects, MSGWAITCALLBACK pfnNonMsg, PKWAIT_BLOCK WaitBlockArray);

BOOL FHungApp(PTHREADINFO pti, DWORD dwTimeFromLastRead);
VOID xxxRedrawHungWindow(PWND pwnd, HRGN hrgnFullDrag);
VOID xxxRedrawHungWindowFrame(PWND pwnd, BOOL fActive);
VOID zzzActiveCursorTracking (PWND pwnd);
PWND GetActiveTrackPwnd(PWND pwnd, Q **ppq);
int xxxActiveWindowTracking(PWND pwnd, UINT uMsg, int iHitTest);
VOID xxxHungAppDemon(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam);

/*
 * shadow.c
 */
BOOL WindowHasShadow(PWND pwnd);
BOOL xxxAddShadow(PWND pwnd);
VOID xxxRemoveShadow(PWND pwnd);
VOID CleanupShadow(PWND pwndShadow);
VOID MoveShadow(PWND pwnd);
VOID UpdateShadowShape(PWND pwnd);
VOID xxxUpdateShadowZorder(PWND pwnd);
BOOL FAnyShadows(VOID);

/*
 * QUEUE.C
 */
__inline BOOL IsShellProcess(
    PPROCESSINFO ppi)
{
    return ((ppi->rpdeskStartup != NULL)
        && (ppi->rpdeskStartup->pDeskInfo->ppiShellProcess == ppi));
}

__inline DWORD GetAppCompatFlags2ForPti(
    PTHREADINFO pti,
    WORD wVer)
{
    if (wVer < pti->dwExpWinVer) {
        return 0;
    }

    return pti->dwCompatFlags2;
}

VOID ClearWakeMask(VOID);
VOID _AllowForegroundActivation(VOID);

ULONG GetTaskName(PTHREADINFO pti, PWSTR Buffer, ULONG BufferLength);
PQMSG FindQMsg(PTHREADINFO pti, PMLIST pml, PWND pwndFilter, UINT msgMin, UINT msgMax, BOOL bProcessAck);
VOID zzzShowStartGlass(DWORD dwTimeout);
DWORD _GetChangeBits(VOID);
NTSTATUS xxxSetCsrssThreadDesktop(PDESKTOP pdesk, PDESKRESTOREDATA pdrdRestore);
NTSTATUS xxxRestoreCsrssThreadDesktop(PDESKRESTOREDATA pdrdRestore);

PQ GetJournallingQueue(PTHREADINFO pti);
VOID ClearAppStarting (PPROCESSINFO ppi);
BOOL _GetProcessDefaultLayout(DWORD *pdwDefaultLayout);
BOOL _SetProcessDefaultLayout(DWORD dwDefaultLayout);


#ifdef HUNGAPP_GHOSTING

/*
 * GHOST.C
 */
VOID _DisableProcessWindowsGhosting(VOID);
LRESULT xxxGhostWndProc(PWND, UINT, WPARAM, LPARAM);
VOID SignalGhost(PWND pwnd);
BOOL xxxCreateGhost(PWND pwnd);
VOID RemoveGhost(PWND pwnd);
PWND FindGhost(PWND pwnd);
BOOL GhostSizedOrMoved(PWND pwnd);


#define WM_HUNGTHREAD (WM_USER + 0)
#define WM_CREATETRAILTIMER (WM_USER + 1)
#define WM_SCANGHOST (WM_USER + 2)

VOID    GhostThread(PDESKTOP pdesk);

__inline VOID SignalGhost(
    PWND pwnd)
{
    /*
     * No ghosting for applications that are debugged, since it can
     * make debugging confusing to developers.
     */
    if (TestWF(pwnd, WFMINIMIZED) ||
        (GETPTI(pwnd)->ppi->fDisableWindowsGhosting) ||
        (PsGetProcessDebugPort(GETPTI(pwnd)->ppi->Process) != NULL) ||
        (GetAppCompatFlags2ForPti(GETPTI(pwnd), VERMAX) & GACF2_NOGHOST)) {
        return;
    }

    _PostMessage(PWNDDESKTOP(pwnd), WM_HUNGTHREAD, 0, (LPARAM)HWq(pwnd));
}

#endif // HUNGAPP_GHOSTING

/*
 * TMSWITCH.C
 */
VOID xxxSwitchToThisWindow(PWND pwnd, BOOL fAltTab);

/*
 * TOUNICOD.C
 */
int xxxToUnicodeEx(UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState,
      LPWSTR pwszBuff, int cchBuff, UINT wFlags, HKL hkl);
int xxxInternalToUnicode(UINT wVirtKey, UINT wScanCode, CONST IN PBYTE pfvk,
      OUT PWCHAR awchChars, INT cChar, UINT uiTMFlags, OUT PDWORD pdwFlags, HKL hkl);

/*
 * HOTKEYS.C
 */
BOOL _RegisterHotKey(PWND pwnd, int id, UINT fsModifiers, UINT vk);
BOOL _UnregisterHotKey(PWND pwnd, int id);

/*
 * FOCUSACT.C
 */
PWND xxxSetFocus(PWND pwnd);
#ifdef FG_HOOKLOCK
#define FG_HOOKLOCK_PARAM(x)    , x
#else
#define FG_HOOKLOCK_PARAM(x)
#endif
BOOL CanForceForeground(PPROCESSINFO ppi FG_HOOKLOCK_PARAM(PTHREADINFO pti));
BOOL xxxStubSetForegroundWindow(PWND pwnd);
BOOL xxxSetForegroundWindow(PWND pwnd, BOOL fFlash);
PWND xxxSetActiveWindow(PWND pwnd);
PWND _GetActiveWindow(VOID);
BOOL xxxAllowSetForegroundWindow(DWORD dwProcessId);
BOOL _LockSetForegroundWindow(UINT uLockCode);

/*
 * UPDATE.C
 */
BOOL xxxInvalidateRect(PWND pwnd, LPRECT lprc, BOOL fErase);
BOOL xxxValidateRect(PWND pwnd, LPRECT lprc);
BOOL xxxInvalidateRgn(PWND pwnd, HRGN hrgn, BOOL fErase);
BOOL xxxValidateRgn(PWND pwnd, HRGN hrgn);
BOOL xxxUpdateWindow(PWND pwnd);
BOOL xxxGetUpdateRect(PWND pwnd, LPRECT lprc, BOOL fErase);
int  xxxGetUpdateRgn(PWND pwnd, HRGN hrgn, BOOL fErase);
int  _ExcludeUpdateRgn(HDC hdc, PWND pwnd);
int  CalcWindowRgn(PWND pwnd, HRGN hrgn, BOOL fClient);
VOID DeleteUpdateRgn(PWND pwnd);
BOOL xxxRedrawWindow(PWND pwnd, LPRECT lprcUpdate, HRGN hrgnUpdate, DWORD flags);
BOOL IntersectWithParents(PWND pwnd, LPRECT lprc);
VOID xxxInternalInvalidate(PWND pwnd, HRGN hrgnUpdate, DWORD flags);

/*
 * WINMGR.C
 */
BOOL xxxEnableWindow(PWND pwnd, BOOL fEnable);
int xxxGetWindowText(PWND pwnd, LPWSTR psz, int cchMax);
PWND xxxSetParent(PWND pwnd, PWND pwndNewParent);
BOOL xxxFlashWindow(PWND pwnd, DWORD dwFlags, DWORD dwTimeout);
extern ATOM gaFlashWState;
__inline DWORD GetFlashWindowState(
    PWND pwnd)
{
    return HandleToUlong(_GetProp(pwnd, MAKEINTATOM(gaFlashWState), PROPF_INTERNAL));
}

__inline VOID SetFlashWindowState(
    PWND pwnd,
    DWORD dwState)
{
    InternalSetProp(pwnd, MAKEINTATOM(gaFlashWState),
                    (HANDLE)ULongToPtr(dwState), PROPF_INTERNAL | PROPF_NOPOOL);
}
__inline VOID RemoveFlashWindowState(
    PWND pwnd)
{
    InternalRemoveProp(pwnd, MAKEINTATOM(gaFlashWState), PROPF_INTERNAL);
}
BOOL _GetWindowPlacement(PWND pwnd, PWINDOWPLACEMENT pwp);
BOOL xxxSetWindowPlacement(PWND pwnd, PWINDOWPLACEMENT pwp);
BOOL ValidateParentDepth(PWND pwnd, PWND pwndParent);
BOOL ValidateOwnerDepth(PWND pwnd, PWND pwndOwner);
VOID WPUpdateCheckPointSettings (PWND pwnd, UINT uWPFlags);

/*
 * DC.C
 */
HDC  _GetDC(PWND pwnd);
HDC  _GetDCEx(PWND pwnd, HRGN hrgnClip, DWORD flags);
HDC  _GetWindowDC(PWND pwnd);
BOOL _ReleaseDC(HDC hdc);
UINT ReleaseCacheDC(HDC hdc, BOOL fEndPaint);
HDC  CreateCacheDC(PWND, DWORD, PMONITOR);
BOOL DestroyCacheDC(PDCE *, HDC);
VOID InvalidateDce(PDCE pdce);
VOID DeleteHrgnClip(PDCE pdce);
PWND WindowFromCacheDC(HDC hdc);
PWND FastWindowFromDC(HDC hdc);
VOID DelayedDestroyCacheDC(VOID);
PDCE LookupDC(HDC hdc);
HDC GetMonitorDC(PDCE pdceOrig, PMONITOR pMonitor);
BOOL GetDCOrgOnScreen(HDC hdc, LPPOINT ppt);
__inline VOID MarkDCEInvalid(
    PDCE pdce)
{
    /*
     * Clear all bits, but these.
     */
    pdce->DCX_flags &= (DCX_CACHE | DCX_REDIRECTED);

    /*
     * Mark this cache entry as invalid
     */
    pdce->DCX_flags |= DCX_INVALID;
}

BOOL MirrorRegion(PWND pwnd, HRGN hrgn, BOOL bUseClient);

/*
 * PAINT.C
 */
HDC  xxxBeginPaint(PWND pwnd, PAINTSTRUCT *lpps);
BOOL xxxEndPaint(PWND pwnd, PAINTSTRUCT *lpps);

/*
 * CAPTURE.C
 */
PWND xxxSetCapture(PWND pwnd);
BOOL xxxReleaseCapture(VOID);

/*
 * KEYBOARD.C
 */
SHORT _GetAsyncKeyState(int vk);
BOOL _SetKeyboardState(CONST BYTE *pKeyboard);
int _GetKeyboardType(int nTypeFlag);
VOID RegisterPerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName);
VOID UpdatePerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName);
VOID UpdatePerUserKeyboardMappings(PUNICODE_STRING pProfileUserName);

#define TestRawKeyDown(vk)     TestKeyDownBit(gafRawKeyState, vk)
#define SetRawKeyDown(vk)      SetKeyDownBit(gafRawKeyState, vk)
#define ClearRawKeyDown(vk)    ClearKeyDownBit(gafRawKeyState, vk)
#define TestRawKeyToggle(vk)   TestKeyToggleBit(gafRawKeyState, vk)
#define SetRawKeyToggle(vk)    SetKeyToggleBit(gafRawKeyState, vk)
#define ClearRawKeyToggle(vk)  ClearKeyToggleBit(gafRawKeyState, vk)
#define ToggleRawKeyToggle(vk) ToggleKeyToggleBit(gafRawKeyState, vk)

/*
 * XLATE.C
 */
int  _GetKeyNameText(LONG lParam, LPWSTR lpString, int nSize);

/*
 * TIMERS.C
 */
BOOL _KillTimer(PWND pwnd, UINT_PTR nIDEvent);
PTIMER FindTimer(PWND pwnd, UINT_PTR nID, UINT flags, BOOL fKill);
VOID xxxSystemTimerProc(PWND pwnd, UINT msg, UINT_PTR id, LPARAM lParam);


/*
 * CARET.C
 */
BOOL zzzDestroyCaret(VOID);
BOOL xxxCreateCaret(PWND, HBITMAP, int, int);
BOOL zzzShowCaret(PWND);
BOOL zzzHideCaret(PWND);
BOOL _SetCaretBlinkTime(UINT);
BOOL zzzSetCaretPos(int, int);

/*
 * MSGBEEP.C
 */
BOOL xxxOldMessageBeep(VOID);
BOOL xxxMessageBeep(UINT wType);
VOID PlayEventSound(UINT idSound);

/*
 * WINWHERE.C
 */
PWND _ChildWindowFromPointEx(PWND pwndParent, POINT pt, UINT i);
PWND xxxWindowFromPoint(POINT pt);
PWND SizeBoxHwnd(PWND pwnd);

/*
 * GETSET.C
 */
WORD  _SetWindowWord(PWND pwnd, int index, WORD value);
DWORD xxxSetWindowLong(PWND pwnd, int index, DWORD value, BOOL bAnsi);
#ifdef _WIN64
ULONG_PTR xxxSetWindowLongPtr(PWND pwnd, int index, ULONG_PTR value, BOOL bAnsi);
#else
#define xxxSetWindowLongPtr xxxSetWindowLong
#endif
#define __GetWindowLong(pwnd, index) ((LONG)(*(DWORD UNALIGNED *)((BYTE *)((pwnd) + 1) + (index))))
#define __GetWindowLongPtr(pwnd, index) ((LONG_PTR)(*(ULONG_PTR UNALIGNED *)((BYTE *)((pwnd) + 1) + (index))))
#if DBG
ULONG DBGGetWindowLong(PWND pwnd, int index);
#define _GetWindowLong DBGGetWindowLong
ULONG_PTR DBGGetWindowLongPtr(PWND pwnd, int index);
#define _GetWindowLongPtr DBGGetWindowLongPtr
#else
#define _GetWindowLong __GetWindowLong
#define _GetWindowLongPtr __GetWindowLongPtr
#endif

/*
 * CLIPBRD.C
 */
BOOL xxxOpenClipboard(PWND pwnd, LPBOOL lpfEmptyClient);
BOOL xxxCloseClipboard(PWINDOWSTATION pwinsta);
UINT _EnumClipboardFormats(UINT fmt);
BOOL xxxEmptyClipboard(PWINDOWSTATION pwinsta);
HANDLE xxxGetClipboardData(PWINDOWSTATION pwinsta, UINT fmt, PGETCLIPBDATA gcd);
BOOL _IsClipboardFormatAvailable(UINT fmt);
int _GetPriorityClipboardFormat(UINT *lpPriorityList, int cfmts);
PWND xxxSetClipboardViewer(PWND pwndClipViewerNew);
BOOL xxxChangeClipboardChain(PWND pwndRemove, PWND pwndNewNext);

/*
 * miscutil.c
 */
VOID SetDialogPointer(PWND pwnd, LONG_PTR lPtr);
VOID ZapActiveAndFocus(VOID);
BOOL xxxSetShellWindow(PWND pwnd, PWND pwndBkGnd);
BOOL _SetProgmanWindow(PWND pwnd);
BOOL _SetTaskmanWindow(PWND pwnd);

#define STW_SAME    ((PWND) 1)
VOID xxxSetTrayWindow(PDESKTOP pdesk, PWND pwnd, PMONITOR pMonitor);
BOOL xxxAddFullScreen(PWND pwnd, PMONITOR pMonitor);
BOOL xxxRemoveFullScreen(PWND pwnd, PMONITOR pMonitor);
BOOL xxxCheckFullScreen(PWND pwnd, PSIZERECT psrc);
BOOL IsTrayWindow(PWND);

#define FDoTray()   (SYSMET(ARRANGE) & ARW_HIDE)
#define FCallHookTray() (IsHooked(PtiCurrent(), WHF_SHELL))
#define FPostTray(p) (p->pDeskInfo->spwndTaskman)
#define FCallTray(p) (FDoTray() && ( FCallHookTray()|| FPostTray(p) ))

// ----------------------------------------------------------------------------
//
//  FTopLevel() - TRUE if window is a top level window
//
//  FHas31TrayStyles() -  TRUE if window is either full screen or has
//                        both a system menu and a caption
//                        (NOTE:  minimized windows always have captions)
//
// ----------------------------------------------------------------------------
#define FTopLevel(pwnd)         (pwnd->spwndParent == PWNDDESKTOP(pwnd))
#define FHas31TrayStyles(pwnd)    (TestWF(pwnd, WFFULLSCREEN) || \
                                  (TestWF(pwnd, WFSYSMENU | WFMINBOX) && \
                                  (TestWF(pwnd, WFCAPTION) || TestWF(pwnd, WFMINIMIZED))))
BOOL IsVSlick(PWND pwnd);
BOOL Is31TrayWindow(PWND pwnd);

/*
 * fullscr.c
 */

#if DBG
#define  VerifyVisibleMonitorCount()    \
    {                                   \
        PMONITOR pMonitor = gpDispInfo->pMonitorFirst;  \
        ULONG cVisMon = 0;                              \
        while (pMonitor) {                              \
            if (pMonitor->dwMONFlags & MONF_VISIBLE) {  \
                cVisMon++;                              \
            }                                           \
            pMonitor = pMonitor->pMonitorNext;          \
        }                                               \
        UserAssert(cVisMon == gpDispInfo->cMonitors);   \
    }
#endif

BOOL xxxMakeWindowForegroundWithState(PWND, BYTE);
void FullScreenCleanup();
LONG xxxUserChangeDisplaySettings(PUNICODE_STRING pstrDeviceName, LPDEVMODEW pDevMode,
    HWND hwnd, PDESKTOP pdesk, DWORD dwFlags, PVOID lParam, MODE PreviousMode);
BOOL xxxbFullscreenSwitch(BOOL bFullscreenSwitch, HWND hwnd);


/*
 * SBAPI.C
 */
BOOL xxxShowScrollBar(PWND, UINT, BOOL);

/*
 * mngray.c
 */
BOOL xxxDrawState(HDC hdcDraw, HBRUSH hbrFore,
        LPARAM lData, int x, int y, int cx, int cy, UINT uFlags);

/*
 * SCROLLW.C
 */
BOOL _ScrollDC(HDC hdc, int dx, int dy, LPRECT prcSrc, LPRECT prcClip,
               HRGN hrgnUpdate, LPRECT prcUpdate);

/*
 * SPB.C
 */
VOID SpbCheckRect(PWND pwnd, LPRECT lprc, DWORD flags);
VOID SpbCheck(VOID);
PSPB FindSpb(PWND pwnd);
VOID FreeSpb(PSPB pspb);
VOID FreeAllSpbs(VOID);
VOID CreateSpb(PWND pwnd, UINT flags, HDC hdcScreen);
UINT RestoreSpb(PWND pwnd, HRGN hrgnUncovered, HDC *phdcScreen);
VOID SpbCheckPwnd(PWND pwnd);
VOID SpbCheckDce(PDCE pdce);
BOOL LockWindowUpdate2(PWND pwndLock, BOOL fThreadOverride);

/*
 * DRAWFRM.C
 */
BOOL BitBltSysBmp(HDC hdc, int x, int y, UINT i);

/*
 * SYSMET.c
 */
BOOL APIENTRY xxxSetSysColors(PUNICODE_STRING pProfileUserName,int count, PUINT pIndex, LPDWORD pClrVal, UINT uOptions);
VOID SetSysColor(UINT icol, DWORD rgb, UINT uOptions);

/*
 * ICONS.C
 */
UINT xxxArrangeIconicWindows(PWND pwnd);
BOOL  _SetSystemMenu(PWND pwnd, PMENU pMenu);

/*
 * RMCREATE.C
 */
PICON _CreateIconIndirect(PICONINFO piconinfo);
PCURSOR _CreateCursor(HANDLE hModule, int iXhotspot, int iYhotspot,
        int iWidth, int iHeight, LPBYTE lpANDplane, LPBYTE lpXORplane);
PICON _CreateIcon(HANDLE hModule, int iWidth, int iHeight,
        BYTE bPlanes, BYTE bBitsPixel, LPBYTE lpANDplane, LPBYTE lpXORplane);
VOID DestroyUnlockedCursor(VOID *pv);
BOOL _DestroyCursor(PCURSOR pcur, DWORD cmdDestroy);
HANDLE _CreateAcceleratorTable(LPACCEL ccxpaccel, int cbAccel);

/*
 * CURSOR.C
 */
#if DBG
    PCURSOR DbgLockQCursor(PQ pq, PCURSOR pcur);
    #define LockQCursor(pq, pcur)   DbgLockQCursor(pq, pcur)
#else
    #define LockQCursor(pq, pcur)   Lock(&pq->spcurCurrent, pcur)
#endif // DBG

PCURSOR zzzSetCursor(PCURSOR pcur);
BOOL    zzzSetCursorPos(int x, int y);
int     zzzShowCursor(BOOL fShow);
BOOL    zzzClipCursor(LPCRECT prcClip);
PCURSOR _GetCursor(VOID);
BOOL    _SetCursorContents(PCURSOR pcur, PCURSOR pcurNew);
VOID    SetPointer(BOOL fSet);
VOID    zzzHideCursorNoCapture(VOID);
#define GETPCI(pcur) ((PCURSINFO)&(pcur->CI_FIRST))

/*
 * WMICON.C
 */
BOOL _DrawIconEx(HDC hdc, int x, int y, PCURSOR pcur, int cx, int cy,
        UINT istepIfAniCur, HBRUSH hbrush, UINT diFlags) ;
BOOL BltIcon(HDC hdc, int x, int y, int cx, int cy,
        HDC hdcSrc, PCURSOR pcursor, UINT diFlag, LONG rop);

/*
 * DESKTOP.C
 */

HDESK xxxCreateDesktop(
        POBJECT_ATTRIBUTES,
        KPROCESSOR_MODE,
        PUNICODE_STRING,
        LPDEVMODEW,
        DWORD,
        DWORD);

#define CST_MAX_THREADS       30

/*
 * Flags for xxxSwitchDesktop().
 */
#define SDF_CREATENEW  0x01 /* New desktop, don't send enable/disable */
#define SDF_SLOVERRIDE 0x02 /* Don't respect WSF_SWITCHLOCK on pwinsta */

HDESK _OpenDesktop(POBJECT_ATTRIBUTES ccxObja, KPROCESSOR_MODE AccessMode, DWORD dwFlags, DWORD dwDesiredAccess, BOOL *pbShutDown);
BOOL OpenDesktopCompletion(PDESKTOP pdesk, HDESK hdesk, DWORD dwFlags, BOOL *pbShutDown);
BOOL xxxSwitchDesktop(PWINDOWSTATION pwinsta, PDESKTOP pdesk, DWORD dwFlags);
VOID zzzSetDesktop(PTHREADINFO pti, PDESKTOP pdesk, HDESK hdesk);
HDESK xxxGetInputDesktop(VOID);
BOOL xxxSetThreadDesktop(HDESK hdesk, PDESKTOP pdesk);
HDESK xxxGetThreadDesktop(DWORD dwThread, HDESK hdeskConsole, KPROCESSOR_MODE AccessMode);
BOOL xxxCloseDesktop(HDESK hdesk, KPROCESSOR_MODE AccessMode);
DWORD _SetDesktopConsoleThread(PDESKTOP pdesk, DWORD dwThreadId);
VOID xxxRealizeDesktop(PWND pwnd);

/*
 * WINSTA.C
 */
NTSTATUS CreateGlobalAtomTable(PVOID* ppAtomTable);
HWINSTA xxxCreateWindowStation(POBJECT_ATTRIBUTES ObjA,
    KPROCESSOR_MODE OwnershipMode,
    DWORD amRequest,
    HANDLE hKbdLayoutFile,
    DWORD offTable,
    PKBDTABLE_MULTI_INTERNAL pKbdTableMulti,
    PCWSTR pwszKLID,
    UINT uKbdInputLocale);
HWINSTA _OpenWindowStation(POBJECT_ATTRIBUTES pObjA, DWORD dwDesiredAccess, KPROCESSOR_MODE AccessMode);
BOOL _CloseWindowStation(HWINSTA hwinsta);
NTSTATUS xxxSetProcessWindowStation(HWINSTA hwinsta, KPROCESSOR_MODE AccessMode);

PWINDOWSTATION _GetProcessWindowStation(HWINSTA *phwinsta);
BOOL _LockWorkStation(VOID);

NTSTATUS ReferenceWindowStation(PETHREAD Thread, HWINSTA hwinsta,
        ACCESS_MASK amDesiredAccess, PWINDOWSTATION *ppwinsta, BOOL fUseDesktop);

/*
 * HOOKS.C
 */
PROC zzzSetWindowsHookAW(int nFilterType, PROC pfnFilterProc, DWORD dwFlags);
BOOL zzzUnhookWindowsHookEx(PHOOK phk);
BOOL zzzUnhookWindowsHook(int nFilterType, PROC pfnFilterProc);
LRESULT xxxCallNextHookEx(int nCode, WPARAM wParam, LPARAM lParam);
BOOL _CallMsgFilter(LPMSG lpMsg, int nCode);
VOID zzzCancelJournalling(VOID);
#if DBG
VOID DbgValidateHooks(PHOOK phk, int iType);
#else
#define DbgValidateHooks(phk, iType)
#endif
BOOL _RegisterUserApiHook(PUNICODE_STRING pstrLib, ULONG_PTR offPfnInitDefWindowProc);
BOOL _UnregisterUserApiHook(VOID);
BOOL xxxLoadUserApiHook(VOID);


extern int gihmodUserApiHook;

__inline BOOL IsInsideUserApiHook(
    VOID)
{
    return gihmodUserApiHook >= 0;
}

#ifdef MESSAGE_PUMP_HOOK

BOOL _DoInitMessagePumpHook(VOID);
BOOL _DoUninitMessagePumpHook(VOID);

extern PTHREADINFO gptiCurrent;

__inline BOOL IsInsideMPH(
    VOID)
{
    PCLIENTTHREADINFO pcti = PtiCurrent()->pcti;
    return pcti->cMessagePumpHooks > 0;
}

#endif // MESSAGE_PUMP_HOOK


/*
 * SRVHOOK.C
 */
LRESULT fnHkINLPCWPEXSTRUCT(PWND pwnd, UINT message, WPARAM wParam,
        LPARAM lParam, ULONG_PTR xParam);
LRESULT fnHkINLPCWPRETEXSTRUCT(PWND pwnd, UINT message, WPARAM wParam,
        LPARAM lParam, ULONG_PTR xParam);

/*
 * EXITWIN.C
 */
LONG xxxClientShutdown(PWND pwnd, WPARAM wParam);
BOOL xxxRegisterUserHungAppHandlers(PFNW32ET pfnW32EndTask, HANDLE hEventWowExec);

/*
 * INIT.C
 */
BOOL CreateTerminalInput(PTERMINAL pTerm);

VOID LW_LoadProfileInitData(PUNICODE_STRING pProfileUserName);
VOID xxxODI_ColorInit(PUNICODE_STRING pProfileUserName);
HRGN InitCreateRgn(VOID);
VOID xxxUpdateSystemCursorsFromRegistry(PUNICODE_STRING pProfileUserName);
VOID xxxUpdateSystemIconsFromRegistry(PUNICODE_STRING pProfileUserName);
VOID RegisterLPK(DWORD dwLpkEntryPoints);
HBITMAP CreateCaptionStrip(VOID);

BOOL LW_BrushInit(VOID);
VOID xxxLW_LoadFonts(BOOL bRemote);

VOID _LoadCursorsAndIcons(VOID);

VOID UnloadCursorsAndIcons(VOID);

VOID IncrMBox(VOID);
VOID DecrMBox(VOID);
VOID InitAnsiOem(PCHAR pOemToAnsi, PCHAR pAnsiToOem);
int  xxxAddFontResourceW(LPWSTR lpFile, FLONG flags, DESIGNVECTOR *pdv);
VOID EnforceColorDependentSettings(VOID);


/*
 * ACCESS.C
 */
VOID xxxUpdatePerUserAccessPackSettings(PUNICODE_STRING pProfileUserName);

/*
 * inctlpan.c
 */
VOID GetWindowNCMetrics(LPNONCLIENTMETRICS lpnc);

HFONT CreateFontFromWinIni(PUNICODE_STRING pProfileUserName,LPLOGFONT lplf, UINT idFont);
VOID SetMinMetrics(PUNICODE_STRING pProfileUserName,LPMINIMIZEDMETRICS lpmin);
BOOL xxxSetWindowNCMetrics(PUNICODE_STRING pProfileUserName,LPNONCLIENTMETRICS lpnc, BOOL fSizeChange, int clNewBorder);
BOOL SetIconMetrics(PUNICODE_STRING pProfileUserName,LPICONMETRICS lpicon);
BOOL xxxSetNCFonts(PUNICODE_STRING pProfileUserName, LPNONCLIENTMETRICS lpnc);
BOOL CreateBitmapStrip(VOID);
BOOL UpdateWinIniInt(PUNICODE_STRING pProfileUserName, UINT idSection, UINT wKeyNameId, int value);

/*
 * rare.c
 */
VOID SetDesktopMetrics(VOID);
VOID SetMsgBox(PWND pwnd);

BOOL _RegisterShellHookWindow(PWND pwnd);
BOOL _DeregisterShellHookWindow(PWND pwnd);
BOOL xxxSendMinRectMessages(PWND pwnd, RECT *lpRect);
void PostShellHookMessages(UINT message, LPARAM lParam);
VOID _ResetDblClk(VOID);
VOID xxxSimulateShiftF10(VOID);
BOOL VWPLAdd(PVWPL *ppvwpl, PWND pwnd, DWORD dwThreshold);
BOOL VWPLRemove(PVWPL *ppvwpl, PWND pwnd);
PWND VWPLNext(PVWPL pvwpl, PWND pwndPrev, DWORD *pnPrev);

/*
 * DDETRACK STUFF
 */

#if DBG
VOID ValidatePublicObjectList(VOID);
VOID TraceDdeMsg(UINT msg, HWND hwndFrom, HWND hwndTo, UINT code);
#define MSG_SENT    0
#define MSG_POST    1
#define MSG_RECV    2
#define MSG_PEEK    3
#else
#define ValidatePublicObjectList()
#define TraceDdeMsg(m, h1, h2, c)
#endif // DBG

typedef struct tagFREELIST {
    struct tagFREELIST *next;
    HANDLE h;                           // CSR client side GMEM_DDESHARE handle
    DWORD flags;                        // XS_ flags describing data
} FREELIST, *PFREELIST;

typedef struct tagDDEIMP {
    SECURITY_QUALITY_OF_SERVICE qos;
    SECURITY_CLIENT_CONTEXT ClientContext;
    short cRefInit;
    short cRefConv;
} DDEIMP, *PDDEIMP;

typedef struct tagDDECONV {
    THROBJHEAD          head;           // HM header
    struct tagDDECONV   *snext;
    struct tagDDECONV   *spartnerConv;  // siamese twin
    PWND                spwnd;          // associated pwnd
    PWND                spwndPartner;   // associated partner pwnd
    struct tagXSTATE    *spxsOut;       // transaction info queue - out point
    struct tagXSTATE    *spxsIn;        // transaction info queue - in point
    struct tagFREELIST  *pfl;           // free list
    DWORD               flags;          // CXF_ flags
    struct tagDDEIMP    *pddei;         // impersonation information
} DDECONV, *PDDECONV;

typedef DWORD (FNDDERESPONSE)(PDWORD pmsg, LPARAM *plParam, PDDECONV pDdeConv);
typedef FNDDERESPONSE *PFNDDERESPONSE;

typedef struct tagXSTATE {
    THROBJHEAD          head;           // HM header
    struct tagXSTATE    *snext;
    PFNDDERESPONSE      fnResponse;     // proc to handle next msg.
    HANDLE              hClient;        // GMEM_DDESAHRE handle on client side
    HANDLE              hServer;        // GMEM_DDESHARE handle on server side
    PINTDDEINFO         pIntDdeInfo;    // DDE data being transfered
    DWORD               flags;          // XS_ flags describing transaction/data
} XSTATE, *PXSTATE;

// values for flags field

#define CXF_IS_SERVER               0x0001
#define CXF_TERMINATE_POSTED        0x0002
#define CXF_PARTNER_WINDOW_DIED     0x0004
#define CXF_INTRA_PROCESS           0x8000

BOOL xxxDDETrackSendHook(PWND pwndTo, DWORD message, WPARAM wParam, LPARAM lParam);
DWORD xxxDDETrackPostHook(PUINT pmessage, PWND pwndTo, WPARAM wParam, LPARAM *plParam, BOOL fSent);
VOID FreeDdeXact(PXSTATE pxs);

VOID xxxDDETrackGetMessageHook(PMSG pmsg);
VOID xxxDDETrackWindowDying(PWND pwnd, PDDECONV pDdeConv);
VOID FreeDdeConv(PDDECONV pDdeConv);
BOOL _ImpersonateDdeClientWindow(PWND pwndClient, PWND pwndServer);


typedef struct tagMONITORPOS
{
    RECT     rcMonitor;     /* where the monitor rect was */
    RECT     rcWork;        /* where the work rect was */
    PMONITOR pMonitor;      /* what new monitor gets its windows */
} MONITORPOS, *PMONITORPOS;

typedef struct tagMONITORRECTS
{
    int             cMonitor;   /* number of monitors */
    MONITORPOS      amp[1];     /* the monitor positions */
} MONITORRECTS, *PMONITORRECTS;


// stuctures for windows resize/ reposition on reconnect.
// when disconnecting from local console, these structures allow
// to memorize the monitors layout and windows size and positions
// on the monitors. When reconnecting back to local console, the snapshot
// is used to restore windows positions for windows that still exist.


typedef struct tagWPSNAPSHOT
{
    RECT     rcWindow;                 /* Windows rect */
    HWND     hwnd;                     /* hwnd */
} WPSNAPSHOT, *PWPSNAPSHOT;

typedef struct tagWMSNAPSHOT
{
    PMONITORRECTS   pmr;        /* Monitors and their dimensions and positions */
    PWPSNAPSHOT     pwps;       /* Windows and their dimensions and positions */
    int cWindows;               /* number of windows in pwps */
} WMSNAPSHOT, *PWMSNAPSHOT;

NTSTATUS RestoreMonitorsAndWindowsRects(VOID);
NTSTATUS SnapShotMonitorsAndWindowsRects(VOID);
VOID  CleanupMonitorsAndWindowsSnapShot(VOID);
PWPSNAPSHOT SnapshotWindowRects(int *pnWindows);

PMONITORRECTS SnapshotMonitorRects(VOID);
VOID xxxDesktopRecalc(PMONITORRECTS pmrOld);
VOID UpdateMonitorRectsSnapShot(PMONITORRECTS pmr);
BOOL IsValidMonitor(PMONITOR pMonitor);

BOOL _SetDoubleClickTime(UINT dtTime);
BOOL _SwapMouseButton(BOOL fSwapButtons);
VOID xxxDestroyThreadInfo(VOID);

BOOL _GetWindowPlacement(PWND pwnd, PWINDOWPLACEMENT pwp);

PMENU xxxGetSystemMenu(PWND pWnd, BOOL bRevert);
PMENU _CreateMenu(VOID);
PMENU _CreatePopupMenu(VOID);
BOOL  _DestroyMenu(PMENU pMenu);
DWORD _CheckMenuItem(PMENU pMenu, UINT wIDCheckItem, UINT wCheck);
DWORD xxxEnableMenuItem(PMENU pMenu, UINT wIDEnableItem, UINT wEnable);

PWND _GetNextQueueWindow(PWND pwnd, BOOL fDir, BOOL fAltEsc);

UINT_PTR _SetSystemTimer(PWND pwnd, UINT_PTR nIDEvent, DWORD dwElapse,
        TIMERPROC_PWND pTimerFunc);
BOOL   _SetClipboardData(UINT fmt, HANDLE hData, BOOL fGlobalHandle, BOOL fIncSerialNumber);
WORD   _SetClassWord(PWND pwnd, int index, WORD value);
DWORD  xxxSetClassLong(PWND pwnd, int index, DWORD value, BOOL bAnsi);
#ifdef _WIN64
ULONG_PTR xxxSetClassLongPtr(PWND pwnd, int index, ULONG_PTR value, BOOL bAnsi);
#else
#define xxxSetClassLongPtr  xxxSetClassLong
#endif
ATOM   xxxRegisterClassEx(LPWNDCLASSVEREX pwc, PCLSMENUNAME pcmn,
        WORD fnid, DWORD dwFlags, LPDWORD pdwWOW);
BOOL  xxxHiliteMenuItem(PWND pwnd, PMENU pmenu, UINT cmd, UINT flags);
HANDLE _CreateAcceleratorTable(LPACCEL paccel, int cbAccel);
HANDLE xxxGetInputEvent(DWORD dwWakeMask);
BOOL   _UnregisterClass(LPCWSTR lpszClassName, HANDLE hModule, PCLSMENUNAME pcmn);
ATOM   _GetClassInfoEx(HANDLE hModule, LPCWSTR lpszClassName, LPWNDCLASSEX pwc, LPWSTR *ppszMenuName, BOOL bAnsi);
PWND   _WindowFromDC(HDC hdc);
PCLS   _GetWOWClass(HANDLE hModule, LPCWSTR lpszClassName);
LRESULT xxxHkCallHook(PHOOK phk, int nCode, WPARAM wParam, LPARAM lParam);
PHOOK  zzzSetWindowsHookEx(HANDLE hmod, PUNICODE_STRING pstrLib,
        PTHREADINFO ptiThread, int nFilterType, PROC pfnFilterProc, DWORD dwFlags);
DWORD  GetDebugHookLParamSize(WPARAM wParam, PDEBUGHOOKINFO pdebughookstruct);
BOOL   _RegisterLogonProcess(DWORD dwProcessId, BOOL fSecure);
UINT   _LockWindowStation(PWINDOWSTATION pwinsta);
BOOL   _UnlockWindowStation(PWINDOWSTATION pwinsta);
BOOL   _SetWindowStationUser(PWINDOWSTATION pwinsta, PLUID pluidUser,
        PSID psidUser, DWORD cbsidUser);
BOOL   _SetDesktopBitmap(PDESKTOP pdesk, HBITMAP hbitmap, DWORD dwStyle);

BOOL   _SetLogonNotifyWindow(PWND pwnd);


BOOL   _RegisterTasklist(PWND pwndTasklist);
LONG_PTR _SetMessageExtraInfo(LONG_PTR);
VOID   xxxRemoveEvents(PQ pq, int nQueue, DWORD flags);

PPCLS _InnerGetClassPtr(ATOM atom, PPCLS ppclsList, HANDLE hModule);

/*
 * ntcb.h funtions.
 */
DWORD ClientGetListboxString(PWND hwnd, UINT msg,
        WPARAM wParam, PVOID lParam,
        ULONG_PTR xParam, PROC xpfn, DWORD dwSCMSFlags, BOOL bNotString, PSMS psms);
HANDLE ClientLoadLibrary(PUNICODE_STRING pstrLib, ULONG_PTR offPfnInitDefWindowProc);
BOOL ClientFreeLibrary(HANDLE hmod);

#ifdef MESSAGE_PUMP_HOOK
BOOL ClientGetMessageMPH(LPMSG msg, HWND hwndFilter, UINT msgMin, UINT msgMax, UINT flags, BOOL fGetMessage);
BOOL ClientWaitMessageExMPH(UINT fsWakeMask, DWORD Timeout);
#endif

BOOL xxxClientGetCharsetInfo(LCID lcid, PCHARSETINFO pcs);
BOOL ClientExitProcess(PFNW32ET pfn, DWORD dwExitCode);
BOOL ClientGrayString(GRAYSTRINGPROC pfnOutProc, HDC hdc,
        DWORD lpData, int nCount);
BOOL CopyFromClient(LPBYTE lpByte, LPBYTE lpByteClient, DWORD cch,
        BOOL fString, BOOL fAnsi);
BOOL CopyToClient(LPBYTE lpByte, LPBYTE lpByteClient,
        DWORD cchMax, BOOL fAnsi);
VOID ClientNoMemoryPopup(VOID);
NTSTATUS xxxClientThreadSetup(VOID);

VOID ClientDeliverUserApc(VOID);

BOOL ClientImmLoadLayout(HKL, PIMEINFOEX);
DWORD ClientImmProcessKey(HWND, HKL, UINT, LPARAM, DWORD);

NTSTATUS xxxUserModeCallback (ULONG uApi, PVOID pIn, ULONG cbIn, PVOID pOut, ULONG cbOut);
int xxxClientLoadStringW(UINT StrID, LPWSTR szText, int cch);

PCURSOR ClassSetSmallIcon(
    PCLS pcls,
    PCURSOR pcursor,
    BOOL fServerCreated);

BOOL _GetTextMetricsW(
    HDC hdc,
    LPTEXTMETRICW ptm);

int xxxDrawMenuBarTemp(
    PWND pwnd,
    HDC hdc,
    LPRECT lprc,
    PMENU pMenu,
    HFONT hFont);

BOOL xxxDrawCaptionTemp(
    PWND pwnd,
    HDC hdc,
    LPRECT lprc,
    HFONT hFont,
    PCURSOR pcursor,
    PUNICODE_STRING pstrText OPTIONAL,
    UINT flags);

WORD xxxTrackCaptionButton(
    PWND pwnd,
    UINT hit);

VOID GiveForegroundActivateRight(HANDLE hPid);
BOOL HasForegroundActivateRight(HANDLE hPid);
BOOL FRemoveForegroundActivate(PTHREADINFO pti);
VOID RestoreForegroundActivate(VOID);
VOID CancelForegroundActivate(VOID);

#define ACTIVATE_ARRAY_SIZE 5
extern HANDLE ghCanActivateForegroundPIDs[ACTIVATE_ARRAY_SIZE];

__inline VOID GiveForegroundActivateRight(
    HANDLE hPid)
{
    static int index = 0;

    TAGMSG1(DBGTAG_FOREGROUND, "Giving 0x%x foreground activate right", hPid);
    ghCanActivateForegroundPIDs[index++] = hPid;
    if (index == ACTIVATE_ARRAY_SIZE) {
        index = 0;
    }
}

__inline BOOL HasForegroundActivateRight(
    HANDLE hPid)
{
    int i = 0;

    for(; i < ACTIVATE_ARRAY_SIZE; ++i) {
            if (ghCanActivateForegroundPIDs[i] == hPid) {
                TAGMSG1(DBGTAG_FOREGROUND, "HasForegroundActivateRight: Found 0x%x", hPid);
                return TRUE;
            }
     }

     TAGMSG1(DBGTAG_FOREGROUND, "HasForegroundActivateRight: Did NOT find 0x%x", hPid);
     return FALSE;
}


#define WHERE_NOONE_CAN_SEE_ME ((int) -32000)
BOOL MinToTray(PWND pwnd);

void xxxUpdateThreadsWindows(
    PTHREADINFO pti,
    PWND pwnd,
    HRGN hrgnFullDrag);

NTSTATUS xxxQueryInformationThread(
    IN HANDLE hThread,
    IN USERTHREADINFOCLASS ThreadInfoClass,
    OUT PVOID ThreadInformation,
    IN ULONG ThreadInformationLength,
    OUT PULONG ReturnLength OPTIONAL);

NTSTATUS xxxSetInformationThread(
    IN HANDLE hThread,
    IN USERTHREADINFOCLASS ThreadInfoClass,
    IN PVOID ThreadInformation,
    IN ULONG ThreadInformationLength);

NTSTATUS GetProcessDefaultWindowOrientation(
    IN HANDLE hProcess,
    OUT DWORD *pdwDefaultOrientation);

NTSTATUS SetProcessDefaultWindowOrientation(
    IN HANDLE hProcess,
    IN DWORD dwDefaultOrientation);

NTSTATUS SetInformationProcess(
    IN HANDLE hProcess,
    IN USERPROCESSINFOCLASS ProcessInfoClass,
    IN PVOID ProcessInformation,
    IN ULONG ProcessInformationLength);


NTSTATUS xxxConsoleControl(
    IN CONSOLECONTROL ConsoleControl,
    IN PVOID ConsoleInformation,
    IN ULONG ConsoleInformationLength);


/***************************************************************************\
* String Table Defines
*
* KERNEL\STRID.MC has a nice big table of strings that are meant to be
* localized. Before use, the strings are pulled from the resource table
* with LoadString, passing it one of the following string ids.
*
* NOTE: Only strings that need to be localized should be added to the
*       string table. Class name strings, etc are NOT localized.
*
* LATER: All string table entries should be reexamined to be sure they
*        conform to the note above.
*
\***************************************************************************/

#define OCR_APPSTARTING         32650

/*
 * Win Event Hook struct
 */
typedef struct tagEVENTHOOK {
    THROBJHEAD          head;                //
    struct tagEVENTHOOK *pehNext;            // Next event hook
    UINT                eventMin;            // Min event (>=) to hook
    UINT                eventMax;            // Max event (<=) to hook
    UINT                fDestroyed:1;        // If orphaned while in use
// IanJa - we don't need this bit
//  UINT                f32Bit:1;            // If 32-bit client
    UINT                fIgnoreOwnThread:1;  // Ignore events for installer thread
    UINT                fIgnoreOwnProcess:1; // Ignore events for installer process
    UINT                fSync:1;             // Sync event (inject DLL into each process)
    HANDLE              hEventProcess;       // Process being hooked
    DWORD               idEventThread;       // Thread being hooked
// (IanJa - have head.pti: don't need ppiInstaller, can use GETPTI(peh)->ppi)
//  DWORD               idInstallerProcess;  // ID of process that installed hook
    ULONG_PTR            offPfn;             // offset event proc
    int                 ihmod;               // index of module containing event proc
    LPWSTR              pwszModulePath;      // Path of module library for global sync.
} EVENTHOOK, *PEVENTHOOK;

typedef struct tagNOTIFY {
    struct tagNOTIFY *pNotifyNext;         // Next notification
    PEVENTHOOK        spEventHook;         // Event this refers to
    DWORD             event;               // Event
    HWND              hwnd;                // hwnd to ask about it
    LONG              idObject;            // object ID
    LONG              idChild;             // child id
    DWORD             idSenderThread;      // Thread generating event
    DWORD             dwEventTime;         // Event time
    DWORD             dwWEFlags;           // WEF_DEFERNOTIFY etc.
    PTHREADINFO       ptiReceiver;         // Thread receiving event
} NOTIFY, *PNOTIFY;

VOID xxxWindowEvent(DWORD event, PWND pwnd, LONG idObject, LONG idChild, DWORD dwFlags);
#define WEF_USEPWNDTHREAD 0x0001
#define WEF_DEFERNOTIFY   0x0002
#define WEF_ASYNC         0x0004
#define WEF_POSTED        0x0008

#define DeferWinEventNotify()      CheckCritIn();          \
                                   gdwDeferWinEvent++
#define IsWinEventNotifyDeferred() (gdwDeferWinEvent > 0)
#define IsWinEventNotifyDeferredOK() (!IsWinEventNotifyDeferred() || ISATOMICCHECK())
#define zzzEndDeferWinEventNotify()                        \
        UserAssert(IsWinEventNotifyDeferred());            \
        CheckCritIn();                                     \
        if (--gdwDeferWinEvent == 0) {                     \
            if (gpPendingNotifies != NULL) { \
                xxxFlushDeferredWindowEvents();            \
            }                                              \
        }

/*
 * Only use this one for bookkeeping gdwDeferWinEvent,
 * which may be required without leaving the critical section.
 */
#define EndDeferWinEventNotifyWithoutProcessing()          \
        UserAssert(IsWinEventNotifyDeferred());            \
        CheckCritIn();                                     \
        --gdwDeferWinEvent

#define zzzWindowEvent(event, pwnd, idObject, idChild, dwFlags) \
        xxxWindowEvent(event, pwnd, idObject, idChild,          \
            IsWinEventNotifyDeferred() ? (dwFlags) | WEF_DEFERNOTIFY : (dwFlags))

VOID xxxFlushDeferredWindowEvents();

BOOL xxxClientCallWinEventProc(WINEVENTPROC pfn, PEVENTHOOK pEventHook, PNOTIFY pNotify);
void DestroyEventHook(PEVENTHOOK);
VOID FreeThreadsWinEvents(PTHREADINFO pti);

BOOL       _UnhookWinEvent(PEVENTHOOK peh);
VOID       DestroyNotify(PNOTIFY pNotify);
PEVENTHOOK xxxProcessNotifyWinEvent(PNOTIFY pNotify);
PEVENTHOOK _SetWinEventHook(DWORD eventMin, DWORD eventMax,
        HMODULE hmodWinEventProc, PUNICODE_STRING pstrLib,
        WINEVENTPROC pfnWinEventProc, HANDLE hEventProcess,
        DWORD idEventThread, DWORD dwFlags);
BOOL _GetGUIThreadInfo(PTHREADINFO pti, PGUITHREADINFO pgui);
BOOL xxxGetTitleBarInfo(PWND pwnd, PTITLEBARINFO ptbi);
BOOL xxxGetComboBoxInfo(PWND pwnd, PCOMBOBOXINFO ptbi);
DWORD xxxGetListBoxInfo(PWND pwnd);
BOOL xxxGetScrollBarInfo(PWND pwnd, LONG idObject, PSCROLLBARINFO ptbi);
PWND _GetAncestor(PWND pwnd, UINT gaFlags);
PWND _RealChildWindowFromPoint(PWND pwndParent, POINT pt);
BOOL _GetAltTabInfo(int iItem, PALTTABINFO pati,
        LPWSTR lpszItemText, UINT cchItemText, BOOL bAnsi);
BOOL xxxGetMenuBarInfo(PWND pwnd, long idObject, long idItem, PMENUBARINFO pmbi);

typedef HWND *PHWND;

typedef struct tagSwitchWndInfo {

    PBWL    pbwl;               // Pointer to the window list built.
    PHWND   phwndLast;          // Pointer to the last window in the list.
    PHWND   phwndCurrent;       // pointer to the current window.

    INT     iTotalTasks;        // Total number of tasks.
    INT     iTasksShown;        // Total tasks shown.
    BOOL    fScroll;            // Is there a need to scroll?

    INT     iFirstTaskIndex;    // Index to the first task shown.

    INT     iNoOfColumns;       // Max Number of tasks per row.
    INT     iNoOfRows;          // Max Number of rows of icons in the switch window.
    INT     iIconsInLastRow;    // Icons in last row.
    INT     iCurCol;            // Current column where hilite lies.
    INT     iCurRow;            // Current row where hilite lies.
    INT     cxSwitch;           // Switch Window dimensions.
    INT     cySwitch;
    POINT   ptFirstRowStart;    // Top left corner of the first Icon Slot.
    RECT    rcTaskName;         // Rect where Task name is displayed.
    BOOL    fJournaling;        // Determins how we check the keyboard state
} SWITCHWNDINFO, *PSWINFO;

typedef struct tagSWITCHWND {
    WND;
    PSWINFO pswi;
} SWITCHWND, *PSWITCHWND;

typedef struct tagHOTKEYSTRUCT {
    PWND  spwnd;
    DWORD key;
} HOTKEYSTRUCT, *PHOTKEYSTRUCT;

#define LANGTOGGLEKEYS_SIZE 3

/*
 * ACCF_ and PUDF_ flags share the same field. ACCF fields
 * are so named because they may later move to a differnt
 * struct.
 */
#define ACCF_DEFAULTFILTERKEYSON        0x00000001
#define ACCF_DEFAULTSTICKYKEYSON        0x00000002
#define ACCF_DEFAULTMOUSEKEYSON         0x00000004
#define ACCF_DEFAULTTOGGLEKEYSON        0x00000008
#define ACCF_DEFAULTTIMEOUTON           0x00000010
#define ACCF_DEFAULTKEYBOARDPREF        0x00000020
#define ACCF_DEFAULTSCREENREADER        0x00000040
#define ACCF_DEFAULTHIGHCONTRASTON      0x00000080
#define ACCF_ACCESSENABLED              0x00000100
#define ACCF_IGNOREBREAKCODE            0x00000400
#define ACCF_FKMAKECODEPROCESSED        0x00000800
#define ACCF_MKVIRTUALMOUSE             0x00001000
#define ACCF_MKREPEATVK                 0x00002000
#define ACCF_FIRSTTICK                  0x00004000
#define ACCF_SHOWSOUNDSON               0x00008000

/*
 * NOTE: PUDF_ANIMATE must have the same value as MINMAX_ANIMATE.
 */
#define PUDF_ANIMATE                    0x00010000

#define ACCF_KEYBOARDPREF               0x00020000
#define ACCF_SCREENREADER               0x00040000
#define PUDF_BEEP                       0x00080000  /* Warning beeps allowed?                   */
#define PUDF_DRAGFULLWINDOWS            0x00100000  /* Drag xor rect or full windows            */
#define PUDF_ICONTITLEWRAP              0x00200000  /* Wrap icon titles or just use single line */
#define PUDF_FONTSARELOADED             0x00400000
#define PUDF_POPUPINUSE                 0x00800000
#define PUDF_EXTENDEDSOUNDS             0x01000000
#define PUDF_MENUSTATEINUSE             0x02000000
#define PUDF_VDMBOUNDSACTIVE            0x04000000
#define PUDF_ALLOWFOREGROUNDACTIVATE    0x08000000
#define PUDF_DRAGGINGFULLWINDOW         0x10000000
#define PUDF_LOCKFULLSCREEN             0x20000000
#define PUDF_GSMWPINUSE                 0x40000000

#define TEST_ACCF(f)               TEST_FLAG(gdwPUDFlags, f)
#define TEST_BOOL_ACCF(f)          TEST_BOOL_FLAG(gdwPUDFlags, f)
#define SET_ACCF(f)                SET_FLAG(gdwPUDFlags, f)
#define CLEAR_ACCF(f)              CLEAR_FLAG(gdwPUDFlags, f)
#define SET_OR_CLEAR_ACCF(f, fSet) SET_OR_CLEAR_FLAG(gdwPUDFlags, f, fSet)
#define TOGGLE_ACCF(f)             TOGGLE_FLAG(gdwPUDFlags, f)

#define TEST_PUDF(f)               TEST_FLAG(gdwPUDFlags, f)
#define TEST_BOOL_PUDF(f)          TEST_BOOL_FLAG(gdwPUDFlags, f)
#define SET_PUDF(f)                SET_FLAG(gdwPUDFlags, f)
#define CLEAR_PUDF(f)              CLEAR_FLAG(gdwPUDFlags, f)
#define SET_OR_CLEAR_PUDF(f, fSet) SET_OR_CLEAR_FLAG(gdwPUDFlags, f, fSet)
#define TOGGLE_PUDF(f)             TOGGLE_FLAG(gdwPUDFlags, f)

/*
 * Power state stuff
 */

typedef struct tagPOWERSTATE {
    volatile ULONG           fInProgress:1;
    volatile ULONG           fCritical:1;
    volatile ULONG           fOverrideApps:1;
    volatile ULONG           fQueryAllowed:1;
    volatile ULONG           fUIAllowed:1;
    PKEVENT                  pEvent;
    BROADCASTSYSTEMMSGPARAMS bsmParams;
    POWERSTATEPARAMS         psParams;
    ULONG PowerStateTask;
} POWERSTATE, *PPOWERSTATE;

typedef struct _POWER_INIT {
    PVIDEO_WIN32K_CALLBACKS_PARAMS Params;
    PKEVENT   pPowerReadyEvent;
} POWER_INIT, *PPOWER_INIT;

#define POWERON_PHASE  -1
#define LOWPOWER_PHASE  1
#define POWEROFF_PHASE  2

NTSTATUS InitializePowerRequestList(HANDLE hPowerRequestEvent);
VOID     CleanupPowerRequestList(VOID);
VOID     DeletePowerRequestList(VOID);
VOID     xxxUserPowerCalloutWorker(VOID);
VOID     VideoPortCalloutThread(PPOWER_INIT pInitData);

/*
 * Fade-in / fade-out globals.
 */

typedef struct tagFADE {
    HANDLE hsprite;
    HDC hdc;
    HBITMAP hbm;
    POINT ptDst;
    SIZE size;
    DWORD dwTime;
    DWORD dwStart;
    DWORD dwFlags;
#ifdef MOUSE_IP
    COLORREF crColorKey;
#endif
} FADE, *PFADE;

/*
 * Globals are included last because they may require some of the types
 * being defined above.
 */
#include "globals.h"
#include "ddemlsvr.h"
/*
 * If you make a change that requires including strid.h when building
 *  ntuser\rtl, then you need to change the sources/makefil* files so this
 *  file will be built in ntuser\inc; make sure that the output of
 *  mc.exe still goes to the kernel directory; this is because there are
 *  other places (like ntuser\server) where we use the same file name.
 */
#ifndef _USERRTL_
#include "strid.h"
#endif

#include "ntuser.h"

#define TestALPHA(uSetting) (!gbDisableAlpha && TestEffectUP(uSetting))

/*
 * tooltips/tracking prototypes from tooltips.c
 */

typedef struct tagTOOLTIP {
    DWORD dwFlags;
    UINT uTID;
    DWORD dwAnimStart;
    int iyAnim;
    LPWSTR pstr;
} TOOLTIP;

typedef struct tagTOOLTIPWND {
    WND;

    DWORD dwShowDelay;
    DWORD dwHideDelay;
    HDC hdcMem;
    HBITMAP hbmMem;

    TOOLTIP;  // this field must be last!
} TOOLTIPWND, *PTOOLTIPWND;

#define HTEXSCROLLFIRST     60
#define HTSCROLLUP          60
#define HTSCROLLDOWN        61
#define HTSCROLLUPPAGE      62
#define HTSCROLLDOWNPAGE    63
#define HTSCROLLTHUMB       64
#define HTEXSCROLLLAST      64
#define HTEXMENUFIRST       65
#define HTMDISYSMENU        65
#define HTMDIMAXBUTTON      66
#define HTMDIMINBUTTON      67
#define HTMDICLOSE          68
#define HTMENUITEM          69
#define HTEXMENULAST        69

int FindNCHitEx(PWND pwnd, int ht, POINT pt);
void xxxTrackMouseMove(PWND pwnd, int htEx, UINT message);
BOOL xxxHotTrack(PWND pwnd, int htEx, BOOL fDraw);
void xxxResetTooltip(PTOOLTIPWND pttwnd);
void xxxCancelMouseMoveTracking (DWORD dwDTFlags, PWND pwndTrack, int htEx, DWORD dwDTCancel);

__inline PVOID DesktopRebaseToClient(
    PTHREADINFO pti,
    PVOID p)
{
    UserAssert(pti->pClientInfo->ulClientDelta != 0);
    return (p) ? (PVOID)((PBYTE)p - pti->pClientInfo->ulClientDelta) : NULL;
}

__inline PVOID SharedRebaseToClient(
    PPROCESSINFO ppi,
    PVOID p)
{
    UserAssert(ppi->pClientBase != 0);
    return (p) ? (PVOID)((PBYTE)ppi->pClientBase + ((PBYTE)p -
            (PBYTE)gpvSharedBase)) : NULL;
}

/*
 * String range IDs.
 *
 * These are defined here to avoid duplicate entries in strid.mc
 */
#define STR_COLORSTART                   STR_SCROLLBAR
#define STR_COLOREND                     STR_MENUBAR

/*
 * Sprite and Fade related functions and defines.
 */
#define FADE_SHOW           0x00000001
#define FADE_COMPLETED      0x00000002
#define FADE_SHOWN          0x00000004
#define FADE_WINDOW         0x00000008
#define FADE_MENU           0x00000010
#define FADE_TOOLTIP        0x00000020
#ifdef MOUSE_IP
#define FADE_COLORKEY       0x00000040
#define FADE_SONAR          0x00000080
#endif

HDC CreateFade(PWND pwnd, RECT *prc, DWORD dwTime, DWORD dwFlags);
VOID StartFade(void);
VOID StopFade(void);
VOID ShowFade(void);
VOID AnimateFade(void);
__inline DWORD TestFadeFlags(
    DWORD dwFlags)
{
    return (gfade.dwFlags & dwFlags);
}

#ifdef MOUSE_IP

#define IS_SONAR_ACTIVE()       (TestUP(MOUSESONAR) && TestFadeFlags(FADE_SONAR))
#define CLEAR_SONAR_LASTVK()        (void)((TestUP(MOUSESONAR) && gbLastVkForSonar) ? (gbLastVkForSonar = 0) : 0)

BOOL StartSonar();
void StopSonar();

#endif

HANDLE xxxSetLayeredWindow(PWND pwnd, BOOL fRepaintBehind);
VOID UnsetLayeredWindow(PWND pwnd);
void TrackLayeredZorder(PWND pwnd);
VOID UpdateRedirectedDC(PDCE pdce);
BOOL _UpdateLayeredWindow(PWND pwnd, HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc,
        POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags);
BOOL _GetLayeredWindowAttributes(PWND hwnd, COLORREF *pcrKey, BYTE *pbAlpha, DWORD *pdwFlags);
BOOL _SetLayeredWindowAttributes(PWND pwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
BOOL RecreateRedirectionBitmap(PWND pwnd);
VOID ResetRedirectedWindows(VOID);

PWND GetStyleWindow(PWND pwnd, DWORD dwStyle);
PWND GetLastChild(PWND pwnd);

BOOL SetRedirectedWindow(PWND pwnd, UINT uFlags);
VOID UnsetRedirectedWindow(PWND pwnd, UINT uFlags);

VOID xxxCompositedPaint(PWND pwnd);

#define REDIRECT_LAYER                     0x0001
#define REDIRECT_COMPOSITED                0x0002
#define REDIRECT_EXTREDIRECTED             0x0004
#define REDIRECT_PRINT                     0x0008

typedef struct tagREDIRECT {
    HBITMAP hbm;
    RECT rcUpdate;
    UINT uFlags;
    HRGN hrgnComp;

#if DBG
    PWND pwnd;
#endif // DBG

} REDIRECT, *PREDIRECT;

HBITMAP GetRedirectionBitmap(PWND pwnd);
BOOL SetRedirectionBitmap(PWND pwnd, HBITMAP hbm);
UINT GetRedirectionFlags(PWND pwnd);
BOOL xxxPrintWindow(PWND pwnd, HDC hdcBlt, UINT nFlags);
void xxxTurnOffCompositing(PWND pwndStart, BOOL fChild);


#ifdef REDIRECTION
BOOL xxxSetProcessRedirectionMode(BOOL fEnable, PPROCESSINFO ppi);
BOOL xxxSetDesktopRedirectionMode(BOOL fEnable, PDESKTOP pDesk, PPROCESSINFO ppi);
#endif // REDIRECTION

void InternalInvalidate3(
    PWND pwnd,
    HRGN hrgn,
    DWORD flags);

BOOL UserSetFont(PUNICODE_STRING pProfileUserName,
    LPLOGFONTW   lplf,
    UINT         idFont,
    HFONT*       phfont
    );

HICON DWP_GetIcon(
    PWND pwnd,
    UINT uType);

BOOL xxxRedrawTitle(
    PWND pwnd, UINT wFlags);

DWORD GetContextHelpId(
    PWND pwnd);


HANDLE xxxClientCopyImage(
    HANDLE hImage,
    UINT type,
    int cxNew,
    int cyNew,
    UINT flags);

VOID _WOWCleanup(
    HANDLE hInstance,
    DWORD hTaskWow);

VOID _WOWModuleUnload(HANDLE hModule);

/*
 * FastProfile APIs
 */
typedef struct tagPROFINTINFO {
    UINT idSection;
    LPWSTR lpKeyName;
    DWORD  nDefault;
    PUINT puResult;
} PROFINTINFO, *PPROFINTINFO;

typedef struct {
    UINT idSection;
    UINT id;
    UINT idRes;
    UINT def;
} SPINFO, *PSPINFO;


#define INITIAL_USER_HANDLE_QUOTA  10000
#define MINIMUM_USER_HANDLE_QUOTA    200

#define INITIAL_POSTMESSAGE_LIMIT   10000
#define MINIMUM_POSTMESSAGE_LIMIT    4000

/*
 * See aFastRegMap[] in ntuser\kernel\profile.c
 */
#define PMAP_COLORS             0
#define PMAP_CURSORS            1
#define PMAP_WINDOWSM           2
#define PMAP_WINDOWSU           3
#define PMAP_DESKTOP            4
#define PMAP_ICONS              5
#define PMAP_FONTS              6
#define PMAP_TRUETYPE           7
#define PMAP_KBDLAYOUT          8
#define PMAP_INPUT              9
#define PMAP_COMPAT            10
#define PMAP_SUBSYSTEMS        11
#define PMAP_BEEP              12
#define PMAP_MOUSE             13
#define PMAP_KEYBOARD          14
#define PMAP_STICKYKEYS        15
#define PMAP_KEYBOARDRESPONSE  16
#define PMAP_MOUSEKEYS         17
#define PMAP_TOGGLEKEYS        18
#define PMAP_TIMEOUT           19
#define PMAP_SOUNDSENTRY       20
#define PMAP_SHOWSOUNDS        21
#define PMAP_AEDEBUG           22
#define PMAP_NETWORK           23
#define PMAP_METRICS           24
#define PMAP_UKBDLAYOUT        25
#define PMAP_UKBDLAYOUTTOGGLE  26
#define PMAP_WINLOGON          27
#define PMAP_KEYBOARDPREF      28
#define PMAP_SCREENREADER      29
#define PMAP_HIGHCONTRAST      30
#define PMAP_IMECOMPAT         31
#define PMAP_IMM               32
#define PMAP_POOLLIMITS        33
#define PMAP_COMPAT32          34
#define PMAP_SETUPPROGRAMNAMES 35
#define PMAP_INPUTMETHOD       36
#define PMAP_COMPAT2           37
#define PMAP_MOUCLASS_PARAMS   38
#define PMAP_KBDCLASS_PARAMS   39
#define PMAP_COMPUTERNAME      40
#define PMAP_TS                41
#define PMAP_TABLETPC          42
#define PMAP_MEDIACENTER       43
#define PMAP_LAST              43

#define MAXPROFILEBUF 256

#define POLICY_NONE     0x0001
#define POLICY_USER     0x0002
#define POLICY_MACHINE  0x0004
#define POLICY_REMOTE   0x0008
#define POLICY_ONLY     0x0010
/*
 * POLICY_REMOTE is not included in POLICY_REMOTE intentionally.
 * Else, we will try to read the remote policy always.
 */
#define POLICY_ALL      (POLICY_NONE | POLICY_USER | POLICY_MACHINE)
#define POLICY_VALID    (POLICY_ALL | POLICY_ONLY | POLICY_REMOTE)

PUNICODE_STRING CreateProfileUserName(TL *ptl);
void FreeProfileUserName(PUNICODE_STRING pProfileUserName,TL *ptl);
HANDLE  OpenCacheKeyEx(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, ACCESS_MASK amRequest, PDWORD pdwPolicyFlags);
BOOL    CheckDesktopPolicy(PUNICODE_STRING pProfileUserName OPTIONAL, PCWSTR lpKeyName);
BOOL    CheckDesktopPolicyChange(PUNICODE_STRING pProfileUserName OPTIONAL);
DWORD   FastGetProfileKeysW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR pszDefault, LPWSTR *ppszKeys);
BOOL    FastGetProfileDwordW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName, DWORD dwDefault, PDWORD pdwReturn, DWORD dwPolicyOnly);
DWORD   FastGetProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, DWORD dwPolicyOnly);
BOOL    FastGetProfileIntW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName, UINT nDefault, PUINT puiReturn, DWORD dwPolicyOnly);
BOOL    FastWriteProfileStringW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName, LPCWSTR lpString);
BOOL    FastGetProfileIntFromID(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, UINT idKey, int def, PINT pResult, DWORD dwPolicyOnly);
DWORD   FastGetProfileStringFromIDW(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, UINT idKey, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD cch, DWORD dwPolicyOnly);
BOOL    FastWriteProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName, UINT uType, LPBYTE lpStruct, UINT cbSizeStruct);
DWORD   FastGetProfileValue(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, LPCWSTR lpKeyName,LPBYTE lpDefault, LPBYTE lpReturn, UINT cbSizeReturn, DWORD dwPolicyOnly);
BOOL    FastGetProfileIntsW(PUNICODE_STRING pProfileUserName OPTIONAL, PPROFINTINFO ppii, DWORD dwPolicyOnly);
BOOL    FastUpdateWinIni(PUNICODE_STRING pProfileUserName OPTIONAL, UINT idSection, UINT wKeyNameId, LPWSTR lpszValue);

VOID RecreateSmallIcons(PWND pwnd);

/*
 * # of pels added to border width. When a user requests a border width of 1
 * that user actualy gets a border width of BORDER_EXTRA + 1 if the window
 * has a sizing border.
 */
#define BORDER_EXTRA    3

/*
 * tmswitch.c stuff
 */

__inline int GetCaptionHeight(
    PWND pwnd)
{
    if (!TestWF(pwnd, WFCPRESENT)) {
        return 0;
    } else {
        return TestWF(pwnd, WEFTOOLWINDOW) ?
                   SYSMET(CYSMCAPTION) : SYSMET(CYCAPTION);
    }
}

__inline VOID InitTooltipDelay(
    PTOOLTIPWND pttwnd)
{
    if (pttwnd != NULL) {
        pttwnd->dwShowDelay = gdtDblClk * 3;
        pttwnd->dwHideDelay = gdtDblClk * 8;
    }
}

__inline PPROFILEVALUEINFO UPDWORDPointer(
    UINT uSetting)
{
    UserAssert(UPIsDWORDRange(uSetting));
    return gpviCPUserPreferences + UPDWORDIndex(uSetting);
}


/*
 * ComputeTickDelta
 *
 * ComputeTickDelta computes a time delta between two times. The
 * delta is defined as a 31-bit, signed value. It is best to think of time as
 * a clock that wraps around. The delta is the minimum distance on this circle
 * between two different places on the circle. If the delta goes
 * counter-clockwise, it is looking at a time in the PAST and is POSITIVE. If
 * the delta goes clockwise, it is looking at a time in the FUTURE and is
 * negative.
 *
 * It is IMPORTANT to realize that the (dwCurTime >= dwLastTime) comparison does
 * not determine the delta's sign, but only determines the operation to compute
 * the delta without an overflow occuring.
 */
__inline
int ComputeTickDelta(
        IN DWORD dwCurTick,
        IN DWORD dwLastTick)
{
    return (int) dwCurTick - dwLastTick;
}


__inline
DWORD ComputePastTickDelta(
        IN DWORD dwCurTick,
        IN DWORD dwLastTick)
{
    /*
     * This handles a wrap-around.
     */
    return dwCurTick - dwLastTick;
}

__inline BOOL IsTimeFromLastInput(
    DWORD dwTimeout)
{
    return ((NtGetTickCount() - glinp.timeLastInputMessage) > dwTimeout);
}

__inline BOOL IsTimeFromLastRITEvent(
    DWORD dwTimeout)
{
    return ((NtGetTickCount() - gpsi->dwLastRITEventTickCount) > dwTimeout);
}

#if DBG
__inline void DBGIncModalMenuCount(
    VOID)
{
    guModalMenuStateCount++;
}

__inline VOID DBGDecModalMenuCount(
    VOID)
{
    UserAssert(guModalMenuStateCount != 0);
    guModalMenuStateCount--;
}
#else
#define DBGIncModalMenuCount()
#define DBGDecModalMenuCount()
#endif

__inline BOOL IsForegroundLocked(
    VOID)
{
    return (guSFWLockCount != 0 || gppiLockSFW != NULL);
}


/* Bug 247768 - joejo
 * Add compatibility hack for foreground activation problems.
 *
 */
__inline
BOOL GiveUpForeground(
    VOID)
{
    if (gptiForeground == NULL) {
        return FALSE;
    }

    if (GetAppCompatFlags2ForPti(gptiForeground, VER40) & GACF2_GIVEUPFOREGROUND){
        TAGMSG0(DBGTAG_FOREGROUND, "GiveUpForeground Hack Succeeded!");
        return TRUE;
    }

    return FALSE;
}

__inline VOID IncSFWLockCount(
    VOID)
{
    guSFWLockCount++;
}

__inline VOID DecSFWLockCount(
    VOID)
{
    UserAssert(guSFWLockCount != 0);
    guSFWLockCount--;
}

__inline DWORD UPDWORDValue(
    UINT uSetting)
{
    return UPDWORDPointer(uSetting)->dwValue;
}
/*
 * Use this macro ONLY if UPIsDWORDRange(SPI_GET ## uSetting) is TRUE.
 */
#define UP(uSetting) UPDWORDValue(SPI_GET ## uSetting)

/*
 * NTIMM.C
 */

#define IMESHOWSTATUS_NOTINITIALIZED    ((BOOL)0xffff)

PIMC CreateInputContext(
    IN ULONG_PTR dwClientImcData);

BOOL DestroyInputContext(
    IN PIMC pImc);

VOID FreeInputContext(
    IN PIMC pImc);

HIMC AssociateInputContext(
    IN PWND pWnd,
    IN PIMC pImc);

AIC_STATUS AssociateInputContextEx(
    IN PWND  pWnd,
    IN PIMC  pImc,
    IN DWORD dwFlag);

BOOL UpdateInputContext(
    IN PIMC pImc,
    IN UPDATEINPUTCONTEXTCLASS UpdateType,
    IN ULONG_PTR UpdateValue);

VOID xxxFocusSetInputContext(
    IN PWND pwnd,
    IN BOOL fActivate,
    IN BOOL fQueueMsg);

UINT BuildHimcList(
    PTHREADINFO pti,
    UINT cHimcMax,
    HIMC *phimcFirst);

PWND xxxCreateDefaultImeWindow(
    IN PWND pwnd,
    IN ATOM atomT,
    IN HANDLE hInst);

BOOL xxxImmActivateThreadsLayout(
    PTHREADINFO pti,
    PTLBLOCK    ptlBlockPrev,
    PKL         pkl);

VOID xxxImmActivateAndUnloadThreadsLayout(
    IN PTHREADINFO *ptiList,
    IN UINT         nEntries,
    IN PTLBLOCK     ptlBlockPrev,
    PKL             pklCurrent,
    DWORD           dwHklReplace);

VOID xxxImmActivateLayout(
    IN PTHREADINFO pti,
    IN PKL pkl);

VOID xxxImmUnloadThreadsLayout(
    IN PTHREADINFO *ptiList,
    IN UINT         nEntry,
    IN PTLBLOCK     ptlBlockPrev,
    IN DWORD        dwFlag);

VOID xxxImmUnloadLayout(
    IN PTHREADINFO pti,
    IN DWORD       dwFlag);

PIMEINFOEX xxxImmLoadLayout(
    IN HKL hKL);

VOID xxxImmActivateLayout(
    IN PTHREADINFO pti,
    IN PKL pkl);

BOOL GetImeInfoEx(
    IN PWINDOWSTATION pwinsta,
    IN PIMEINFOEX piiex,
    IN IMEINFOEXCLASS SearchType);

BOOL SetImeInfoEx(
    IN PWINDOWSTATION pwinsta,
    IN PIMEINFOEX piiex);

DWORD xxxImmProcessKey(
    IN PQ   pq,
    IN PWND pwnd,
    IN UINT message,
    IN WPARAM wParam,
    IN LPARAM lParam);

BOOL GetImeHotKey(
    DWORD dwHotKeyID,
    PUINT puModifiers,
    PUINT puVKey,
    HKL   *phKL );

BOOL  SetImeHotKey(
    DWORD  dwHotKeyID,
    UINT   uModifiers,
    UINT   uVKey,
    HKL    hKL,
    DWORD  dwAction );

PIMEHOTKEYOBJ CheckImeHotKey(
    PQ   pq,
    UINT uVKey,
    LPARAM lParam);

BOOL ImeCanDestroyDefIME(
    IN PWND pwndDefaultIme,
    IN PWND pwndDestroy);

BOOL IsChildSameThread(
    IN PWND pwndParent,
    IN PWND pwndChild);

BOOL ImeCanDestroyDefIMEforChild(
    IN PWND pwndDefaultIme,
    IN PWND pwndDestroy);

VOID ImeCheckTopmost(
    IN PWND pwnd);

VOID ImeSetFutureOwner(
    IN PWND pwndDefaultIme,
    IN PWND pwndOrgOwner);

VOID ImeSetTopmostChild(
    IN PWND pwndRoot,
    IN BOOL fFlag);

VOID ImeSetTopmost(
    IN PWND pwndRoot,
    IN BOOL fFlag,
    IN PWND pwndInsertBefore);

PSOFTKBDDATA ProbeAndCaptureSoftKbdData(
    PSOFTKBDDATA Source);

VOID xxxNotifyIMEStatus(
    IN PWND pwnd,
    IN DWORD dwOpen,
    IN DWORD dwConversion );

BOOL xxxSetIMEShowStatus(
    IN BOOL fShow);

VOID xxxBroadcastImeShowStatusChange(
    IN PWND pwndDefIme,
    IN BOOL fShow);

VOID xxxCheckImeShowStatusInThread(
    IN PWND pwndDefIme);


#define IsWndImeRelated(pwnd)   \
    (pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME] || \
     TestCF(pwnd, CFIME))

/*
 * Critical section routines for processing mouse input
 */
__inline VOID EnterMouseCrit(
    VOID)
{

    KeEnterCriticalRegion();
    ExAcquireResourceExclusiveLite(gpresMouseEventQueue, TRUE);
}

__inline VOID LeaveMouseCrit(
    VOID)
{

    ExReleaseResourceLite(gpresMouseEventQueue);
    KeLeaveCriticalRegion();
}

#if DBG
#define EnterDeviceInfoListCrit _EnterDeviceInfoListCrit
#define LeaveDeviceInfoListCrit _LeaveDeviceInfoListCrit
VOID _EnterDeviceInfoListCrit();
VOID _LeaveDeviceInfoListCrit();
#else
/*
 * Critical section routines for accessing the Device List (gpDeviceInfoList)
 */
__inline VOID EnterDeviceInfoListCrit(
    VOID)
{
    KeEnterCriticalRegion();
    ExAcquireResourceExclusiveLite(gpresDeviceInfoList, TRUE);
}
__inline VOID LeaveDeviceInfoListCrit(
    VOID)
{
    ExReleaseResourceLite(gpresDeviceInfoList);
    KeLeaveCriticalRegion();
}
#endif // DBG

#define BEGIN_REENTER_DEVICEINFOLISTCRIT()                              \
{                                                                       \
    BOOL fAlreadyHadDeviceInfoCrit;                                     \
                                                                        \
    /*                                                                  \
     * If we're not in the user crit then acquire it.                   \
     */                                                                 \
    fAlreadyHadDeviceInfoCrit = ExIsResourceAcquiredExclusiveLite(gpresDeviceInfoList); \
    if (fAlreadyHadDeviceInfoCrit == FALSE) {                           \
        EnterDeviceInfoListCrit();                                      \
    }

#define END_REENTER_DEVICEINFOLISTCRIT()                                \
    if (fAlreadyHadDeviceInfoCrit == FALSE) {                           \
       LeaveDeviceInfoListCrit();                                       \
    }                                                                   \
}


/*
 * Request RIT to update the keyboard h/w settings
 */
__inline VOID RequestKeyboardRateUpdate(
    VOID)
{
    gdwUpdateKeyboard |= UPDATE_KBD_TYPEMATIC;
}



/*
 * Keep some capture state visible from user-mode for performance.
 */
__inline VOID LockCaptureWindow(
    PQ pq,
    PWND pwnd)
{
    if (pq->spwndCapture) {
        UserAssert(gpsi->cCaptures > 0);
        gpsi->cCaptures--;
    }

    if (pwnd) {
        gpsi->cCaptures++;
    }

    Lock(&pq->spwndCapture, pwnd);
}

__inline VOID UnlockCaptureWindow(
    PQ pq)
{
    if (pq->spwndCapture) {
        UserAssert(gpsi->cCaptures > 0);
        gpsi->cCaptures--;
        Unlock(&pq->spwndCapture);
    }
}

/*
 * Some routines for manipulating desktop and windowstation handles.
 */
#define HF_DESKTOPHOOK  0       // offset to desktop hook flag
#define HF_PROTECTED    1       // offset to protected flag
#define HF_LIMIT        2       // number of flags per handle

BOOL SetHandleFlag(HANDLE hObject, DWORD dwFlag, BOOL fSet);
BOOL CheckHandleFlag(PEPROCESS Process, DWORD dwSessionId, HANDLE hObject, DWORD dwFlag);
VOID SetHandleInUse(HANDLE hObject);
BOOL CheckHandleInUse(HANDLE hObject);

__inline NTSTATUS CloseProtectedHandle(
    HANDLE handle)
{
    if (handle != NULL) {
        SetHandleFlag(handle, HF_PROTECTED, FALSE);
        return ZwClose(handle);
    }

    return STATUS_SUCCESS;
}

__inline VOID EnterHandleFlagsCrit(
    VOID)
{
    KeEnterCriticalRegion();
    ExAcquireFastMutexUnsafe(gpHandleFlagsMutex);
}

__inline VOID LeaveHandleFlagsCrit(
    VOID)
{
    ExReleaseFastMutexUnsafe(gpHandleFlagsMutex);
    KeLeaveCriticalRegion();
}

// multimon apis

BOOL    xxxEnumDisplayMonitors(
                HDC             hdc,
                LPRECT          lprcClip,
                MONITORENUMPROC lpfnEnum,
                LPARAM          dwData,
                BOOL            fInternal);

BOOL    xxxClientMonitorEnumProc(
                HMONITOR        hMonitor,
                HDC             hdcMonitor,
                LPRECT          lprc,
                LPARAM          dwData,
                MONITORENUMPROC xpfnProc);

VOID    ClipPointToDesktop(LPPOINT lppt);
VOID    DestroyMonitor(PMONITOR pMonitor);
BOOL    GetHDevName(HMONITOR hMon, PWCHAR pName);
ULONG   HdevFromMonitor(PMONITOR pMonitor);

/*
 * Rebasing functions for shared memory.
 */
#define REBASESHAREDPTR(p)       (p)
#define REBASESHAREDPTRALWAYS(p) (p)

#define PDEV_ENABLED() \
    InterlockedExchange((LPLONG)&gbMDEVDisabled, FALSE);

#define PDEV_DISABLED() \
    InterlockedExchange((LPLONG)&gbMDEVDisabled, TRUE);

__inline BOOL SafeEnableMDEV()
{
    if(gbMDEVDisabled) {
        if (DrvEnableMDEV(gpDispInfo->pmdev, TRUE)) {
            PDEV_ENABLED();
            return TRUE;
        } else {
            return FALSE;
        }
    } else {
        RIPMSG0(RIP_WARNING, "Trying to enable an enabled MDEV");
        return TRUE;
    }
}

__inline BOOL SafeDisableMDEV()
{
    if(!gbMDEVDisabled) {
        if (DrvDisableMDEV(gpDispInfo->pmdev, TRUE)) {
            PDEV_DISABLED();
            return TRUE;
        } else {
            return FALSE;
        }
    } else {
        RIPMSG0(RIP_WARNING, "Trying to disable a disabled MDEV");
        return TRUE;
    }
}

/*
 * Multimonitor macros used in RTL. There are similar definitions
 * in client\usercli.h
 */
__inline PDISPLAYINFO
GetDispInfo(
    VOID)
{
    return gpDispInfo;
}

__inline PMONITOR
GetPrimaryMonitor(
    VOID)
{
    return REBASESHAREDPTRALWAYS(GetDispInfo()->pMonitorPrimary);
}

VOID _QueryUserHandles(
        IN  LPDWORD     lpIn,
        IN  DWORD       dwInLength,
        OUT DWORD       pdwResult[][TYPE_CTYPES]);



#define REMOVE_FROM_LIST(type, pstart, pitem, next) \
    {                                                           \
        type** pp;                                              \
                                                                \
        for (pp = &pstart; *pp != NULL; pp = &(*pp)->next) {    \
            if (*pp == pitem) {                                 \
                *pp = pitem->next;                              \
                break;                                          \
            }                                                   \
        }                                                       \
    }                                                           \


#define HH_DRIVERENTRY              0x00000001
#define HH_USERINITIALIZE           0x00000002
#define HH_INITVIDEO                0x00000004
#define HH_REMOTECONNECT            0x00000008
#define HH_REMOTEDISCONNECT         0x00000010
#define HH_REMOTERECONNECT          0x00000020
#define HH_REMOTELOGOFF             0x00000040
#define HH_DRIVERUNLOAD             0x00000080
#define HH_GRECLEANUP               0x00000100
#define HH_USERKCLEANUP             0x00000200
#define HH_INITIATEWIN32KCLEANUP    0x00000400
#define HH_ALLDTGONE                0x00000800
#define HH_RITGONE                  0x00001000
#define HH_RITCREATED               0x00002000
#define HH_LOADCURSORS              0x00004000
#define HH_KBDLYOUTGLOBALCLEANUP    0x00008000
#define HH_KBDLYOUTFREEWINSTA       0x00010000
#define HH_CLEANUPRESOURCES         0x00020000
#define HH_DISCONNECTDESKTOP        0x00040000
#define HH_DTQUITPOSTED             0x00080000
#define HH_DTQUITRECEIVED           0x00100000
#define HH_DTWAITONHANDLES          0x00400000

#define HYDRA_HINT(ev)  (gdwHydraHint |= ev)

#if DBG
    VOID TrackAddDesktop(PVOID pDesktop);
    VOID TrackRemoveDesktop(PVOID pDesktop);
    VOID DumpTrackedDesktops(BOOL bBreak);

    #define DbgTrackAddDesktop(pdesk) TrackAddDesktop(pdesk)
    #define DbgTrackRemoveDesktop(pdesk) TrackRemoveDesktop(pdesk)
    #define DbgDumpTrackedDesktops(b) DumpTrackedDesktops(b)
#else
    #define DbgTrackAddDesktop(pdesk)
    #define DbgTrackRemoveDesktop(pdesk)
    #define DbgDumpTrackedDesktops(b)
#endif

#if DBG
    #define TRACE_HYDAPI(m)                                     \
        if (gbTraceHydraApi) {                                  \
            KdPrint(("HYD-%d API: ", gSessionId));              \
            KdPrint(m);                                         \
        }
#else
    #define TRACE_HYDAPI(m)
#endif

#if DBG
    #define TRACE_DESKTOP(m)                                    \
        if (gbTraceDesktop) {                                   \
            KdPrint(("HYD-%d DT ", gSessionId));                \
            KdPrint(m);                                         \
        }
#else
    #define TRACE_DESKTOP(m)
#endif

NTSTATUS
RemoteConnect(
    IN PDOCONNECTDATA pDoConnectData,
    IN ULONG DisplayDriverNameLength,
    IN PWCHAR DisplayDriverName);

NTSTATUS
xxxRemoteDisconnect(
    VOID);

NTSTATUS
xxxRemoteConsoleShadowStop(
    VOID);


NTSTATUS
xxxRemoteReconnect(
    IN PDORECONNECTDATA pDoReconnectData);


NTSTATUS
xxxRemoteNotify(
    IN PDONOTIFYDATA pDoNotifyData);

NTSTATUS
RemoteLogoff(
    VOID);

BOOL
PrepareForLogoff(
    UINT uFlags);

NTSTATUS
xxxRemoteStopScreenUpdates(
    BOOL fDisableGraphics);

VOID xxxPushKeyEvent(
    BYTE  bVk,
    BYTE  bScan,
    DWORD dwFlags,
    DWORD dwExtraInfo);

NTSTATUS
RemoteThinwireStats(
    OUT PVOID Stats);

NTSTATUS
RemoteNtSecurity(
    VOID);

NTSTATUS
xxxRemoteShadowSetup(
    VOID);

NTSTATUS
RemoteShadowStart(
    IN PVOID pThinwireData,
    ULONG ThinwireDataLength);

NTSTATUS
xxxRemoteShadowStop(
    VOID);

NTSTATUS
RemoteShadowCleanup(
    IN PVOID pThinwireData,
    ULONG ThinwireDataLength);

NTSTATUS
xxxRemotePassthruEnable(
    VOID);

NTSTATUS
RemotePassthruDisable(
    VOID);

NTSTATUS
CtxDisplayIOCtl(
    ULONG  DisplayIOCtlFlags,
    PUCHAR pDisplayIOCtlData,
    ULONG  cbDisplayIOCtlData);

DWORD
RemoteConnectState(
    VOID);

BOOL
_GetWinStationInfo(
    WSINFO* pWsInfo);

// from fullscr.c

NTSTATUS
RemoteRedrawRectangle(
    WORD Left,
    WORD Top,
    WORD Right,
    WORD Bottom);

NTSTATUS
RemoteRedrawScreen(
    VOID);

NTSTATUS
RemoteDisableScreen(
    VOID);

// from fekbd.c
VOID
NlsKbdSendIMEProc(
    DWORD dwImeOpen,
    DWORD dwImeConversion);


/*
 * Additional menu functions (dependant on previous inline functions)
 */
__inline BOOL MNIsFlatMenu(
    VOID)
{
    return TestEffectUP(FLATMENU);
}

VOID SetMouseTrails(UINT n);
VOID HideMouseTrails(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam);


#if DBG
#define CheckPublicDC(lpszStr, hdc)                                         \
{                                                                           \
    if (GreGetObjectOwner((HOBJ)hdc, DC_TYPE) == OBJECT_OWNER_PUBLIC) {     \
        RIPMSG1(RIP_ERROR, lpszStr, hdc);                                   \
    }                                                                       \
}
#else
#define CheckPublicDC(lpszStr, hdc)
#endif
#define szMESSAGE   L"Message"

#ifdef LAME_BUTTON
// Lame button constants
#define LBUTTON_DIALOG      0x4
#define LBUTTON_TOPLEVEL    0x8

VOID SetStackTrace(HWND hwnd, PVOID pStackTrace);

__inline BOOL NeedsLameButton(
    PWND pwnd,
    PWND pwndParent)
{
    /*
     * Windows with the WS_EX_TOOLWINDOW style can't have a lame button (see
     * Windows Bug #237648), nor can consoles.
     */
    if (TestWF(pwnd, WEFTOOLWINDOW) || PsGetCurrentProcess() == gpepCSRSS) {
        return FALSE;
    } else if (pwndParent != NULL && GETFNID(pwndParent) == FNID_DESKTOP) {
        return (gdwLameFlags & LBUTTON_TOPLEVEL) != 0;
    } else if (GETFNID(pwnd) == FNID_DIALOG) {
        return (gdwLameFlags & LBUTTON_DIALOG) != 0;
    } else {
        return FALSE;
    }
}
#endif // LAME_BUTTON

#ifdef TRACK_PNP_NOTIFICATION

typedef enum tagPNP_NOTIFICATION_TYPE {
    PNP_NTF_CLASSNOTIFY,
    PNP_NTF_CREATEDEVICEINFO,
    PNP_NTF_FREEDEVICEINFO,
    PNP_NTF_PROCESSDEVICECHANGES,
    PNP_NTF_REQUESTDEVICECHANGE,
    PNP_NTF_DEVICENOTIFY,
    PNP_NTF_FREEDEVICEINFO_DEFERRED,
    PNP_NTF_CLOSEDEVICE,
    PNP_NTF_DEVICENOTIFY_UNLISTED,
    PNP_NTF_UNREGISTER_NOTIFICATION,
    PNP_NTF_UNREGISTER_REMOTE_CANCELLED,
} PNP_NOTIFICATION_TYPE;

typedef struct tagPNP_NOTIFICATION_RECORD {
    UINT iSeq;
    PNP_NOTIFICATION_TYPE type;
    PVOID pKThread;
    PDEVICEINFO pDeviceInfo;
    HANDLE hDeviceInfo;
    UCHAR szPathName[80];
    ULONG_PTR NotificationCode;
    PVOID trace[LOCKRECORD_STACK];
} PNP_NOTIFICATION_RECORD, *PPNP_NOTIFICATION_RECORD;

void CleanupPnpNotificationRecord();

void RecordPnpNotification(
    PNP_NOTIFICATION_TYPE type,
    PDEVICEINFO pDeviceInfo,
    ULONG_PTR NotificationCode);

extern BOOL gfRecordPnpNotification;

#endif // TRACK_PNP_NOTIFICATION

#ifdef SUBPIXEL_MOUSE
VOID BuildMouseAccelerationCurve(
    PMONITOR pMonitor);

VOID DoNewMouseAccel(
    INT *dx,
    INT *dw);

VOID ReadDefaultAccelerationCurves(
    PUNICODE_STRING pProfileUserName);

VOID ResetMouseAccelerationCurves(
    VOID);
#endif // SUBPIXEL_MOUSE

#ifdef AUTORUN_CURSOR
VOID ShowAutorunCursor(
    ULONG ulTimeout);

VOID HideAutorunCursor(
    PWND pwnd,
    UINT message,
    UINT_PTR nID,
    LPARAM lParam);
#endif // AUTORUN_CURSOR

/*
 * These must go after globals.h is #include'd, as they're inline functions and
 * they use gptiCurrent (indirectly, by way of ThreadLock()).
 */
__inline VOID ThreadLockMenuNoModify(
    PMENU pMenu,
    PTL ptl)
{
    UserAssert(!TestMF(pMenu, MFREADONLY));
    SetMF(pMenu, MFREADONLY);
    ThreadLock(pMenu, ptl);
}

__inline VOID ThreadLockMenuAlwaysNoModify(
    PMENU pMenu,
    PTL ptl)
{
    UserAssert(!TestMF(pMenu, MFREADONLY));
    SetMF(pMenu, MFREADONLY);
    ThreadLockAlways(pMenu, ptl);
}

__inline VOID ThreadUnlockMenuNoModify (
    PTL ptl)
{
    UserAssert(TestMF((PMENU)ptl->pobj, MFREADONLY));
    ClearMF((PMENU)ptl->pobj, MFREADONLY);
    ThreadUnlock(ptl);
}

__inline int
SetBestStretchMode(
    HDC hdc,
    UINT bpp,
    BOOL fHT)
{
    return GreSetStretchBltMode(
                   hdc,
                   ((fHT) ?
                       HALFTONE : ((bpp == 1) ? BLACKONWHITE : COLORONCOLOR)));
}

#endif  // !_USERK_