windows-nt/Source/XPSP1/NT/base/wmi/cdmprov/cimmap.cpp
2020-09-26 16:20:57 +08:00

551 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: cimmap.cpp
//
//
// This file contains routines that will establish a mapping between
// Wdm class instances and Cdm class instances. See
// MapWdmClassToCimClass for more information.
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <wbemidl.h>
#include "wbemmisc.h"
#include "debug.h"
#include "cimmap.h"
HRESULT WdmInstanceNameToPnPId(
IWbemServices *pWdmServices,
BSTR WdmInstanceName,
VARIANT /* FREE */ *PnPId
)
/*+++
Routine Description:
This routine will convert a Wdm instance name into its
corresponding pnp id
Arguments:
pWdmServices is the pointer to the root\wmi namespace
WdmInstanceName
*PnPId returns with the pnp id
Return Value:
HRESULT
---*/
{
WCHAR Query[2 * MAX_PATH];
WCHAR s[MAX_PATH];
BSTR sQuery;
HRESULT hr;
IEnumWbemClassObject *pWdmEnumInstances;
IWbemClassObject *pWdmInstance;
ULONG Count;
BSTR sWQL;
WmipAssert(pWdmServices != NULL);
WmipAssert(WdmInstanceName != NULL);
WmipAssert(PnPId != NULL);
sWQL = SysAllocString(L"WQL");
if (sWQL != NULL)
{
//
// First get PnP id from Instance name from the MSWmi_PnPDeviceId
// class (select * from MSWMI_PnPDeviceId where InstanceName =
// "<WdmInstanceName>"
//
wsprintfW(Query,
L"select * from MSWmi_PnPDeviceId where InstanceName = \"%ws\"",
AddSlashesToStringW(s, WdmInstanceName));
sQuery = SysAllocString(Query);
if (sQuery != NULL)
{
hr = pWdmServices->ExecQuery(sWQL,
sQuery,
WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_ENSURE_LOCATABLE,
NULL,
&pWdmEnumInstances);
if (hr == WBEM_S_NO_ERROR)
{
hr = pWdmEnumInstances->Next(WBEM_INFINITE,
1,
&pWdmInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
hr = WmiGetProperty(pWdmInstance,
L"PnPDeviceId",
CIM_STRING,
PnPId);
pWdmInstance->Release();
}
pWdmEnumInstances->Release();
} else {
WmipDebugPrint(("CDMPROV: Query %ws failed %x\n",
sQuery, hr));
}
SysFreeString(sQuery);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
SysFreeString(sWQL);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT FindCimClassByWdmInstanceName(
IN IWbemServices *pWdmServices,
IN IWbemServices *pCimServices,
IN BSTR CimClassName,
IN BSTR WdmInstanceName,
OUT BSTR *PnPId,
OUT BSTR /* FREE */ *CimRelPath
)
/*+++
Routine Description:
This routine will find the Cim class instance that corresponds to a
particular Wdm class instance
Arguments:
pWdmServices is the pointer to the root\wmi namespace
pCdmServices is the pointer to the root\cimv2 namespace
CimClassName is the name of the cim class that the wdm instance
would map to
WdmInstanceName
*PnPId returns with the PnP id for the device stack
*CimRelPath returns with the relpath for the Cim instance
Return Value:
HRESULT
---*/
{
HRESULT hr;
VARIANT v;
IEnumWbemClassObject *pCimEnumInstances;
IWbemClassObject *pCimInstance;
ULONG Count;
BSTR sWQL;
WmipAssert(pWdmServices != NULL);
WmipAssert(pCimServices != NULL);
WmipAssert(CimClassName != NULL);
WmipAssert(WdmInstanceName != NULL);
WmipAssert(CimRelPath != NULL);
sWQL = SysAllocString(L"WQL");
if (sWQL != NULL)
{
// ****************************************************************
// Note: Net cards need to do something similar. We get the
// netcard address in class MSNDIS_???? and then get the CIM class
// by matching the netcard addresses.
// ****************************************************************
//
// First thing is to convert from an instance name to a pnpid
//
hr = WdmInstanceNameToPnPId(pWdmServices,
WdmInstanceName,
&v);
if (hr == WBEM_S_NO_ERROR)
{
//
// Next select * from CimClassName where PnPDeviceId = "<PnPDevice
// Id from above>".
//
WCHAR Query[2 * MAX_PATH];
WCHAR s[MAX_PATH];
BSTR sQuery;
wsprintfW(Query,
L"select * from %ws where PnPDeviceId = \"%ws\"",
CimClassName,
AddSlashesToStringW(s, v.bstrVal));
*PnPId = v.bstrVal;
sQuery = SysAllocString(Query);
if (sQuery != NULL)
{
hr = pCimServices->ExecQuery(sWQL,
sQuery,
WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_ENSURE_LOCATABLE,
NULL,
&pCimEnumInstances);
SysFreeString(sQuery);
if (hr == WBEM_S_NO_ERROR)
{
hr = pCimEnumInstances->Next(WBEM_INFINITE,
1,
&pCimInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
//
// Finally grab the relpath from cim class and we're done
//
hr = WmiGetProperty(pCimInstance,
L"__RELPATH",
CIM_STRING,
&v);
if (hr == WBEM_S_NO_ERROR)
{
*CimRelPath = SysAllocString(v.bstrVal);
if (*CimRelPath == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
VariantClear(&v);
}
pCimInstance->Release();
}
pCimEnumInstances->Release();
} else {
WmipDebugPrint(("CDMPROV: Query %ws failed %x\n",
Query, hr));
}
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
SysFreeString(sWQL);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
return(hr);
}
HRESULT GetEnumCount(
IN IEnumWbemClassObject *pEnumInstances,
OUT int *RelPathCount
)
/*+++
Routine Description:
This routine will return the count of instances in the enumeration
Arguments:
pEnumInstance is the instance enumerator
*RelPathCount returns the number of instances in the enumeration
Return Value:
HRESULT
---*/
{
ULONG Count;
HRESULT hr;
IWbemClassObject *pInstance;
WmipAssert(pEnumInstances != NULL);
WmipAssert(RelPathCount != NULL);
*RelPathCount = 0;
do
{
hr = pEnumInstances->Next(WBEM_INFINITE,
1,
&pInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1))
{
(*RelPathCount)++;
pInstance->Release();
} else {
if (hr == WBEM_S_FALSE)
{
hr = WBEM_S_NO_ERROR;
}
break;
}
} while (TRUE);
return(hr);
}
HRESULT MapWdmClassToCimClass(
IN IWbemServices *pWdmServices,
IN IWbemServices *pCimServices,
IN BSTR WdmClassName,
IN BSTR CimClassName,
OUT BSTR /* FREE */ **PnPDeviceIds,
OUT BSTR /* FREE */ **WdmInstanceNames,
OUT BSTR /* FREE */ **WdmRelPaths,
OUT BSTR /* FREE */ **CimRelPaths,
OUT int *RelPathCount
)
/*+++
Routine Description:
This routine will perform a mapping between the instances of WDM
classes and Cim Classes
Arguments:
pWdmServices
pCdmServices
WdmClassName
CimClassName
*PnPDeviceIds return with the an array of PnP device ids
*WdmInstanceNames returns with an array of Wdm instnace names
*WdmRelPaths returns with an array of relpaths to Wdm instances
*CimRelpaths returns with an array of relapaths to Cim instance
*RelPathCount returns with the count of instances that are mapped
Return Value:
HRESULT
---*/
{
IWbemClassObject *pWdmInstance;
IEnumWbemClassObject *pWdmEnumInstances;
HRESULT hr;
int i, NumberWdmInstances;
VARIANT v;
ULONG Count;
ULONG AllocSize;
WmipAssert(pWdmServices != NULL);
WmipAssert(pCimServices != NULL);
WmipAssert(WdmClassName != NULL);
WmipAssert(CimClassName != NULL);
WmipAssert(PnPDeviceIds != NULL);
WmipAssert(WdmInstanceNames != NULL);
WmipAssert(CimRelPaths != NULL);
WmipAssert(RelPathCount != NULL);
WmipDebugPrint(("CDMPROV: Mapping Wdm %ws to CIM %ws\n",
WdmClassName,
CimClassName));
*PnPDeviceIds = NULL;
*WdmInstanceNames = NULL;
*WdmRelPaths = NULL;
*CimRelPaths = NULL;
//
// Get all instances of the Wdm Class
//
hr = pWdmServices->CreateInstanceEnum(WdmClassName,
WBEM_FLAG_USE_AMENDED_QUALIFIERS |
WBEM_FLAG_SHALLOW,
NULL,
&pWdmEnumInstances);
if (hr == WBEM_S_NO_ERROR)
{
hr = GetEnumCount(pWdmEnumInstances,
RelPathCount);
NumberWdmInstances = *RelPathCount;
if (hr == WBEM_S_NO_ERROR)
{
AllocSize = NumberWdmInstances * sizeof(BSTR *);
*WdmRelPaths = (BSTR *)WmipAlloc(AllocSize);
*CimRelPaths = (BSTR *)WmipAlloc(AllocSize);
*WdmInstanceNames = (BSTR *)WmipAlloc(AllocSize);
*PnPDeviceIds = (BSTR *)WmipAlloc(AllocSize);
if ((*WdmRelPaths != NULL) &&
(*CimRelPaths != NULL) &&
(*WdmInstanceNames != NULL) &&
(*PnPDeviceIds != NULL))
{
memset(*WdmRelPaths, 0, AllocSize);
memset(*CimRelPaths, 0, AllocSize);
memset(*WdmInstanceNames, 0, AllocSize);
memset(*PnPDeviceIds, 0, AllocSize);
pWdmEnumInstances->Reset();
i = 0;
do
{
hr = pWdmEnumInstances->Next(WBEM_INFINITE,
1,
&pWdmInstance,
&Count);
if ((hr == WBEM_S_NO_ERROR) &&
(Count == 1) &&
(i < NumberWdmInstances))
{
//
// Lets get the instance name and then lookup the pnp
// id for it
//
hr = WmiGetProperty(pWdmInstance,
L"InstanceName",
CIM_STRING,
&v);
if (hr == WBEM_S_NO_ERROR)
{
//
// Remember wdm instnace name
//
WmipDebugPrint(("CDMPROV: Wdm InstanceName is %ws\n",
v.bstrVal));
(*WdmInstanceNames)[i] = v.bstrVal;
hr = FindCimClassByWdmInstanceName(pWdmServices,
pCimServices,
CimClassName,
v.bstrVal,
&((*PnPDeviceIds)[i]),
&((*CimRelPaths)[i]));
if (hr == WBEM_S_NO_ERROR)
{
//
// Remember Wdm class relative path
//
WmipDebugPrint(("CDMPROV: Found CimRelPath %ws for Wdm class %ws\n",
((*CimRelPaths)[i]), WdmClassName));
hr = WmiGetProperty(pWdmInstance,
L"__RELPATH",
CIM_STRING,
&v);
if (hr == WBEM_S_NO_ERROR)
{
(*WdmRelPaths)[i] = SysAllocString(v.bstrVal);
if ((*WdmRelPaths)[i] == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
VariantClear(&v);
i++;
}
} else {
//
// We did not find a CIM class
// to match our Wdm instance
// names, so we decrement our
// relpath count and continue
// searching
(*RelPathCount)--;
if (*RelPathCount == 0)
{
hr = WBEM_E_NOT_FOUND;
} else {
hr = WBEM_S_NO_ERROR;
}
}
}
pWdmInstance->Release();
} else {
if (hr == WBEM_S_FALSE)
{
hr = WBEM_S_NO_ERROR;
}
break;
}
} while (hr == WBEM_S_NO_ERROR);
} else {
hr = WBEM_E_OUT_OF_MEMORY;
}
}
pWdmEnumInstances->Release();
}
//
// If mapping was unsuccessful then be sure to clean up any
// allocated instance names and relpaths
//
if (hr != WBEM_S_NO_ERROR)
{
if (*PnPDeviceIds != NULL)
{
FreeTheBSTRArray(*WdmRelPaths,
NumberWdmInstances);
*WdmRelPaths = NULL;
}
if (*WdmRelPaths != NULL)
{
FreeTheBSTRArray(*WdmRelPaths,
NumberWdmInstances);
*WdmRelPaths = NULL;
}
if (*CimRelPaths != NULL)
{
FreeTheBSTRArray(*CimRelPaths,
NumberWdmInstances);
*CimRelPaths = NULL;
}
if (*WdmInstanceNames != NULL)
{
FreeTheBSTRArray(*WdmInstanceNames,
NumberWdmInstances);
*WdmInstanceNames = NULL;
}
}
return(hr);
}