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.
 
 
 
 
 
 

1404 lines
32 KiB

//***************************************************************************
//
// PROVTHRD.CPP
//
// Module: OLE MS PROVIDER FRAMEWORK
//
// Copyright (c) 1996-2003 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include <precomp.h>
#include <provimex.h>
#include <provexpt.h>
#include <provtempl.h>
#include <strsafe.h>
#include <provmt.h>
#include <typeinfo.h>
#include <process.h>
#include <objbase.h>
#include <provcont.h>
#include "provevt.h"
#include "provthrd.h"
#include "provlog.h"
#include <Allocator.cpp>
#include <Algorithms.h>
CStaticCriticalSection ProvThreadObject :: s_Lock ;
LONG ProvThreadObject :: s_ReferenceCount = 0 ;
WmiAllocator g_Allocator ;
ThreadContainer ProvThreadObject :: s_ThreadContainer ( g_Allocator ) ;
typedef ProvOnDelete < CRITICAL_SECTION *, VOID ( * ) ( LPCRITICAL_SECTION ), LeaveCriticalSection > LeaveCriticalSectionScope;
class ProvShutdownTaskObject : public ProvTaskObject
{
private:
ProvThreadObject *m_ThreadToShutdown ;
protected:
public:
ProvShutdownTaskObject (ProvThreadObject *threadToShutdown) ;
void Process () ;
} ;
ProvShutdownTaskObject :: ProvShutdownTaskObject (
ProvThreadObject *threadToShutdown
) : m_ThreadToShutdown ( threadToShutdown )
{
}
void ProvShutdownTaskObject ::Process()
{
if ( m_ThreadToShutdown )
{
m_ThreadToShutdown->SignalThreadShutdown ();
}
Complete();
}
BOOL ProvThreadObject :: Startup ()
{
InterlockedIncrement ( & s_ReferenceCount ) ;
return TRUE ;
}
void ProvThreadObject :: Closedown()
{
#if DBG == 1
if ( s_ReferenceCount == 0 )
{
DebugBreak ();
}
#endif
if ( InterlockedDecrement ( & s_ReferenceCount ) <= 0 )
ProcessDetach () ;
}
void ProvThreadObject :: ProcessAttach ()
{
}
void ProvThreadObject :: ProcessDetach ( BOOL a_ProcessDetaching )
{
// delete all known thread objects
s_Lock.Lock();
ThreadContainerIterator t_Iterator = s_ThreadContainer.Begin () ;
while ( ! t_Iterator.Null () )
{
s_Lock.Unlock () ;
t_Iterator.GetElement ()->SignalThreadShutdown () ;
s_Lock.Lock();
t_Iterator = s_ThreadContainer.Begin () ;
}
s_ThreadContainer.UnInitialize () ;
s_Lock.Unlock () ;
}
void ProvThreadObject :: ThreadExecutionProcedure ( void *a_ThreadParameter )
{
SetStructuredExceptionHandler seh;
try
{
ProvThreadObject *t_ThreadObject = ( ProvThreadObject * ) a_ThreadParameter ;
BOOL bInitialised = FALSE;
try
{
if ( t_ThreadObject->RegisterThread () )
{
t_ThreadObject->Initialise () ;
bInitialised = TRUE;
SetEvent ( t_ThreadObject->m_ThreadInitialization ) ;
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n [%s] Thread beginning dispatch") , t_ThreadObject->m_ThreadName ) ;
)
if ( t_ThreadObject->Wait () )
{
}
else
{
}
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n [%s] Thread completed dispatch") , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
bInitialised = FALSE;
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Thread terminating") ) ;
)
}
}
catch(Structured_Exception e_SE)
{
t_ThreadObject->RemoveThread () ;
if ( bInitialised )
{
DebugMacro(
CNTEventProvider::g_NTEvtDebugLog->Write ( _TEXT("\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(
CNTEventProvider::g_NTEvtDebugLog->Write ( _TEXT("\n *** [%s] Thread terminating -> heap exception *** ") , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
}
return;
}
catch(...)
{
t_ThreadObject->RemoveThread () ;
if ( bInitialised )
{
DebugMacro(
CNTEventProvider::g_NTEvtDebugLog->Write ( _TEXT("\n *** [%s] Thread terminating -> exception *** ") , t_ThreadObject->m_ThreadName ) ;
)
t_ThreadObject->Uninitialise () ;
}
return;
}
}
catch ( ... )
{
DebugMacro(
CNTEventProvider::g_NTEvtDebugLog->Write ( _TEXT("\n *** Thread terminating -> second chance exception *** ") ) ;
)
}
}
void ProvThreadObject :: TerminateThread ()
{
:: TerminateThread (m_ThreadHandle,0) ;
}
ProvThreadObject :: ProvThreadObject (
const TCHAR *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 ) ,
m_ScheduleReapContainer ( g_Allocator ) ,
m_TaskQueue ( g_Allocator ) ,
m_ThreadInitialization ( NULL )
{
if ( a_ThreadName )
{
m_ThreadName = _tcsdup ( a_ThreadName ) ;
if( NULL == m_ThreadName) throw Heap_Exception(Heap_Exception::E_ALLOCATION_ERROR);
}
m_ThreadInitialization = CreateEvent ( NULL , FALSE , FALSE , NULL ) ;
if ( NULL == m_ThreadInitialization) throw Heap_Exception(Heap_Exception::E_ALLOCATION_ERROR);
ConstructEventContainer () ;
}
void ProvThreadObject :: BeginThread()
{
UINT_PTR t_PseudoHandle = _beginthread (
ProvThreadObject :: 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 ProvThreadObject :: WaitForStartup ()
{
DWORD dwHandles = 2;
HANDLE hHandles[] =
{
m_ThreadInitialization,
m_ThreadHandle
};
DWORD dwWaitResult = WAIT_TIMEOUT;
dwWaitResult = WaitForMultipleObjects ( dwHandles, hHandles, FALSE, INFINITE ) ;
return ( ( ( dwWaitResult - WAIT_OBJECT_0 ) == 0 ) && ( dwWaitResult != WAIT_FAILED ) );
}
ProvThreadObject :: ~ProvThreadObject ()
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Enter Thread destructor") ) ;
)
if ( ( m_ThreadId != GetCurrentThreadId () ) && ( m_ThreadId != 0 ))
{
SignalThreadShutdown () ;
}
free ( m_ThreadName ) ;
ProvAbstractTaskObject *t_TaskObject = NULL ;
WmiStatusCode t_StatusCode ;
while ( ( t_StatusCode = m_TaskQueue.Top ( t_TaskObject ) ) == e_StatusCode_Success )
{
m_TaskQueue.DeQueue () ;
t_TaskObject->DetachTaskFromThread ( *this ) ;
}
m_TaskQueue.UnInitialize () ;
free ( m_EventContainer ) ;
// we should have task already deleted by SignalThreadShutdown
s_Lock.Lock();
s_ThreadContainer.Delete ( m_ThreadId ) ;
s_Lock.Unlock () ;
if ( m_ThreadInitialization )
{
CloseHandle ( m_ThreadInitialization ) ;
}
if (m_pShutdownTask != NULL)
{
delete m_pShutdownTask;
}
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Exit Thread destructor") ) ;
)
}
void ProvThreadObject :: PostSignalThreadShutdown ()
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Posting thread shutdown") ) ;
)
if (m_pShutdownTask != NULL)
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Thread shutdown previously posted") ) ;
)
}
else
{
m_pShutdownTask = new ProvShutdownTaskObject(this);
ScheduleTask(*m_pShutdownTask);
m_pShutdownTask->Exec();
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n Thread shutdown posted") ) ;
)
}
}
void ProvThreadObject :: SignalThreadShutdown ()
{
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock) ;
WmiStatusCode t_StatusCode = s_ThreadContainer.Delete ( m_ThreadId ) ;
lcs.Exec ();
if ( t_StatusCode != e_StatusCode_NotFound )
{
// 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 ProvThreadObject :: ConstructEventContainer ()
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Constructing Container") , m_ThreadName ) ;
)
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock ) ;
BOOL bAllocated = FALSE;
do
{
ULONG origEventContainerLength = m_EventContainerLength ;
if ( ( m_TaskQueue.Size () + 2 ) < MAXIMUM_WAIT_OBJECTS )
{
m_EventContainerLength = m_TaskQueue.Size () + 2;
}
else
{
m_EventContainerLength = MAXIMUM_WAIT_OBJECTS - 1;
}
HANDLE * tempArray = ( HANDLE * ) realloc ( m_EventContainer , sizeof ( HANDLE ) * m_EventContainerLength );
if ( tempArray == NULL )
{
//
// revert the size back
//
m_EventContainerLength = origEventContainerLength ;
s_Lock.Unlock () ;
// system will eventually come back !
Sleep (60000);
s_Lock.Lock();
}
else
{
m_EventContainer = tempArray;
bAllocated = TRUE;
}
}
while ( ! bAllocated );
m_EventContainer [ 0 ] = GetHandle () ;
m_EventContainer [ 1 ] = m_ThreadTerminateEvent.GetHandle () ;
ULONG t_EventIndex = 2 ;
WmiStatusCode t_StatusCode ;
ProvAbstractTaskObject *t_TaskObject = NULL ;
while ( ( t_EventIndex < m_EventContainerLength ) && ( t_StatusCode = m_TaskQueue.Top ( t_TaskObject ) ) == e_StatusCode_Success )
{
t_StatusCode = m_TaskQueue.DeQueue () ;
t_StatusCode = m_TaskQueue.EnQueue ( t_TaskObject ) ;
m_EventContainer [ t_EventIndex ] = t_TaskObject->GetHandle () ;
t_EventIndex ++ ;
}
}
ProvThreadObject *ProvThreadObject :: GetThreadObject ()
{
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock );
DWORD t_CurrentThreadId = GetCurrentThreadId () ;
ProvThreadObject *t_ThreadObject ;
ThreadContainerIterator t_Iterator ;
if ( s_ThreadContainer.Find ( GetCurrentThreadId () , t_Iterator ) == e_StatusCode_Success )
{
t_ThreadObject = t_Iterator.GetElement () ;
}
else
{
t_ThreadObject = NULL ;
}
return t_ThreadObject ;
}
ProvAbstractTaskObject *ProvThreadObject :: GetTaskObject ( HANDLE &a_Handle )
{
ProvAbstractTaskObject *t_TaskObject = NULL ;
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock );
ULONG t_QueueSize = m_TaskQueue.Size () ;
WmiStatusCode t_StatusCode ;
while ( t_QueueSize && ( ( t_StatusCode = m_TaskQueue.Top ( t_TaskObject ) ) == e_StatusCode_Success ) )
{
m_TaskQueue.DeQueue () ;
m_TaskQueue.EnQueue ( t_TaskObject ) ;
if ( t_TaskObject->GetHandle () == a_Handle )
{
break ;
}
t_QueueSize -- ;
}
return t_TaskObject ;
}
BOOL ProvThreadObject :: RegisterThread ()
{
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock );
BOOL t_Status = FALSE ;
m_ThreadId = GetCurrentThreadId () ;
ThreadContainerIterator t_Iterator ;
if ( s_ThreadContainer.Insert ( m_ThreadId , this , t_Iterator ) == e_StatusCode_Success )
{
t_Status = TRUE;
}
DebugMacro8(
TCHAR buffer [ 1025 ] ;
StringCchPrintf ( buffer , sizeof ( buffer ) / sizeof ( TCHAR ) , _TEXT("\nThread [%s] = %lx, with thread id = %lx") , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, buffer ) ;
)
return t_Status ;
}
BOOL ProvThreadObject :: RemoveThread ()
{
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock );
BOOL t_Status = s_ThreadContainer.Delete ( m_ThreadId ) ;
if ( t_Status )
{
DebugMacro8(
TCHAR buffer [ 1025 ] ;
StringCchPrintf ( buffer , sizeof ( buffer ) / sizeof ( TCHAR ) , _TEXT("\nThread [%s] = %lx, with thread id = %lx was removed from container") , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, buffer ) ;
)
}
else
{
DebugMacro8(
TCHAR buffer [ 1025 ] ;
StringCchPrintf ( buffer , sizeof ( buffer ) / sizeof ( TCHAR ) , _TEXT("\nThread [%s] = %lx, with thread id = %lx failed to remove from container") , m_ThreadName , (UINT_PTR)this , m_ThreadId ) ;
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, buffer ) ;
)
}
return t_Status ;
}
void ProvThreadObject :: Process ()
{
s_Lock.Lock();
LeaveCriticalSectionScope lcs ( s_Lock );
ScheduleReapContainerIterator t_Iterator = m_ScheduleReapContainer.Begin () ;
while ( ! t_Iterator.Null () )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Thread Process [%lx]") , m_ThreadName , t_Iterator.GetKey () );
)
t_Iterator.GetElement ()->Set () ;
t_Iterator.Increment () ;
}
}
BOOL ProvThreadObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Someone t_Terminated") , m_ThreadName ) ;
)
}
else
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Thread Wait: Processing Task") , m_ThreadName );
)
ProvAbstractTaskObject *t_TaskObject = GetTaskObject ( t_Handle ) ;
if ( t_TaskObject )
{
ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Couldn't Find Task Object") , m_ThreadName ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
BOOL ProvThreadObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Unknown handle index") , m_ThreadName ) ;
)
t_Status = FALSE ;
}
}
}
return t_Status ;
}
ULONG ProvThreadObject :: GetEventHandlesSize ()
{
return m_EventContainerLength ;
}
HANDLE *ProvThreadObject :: GetEventHandles ()
{
return m_EventContainer ;
}
BOOL ProvThreadObject :: ScheduleTask ( ProvAbstractTaskObject &a_TaskObject )
{
BOOL t_Result = TRUE ;
s_Lock.Lock();
/*
* Add Synchronous object to worker thread container
*/
a_TaskObject.m_ScheduledHandle = a_TaskObject.GetHandle ();
WmiStatusCode t_StatusCode = m_TaskQueue.EnQueue ( &a_TaskObject ) ;
s_Lock.Unlock () ;
a_TaskObject.AttachTaskToThread ( *this ) ;
if ( GetCurrentThreadId () != m_ThreadId )
{
Set () ;
}
else
{
ConstructEventContainer () ;
}
return t_Result ;
}
BOOL ProvThreadObject :: ReapTask ( ProvAbstractTaskObject &a_TaskObject )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Entering ReapTask [%lx]") , m_ThreadName , a_TaskObject.m_ScheduledHandle );
)
BOOL t_Result = TRUE ;
s_Lock.Lock();
/*
* Remove worker object from worker thread container
*/
ProvAbstractTaskObject *t_TaskObject = NULL ;
ULONG t_QueueSize = m_TaskQueue.Size () ;
WmiStatusCode t_StatusCode ;
while ( t_QueueSize && ( ( t_StatusCode = m_TaskQueue.Top ( t_TaskObject ) ) == e_StatusCode_Success ) )
{
m_TaskQueue.DeQueue () ;
if ( a_TaskObject.m_ScheduledHandle == t_TaskObject->m_ScheduledHandle )
{
break ;
}
m_TaskQueue.EnQueue ( t_TaskObject ) ;
t_QueueSize -- ;
}
s_Lock.Unlock () ;
/*
* Inform worker thread,thread container has been updated.
*/
if ( GetCurrentThreadId () != m_ThreadId )
{
ProvEventObject t_ReapedEventObject ;
s_Lock.Lock() ;
ScheduleReapContainerIterator t_Iterator ;
WmiStatusCode t_StatusCode = m_ScheduleReapContainer.Insert ( t_ReapedEventObject.GetHandle () , &t_ReapedEventObject , t_Iterator ) ;
s_Lock.Unlock () ;
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] ReapTask: Setting update") , m_ThreadName );
)
Set () ;
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] ReapTask: Beginning Wait on [%lx]") , m_ThreadName , t_ReapedEventObject.GetHandle () );
)
if ( t_ReapedEventObject.Wait () )
{
}
else
{
t_Result = FALSE ;
}
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] ReapTask: Ended Wait") , m_ThreadName );
)
s_Lock.Lock();
t_StatusCode = m_ScheduleReapContainer.Delete ( t_ReapedEventObject.GetHandle () ) ;
s_Lock.Unlock () ;
}
else
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] ReapTask: ConstructEventContainer") , m_ThreadName );
)
ConstructEventContainer () ;
}
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\n[%s] Returning from ReapTask [%lx]") , m_ThreadName , a_TaskObject.m_ScheduledHandle );
)
a_TaskObject.DetachTaskFromThread ( *this ) ;
return t_Result ;
}
ProvAbstractTaskObject :: ProvAbstractTaskObject (
const TCHAR *a_GlobalTaskNameComplete,
const TCHAR *a_GlobalTaskNameAcknowledgement,
DWORD a_timeout
) : m_CompletionEvent ( a_GlobalTaskNameComplete ) ,
m_AcknowledgementEvent ( a_GlobalTaskNameAcknowledgement ) ,
m_timeout ( a_timeout ),
m_ScheduledHandle (NULL),
m_ThreadContainer (g_Allocator)
{
}
ProvAbstractTaskObject :: ~ProvAbstractTaskObject ()
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: ~ProvAbstractTaskObject () [%lx]") , m_ScheduledHandle ) ;
)
m_Lock.Lock();
LeaveCriticalSectionScope lcs ( m_Lock );
if (NULL != m_ScheduledHandle)
{
ThreadContainerIterator t_Iterator = m_ThreadContainer.Begin () ;
while ( ! t_Iterator.Null () )
{
ProvThreadObject *t_Task = t_Iterator.GetElement () ;
t_Task->ReapTask ( *this ) ;
t_Iterator = m_ThreadContainer.Begin () ;
}
}
m_ThreadContainer.UnInitialize () ;
}
void ProvAbstractTaskObject :: DetachTaskFromThread ( ProvThreadObject &a_ThreadObject )
{
m_Lock.Lock();
LeaveCriticalSectionScope lcs ( m_Lock );
WmiStatusCode t_StatusCode = m_ThreadContainer.Delete ( a_ThreadObject.GetThreadId () ) ;
}
void ProvAbstractTaskObject :: AttachTaskToThread ( ProvThreadObject &a_ThreadObject )
{
m_Lock.Lock();
LeaveCriticalSectionScope lcs ( m_Lock );
ThreadContainerIterator t_Iterator ;
WmiStatusCode t_StatusCode = m_ThreadContainer.Insert ( a_ThreadObject.GetThreadId () , &a_ThreadObject , t_Iterator ) ;
}
BOOL ProvAbstractTaskObject :: Wait ( BOOL a_Dispatch )
{
BOOL t_Status = TRUE ;
BOOL t_Processed = FALSE ;
while ( t_Status && ! t_Processed )
{
ProvThreadObject *t_ThreadObject = ProvThreadObject :: 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_CompletionEvent.GetHandle () ;
}
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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: Illegal Handle index") ) ;
)
t_Status = FALSE ;
}
delete [] t_TaskEventArray ;
}
return t_Status ;
}
BOOL ProvAbstractTaskObject :: WaitDispatch ( ProvThreadObject *a_ThreadObject, HANDLE a_Handle , BOOL &a_Processed )
{
BOOL t_Status = TRUE ;
if ( a_Handle == m_CompletionEvent.GetHandle () )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nWait: Completed") );
)
m_CompletionEvent.Process () ;
a_Processed = TRUE ;
}
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nTask Wait: Refreshing handles") );
)
a_ThreadObject->Process () ;
a_ThreadObject->ConstructEventContainer () ;
}
else
{
ProvAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
if ( t_TaskObject )
{
a_ThreadObject->ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: Illegal Task") ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
BOOL ProvAbstractTaskObject :: WaitAcknowledgement ( BOOL a_Dispatch )
{
BOOL t_Status = TRUE ;
BOOL t_Processed = FALSE ;
while ( t_Status && ! t_Processed )
{
ProvThreadObject *t_ThreadObject = ProvThreadObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: 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(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: Illegal Handle index") ) ;
)
t_Status = FALSE ;
}
delete [] t_TaskEventArray ;
}
return t_Status ;
}
BOOL ProvAbstractTaskObject :: WaitAcknowledgementDispatch ( ProvThreadObject *a_ThreadObject , HANDLE a_Handle , BOOL &a_Processed )
{
BOOL t_Status = TRUE ;
if ( a_Handle == m_AcknowledgementEvent.GetHandle () )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nWait: Completed") );
)
m_AcknowledgementEvent.Process () ;
a_Processed = TRUE ;
}
else if ( a_ThreadObject && ( a_Handle == a_ThreadObject->GetHandle () ) )
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nTask Wait: Refreshing handles") );
)
a_ThreadObject->Process () ;
a_ThreadObject->ConstructEventContainer () ;
}
else
{
ProvAbstractTaskObject *t_TaskObject = a_ThreadObject->GetTaskObject ( a_Handle ) ;
if ( t_TaskObject )
{
a_ThreadObject->ConstructEventContainer () ;
t_TaskObject->Process () ;
}
else
{
DebugMacro8(
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine ( _TEXT(__FILE__),__LINE__, _TEXT("\nProvAbstractTaskObject :: Illegal Task") ) ;
)
t_Status = FALSE ;
}
}
return t_Status ;
}
ProvTaskObject::ProvTaskObject (
const TCHAR *a_GlobalTaskNameStart,
const TCHAR *a_GlobalTaskNameComplete ,
const TCHAR *a_GlobalTaskNameAcknowledge,
DWORD a_timeout
): ProvAbstractTaskObject(a_GlobalTaskNameComplete, a_GlobalTaskNameAcknowledge,a_timeout), m_Event(a_GlobalTaskNameStart)
{
}