2025-04-27 07:49:33 -04:00

487 lines
13 KiB
C++

//***************************************************************************
//
// INSTPRO.CPP
//
// Module: WMI Instance provider sample code
//
// Purpose: Defines the CServExtPro class. An object of this class is
// created by the class factory for each connection.
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include <windows.h>
#include "servprov.h"
// #define _MT
#include <process.h>
#include <genlex.h>
#include <opathlex.h>
#include <objpath.h>
#define PERFORMANCE_SERVICE_CLASS L"Win32_PerformanceService"
#define SERVICE_CLASS_KEY L"Name"
//***************************************************************************
//
// CServExtPro::CServExtPro
// CServExtPro::~CServExtPro
//
//***************************************************************************
CServExtPro::CServExtPro()
{
m_pClass = NULL;
m_hServices = NULL;
m_cRef=0;
InterlockedIncrement(&g_cObj);
return;
}
CServExtPro::~CServExtPro(void)
{
if(m_pClass)
m_pClass->Release();
if(m_hServices)
RegCloseKey(m_hServices);
InterlockedDecrement(&g_cObj);
return;
}
//***************************************************************************
//
// CServExtPro::QueryInterface
// CServExtPro::AddRef
// CServExtPro::Release
//
// Purpose: IUnknown members for CServExtPro object.
//***************************************************************************
STDMETHODIMP CServExtPro::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
// Since we 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) CServExtPro::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CServExtPro::Release(void)
{
ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
if (0L == nNewCount)
delete this;
return nNewCount;
}
/***********************************************************************
* *
* CServExtPro::Initialize *
* *
* Purpose: This is the implementation of IWbemProviderInit. The method *
* is need to initialize with CIMOM. *
* *
***********************************************************************/
STDMETHODIMP CServExtPro::Initialize(LPWSTR pszUser, LONG lFlags,
LPWSTR pszNamespace, LPWSTR pszLocale,
IWbemServices *pNamespace,
IWbemContext *pCtx,
IWbemProviderInitSink *pInitSink)
{
HRESULT hres;
// Retrieve our class definition
// =============================
BSTR strClassName = SysAllocString(PERFORMANCE_SERVICE_CLASS);
hres = pNamespace->GetObject(strClassName, 0, pCtx, &m_pClass, NULL);
SysFreeString(strClassName);
if(FAILED(hres))
{
pInitSink->SetStatus(WBEM_E_FAILED, 0);
return WBEM_S_NO_ERROR;
}
// There is no need to keep the namespace pointer --- we got all we needed
// =======================================================================
// Open the registry key for services
// ==================================
long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services",
0, KEY_READ, &m_hServices);
if(lRes)
{
pInitSink->SetStatus(WBEM_E_FAILED, 0);
return WBEM_S_NO_ERROR;
}
//Let CIMOM know you are initialized
//==================================
pInitSink->SetStatus(WBEM_S_INITIALIZED,0);
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
// CServExtPro::CreateInstanceEnumAsync
//
// Purpose: Asynchronously enumerates the instances.
//
//***************************************************************************
STDMETHODIMP CServExtPro::CreateInstanceEnumAsync(const BSTR strClass, long lFlags,
IWbemContext *pCtx, IWbemObjectSink* pSink)
{
CoImpersonateClient();
BOOL bRes;
HANDLE hOrigToken;
long lRes;
bRes = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hOrigToken);
lRes = GetLastError();
HANDLE hNewToken;
bRes = DuplicateTokenEx(hOrigToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenPrimary, &hNewToken);
lRes = GetLastError();
STARTUPINFO si;
memset((void*)&si, 0, sizeof(si));
si.cb = sizeof(si);
si.lpDesktop = "winsta0\\default";
PROCESS_INFORMATION pi;
bRes = CreateProcessAsUser(hNewToken, NULL, "c:\\winnt\\system32\\cmd.exe",
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
lRes = GetLastError();
// Check the class to ensure it is supported
// =========================================
if(strClass == NULL || _wcsicmp(strClass, PERFORMANCE_SERVICE_CLASS) ||
pSink == NULL)
{
return WBEM_E_INVALID_PARAMETER;
}
HRESULT hres;
// Determine maximum subkey length
// ===============================
DWORD dwMaxLen;
lRes = RegQueryInfoKey(m_hServices, NULL, NULL, NULL, NULL, &dwMaxLen,
NULL, NULL, NULL, NULL, NULL, NULL);
if(lRes)
return WBEM_E_FAILED;
// Enumerate all the subkeys of the Services key
// =============================================
DWORD dwIndex = 0;
WCHAR* wszKeyName = new WCHAR[dwMaxLen+1];
DWORD dwNameLen = dwMaxLen + 1;
while(RegEnumKeyExW(m_hServices, dwIndex++, wszKeyName, &dwNameLen, NULL,
NULL, NULL, NULL) == ERROR_SUCCESS)
{
// Construct our instance (if any) for this service
// ================================================
IWbemClassObject* pInst = NULL;
if(ConstructInstance(wszKeyName, &pInst))
{
// Report it to CIMOM using Indicate
// =================================
hres = pSink->Indicate(1, &pInst);
pInst->Release();
if(FAILED(hres))
{
// Operation must be cancelled
// ===========================
break;
}
}
dwNameLen = dwMaxLen + 1;
}
// Report success to CIMOM
// =======================
pSink->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
delete [] wszKeyName;
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
// CServExtPro::GetObjectByPath
// CServExtPro::GetObjectByPathAsync
//
// Purpose: Creates an instance given a particular path value.
//
//***************************************************************************
SCODE CServExtPro::GetObjectAsync(const BSTR strObjectPath, long lFlags,
IWbemContext *pCtx, IWbemObjectSink* pSink)
{
CoImpersonateClient();
if(strObjectPath == NULL || pSink == NULL)
return WBEM_E_INVALID_PARAMETER;
// Parse the object path
// =====================
BSTR strServiceName;
if(!ParsePath(strObjectPath, &strServiceName))
return WBEM_E_INVALID_OBJECT_PATH;
// Construct the instance representing this service, if any
// ========================================================
IWbemClassObject* pInst = NULL;
if(ConstructInstance(strServiceName, &pInst))
{
// Report it to CIMOM using Indicate
// =================================
pSink->Indicate(1, &pInst);
pInst->Release();
// Report success to CIMOM using SetStatus
// =======================================
pSink->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
}
else
{
// No such instance: report failure to CIMOM
// =========================================
pSink->SetStatus(0, WBEM_E_NOT_FOUND, NULL, NULL);
}
SysFreeString(strServiceName);
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
// CServExtPro::GetByPath
//
// Purpose: Creates an instance given a particular Path value.
//
//***************************************************************************
BOOL CServExtPro::ParsePath(const BSTR strObjectPath, BSTR* pstrServiceName)
{
// Get the sample parser to parse it into a structure
// ==================================================
CObjectPathParser Parser;
ParsedObjectPath* pOutput;
if(Parser.Parse(strObjectPath, &pOutput) != CObjectPathParser::NoError)
return FALSE;
// Make sure the class name is the right one
// =========================================
if(_wcsicmp(pOutput->m_pClass, PERFORMANCE_SERVICE_CLASS))
{
Parser.Free(pOutput);
return FALSE;
}
// Check the number of keys
// ========================
if(pOutput->m_dwNumKeys != 1)
{
Parser.Free(pOutput);
return FALSE;
}
// Check key name
// ==============
if(pOutput->m_paKeys[0]->m_pName != NULL &&
_wcsicmp(pOutput->m_paKeys[0]->m_pName, SERVICE_CLASS_KEY))
{
Parser.Free(pOutput);
return FALSE;
}
// Return the value of the key
// ===========================
if(V_VT(&pOutput->m_paKeys[0]->m_vValue) != VT_BSTR)
{
Parser.Free(pOutput);
return FALSE;
}
*pstrServiceName = SysAllocString(V_BSTR(&pOutput->m_paKeys[0]->m_vValue));
Parser.Free(pOutput);
return TRUE;
}
BOOL CServExtPro::ConstructInstance(LPCWSTR wszServiceName,
IWbemClassObject** ppInst)
{
// Locate the service
// ==================
HKEY hService;
if(RegOpenKeyExW(m_hServices, wszServiceName, 0, KEY_READ, &hService))
return FALSE;
// Open its performance data
// =========================
HKEY hPerformance;
if(RegOpenKeyExW(hService, L"Performance", 0, KEY_READ, &hPerformance))
{
// No performance subkey --- not our service
// =========================================
RegCloseKey(hService);
return FALSE;
}
RegCloseKey(hService);
// Spawn an instance of the class
// ==============================
IWbemClassObject* pInst = NULL;
m_pClass->SpawnInstance(0, &pInst);
VARIANT v;
VariantInit(&v);
// Fill in the key
// ===============
BSTR strPropName = SysAllocString(SERVICE_CLASS_KEY);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(wszServiceName);
pInst->Put(strPropName, 0, &v, 0);
SysFreeString(strPropName);
VariantClear(&v);
// Get the library name
// ====================
WCHAR wszLibraryName[MAX_PATH];
DWORD dwValLen = MAX_PATH;
if(RegQueryValueExW(hPerformance, L"Library", NULL, NULL,
(LPBYTE)wszLibraryName, &dwValLen) == 0)
{
// Fill in the property
// ====================
strPropName = SysAllocString(L"Library");
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(wszLibraryName);
pInst->Put(strPropName, 0, &v, 0);
SysFreeString(strPropName);
VariantClear(&v);
}
// Get the FirstCounter index
// ==========================
dwValLen = sizeof(DWORD);
V_VT(&v) = VT_I4;
if(RegQueryValueExW(hPerformance, L"First Counter", NULL, NULL,
(LPBYTE)&V_I4(&v), &dwValLen) == 0)
{
// Fill in the property
// ====================
strPropName = SysAllocString(L"FirstCounter");
pInst->Put(strPropName, 0, &v, 0);
SysFreeString(strPropName);
}
// Get the LastCounter index
// ==========================
dwValLen = sizeof(DWORD);
V_VT(&v) = VT_I4;
if(RegQueryValueExW(hPerformance, L"Last Counter", NULL, NULL,
(LPBYTE)&V_I4(&v), &dwValLen) == 0)
{
// Fill in the property
// ====================
strPropName = SysAllocString(L"LastCounter");
pInst->Put(strPropName, 0, &v, 0);
SysFreeString(strPropName);
}
// Clean up
// ========
RegCloseKey(hPerformance);
*ppInst = pInst;
return TRUE;
}