プロバイダーを記述して WMI にデータを提供する方法
WMI プロバイダーは、サポートされているクラス、インスタンス、およびイベントのグループを作成して、WMI にデータを渡します。 その後、管理アプリケーションまたはスクリプトはプロバイダー メソッドを呼び出して、プロバイダーが提供するデータを操作できます。
次の図は、WMI に結合されているプロバイダーとアプリケーションの関係を示しています。
次の手順では、インスタンスのセットをサポートする単純なプロバイダーを作成する方法について説明します。 ここで説明するプロバイダーは、WMI プロセス内で実行するように登録されています。 場合によっては、別のプロセスで実行される分離プロバイダーを使用します。 プロバイダー ホスティング モデルの詳細については、「プロバイダー ホスティングとセキュリティ」を参照してください。 次の手順のステップ 1 と 2 は、分離プロバイダーでは異なりますが、他の点では、インプロセス プロバイダーと同じインターフェイスを使用します。 詳細については、「アプリケーションへのプロバイダーの組み込み」を参照してください。
インスタンス プロバイダーを作成する方法:
Managed Object Format (MOF) コードを使用して、__Win32Provider クラスのインスタンスを作成し、プロバイダーの名前と CLSID を指定します。 詳細については、「管理オブジェクトフォーマット (MOF) クラスの設計」を参照してください。
次のコード サンプルは、__Win32Provider クラスのインスタンスを作成する方法を示しています。
Instance of __Win32Provider as $P // $P is an alias { // Name that describes your provider Name = "InstProvSamp" ; ClsId = "{22CB8761-914A-11cf-B705-00AA0062CBB7}" ; } ;
Note
WMI に障害が発生して再起動した場合に、マネージド オブジェクトのすべての WMI クラス定義が WMI リポジトリに確実に復元されるようにするには、MOF ファイルで #pragma autorecover ステートメント プリプロセッサ命令を使用します。
詳細については、「インスタンスの作成」および「インスタンス プロバイダーの登録」を参照してください。
インスタンス プロバイダーの機能を記述する __InstanceProviderRegistration クラスのインスタンスを作成します。
次のコード サンプルは、__InstanceProviderRegistration クラスのインスタンスを作成する方法を示しています。
instance of __InstanceProviderRegistration { Provider = $P; // Alias to the __Win32Provider SupportsPut = FALSE; // Does not support the Put method SupportsGet = TRUE; // Supports the Get method SupportsDelete = FALSE; // Does not support the Delete method SupportsEnumeration = TRUE; // Supports enumeration. };
MOF コードのこのセクションのプロパティの詳細については、「__InstanceProviderRegistration」および「__ObjectProviderRegistration」を参照してください。
詳細については、「インスタンス プロバイダーの登録」 を参照してください。
MOF コードを使用して、プロバイダーがインスタンスを提供する動的クラスを作成します。
動的クラスは、インスタンスがプロバイダーから更新を受け取るクラスです。 これらの更新は、定期的に行うか、インスタンスが表すオブジェクトの散発的な変更にリンクさせることができます。 動的クラス インスタンスへの変更は、独自の管理アプリケーションまたは WMI オブジェクト ブラウザーを使用して表示できます。
次のコード サンプルでは、"InstProvSamp" プロバイダーでサポートされる動的クラスについて説明します。
[dynamic, provider("InstProvSamp"), // uses the InstProvSamp Provider ClassContext("whatever!")] // information is dynamically // supported by the provider class InstProvSamp { [key] // MyKey uniquely identifies this class String MyKey="HELLO"; // InstProvSamp dynamically updates MyValue [PropertyContext("Name")] uint32 MyValue; };
MOF コンパイラを使用して WMI にクラスを登録します。
プロバイダー ディレクトリのコマンド プロンプトから、次のように入力して、MOF コードの例を WMI に登録します。
mofcomp instprov.mof
詳細については、「MOF ファイルのコンパイル」を参照してください。
プロバイダーを格納する COM オブジェクトを定義します。 この手順のコード例は、このトピックの最後にある完全な例に示されています。
COM オブジェクトと同様に、コンストラクターとデコンストラクター、および QueryInterface、AddRef、および Release メソッドを実装する必要があります。
COM オブジェクトに IWbemProviderInit::Initialize メソッドを実装します。
この例の Initialize の主な目的は、m_pNamespace メンバーを現在の名前空間に設定することです。 名前空間の詳細については、「WMI 内での階層の作成」を参照してください。
シンクは、IWbemProviderInit::Initialize メソッドの pInitSink パラメーターを介して渡され、プロバイダーが正常に初期化されたことを示します。 シンクの詳細については、「IWbemObjectSink」および「メソッドの呼び出し」を参照してください。
COM オブジェクト内に IWbemServices::CreateInstanceEnumAsync メソッドを実装します (さまざまな IWbemServices インターフェイスを実装できますが、このトピックの最後の例では、CreateInstanceEnumAsync のみを実装します)。 具体的には、CreateInstanceEnumAsync は、指定したオブジェクトのインスタンスを WMI に返します。
COM オブジェクト内に GetObjectAsync メソッドを実装します。
このトピックの最後にある例では、GetObjectAsync はマネージド オブジェクトのパラメーターをチェックし、指定されたオブジェクトを取得し、エラー チェックを実行して、シンクに適切なコードを返します。
RegSvr32 を使用して、プロバイダーを COM オブジェクトとして登録します。
プロバイダー ディレクトリのコマンド プロンプトから、次のように入力します。
regsvr32 InstProv.dll
これでデプロイが完成しました。 この時点で、WMI 内から InstProvSamp クラスのインスタンスにアクセスできるようになっています。
次のコード例では、上記のステップ 5 で説明したように、プロバイダーを格納する COM オブジェクトを作成します。 完全なサンプルには、Sample.h というタイトルのヘッダー ファイルのコードと、Instprov.cpp、Utils.cpp、Classfac.cpp、Maindll.cpp というタイトルのソース ファイルが含まれています。
//*******************************************************************
// sample.h
// WMI Instance provider sample code
//
// Copyright (C) Microsoft. All Rights Reserved.
//
//*******************************************************************
#ifndef _sample_H_
#define _sample_H_
#include <wbemprov.h>
#pragma comment(lib, "wbemuuid.lib")
typedef LPVOID * PPVOID;
// Provider interfaces are provided by objects of this class
class CInstPro : public IWbemServices, public IWbemProviderInit
{
protected:
ULONG m_cRef; //Object reference count
IWbemServices* m_pNamespace;
public:
CInstPro(BSTR ObjectPath = NULL, BSTR User = NULL, BSTR Password = NULL, IWbemContext * pCtx=NULL);
~CInstPro(void);
//Non-delegating object IUnknown
STDMETHODIMP QueryInterface(REFIID, PPVOID);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
//IWbemProviderInit
HRESULT STDMETHODCALLTYPE Initialize(
/* [in] */ LPWSTR pszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR pszNamespace,
/* [in] */ LPWSTR pszLocale,
/* [in] */ IWbemServices *pNamespace,
/* [in] */ IWbemContext *pCtx,
/* [in] */ IWbemProviderInitSink *pInitSink
);
SCODE GetByPath( BSTR Path,
IWbemClassObject FAR* FAR* pObj,
IWbemContext *pCtx);
//IWbemServices
HRESULT STDMETHODCALLTYPE OpenNamespace(
/* [in] */ const BSTR Namespace,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemServices __RPC_FAR *__RPC_FAR *ppWorkingNamespace,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE CancelAsyncCall(
/* [in] */ IWbemObjectSink __RPC_FAR *pSink)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE QueryObjectSink(
/* [in] */ long lFlags,
/* [out] */ IWbemObjectSink __RPC_FAR *__RPC_FAR *ppResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE GetObject(
/* [in] */ const BSTR ObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppObject,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE GetObjectAsync(
/* [in] */ const BSTR ObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler);
HRESULT STDMETHODCALLTYPE PutClass(
/* [in] */ IWbemClassObject __RPC_FAR *pObject,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE PutClassAsync(
/* [in] */ IWbemClassObject __RPC_FAR *pObject,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE DeleteClass(
/* [in] */ const BSTR Class,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE DeleteClassAsync(
/* [in] */ const BSTR Class,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE CreateClassEnum(
/* [in] */ const BSTR Superclass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */
IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE CreateClassEnumAsync(
/* [in] */ const BSTR Superclass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE PutInstance(
/* [in] */ IWbemClassObject __RPC_FAR *pInst,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE PutInstanceAsync(
/* [in] */ IWbemClassObject __RPC_FAR *pInst,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE DeleteInstance(
/* [in] */ const BSTR ObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE DeleteInstanceAsync(
/* [in] */ const BSTR ObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE CreateInstanceEnum(
/* [in] */ const BSTR Class,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE CreateInstanceEnumAsync(
/* [in] */ const BSTR Class,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler);
HRESULT STDMETHODCALLTYPE ExecQuery(
/* [in] */ const BSTR QueryLanguage,
/* [in] */ const BSTR Query,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE ExecQueryAsync(
/* [in] */ const BSTR QueryLanguage,
/* [in] */ const BSTR Query,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE ExecNotificationQuery(
/* [in] */ const BSTR QueryLanguage,
/* [in] */ const BSTR Query,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE ExecNotificationQueryAsync(
/* [in] */ const BSTR QueryLanguage,
/* [in] */ const BSTR Query,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
{return WBEM_E_NOT_SUPPORTED;};
HRESULT STDMETHODCALLTYPE ExecMethod( const BSTR,
const BSTR,
long,
IWbemContext*,
IWbemClassObject*,
IWbemClassObject**,
IWbemCallResult**)
{return WBEM_E_NOT_SUPPORTED;}
HRESULT STDMETHODCALLTYPE ExecMethodAsync( const BSTR,
const BSTR,
long,
IWbemContext*,
IWbemClassObject*,
IWbemObjectSink*)
{return WBEM_E_NOT_SUPPORTED;}
};
typedef CInstPro *PCInstPro;
// This class is the class factory for CInstPro objects.
class CProvFactory : public IClassFactory
{
protected:
ULONG m_cRef;
public:
CProvFactory(void);
~CProvFactory(void);
//IUnknown members
STDMETHODIMP QueryInterface(REFIID, PPVOID);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
//IClassFactory members
STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, PPVOID);
STDMETHODIMP LockServer(BOOL);
};
typedef CProvFactory *PCProvFactory;
// These variables keep track of
// when the module can be unloaded
extern long g_cObj;
extern long g_cLock;
// General purpose utilities.
DWORD GetCurrentImpersonationLevel ();
SCODE CreateInst( IWbemServices * pNamespace,
LPWSTR pKey, long lVal,
IWbemClassObject ** pNewInst,
WCHAR * pwcClassName,
IWbemContext *pCtx);
typedef struct {
WCHAR * pwcKey;
long lValue;
} InstDef;
extern InstDef MyDefs[];
extern long glNumInst;
#endif
Instpro.cpp ソース ファイルには、Sample.h ヘッダー ファイルで宣言されたプロバイダーの関数を実装するコードが含まれています。
//*******************************************************************
// INSTPRO.CPP
//
// Module: WMI Instance provider sample code
//
// Purpose: Defines the CInstPro class. An object of this class is
// created by the class factory for each connection.
// Copyright (C) Microsoft. All Rights Reserved.
//
//*******************************************************************
#define _WIN32_WINNT 0x0500
#include <objbase.h>
#include "sample.h"
#include <process.h>
#include <strsafe.h>
#include <sddl.h>
InstDef MyDefs[] = {{L"a", 1}, {L"b", 2}, {L"c", 3}};
long glNumInst = sizeof(MyDefs)/sizeof(InstDef);
//*******************************************************************
//
// CInstPro::CInstPro
// CInstPro::~CInstPro
//
//*******************************************************************
CInstPro::CInstPro(BSTR ObjectPath,
BSTR User,
BSTR Password,
IWbemContext * pCtx)
{
m_pNamespace = NULL;
m_cRef=0;
InterlockedIncrement(&g_cObj);
return;
}
CInstPro::~CInstPro(void)
{
if(m_pNamespace)
m_pNamespace->Release();
InterlockedDecrement(&g_cObj);
return;
}
//*******************************************************************
//
// CInstPro::QueryInterface
// CInstPro::AddRef
// CInstPro::Release
//
// Purpose: IUnknown members for CInstPro object.
//*******************************************************************
STDMETHODIMP CInstPro::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
// Because you have dual inheritance,
// it is necessary to cast the return type
if(riid== IID_IWbemServices)
*ppv=(IWbemServices*)this;
if(IID_IUnknown==riid || riid== IID_IWbemProviderInit)
*ppv=(IWbemProviderInit*)this;
if (NULL!=*ppv)
{
AddRef();
return NOERROR;
}
else
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CInstPro::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CInstPro::Release(void)
{
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
if (0L == nNewCount)
delete this;
return nNewCount;
}
/********************************************************************
*
* CInstPro::Initialize
*
* Purpose: This is the implementation of IWbemProviderInit.
* The method is required to initialize with CIMOM.
*
********************************************************************/
STDMETHODIMP CInstPro::Initialize(LPWSTR pszUser,
LONG lFlags,
LPWSTR pszNamespace,
LPWSTR pszLocale,
IWbemServices *pNamespace,
IWbemContext *pCtx,
IWbemProviderInitSink *pInitSink)
{
if(! pNamespace)
{
pInitSink->SetStatus(WBEM_E_FAILED , 0);
}
else
{
m_pNamespace = pNamespace;
m_pNamespace->AddRef();
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
}
return WBEM_S_NO_ERROR;
}
//*******************************************************************
//
// CInstPro::CreateInstanceEnumAsync
//
// Purpose: Asynchronously enumerates the instances.
//
//*******************************************************************
SCODE CInstPro::CreateInstanceEnumAsync( const BSTR RefStr,
long lFlags,
IWbemContext *pCtx,
IWbemObjectSink FAR* pHandler)
{
//Impersonate the client
HRESULT hr = CoImpersonateClient () ;
if ( FAILED ( hr ) )
{
pHandler->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
// Check to see if call is at lower than
// RPC_C_IMP_LEVEL_IMPERSONATE level. If that is the case,
// the provider will not be able to impersonate
// the client to access the protected resources.
DWORD t_CurrentImpersonationLevel =
GetCurrentImpersonationLevel () ;
if ( t_CurrentImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE )
{
// Revert before you perform any operations
CoRevertToSelf () ;
hr = WBEM_E_ACCESS_DENIED;
pHandler->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
SCODE sc;
int iCnt;
IWbemClassObject FAR* pNewInst;
// Do a check of arguments and ensure
// you have a pointer to Namespace
if(pHandler == NULL || m_pNamespace == NULL)
return WBEM_E_INVALID_PARAMETER;
for(iCnt=0; iCnt < glNumInst; iCnt++)
{
sc = CreateInst(m_pNamespace,MyDefs[iCnt].pwcKey, MyDefs[iCnt].lValue, &pNewInst, RefStr, pCtx);
if(sc != S_OK)
break;
// Send the object to the caller
pHandler->Indicate(1,&pNewInst);
pNewInst->Release();
}
// Set status
pHandler->SetStatus(0,sc,NULL, NULL);
return sc;
}
//*******************************************************************
//
// CInstPro::GetObjectByPath
// CInstPro::GetObjectByPathAsync
//
// Purpose: Creates an instance given a particular path value.
//
//*******************************************************************
SCODE CInstPro::GetObjectAsync(const BSTR ObjectPath,
long lFlags,
IWbemContext *pCtx,
IWbemObjectSink FAR* pHandler)
{
//Impersonate the client
HRESULT hr = CoImpersonateClient () ;
if ( FAILED ( hr ) )
{
pHandler->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
// Check to see if call is at the
// RPC_C_IMP_LEVEL_IDENTIFY level. If that is the case,
// the provider will not be able to impersonate
// the client to access the protected resources.
if (GetCurrentImpersonationLevel () == RPC_C_IMP_LEVEL_IDENTIFY)
{
hr = WBEM_E_ACCESS_DENIED;
pHandler->SetStatus ( 0 , hr , NULL , NULL ) ;
return hr ;
}
SCODE sc;
IWbemClassObject FAR* pObj;
BOOL bOK = FALSE;
// Do a check of arguments and ensure
// you have a pointer to Namespace
if(ObjectPath == NULL ||
pHandler == NULL ||
m_pNamespace == NULL)
return WBEM_E_INVALID_PARAMETER;
// do the get, pass the object on to the notify
sc = GetByPath(ObjectPath,&pObj, pCtx);
if(sc == S_OK)
{
pHandler->Indicate(1,&pObj);
pObj->Release();
bOK = TRUE;
}
sc = (bOK) ? S_OK : WBEM_E_NOT_FOUND;
// Set Status
pHandler->SetStatus(0,sc, NULL, NULL);
return sc;
}
//*******************************************************************
//
// CInstPro::GetByPath
//
// Purpose: Creates an instance given a particular Path value.
//
//*******************************************************************
SCODE CInstPro::GetByPath(BSTR ObjectPath,
IWbemClassObject FAR* FAR* ppObj,
IWbemContext *pCtx)
{
SCODE sc = S_OK;
int iCnt;
// Do a simple path parse. The path looks like
// InstProvSamp.MyKey="a"
// Create a test string with just the part between quotes.
WCHAR wcTest[MAX_PATH+1];
memset(wcTest, NULL, sizeof(wcTest));
StringCbCopyW(wcTest, sizeof(wcTest), ObjectPath);
WCHAR * pwcTest, * pwcCompare = NULL;
int iNumQuotes = 0;
for(pwcTest = wcTest; *pwcTest; pwcTest++)
if(*pwcTest == L'\"')
{
iNumQuotes++;
if(iNumQuotes == 1)
{
pwcCompare = pwcTest+1;
}
else if(iNumQuotes == 2)
{
*pwcTest = NULL;
break;
}
}
else if(*pwcTest == L'.')
*pwcTest = NULL; // isolate the class name.
if(iNumQuotes != 2)
return WBEM_E_FAILED;
// check the instance list for a match.
for(iCnt = 0; iCnt < glNumInst; iCnt++)
{
if(!_wcsicmp(MyDefs[iCnt].pwcKey, pwcCompare))
{
sc = CreateInst(m_pNamespace,MyDefs[iCnt].pwcKey, MyDefs[iCnt].lValue, ppObj, wcTest, pCtx);
return sc;
}
}
return WBEM_E_NOT_FOUND;
}
Utils.cpp ソース ファイルには、Sample.h ヘッダー ファイルで宣言されたプロバイダーのユーティリティ関数を実装するコードが含まれています。
//*******************************************************************
// UTILS.CPP
// Module: WMI Instance provider sample code
// Purpose: General purpose utilities.
// (c) Microsoft. All rights reserved.
//
//*******************************************************************
#include <objbase.h>
#include "sample.h"
//*******************************************************************
//
// CreateInst
//
// Purpose: Creates a new instance and sets
// the initial values of the properties.
//
// Return: S_OK if all is well, otherwise an error code is returned
//
//*******************************************************************
SCODE CreateInst(IWbemServices * pNamespace,
LPWSTR pKey,
long lVal,
IWbemClassObject ** pNewInst,
WCHAR * pwcClassName,
IWbemContext *pCtx)
{
SCODE sc;
IWbemClassObject * pClass = NULL;
sc = pNamespace->GetObject(pwcClassName, 0, pCtx, &pClass, NULL);
if(sc != S_OK)
return WBEM_E_FAILED;
sc = pClass->SpawnInstance(0, pNewInst);
pClass->Release();
if(FAILED(sc))
return sc;
VARIANT v;
// Set the key property value.
v.vt = VT_BSTR;
v.bstrVal = SysAllocString(pKey);
if (!v.bstrVal)
return WBEM_E_OUT_OF_MEMORY;
sc = (*pNewInst)->Put(L"MyKey", 0, &v, 0);
VariantClear(&v);
if(FAILED(sc))
return sc;
// Set the number property value.
v.vt = VT_I4;
v.lVal = lVal;
sc = (*pNewInst)->Put(L"MyValue", 0, &v, 0);
return sc;
}
/********************************************************************
*
* Name: GetCurrentImpersonationLevel
* Description: Get COM impersonation level of caller.
*
*******************************************************************/
DWORD GetCurrentImpersonationLevel ()
{
DWORD t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
HANDLE t_ThreadToken = NULL ;
BOOL t_Status = OpenThreadToken(GetCurrentThread(),TOKEN_QUERY,TRUE,&t_ThreadToken);
if ( t_Status )
{
SECURITY_IMPERSONATION_LEVEL t_Level = SecurityAnonymous ;
DWORD t_Returned = 0 ;
t_Status = GetTokenInformation( t_ThreadToken,
TokenImpersonationLevel,
&t_Level,
sizeof(SECURITY_IMPERSONATION_LEVEL),
&t_Returned);
CloseHandle ( t_ThreadToken ) ;
if ( t_Status == FALSE )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
else
{
switch ( t_Level )
{
case SecurityAnonymous:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS;
}
break;
case SecurityIdentification:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_IDENTIFY;
}
break ;
case SecurityImpersonation:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
}
break ;
case SecurityDelegation:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE ;
}
break ;
default:
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
break ;
}
}
}
else
{
ULONG t_LastError = GetLastError () ;
if ( t_LastError == ERROR_NO_IMPERSONATION_TOKEN ||
t_LastError == ERROR_NO_TOKEN )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE ;
}
else
{
if ( t_LastError == ERROR_CANT_OPEN_ANONYMOUS )
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
else
{
t_ImpersonationLevel = RPC_C_IMP_LEVEL_ANONYMOUS ;
}
}
}
return t_ImpersonationLevel ;
}
Classfac.cpp ソース ファイルには、接続が要求されたときにオブジェクトを作成するコードが含まれています。
//*******************************************************************
//
// CLASSFAC.CPP
// Module: WMI Instance provider sample code
// Purpose: Contains the class factory. This creates objects when
// connections are requested.
// Copyright (C) Microsoft. All Rights Reserved.
//
//*******************************************************************
#include <objbase.h>
#include "sample.h"
//*******************************************************************
//
// CProvFactory::CProvFactory
// CProvFactory::~CProvFactory
//
// Constructor Parameters:
// None
//*******************************************************************
CProvFactory::CProvFactory()
{
m_cRef=0L;
return;
}
CProvFactory::~CProvFactory(void)
{
return;
}
//*******************************************************************
//
// CProvFactory::QueryInterface
// CProvFactory::AddRef
// CProvFactory::Release
//
// Purpose: Standard Ole routines needed for all interfaces
//
//*******************************************************************
STDMETHODIMP CProvFactory::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid || IID_IClassFactory==riid)
*ppv=this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CProvFactory::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CProvFactory::Release(void)
{
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
if (0L == nNewCount)
delete this;
return nNewCount;
}
//*******************************************************************
//
// CProvFactory::CreateInstance
//
// Purpose: Instantiates a Locator object
// and returns an interface pointer.
//
// Parameters:
// pUnkOuter LPUNKNOWN to the controlling IUnknown if
// being used in an aggregation.
// riid REFIID identifies the interface the caller
// desires to have for the new object.
// ppvObj PPVOID in which to store the desired
// interface pointer for the new object.
//
// Return Value:
// HRESULT NOERROR if successful, otherwise E_NOINTERFACE
// if you cannot support the requested interface.
//*******************************************************************
STDMETHODIMP CProvFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, PPVOID ppvObj)
{
CInstPro * pObj;
HRESULT hr;
*ppvObj=NULL;
// This object does not support aggregation.
if (NULL!=pUnkOuter)
return CLASS_E_NOAGGREGATION;
// Create the locator object.
pObj=new CInstPro();
if (NULL==pObj)
return E_OUTOFMEMORY;
hr=pObj->QueryInterface(riid, ppvObj);
//Kill the object if initial creation or Init failed.
if (FAILED(hr))
delete pObj;
return hr;
}
//*******************************************************************
//
// CProvFactory::LockServer
//
// Purpose:
// Increments or decrements the lock count of the DLL. If the
// lock count goes to zero and there are no objects, the DLL
// is allowed to unload. See DllCanUnloadNow.
//
// Parameters:
// fLock BOOL specifying whether to increment or
// decrement the lock count.
//
// Return Value:
// HRESULT NOERROR always.
//*******************************************************************
STDMETHODIMP CProvFactory::LockServer(BOOL fLock)
{
if (fLock)
InterlockedIncrement(&g_cLock);
else
InterlockedDecrement(&g_cLock);
return NOERROR;
}
Maindll.cpp ソース ファイルには、オブジェクトとロックの数を追跡することによって DLL をアンロードできるタイミングを制御するコードと、自己登録をサポートするルーチンが含まれています。
//*******************************************************************
// MAINDLL.CPP
// Module: WMI Instance provider sample code
// Purpose: Contains DLL entry points. Also has code that controls
// when the DLL can be unloaded by tracking the number of
// objects and locks as well as routines that support
// self registration.
//
// Copyright (C) Microsoft. All Rights Reserved.
//
//*******************************************************************
#include <objbase.h>
#include <initguid.h>
#include <strsafe.h>
#include "sample.h"
HMODULE ghModule;
// TODO, GuidGen should be used to generate a unique number for any
// providers that are going to be used for anything more extensive
// than just testing.
DEFINE_GUID(CLSID_instprovider, 0x22cb8761, 0x914a, 0x11cf, 0xb7, 0x5, 0x0, 0xaa, 0x0, 0x62, 0xcb, 0xb7);
// {22CB8761-914A-11cf-B705-00AA0062CBB7}
//Count number of objects and number of locks.
long g_cObj=0;
long g_cLock=0;
//*******************************************************************
//
// LibMain32
//
// Purpose: Entry point for DLL.
//
// Return: TRUE if OK.
//
//*******************************************************************
BOOL WINAPI LibMain32(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
if (DLL_PROCESS_ATTACH==ulReason)
ghModule = hInstance;
return TRUE;
}
//*******************************************************************
//
// DllGetClassObject
//
// Purpose: Called by Ole when some client wants a class factory.
// Return one only if it is the sort of
// class this DLL supports.
//
//*******************************************************************
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PPVOID ppv)
{
HRESULT hr;
CProvFactory *pObj;
if (CLSID_instprovider!=rclsid)
return E_FAIL;
pObj=new CProvFactory();
if (NULL==pObj)
return E_OUTOFMEMORY;
hr=pObj->QueryInterface(riid, ppv);
if (FAILED(hr))
delete pObj;
return hr;
}
//*******************************************************************
//
// DllCanUnloadNow
//
// Purpose: Called periodically by Ole to determine if the
// DLL can be freed.
//
// Return: S_OK if there are no objects in use and the class factory
// is not locked.
//
//*******************************************************************
STDAPI DllCanUnloadNow(void)
{
SCODE sc;
//It is OK to unload if there are no objects or locks on the
// class factory.
sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
return sc;
}
//*******************************************************************
//
// DllRegisterServer
//
// Purpose: Called during setup or by regsvr32.
//
// Return: NOERROR if registration successful, error otherwise.
//*******************************************************************
STDAPI DllRegisterServer(void)
{
char szID[128];
WCHAR wcID[128];
char szCLSID[128];
TCHAR szModule[MAX_PATH + 1];
const char * pName = "WMI Sample Instance Provider";
const char * pModel = "Both";
HKEY hKey1, hKey2;
// Create the path.
memset(wcID, NULL, sizeof(wcID));
memset(szID, NULL, sizeof(szID));
StringFromGUID2(CLSID_instprovider, wcID, sizeof(wcID)/sizeof(WCHAR));
wcstombs(szID, wcID, sizeof(szID));
StringCbCopy(szCLSID, sizeof(szCLSID), "Software\\classes\\CLSID\\");
StringCbCat(szCLSID, sizeof(szCLSID), (LPCTSTR)szID);
// Create entries under CLSID
LONG lRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
szCLSID,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey1,
NULL );
if (lRet != ERROR_SUCCESS)
{
return E_FAIL;
}
lRet = RegSetValueEx(hKey1, NULL, 0, REG_SZ, (BYTE *)pName, strlen(pName)+1);
if (lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey1);
return E_FAIL;
}
lRet = RegCreateKeyEx( hKey1, "InprocServer32", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey2, NULL );
if (lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey1);
return E_FAIL;
}
memset(&szModule, NULL, sizeof(szModule));
GetModuleFileName(ghModule, szModule, sizeof(szModule)/sizeof(TCHAR) - 1);
lRet = RegSetValueEx(hKey2, NULL, 0, REG_SZ, (BYTE *)szModule, strlen(szModule)+1);
if (lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey2);
RegCloseKey(hKey1);
return E_FAIL;
}
lRet = RegSetValueEx(hKey2, "ThreadingModel", 0, REG_SZ, (BYTE *)pModel, strlen(pModel)+1);
if (lRet != ERROR_SUCCESS)
{
RegCloseKey(hKey2);
RegCloseKey(hKey1);
return E_FAIL;
}
RegCloseKey(hKey1);
RegCloseKey(hKey2);
return NOERROR;
}
//*******************************************************************
//
// DllUnregisterServer
//
// Purpose: Called when it is time to remove the registry entries.
//
// Return: NOERROR if registration successful, error otherwise.
//*******************************************************************
STDAPI DllUnregisterServer(void)
{
TCHAR szID[128];
WCHAR wcID[128];
TCHAR szCLSID[128];
HKEY hKey;
// Create the path using the CLSID
memset(wcID, NULL, sizeof(wcID));
memset(szID, NULL, sizeof(szID));
StringFromGUID2(CLSID_instprovider, wcID, sizeof(wcID)/sizeof(WCHAR));
wcstombs(szID, wcID, sizeof(szID));
StringCbCopy(szCLSID, sizeof(szCLSID), "Software\\classes\\CLSID\\");
StringCbCat(szCLSID, sizeof(szCLSID), (LPCTSTR)szID);
// First delete the InProcServer subkey.
DWORD dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCLSID, 0, KEY_WRITE, &hKey);
if(dwRet == NO_ERROR)
{
RegDeleteKey(hKey, "InProcServer32");
RegCloseKey(hKey);
}
dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\classes\\CLSID", 0, KEY_WRITE, &hKey);
if(dwRet == NO_ERROR)
{
RegDeleteKey(hKey,szID);
RegCloseKey(hKey);
}
return NOERROR;
}
関連トピック