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

hungapp.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define CHRLINCR   10

Functions

VOID SetHungFlag (PWND pwnd, WORD wFlag)
VOID ClearHungFlag (PWND pwnd, WORD wFlag)
BOOL FHungApp (PTHREADINFO pti, DWORD dwTimeFromLastRead)
VOID xxxRedrawHungWindowFrame (PWND pwnd, BOOL fActive)
VOID xxxRedrawHungWindow (PWND pwnd, HRGN hrgnFullDrag)
VOID xxxHungAppDemon (PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam)


Define Documentation

#define CHRLINCR   10
 

Definition at line 24 of file hungapp.c.

Referenced by SetHungFlag().


Function Documentation

VOID ClearHungFlag PWND  pwnd,
WORD  wFlag
 

Definition at line 57 of file hungapp.c.

References BOOL, ClrWF, gpvwplHungRedraw, TestWF, VOID(), VWPLRemove(), and WFANYHUNGREDRAW.

Referenced by InternalInvalidate3(), xxxBeginPaint(), xxxDrawCaptionBar(), xxxFreeWindow(), xxxHungAppDemon(), xxxRedrawHungWindow(), and xxxSimpleDoSyncPaint().

00060 { 00061 BOOL fInRedrawList = TestWF(pwnd, WFANYHUNGREDRAW); 00062 00063 ClrWF(pwnd, wFlag); 00064 if (!TestWF(pwnd, WFANYHUNGREDRAW) && fInRedrawList) { 00065 /* 00066 * Remove the window from the redraw list and possibly compact it. 00067 */ 00068 VWPLRemove(&gpvwplHungRedraw, pwnd); 00069 } 00070 }

BOOL FHungApp PTHREADINFO  pti,
DWORD  dwTimeFromLastRead
 

Definition at line 80 of file hungapp.c.

References BOOL, FALSE, tagCLIENTTHREADINFO::fsWakeMask, GET_TIME_LAST_READ, NtGetTickCount(), tagTHREADINFO::pcti, tagTHREADINFO::ppi, and TRUE.

Referenced by IdleTimerProc(), InterQueueMsgCleanup(), NtUserQueryWindow(), xxxButtonEvent(), xxxCallHook2(), xxxDesktopThread(), xxxDesktopWndProc(), xxxHungAppDemon(), xxxInterSendMsgEx(), xxxQueryInformationThread(), xxxRedrawHungWindow(), xxxSendMessageTimeout(), xxxSetForegroundWindow2(), and xxxSimpleDoSyncPaint().

00083 { 00084 00085 /* 00086 * An app is considered hung if it isn't waiting for input, isn't in 00087 * startup processing, and hasn't called PeekMessage() within the 00088 * specified timeout. 00089 */ 00090 if (((NtGetTickCount() - GET_TIME_LAST_READ(pti)) > dwTimeFromLastRead) && 00091 !((pti->pcti->fsWakeMask & QS_INPUT) && (pti->pEThread->Tcb.FreezeCount == 0)) && 00092 !(pti->ppi->W32PF_Flags & W32PF_APPSTARTING)) { 00093 return TRUE; 00094 } 00095 00096 return FALSE; 00097 }

VOID SetHungFlag PWND  pwnd,
WORD  wFlag
 

Definition at line 26 of file hungapp.c.

References CHRLINCR, gpvwplHungRedraw, PWNDDESKTOP, SetWF, tagWND::spwndParent, TestWF, VOID(), VWPLAdd(), and WFANYHUNGREDRAW.

Referenced by InternalInvalidate3(), and xxxSetForegroundWindow2().

00029 { 00030 /* 00031 * If the window has no hung redraw bits set and it's a top-level 00032 * window, add it to the redraw list. 00033 */ 00034 if (!TestWF(pwnd, WFANYHUNGREDRAW) && pwnd->spwndParent == PWNDDESKTOP(pwnd)) { 00035 /* 00036 * Add pwnd to the Hung Redraw Volatile Window Pointer List. 00037 */ 00038 VWPLAdd(&gpvwplHungRedraw, pwnd, CHRLINCR); 00039 } 00040 00041 SetWF(pwnd, wFlag); 00042 }

VOID xxxHungAppDemon PWND  pwnd,
UINT  message,
UINT_PTR  nID,
LPARAM  lParam
 

Definition at line 446 of file hungapp.c.

References CheckLock, ClearHungFlag(), CMSHUNGAPPTIMEOUT, DWORD, FHungApp(), GETPTI, gpvwplHungRedraw, grpdeskRitInput, gtimeStartCursorHide, IdleTimerProc(), NtGetTickCount(), NULL, tagDESKTOP::pDeskInfo, tagDESKTOPINFO::spwnd, TestWF, TestwndFrameOn, ThreadLock, ThreadUnlock, VOID(), VWPLNext(), WFREDRAWFRAMEIFHUNG, WFREDRAWIFHUNG, xxxRedrawHungWindow(), xxxRedrawHungWindowFrame(), and zzzCalcStartCursorHide().

Referenced by StartTimers().

00451 { 00452 TL tlpwnd; 00453 #if DBG 00454 PWND pwndT; 00455 #endif 00456 DWORD nPwndHungRedraw; 00457 PWND pwndHungRedraw; 00458 00459 00460 00461 UNREFERENCED_PARAMETER(message); 00462 UNREFERENCED_PARAMETER(nID); 00463 00464 UNREFERENCED_PARAMETER(lParam); 00465 UNREFERENCED_PARAMETER(pwnd); 00466 CheckLock(pwnd); 00467 00468 /* 00469 * See if we should start the screen saver. 00470 */ 00471 IdleTimerProc(); 00472 00473 /* 00474 * If it is time to hide the app starting cursor, do it. 00475 */ 00476 if (NtGetTickCount() >= gtimeStartCursorHide) { 00477 /* 00478 * No need to DeferWinEventNotify() 00479 */ 00480 zzzCalcStartCursorHide(NULL, 0); 00481 } 00482 00483 /* 00484 * Now check to see if there are any top-level 00485 * windows that need redrawing. 00486 */ 00487 if (grpdeskRitInput == NULL || grpdeskRitInput->pDeskInfo->spwnd == NULL) 00488 return; 00489 00490 /* 00491 * Walk down the list of redraw-if-hung windows. Loop 00492 * until we hit the end of the array or find a NULL. 00493 */ 00494 nPwndHungRedraw = 0; 00495 pwndHungRedraw = NULL; 00496 while (pwndHungRedraw = VWPLNext(gpvwplHungRedraw, pwndHungRedraw, &nPwndHungRedraw)) { 00497 /* 00498 * See if the app is hung. If so, do the appropriate 00499 * redrawing. 00500 */ 00501 if (FHungApp(GETPTI(pwndHungRedraw), CMSHUNGAPPTIMEOUT)) { 00502 ThreadLock(pwndHungRedraw, &tlpwnd); 00503 if (TestWF(pwndHungRedraw, WFREDRAWFRAMEIFHUNG)) { 00504 00505 /* 00506 * WFREDRAWFRAMEIFHUNG will be cleared in the process 00507 * of drawing the frame, no need to clear it here. 00508 */ 00509 xxxRedrawHungWindowFrame(pwndHungRedraw, TestwndFrameOn(pwndHungRedraw)); 00510 } 00511 00512 if (TestWF(pwndHungRedraw, WFREDRAWIFHUNG)) { 00513 ClearHungFlag(pwndHungRedraw, WFREDRAWIFHUNG); 00514 xxxRedrawHungWindow(pwndHungRedraw, NULL); 00515 } 00516 #if DBG 00517 pwndT = 00518 #endif 00519 00520 ThreadUnlock(&tlpwnd); 00521 } 00522 } 00523 00524 return; 00525 }

VOID xxxRedrawHungWindow PWND  pwnd,
HRGN  hrgnFullDrag
 

Definition at line 135 of file hungapp.c.

References _GetDCEx(), _GetWindowLong, _ReleaseDC(), tagCLS::atomClassName, BEGINATOMICCHECK, CheckCritIn, CheckLock, ClearHungFlag(), CMSHUNGAPPTIMEOUT, CopyRect, CopyRgn, CreateEmptyRgn(), DWORD, ENDATOMICCHECK, FHungApp(), FillRect(), gatomConsoleClass, GetCurrentProcessId, GETPTI, ghbrHungApp, ghrgnInv2, tagWND::head, HRGN_FULL, tagWND::hrgnUpdate, IntersectRect(), IntersectRgn, NULL, OffsetRect(), tagWND::pcls, PWNDDESKTOP, tagWND::rcWindow, SetRectRgnIndirect(), SetWF, tagWND::spwndChild, tagWND::spwndNext, SYSHBR, SYSHBRUSH, TestWF, TestwndFrameOn, ThreadLock, ThreadLockExchangeAlways(), ThreadLockNever, ThreadUnlock, TRUE, UINT, VOID(), WFCLIPCHILDREN, WFCLIPSIBLINGS, WFDESTROYED, WFDIALOGWINDOW, WFREDRAWIFHUNG, WFSENDERASEBKGND, WFSENDNCPAINT, WFSTARTPAINT, WFUPDATEDIRTY, WFVISIBLE, WFWIN40COMPAT, WINDOW, xxxCalcClientRect(), xxxDrawWindowFrame(), xxxInternalInvalidate(), and xxxInternalPaintDesktop().

Referenced by xxxHungAppDemon(), xxxSimpleDoSyncPaint(), and xxxUpdateOtherThreadsWindows().

00138 { 00139 HDC hdc; 00140 HBRUSH hbr; 00141 HRGN hrgnUpdate; 00142 RECT rc; 00143 TL tlpwnd; // should remove (IanJa) 00144 UINT flags; 00145 W32PID sid; 00146 DWORD dwColor; 00147 PWND pwndDesk; 00148 TL tlpwndDesk; 00149 00150 CheckCritIn(); 00151 CheckLock(pwnd); 00152 00153 if (pwnd->hrgnUpdate == NULL) { 00154 return; 00155 } 00156 00157 #ifdef HUNGAPP_GHOSTING 00158 00159 /* 00160 * Don't bother doing anything here when the window isn't even visible. 00161 */ 00162 if (!TestWF(pwnd, WFVISIBLE)) { 00163 return; 00164 } 00165 00166 /* 00167 * This function can be called from the full-drag code to quick redraw 00168 * windows that aren't hung. In that case check if that thread is hung. 00169 */ 00170 if ((hrgnFullDrag == NULL) || (hrgnFullDrag != NULL && 00171 FHungApp(GETPTI(pwnd), CMSHUNGAPPTIMEOUT))) { 00172 SignalGhost(pwnd); 00173 } 00174 00175 #endif // HUNGAPP_GHOSTING 00176 00177 /* 00178 * First calculate hrgnUpdate. 00179 */ 00180 if (pwnd->hrgnUpdate > HRGN_FULL) { 00181 hrgnUpdate = CreateEmptyRgn(); 00182 if (hrgnUpdate == NULL) { 00183 hrgnUpdate = HRGN_FULL; 00184 00185 } else if (CopyRgn(hrgnUpdate, pwnd->hrgnUpdate) == ERROR) { 00186 GreDeleteObject(hrgnUpdate); 00187 hrgnUpdate = HRGN_FULL; 00188 } 00189 00190 } else { 00191 00192 /* 00193 * For our purposes, we need a real hrgnUpdate, so try and 00194 * create one if even if the entire window needs updating. 00195 */ 00196 CopyRect(&rc, &pwnd->rcWindow); 00197 hrgnUpdate = GreCreateRectRgnIndirect(&rc); 00198 if (hrgnUpdate == NULL) { 00199 hrgnUpdate = HRGN_FULL; 00200 } 00201 } 00202 00203 /* 00204 * If we're redrawing because we're full dragging and if the window's 00205 * update region does not intersect with the Full drag 00206 * update region, don't erase the hung window again. This is to prevent 00207 * flickering when a window has been invalidated by another window doing 00208 * full drag and hasn't received the paint message yet. 00209 * This way, only if there is a new region that has been invalidated will 00210 * we redraw the hung window. 00211 */ 00212 if (hrgnFullDrag && hrgnUpdate != HRGN_FULL && 00213 IntersectRgn(hrgnUpdate, hrgnUpdate, hrgnFullDrag) == NULLREGION) { 00214 GreDeleteObject(hrgnUpdate); 00215 return; 00216 } 00217 00218 ThreadLock(pwnd, &tlpwnd); // should remove (IanJa) 00219 00220 hdc = _GetDCEx(pwnd, hrgnUpdate, DCX_USESTYLE | DCX_WINDOW | 00221 DCX_INTERSECTRGN | DCX_NODELETERGN | DCX_LOCKWINDOWUPDATE); 00222 xxxDrawWindowFrame(pwnd, hdc, TRUE, TestwndFrameOn(pwnd)); 00223 _ReleaseDC(hdc); 00224 00225 CopyRect(&rc, &pwnd->rcWindow); 00226 xxxCalcClientRect(pwnd, &rc, TRUE); 00227 SetRectRgnIndirect(ghrgnInv2, &rc); 00228 00229 if (hrgnUpdate > HRGN_FULL) { 00230 switch (IntersectRgn(hrgnUpdate, hrgnUpdate, ghrgnInv2)) { 00231 00232 case ERROR: 00233 GreDeleteObject(hrgnUpdate); 00234 hrgnUpdate = HRGN_FULL; 00235 break; 00236 00237 case NULLREGION: 00238 /* 00239 * There is nothing in the client area to repaint. 00240 * Blow the region away, and decrement the paint count 00241 * if possible. 00242 */ 00243 GreDeleteObject(hrgnUpdate); 00244 hrgnUpdate = NULL; 00245 break; 00246 } 00247 } 00248 00249 /* 00250 * Erase the rest of the window. 00251 * When pwnd isn't WFCLIPCHILDREN, make sure valid children bits 00252 * don't get overwritten if the child is in the middle of BeginPaint 00253 * or just completed it's painting and it's hrgnUpdate is NULL. 00254 */ 00255 if (hrgnUpdate != NULL && !TestWF(pwnd, WFCLIPCHILDREN)) { 00256 RECT rcT; 00257 PWND pwndT; 00258 00259 if (hrgnUpdate == HRGN_FULL) { 00260 rc = pwnd->rcWindow; 00261 } else { 00262 GreGetRgnBox(hrgnUpdate, &rc); 00263 } 00264 00265 for (pwndT = pwnd->spwndChild; pwndT != NULL; 00266 pwndT = pwndT->spwndNext) { 00267 00268 if (TestWF(pwndT, WFVISIBLE) && 00269 (TestWF(pwndT, WFSTARTPAINT) || pwndT->hrgnUpdate == NULL) && 00270 IntersectRect(&rcT, &rc, &pwndT->rcWindow)) { 00271 00272 /* 00273 * This invalidate call won't leave the critial section. In 00274 * reality the entire xxxRedrawHungWindow must not leave 00275 * the critical section. 00276 */ 00277 BEGINATOMICCHECK(); 00278 xxxInternalInvalidate(pwndT, hrgnUpdate, RDW_INVALIDATE | 00279 RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN); 00280 ENDATOMICCHECK(); 00281 } 00282 } 00283 } 00284 00285 /* 00286 * Get a window dc so that the menu and scroll bar areas are erased 00287 * appropriately. But make sure it is clipped so that the children 00288 * get clipped out correctly! If we don't do this, this we could erase 00289 * children that aren't invalid. 00290 * 00291 * Note: DCX_WINDOW and DCX_USESTYLE will never clip out children. 00292 * Need to pass the clipping styles in directly, instead of passing 00293 * DCX_USESTYLE. 00294 */ 00295 flags = DCX_INTERSECTRGN | DCX_WINDOW | DCX_CACHE; 00296 if (TestWF(pwnd, WFCLIPSIBLINGS)) 00297 flags |= DCX_CLIPSIBLINGS; 00298 if (TestWF(pwnd, WFCLIPCHILDREN)) 00299 flags |= DCX_CLIPCHILDREN; 00300 00301 hdc = _GetDCEx(pwnd, hrgnUpdate, flags); 00302 00303 if (pwnd == pwnd->head.rpdesk->pDeskInfo->spwndBkGnd) { 00304 pwndDesk = PWNDDESKTOP(pwnd); 00305 ThreadLock(pwndDesk, &tlpwndDesk); 00306 xxxInternalPaintDesktop(PWNDDESKTOP(pwnd), hdc, TRUE); 00307 ThreadUnlock(&tlpwndDesk); 00308 00309 } else { 00310 00311 rc = pwnd->rcWindow; 00312 00313 OffsetRect(&rc, -pwnd->rcWindow.left, -pwnd->rcWindow.top); 00314 00315 /* 00316 * Erase the rest of the window using the window' class background 00317 * brush. 00318 */ 00319 if ((hbr = pwnd->pcls->hbrBackground) != NULL) { 00320 if (hbr <= (HBRUSH)COLOR_ENDCOLORS + 1) 00321 hbr = SYSHBRUSH((ULONG_PTR)hbr - 1); 00322 } else { 00323 /* 00324 * Use the window brush for windows and 3.x dialogs, 00325 * Use the COLOR3D brush for 4.x dialogs. 00326 */ 00327 if (TestWF(pwnd, WFDIALOGWINDOW) && TestWF(pwnd, WFWIN40COMPAT)) 00328 hbr = SYSHBR(3DFACE); 00329 else 00330 hbr = SYSHBR(WINDOW); 00331 } 00332 00333 /* 00334 * If the window's class background brush is public, use it. 00335 */ 00336 sid = (W32PID)GreGetObjectOwner((HOBJ)hbr, BRUSH_TYPE); 00337 if (sid == (W32PID)(ULONG_PTR)GetCurrentProcessId() || sid == OBJECT_OWNER_PUBLIC) { 00338 00339 FillRect(hdc, &rc, hbr); 00340 00341 } else { 00342 00343 /* 00344 * The window's class background brush is not public. 00345 * We get its color and set the color of our own public brush and use 00346 * that for the background brush. 00347 */ 00348 00349 /* 00350 * If the window is a console window, get the console background brush. 00351 * This brush will be different than the console class brush if the user 00352 * changed the console background color. 00353 */ 00354 if (gatomConsoleClass == pwnd->pcls->atomClassName) { 00355 00356 dwColor = _GetWindowLong(pwnd, GWL_CONSOLE_BKCOLOR); 00357 00358 } else { 00359 00360 if ((dwColor = GreGetBrushColor(hbr)) == -1) 00361 dwColor = GreGetBrushColor(SYSHBR(WINDOW)); 00362 } 00363 00364 GreSetSolidBrush(ghbrHungApp, dwColor); 00365 00366 FillRect(hdc, &rc, ghbrHungApp); 00367 } 00368 } 00369 _ReleaseDC(hdc); 00370 00371 /* 00372 * The window has been erased and framed. It only did this because the 00373 * app hasn't done it yet: 00374 * 00375 * - the app hasn't erased and frame yet. 00376 * - the app is in the middle of erasing and framing. 00377 * 00378 * The app could not of completed erasing and framing, because the 00379 * WFREDRAWIFHUNG bit is cleared when this successfully completes. 00380 * 00381 * Given that the app may be in the middle of erasing and framing, we 00382 * need to set both the erase and frame bits *again* so it erasing and 00383 * frames over again (if we don't, it never will). If the app hasn't 00384 * done any erasing/framing yet, this is a nop. 00385 */ 00386 SetWF(pwnd, WFSENDNCPAINT); 00387 SetWF(pwnd, WFSENDERASEBKGND); 00388 00389 /* 00390 * Always set WFUPDATEDIRTY: we don't want the app to draw, then stop 00391 * and have the hung app thread draw, and then allow the app to validate 00392 * itself: Mark the update region dirty - cannot be validated until the 00393 * app calls a painting function and acknowledges the update region. 00394 */ 00395 SetWF(pwnd, WFUPDATEDIRTY); 00396 00397 #ifdef WIN95DOESTHIS 00398 /* 00399 * Go through all the children and redraw hung ones too. 00400 */ 00401 if (hrgnFullDrag != NULL) { 00402 PWND pwndT; 00403 TL tlpwndT; 00404 00405 pwndT = pwnd->spwndChild; 00406 ThreadLockNever(&tlpwndT); 00407 while (pwndT) { 00408 00409 if ( TestWF(pwndT, WFREDRAWIFHUNG) && 00410 FHungApp(GETPTI(pwndT), CMSHUNGAPPTIMEOUT)) { 00411 00412 ClearHungFlag(pwndT, WFREDRAWIFHUNG); 00413 ThreadLockExchangeAlways(pwndT, &tlpwndT); 00414 xxxRedrawHungWindow(pwndT, NULL); 00415 } 00416 00417 if (TestWF(pwndT, WFDESTROYED)) { 00418 break; 00419 } 00420 00421 pwndT = pwndT->spwndNext; 00422 } 00423 00424 ThreadUnlock(&tlpwndT); 00425 } 00426 #endif 00427 00428 ThreadUnlock(&tlpwnd); // should remove (IanJa) 00429 }

VOID xxxRedrawHungWindowFrame PWND  pwnd,
BOOL  fActive
 

Definition at line 107 of file hungapp.c.

References _GetDCEx(), _ReleaseDC(), CheckLock, NULL, UINT, VOID(), and xxxDrawCaptionBar().

Referenced by xxxHungAppDemon(), and xxxSetForegroundWindow2().

00110 { 00111 HDC hdc; 00112 UINT wFlags = DC_NC | DC_NOSENDMSG; 00113 00114 CheckLock(pwnd); 00115 00116 if (fActive) 00117 wFlags |= DC_ACTIVE; 00118 00119 hdc = _GetDCEx(pwnd, NULL, DCX_USESTYLE | DCX_WINDOW); 00120 xxxDrawCaptionBar(pwnd, hdc, wFlags); 00121 _ReleaseDC(hdc); 00122 }


Generated on Sat May 15 19:44:06 2004 for test by doxygen 1.3.7