windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/repdrvr/sqlutils.cpp
2020-09-26 16:20:57 +08:00

506 lines
20 KiB
C++

//***************************************************************************
//
// (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
//
// sqlcache.cpp
//
// cvadai 6-May-1999 created.
//
//***************************************************************************
#define _SQLCACHE_CPP_
#pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#include "precomp.h"
#include <std.h>
#include <smrtptr.h>
#include <reputils.h>
#include <sqlutils.h>
#include <sqlcache.h>
#include <sqlit.h>
#include <repdrvr.h>
#include <wbemint.h>
#if defined _WIN64
#define ULONG unsigned __int64
#define LONG __int64
#endif
//***************************************************************************
//
// COLEDBConnection::COLEDBConnection
//
//***************************************************************************
COLEDBConnection::COLEDBConnection (IDBInitialize *pDBInit)
{
m_pDBInit = pDBInit;
m_tCreateTime = time(0);
m_bInUse = false;
m_pSession = NULL;
m_pCmd = NULL;
m_pTrans = NULL;
}
//***************************************************************************
//
// COLEDBConnection::~COLEDBConnection
//
//***************************************************************************
COLEDBConnection::~COLEDBConnection ()
{
if (m_pDBInit)
{
m_ObjMgr.Empty();
if (m_pTrans)
m_pTrans->Release();
if (m_pCmd) m_pCmd->Release();
if (m_pSession)
m_pSession->Release();
m_pDBInit->Uninitialize();
while (m_pDBInit->Release());
}
}
//***************************************************************************
//
// CSQLExecuteRepdrvr::GetNextResultRows
//
//***************************************************************************
HRESULT CSQLExecuteRepdrvr::GetNextResultRows(int iNumRows, IRowset *pIRowset, IMalloc *pMalloc, IWbemClassObject *pNewObj, CSchemaCache *pSchema
, CWmiDbSession *pSession, Properties &PropIds, bool *bImage, bool bOnImage)
{
HRESULT hr = WBEM_S_NO_ERROR;
ULONG nCols;
DBCOLUMNINFO* pColumnsInfo = NULL;
OLECHAR* pColumnStrings = NULL;
ULONG nCol;
ULONG cRowsObtained; // Count of rows
// obtained
HROW *rghRows = new HROW[iNumRows]; // Row handles
HROW* pRows = &rghRows[0]; // Pointer to the row
// handles
CDeleteMe <HROW> r2 (rghRows);
IAccessor* pIAccessor; // Pointer to the
// accessor
HACCESSOR hAccessor; // Accessor handle
DBBINDSTATUS* pDBBindStatus = NULL;
DBBINDING* pDBBindings = NULL;
BYTE* pRowValues = NULL;
LPWSTR lpColumnName;
// Get Column Info
IColumnsInfo* pIColumnsInfo;
pIRowset->QueryInterface(IID_IColumnsInfo, (void**) &pIColumnsInfo);
hr = pIColumnsInfo->GetColumnInfo(&nCols, &pColumnsInfo, &pColumnStrings);
CReleaseMe r1 (pIColumnsInfo);
if (nCols > 11 || nCols < 10)
return WBEM_E_INVALID_QUERY;
// Create the binding structures
ULONG cbRow = 0;
pDBBindings = new DBBINDING[nCols];
CDeleteMe <DBBINDING> d1(pDBBindings);
if (!pDBBindings || !rghRows)
return WBEM_E_OUT_OF_MEMORY;
for (nCol = 0; nCol < nCols; nCol++)
{
pDBBindings[nCol].iOrdinal = nCol+1;
pDBBindings[nCol].obValue = cbRow;
pDBBindings[nCol].obLength = 0;
pDBBindings[nCol].obStatus = 0;
pDBBindings[nCol].pTypeInfo = NULL;
pDBBindings[nCol].pObject = NULL;
pDBBindings[nCol].pBindExt = NULL;
pDBBindings[nCol].dwPart = DBPART_VALUE;
pDBBindings[nCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
if (nCol == 10)
{
pDBBindings[nCol].wType = DBTYPE_WSTR; // 64-bit ints must end up as strings.
pDBBindings[nCol].cbMaxLen = 50;
}
else
{
if (pDBBindings[nCol].wType == DBTYPE_WSTR ||
pDBBindings[nCol].wType == DBTYPE_STR ||
pDBBindings[nCol].wType == DBTYPE_BSTR)
pDBBindings[nCol].cbMaxLen = pColumnsInfo[nCol].ulColumnSize+1;
else
if (pColumnsInfo[nCol].ulColumnSize > 65535)
pDBBindings[nCol].cbMaxLen = 65535;
else
pDBBindings[nCol].cbMaxLen = pColumnsInfo[nCol].ulColumnSize;
}
pDBBindings[nCol].dwFlags = 0;
pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
lpColumnName = pColumnsInfo[nCol].pwszName;
cbRow += pDBBindings[nCol].cbMaxLen;
}
pRowValues = new BYTE[cbRow];
pDBBindStatus = new DBBINDSTATUS[nCols];
CDeleteMe <BYTE> r3 (pRowValues);
CDeleteMe <DBBINDSTATUS> r4 (pDBBindStatus);
if (!pRowValues || !pDBBindStatus)
return WBEM_E_OUT_OF_MEMORY;
pIRowset->QueryInterface(IID_IAccessor, (void**) &pIAccessor);
CReleaseMe r7 (pIAccessor);
pIAccessor->CreateAccessor(
DBACCESSOR_ROWDATA,// Accessor will be used to retrieve row
// data
nCols, // Number of columns being bound
pDBBindings, // Structure containing bind info
0,
&hAccessor, // Returned accessor handle
pDBBindStatus // Information about binding validity
);
// Get the next row.
hr = pIRowset->GetNextRows( 0, // Reserved
0, // cRowsToSkip
iNumRows, // cRowsDesired
&cRowsObtained, // cRowsObtained
&pRows ); // Filled in w/ row handles.
if (FAILED(hr))
{
// SetWMIOLEDBError(pIRowset);
}
else
{
if (cRowsObtained > 0)
{
for (int i = 0; i < cRowsObtained; i++)
{
pIRowset->GetData(rghRows[i], hAccessor, pRowValues);
DWORD dwPropertyId, dwStorage, dwPosition, dwCIMType, dwFlags, dwPropFlags;
_bstr_t sPropName;
SQL_ID dRefID = 0;
VARIANT vValue;
CClearMe c (&vValue);
wchar_t wTemp[455];
// We should have exactly 13 columns:
// (ObjectId, ClassId, PropertyId, ArrayPos, PropertyStringValue,
// PropertyNumericValue, PropertyRealValue, Flags, ClassId, ObjectPath,
// RefId, RefClassId, string binding of PropertyNumericValue
// ===================================================================
SQL_ID dOrigClassId = 0;
if (&pRowValues[pDBBindings[0].obValue] != NULL)
{
if (pDBBindings[1].wType == DBTYPE_NUMERIC)
{
DB_NUMERIC *pTemp = (DB_NUMERIC *)&pRowValues[pDBBindings[1].obValue];
dOrigClassId = CSQLExecute::GetInt64(pTemp);
}
else
dOrigClassId = *((long *)&pRowValues[pDBBindings[1].obValue]);;
}
dwPropertyId = *((long *)&pRowValues[pDBBindings[2].obValue]);
dwPosition = *((short *)&pRowValues[pDBBindings[3].obValue]);
dwFlags = *((short *)&pRowValues[pDBBindings[7].obValue]) == NULL ? 0 : *((short *)&pRowValues[pDBBindings[7].obValue]);
hr = pSchema->GetPropertyInfo (dwPropertyId, &sPropName, NULL, &dwStorage,
&dwCIMType, &dwPropFlags);
if (FAILED(hr))
break;
BYTE *pBuffer = NULL;
DWORD dwLen = 0;
switch (dwStorage)
{
case WMIDB_STORAGE_STRING:
if (bOnImage)
{
hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
SetVariant(CIM_STRING, &vValue, pBuffer, dwCIMType);
}
else
{
SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[4].obValue], dwCIMType);
int iLen = wcslen(vValue.bstrVal);
if (bImage)
*bImage = (IsTruncated(vValue.bstrVal) ? true : false);
}
break;
case WMIDB_STORAGE_NUMERIC:
if (dwCIMType == CIM_UINT64 || dwCIMType == CIM_SINT64)
SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[10].obValue], dwCIMType);
else
{
if (pDBBindings[5].wType == DBTYPE_NUMERIC)
SetVariant(DBTYPE_NUMERIC, &vValue, &pRowValues[pDBBindings[5].obValue], dwCIMType);
else
SetVariant(VT_I4, &vValue, &pRowValues[pDBBindings[5].obValue], dwCIMType);
}
break;
case WMIDB_STORAGE_REAL:
SetVariant(VT_R8, &vValue, &pRowValues[pDBBindings[6].obValue], dwCIMType);
break;
case WMIDB_STORAGE_REFERENCE: // Reference or object
if (bOnImage)
{
hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
if (dwCIMType == CIM_REFERENCE)
SetVariant(CIM_STRING, &vValue, pBuffer, dwCIMType);
}
else
SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[4].obValue], dwCIMType);
break;
case WMIDB_STORAGE_IMAGE: // Used different procedure.
hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
// Read the buffer, and attempt to set it as a safearray.
if (dwCIMType != CIM_OBJECT)
{
if (SUCCEEDED(hr) && dwLen > 0)
{
long why[1];
unsigned char t;
SAFEARRAYBOUND aBounds[1];
aBounds[0].cElements = dwLen; // This *should* be the max value!!!!
aBounds[0].lLbound = 0;
SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, aBounds);
vValue.vt = VT_I1;
for (int i2 = 0; i2 < dwLen; i2++)
{
why[0] = i2;
t = pBuffer[i2];
hr = SafeArrayPutElement(pArray, why, &t);
}
vValue.vt = VT_ARRAY|VT_UI1;
V_ARRAY(&vValue) = pArray;
CWin32DefaultArena::WbemMemFree(pBuffer);
dwCIMType |= CIM_FLAG_ARRAY;
}
else
vValue.vt = VT_NULL;
}
break;
default:
hr = WBEM_E_NOT_AVAILABLE;
break;
}
// Qualifier's property ID, if applicable.
if (dwPropFlags & REPDRVR_FLAG_QUALIFIER ||
dwPropFlags & REPDRVR_FLAG_IN_PARAM ||
dwPropFlags & REPDRVR_FLAG_OUT_PARAM)
{
if (pDBBindings[8].wType == DBTYPE_NUMERIC)
{
DB_NUMERIC *pTemp = (DB_NUMERIC *)&pRowValues[pDBBindings[8].obValue];
dRefID = CSQLExecute::GetInt64(pTemp);
}
else
dRefID = *((long *)&pRowValues[pDBBindings[8].obValue]);
}
// If this is an object (not a reference),
// then we need to Get the object and set it in
// the variant. Otherwise, the variant is simply
// the string path to the object.
// ===============================================
if (dwCIMType == CIM_OBJECT)
{
if (!bOnImage)
{
IWmiDbHandle *pHand = NULL;
hr = pSession->GetObject_Internal((LPWSTR)vValue.bstrVal, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHand);
CReleaseMe r4 (pHand);
if (SUCCEEDED(hr))
{
IWbemClassObject *pEmbed = NULL;
hr = pHand->QueryInterface(IID_IWbemClassObject, (void **)&pEmbed);
if (SUCCEEDED(hr))
{
VariantClear(&vValue);
V_UNKNOWN(&vValue) = (IUnknown *)pEmbed;
vValue.vt = VT_UNKNOWN;
// VariantClear will release this, right?
}
}
}
else
{
IWbemClassObject *pEmbedClass = NULL, *pEmbed = NULL;
_IWmiObject *pInt = NULL;
hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemClassObject, (void **)&pEmbedClass);
if (SUCCEEDED(hr))
{
VARIANT v;
VariantInit(&v);
CClearMe c (&v);
v.bstrVal = SysAllocString(L"Z");
v.vt = VT_BSTR;
pEmbedClass->Put(L"__Class", 0, &v, CIM_STRING);
hr = pEmbedClass->SpawnInstance(0, &pEmbed);
CReleaseMe r1 (pEmbedClass);
if (SUCCEEDED(hr))
{
hr = pEmbed->QueryInterface(IID__IWmiObject, (void **)&pInt);
CReleaseMe r (pInt);
if (SUCCEEDED(hr))
{
LPVOID pTaskMem = NULL;
if (SUCCEEDED(hr))
{
pTaskMem = CoTaskMemAlloc( dwLen );
if ( NULL != pTaskMem )
{
// Copy the memory
CopyMemory( pTaskMem, pBuffer, dwLen );
hr = pInt->SetObjectMemory(pTaskMem, dwLen);
if (SUCCEEDED(hr))
{
VariantClear(&vValue);
V_UNKNOWN(&vValue) = (IUnknown *)pEmbed;
vValue.vt = VT_UNKNOWN;
dwStorage = WMIDB_STORAGE_REFERENCE;
}
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
}
}
}
// For array properties, what we actually need to do is
// see if the property exists already. If not, we
// initialize the safe array and add the first element.
// If so, we simply set the value in the existing array.
// ======================================================
if (FAILED(hr))
break;
if (dwPropFlags & REPDRVR_FLAG_ARRAY && (dwStorage != WMIDB_STORAGE_IMAGE) )
{
dwCIMType |= CIM_FLAG_ARRAY;
VARIANT vTemp;
CClearMe c (&vTemp);
VariantCopy(&vTemp, &vValue);
long lTemp;
CIMTYPE cimtype;
VariantClear(&vValue);
if (SUCCEEDED(pNewObj->Get(sPropName, 0, &vValue, &cimtype, &lTemp)))
{
if (PropIds[dwPropertyId])
{
SAFEARRAY *pArray = V_ARRAY(&vValue);
hr = PutVariantInArray(&pArray, dwPosition, &vTemp);
}
else
{
if (vValue.vt != VT_NULL)
VariantClear(&vValue);
// This is a new object.
SAFEARRAYBOUND aBounds[1];
aBounds[0].cElements = dwPosition+1; // This *should* be the max value!!!!
aBounds[0].lLbound = 0;
SAFEARRAY* pArray = SafeArrayCreate(vTemp.vt, 1, aBounds);
hr = PutVariantInArray(&pArray, dwPosition, &vTemp);
vValue.vt = VT_ARRAY|vTemp.vt;
V_ARRAY(&vValue) = pArray;
PropIds[dwPropertyId] = true;
}
}
}
if (!(dwPropFlags & REPDRVR_FLAG_QUALIFIER) &&
!(dwPropFlags & REPDRVR_FLAG_IN_PARAM) &&
!(dwPropFlags & REPDRVR_FLAG_OUT_PARAM))
{
hr = pNewObj->Put(sPropName, 0, &vValue, dwCIMType);
}
// If this is a qualifier on a class, get the qualifier set and set the value.
else if (dwPropFlags & REPDRVR_FLAG_QUALIFIER )
{
if (dRefID != 0)
{
_bstr_t sProp2;
DWORD dwFlags2, dwRefID;
hr = pSchema->GetPropertyInfo (dRefID, &sProp2, NULL, NULL,
NULL, &dwFlags2, NULL, NULL, &dwRefID);
if (SUCCEEDED(hr))
{
IWbemQualifierSet *pQS = NULL;
hr = pNewObj->GetPropertyQualifierSet(sProp2, &pQS);
CReleaseMe r4 (pQS);
if (SUCCEEDED(hr))
pQS->Put(sPropName, &vValue, dwFlags);
}
}
else // Its just a class/instance qualifier. Set it.
{
IWbemQualifierSet *pQS = NULL;
hr = pNewObj->GetQualifierSet(&pQS);
CReleaseMe r5 (pQS);
if (SUCCEEDED(hr))
hr = pQS->Put(sPropName, &vValue, dwFlags);
}
}
}
}
else
hr = WBEM_S_NO_MORE_DATA;
}
pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL);
pIAccessor->ReleaseAccessor(hAccessor, NULL);
pMalloc->Free( pColumnsInfo );
pMalloc->Free( pColumnStrings );
if (hr == DB_S_ENDOFROWSET)
hr = WBEM_S_NO_MORE_DATA;
return hr;
}