/****************************************************************** 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 // 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 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; }