613 lines
18 KiB
C++
613 lines
18 KiB
C++
// [!output IMPL_FILE] : Implementation of [!output CLASS_NAME]
|
|
#include "stdafx.h"
|
|
#include "[!output PROJECT_NAME].h"
|
|
#include "[!output HEADER_FILE]"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Class, property and method names
|
|
|
|
// IMPORTANT: the strings defined below are not localizable
|
|
|
|
[!if CLASS_SPECIFIED]
|
|
const static WCHAR * s_pMyClassName = L"[!output WMICLASSNAME]"; //class name
|
|
|
|
//properies:
|
|
[!output PROPERTY_DEFINITIONS]
|
|
|
|
//methods:
|
|
[!output METHOD_DEFINITIONS]
|
|
|
|
[!else]
|
|
//TODO: define provided class name, e.g.:
|
|
const static WCHAR * s_pMyClassName = L"MyClassName";
|
|
|
|
//TODO: define property names of the provided class, e.g.:
|
|
//const static WCHAR * pMyProperty = L"MyProperty";
|
|
|
|
//TODO: define method names of the provided class, e.g.:
|
|
//const static WCHAR * pMyMethod = L"MyMethod";
|
|
[!endif]
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::Initialize
|
|
//Refer to MSDN documentation for IWbemProviderInit::Initialize()
|
|
//for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::Initialize(LPWSTR pszUser,
|
|
LONG lFlags,
|
|
LPWSTR pszNamespace,
|
|
LPWSTR pszLocale,
|
|
IWbemServices *pNamespace,
|
|
IWbemContext *pCtx,
|
|
IWbemProviderInitSink *pInitSink)
|
|
{
|
|
|
|
if ( NULL == pNamespace || NULL == pInitSink)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//cache IWbemServices pointer
|
|
//Note: m_pNamespace is a smart pointer, so it AddRef()'s automatically
|
|
m_pNamespace = pNamespace;
|
|
|
|
//cache provided class definition
|
|
//NOTE: the code below assumes that your class definition doesn't change while
|
|
//your provider is running. If this is not true, you should implement a consumer
|
|
//for class modification ans class deletion events. Refer to WMI documentation
|
|
//for event consumers on MSDN.
|
|
|
|
HRESULT hr = m_pNamespace->GetObject(CComBSTR(s_pMyClassName),
|
|
0,
|
|
pCtx, //passing IWbemContext pointer to prevent deadlocks
|
|
&m_pClass,
|
|
NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
//cache path parser class factory
|
|
hr = CoGetClassObject(CLSID_WbemDefPath,
|
|
CLSCTX_INPROC_SERVER,
|
|
NULL,
|
|
IID_IClassFactory,
|
|
(void **) &m_pPathFactory);
|
|
if (FAILED(hr))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
//create helper object
|
|
m_pHelper = new CInstanceProviderHelper(pNamespace, pCtx);
|
|
|
|
//NOTE: to report a detailed error or status to WMI, you can call
|
|
//ConstructErrorObject() on m_pHelper anywhere in your provider
|
|
|
|
pInitSink->SetStatus(WBEM_S_INITIALIZED,0);
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::GetObjectAsync
|
|
// Refer to MSDN documentation for IWbemServices::GetObjectAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::GetObjectAsync(
|
|
const BSTR bstrObjectPath,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
|
|
//bugbug: per-property retrieval?
|
|
[!if SUPPORT_GET ]
|
|
if (NULL == pResponseHandler)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
CComPtr<IWbemClassObject> pInstance;
|
|
HRESULT hr = GetInstanceByPath(bstrObjectPath, &pInstance);
|
|
if (FAILED (hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//if all is well, return the object to WMI and indicate success:
|
|
pResponseHandler->Indicate (1, &pInstance);
|
|
pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
[!else]
|
|
return WBEM_E_PROVIDER_NOT_CAPABLE;
|
|
[!endif]
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::PutInstanceAsync()
|
|
// Refer to MSDN documentation for IWbemServices::PutInstanceAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::PutInstanceAsync(
|
|
IWbemClassObject *pInst,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
|
|
[!if SUPPORT_PUT ]
|
|
if ( NULL == pResponseHandler || NULL == pInst)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
//TODO: examine possible flag values: WBEM_FLAG_UPDATE_ONLY,
|
|
//WBEM_FLAG_CREATE_ONLY and WBEM_FLAG_CREATE_OR_UPDATE
|
|
//and choose the level of support you need and return WBEM_E_PROVIDER_NOT_CAPABLE
|
|
//for flag values you do not support
|
|
|
|
//TODO: if you are planning to support partial updates, examine pCtx
|
|
//for "__PUT_EXTENSIONS" and other relevant system context values
|
|
//and update your instance data appropriately
|
|
|
|
//TODO: handle the instance update or creation here
|
|
|
|
pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
|
|
return WBEM_S_NO_ERROR;
|
|
[!else]
|
|
return WBEM_E_PROVIDER_NOT_CAPABLE;
|
|
[!endif]
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::DeleteInstanceAsync()
|
|
// Refer to MSDN help for IWbemServices::DeleteInstanceAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::DeleteInstanceAsync(
|
|
const BSTR ObjectPath,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
//To implement this method, an instance provider parses the object path string
|
|
//specified in the strObjectPath parameter and attempts to locate the corresponding
|
|
//instance and delete it.
|
|
[!if SUPPORT_DELETE ]
|
|
|
|
if (NULL == pResponseHandler)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
[!if IS_COMPOUND_KEY]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF | WBEMPATH_INFO_IS_COMPOUND;
|
|
[!else]
|
|
[!if IS_SINGLETON]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF | WBEMPATH_INFO_CONTAINS_SINGLETON;
|
|
[!else]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF;
|
|
[!endif]
|
|
[!endif]
|
|
|
|
if (FAILED(m_pHelper->CheckInstancePath(m_pPathFactory,
|
|
ObjectPath,
|
|
CComBSTR(s_pMyClassName),
|
|
ulPathTest)) )
|
|
{
|
|
//syntax error in path or path incorrect for class provided
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
[!if IS_SINGLETON]
|
|
//NOTE: [!output WMICLASSNAME] is a singleton object. No need to identify the instance.
|
|
//NOTE: If the instance is not present, uncomment the following line to communicate this back to WMI:
|
|
//return WBEM_E_NOT_FOUND;
|
|
[!else]
|
|
//Create path parser object
|
|
CComPtr<IWbemPath>pPath;
|
|
HRESULT hr = m_pPathFactory->CreateInstance(NULL,
|
|
IID_IWbemPath,
|
|
(void **) &pPath);
|
|
if (FAILED(hr))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
CComPtr<IWbemPathKeyList> pIKeyList;
|
|
hr = pPath->GetKeyList(&pIKeyList);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
unsigned long ulNumKeys;
|
|
hr = pIKeyList->GetCount(&ulNumKeys);
|
|
|
|
//Get values of key properties
|
|
unsigned long uKeyNameBufferSize = CComBSTR(ObjectPath).Length() + 1;
|
|
WCHAR * wKeyName = new WCHAR[uKeyNameBufferSize];
|
|
if (NULL == wKeyName)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CComVariant vValue;
|
|
unsigned long ulApparentCimType;
|
|
for (unsigned long i = 0; i < ulNumKeys; i++)
|
|
{
|
|
hr = pIKeyList->GetKey2(i, 0L, &uKeyNameBufferSize,
|
|
wKeyName, &vValue, &ulApparentCimType);
|
|
//TODO: save vValue for later use
|
|
}
|
|
delete[] wKeyName;
|
|
|
|
//TODO: iterate through your data source to find the matching object and delete it.
|
|
//NOTE: If you don't find an object that matches key values indicated in the path,
|
|
//uncomment the following line to communicate this back to WMI:
|
|
//return WBEM_E_NOT_FOUND;
|
|
[!endif]
|
|
|
|
pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
[!else]
|
|
return WBEM_E_PROVIDER_NOT_CAPABLE;
|
|
[!endif]
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::CreateInstanceEnumAsync()
|
|
// Refer to MSDN documentation for IWbemServices::CreateInstanceEnumAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::CreateInstanceEnumAsync(
|
|
const BSTR Class,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
|
|
|
|
//NOTE: It is important to note that the instance provider has acquired a thread from WMI
|
|
//to perform these operations. It may be desirable to call the sink AddRef() method and create
|
|
//another thread for delivering the objects in the result set.
|
|
//This strategy allows the current thread to return to WMI without depleting the thread pool.
|
|
//Whether the provider chooses the single thread design over the dual thread design depends on how
|
|
//long the provider plans on using the WMI thread.
|
|
|
|
[!if SUPPORT_ENUMERATE ]
|
|
if (NULL == pResponseHandler)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
[!if IS_SINGLETON]
|
|
// Prepare an empty object to receive the instance data
|
|
CComPtr<IWbemClassObject> pNewInst;
|
|
hr = m_pClass->SpawnInstance(0, &pNewInst);
|
|
|
|
CComVariant var;
|
|
[!if CLASS_SPECIFIED]
|
|
[!output POPULATE_INSTANCE]
|
|
[!else]
|
|
//TODO: populate the instance with properties, e.g.:
|
|
//CComVariant var;
|
|
//var.ChangeType(VT_BSTR);
|
|
//var = <value>; //put appropriate value here
|
|
//hr = pNewInst->Put(CComBSTR(pMyProperty), 0, &var, 0);
|
|
//var.Clear();
|
|
[!endif]
|
|
|
|
// Deliver the class to WMI.
|
|
pResponseHandler->Indicate(1, &pNewInst);
|
|
[!else]
|
|
// Loop through the private source and create each instance
|
|
//while (<there's more instances>)
|
|
{
|
|
// Prepare an empty object to receive the class definition.
|
|
CComPtr<IWbemClassObject> pNewInst;
|
|
hr = m_pClass->SpawnInstance(0, &pNewInst);
|
|
if (FAILED(hr))
|
|
{
|
|
//TODO: uncomment the line below once the loop condition is in place
|
|
//break;
|
|
}
|
|
|
|
CComVariant var;
|
|
[!if CLASS_SPECIFIED]
|
|
[!output POPULATE_INSTANCE]
|
|
[!else]
|
|
//TODO: populate the instance with properties, e.g.:
|
|
//CComVariant var;
|
|
//var.ChangeType(VT_BSTR);
|
|
//var = <value>; //put appropriate value here
|
|
//hr = pNewInst->Put(CComBSTR(pMyProperty), 0, &var, 0);
|
|
//var.Clear();
|
|
[!endif]
|
|
|
|
// Deliver the class to WMI.
|
|
pResponseHandler->Indicate(1, &pNewInst);
|
|
}
|
|
[!endif]
|
|
pResponseHandler->SetStatus(0, hr, NULL, NULL);
|
|
return WBEM_S_NO_ERROR;
|
|
[!else]
|
|
return WBEM_E_PROVIDER_NOT_CAPABLE;
|
|
[!endif]
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//[!output CLASS_NAME]::ExecQueryAsync()
|
|
// Refer to MSDN documentation for IWbemServices::ExecQueryAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::ExecQueryAsync(
|
|
const BSTR QueryLanguage,
|
|
const BSTR Query,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
|
|
|
|
// Instance providers have the option of supporting query processing or relying on WMI
|
|
// for that service. To support queries, an instance provider must be capable of parsing
|
|
// simple Structured Query Language (SQL) statements, executing the requested query,
|
|
// and delivering the result set objects to the requester's sink.
|
|
|
|
//TODO: put your query processing code here
|
|
|
|
//pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
|
|
// return WBEM_S_NO_ERROR;
|
|
|
|
return WBEM_E_PROVIDER_NOT_CAPABLE;
|
|
|
|
}
|
|
|
|
[!if PROVIDE_METHODS ]
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::ExecMethodAsync()
|
|
// Refer to MSDN documentation for IWbemServices::ExecMethodAsync()
|
|
// for details about implementing this method
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::ExecMethodAsync(
|
|
const BSTR strObjectPath,
|
|
const BSTR strMethodName,
|
|
long lFlags,
|
|
IWbemContext *pCtx,
|
|
IWbemClassObject *pInParams,
|
|
IWbemObjectSink *pResponseHandler)
|
|
{
|
|
|
|
|
|
[!if CLASS_SPECIFIED]
|
|
[!if !HAS_IMPL_METHODS]
|
|
//[!output WMICLASSNAME] has no implemented methods
|
|
return WBEM_E_NOT_SUPPORTED;
|
|
[!else]
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
if (NULL == pResponseHandler)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
[!output EXEC_METHOD_BODY]
|
|
[!endif]
|
|
[!else]
|
|
|
|
//Check that class name in the path is correct.
|
|
//Get path parser object:
|
|
CComPtr<IWbemPath>pPath;
|
|
HRESULT hr = m_pPathFactory->CreateInstance(NULL,
|
|
IID_IWbemPath,
|
|
(void **) &pPath);
|
|
if (FAILED(hr))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
HRESULT hr = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, strObjectPath);
|
|
long nPathLen = CComBSTR(strObjectPath).Length();
|
|
unsigned long ulBufLen = nPathLen + 1;
|
|
WCHAR * wClass = new WCHAR[nPathLen];
|
|
if (NULL == wClass)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
pPath->GetClassName(&ulBufLen, wClass);
|
|
if ( _wcsicmp(s_pMyClassName, wClass))
|
|
{
|
|
delete[] wClass;
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
delete[] wClass;
|
|
//TODO: compare requested method name with methods of your class
|
|
//if (!_wcsicmp (strMethodName, pMyNonStaticMethod))
|
|
{
|
|
CComVariant var;
|
|
|
|
//Get input arguments:
|
|
//TODO: if the method has input arguments, they will be passed as properties of
|
|
//the pInParams object. The commented line below demonstrates how to extract these:
|
|
//hr = pInParams->Get(CComBSTR("InputArgument1"), 0, &var, NULL, NULL);
|
|
//TODO: save input parameter value
|
|
var.Clear();
|
|
|
|
//parse path to find instance for method execution: for a non-static method
|
|
CComPtr<IWbemPathKeyList> pIKeyList;
|
|
hr = pPath->GetKeyList(&pIKeyList);
|
|
if (FAILED(hr))
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
unsigned long ulNumKeys;
|
|
hr = pIKeyList->GetCount(&ulNumKeys);
|
|
//Get values of key properties:
|
|
unsigned long uKeyNameBufferSize = nPathLen + 1;
|
|
WCHAR * wKeyName = new WCHAR[uKeyNameBufferSize];
|
|
if (NULL == wKeyName)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CComVariant vValue;
|
|
unsigned long ulApparentCimType;
|
|
for (unsigned long i = 0; i < ulNumKeys; i++)
|
|
{
|
|
hr = pIKeyList->GetKey2(i, 0L, &uKeyNameBufferSize,
|
|
wKeyName, &vValue, &ulApparentCimType);
|
|
//TODO: save vValue for later use
|
|
}
|
|
delete[] wKeyName;
|
|
|
|
//TODO: iterate through your data source to find the matching object
|
|
|
|
//TODO: add code to execute the method here
|
|
//get output parameters class
|
|
CComPtr<IWbemClassObject> pOutClass;
|
|
hr = m_pClass->GetMethod(CComBSTR("Method1"), 0, NULL, &pOutClass);
|
|
CComPtr<IWbemClassObject> pOutParams;
|
|
pOutClass->SpawnInstance(0, &pOutParams);
|
|
//TODO: create output parameters by filling properties
|
|
//of pOutParams class. For example:
|
|
|
|
//var.ChangeType(VT_BSTR);
|
|
//fill var with appropriate value
|
|
//hr = pOutParams->Put(CComBSTR("MyOutputParameter"), 0, &var, 0);
|
|
//var.Clear();
|
|
//var.ChangeType(VT_I2);
|
|
//fill var with appropriate value
|
|
//hr = pOutParams->Put(CComBSTR("ReturnValue"), 0, &var, 0);
|
|
//var.Clear();
|
|
// Send the output object back to the client via the sink
|
|
hr = pResponseHandler->Indicate(1, &pOutParams);
|
|
|
|
pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//method name not recognized
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
|
|
[!endif]
|
|
}
|
|
[!endif]
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// [!output CLASS_NAME]::GetInstanceByPath() parses the path to find out required key values,
|
|
// then searhces the internal store for an object with matching key values. If such
|
|
// an object is found, the method spawns a new instance, fills all properties and
|
|
// returns it in ppInstance. If not, the method returns WBEM_E_NOT_FOUND.
|
|
// bugbug: partial-instance provision??? other possible flags?
|
|
|
|
STDMETHODIMP [!output CLASS_NAME]::GetInstanceByPath (
|
|
/*in*/CComBSTR bstrPath,
|
|
/*out*/IWbemClassObject ** ppInstance )
|
|
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
[!if IS_COMPOUND_KEY]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF | WBEMPATH_INFO_IS_COMPOUND;
|
|
[!else]
|
|
[!if IS_SINGLETON]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF | WBEMPATH_INFO_CONTAINS_SINGLETON;
|
|
[!else]
|
|
ULONG ulPathTest = WBEMPATH_INFO_IS_INST_REF;
|
|
[!endif]
|
|
[!endif]
|
|
|
|
if (FAILED(m_pHelper->CheckInstancePath(m_pPathFactory,
|
|
bstrPath,
|
|
CComBSTR(s_pMyClassName),
|
|
ulPathTest)))
|
|
{
|
|
//syntax error in path or path incorrect for class provided
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
[!if IS_SINGLETON]
|
|
//[!output WMICLASSNAME] is a singleton object. No need to identify the instance.
|
|
//NOTE: If the instance is not present, uncomment the following line to communicate this back to WMI:
|
|
//return WBEM_E_NOT_FOUND;
|
|
[!else]
|
|
//Get path parser object:
|
|
CComPtr<IWbemPath>pPath;
|
|
hr = m_pPathFactory->CreateInstance(NULL,
|
|
IID_IWbemPath,
|
|
(void **) &pPath);
|
|
if (FAILED(hr))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
hr = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL,
|
|
bstrPath);
|
|
|
|
CComPtr<IWbemPathKeyList> pIKeyList;
|
|
hr = pPath->GetKeyList(&pIKeyList);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
unsigned long ulNumKeys;
|
|
hr = pIKeyList->GetCount(&ulNumKeys);
|
|
|
|
//Get values of key properties
|
|
unsigned long uKeyNameBufferSize = bstrPath.Length() + 1;
|
|
WCHAR * wKeyName = new WCHAR[uKeyNameBufferSize];
|
|
if (NULL == wKeyName)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CComVariant vValue;
|
|
unsigned long ulApparentCimType;
|
|
for (unsigned long i = 0; i < ulNumKeys; i++)
|
|
{
|
|
hr = pIKeyList->GetKey2(i, 0L, &uKeyNameBufferSize,
|
|
wKeyName, &vValue, &ulApparentCimType);
|
|
//TODO: save vValue for later use
|
|
}
|
|
|
|
delete[] wKeyName;
|
|
|
|
//TODO: search your internal data source to find the matching object.
|
|
//If no objects with required key values can be found,
|
|
//return WBEM_E_NOT_FOUND.
|
|
[!endif]
|
|
|
|
//spawn new instance
|
|
CComPtr<IWbemClassObject> pNewInst;
|
|
hr = m_pClass->SpawnInstance(0, &pNewInst);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
CComVariant var;
|
|
|
|
//TODO: fill the properties of the new instance with those of the matching internal object
|
|
[!if CLASS_SPECIFIED]
|
|
[!output POPULATE_INSTANCE]
|
|
[!else]
|
|
//Example:
|
|
//var.ChangeType(VT_BSTR);
|
|
//var = <value>; //put appropriate value here
|
|
//hr = pNewInst->Put(CComBSTR(pMyProperty), 0, &var, 0);
|
|
//var.Clear();
|
|
[!endif]
|
|
|
|
return hr;
|
|
}
|
|
|