PRB: JournalPlayback Hook Can Cause Windows NT to HangLast reviewed: September 29, 1995Article ID: Q124835 |
The information in this article applies to:
SYMPTOMSIncorrect use of the delay return value from a journal playback hook can cause Windows NT to hang temporarily.
CAUSEThe menu loop in Windows NT calls PeekMessage() with the PM_NOREMOVE flag, does some processing, and then removes the message from the queue. This sequence is repeated until the menu goes away. When JournalPlayback is occurring, the PeekMessage( PM_NOREMOVE ) results in a callback to the application's JournalPlaybackProc with an HC_ACTION code. The subsequent PeekMessage( PM_REMOVE ) also calls the JournalPlaybackProc with an HC_ACTION code. If the peek is successful, it is followed by an HC_SKIP callback. In order to have playback from a journal playback hook occur at a certain rate, Microsoft designed it so that the value returned by the JournalPlaybackProc can be non-zero. This value represents the number of clock-ticks the system should wait before processing the event. What the documentation doesn't make clear is that when the delay has expired, another callback to the JournalPlaybackProc is made to obtain the same event again; the event provided with the previous non-zero delay is not used at all. All subsequent HC_ACTION calls that request the same event should be returned with a zero delay value. Only after an HC_SKIP callback has been made, may an HC_ACTION callback return a non-zero delay value again. Some applications do not do this correctly, and simply alternate between returning a delay and returning a non-delay. This alternating delay/no delay method made the Windows NT menu loop hang because the PeekMessage( PM_NOREMOVE ) would get an input event (with no delay), then the PeekMessage( PM_REMOVE ) would get a non-zero return value from the JournalPlaybackProc. This represents no message -- so instead of issuing an HC_SKIP callback to the JournalPlaybackProc to advance to the next event, the Windows NT menu loop code simply looped back to the PeekMessage( PM_NOREMOVE ) getting stuck in an infinite loop.
RESOLUTIONTo work around this problem, make sure the JournalPlaybackProc correctly returns the delay only for the first request for an event. Neither Windows version 3.1 nor Windows 95 have this problem.
STATUSThis behavior is by design.
MORE INFORMATIONThe following sample code demonstrates correct and incorrect methods of handling delays in a journal playback hook.
Sample CodeLRESULT CALLBACK JournalPlaybackProc( int nCode, WPARAM wParam, LPARAM lParam){ static BOOL fDelay; static EVENTMSG event; static LRESULT ticks_delay; BOOL fCallNextHook = FALSE; LRESULT lResult = 0; switch( nCode ) { case HC_SKIP: fDelay = TRUE; // <<<< CORRECT PLACE TO RESET fDelay // Get the next event from the list. If the routine returns // FALSE, then we are done - release the hook. if( !GetNextEvent( &event, &ticks_delay )) SetJournalHook( FALSE, NULL ); break; case HC_GETNEXT: { // Structure information returned from previous GetNextEvent // call LPEVENTMSG lpEvent = (LPEVENTMSG) lParam; // Set the event *lpEvent = event; if( fDelay ) { // Toggle pause variable so that the next call won't // pause. Return the pause length specified by ticks_delay // since this is the first time the event has been // requested. fDelay = FALSE; // <<<< CORRECT PLACE TO CLEAR fDelay return( ticks_delay ); } break; } case HC_SYSMODALOFF: // System modal dialog is going away - something really got // hosed. Windows took care of removing our JournalPlayback // hook, so no need to call SetJournalHook( FALSE ). fCallNextHook = TRUE; break; case HC_SYSMODALON: default: // Something is is not right here, let the next hook handle // it. fCallNextHook = TRUE; break; } // If the event wasn't processed by our code, call next hook if( fCallNextHook ) lResult = CallNextHookEx( s_journalHook, nCode, wParam, lParam ); // fDelay = TRUE; // <<<< WRONG PLACE TO RESET bDelay !!! return lResult;}
|
Additional reference words: 3.10 3.50
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |