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.
803 lines
16 KiB
803 lines
16 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ProvResv.cpp
|
|
|
|
Abstract:
|
|
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "PreComp.h"
|
|
#include <wbemint.h>
|
|
#include <stdio.h>
|
|
|
|
#include "CGlobals.h"
|
|
#include "ProvObjectSink.h"
|
|
|
|
#include <wbemutil.h>
|
|
|
|
#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 ;
|
|
}
|
|
|