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.
226 lines
6.3 KiB
226 lines
6.3 KiB
//******************************************************************************
|
|
//
|
|
// ESSUTILS.CPP
|
|
//
|
|
// Copyright (C) 1996-1999 Microsoft Corporation
|
|
//
|
|
//******************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include "ess.h"
|
|
#include "essutils.h"
|
|
#include <tls.h>
|
|
|
|
CTLS g_tlsContext;
|
|
|
|
long g_lNumExternalThreadObjects = 0;
|
|
|
|
INTERNAL CEssThreadObject* GetCurrentEssThreadObject()
|
|
{
|
|
CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
|
|
if ( pObj != NULL )
|
|
{
|
|
//
|
|
// mark the fact that we are handing the thread object to the
|
|
// outside world. We use this later on when checking
|
|
// thread object leaks.
|
|
//
|
|
pObj->SetReferencedExternally();
|
|
}
|
|
|
|
return pObj;
|
|
}
|
|
|
|
void SetCurrentEssThreadObject(IWbemContext* pContext)
|
|
{
|
|
//
|
|
// make sure we're not overwriting an existing internal thread object.
|
|
// if its externally referenced, we really can't tell if this would
|
|
// be a leak or not.
|
|
//
|
|
CEssThreadObject* pOldObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
_DBG_ASSERT( pOldObj == NULL || pOldObj->IsReferencedExternally() );
|
|
|
|
CEssThreadObject* pObj = new CEssThreadObject(pContext);
|
|
g_tlsContext.Set((void*)pObj);
|
|
}
|
|
|
|
void SetConstructedEssThreadObject(CEssThreadObject* pObj)
|
|
{
|
|
//
|
|
// make sure we're not overwriting an existing internal thread object.
|
|
// if its externally referenced, we really can't tell if this would
|
|
// be a leak or not.
|
|
//
|
|
CEssThreadObject* pOldObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
_DBG_ASSERT( pOldObj == NULL || pOldObj->IsReferencedExternally() );
|
|
|
|
//
|
|
// since this object was passed in from the outside world, then
|
|
// mark it as externally referenced.
|
|
//
|
|
if ( pObj != NULL )
|
|
{
|
|
pObj->SetReferencedExternally();
|
|
}
|
|
|
|
g_tlsContext.Set((void*)pObj);
|
|
}
|
|
|
|
void ClearCurrentEssThreadObject()
|
|
{
|
|
//
|
|
// make sure we're not overwriting an existing internal thread object.
|
|
// if its externally referenced, we really can't tell if this would
|
|
// be a leak or not.
|
|
//
|
|
CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
_DBG_ASSERT( pObj == NULL || pObj->IsReferencedExternally() );
|
|
|
|
g_tlsContext.Set(NULL);
|
|
}
|
|
|
|
INTERNAL IWbemContext* GetCurrentEssContext()
|
|
{
|
|
CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
if(pThreadObj)
|
|
return pThreadObj->m_pContext;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
INTERNAL CPostponedList* GetCurrentPostponedList()
|
|
{
|
|
CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
if(pThreadObj)
|
|
return &pThreadObj->m_PostponedList;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
INTERNAL CPostponedList* GetCurrentPostponedEventList()
|
|
{
|
|
CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
if(pThreadObj)
|
|
return &pThreadObj->m_PostponedEventList;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
CEssThreadObject::CEssThreadObject( IWbemContext* pContext )
|
|
: m_bReferencedExternally( FALSE )
|
|
{
|
|
m_pContext = pContext;
|
|
|
|
if( m_pContext == NULL )
|
|
{
|
|
m_pContext = GetSpecialContext();
|
|
}
|
|
|
|
if ( m_pContext != NULL )
|
|
{
|
|
m_pContext->AddRef();
|
|
}
|
|
}
|
|
|
|
void CEssThreadObject::SetReferencedExternally()
|
|
{
|
|
if ( !m_bReferencedExternally )
|
|
{
|
|
g_lNumExternalThreadObjects++;
|
|
m_bReferencedExternally = TRUE;
|
|
}
|
|
}
|
|
|
|
IWbemContext* CEssThreadObject::mstatic_pSpecialContext = NULL;
|
|
|
|
INTERNAL IWbemContext* CEssThreadObject::GetSpecialContext()
|
|
{
|
|
// Create a "special" context object that will make sure that our
|
|
// calls back into CIMOM are not blocked
|
|
// ==============================================================
|
|
|
|
if(mstatic_pSpecialContext == NULL)
|
|
{
|
|
IWbemCausalityAccess* pCause = NULL;
|
|
HRESULT hres = CoCreateInstance(CLSID_WbemContext, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IWbemCausalityAccess,
|
|
(void**)&pCause);
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "Unable to create special context object: "
|
|
"0x%X. Danger of deadlock\n", hres));
|
|
return NULL;
|
|
}
|
|
|
|
CReleaseMe rm1(pCause);
|
|
|
|
hres = pCause->MakeSpecial();
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "Unable to make the context special: "
|
|
"0x%X. Danger of deadlock\n", hres));
|
|
return NULL;
|
|
}
|
|
|
|
IWbemContext* pContext = NULL;
|
|
hres = pCause->QueryInterface(IID_IWbemContext, (void**)&pContext);
|
|
if(FAILED(hres))
|
|
{
|
|
ERRORTRACE((LOG_ESS, "Internal error: invalid context (0x%X)\n",
|
|
hres));
|
|
return NULL;
|
|
}
|
|
|
|
if(mstatic_pSpecialContext == NULL) // tiny window for a one-time leak
|
|
mstatic_pSpecialContext = pContext;
|
|
else
|
|
pContext->Release();
|
|
}
|
|
return mstatic_pSpecialContext;
|
|
}
|
|
|
|
CEssThreadObject::~CEssThreadObject()
|
|
{
|
|
if ( m_bReferencedExternally )
|
|
{
|
|
g_lNumExternalThreadObjects--;
|
|
|
|
//
|
|
// since ClearCurrentEssThreadObject() can reference the
|
|
// thread object ( for leak checking ) and because we previously
|
|
// supported the thread object being deleted before
|
|
// CurrentThreadEssThreadObject(), make sure that we perform the
|
|
// Clear if the current thread object matches this one. This only
|
|
// can happen when the thread object is referenced externally.
|
|
//
|
|
|
|
CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
|
|
|
|
if ( pObj == this )
|
|
{
|
|
ClearCurrentEssThreadObject();
|
|
}
|
|
}
|
|
|
|
_DBG_ASSERT( m_PostponedList.IsEmpty() );
|
|
|
|
if ( m_pContext != NULL )
|
|
{
|
|
m_pContext->Release();
|
|
}
|
|
}
|
|
|
|
void /*static*/ CEssThreadObject::ClearSpecialContext()
|
|
{
|
|
// Call only when no other work can be taking place, e.g. in DllCanUnloadNow
|
|
// =========================================================================
|
|
|
|
if(mstatic_pSpecialContext)
|
|
mstatic_pSpecialContext->Release();
|
|
mstatic_pSpecialContext = NULL;
|
|
}
|
|
|
|
|