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.
249 lines
6.6 KiB
249 lines
6.6 KiB
/*++
|
|
|
|
Copyright (C) 2001 Microsoft Corporation
|
|
|
|
Module Name: ErrorObj
|
|
|
|
Abstract: IErrorInfo support for the standard consumers
|
|
|
|
History: 07/11/2001 - creation, HHance.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
//#include <stdio.h>
|
|
#include <wbemutil.h>
|
|
//#include <ArrTempl.h>
|
|
//#include <lmaccess.h>
|
|
#include <wbemdisp.h>
|
|
//#include "ScriptKiller.h"
|
|
//#include "script.h"
|
|
//#include "ClassFac.h"
|
|
//#include <GroupsForUser.h>
|
|
#include <GenUtils.h>
|
|
|
|
#include "ErrorObj.h"
|
|
#include <strsafe.h>
|
|
|
|
|
|
#define ClassName L"__ExtendedStatus"
|
|
|
|
// no touch. Use GetErrorObj instead.
|
|
ErrorObj StaticErrorObj;
|
|
|
|
// so we can manage our component's lifetimes in the wunnerful world of COM, etc...
|
|
// returns addref'd error object
|
|
ErrorObj* ErrorObj::GetErrorObj()
|
|
{
|
|
StaticErrorObj.AddRef();
|
|
return &StaticErrorObj;
|
|
}
|
|
|
|
|
|
// returns adref'd namespace ("root")
|
|
IWbemServices* ErrorObj::GetMeANamespace()
|
|
{
|
|
IWbemServices* pNamespace = NULL;
|
|
IWbemLocator* pLocator = NULL;
|
|
|
|
if (SUCCEEDED(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator, (void**)&pLocator)))
|
|
{
|
|
BSTR bstrNamespace;
|
|
bstrNamespace = SysAllocString(L"root");
|
|
|
|
if (bstrNamespace)
|
|
{
|
|
pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
|
|
SysFreeString(bstrNamespace);
|
|
}
|
|
|
|
pLocator->Release();
|
|
}
|
|
|
|
return pNamespace;
|
|
}
|
|
|
|
|
|
ULONG ErrorObj::AddRef()
|
|
{
|
|
// since we don't do a delete this
|
|
// there is a chance that someone could sneak in and re-init while we're in the process
|
|
// of shutting down. That would be bad.
|
|
// Hence we use our own CS instead of interlockedXXrement.
|
|
|
|
CInCritSec cs( &m_cs );
|
|
|
|
ULONG count = ++m_lRef;
|
|
|
|
return count;
|
|
}
|
|
|
|
// we do not do a 'delete this' here.
|
|
// We just release the COM objects
|
|
ULONG ErrorObj::Release()
|
|
{
|
|
// since we don't do a 'delete this'
|
|
// there is a chance that someone could sneak in and re-init
|
|
// while we're in the process of shutting down.
|
|
// That would be bad.
|
|
// Hence we use our own CS instead of interlockedXXrement.
|
|
CInCritSec cs( &m_cs );
|
|
|
|
ULONG count = --m_lRef;
|
|
|
|
if (m_lRef == 0)
|
|
{
|
|
if (m_pErrorObject)
|
|
{
|
|
m_pErrorObject->Release();
|
|
m_pErrorObject = NULL;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
// does the real work, creates the object, populates it, sends it off.
|
|
// arguments map to __ExtendedStatus class.
|
|
// void func - what are y'gonna do if you can't report an error? Report an error?
|
|
// bFormat - will attempt to use FormatError to fill in the description if NULL.
|
|
void ErrorObj::ReportError(const WCHAR* operation, const WCHAR* parameterInfo, const WCHAR* description, UINT statusCode, bool bFormat)
|
|
{
|
|
// a shiny new instance of __ExtendedStatus
|
|
IWbemClassObject* pObj = GetObj();
|
|
IErrorInfo* pEI = NULL;
|
|
|
|
if (pObj && SUCCEEDED(pObj->QueryInterface(IID_IErrorInfo, (void**)&pEI)))
|
|
{
|
|
// theory: I'm going to try to set everything.
|
|
// something might fail along the way. At this point
|
|
// the biggest disaster would be that the user got partial info
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
|
|
// Operation
|
|
if (operation)
|
|
{
|
|
v.bstrVal = SysAllocString(operation);
|
|
if (v.bstrVal)
|
|
{
|
|
pObj->Put(L"Operation", 0, &v, 0);
|
|
SysFreeString(v.bstrVal);
|
|
}
|
|
}
|
|
|
|
// ParameterInfo
|
|
if (parameterInfo)
|
|
{
|
|
v.bstrVal = SysAllocString(parameterInfo);
|
|
if (v.bstrVal)
|
|
{
|
|
pObj->Put(L"ParameterInfo", 0, &v, 0);
|
|
SysFreeString(v.bstrVal);
|
|
}
|
|
}
|
|
|
|
|
|
// Description
|
|
if (description)
|
|
v.bstrVal = SysAllocString(description);
|
|
else if (bFormat)
|
|
{
|
|
WCHAR* pMsg = NULL;
|
|
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL, statusCode, 0, (WCHAR*)&pMsg, 1, NULL) && pMsg)
|
|
{
|
|
v.bstrVal = SysAllocString(pMsg);
|
|
LocalFree(pMsg);
|
|
}
|
|
else
|
|
v.bstrVal = NULL;
|
|
}
|
|
else
|
|
v.bstrVal = NULL;
|
|
|
|
if (v.bstrVal)
|
|
{
|
|
pObj->Put(L"Description", 0, &v, 0);
|
|
SysFreeString(v.bstrVal);
|
|
}
|
|
|
|
|
|
// StatusCode
|
|
v.vt = VT_I4;
|
|
v.lVal = statusCode;
|
|
pObj->Put(L"StatusCode", 0, &v, 0);
|
|
|
|
// do it to it
|
|
SetErrorInfo(0, pEI);
|
|
}
|
|
|
|
if (pObj)
|
|
pObj->Release();
|
|
|
|
if (pEI)
|
|
pEI->Release();
|
|
|
|
}
|
|
|
|
// spawn off an object to be populated
|
|
// can't keep reusing same object as we have more than one thread going
|
|
IWbemClassObject* ErrorObj::GetObj()
|
|
{
|
|
IWbemClassObject* pObj = NULL;
|
|
|
|
// big CS -- need to guard against possibility of shut down
|
|
// occuring during startup.
|
|
CInCritSec cs( &m_cs );
|
|
|
|
if (!m_pErrorObject)
|
|
{
|
|
IWbemServices* pNamespace = NULL;
|
|
pNamespace = GetMeANamespace();
|
|
|
|
if (pNamespace)
|
|
{
|
|
BSTR className;
|
|
className = SysAllocString(ClassName);
|
|
|
|
if (className)
|
|
{
|
|
IWbemClassObject* pClassObject = NULL;
|
|
if (SUCCEEDED(pNamespace->GetObject(className, 0, NULL, &pClassObject, NULL)))
|
|
{
|
|
// okay, if it fails, then m_pErrorObject is still NULL. No problemo.
|
|
pClassObject->SpawnInstance(0, &m_pErrorObject);
|
|
pClassObject->Release();
|
|
}
|
|
|
|
SysFreeString(className);
|
|
}
|
|
|
|
pNamespace->Release();
|
|
}
|
|
}
|
|
|
|
if (m_pErrorObject)
|
|
m_pErrorObject->Clone(&pObj);
|
|
|
|
return pObj;
|
|
}
|
|
|
|
/************************ a legacy before it's shipped...
|
|
// must be called inside the CS.
|
|
// must be called prior to ReportError (if you expect it to succeed, anyway...)
|
|
void ErrorObj::SetNamespace(IWbemServices* pNamespace)
|
|
{
|
|
// first one in wins, after that it's static
|
|
if (pNamespace && !m_pNamespace)
|
|
{
|
|
if (!m_pNamespace)
|
|
{
|
|
m_pNamespace = pNamespace;
|
|
m_pNamespace->AddRef();
|
|
}
|
|
}
|
|
}
|
|
*************************/
|