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
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)
|
|
{
|
|
}
|