|
|
/******************************************************************
SNetScal.cpp -- WBEM provider class implementation
MODULE: DhcpProv.dll
DESCRIPTION: Contains: the definition of the DHCP_Subnet class, the static table of manageable objects.
REVISION: 08/03/98 - created
******************************************************************/ #include <stdafx.h>
#include "SNetFn.h" // needed for the declarations of all the functions.
#include "SNetScal.h" // own header
// static table of CDHCP_Property objects containing the DHCP Server
// scalar parameters (properties) which are WBEM manageable. Each object associates
// the name of the property with their SET and GET functions.
// *** NOTE ***
// The name of each property has to be in sync with the ones specified in the DhcpSchema.mof.
// The indices specified in SrvScal.h should also be in sync with the actual row from this table (they are used
// in the property's action functions.
static const CDHCP_Property DHCP_Subnet_Property[]= { CDHCP_Property(L"Address", fnSNetGetAddress, NULL), CDHCP_Property(L"Mask", fnSNetGetMask, NULL), CDHCP_Property(L"Name", fnSNetGetName, fnSNetSetName), CDHCP_Property(L"Comment", fnSNetGetComment, fnSNetSetComment), CDHCP_Property(L"State", fnSNetGetState, fnSNetSetState), CDHCP_Property(L"NumberOfAddressesInUse", fnSNetGetNumberOfAddressesInUse, NULL), CDHCP_Property(L"NumberOfAddressesFree", fnSNetGetNumberOfAddressesFree, NULL), CDHCP_Property(L"NumberOfPendingOffers", fnSNetGetNumberOfPendingOffers, NULL) };
// the name of the WBEM class
#define PROVIDER_NAME_DHCP_SUBNET "DHCP_Subnet"
// main class instantiation.
CDHCP_Subnet MyDHCP_Subnet_Scalars (PROVIDER_NAME_DHCP_SUBNET, PROVIDER_NAMESPACE_DHCP) ;
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::CDHCP_Subnet * * DESCRIPTION : Constructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : Calls the Provider constructor. * *****************************************************************************/ CDHCP_Subnet::CDHCP_Subnet (const CHString& strName, LPCSTR pszNameSpace ) : Provider(strName, pszNameSpace) { }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::~CDHCP_Subnet * * DESCRIPTION : Destructor * * INPUTS : none * * RETURNS : nothing * * COMMENTS : * *****************************************************************************/ CDHCP_Subnet::~CDHCP_Subnet () { }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * * INPUTS : none * * RETURNS : WBEM_S_NO_ERROR if successful * * COMMENTS : Enumerates all this instances of this class. As there is only one * DHCP Server per system, there is only one instance for this class * *****************************************************************************/ HRESULT CDHCP_Subnet::EnumerateInstances ( MethodContext* pMethodContext, long lFlags ) { CInstance* pInstance; CDHCP_Subnet_Parameters subnetParams(0); // don't know here the IP address
LPDHCP_MIB_INFO pMibInfo; LPSCOPE_MIB_INFO pScopeMibInfo;
HRESULT hRes = WBEM_E_FAILED;
if (subnetParams.GetMibInfo(pMibInfo, pScopeMibInfo, TRUE) && pMibInfo != NULL) { hRes = WBEM_S_NO_ERROR;
for (int i=0; hRes == WBEM_S_NO_ERROR && i < pMibInfo->Scopes; i++) { LPSCOPE_MIB_INFO pScope = &(pMibInfo->ScopeInfo[i]); // this is the info from the server,
CInstance* pInstance = CreateNewInstance(pMethodContext); // create now the instance
if (pScope != NULL && pInstance != NULL) { WCHAR szSubnetAddr[16]; // should be enough for holding 'xxx.yyy.zzz.uuu\0'
// don't want to link to ws2_32.lib just for using inet_ntoa only
swprintf(szSubnetAddr, L"%u.%u.%u.%u",(pScope->Subnet & 0xff000000) >> 24, (pScope->Subnet & 0x00ff0000) >> 16, (pScope->Subnet & 0x0000ff00) >> 8, (pScope->Subnet & 0x000000ff));
if (pInstance->SetCHString(DHCP_Subnet_Property[IDX_SNET_Address].m_wsPropName, szSubnetAddr) && LoadInstanceProperties(pInstance)) { hRes = Commit(pInstance); // now everything relys on the err returned above.
continue; } }
// at this point something should have definitively gone wrong
hRes = WBEM_E_FAILED; } }
return hRes ; }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::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. * * 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 CDHCP_Subnet::GetObject ( CInstance* pInstance, long lFlags ) { return LoadInstanceProperties(pInstance)? WBEM_S_NO_ERROR : WBEM_E_NOT_FOUND; }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::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. CIMOM will post - * filter the query for you, you may return more instances * or more properties than are requested and CIMOM * will filter out any that do not apply. * * * INPUTS : * * 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, cimom * 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 entire method. * *****************************************************************************/ HRESULT CDHCP_Subnet::ExecQuery (MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags) { return (WBEM_E_PROVIDER_NOT_CAPABLE); }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::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. Since by default PutInstance * returns WBEM_E_PROVIDER_NOT_CAPABLE, this function is placed here as a * skeleton, but can be removed if not used. * * INPUTS : * * 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 CDHCP_Subnet::PutInstance ( const CInstance &Instance, long lFlags) { int i; DWORD returnCode; CHString strName, strMask; DHCP_IP_ADDRESS dwAddress, dwMask; LPDHCP_SUBNET_INFO pSubnetInfo; BOOL newInstance;
if (!Instance.GetCHString(DHCP_Subnet_Property[IDX_SNET_Address].m_wsPropName, strName) || !Instance.GetCHString(DHCP_Subnet_Property[IDX_SNET_Mask].m_wsPropName, strMask) || !inet_wstodw(strName, dwAddress) || !inet_wstodw(strMask, dwMask)) return FALSE;
// the object below is used as a "repository" for all the properties' values.
// once it is filled up with data, it is commited explicitely to the DHCP Server.
CDHCP_Subnet_Parameters SubnetParameters(dwAddress, dwMask);
// first get the subnet information, just to get the info that doesn't change
// if fails => a new instance has to be created
newInstance = !SubnetParameters.GetSubnetInfo(pSubnetInfo,TRUE);
for (i = 0; i < NUM_SUBNET_PROPERTIES; i++) { if (DHCP_Subnet_Property[i].m_pfnActionSet != NULL) { // execute the SET property action function
// because of the last NULL, no data is written to DHCP Server at this moment,
// only SubnetParameters object is filled up with the values taken from the Instance.
// don't care much here about the error codes. Failure means some properties will
// not be written. At least we are giving a chance to all the writable properties.
(*(DHCP_Subnet_Property[i].m_pfnActionSet))(&SubnetParameters, (CInstance *)&Instance, NULL); } }
if (newInstance) return SubnetParameters.CommitNew(returnCode) ? WBEM_S_NO_ERROR : WBEM_E_FAILED; else // commit the values of all the writable properties to DHCP Server
return SubnetParameters.CommitSet(returnCode) ? WBEM_S_NO_ERROR : WBEM_E_FAILED; }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::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. * Like PutInstance, DeleteInstance returns WBEM_E_PROVIDER_NOT_CAPABLE from * inside Provider::DeleteInstance (defined in Provider.h). So, if * you choose not to implement DeleteInstance, remove this function * definition and the declaration from DHCP_Server_Scalars.h * * INPUTS : * * 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 CDHCP_Subnet::DeleteInstance ( const CInstance &Instance, long lFlags ) { DWORD returnCode; CHString str; DHCP_IP_ADDRESS dwAddress;
if (!Instance.GetCHString(DHCP_Subnet_Property[IDX_SNET_Address].m_wsPropName, str) || !inet_wstodw(str, dwAddress)) return (WBEM_E_FAILED);
// the object below is used as a "repository" for all the properties' values.
// once it is filled up with data, it is commited explicitely to the DHCP Server.
CDHCP_Subnet_Parameters SubnetParameters(dwAddress);
return SubnetParameters.DeleteSubnet() ? WBEM_S_NO_ERROR : WBEM_E_FAILED; }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::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 CDHCP_Subnet::ExecMethod ( const CInstance& Instance, const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams, long lFlags) { int i; DWORD returnCode; CHString str; DHCP_IP_ADDRESS dwAddress; LPDHCP_SUBNET_INFO pSubnetInfo; int nSetPrefixLen = wcslen(_SNET_SET_PREFIX);
if (!Instance.GetCHString(DHCP_Subnet_Property[IDX_SNET_Address].m_wsPropName, str) || !inet_wstodw(str, dwAddress)) return FALSE;
// build the object identifying the subnet against which the method is executed
CDHCP_Subnet_Parameters SubnetParameters(dwAddress);
// get the subnet information, just to preserve the info that doesn't change
if (!SubnetParameters.GetSubnetInfo(pSubnetInfo,TRUE)) return WBEM_E_FAILED;
// is it a "SET" operation?
if (!_wcsnicmp (bstrMethodName, _SNET_SET_PREFIX, nSetPrefixLen)) { int i;
WCHAR *wcsPropertyName = bstrMethodName + nSetPrefixLen; // pointer to the property name
// scan the DHCP_Subnet_Property table looking for the property's row
for (i = 0; i < NUM_SUBNET_PROPERTIES; i++) { // if the property row is found
if (!_wcsicmp(wcsPropertyName, DHCP_Subnet_Property[i].m_wsPropName)) { // see if the property is writable
if (DHCP_Subnet_Property[i].m_pfnActionSet != NULL) { // execute the SET property action function
// because of the pOutParams, the method will be commited inside the call
if ((*(DHCP_Subnet_Property[i].m_pfnActionSet))(&SubnetParameters, pInParams, pOutParams)) // everything worked fine.
return WBEM_S_NO_ERROR; else // an error occured during "SET"
return WBEM_E_FAILED; } else // no, the property cannot be written. (shouldn't really happen, as the methods from the
// repository should match the writable properties only)
return WBEM_E_READ_ONLY; } } }
// if this point was reached, no method was found => provider not capable
return WBEM_E_PROVIDER_NOT_CAPABLE; }
/*****************************************************************************
* * FUNCTION : CDHCP_Subnet::LoadInstanceProperties * * RETURNS : TRUE if the values for all the properties was loaded successfully, * FALSE otherwise. * * COMMENTS : It loops through the Server_Property table, calling the GET functions. * *****************************************************************************/ BOOL CDHCP_Subnet::LoadInstanceProperties(CInstance* pInstance) { CHString str; DHCP_IP_ADDRESS dwAddress;
if (!pInstance->GetCHString(DHCP_Subnet_Property[IDX_SNET_Address].m_wsPropName, str) || !inet_wstodw(str, dwAddress)) return FALSE;
// there should be used this object, in order to not call several times the DHCP Server API.
CDHCP_Subnet_Parameters SubnetParameters(dwAddress);
for (int i = 0; i < NUM_SUBNET_PROPERTIES; i++) { // if there is an invisible property (does not support GET) just skip it.
if (DHCP_Subnet_Property[i].m_pfnActionGet == NULL) continue;
// call the appropriate GET function, fail if the call fails (there should be no reason for failure)
if (!(*(DHCP_Subnet_Property[i].m_pfnActionGet))(&SubnetParameters, NULL, pInstance)) return FALSE; }
return TRUE; }
|