Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1417 lines
37 KiB

//***************************************************************************
//
// File:
//
// Module: MS SNMP Provider
//
// Purpose:
//
// Copyright (c) 1997-2003 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "precomp.h"
#include <provexpt.h>
#include <snmptempl.h>
#include <snmpmt.h>
#include <typeinfo.h>
#include <process.h>
#include <objbase.h>
#include <stdio.h>
#include <snmpcont.h>
#include "snmpevt.h"
#include "snmpthrd.h"
#include "snmplog.h"
CCriticalSection SnmpThreadObject :: s_Lock ;
LONG SnmpThreadObject :: s_ReferenceCount = 0 ;
SnmpMap <DWORD,DWORD,SnmpThreadObject *,SnmpThreadObject *> SnmpThreadObject :: s_ThreadContainer ;
typedef ProvOnDelete < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), LeaveCriticalSection > LeaveCriticalSectionScope;
typedef ProvOnDelete < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), DeleteCriticalSection > DeleteCriticalSectionScope;
typedef WaitException < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), EnterCriticalSection, 1000 > EnterCriticalSectionWait;
class SnmpShutdownTaskObject : public SnmpTaskObject
{
private:
SnmpThreadObject* m_ThreadToShutdown ;
protected:
public:
SnmpShutdownTaskObject (SnmpThreadObject* threadToShutdown) ;
void Process () ;
} ;
SnmpShutdownTaskObject :: SnmpShutdownTaskObject (SnmpThreadObject* threadToShutdown)
: m_ThreadToShutdown ( threadToShutdown )
{
}
void SnmpShutdownTaskObject ::Process()
{
if (m_ThreadToShutdown)
{
m_ThreadToShutdown->SignalThreadShutdown();
}
Complete();
}
BOOL SnmpThreadObject :: Startup ()
{
InterlockedIncrement ( & s_ReferenceCount ) ;
return TRUE ;
}
void SnmpThreadObject :: Closedown()
{
#if DBG == 1
if ( s_ReferenceCount == 0 )
{
DebugBreak ();
}
#endif
if ( InterlockedDecrement ( & s_ReferenceCount ) <= 0 )
ProcessDetach () ;
}
void SnmpThreadObject :: ProcessAttach ()
{
}
void SnmpThreadObject :: ProcessDetach ( BOOL a_ProcessDetaching )
{
// delete all known thread objects
EnterCriticalSectionWait ecs ( s_Lock ) ;
POSITION t_Position = s_ThreadContainer.GetStartPosition () ;
while ( t_Position )
{
DWORD t_EventId ;
SnmpThreadObject *t_ThreadObject ;
s_ThreadContainer.GetNextAssoc ( t_Position , t_EventId , t_ThreadObject ) ;
s_Lock.Unlock () ;
t_ThreadObject->SignalThreadShutdown () ;
EnterCriticalSectionWait ecs ( s_Lock ) ;
t_Position = s_ThreadContainer.GetStartPosition () ;
}
s_ThreadContainer.RemoveAll () ;
s_Lock.Unlock () ;
}
void __cdecl SnmpThreadObject :: ThreadExecutionProcedure ( void *a_ThreadParameter )
{
SetStructuredExceptionHandler seh;
try
{
SnmpThreadObject *t_ThreadObject = ( SnmpThreadObject * ) a_ThreadParameter ;
BOOL bInitialised = FALSE;
try
{
t_ThreadObject->RegisterThread () ;
t_ThreadObject->Initialise () ;
bInitialised = TRUE;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n [%S] Thread beginning dispatch" , t_ThreadObject->m_ThreadName ) ;
)
if ( t_ThreadObject->Wait () )
{
}
else
{
}
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n [%S] Thread completed dispatch" , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
bInitialised = FALSE;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread terminating" ) ;
)
}
catch(Structured_Exception e_SE)
{
t_ThreadObject->RemoveThread () ;
if ( bInitialised )
{
DebugMacro(
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> structured exception *** " , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
}
return;
}
catch(Heap_Exception e_HE)
{
t_ThreadObject->RemoveThread () ;
if ( bInitialised )
{
DebugMacro(
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> heap exception *** " , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
}
return;
}
catch(...)
{
t_ThreadObject->RemoveThread () ;
if ( bInitialised )
{
DebugMacro(
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** [%S] Thread terminating -> exception *** " , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
}
return;
}
}
catch ( ... )
{
DebugMacro(
SnmpDebugLog :: s_SnmpDebugLog->Write ( L"\n *** Thread terminating -> second chance exception *** " ) ;
)
}
}
void SnmpThreadObject :: TerminateThread ()
{
:: TerminateThread (m_ThreadHandle,0) ;
}
SnmpThreadObject :: SnmpThreadObject (
const char *a_ThreadName,
DWORD a_timeout
) : m_EventContainer ( NULL ) ,
m_EventContainerLength ( 0 ) ,
m_ThreadId ( 0 ) ,
m_ThreadHandle ( 0 ) ,
m_ThreadName ( NULL ) ,
m_timeout ( a_timeout ),
m_pShutdownTask ( NULL )
{
if ( a_ThreadName )
{
m_ThreadName = _strdup ( a_ThreadName ) ;
if( NULL == m_ThreadName) throw Heap_Exception(Heap_Exception::E_ALLOCATION_ERROR);
}
ConstructEventContainer () ;
}
void SnmpThreadObject :: BeginThread()
{
UINT_PTR t_PseudoHandle = _beginthread (
SnmpThreadObject :: ThreadExecutionProcedure ,
0 ,
( void * ) this
) ;
s_Lock.Lock () ;
LeaveCriticalSectionScope lcs ( s_Lock );
if ( ( HANDLE ) t_PseudoHandle != INVALID_HANDLE_VALUE )
{
BOOL t_Status = DuplicateHandle (
GetCurrentProcess () ,
( HANDLE ) t_PseudoHandle ,
GetCurrentProcess () ,
GetThreadHandleReference () ,
0 ,
TRUE ,
DUPLICATE_SAME_ACCESS
) ;
if ( ! t_Status )
{
throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR);
}
}
}
BOOL SnmpThreadObject :: WaitForStartup ()
{
BOOL bResult = FALSE;
SnmpTaskObject t_TaskObject ;
ScheduleTask ( t_TaskObject ) ;
t_TaskObject.Exec () ;
if ( ( bResult = t_TaskObject.Wait () ) == TRUE )
{
bResult = ReapTask ( t_TaskObject ) ;
}
return bResult;
}
SnmpThreadObject :: ~SnmpThreadObject ()
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Enter Thread destructor" ) ;
)
if ( ( m_ThreadId != GetCurrentThreadId () ) && ( m_ThreadId != 0 ))
{
SignalThreadShutdown () ;
}
free ( m_ThreadName ) ;
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
while ( t_Position )
{
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
t_TaskObject->DetachTaskFromThread ( *this ) ;
}
m_TaskContainer.RemoveAll () ;
free ( m_EventContainer ) ;
// we should have task already deleted by SignalThreadShutdown
EnterCriticalSectionWait ecs ( s_Lock );
s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
s_Lock.Unlock () ;
if (m_pShutdownTask != NULL)
{
delete m_pShutdownTask;
}
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Exit Thread destructor" ) ;
)
}
void SnmpThreadObject :: PostSignalThreadShutdown ()
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Posting thread shutdown" ) ;
)
if (m_pShutdownTask != NULL)
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread shutdown previously posted" ) ;
)
}
else
{
m_pShutdownTask = new SnmpShutdownTaskObject(this);
ScheduleTask(*m_pShutdownTask);
m_pShutdownTask->Exec();
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n Thread shutdown posted" ) ;
)
}
}
void SnmpThreadObject :: SignalThreadShutdown ()
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock) ;
BOOL t_bRemoved = s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
lcs.Exec ();
if (t_bRemoved)
{
// this should be safe now
if ( m_ThreadId == GetCurrentThreadId () )
{
m_ThreadTerminateEvent.Set () ;
}
else
{
HANDLE t_Handle = m_ThreadHandle ;
m_ThreadTerminateEvent.Set () ;
DWORD t_Event = WaitForSingleObject (
t_Handle ,
INFINITE
) ;
if ( t_Event != WAIT_OBJECT_0 )
{
DWORD dwError = ERROR_SUCCESS;
dwError = ::GetLastError ();
if ( dwError != ERROR_NOT_ENOUGH_MEMORY )
{
#if DBG == 1
// for testing purpose I will let process break
::DebugBreak();
#endif
}
while ( ERROR_SUCCESS != dwError )
{
// resources will eventually come back
::Sleep ( 1000 );
if ( WAIT_OBJECT_0 == WaitForSingleObject (
t_Handle ,
INFINITE
) )
{
// terminate loop
dwError = ERROR_SUCCESS;
}
}
}
CloseHandle ( t_Handle ) ;
}
}
}
void SnmpThreadObject :: ConstructEventContainer ()
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Constructing Container" , m_ThreadName ) ;
)
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock ) ;
BOOL bAllocated = FALSE;
do
{
ULONG origEventContainerLength = m_EventContainerLength ;
if ( ( m_TaskContainer.GetCount () + 2 ) < MAXIMUM_WAIT_OBJECTS )
{
m_EventContainerLength = m_TaskContainer.GetCount () + 2;
}
else
{
m_EventContainerLength = MAXIMUM_WAIT_OBJECTS - 1;
}
PVOID pNewMem = realloc ( m_EventContainer , sizeof ( HANDLE ) * m_EventContainerLength );
if ( pNewMem == NULL )
{
//
// revert the size back
//
m_EventContainerLength = origEventContainerLength ;
s_Lock.Unlock () ;
// system will eventually come back !
Sleep (60000);
EnterCriticalSectionWait ecs ( s_Lock ) ;
}
else
{
m_EventContainer = ( HANDLE * ) pNewMem;
bAllocated = TRUE;
}
}
while ( ! bAllocated );
m_EventContainer [ 0 ] = GetHandle () ;
m_EventContainer [ 1 ] = m_ThreadTerminateEvent.GetHandle () ;
ULONG t_EventIndex = 2 ;
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
while ( t_Position && (t_EventIndex < m_EventContainerLength))
{
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
m_EventContainer [ t_EventIndex ] = t_TaskObject->GetHandle () ;
t_EventIndex ++ ;
}
}
void SnmpThreadObject :: RotateTask ( SnmpAbstractTaskObject *a_TaskObject )
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
while ( t_Position )
{
POSITION t_LastPosition = t_Position ;
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
if ( a_TaskObject->GetHandle () == t_TaskObject->GetHandle () )
{
m_TaskContainer.RemoveAt ( t_LastPosition ) ;
m_TaskContainer.Add ( t_TaskObject ) ;
break ;
}
}
}
SnmpThreadObject *SnmpThreadObject :: GetThreadObject ()
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
DWORD t_CurrentThreadId = GetCurrentThreadId () ;
SnmpThreadObject *t_ThreadObject ;
if ( s_ThreadContainer.Lookup ( GetCurrentThreadId () , t_ThreadObject ) )
{
}
else
{
t_ThreadObject = NULL ;
}
return t_ThreadObject ;
}
SnmpAbstractTaskObject *SnmpThreadObject :: GetTaskObject ( HANDLE &a_Handle )
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
while ( t_Position )
{
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
if ( t_TaskObject->GetHandle () == a_Handle )
{
return t_TaskObject ;
}
}
return NULL ;
}
BOOL SnmpThreadObject :: RegisterThread ()
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
m_ThreadId = GetCurrentThreadId () ;
s_ThreadContainer [ m_ThreadId ] = this ;
BOOL t_Status = TRUE;
DebugMacro8(
wchar_t buffer [ 1025 ] ;
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx" , m_ThreadName , this , m_ThreadId ) ;
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
)
return t_Status ;
}
BOOL SnmpThreadObject :: RemoveThread ()
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
BOOL t_Status = s_ThreadContainer.RemoveKey ( m_ThreadId ) ;
if ( t_Status )
{
DebugMacro8(
wchar_t buffer [ 1025 ] ;
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx was removed from container" , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
)
}
else
{
DebugMacro8(
wchar_t buffer [ 1025 ] ;
wsprintf ( buffer , L"\nThread [%S] = %lx, with thread id = %lx failed to remove from container" , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, buffer ) ;
)
}
return t_Status ;
}
void SnmpThreadObject :: Process ()
{
EnterCriticalSectionWait ecs ( s_Lock ) ;
LeaveCriticalSectionScope lcs ( s_Lock );
POSITION t_Position = m_ScheduleReapEventContainer.GetStartPosition () ;
while ( t_Position )
{
HANDLE t_EventId ;
SnmpEventObject *t_Event ;
m_ScheduleReapEventContainer.GetNextAssoc ( t_Position , t_EventId , t_Event) ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Process [%lx]" , m_ThreadName , t_EventId);
)
t_Event->Set () ;
}
}
BOOL SnmpThreadObject :: WaitDispatch ( ULONG t_HandleIndex , BOOL &a_Terminated )
{
BOOL t_Status = TRUE ;
HANDLE t_Handle = m_EventContainer [ t_HandleIndex ] ;
if ( t_Handle == GetHandle () )
{
// Task has been scheduled so we must update arrays
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Wait: Refreshing handles" , m_ThreadName );
)
Process () ;
ConstructEventContainer () ;
}
else if ( t_Handle == m_ThreadTerminateEvent.GetHandle () )
{
// thread has been told to close down
a_Terminated = TRUE ;
m_ThreadTerminateEvent.Process () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Someone t_Terminated" , m_ThreadName ) ;
)
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Thread Wait: Processing Task" , m_ThreadName );
)
SnmpAbstractTaskObject *t_TaskObject = GetTaskObject ( t_Handle ) ;
if ( t_TaskObject )
{
RotateTask ( t_TaskObject ) ;
ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Couldn't Find Task Object" , m_ThreadName ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
BOOL SnmpThreadObject :: Wait ()
{
BOOL t_Status = TRUE ;
BOOL t_Terminated = FALSE ;
while ( t_Status && ! t_Terminated )
{
DWORD t_Event = MsgWaitForMultipleObjects (
m_EventContainerLength ,
m_EventContainer ,
FALSE ,
m_timeout ,
QS_ALLINPUT
) ;
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DWORD t_Error = GetLastError () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Handle problem" , m_ThreadName ) ;
)
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
TimedOut();
}
else if ( t_HandleIndex <= m_EventContainerLength )
{
// Go into dispatch loop
if ( t_HandleIndex == m_EventContainerLength )
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
int t_Result = 0;
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
if ( t_Result != 0 && t_Result != -1 )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
BOOL t_Timeout = FALSE ;
while ( ! t_Timeout && t_Status && ! t_Terminated )
{
t_Event = WaitForMultipleObjects (
m_EventContainerLength ,
m_EventContainer ,
FALSE ,
0
) ;
t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DWORD t_Error = GetLastError () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Handle problem" , m_ThreadName ) ;
)
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
t_Timeout = TRUE ;
}
else if ( t_HandleIndex < m_EventContainerLength )
{
t_Status = WaitDispatch ( t_HandleIndex , t_Terminated ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Unknown handle index" , m_ThreadName ) ;
)
t_Status = FALSE ;
}
}
}
}
else if ( t_HandleIndex < m_EventContainerLength )
{
t_Status = WaitDispatch ( t_HandleIndex , t_Terminated ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Unknown handle index" , m_ThreadName ) ;
)
t_Status = FALSE ;
}
}
}
return t_Status ;
}
ULONG SnmpThreadObject :: GetEventHandlesSize ()
{
return m_EventContainerLength ;
}
HANDLE *SnmpThreadObject :: GetEventHandles ()
{
return m_EventContainer ;
}
BOOL SnmpThreadObject :: ScheduleTask ( SnmpAbstractTaskObject &a_TaskObject )
{
BOOL t_Result = TRUE ;
EnterCriticalSectionWait ecs ( s_Lock ) ;
/*
* Add Synchronous object to worker thread container
*/
a_TaskObject.m_ScheduledHandle = a_TaskObject.GetHandle ();
m_TaskContainer.Add ( &a_TaskObject ) ;
s_Lock.Unlock () ;
a_TaskObject.AttachTaskToThread ( *this ) ;
if ( GetCurrentThreadId () != m_ThreadId )
{
#if 0
SnmpEventObject t_ScheduledEventObject ;
EnterCriticalSectionWait ecs1 ( s_Lock ) ;
m_ScheduleReapEventContainer [ t_ScheduledEventObject.GetHandle () ] = &t_ScheduledEventObject ;
s_Lock.Unlock () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Setting update" , m_ThreadName );
)
Set () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Beginning Wait" , m_ThreadName );
)
if ( t_ScheduledEventObject.Wait () )
{
}
else
{
t_Result = FALSE ;
}
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ScheduleTask: Ended Wait" , m_ThreadName );
)
EnterCriticalSectionWait ecs2 ( s_Lock ) ;
m_ScheduleReapEventContainer.RemoveKey ( t_ScheduledEventObject.GetHandle () ) ;
s_Lock.Unlock () ;
#else
Set () ;
#endif
}
else
{
ConstructEventContainer () ;
}
return t_Result ;
}
BOOL SnmpThreadObject :: ReapTask ( SnmpAbstractTaskObject &a_TaskObject )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Entering ReapTask [%lx]" , m_ThreadName , a_TaskObject.m_ScheduledHandle );
)
BOOL t_Result = TRUE ;
EnterCriticalSectionWait ecs ( s_Lock ) ;
/*
* Remove worker object from worker thread container
*/
POSITION t_Position = m_TaskContainer.GetHeadPosition () ;
while ( t_Position )
{
POSITION t_LastPosition = t_Position ;
SnmpAbstractTaskObject *t_TaskObject = m_TaskContainer.GetNext ( t_Position ) ;
if ( a_TaskObject.m_ScheduledHandle == t_TaskObject->m_ScheduledHandle )
{
m_TaskContainer.RemoveAt ( t_LastPosition ) ;
break ;
}
}
s_Lock.Unlock () ;
/*
* Inform worker thread,thread container has been updated.
*/
if ( GetCurrentThreadId () != m_ThreadId )
{
SnmpEventObject t_ReapedEventObject ;
EnterCriticalSectionWait ecs1 ( s_Lock ) ;
m_ScheduleReapEventContainer [ t_ReapedEventObject.GetHandle () ] = &t_ReapedEventObject ;
s_Lock.Unlock () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Setting update" , m_ThreadName );
)
Set () ;
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Beginning Wait on [%lx]" , m_ThreadName , t_ReapedEventObject.GetHandle () );
)
if ( t_ReapedEventObject.Wait () )
{
}
else
{
t_Result = FALSE ;
}
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: Ended Wait" , m_ThreadName );
)
EnterCriticalSectionWait ecs2 ( s_Lock ) ;
m_ScheduleReapEventContainer.RemoveKey ( t_ReapedEventObject.GetHandle () ) ;
s_Lock.Unlock () ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] ReapTask: ConstructEventContainer" , m_ThreadName );
)
ConstructEventContainer () ;
}
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\n[%S] Returning from ReapTask [%lx]" , m_ThreadName , a_TaskObject.m_ScheduledHandle );
)
a_TaskObject.DetachTaskFromThread ( *this ) ;
return t_Result ;
}
SnmpAbstractTaskObject :: SnmpAbstractTaskObject (
const wchar_t *a_GlobalTaskNameComplete,
const wchar_t *a_GlobalTaskNameAcknowledgement,
DWORD a_timeout
) : m_CompletionEvent ( a_GlobalTaskNameComplete ) ,
m_AcknowledgementEvent ( a_GlobalTaskNameAcknowledgement ) ,
m_timeout ( a_timeout ),
m_ScheduledHandle (NULL)
{
}
SnmpAbstractTaskObject :: ~SnmpAbstractTaskObject ()
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: ~SnmpAbstractTaskObject () [%lx]" , m_ScheduledHandle ) ;
)
EnterCriticalSectionWait ecs ( m_Lock ) ;
LeaveCriticalSectionScope lcs ( m_Lock );
if (NULL != m_ScheduledHandle)
{
POSITION t_Position = m_ThreadContainer.GetStartPosition () ;
while ( t_Position )
{
DWORD t_ThreadId ;
SnmpThreadObject *t_ThreadObject ;
m_ThreadContainer.GetNextAssoc ( t_Position , t_ThreadId , t_ThreadObject ) ;
t_ThreadObject->ReapTask ( *this ) ;
}
}
m_ThreadContainer.RemoveAll () ;
}
void SnmpAbstractTaskObject :: DetachTaskFromThread ( SnmpThreadObject &a_ThreadObject )
{
EnterCriticalSectionWait ecs ( m_Lock ) ;
LeaveCriticalSectionScope lcs ( m_Lock );
m_ThreadContainer.RemoveKey ( a_ThreadObject.GetThreadId () ) ;
}
void SnmpAbstractTaskObject :: AttachTaskToThread ( SnmpThreadObject &a_ThreadObject )
{
EnterCriticalSectionWait ecs ( m_Lock ) ;
LeaveCriticalSectionScope lcs ( m_Lock );
m_ThreadContainer [ a_ThreadObject.GetThreadId () ] = &a_ThreadObject ;
}
BOOL SnmpAbstractTaskObject :: Wait ( BOOL a_Dispatch )
{
BOOL t_Status = TRUE ;
BOOL t_Processed = FALSE ;
while ( t_Status && ! t_Processed )
{
SnmpThreadObject *t_ThreadObject = SnmpThreadObject :: GetThreadObject () ;
ULONG t_TaskEventArrayLength = 0 ;
HANDLE *t_TaskEventArray = NULL ;
if ( t_ThreadObject && a_Dispatch )
{
ULONG t_TaskArrayLength = t_ThreadObject->GetEventHandlesSize () ;
t_TaskEventArrayLength = t_TaskArrayLength + 1 ;
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
if ( t_TaskEventArray )
{
t_TaskEventArray [ 0 ] = m_CompletionEvent.GetHandle () ;
memcpy (
& ( t_TaskEventArray [ 1 ] ) ,
t_ThreadObject->GetEventHandles () ,
t_TaskArrayLength * sizeof ( HANDLE )
) ;
}
else
{
return FALSE;
}
}
else
{
t_TaskEventArrayLength = 1 ;
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
t_TaskEventArray [ 0 ] = m_CompletionEvent.GetHandle () ;
}
DWORD t_Event ;
if ( a_Dispatch )
{
t_Event = MsgWaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
m_timeout ,
QS_ALLINPUT
) ;
}
else
{
t_Event = WaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
m_timeout
) ;
}
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
)
DWORD t_Error = GetLastError () ;
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
TimedOut();
}
else if ( t_HandleIndex == t_TaskEventArrayLength )
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
int t_Result = 0;
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
if ( t_Result != 0 && t_Result != -1 )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
BOOL t_Timeout = FALSE ;
while ( ! t_Timeout && t_Status && ! t_Processed )
{
t_Event = WaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
0
) ;
t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
)
DWORD t_Error = GetLastError () ;
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
t_Timeout = TRUE ;
}
else if ( t_HandleIndex < t_TaskEventArrayLength )
{
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
t_Status = WaitDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
)
t_Status = FALSE ;
}
}
}
}
else if ( t_HandleIndex < t_TaskEventArrayLength )
{
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
t_Status = WaitDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
)
t_Status = FALSE ;
}
delete [] t_TaskEventArray ;
}
return t_Status ;
}
BOOL SnmpAbstractTaskObject :: WaitDispatch ( SnmpThreadObject *a_ThreadObject, HANDLE a_Handle , BOOL &a_Processed )
{
BOOL t_Status = TRUE ;
if ( a_Handle == m_CompletionEvent.GetHandle () )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nWait: Completed" );
)
m_CompletionEvent.Process () ;
a_Processed = TRUE ;
}
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nTask Wait: Refreshing handles" );
)
a_ThreadObject->Process () ;
a_ThreadObject->ConstructEventContainer () ;
}
else
{
SnmpAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
if ( t_TaskObject )
{
a_ThreadObject->RotateTask ( t_TaskObject ) ;
a_ThreadObject->ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Task" ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
BOOL SnmpAbstractTaskObject :: WaitAcknowledgement ( BOOL a_Dispatch )
{
BOOL t_Status = TRUE ;
BOOL t_Processed = FALSE ;
while ( t_Status && ! t_Processed )
{
SnmpThreadObject *t_ThreadObject = SnmpThreadObject :: GetThreadObject () ;
ULONG t_TaskEventArrayLength = 0 ;
HANDLE *t_TaskEventArray = NULL ;
if ( t_ThreadObject && a_Dispatch )
{
ULONG t_TaskArrayLength = t_ThreadObject->GetEventHandlesSize () ;
t_TaskEventArrayLength = t_TaskArrayLength + 1 ;
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
if ( t_TaskArrayLength )
{
memcpy (
& ( t_TaskEventArray [ 1 ] ) ,
t_ThreadObject->GetEventHandles () ,
t_TaskArrayLength * sizeof ( HANDLE )
) ;
}
t_TaskEventArray [ 0 ] = m_AcknowledgementEvent.GetHandle () ;
}
else
{
t_TaskEventArrayLength = 1 ;
t_TaskEventArray = new HANDLE [ t_TaskEventArrayLength ] ;
t_TaskEventArray [ 0 ] = m_AcknowledgementEvent.GetHandle () ;
}
DWORD t_Event ;
if ( a_Dispatch )
{
t_Event = MsgWaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
m_timeout ,
QS_ALLINPUT
) ;
}
else
{
t_Event = WaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
m_timeout
) ;
}
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
)
DWORD t_Error = GetLastError () ;
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
TimedOut();
}
if ( t_HandleIndex == t_TaskEventArrayLength )
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
int t_Result = 0;
t_Result = GetMessage ( & t_Msg , NULL , 0 , 0 );
if ( t_Result != 0 && t_Result != -1 )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
BOOL t_Timeout = FALSE ;
while ( ! t_Timeout && t_Status && ! t_Processed )
{
t_Event = WaitForMultipleObjects (
t_TaskEventArrayLength ,
t_TaskEventArray ,
FALSE ,
0
) ;
ULONG t_HandleIndex = t_Event - WAIT_OBJECT_0 ;
if ( t_Event == 0xFFFFFFFF )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle" ) ;
)
DWORD t_Error = GetLastError () ;
t_Status = FALSE ;
}
else if ( t_Event == WAIT_TIMEOUT)
{
t_Timeout = TRUE ;
}
else if ( t_HandleIndex < t_TaskEventArrayLength )
{
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
t_Status = WaitAcknowledgementDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
)
t_Status = FALSE ;
}
}
}
}
else if ( t_HandleIndex < t_TaskEventArrayLength )
{
HANDLE t_Handle = t_TaskEventArray [ t_HandleIndex ] ;
t_Status = WaitAcknowledgementDispatch ( t_ThreadObject , t_Handle , t_Processed ) ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Handle index" ) ;
)
t_Status = FALSE ;
}
delete [] t_TaskEventArray ;
}
return t_Status ;
}
BOOL SnmpAbstractTaskObject :: WaitAcknowledgementDispatch ( SnmpThreadObject *a_ThreadObject , HANDLE a_Handle , BOOL &a_Processed )
{
BOOL t_Status = TRUE ;
if ( a_Handle == m_AcknowledgementEvent.GetHandle () )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nWait: Completed" );
)
m_AcknowledgementEvent.Process () ;
a_Processed = TRUE ;
}
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nTask Wait: Refreshing handles" );
)
a_ThreadObject->Process () ;
a_ThreadObject->ConstructEventContainer () ;
}
else
{
SnmpAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
if ( t_TaskObject )
{
a_ThreadObject->RotateTask ( t_TaskObject ) ;
a_ThreadObject->ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"\nSnmpAbstractTaskObject :: Illegal Task" ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
SnmpTaskObject::SnmpTaskObject (
const wchar_t *a_GlobalTaskNameStart,
const wchar_t *a_GlobalTaskNameComplete ,
const wchar_t *a_GlobalTaskNameAcknowledge,
DWORD a_timeout
): SnmpAbstractTaskObject(a_GlobalTaskNameComplete, a_GlobalTaskNameAcknowledge,a_timeout), m_Event(a_GlobalTaskNameStart)
{
}