藉由撰寫提供者將數據提供給 WMI
WMI 提供者會建立一組支援的類別、實例和事件,以將數據傳遞至 WMI。 接著,管理應用程式或腳本可以呼叫 提供者方法來 操作提供者提供的數據。
下圖說明與 WMI 和應用程式結合之提供者之間的關聯性。
下列程序說明如何建立支援一組實例的簡單提供者。 此處所述的提供者已註冊以在 WMI 進程內執行。 在某些情況下,請使用 在不同進程中執行的分離提供者 。 如需提供者裝載模型的詳細資訊,請參閱 提供者裝載和安全性。 下列程式中的步驟 1 和 2 與分離提供者不同,但在其他方面,它們會使用與同進程提供者相同的介面。 如需詳細資訊,請參閱 在應用程式中納入提供者。
建立實例提供者
使用 Managed 物件格式 (MOF) 程式代碼建立__Win32Provider類別的實例,並提供提供者的名稱和 CLSID。 如需詳細資訊,請參閱 設計 Managed 物件格式 (MOF) 類別。
下列程式代碼範例示範如何建立 __Win32Provider 類別的實例。
Instance of __Win32Provider as $P // $P is an alias { // Name that describes your provider Name = "InstProvSamp" ; ClsId = "{22CB8761-914A-11cf-B705-00AA0062CBB7}" ; } ;
注意
若要確定如果 WMI 失敗且重新啟動,則會將所有 Managed 物件的 WMI 類別定義還原至 WMI 存放庫,請在 MOF 檔案中使用 #pragma 自動復原語句預處理器指示。
建立 描述實例提供者功能的 __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註冊您的類別。
從提供者目錄中的命令提示字元中,輸入下列命令,向WMI 註冊範例MOF程式碼。
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 會檢查 Managed 物件上的參數、擷取指定的物件、執行錯誤檢查,並將適當的程式代碼傳回給接收。
使用 RegSvr32 將您的提供者註冊為 COM 物件。
從提供者目錄中的指令提示字元中,輸入下列命令:
regsvr32 InstProv.dll
您的提供者現在已完成。 此時,您應該能夠從 WMI 中存取 InstProvSamp 類別的實例。
下列程式代碼範例會建立 COM 物件,以包含您的提供者,如上述步驟 5 所述。 完整範例包含標題為 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;
}
相關主題