EternalWindows
WMI / プロバイダ サンプル(dll)

プロバイダの実体はCOMサーバーであるため、dllでもexeでも実装することができます。 今回はdllを例にプロバイダの実装を確認します。 このdllはwmiprvse.exeにロードされることになり、 MOFファイルにホスティングの指定を行っていない場合は、 network serviceとして動作することになります。 このため、dllが特定のユーザープロファイル以下に存在する場合は、 クライアントがプロバイダを使用とした際にdllへアクセスできず、 WBEM_E_PROVIDER_LOAD_FAILUREが返ることになります。 よって、dllはC:\Program Filesや以下やC:\Windows以下に配置しておくべきといえます。

LIBRARY	"mydll"

EXPORTS
	DllCanUnloadNow PRIVATE
	DllGetClassObject PRIVATE
	DllRegisterServer PRIVATE
	DllUnregisterServer PRIVATE

次に、ヘッダーファイルを示します。

class CWbemProvider : public IWbemProviderInit, public IWbemServices
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();

	STDMETHODIMP Initialize(LPWSTR wszUser, LONG lFlags, LPWSTR wszNamespace, LPWSTR wszLocale, IWbemServices *pNamespace, IWbemContext *pCtx, IWbemProviderInitSink *pInitSink);

	STDMETHODIMP OpenNamespace(const BSTR strNamespace, long lFlags, IWbemContext *pCtx, IWbemServices **ppWorkingNamespace, IWbemCallResult **ppResult);
	STDMETHODIMP CancelAsyncCall(IWbemObjectSink *pSink);
	STDMETHODIMP QueryObjectSink(long lFlags, IWbemObjectSink **ppResponseHandler);
	STDMETHODIMP GetObject(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemClassObject **ppObject, IWbemCallResult **ppCallResult);
	STDMETHODIMP GetObjectAsync(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP PutClass(IWbemClassObject *pObject, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult);
	STDMETHODIMP PutClassAsync(IWbemClassObject *pObject, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP DeleteClass(const BSTR strClass, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult);
	STDMETHODIMP DeleteClassAsync(const BSTR strClass, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP CreateClassEnum(const BSTR strSuperclass, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
	STDMETHODIMP CreateClassEnumAsync(const BSTR strSuperclass, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP PutInstance(IWbemClassObject *pInst, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult);
	STDMETHODIMP PutInstanceAsync(IWbemClassObject *pInst, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP DeleteInstance(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult);
	STDMETHODIMP DeleteInstanceAsync(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP CreateInstanceEnum(const BSTR strFilter, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
	STDMETHODIMP CreateInstanceEnumAsync(const BSTR strFilter, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP ExecQuery(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
	STDMETHODIMP ExecQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP ExecNotificationQuery(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
	STDMETHODIMP ExecNotificationQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler);
	STDMETHODIMP ExecMethod(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemClassObject **ppOutParams, IWbemCallResult **ppCallResult);
	STDMETHODIMP ExecMethodAsync(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemObjectSink *pResponseHandler);

	CWbemProvider();
	~CWbemProvider();
	void SampleMethod(IWbemClassObject *pInParams, IWbemClassObject *pOutParams);
	
private:
	LONG          m_cRef;
	IWbemServices *m_pNamespace;
};

class CClassFactory : public IClassFactory
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
	
	STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
	STDMETHODIMP LockServer(BOOL fLock);
};

次に、ソースファイル(非WMI関連)を示します。

#include <windows.h>
#include <wbemidl.h>
#include <shlwapi.h>
#include "sample.h"

#pragma comment (lib, "shlwapi.lib")
#pragma comment (lib, "wbemuuid.lib")

const CLSID CLSID_WbemProviderSample = {0xbb466b74, 0x24a8, 0x4611, {0x89, 0x5f, 0x88, 0xa4, 0x67, 0x66, 0xe8, 0xa0}};
const TCHAR g_szClsid[] = TEXT("{BB466B74-24A8-4611-895F-88A46766E8A0}");

LONG      g_lLocks = 0;
HINSTANCE g_hinstDll = NULL;

void LockModule(BOOL bLock);
BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData);


// CClassFactory


STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
		*ppvObject = static_cast<IClassFactory *>(this);
	else
		return E_NOINTERFACE;

	AddRef();
	
	return S_OK;
}

STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
	LockModule(TRUE);

	return 2;
}

STDMETHODIMP_(ULONG) CClassFactory::Release()
{
	LockModule(FALSE);

	return 1;
}

STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{
	CWbemProvider *p;
	HRESULT       hr;
	
	*ppvObject = NULL;

	if (pUnkOuter != NULL)
		return CLASS_E_NOAGGREGATION;
	
	p = new CWbemProvider();
	if (p == NULL)
		return E_OUTOFMEMORY;

	hr = p->QueryInterface(riid, ppvObject);
	p->Release();

	return hr;
}

STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
	LockModule(fLock);

	return S_OK;
}


// DLL Export


STDAPI DllCanUnloadNow(void)
{
	return g_lLocks == 0 ? S_OK : S_FALSE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
	static CClassFactory serverFactory;
	HRESULT hr;
	
	*ppv = NULL;

	if (IsEqualCLSID(rclsid, CLSID_WbemProviderSample))
		hr = serverFactory.QueryInterface(riid, ppv);
	else
		hr = CLASS_E_CLASSNOTAVAILABLE;

	return hr;
}

STDAPI DllRegisterServer(void)
{
	TCHAR szModulePath[MAX_PATH];
	TCHAR szKey[256];

	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("WMI Provider Sample")))
		return E_FAIL;

	GetModuleFileName(g_hinstDll, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szModulePath))
		return E_FAIL;
	
	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, TEXT("ThreadingModel"), TEXT("Both")))
		return E_FAIL;

	return S_OK;
}

STDAPI DllUnregisterServer(void)
{
	TCHAR szKey[256];

	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	SHDeleteKey(HKEY_CLASSES_ROOT, szKey);

	return S_OK;
}

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
{
	switch (dwReason) {

	case DLL_PROCESS_ATTACH:
		g_hinstDll = hinstDll;
		DisableThreadLibraryCalls(hinstDll);
		return TRUE;

	}

	return TRUE;
}


// Function


void LockModule(BOOL bLock)
{
	if (bLock)
		InterlockedIncrement(&g_lLocks);
	else
		InterlockedDecrement(&g_lLocks);
}

BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData)
{
	HKEY  hKey;
	LONG  lResult;
	DWORD dwSize;

	lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
	if (lResult != ERROR_SUCCESS)
		return FALSE;

	if (lpszData != NULL)
		dwSize = (lstrlen(lpszData) + 1) * sizeof(TCHAR);
	else
		dwSize = 0;

	RegSetValueEx(hKey, lpszValue, 0, REG_SZ, (LPBYTE)lpszData, dwSize);
	RegCloseKey(hKey);
	
	return TRUE;
}

最後に、ソースファイル(WMI関連)を示します。

#include <windows.h>
#include <wbemidl.h>
#include "sample.h"

struct DATA {
	int   nId;
	WCHAR szData[256];
} g_data[] = {
	{1, L"apple"},
	{2, L"orange"}
};
const int g_nCount = sizeof(g_data) / sizeof(g_data[0]);
const WCHAR g_szClassName[] = L"MySampProv";


// CWbemProvider


CWbemProvider::CWbemProvider()
{
	m_cRef = 1;
	m_pNamespace = NULL;
}

CWbemProvider::~CWbemProvider()
{
	if (m_pNamespace != NULL)
		m_pNamespace->Release();
}

STDMETHODIMP CWbemProvider::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;

	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IWbemProviderInit))
		*ppvObject = static_cast<IWbemProviderInit *>(this);
	else if (IsEqualIID(riid, IID_IWbemServices))
		*ppvObject = static_cast<IWbemServices *>(this);
	else
		return E_NOINTERFACE;
	
	AddRef();

	return S_OK;
}

STDMETHODIMP_(ULONG) CWbemProvider::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) CWbemProvider::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {
		delete this;
		return 0;
	}

	return m_cRef;
}

STDMETHODIMP CWbemProvider::Initialize(LPWSTR wszUser, LONG lFlags, LPWSTR wszNamespace, LPWSTR wszLocale, IWbemServices *pNamespace, IWbemContext *pCtx, IWbemProviderInitSink *pInitSink)
{
	if (pNamespace != NULL) {
		m_pNamespace = pNamespace;
		m_pNamespace->AddRef();
		pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
		
	}
	else
		pInitSink->SetStatus(WBEM_E_FAILED, 0);

	return WBEM_S_NO_ERROR;
}

STDMETHODIMP CWbemProvider::OpenNamespace(const BSTR strNamespace, long lFlags, IWbemContext *pCtx, IWbemServices **ppWorkingNamespace, IWbemCallResult **ppResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::CancelAsyncCall(IWbemObjectSink *pSink)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::QueryObjectSink(long lFlags, IWbemObjectSink **ppResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::GetObject(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemClassObject **ppObject, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::GetObjectAsync(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::PutClass(IWbemClassObject *pObject, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::PutClassAsync(IWbemClassObject *pObject, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::DeleteClass(const BSTR strClass, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::DeleteClassAsync(const BSTR strClass, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::CreateClassEnum(const BSTR strSuperclass, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::CreateClassEnumAsync(const BSTR strSuperclass, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::PutInstance(IWbemClassObject *pInst, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::PutInstanceAsync(IWbemClassObject *pInst, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::DeleteInstance(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::DeleteInstanceAsync(const BSTR strObjectPath, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::CreateInstanceEnum(const BSTR strFilter, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::CreateInstanceEnumAsync(const BSTR strFilter, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	int              i;
	IWbemClassObject *pClass = NULL;
	IWbemClassObject *pNewInst[100];
	VARIANT          var;

	for (i = 0; i < g_nCount; i++) {
		m_pNamespace->GetObject(strFilter, 0, pCtx, &pClass, NULL);
		pClass->SpawnInstance(0, &pNewInst[i]);
		pClass->Release();
		
		var.vt = VT_I4;
		var.lVal = g_data[i].nId;
		pNewInst[i]->Put(L"id", 0, &var, 0);

		var.vt = VT_BSTR;
		var.bstrVal = SysAllocString(g_data[i].szData);
		pNewInst[i]->Put(L"data", 0, &var, 0);
		VariantClear(&var);
	}	

	pResponseHandler->Indicate(g_nCount, pNewInst);

	pResponseHandler->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);

	return WBEM_S_NO_ERROR;
}

STDMETHODIMP CWbemProvider::ExecQuery(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::ExecQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::ExecNotificationQuery(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::ExecNotificationQueryAsync(const BSTR strQueryLanguage, const BSTR strQuery, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::ExecMethod(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemClassObject **ppOutParams, IWbemCallResult **ppCallResult)
{
	return WBEM_E_NOT_SUPPORTED;
}

STDMETHODIMP CWbemProvider::ExecMethodAsync(const BSTR strObjectPath, const BSTR strMethodName, long lFlags, IWbemContext *pCtx, IWbemClassObject *pInParams, IWbemObjectSink *pResponseHandler)
{
	HRESULT          hr;
	IWbemClassObject *pClass = NULL;
	IWbemClassObject *pOutClass = NULL;
	IWbemClassObject *pOutParams = NULL;
	BSTR             bstrClassName;
	
	bstrClassName = SysAllocString(g_szClassName);
	m_pNamespace->GetObjectW(bstrClassName, 0, pCtx, &pClass, NULL);
	if (pClass == NULL) {
		SysFreeString(bstrClassName);
		pResponseHandler->SetStatus(0, WBEM_E_NOT_SUPPORTED, NULL, NULL);
		return WBEM_E_NOT_SUPPORTED;
	}

	pClass->GetMethod(strMethodName, 0, NULL, &pOutClass);
	pOutClass->SpawnInstance(0, &pOutParams);

	if (lstrcmpW(L"SampleMethod", strMethodName) == 0) {	
		SampleMethod(pInParams, pOutParams);
		pResponseHandler->Indicate(1, &pOutParams);
		hr = WBEM_S_NO_ERROR;
	}
	else
		hr = WBEM_E_NOT_SUPPORTED;

	pResponseHandler->SetStatus(0, hr, NULL, NULL);

	pOutParams->Release();
	pOutClass->Release();
	pClass->Release();
	SysFreeString(bstrClassName);

	return hr;
}

void CWbemProvider::SampleMethod(IWbemClassObject *pInParams, IWbemClassObject *pOutParams)
{
	BSTR    bstrInputArgName = SysAllocString(L"strIn");
	BSTR    bstrOutputArgName = SysAllocString(L"strOut");
	BSTR    bstrRetValName = SysAllocString(L"ReturnValue");
	VARIANT varIn, varOut, varRet;
	BSTR    bstr;
	LONG    lRetValue;

	VariantInit(&varIn);
	pInParams->Get(bstrInputArgName, 0, &varIn, NULL, NULL);
	if (varIn.vt == VT_BSTR) {
		bstr = varIn.bstrVal;
		CharUpperBuffW(bstr, lstrlenW(bstr));
		
		varOut.vt = VT_BSTR;
		varOut.bstrVal = bstr;
		pOutParams->Put(bstrOutputArgName, 0, &varOut, 0);

		lRetValue = lstrlenW(bstr);

		VariantClear(&varIn);
		VariantClear(&varOut);
	}
	else
		lRetValue = -1;

	varRet.vt = VT_I4;
	varRet.lVal = lRetValue;
	pOutParams->Put(bstrRetValName, 0, &varRet, 0);
	
	SysFreeString(bstrInputArgName);
	SysFreeString(bstrOutputArgName);
	SysFreeString(bstrRetValName);
}

今回のプロバイダがサポートするのはインスタンスの列挙とメソッドの呼び出しであるため、 CreateInstanceEnumAsyncとExecMethodAsyncについては適切な実装を行っています。 それ以外のメソッドについては、WBEM_E_NOT_SUPPORTEDを返せばよいでしょう。 プロバイダを作成したらレジストリに登録します。

regsvr32 C:\sample.dll (登録の解除時は regsvr32 /u C:\sample.dll のようにする)

regsvr32にDLLのパスを指定すれば、DLLのDllRegisterServerを呼ばれ登録処理が行われます。 dllだけ登録しても、MOFファイルがコンパイルされていないことには、 プロバイダは使用されないことに注意してください。

クライアントの実装例

今回作成したプロバイダを使用する例を次に示します。

#include <windows.h>
#include <wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

HRESULT EnumInstance(IWbemServices *pNamespace, BSTR bstrClassPath);
HRESULT CallMethod(IWbemServices *pNamespace, BSTR bstrClassPath);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	HRESULT       hr;
	IWbemLocator  *pLocator;
	IWbemServices *pNamespace;
	BSTR          bstrClassPath;
	BSTR          bstrNamespace;
	BOOL          bEnum = TRUE;

	CoInitializeEx(0, COINIT_MULTITHREADED);
	CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);

	CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pLocator));
	
	bstrNamespace = SysAllocString(L"root\\cimv2");
	hr = pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
	if (FAILED(hr)) {
		SysFreeString(bstrNamespace);
		pLocator->Release();
		return 0;
	}
	
	hr = CoSetProxyBlanket(pNamespace, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);

	bstrClassPath = SysAllocString(L"MySampProv");
	if (bEnum)
		hr = EnumInstance(pNamespace, bstrClassPath);
	else
		hr = CallMethod(pNamespace, bstrClassPath);

	if (FAILED(hr)) {
		TCHAR szBuf[256];
		wsprintf(szBuf, TEXT("%x"), hr);
		MessageBox(NULL, szBuf, NULL, MB_ICONWARNING);
	}

	SysFreeString(bstrClassPath);
	pNamespace->Release();
	pLocator->Release();
	CoUninitialize();

	return 0;
}

HRESULT EnumInstance(IWbemServices *pNamespace, BSTR bstrClassPath)
{
	IEnumWbemClassObject *pEnumerator;
	IWbemClassObject     *pObject;
	BSTR                 bstrData;
	ULONG                uReturned;
	VARIANT              var;
	HRESULT              hr;
	WCHAR                szBuf[256];
	int                  nId;
	
	hr = pNamespace->CreateInstanceEnum(bstrClassPath, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator);
	if (FAILED(hr))
		return hr;

	while (pEnumerator) {
		hr = pEnumerator->Next(WBEM_INFINITE, 1, &pObject, &uReturned);
		if (hr != S_OK)
			break;

		pObject->Get(L"id", 0, &var, 0, 0);
		nId = var.lVal;
		pObject->Get(L"data", 0, &var, 0, 0);
		bstrData = var.bstrVal;

		wsprintfW(szBuf, L"%d %s", nId, bstrData);
		MessageBoxW(NULL, szBuf, L"OK", MB_OK);

		SysFreeString(bstrData);
		pObject->Release();
	}

	pEnumerator->Release();

	return hr;
}

HRESULT CallMethod(IWbemServices *pNamespace, BSTR bstrClassPath)
{
	IWbemClassObject *pClass;
	IWbemClassObject *pInClass;
	IWbemClassObject *pInInst;
	IWbemClassObject *pOutInst;
	BSTR             bstrMethodName;
	BSTR             bstrInputArgName;
	BSTR             bstrOutputArgName;
	BSTR             bstrInputValue;
	VARIANT          var;
	HRESULT          hr;

	hr = pNamespace->GetObject(bstrClassPath, 0, NULL, &pClass, NULL);
	if (FAILED(hr))
		return hr;

	bstrMethodName = SysAllocString(L"SampleMethod");
	hr = pClass->GetMethod(bstrMethodName, 0, &pInClass, NULL);
	if (FAILED(hr)) {
		pClass->Release();
		SysFreeString(bstrMethodName);
		return hr;
	}
	
	pInClass->SpawnInstance(0, &pInInst);
	
	bstrInputArgName = SysAllocString(L"strIn");
	bstrInputValue = SysAllocString(L"hello");
	var.vt = VT_BSTR;
	var.bstrVal = bstrInputValue;
	hr = pInInst->Put(bstrInputArgName, 0, &var, 0);
	if (FAILED(hr)) {
		pInInst->Release();
		pInClass->Release();
		pClass->Release();
		SysFreeString(bstrInputArgName);
		SysFreeString(bstrInputValue);
		SysFreeString(bstrMethodName);
		return hr;
	}
	
	pOutInst = NULL;
	hr = pNamespace->ExecMethod(bstrClassPath, bstrMethodName, 0, NULL, pInInst, &pOutInst, NULL);
	if (FAILED(hr)) {
		pInInst->Release();
		pInClass->Release();
		pClass->Release();
		SysFreeString(bstrInputArgName);
		SysFreeString(bstrInputValue);
		SysFreeString(bstrMethodName);
		return hr;
	}

	bstrOutputArgName = SysAllocString(L"strOut");
	VariantInit(&var);
	hr = pOutInst->Get(bstrOutputArgName, 0, &var, NULL, NULL);
	if (SUCCEEDED(hr)) {
		MessageBoxW(NULL, var.bstrVal, L"OK", MB_OK);
		VariantClear(&var);
	}
	
	pOutInst->Release();
	pInInst->Release();
	pInClass->Release();
	pClass->Release();
	SysFreeString(bstrOutputArgName);
	SysFreeString(bstrInputArgName);
	SysFreeString(bstrInputValue);
	SysFreeString(bstrMethodName);
	
	return hr;
}

今回のプロバイダは、MySampProvというクラスを定義していたため、その名前をbstrClassPathに指定します。 EnumInstanceではインスタンスを列挙する処理を行っていますが、ここでプロバイダのDATA構造体の中身が反映されていれば成功です。 CallMethodでは、プロバイダが定義していたSampleMethodというメソッドを呼び出します。 このメソッドは小文字を大文字に変換する処理になっていたため、引数に指定したhelloがHELLOと表示されれば成功です。



戻る