/*++ Copyright (C) 1996-2001 Microsoft Corporation Module Name: ProvResv.cpp Abstract: History: --*/ #include "PreComp.h" #include #include #include "CGlobals.h" #include "ProvObjectSink.h" #include #ifdef DBG fn__uncaught_exception InterlockedGuard::__uncaught_exception = NULL; InterlockedGuard::FunctLoader InterlockedGuard::FunctLoader_; #endif /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ #pragma warning( disable : 4355 ) CCommon_IWbemSyncObjectSink :: CCommon_IWbemSyncObjectSink ( WmiAllocator &a_Allocator , IWbemObjectSink *a_InterceptedSink , IUnknown *a_Unknown , CWbemGlobal_IWmiObjectSinkController *a_Controller , ULONG a_Dependant ) : ObjectSinkContainerElement ( a_Controller , a_InterceptedSink ) , m_InterceptedSink ( a_InterceptedSink ) , m_GateClosed ( 0 ) , m_InProgress ( 0 ) , m_Unknown ( a_Unknown ) , m_StatusCalled ( FALSE ) , m_Dependant ( a_Dependant ) { if ( m_Unknown ) { m_Unknown->AddRef () ; } if ( m_InterceptedSink ) { m_InterceptedSink->AddRef () ; } } #pragma warning( default : 4355 ) /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ CCommon_IWbemSyncObjectSink :: ~CCommon_IWbemSyncObjectSink () { } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ void CCommon_IWbemSyncObjectSink :: CallBackInternalRelease () { if ( ! InterlockedCompareExchange ( & m_StatusCalled , 0 , 0 ) ) { m_InterceptedSink->SetStatus ( 0 , WBEM_E_UNEXPECTED , NULL , NULL ) ; } if ( m_InterceptedSink ) { m_InterceptedSink->Release () ; } if ( m_Unknown ) { m_Unknown->Release () ; } } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ STDMETHODIMP CCommon_IWbemSyncObjectSink :: QueryInterface ( REFIID iid , LPVOID FAR *iplpv ) { *iplpv = NULL ; if ( iid == IID_IUnknown ) { *iplpv = ( LPVOID ) this ; } else if ( iid == IID_IWbemObjectSink ) { *iplpv = ( LPVOID ) ( IWbemObjectSink * ) this ; } else if ( iid == IID_IWbemShutdown ) { *iplpv = ( LPVOID ) ( IWbemShutdown * ) this ; } if ( *iplpv ) { ( ( LPUNKNOWN ) *iplpv )->AddRef () ; return ResultFromScode ( S_OK ) ; } else { return ResultFromScode ( E_NOINTERFACE ) ; } } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ STDMETHODIMP_(ULONG) CCommon_IWbemSyncObjectSink :: AddRef ( void ) { return ObjectSinkContainerElement :: AddRef () ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ STDMETHODIMP_(ULONG) CCommon_IWbemSyncObjectSink :: Release ( void ) { return ObjectSinkContainerElement :: Release () ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: SinkInitialize () { HRESULT t_Result = S_OK ; return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: Indicate ( long a_ObjectCount , IWbemClassObject **a_ObjectArray ) { HRESULT t_Result = S_OK ; InterlockedGuard ig(&m_InProgress); if ( m_GateClosed ) { t_Result = WBEM_E_SHUTTING_DOWN ; } else { t_Result = Helper_Indicate ( a_ObjectCount , a_ObjectArray ) ; #ifdef DBG if ( FAILED ( t_Result ) ) { DbgPrintfA(0,"CCommon_IWbemSyncObjectSink :: Indicate - %08x",t_Result) ; } #endif } return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: Helper_Indicate ( long a_ObjectCount , IWbemClassObject **a_ObjectArray ) { HRESULT t_Result = m_InterceptedSink->Indicate ( a_ObjectCount , a_ObjectArray ) ; return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: Helper_SetStatus ( long a_Flags , HRESULT a_Result , BSTR a_StringParam , IWbemClassObject *a_ObjectParam ) { HRESULT t_Result = S_OK ; BSTR t_StringParam = NULL ; if ( a_StringParam ) { t_StringParam = SysAllocString ( a_StringParam ) ; if ( t_StringParam == NULL ) { t_Result = WBEM_E_OUT_OF_MEMORY ; } } if ( SUCCEEDED ( t_Result ) ) { t_Result = m_InterceptedSink->SetStatus ( a_Flags , a_Result , t_StringParam , a_ObjectParam ) ; SysFreeString ( t_StringParam ) ; } return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: SetStatus ( long a_Flags , HRESULT a_Result , BSTR a_StringParam , IWbemClassObject *a_ObjectParam ) { HRESULT t_Result = S_OK ; InterlockedGuard ig(&m_InProgress); if ( m_GateClosed ) { t_Result = WBEM_E_SHUTTING_DOWN ; } else { switch ( a_Flags ) { case WBEM_STATUS_PROGRESS: { t_Result = Helper_SetStatus ( a_Flags , a_Result , a_StringParam , a_ObjectParam ) ; } break ; case WBEM_STATUS_COMPLETE: { if ( ! InterlockedCompareExchange ( & m_StatusCalled , 1 , 0 ) ) { t_Result = Helper_SetStatus ( a_Flags , a_Result , a_StringParam , a_ObjectParam ) ; } } break ; default: { t_Result = WBEM_E_INVALID_PARAMETER ; } break ; } } return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_IWbemSyncObjectSink :: Shutdown ( LONG a_Flags , ULONG a_MaxMilliSeconds , IWbemContext *a_Context ) { HRESULT t_Result = S_OK ; InterlockedIncrement ( & m_GateClosed ) ; if ( ! InterlockedCompareExchange ( & m_StatusCalled , 1 , 0 ) ) { t_Result = Helper_SetStatus ( 0 , WBEM_E_SHUTTING_DOWN , NULL , NULL ) ; } bool t_Acquired = false ; while ( ! t_Acquired ) { if ( m_InProgress == 0 ) { t_Acquired = true ; break ; } if ( SwitchToThread () == FALSE ) { } } return t_Result ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ #pragma warning( disable : 4355 ) CCommon_Batching_IWbemSyncObjectSink :: CCommon_Batching_IWbemSyncObjectSink ( WmiAllocator &a_Allocator , IWbemObjectSink *a_InterceptedSink , IUnknown *a_Unknown , CWbemGlobal_IWmiObjectSinkController *a_Controller , ULONG a_Dependant ) : CCommon_IWbemSyncObjectSink ( a_Allocator , a_InterceptedSink , a_Unknown , a_Controller , a_Dependant ) , m_Queue ( a_Allocator ) , m_Size ( 0 ), m_CriticalSection(NOTHROW_LOCK) { } #pragma warning( default : 4355 ) /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ CCommon_Batching_IWbemSyncObjectSink :: ~CCommon_Batching_IWbemSyncObjectSink () { ULONG t_Count = m_Queue.Size(); for ( ULONG t_Index = 0 ; t_Index < t_Count ; t_Index ++ ) { IWbemClassObject *t_ClassObject ; WmiStatusCode t_StatusCode = m_Queue.Top ( t_ClassObject ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_ClassObject->Release () ; t_StatusCode = m_Queue.DeQueue () ; } } m_Queue.UnInitialize () ; WmiHelper :: DeleteCriticalSection ( & m_CriticalSection ); } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_Batching_IWbemSyncObjectSink :: SinkInitialize () { HRESULT t_Result = CCommon_IWbemSyncObjectSink :: SinkInitialize () ; if ( SUCCEEDED ( t_Result ) ) { WmiStatusCode t_StatusCode = WmiHelper :: InitializeCriticalSection ( & m_CriticalSection ); if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_Queue.Initialize () ; if ( t_StatusCode == e_StatusCode_Success ) { } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } } return t_Result ; } class CReleaseMe { private: IUnknown * m_pUnk; public: CReleaseMe(IUnknown * pUnk):m_pUnk(pUnk){}; ~CReleaseMe(){ m_pUnk->Release(); }; }; /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_Batching_IWbemSyncObjectSink :: Indicate ( long a_ObjectCount , IWbemClassObject **a_ObjectArray ) { HRESULT t_Result = S_OK ; if ( m_GateClosed == 0 ) { WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_CriticalSection , FALSE ) ; if ( t_StatusCode == e_StatusCode_Success ) { for ( LONG t_Index = 0 ; SUCCEEDED ( t_Result ) && ( t_Index < a_ObjectCount ) ; t_Index ++ ) { if ( a_ObjectArray [ t_Index ] ) { IWbemClassObject *t_ClonedObject = NULL ; t_Result = a_ObjectArray [ t_Index ]->Clone ( &t_ClonedObject ) ; if ( SUCCEEDED ( t_Result ) ) { CReleaseMe rmCloned(t_ClonedObject); ULONG t_ObjectSize = 0 ; _IWmiObject *t_Object ; HRESULT t_TempResult = t_ClonedObject->QueryInterface ( IID__IWmiObject , ( void ** ) & t_Object ) ; if ( SUCCEEDED ( t_TempResult ) ) { CReleaseMe rmQIed(t_Object); t_TempResult = t_Object->GetObjectMemory ( NULL , 0 , & t_ObjectSize ); if ( t_TempResult == WBEM_E_BUFFER_TOO_SMALL ) { WmiStatusCode t_StatusCode = m_Queue.EnQueue ( t_ClonedObject ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_ClonedObject ->AddRef(); m_Size = m_Size + t_ObjectSize ; } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } if ( SUCCEEDED(t_Result) && (( m_Size ) >= ProviderSubSystem_Common_Globals :: GetTransmitSize () )) { ULONG t_Count = m_Queue.Size () ; IWbemClassObject **t_Array = new IWbemClassObject * [ t_Count ] ; if ( t_Array ) { IWbemClassObject *t_ClassObject ; WmiStatusCode t_StatusCode ; ULONG t_InnerIndex = 0 ; while ( ( t_StatusCode = m_Queue.Top ( t_ClassObject ) ) == e_StatusCode_Success ) { t_Array [ t_InnerIndex ] = t_ClassObject ; t_InnerIndex ++ ; t_StatusCode = m_Queue.DeQueue() ; } m_Size = 0 ; WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ; t_Result = CCommon_IWbemSyncObjectSink :: Indicate ( t_Count , t_Array ) ; for ( t_InnerIndex = 0 ; t_InnerIndex < t_Count ; t_InnerIndex ++ ) { t_Array [ t_InnerIndex ]->Release () ; } delete [] t_Array ; t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_CriticalSection , FALSE ) ; if ( t_StatusCode == e_StatusCode_Success ) { } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } } } else { t_Result = WBEM_E_CRITICAL_ERROR ; } } else { t_Result = WBEM_E_CRITICAL_ERROR ; } } } } WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ); return t_Result ; } else { return WBEM_E_OUT_OF_MEMORY ; } } else { return WBEM_E_SHUTTING_DOWN ; } } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ HRESULT CCommon_Batching_IWbemSyncObjectSink :: SetStatus ( long a_Flags , HRESULT a_Result , BSTR a_StringParam , IWbemClassObject *a_ObjectParam ) { HRESULT t_Result = S_OK ; switch ( a_Flags ) { case WBEM_STATUS_COMPLETE: { if ( m_GateClosed == 0 ) { WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_CriticalSection , FALSE ); if ( t_StatusCode == e_StatusCode_Success ) { LONG t_Count = m_Queue.Size () ; if ( t_Count ) { IWbemClassObject **t_Array = new IWbemClassObject * [ m_Queue.Size () ] ; if ( t_Array ) { for ( LONG t_Index = 0 ; t_Index < t_Count ; t_Index ++ ) { IWbemClassObject *t_ClassObject ; WmiStatusCode t_StatusCode = m_Queue.Top ( t_ClassObject ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_Array [ t_Index ] = t_ClassObject ; t_StatusCode = m_Queue.DeQueue () ; } } WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ); t_Result = CCommon_IWbemSyncObjectSink :: Indicate ( t_Count , t_Array ) ; for ( t_Index = 0 ; t_Index < t_Count ; t_Index ++ ) { if ( t_Array [ t_Index ] ) { t_Array [ t_Index ]->Release () ; } } delete [] t_Array ; } else { WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ); t_Result = WBEM_E_OUT_OF_MEMORY ; } } else { WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ); } } else { t_Result = WBEM_E_OUT_OF_MEMORY ; } } if ( FAILED ( t_Result ) ) { a_Result = t_Result ; } t_Result = CCommon_IWbemSyncObjectSink :: SetStatus ( a_Flags , a_Result , a_StringParam , a_ObjectParam ) ; } break ; default: { t_Result = CCommon_IWbemSyncObjectSink :: SetStatus ( a_Flags , a_Result , a_StringParam , a_ObjectParam ) ; } break ; } return t_Result ; }