windows-nt/Source/XPSP1/NT/admin/wmi/wbem/scripting/error.cpp
2020-09-26 16:20:57 +08:00

362 lines
7.8 KiB
C++

//***************************************************************************
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// ERROR.CPP
//
// alanbos 28-Jun-98 Created.
//
// Defines the WBEM error cache implementation
//
//***************************************************************************
#include "precomp.h"
#define NULLBSTR(x) \
SysFreeString (x);\
x = NULL;
#define FREECOAUTH(x) \
if (x)\
{\
WbemFreeAuthIdentity (x);\
x = NULL;\
}
//***************************************************************************
//
// CWbemErrorCache::CWbemErrorCache
//
// DESCRIPTION:
//
// Constructor
//
//***************************************************************************
CWbemErrorCache::CWbemErrorCache ()
{
InitializeCriticalSection (&m_cs);
headPtr = NULL;
}
//***************************************************************************
//
// CWbemErrorCache::~CWbemErrorCache
//
// DESCRIPTION:
//
// Destructor
//
//***************************************************************************
CWbemErrorCache::~CWbemErrorCache ()
{
EnterCriticalSection (&m_cs);
ThreadError *pPtr = headPtr;
while (pPtr)
{
if (pPtr->pErrorObject)
{
pPtr->pErrorObject->Release ();
pPtr->pErrorObject = NULL;
}
if (pPtr->pService)
{
pPtr->pService->Release ();
pPtr->pService = NULL;
}
NULLBSTR (pPtr->strNamespacePath);
NULLBSTR (pPtr->strAuthority);
NULLBSTR (pPtr->strPrincipal);
FREECOAUTH (pPtr->pCoAuthIdentity)
ThreadError *pTmp = pPtr;
pPtr = pPtr->pNext;
delete pTmp;
}
headPtr = NULL;
LeaveCriticalSection (&m_cs);
DeleteCriticalSection (&m_cs);
}
//***************************************************************************
//
// CWbemErrorCache::GetAndResetCurrentThreadError
//
// DESCRIPTION:
//
// Extract the WBEM error object (if any) from the current thread. This
// is a once-only operation as the entry for that thread is cleared by this
// read.
//
//***************************************************************************
CSWbemObject *CWbemErrorCache::GetAndResetCurrentThreadError ()
{
CSWbemObject *pObject = NULL;
DWORD threadId = GetCurrentThreadId ();
EnterCriticalSection (&m_cs);
ThreadError *pPtr = headPtr;
while (pPtr)
{
if (threadId == pPtr->dwThreadId)
{
if (pPtr->pErrorObject)
{
CSWbemServices *pService = NULL;
// Try and create a services object
if (pPtr->pService)
{
pService = new CSWbemServices (pPtr->pService, pPtr->strNamespacePath,
pPtr->pCoAuthIdentity, pPtr->strPrincipal,
pPtr->strAuthority);
if (pService)
pService->AddRef ();
}
if (pPtr->pService)
{
pPtr->pService->Release ();
pPtr->pService = NULL;
}
NULLBSTR (pPtr->strNamespacePath);
NULLBSTR (pPtr->strAuthority);
NULLBSTR (pPtr->strPrincipal);
FREECOAUTH (pPtr->pCoAuthIdentity)
pObject = new CSWbemObject (pService, pPtr->pErrorObject, NULL, true);
pPtr->pErrorObject->Release ();
pPtr->pErrorObject = NULL;
if (pService)
pService->Release ();
// Unhook and delete the ThreadError
if (pPtr == headPtr)
headPtr = pPtr->pNext;
if (pPtr->pNext)
pPtr->pNext->pPrev = pPtr->pPrev;
if (pPtr->pPrev)
pPtr->pPrev->pNext = pPtr->pNext;
delete pPtr;
}
break;
}
pPtr = pPtr->pNext;
}
LeaveCriticalSection (&m_cs);
return pObject;
}
//***************************************************************************
//
// CWbemErrorCache::SetCurrentThreadError
//
// DESCRIPTION:
//
// Set the WBEM error object (if any) for the current thread.
//
//***************************************************************************
void CWbemErrorCache::SetCurrentThreadError (CSWbemServices *pService)
{
IErrorInfo * pInfo = NULL;
if(SUCCEEDED(GetErrorInfo(0, &pInfo)) && pInfo)
{
// Is this a WBEM Error Object?
IWbemClassObject * pObj = NULL;
if(SUCCEEDED(pInfo->QueryInterface(IID_IWbemClassObject, (void **)&pObj)) && pObj)
{
DWORD threadId = GetCurrentThreadId ();
EnterCriticalSection (&m_cs);
ThreadError *pPtr = headPtr;
// Find the current entry (if any)
while (pPtr)
{
if (threadId == pPtr->dwThreadId)
break;
pPtr = pPtr->pNext;
}
// Have a new error object - chain it into the list
if (!pPtr)
{
// No entry for this thread - create one at the head
ThreadError *pTmp = headPtr;
headPtr = new ThreadError;
if (headPtr)
{
headPtr->pPrev = NULL;
headPtr->pNext = pTmp;
if (pTmp)
pTmp->pPrev = headPtr;
headPtr->dwThreadId = threadId;
headPtr->pErrorObject = pObj;
headPtr->pService = NULL;
headPtr->strAuthority = NULL;
headPtr->strPrincipal = NULL;
headPtr->pCoAuthIdentity = NULL;
headPtr->strNamespacePath = NULL;
if (pService)
{
headPtr->pService = pService->GetIWbemServices ();
CSWbemSecurity *pSecurity = pService->GetSecurityInfo ();
if (pSecurity)
{
headPtr->strAuthority = SysAllocString (pSecurity->GetAuthority ());
headPtr->strPrincipal = SysAllocString (pSecurity->GetPrincipal ());
headPtr->pCoAuthIdentity = pSecurity->GetCoAuthIdentity ();
pSecurity->Release ();
}
headPtr->strNamespacePath = SysAllocString(pService->GetPath ());
}
}
}
else
{
// pPtr addresses the current entry for the thread
/***************************************************
* We should not actually do this any more as we
* remove the entry both when it is read and at the
* start of the API call. So at this point there should
* not be any entries left for this thread
****************************************************/
if (pPtr->pErrorObject)
pPtr->pErrorObject->Release ();
pPtr->pErrorObject = pObj;
if (pPtr->pService)
{
pPtr->pService->Release ();
pPtr->pService = NULL;
}
NULLBSTR (pPtr->strNamespacePath);
NULLBSTR (pPtr->strAuthority);
NULLBSTR (pPtr->strPrincipal);
FREECOAUTH (pPtr->pCoAuthIdentity)
if (pService)
{
pPtr->pService = pService->GetIWbemServices ();
CSWbemSecurity *pSecurity = pService->GetSecurityInfo ();
if (pSecurity)
{
pPtr->strAuthority = SysAllocString (pSecurity->GetAuthority ());
pPtr->strPrincipal = SysAllocString (pSecurity->GetPrincipal ());
pPtr->pCoAuthIdentity = pSecurity->GetCoAuthIdentity ();
pSecurity->Release ();
}
pPtr->strNamespacePath = SysAllocString(pService->GetPath ());
}
}
LeaveCriticalSection (&m_cs);
}
pInfo->Release (); // To balance the GetErrorInfo call
}
}
//***************************************************************************
//
// CWbemErrorCache::ResetCurrentThreadError
//
// DESCRIPTION:
//
// If there is an entry for the current thread then remove it
//
//***************************************************************************
void CWbemErrorCache::ResetCurrentThreadError ()
{
DWORD threadId = GetCurrentThreadId ();
EnterCriticalSection (&m_cs);
ThreadError *pPtr = headPtr;
// Find the current entry (if any)
while (pPtr)
{
if (threadId == pPtr->dwThreadId)
break;
pPtr = pPtr->pNext;
}
if (pPtr)
{
// pPtr addresses the current entry for the thread
if (pPtr->pErrorObject)
{
pPtr->pErrorObject->Release ();
pPtr->pErrorObject = NULL;
}
if (pPtr->pService)
{
pPtr->pService->Release ();
pPtr->pService = NULL;
}
NULLBSTR (pPtr->strNamespacePath);
NULLBSTR (pPtr->strAuthority);
NULLBSTR (pPtr->strPrincipal);
FREECOAUTH (pPtr->pCoAuthIdentity)
// Unhook and delete the ErrorInfo
if (pPtr == headPtr)
headPtr = pPtr->pNext;
if (pPtr->pNext)
pPtr->pNext->pPrev = pPtr->pPrev;
if (pPtr->pPrev)
pPtr->pPrev->pNext = pPtr->pNext;
delete pPtr;
}
LeaveCriticalSection (&m_cs);
}