493 lines
21 KiB
C++
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;
|
|
}
|