reactos/win32ss/user/ntuser/win32.h
Hermès Bélusca-Maïto a8e7defb01
[WIN32SS:USER] Some minimal work and fixes concerning message queues timeouts.
CORE-15147

- Rename CLIENTTHREADINFO::tickLastMsgChecked into timeLastRead as
  documented in https://reactos.org/wiki/Techwiki:Win32k/CLIENTTHREADINFO .
  This is the last time the message queue was read.

- This is the structure member one must compare against the current tick
  count timestamp in order to heuristically determine whether a message
  queue thread is hung!! Fix MsqIsHung() in accordance, add extra debug
  logging in order to help us determining which of our code present
  regular GUI hangs, and add as well an extra "TimeOut" parameter so as
  not to hardcode a fixed value within that function but instead
  allowing its caller to specify possible different values.

- THREADINFO::timeLast is on the contrary the last message time stamp,
  and will definitively differ from CLIENTTHREADINFO::timeLastRead .
  It should only be used for information purposes!

- Accordingly, in NtUserGetThreadState()::THREADSTATE_UPTIMELASTREAD
  and in InitThreadCallback(), only (re-)initialize the timeLastRead
  member of the CLIENTTHREADINFO structure of the THREADINFO of interest.

- In co_IntPeekMessage(), update more often the timeLastRead timestamp
  whenever the current message queue has been read (but NOT timeLast!!
  That one will be updated ONLY WHEN a message is found!).

- In co_IntSendMessageTimeoutSingle() first check whether the window to
  which we send the message is being destroyed, before checking for
  queue hangs etc. Collapse the logic checks for queue hang and increase
  the hang timeout check to 4 times MSQ_HUNG (== 4 * 5 seconds) and
  display a debug trace.
2019-12-29 16:14:15 +01:00

313 lines
9.1 KiB
C

#pragma once
/* W32PROCESS flags */
#define W32PF_CONSOLEAPPLICATION 0x00000001
#define W32PF_FORCEOFFFEEDBACK 0x00000002
#define W32PF_STARTGLASS 0x00000004
#define W32PF_WOW 0x00000008
#define W32PF_READSCREENACCESSGRANTED 0x00000010
#define W32PF_INITIALIZED 0x00000020
#define W32PF_APPSTARTING 0x00000040
#define W32PF_WOW64 0x00000080
#define W32PF_ALLOWFOREGROUNDACTIVATE 0x00000100
#define W32PF_OWNDCCLEANUP 0x00000200
#define W32PF_SHOWSTARTGLASSCALLED 0x00000400
#define W32PF_FORCEBACKGROUNDPRIORITY 0x00000800
#define W32PF_TERMINATED 0x00001000
#define W32PF_CLASSESREGISTERED 0x00002000
#define W32PF_THREADCONNECTED 0x00004000
#define W32PF_PROCESSCONNECTED 0x00008000
#define W32PF_SETFOREGROUNDALLOWED 0x00008000
#define W32PF_WAKEWOWEXEC 0x00010000
#define W32PF_WAITFORINPUTIDLE 0x00020000
#define W32PF_IOWINSTA 0x00040000
#define W32PF_CONSOLEFOREGROUND 0x00080000
#define W32PF_OLELOADED 0x00100000
#define W32PF_SCREENSAVER 0x00200000
#define W32PF_IDLESCREENSAVER 0x00400000
#define W32PF_ICONTITLEREGISTERED 0x10000000
#define W32PF_DPIAWARE 0x20000000
// ReactOS
#define W32PF_NOWINDOWGHOSTING (0x01000000)
#define W32PF_MANUALGUICHECK (0x02000000)
#define W32PF_CREATEDWINORDC (0x04000000)
#define W32PF_APIHOOKLOADED (0x08000000)
#define QSIDCOUNTS 7
typedef enum _QS_ROS_TYPES
{
QSRosKey = 0,
QSRosMouseMove,
QSRosMouseButton,
QSRosPostMessage,
QSRosSendMessage,
QSRosHotKey,
QSRosEvent,
} QS_ROS_TYPES, *PQS_ROS_TYPES;
extern BOOL ClientPfnInit;
extern HINSTANCE hModClient;
extern HANDLE hModuleWin; // This Win32k Instance.
extern struct _CLS *SystemClassList;
extern BOOL RegisteredSysClasses;
#include <pshpack1.h>
// FIXME: Move to ntuser.h
typedef struct _TL
{
struct _TL* next;
PVOID pobj;
PVOID pfnFree;
} TL, *PTL;
typedef struct _W32THREAD
{
PETHREAD pEThread;
LONG RefCount;
PTL ptlW32;
PVOID pgdiDcattr;
PVOID pgdiBrushAttr;
PVOID pUMPDObjs;
PVOID pUMPDHeap;
DWORD dwEngAcquireCount;
PVOID pSemTable;
PVOID pUMPDObj;
} W32THREAD, *PW32THREAD;
#ifdef __cplusplus
typedef struct _THREADINFO : _W32THREAD
{
#else
typedef struct _THREADINFO
{
W32THREAD;
#endif
PTL ptl;
PPROCESSINFO ppi;
struct _USER_MESSAGE_QUEUE* MessageQueue;
struct tagKL* KeyboardLayout;
struct _CLIENTTHREADINFO * pcti;
struct _DESKTOP* rpdesk;
struct _DESKTOPINFO * pDeskInfo;
struct _CLIENTINFO * pClientInfo;
FLONG TIF_flags;
PUNICODE_STRING pstrAppName;
struct _USER_SENT_MESSAGE *pusmSent;
struct _USER_SENT_MESSAGE *pusmCurrent;
/* Queue of messages sent to the queue. */
LIST_ENTRY SentMessagesListHead; // psmsReceiveList
/* Last message time and ID */
LONG timeLast;
ULONG_PTR idLast;
/* True if a WM_QUIT message is pending. */
BOOLEAN QuitPosted;
/* The quit exit code. */
INT exitCode;
HDESK hdesk;
UINT cPaintsReady; /* Count of paints pending. */
UINT cTimersReady; /* Count of timers pending. */
struct tagMENUSTATE* pMenuState;
DWORD dwExpWinVer;
DWORD dwCompatFlags;
DWORD dwCompatFlags2;
struct _USER_MESSAGE_QUEUE* pqAttach;
PTHREADINFO ptiSibling;
ULONG fsHooks;
struct tagHOOK * sphkCurrent;
LPARAM lParamHkCurrent;
WPARAM wParamHkCurrent;
struct tagSBTRACK* pSBTrack;
/* Set if there are new messages specified by WakeMask in any of the queues. */
HANDLE hEventQueueClient;
/* Handle for the above event (in the context of the process owning the queue). */
PKEVENT pEventQueueServer;
LIST_ENTRY PtiLink;
INT iCursorLevel;
/* Last message cursor position */
POINT ptLast;
INT cEnterCount;
/* Queue of messages posted to the queue. */
LIST_ENTRY PostedMessagesListHead; // mlPost
WORD fsChangeBitsRemoved;
WCHAR wchInjected;
UINT cWindows;
UINT cVisWindows;
#ifndef __cplusplus /// FIXME!
LIST_ENTRY aphkStart[NB_HOOKS];
CLIENTTHREADINFO cti; // Used only when no Desktop or pcti NULL.
/* ReactOS */
/* Thread Queue state tracking */
// Send list QS_SENDMESSAGE
// Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
// Hard list QS_MOUSE|QS_KEY only
// Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
LIST_ENTRY WindowListHead;
LIST_ENTRY W32CallbackListHead;
SINGLE_LIST_ENTRY ReferencesList;
ULONG cExclusiveLocks;
#if DBG
USHORT acExclusiveLockCount[GDIObjTypeTotal + 1];
#endif
#endif // __cplusplus
} THREADINFO;
#include <poppack.h>
#define IntReferenceThreadInfo(pti) \
InterlockedIncrement(&(pti)->RefCount)
VOID UserDeleteW32Thread(PTHREADINFO);
#define IntDereferenceThreadInfo(pti) \
do { \
if (InterlockedDecrement(&(pti)->RefCount) == 0) \
{ \
ASSERT(((pti)->TIF_flags & (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)) == (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)); \
UserDeleteW32Thread(pti); \
} \
} while(0)
#define IntReferenceProcessInfo(ppi) \
InterlockedIncrement((volatile LONG*)(&(ppi)->RefCount))
VOID UserDeleteW32Process(_Pre_notnull_ __drv_freesMem(Mem) PPROCESSINFO);
#define IntDereferenceProcessInfo(ppi) \
do { \
if (InterlockedDecrement((volatile LONG*)(&(ppi)->RefCount)) == 0) \
{ \
ASSERT(((ppi)->W32PF_flags & W32PF_TERMINATED) != 0); \
UserDeleteW32Process(ppi); \
} \
} while(0)
typedef struct _W32HEAP_USER_MAPPING
{
struct _W32HEAP_USER_MAPPING* Next;
PVOID KernelMapping;
PVOID UserMapping;
ULONG_PTR Limit;
ULONG Count;
} W32HEAP_USER_MAPPING, *PW32HEAP_USER_MAPPING;
/*
Information from STARTUPINFOW, psdk/winbase.h.
Set from PsGetCurrentProcess()->Peb->ProcessParameters.
*/
typedef struct tagUSERSTARTUPINFO
{
ULONG cb;
DWORD dwX; // STARTF_USEPOSITION StartupInfo->dwX/Y
DWORD dwY;
DWORD dwXSize; // STARTF_USESIZE StartupInfo->dwX/YSize
DWORD dwYSize;
DWORD dwFlags; // STARTF_ StartupInfo->dwFlags
WORD wShowWindow; // StartupInfo->wShowWindow
USHORT cbReserved2;
} USERSTARTUPINFO, *PUSERSTARTUPINFO;
typedef struct _W32PROCESS
{
PEPROCESS peProcess;
DWORD RefCount;
ULONG W32PF_flags;
PKEVENT InputIdleEvent;
DWORD StartCursorHideTime;
struct _W32PROCESS* NextStart;
PVOID pDCAttrList;
PVOID pBrushAttrList;
DWORD W32Pid;
LONG GDIHandleCount;
LONG UserHandleCount;
PEX_PUSH_LOCK GDIPushLock; /* Locking Process during access to structure. */
RTL_AVL_TABLE GDIEngUserMemAllocTable; /* Process AVL Table. */
LIST_ENTRY GDIDcAttrFreeList;
LIST_ENTRY GDIBrushAttrFreeList;
} W32PROCESS, *PW32PROCESS;
#define CLIBS 32
#ifdef __cplusplus
typedef struct _PROCESSINFO : _W32PROCESS
{
#else
typedef struct _PROCESSINFO
{
W32PROCESS;
#endif
PTHREADINFO ptiList;
PTHREADINFO ptiMainThread;
struct _DESKTOP* rpdeskStartup;
struct _CLS *pclsPrivateList;
struct _CLS *pclsPublicList;
PPROCESSINFO ppiNext;
INT cThreads;
HDESK hdeskStartup;
DWORD dwhmodLibLoadedMask;
HANDLE ahmodLibLoaded[CLIBS];
struct _WINSTATION_OBJECT* prpwinsta;
HWINSTA hwinsta;
ACCESS_MASK amwinsta;
DWORD dwHotkey;
HMONITOR hMonitor;
UINT iClipSerialNumber;
struct _CURICON_OBJECT* pCursorCache;
PVOID pClientBase;
DWORD dwLpkEntryPoints;
PVOID pW32Job;
DWORD dwImeCompatFlags;
LUID luidSession;
USERSTARTUPINFO usi;
DWORD dwLayout;
DWORD dwRegisteredClasses;
/* ReactOS */
FAST_MUTEX PrivateFontListLock;
LIST_ENTRY PrivateFontListHead;
LIST_ENTRY PrivateMemFontListHead;
UINT PrivateMemFontHandleCount;
FAST_MUTEX DriverObjListLock;
LIST_ENTRY DriverObjListHead;
W32HEAP_USER_MAPPING HeapMappings;
struct _GDI_POOL* pPoolDcAttr;
struct _GDI_POOL* pPoolBrushAttr;
struct _GDI_POOL* pPoolRgnAttr;
#if DBG
BYTE DbgChannelLevel[DbgChCount];
#ifndef __cplusplus
DWORD DbgHandleCount[TYPE_CTYPES];
#endif // __cplusplus
#endif // DBG
} PROCESSINFO;
#if DBG
void NTAPI UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments);
ULONG_PTR NTAPI UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult);
#endif
/* Helper function used by some wine code */
__forceinline
int
lstrlenW(
_In_ LPCWSTR lpString)
{
size_t size = wcslen(lpString);
if (size > ULONG_MAX) __fastfail(FAST_FAIL_RANGE_CHECK_FAILURE);
return (int)size;
}
#define strlenW lstrlenW