2025-04-27 07:49:33 -04:00

493 lines
21 KiB
C++

/******************************************************************
Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
ReindeerProv.CPP -- WBEM provider class implementation
Generated by Microsoft WBEM Code Generation Engine
TO DO: See individual function headers
Description:
Sample provider using the Provider Framework
******************************************************************/
#include <fwcommon.h> // This must be the first include.
#include "ReindeerProv.h"
// TO DO: Replace "NameSpace" with the appropriate namespace for your
// provider instance. For instance: "root\\default or "root\\cimv2".
//===================================================================
CReindeer MyReindeerProvSet (PROVIDER_NAME_REINDEERPROV, L"root\\default") ;
// Property names
//===============
const static WCHAR* pName = L"Name" ;
const static WCHAR* pRedNose = L"RedNose" ;
const static WCHAR* pWeight = L"Weight" ;
// Sample data
// ===========
Deers ohDeers[Deers::NDeers] =
{
// Name Weight Red Nose Deleted flag
{L"Dasher", 200, false, false},
{L"Dancer", 150, false, false},
{L"Prancer", 162, false, false},
{L"Vixen", 125, false, false},
{L"Comet", 212, false, false},
{L"Cupid", 196, false, false},
{L"Donder", 255, false, false},
{L"Blitzen", 145, false, false},
{L"Rudolf", 123, true, false}
};
/*****************************************************************************
*
* FUNCTION : CReindeer::CReindeer
*
* DESCRIPTION : Constructor
*
* INPUTS : none
*
* RETURNS : nothing
*
* COMMENTS : Calls the Provider constructor.
*
*****************************************************************************/
CReindeer::CReindeer (LPCWSTR pszName, LPCWSTR pszNameSpace ) :
Provider(pszName, pszNameSpace)
{
}
/*****************************************************************************
*
* FUNCTION : CReindeer::~CReindeer
*
* DESCRIPTION : Destructor
*
* INPUTS : none
*
* RETURNS : nothing
*
* COMMENTS :
*
*****************************************************************************/
CReindeer::~CReindeer ()
{
}
/*****************************************************************************
*
* FUNCTION : CReindeer::EnumerateInstances
*
* DESCRIPTION : Returns all the instances of this class.
*
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
* A long that contains the flags described in
* IWbemServices::CreateInstanceEnumAsync. Note that the following
* flags are handled by (and filtered out by) WinMgmt:
* WBEM_FLAG_DEEP
* WBEM_FLAG_SHALLOW
* WBEM_FLAG_RETURN_IMMEDIATELY
* WBEM_FLAG_FORWARD_ONLY
* WBEM_FLAG_BIDIRECTIONAL
*
* RETURNS : WBEM_S_NO_ERROR if successful
*
* COMMENTS : TO DO: All instances on the machine should be returned here.
* If there are no instances, return WBEM_S_NO_ERROR.
* It is not an error to have no instances.
*
*****************************************************************************/
HRESULT CReindeer::EnumerateInstances ( MethodContext* pMethodContext, long lFlags )
{
HRESULT hRes = WBEM_S_NO_ERROR;
// TO DO: The following commented lines contain the 'set' methods for the
// properties entered for this class. They are commented because they
// will NOT compile in their current form. Each <Property Value> should be
// replaced with the appropriate value.
//
// If the expectation is that there is more than one instance on the machine
// EnumerateInstances should loop through the instances and fill them accordingly.
//
// Note that you must ALWAYS set ALL the key properties. See the docs for
// further details.
///////////////////////////////////////////////////////////////////////////////
// create an instance for each reindeer
for (int i = 0; (i < Deers::NDeers) && (SUCCEEDED(hRes)); i++)
{
// we don't want to return deleted deer
if (!ohDeers[i].m_deleted)
{
CInstance *pInstance = CreateNewInstance(pMethodContext);
if (pInstance)
{
pInstance->SetCHString(pName, CHString(ohDeers[i].m_name));
pInstance->SetDWORD(pWeight, ohDeers[i].m_weight);
pInstance->Setbool(pRedNose, ohDeers[i].m_redNose);
hRes = Commit(pInstance);
}
else
{
// couldn't create new instance
hRes = WBEM_E_OUT_OF_MEMORY;
break;
}
}
}
return hRes ;
}
/*****************************************************************************
*
* FUNCTION : CReindeer::GetObject
*
* DESCRIPTION : Find a single instance based on the key properties for the
* class.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::GetObjectAsync.
*
* RETURNS : WBEM_S_NO_ERROR if the instance can be found
* WBEM_E_NOT_FOUND if the instance described by the key properties
* could not be found
* WBEM_E_FAILED if the instance could be found but another error
* occurred.
*
* COMMENTS :
*
*****************************************************************************/
HRESULT CReindeer::GetObject ( CInstance* pInstance, long lFlags )
{
// TO DO: The GetObject function is used to search for an instance of this
// class on the machine based on the key properties. Unlike
// EnumerateInstances which finds all instances on the machine, GetObject
// uses the key properties to find the matching single instance and
// returns that instance.
//
// Use the CInstance Get functions (GetCHString, etc) against pInstance to see
// the key values the client requested.
HRESULT hr = WBEM_E_NOT_FOUND;
// name is the key, we retrieve the name
CHString name;
pInstance->GetCHString(pName, name);
// search the array for a Reindeer with the name we're given
// (make sure he hasn't been deleted!)
for (int i = 0; i < Deers::NDeers; i++)
{
if (0 == name.CompareNoCase(CHString(ohDeers[i].m_name)) && !ohDeers[i].m_deleted)
{
// we found the one they're look for - fill in the data
pInstance->SetDWORD(pWeight, ohDeers[i].m_weight);
pInstance->Setbool(pRedNose, ohDeers[i].m_redNose);
hr = WBEM_S_NO_ERROR;
break;
}
}
return hr ;
}
/*****************************************************************************
*
* FUNCTION : CReindeer::ExecQuery
*
* DESCRIPTION : You are passed a method context to use in the creation of
* instances that satisfy the query, and a CFrameworkQuery
* which describes the query. Create and populate all
* instances which satisfy the query. WinMgmt will post -
* filter the query for you, so you may return more instances
* or more properties than are requested and WinMgmt
* will filter out any that do not apply.
*
*
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
* A query object describing the query to satisfy.
* A long that contains the flags described in
* IWbemServices::CreateInstanceEnumAsync. Note that the following
* flags are handled by (and filtered out by) WinMgmt:
* WBEM_FLAG_FORWARD_ONLY
* WBEM_FLAG_BIDIRECTIONAL
* WBEM_FLAG_ENSURE_LOCATABLE
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not supported for this class
* WBEM_E_FAILED if the query failed
* WBEM_S_NO_ERROR if query was successful
*
* COMMENTS : TO DO: Most providers will not need to implement this method. If you don't, WinMgmt
* will call your enumerate function to get all the instances and perform the
* filtering for you. Unless you expect SIGNIFICANT savings from implementing
* queries, you should remove this method.
*
*****************************************************************************/
HRESULT CReindeer::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags)
{
// While this class is too small to really benefit from query processing, this method is
// being instrumented to show how it could be done. There are two different ways query processing
// can be used to improve performance.
//
// Method 1 - Look at the fields that are being requested, and only return data for those fields. This
// can be a very big win for some classes if some properties are very expensive to retrieve. In
// our own LogicalDisk class, populating just the DeviceID field is very cheap. However, populating
// the FreeSpace property requires that we spin up the disk. For floppy, cd, and network drives,
// that is very expensive.
//
// Method 2 - Look at the where clause and only return the requested records. Obviously, this also has the
// potential to be a big win. For example, if the query is of the form 'Select Name, Size from
// CIM_Datafile where where drive="a:"', clearly this can be resolved much faster then doing the
// default behavior when no ExecQuery routine is specified (enumerating all directories on all
// drives and let Winmgmt pick out the matching entries).
// On the other hand, just because a WHERE clause in included doesn't mean that the query can be
// processed any faster. Consider a query of the form "Select * from CIM_Datafile where ReadOnly = TRUE"
// By the time we have called FindFirstFile and examined the structure, the most expensive parts
// of the processing is already done. How about a query of the form 'Select * from CIM_Datafile
// where Drive="a:" or ReadOnly = TRUE'? Again, to satisfy this query, we're going to have to walk
// all the instances on all the drives anyway since there is no way to specify to the Win32 API's that
// you only want ReadOnly files. Since Winmgmt already has a bunch of code to process instances
// against queries, there's no reason to add that complexity to our provider UNLESS we are getting
// a big performance win. If we send back a few too many instances, winmgmt will trim them out.
// For most classes, there are a few (sometimes only 1) properties that it makes sense to try to
// optimize on (CIM_Datafile actually does a bunch, but many other classes that process queries
// only do 1-2).
// So, there is a method that can be run against the CFrameworkQuery object where you pass it the name
// of a property, and it will tell you all the values they requested. For example, if the query is of
// the form 'Select * from Reindeer where name = "Dasher" or name = "Dancer" or name = "pickle"',
// GetValuesForProp(L"Name") would send back an array that contains {"Dasher", "Dancer", "pickle"}.
// Or if the query was of the form 'Select * from CIM_Datafile where Drive = "a:" AND ReadOnly = TRUE'
// (note that this query, unlike the one in the paragraph above, uses AND), then GetValuesForProp(L"Drive")
// would return {"a:"}. Given this array, you can quickly return just the few instances they requested. If
// there are additional clauses on the query that you didn't process, (like the Drive AND ReadOnly example
// above), don't worry. Winmgmt will discard the instances that don't match.
// In your provider, you can use either, neither, or both of these methods. In the code below,
// both methods are illustrated.
CHStringArray asNames;
BOOL bGetAll, bSetName, bSetWeight, bSetNose;
HRESULT hRes = WBEM_S_NO_ERROR;
// Part of Method 2
Query.GetValuesForProp(pName, asNames);
bGetAll = asNames.GetSize() == 0;
// Used by Method 1
bSetName = Query.IsPropertyRequired(pName);
bSetWeight = Query.IsPropertyRequired(pWeight);
bSetNose = Query.IsPropertyRequired(pRedNose);
// walk through all the reindeer
for (int i = 0; (i < Deers::NDeers) && (SUCCEEDED(hRes)); i++)
{
// we don't want to return deleted deer
if (!ohDeers[i].m_deleted)
{
// Method 2 - Check to see if the query CAN be processed by 'name', if so,
// only return those names.
if (bGetAll || IsInList(asNames, ohDeers[i].m_name))
{
CInstance *pInstance = CreateNewInstance(pMethodContext);
if (pInstance)
{
// Method 1
if (bSetName)
pInstance->SetCHString(pName, CHString(ohDeers[i].m_name));
// Method 1
if (bSetWeight)
pInstance->SetDWORD(pWeight, ohDeers[i].m_weight);
// Method 1
if (bSetNose)
pInstance->Setbool(pRedNose, ohDeers[i].m_redNose);
hRes = Commit(pInstance);
}
else
{
// couldn't create new instance
hRes = WBEM_E_OUT_OF_MEMORY;
break;
}
}
}
}
return hRes;
}
/*****************************************************************************
*
* FUNCTION : CReindeer::PutInstance
*
* DESCRIPTION : PutInstance should be used in provider classes that can write
* instance information back to the hardware or software.
* For example: Win32_Environment will allow a PutInstance of a new
* environment variable, because environment variables are "software"
* related. However, a class like Win32_MotherboardDevice will not
* allow editing of the bus speed.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::PutInstanceAsync.
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if PutInstance is not available
* WBEM_E_FAILED if there is an error delivering the instance
* WBEM_E_INVALID_PARAMETER if any of the instance properties
* are incorrect.
* WBEM_S_NO_ERROR if instance is properly delivered
*
* COMMENTS : TO DO: If you don't intend to support writing to your provider, remove this method.
*
*****************************************************************************/
HRESULT CReindeer::PutInstance ( const CInstance &Instance, long lFlags)
{
HRESULT hresult = WBEM_E_INVALID_PARAMETER;
// we do not create reindeer here.
if (lFlags & WBEM_FLAG_CREATE_ONLY)
hresult = WBEM_E_UNSUPPORTED_PARAMETER;
else
{
// get the key value so we can tell which reindeer we're operating on
CHString name;
Instance.GetCHString(pName, name);
for (int i = 0; i < Deers::NDeers; i++)
{
if (0 == name.CompareNoCase(CHString(ohDeers[i].m_name)) && !ohDeers[i].m_deleted)
{
// we found one, we can change the red nose and/or the weight properties
DWORD weight;
bool redNoze;
if (Instance.GetDWORD(pWeight, weight))
ohDeers[i].m_weight = weight;
if (Instance.Getbool(pRedNose, redNoze))
ohDeers[i].m_redNose = redNoze;
hresult = WBEM_S_NO_ERROR;
break;
}
}
if (FAILED(hresult))
{
// If they said they wanted to update, but it wasn't there
if (lFlags & WBEM_FLAG_UPDATE_ONLY)
{
hresult = WBEM_E_NOT_FOUND;
}
}
}
return hresult;
}
/*****************************************************************************
*
* FUNCTION : CReindeer::DeleteInstance
*
* DESCRIPTION : DeleteInstance, like PutInstance, actually writes information
* to the software or hardware. For most hardware devices,
* DeleteInstance should not be implemented, but for software
* configuration, DeleteInstance implementation is plausible.
*
* INPUTS : A pointer to a CInstance object containing the key properties.
* A long that contains the flags described in
* IWbemServices::DeleteInstanceAsync.
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if DeleteInstance is not available.
* WBEM_E_FAILED if there is an error deleting the instance.
* WBEM_E_INVALID_PARAMETER if any of the instance properties
* are incorrect.
* WBEM_S_NO_ERROR if instance is properly deleted.
*
* COMMENTS : TO DO: If you don't intend to support deleting instances, remove this method.
*
*****************************************************************************/
HRESULT CReindeer::DeleteInstance ( const CInstance &Instance, long lFlags )
{
HRESULT hresult = WBEM_E_NOT_FOUND;
// get the key value so we can tell which reindeer we're operating on
CHString name;
Instance.GetCHString(pName, name);
// see if we can find the deer we want,
// note that we won't delete one that's already been deleted
for (int i = 0; i < Deers::NDeers; i++)
{
if (0 == name.CompareNoCase(CHString(ohDeers[i].m_name)) && !ohDeers[i].m_deleted)
{
// we found it - mark as deleted
ohDeers[i].m_deleted = true;
hresult = WBEM_S_NO_ERROR;
break;
}
}
return hresult;
}
/*****************************************************************************
*
* FUNCTION : CReindeer::ExecMethod
*
* DESCRIPTION : Override this function to provide support for methods.
* A method is an entry point for the user of your provider
* to request your class perform some function above and
* beyond a change of state. (A change of state should be
* handled by PutInstance() )
*
* INPUTS : A pointer to a CInstance containing the instance the method was executed against.
* A string containing the method name
* A pointer to the CInstance which contains the IN parameters.
* A pointer to the CInstance to contain the OUT parameters.
* A set of specialized method flags
*
* RETURNS : WBEM_E_PROVIDER_NOT_CAPABLE if not implemented for this class
* WBEM_S_NO_ERROR if method executes successfully
* WBEM_E_FAILED if error occurs executing method
*
* COMMENTS : TO DO: If you don't intend to support Methods, remove this method.
*
*****************************************************************************/
HRESULT CReindeer::ExecMethod ( const CInstance& Instance,
const BSTR bstrMethodName,
CInstance *pInParams,
CInstance *pOutParams,
long lFlags)
{
return (WBEM_E_PROVIDER_NOT_CAPABLE);
}
BOOL CReindeer::IsInList(const CHStringArray &asArray, LPCWSTR pszString)
{
DWORD dwSize = asArray.GetSize();
for (DWORD x=0; x < dwSize; x++)
{
if (asArray[x].CompareNoCase(pszString) == 0)
{
return TRUE;
}
}
return FALSE;
}