综述:
xxxRealInternalGetMessage分析之While循环分析----干货第二部分win32k!xxxDoPaint函数分析
scrnsave屏保会调用GetMessage函数
00 win32k!xxxDoPaint
01 win32k!xxxRealInternalGetMessage
02 win32k!NtUserGetMessage
03 nt!_KiSystemService
04 SharedUserData!SystemCallStub
05 USER32!NtUserGetMessage
06 USER32!GetMessageA_wrapper
07 scrnsave!main
08 scrnsave!mainCRTStartup
09 kernel32!BaseProcessStart
位置windows\core\ntuser\kernel
下面只是调用关系。
下一篇具体分析。
第一部分:
/***************************************************************************\
* xxxCompositedTraverse
*使用从最后一个子对象开始的预购遍历来渲染
以自下而上的顺序显示窗口。
*使用从最后一个子窗口开始的按前序遍历来渲染
按照自下而上的顺序打开窗口。
* Uses pre-order traversal starting with the last child to render the
* windows in a bottom-up order.
*
* 9/30/1999 vadimg created
\***************************************************************************/
BOOL xxxCompositedTraverse(PWND pwnd)
{
TL tlpwnd;
BOOL fPainted = FALSE;
CheckLock(pwnd);
if (NEEDSPAINT(pwnd)) {
xxxSendMessage(pwnd, WM_PAINT, 0, 0);
fPainted = TRUE;
}
pwnd = GetLastChild(pwnd);
ThreadLock(pwnd, &tlpwnd);
while (pwnd != NULL) {
if (xxxCompositedTraverse(pwnd)) {
fPainted = TRUE;
}
pwnd = pwnd->spwndPrev;
if (ThreadLockExchange(pwnd, &tlpwnd) == NULL) {
break;
}
}
ThreadUnlock(&tlpwnd);
return fPainted;
}
/***************************************************************************\
* xxxCompositedPaint
* Composited 合成
* 9/30/1999 vadimg created
\***************************************************************************/
VOID xxxCompositedPaint(PWND pwnd)
{
BOOL fPainted;
HBITMAP hbm, hbmOld;
PREDIRECT prdr;
HDC hdc;
LPRECT prc;
SIZE size;
POINT pt;
CheckLock(pwnd);
UserAssert(TestWF(pwnd, WEFCOMPOSITED));
SetWF(pwnd, WEFPCOMPOSITING);
/*
* Render the child windows in a bottom-up order.
*/
fPainted = xxxCompositedTraverse(pwnd);
ClrWF(pwnd, WEFPCOMPOSITING);
/*
* While we were compositing, an invalid region may have accumulated.
* So, let's go and invalidate that area of the window.
*/
BEGINATOMICCHECK();
prdr = _GetProp(pwnd, PROP_LAYER, TRUE);
if (prdr != NULL && prdr->hrgnComp != NULL) {
xxxInternalInvalidate(pwnd, prdr->hrgnComp, RDW_INVALIDATE |
RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
if (prdr->hrgnComp != HRGN_FULL) {
GreDeleteObject(prdr->hrgnComp);
}
prdr->hrgnComp = NULL;
}
ENDATOMICCHECK();
#ifdef REDIRECTION
if (TestWF(pwnd, WEFEXTREDIRECTED)) {
return;
}
#endif // REDIRECTION
BEGINATOMICCHECK();
if (fPainted && TestWF(pwnd, WEFPREDIRECTED)) {
prdr = (PREDIRECT)_GetProp(pwnd, PROP_LAYER, TRUE);
prc = &prdr->rcUpdate;
hbm = prdr->hbm;
UserAssert(hbm != NULL);
if (TestWF(pwnd, WEFLAYERED)) {
hbmOld = GreSelectBitmap(ghdcMem, hbm);
size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left;
size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top;
pt.x = pt.y = 0;
GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, NULL,
&size, ghdcMem, &pt, 0, NULL, ULW_DEFAULT_ATTRIBUTES, prc);
GreSelectBitmap(ghdcMem, hbmOld);
} else {
/*
* Temporarily clear the redirected bit so that we can get the dc
* with proper screen clipping.
*/
ClrWF(pwnd, WEFPREDIRECTED);
hbmOld = GreSelectBitmap(ghdcMem, hbm);
hdc = _GetDCEx(pwnd, NULL, DCX_USESTYLE | DCX_WINDOW | DCX_CACHE);
/*
* Transfer the bits for the window from the redirection bitmap
* to the screen.
*/
GreBitBlt(hdc, prc->left, prc->top, prc->right - prc->left,
prc->bottom - prc->top, ghdcMem,
prc->left, prc->top, SRCCOPY, 0);
_ReleaseDC(hdc);
GreSelectBitmap(ghdcMem, hbmOld);
/*
* Restore the redirection bit on the window.
*/
SetWF(pwnd, WEFPREDIRECTED);
}
SetRectEmpty(prc);
}
ENDATOMICCHECK();
}
第二部分:xxxCompositedPaint函数被xxxInternalDoPaint函数调用
/***************************************************************************\
* InternalDoPaint
*返回当前线程创建的等于或低于pwnd的窗口,这需要绘画。
* Return a window equal to or below pwnd, created by the current thread,
* which needs painting.
*
* pwnd - Window to start searching from. Search is depth first.
* ptiCurrent - The current thread.
*
* History:
* 16-Jul-1991 DarrinM Ported from Win 3.1 sources.
\***************************************************************************/
PWND xxxInternalDoPaint(
PWND pwnd,
PTHREADINFO ptiCurrent)
{
PWND pwndT;
TL tlpwnd;
/*
* Enumerate all windows, top-down, looking for one that
* needs repainting. Skip windows of other tasks.
*/
while (pwnd != NULL) {
if (GETPTI(pwnd) == ptiCurrent) {
if (TestWF(pwnd, WEFCOMPOSITED)) {
ThreadLock(pwnd, &tlpwnd);
xxxCompositedPaint(pwnd);
pwnd = pwnd->spwndNext;
if (ThreadUnlock(&tlpwnd) == NULL) {
return NULL;
}
continue;
} else if (NEEDSPAINT(pwnd)) {
/*
* If this window is transparent, we don't want to
* send it a WM_PAINT until all its siblings below it
* have been repainted. If we find an unpainted sibling
* below, return it instead.
*/
if (TestWF(pwnd, WEFTRANSPARENT)) {
pwndT = pwnd;
while ((pwndT = pwndT->spwndNext) != NULL) {
/*
* Make sure sibling window belongs to same app
*/
if ((GETPTI(pwndT) == ptiCurrent) && NEEDSPAINT(pwndT)) {
if (TestWF(pwndT, WEFTRANSPARENT))
continue;
return pwndT;
}
}
}
return pwnd;
}
}
if (pwnd->spwndChild &&
(pwndT = xxxInternalDoPaint(pwnd->spwndChild, ptiCurrent))) {
return pwndT;
}
pwnd = pwnd->spwndNext;
}
return pwnd;
}
第三部分:xxxInternalDoPaint函数被xxxInternalDoPaint函数递归调用或被xxxDoPaint函数调用
/***************************************************************************\
* DoPaint
*
*查看所有桌面上需要涂漆的窗口,并放置WM_PAINT在其队列中。
* Looks at all the desktops for the window needing a paint and places a
* WM_PAINT in its queue.
*
* History:
* 16-Jul-91 DarrinM Ported from Win 3.1 sources.
\***************************************************************************/
BOOL xxxDoPaint(
PWND pwndFilter,
LPMSG lpMsg)
{
PWND pwnd;
PWND pwndT;
PTHREADINFO ptiCurrent = PtiCurrent();
CheckLock(pwndFilter);
#if 0 // CHRISWIL: WIN95 SPECIFIC
/*
* If there is a system modal up and it is attached to another task,
* DON'T do paints. We don't want to return a message for a window in
* another task!
*/
if (hwndSysModal && (hwndSysModal->hq != hqCurrent)) {
/*
* Poke this guy so he wakes up at some point in the future,
* otherwise he may never wake up to realize he should paint.
* Causes hangs - e.g. Photoshop installation program
* PostThreadMessage32(Lpq(hqCurrent)->idThread, WM_NULL, 0, 0, 0);
*/
return FALSE;
}
#endif
/*
* If this is a system thread, then walk the windowstation desktop-list
* to find the window which needs painting. For other threads, we
* reference off the thread-desktop.
*/
if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) {
PWINDOWSTATION pwinsta;
PDESKTOP pdesk;
if ((pwinsta = ptiCurrent->pwinsta) == NULL) {
RIPMSG0(RIP_ERROR, "DoPaint: SYSTEMTHREAD does not have (pwinsta)");
return FALSE;
}
pwnd = pwinsta->pTerm->spwndDesktopOwner;
if (!NEEDSPAINT(pwnd)) {
pwnd = NULL;
for(pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
if (pwnd = xxxInternalDoPaint(pdesk->pDeskInfo->spwnd, ptiCurrent))
break;
}
}
} else {
pwnd = xxxInternalDoPaint(ptiCurrent->rpdesk->pDeskInfo->spwnd,
ptiCurrent);
}
if (pwnd != NULL) {
if (!CheckPwndFilter(pwnd, pwndFilter))
return FALSE;
/*
* We're returning a WM_PAINT message, so clear WFINTERNALPAINT so
* it won't get sent again later.
*/
if (TestWF(pwnd, WFINTERNALPAINT)) {
ClrWF(pwnd, WFINTERNALPAINT);
/*
* If there is no update region, then no more paint for this
* window.
*/
if (pwnd->hrgnUpdate == NULL)
DecPaintCount(pwnd);
}
/*
* Set the STARTPAINT so that any other calls to BeginPaint while
* painting is begin performed, will prevent painting on those
* windows.
*
* Clear the UPDATEDIRTY since some apps (DBFast) don't call
* GetUpdateRect, BeginPaint/EndPaint.
*/
ClrWF(pwnd, WFSTARTPAINT);
ClrWF(pwnd, WFUPDATEDIRTY);
/*
* If we get an invalidate between now and the time the app calls
* BeginPaint() and the windows parent is not CLIPCHILDREN, then
* the parent will paint in the wrong order. So we are going to
* cause the child to paint again. Look in beginpaint and internal
* invalidate for other parts of this fix.
*
* Set a flag to signify that we are in the bad zone.
*
* Must go up the parent links to make sure all parents have
* WFCLIPCHILDREN set otherwise set the WFWMPAINTSENT flag.
* This is to fix Excel spreadsheet and fulldrag. The speadsheet
* parent window (class XLDESK) has WFCLIPCHILDREN set but it's
* parent (class XLMAIN) doesn't. So the main window erases the
* background after the child window paints.
*
* JOHANNEC : 27-Jul-1994
*/
/*
* NT Bug 400167: As we walk up the tree, we need to stop short of
* desktop windows and mother desktop windows. We can't do a test
* for WFCLIPCHILDREN on the mother desktop window's parent because
* it doesn't exist. This means that no desktop window will get
* WFWMPAINTSENT set, but the message window will be able to get
* WFWMPAINTSENT set.
*/
pwndT = pwnd;
while (pwndT && (GETFNID(pwndT) != FNID_DESKTOP)) {
if (!TestWF(pwndT->spwndParent, WFCLIPCHILDREN)) {
SetWF(pwnd, WFWMPAINTSENT);
break;
}
pwndT = pwndT->spwndParent;
}
/*
* If the top level "tiled" owner/parent of this window is iconed,
* send a WM_PAINTICON rather than a WM_PAINT. The wParam
* is TRUE if this is the tiled window and FALSE if it is a
* child/owned popup of the minimized window.
*
* BACKWARD COMPATIBILITY HACK
*
* 3.0 sent WM_PAINTICON with wParam == TRUE for no apparent
* reason. Lotus Notes 2.1 depends on this for some reason
* to properly change its icon when new mail arrives.
*/
if (!TestWF(pwnd, WFWIN40COMPAT) &&
TestWF(pwnd, WFMINIMIZED) &&
(pwnd->pcls->spicn != NULL)) {
StoreMessage(lpMsg, pwnd, WM_PAINTICON, (DWORD)TRUE, 0L, 0L);
} else {
StoreMessage(lpMsg, pwnd, WM_PAINT, 0, 0L, 0L);
}
return TRUE;
}
return FALSE;
}
第四部分:xxxDoPaint函数被xxxRealInternalGetMessage函数调用
xxxRealInternalGetMessage分析之While循环分析----干货
https://blog.csdn.net/oldlinux/article/details/141813955
BOOL xxxRealInternalGetMessage(
LPMSG lpMsg,
HWND hwndFilter,
UINT msgMin,
UINT msgMax,
UINT flags,
BOOL fGetMessage)
{
。。。。。。
/*
* Does the caller want paint messages? If so, try to find a paint.
*/
if (fsWakeBits & fsWakeMask & QS_PAINT) {
if (xxxDoPaint(pwndFilter, lpMsg)) {
PATHTAKEN(0x100);
break;
}
}
。。。。。。
Error:
PATHTAKEN(0x8000);
DUMPPATHTAKEN();
return fExit;
}