// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved /*--------------------------------------------------------- Filename: window.cpp Written By: B.Rajeev ----------------------------------------------------------*/ #include "precomp.h" #include "common.h" #include "timer.h" #include "window.h" extern HINSTANCE g_hInst ; WindowMapping Window::mapping; CriticalSection Window::window_CriticalSection; UINT Window :: g_TimerMessage = SNMP_WM_TIMER ; UINT Window :: g_SendErrorEvent = SEND_ERROR_EVENT ; UINT Window :: g_OperationCompletedEvent = OPERATION_COMPLETED_EVENT ; UINT Window :: g_MessageArrivalEvent = MESSAGE_ARRIVAL_EVENT ; UINT Window :: g_SentFrameEvent = SENT_FRAME_EVENT ; UINT Window :: g_NullEventId = NULL_EVENT_ID ; UINT Window :: g_DeleteSessionEvent = DELETE_SESSION_EVENT ; BOOL WaitPostMessage ( HWND window , UINT user_msg_id, WPARAM wParam, LPARAM lParam ) { BOOL status = FALSE ; while ( ! status ) { status = :: PostMessage ( window , user_msg_id, wParam, lParam ) ; if ( status ) { return status ; } DWORD lastError = GetLastError () ; if ( lastError != E_OUTOFMEMORY ) { TerminateProcess ( GetCurrentProcess () , lastError ) ; } } return FALSE ; } Window::Window ( char *templateCode, BOOL display ) : window_handle ( NULL ) { // is invalid is_valid = FALSE; // initialize the window Initialize ( templateCode, HandleGlobalEvent, display ) ; // if handle is null, return if ( window_handle == NULL ) return; is_valid = TRUE; } LONG_PTR CALLBACK WindowsMainProc ( HWND hWnd, UINT message , WPARAM wParam , LPARAM lParam ) { return DefWindowProc(hWnd, message, wParam, lParam); } BOOL Window::CreateCriticalSection () { return TRUE ; } void Window::DestroyCriticalSection() { } void Window::Initialize ( char *templateCode, WNDPROC EventHandler, BOOL display ) { WNDCLASS wc ; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.lpfnWndProc = EventHandler ; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ; wc.hInstance = g_hInst ; wc.hIcon = LoadIcon(NULL, IDI_HAND) ; wc.hCursor = LoadCursor(NULL, IDC_ARROW) ; wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ; wc.lpszMenuName = NULL ; wc.lpszClassName = L"templateCode" ; ATOM winClass = RegisterClass ( &wc ) ; if ( ! winClass ) { DWORD t_GetLastError = GetLastError () ; DebugMacro4( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"Window::Initialise: Error = %lx\n" , t_GetLastError ) ; ) } window_handle = CreateWindow ( L"templateCode" , // see RegisterClass() call L"templateCode" , // text for window title bar WS_OVERLAPPEDWINDOW , // window style CW_USEDEFAULT , // default horizontal position CW_USEDEFAULT , // default vertical position CW_USEDEFAULT , // default width CW_USEDEFAULT , // default height NULL , // overlapped windows have no parent NULL , // use the window class menu g_hInst, // instance (0 is used) NULL // pointer not needed ) ; if ( window_handle == NULL ) return; // obtain lock CriticalSectionLock lock(window_CriticalSection); // if cannot obtain lock, destroy the window // since the window cannot be registered, future messages to // it cannot be passed to it for processing if ( !lock.GetLock(INFINITE) ) { DestroyWindow(window_handle); window_handle = NULL; return; } // register the window with the mapping // (HWND,event_handler) try { mapping[window_handle] = this; } catch ( Heap_Exception e_He ) { DestroyWindow(window_handle); window_handle = NULL; return ; } // release lock lock.UnLock(); if ( display == TRUE ) { ShowWindow ( window_handle , SW_SHOW ) ; } } BOOL Window::InitializeStaticComponents() { return CreateCriticalSection(); } void Window::DestroyStaticComponents() { DestroyCriticalSection(); } // it determines the corresponding EventHandler and calls it // with the appropriate parameters LONG_PTR CALLBACK Window::HandleGlobalEvent ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) { LONG_PTR rc = 0 ; // send timer events to the Timer if ( message == WM_TIMER ) { #if 1 UINT timerId = ( UINT ) wParam ; SnmpTimerObject *timerObject ; CriticalSectionLock session_lock(Timer::timer_CriticalSection); if ( !session_lock.GetLock(INFINITE) ) throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ; if ( SnmpTimerObject :: timerMap.Lookup ( timerId , timerObject ) ) { SnmpTimerObject :: TimerNotification ( timerObject->GetHWnd () , timerId ) ; } else { } #else UINT timerId = ( UINT ) wParam ; SnmpTimerObject *timerObject ; CriticalSectionLock session_lock(Timer::timer_CriticalSection); if ( !session_lock.GetLock(INFINITE) ) throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ; if ( SnmpTimerObject :: timerMap.Lookup ( timerId , timerObject ) ) { Timer::HandleGlobalEvent(timerObject->GetHWnd (), Timer :: g_SnmpWmTimer, timerId, lParam); } else { } #endif return rc ; } if ( message == Timer :: g_SnmpWmTimer ) { Timer::HandleGlobalEvent( hWnd, message, wParam, (DWORD)lParam ); return rc; } Window *window; // obtain lock CriticalSectionLock lock(window_CriticalSection); // if cannot obtain lock, print a debug error message // and return if ( !lock.GetLock(INFINITE) ) { DebugMacro4( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"Window::HandleGlobalEvent: ignoring window message (unable to obtain lock)\n" ) ; ) return rc; } BOOL found = mapping.Lookup(hWnd, window); // release lock lock.UnLock(); // if no such window, return if ( !found ) return DefWindowProc(hWnd, message, wParam, lParam); // let the window handle the event return window->HandleEvent(hWnd, message, wParam, lParam); } // calls the default handler // a deriving class may override this, but // must call this method explicitly for default // case handling LONG_PTR Window::HandleEvent ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) { return DefWindowProc ( hWnd , message , wParam , lParam ); } bool WaitLock ( CriticalSectionLock &a_Lock , BOOL a_WaitCritical = TRUE ) { SetStructuredExceptionHandler t_StructuredException ; BOOL t_Do ; do { try { a_Lock.GetLock(INFINITE) ; return true ; } catch ( Structured_Exception & t_StructuredException ) { #ifdef DBG OutputDebugString ( L"CriticalSection exception" ) ; #endif t_Do = a_WaitCritical ; if ( t_Do ) { Sleep ( 1000 ) ; } if ( t_StructuredException.GetSENumber () == STATUS_NO_MEMORY ) { } else { return false ; } } catch ( ... ) { return false ; } } while ( t_Do ) ; return true ; } Window::~Window(void) { if ( window_handle != NULL ) { // obtain lock CriticalSectionLock lock(window_CriticalSection); if ( WaitLock ( lock ) ) { mapping.RemoveKey(window_handle); } else { throw GeneralException ( Snmp_Error , Snmp_Local_Error,__FILE__,__LINE__ ) ; } // release lock lock.UnLock(); DestroyWindow(window_handle); UnregisterClass ( L"templateCode" , 0 ) ; } } BOOL Window::PostMessage( UINT user_msg_id, WPARAM wParam, LPARAM lParam ) { return WaitPostMessage(GetWindowHandle(), user_msg_id, wParam, lParam); }