//*************************************************************************** // // (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 #include #include #include #include #include #include #include #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 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 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 r3 (pRowValues); CDeleteMe 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; }