Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

505 lines
20 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // sqlcache.cpp
  6. //
  7. // cvadai 6-May-1999 created.
  8. //
  9. //***************************************************************************
  10. #define _SQLCACHE_CPP_
  11. #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
  12. #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
  13. #include "precomp.h"
  14. #include <std.h>
  15. #include <smrtptr.h>
  16. #include <reputils.h>
  17. #include <sqlutils.h>
  18. #include <sqlcache.h>
  19. #include <sqlit.h>
  20. #include <repdrvr.h>
  21. #include <wbemint.h>
  22. #if defined _WIN64
  23. #define ULONG unsigned __int64
  24. #define LONG __int64
  25. #endif
  26. //***************************************************************************
  27. //
  28. // COLEDBConnection::COLEDBConnection
  29. //
  30. //***************************************************************************
  31. COLEDBConnection::COLEDBConnection (IDBInitialize *pDBInit)
  32. {
  33. m_pDBInit = pDBInit;
  34. m_tCreateTime = time(0);
  35. m_bInUse = false;
  36. m_pSession = NULL;
  37. m_pCmd = NULL;
  38. m_pTrans = NULL;
  39. }
  40. //***************************************************************************
  41. //
  42. // COLEDBConnection::~COLEDBConnection
  43. //
  44. //***************************************************************************
  45. COLEDBConnection::~COLEDBConnection ()
  46. {
  47. if (m_pDBInit)
  48. {
  49. m_ObjMgr.Empty();
  50. if (m_pTrans)
  51. m_pTrans->Release();
  52. if (m_pCmd) m_pCmd->Release();
  53. if (m_pSession)
  54. m_pSession->Release();
  55. m_pDBInit->Uninitialize();
  56. while (m_pDBInit->Release());
  57. }
  58. }
  59. //***************************************************************************
  60. //
  61. // CSQLExecuteRepdrvr::GetNextResultRows
  62. //
  63. //***************************************************************************
  64. HRESULT CSQLExecuteRepdrvr::GetNextResultRows(int iNumRows, IRowset *pIRowset, IMalloc *pMalloc, IWbemClassObject *pNewObj, CSchemaCache *pSchema
  65. , CWmiDbSession *pSession, Properties &PropIds, bool *bImage, bool bOnImage)
  66. {
  67. HRESULT hr = WBEM_S_NO_ERROR;
  68. ULONG nCols;
  69. DBCOLUMNINFO* pColumnsInfo = NULL;
  70. OLECHAR* pColumnStrings = NULL;
  71. ULONG nCol;
  72. ULONG cRowsObtained; // Count of rows
  73. // obtained
  74. HROW *rghRows = new HROW[iNumRows]; // Row handles
  75. HROW* pRows = &rghRows[0]; // Pointer to the row
  76. // handles
  77. CDeleteMe <HROW> r2 (rghRows);
  78. IAccessor* pIAccessor; // Pointer to the
  79. // accessor
  80. HACCESSOR hAccessor; // Accessor handle
  81. DBBINDSTATUS* pDBBindStatus = NULL;
  82. DBBINDING* pDBBindings = NULL;
  83. BYTE* pRowValues = NULL;
  84. LPWSTR lpColumnName;
  85. // Get Column Info
  86. IColumnsInfo* pIColumnsInfo;
  87. pIRowset->QueryInterface(IID_IColumnsInfo, (void**) &pIColumnsInfo);
  88. hr = pIColumnsInfo->GetColumnInfo(&nCols, &pColumnsInfo, &pColumnStrings);
  89. CReleaseMe r1 (pIColumnsInfo);
  90. if (nCols > 11 || nCols < 10)
  91. return WBEM_E_INVALID_QUERY;
  92. // Create the binding structures
  93. ULONG cbRow = 0;
  94. pDBBindings = new DBBINDING[nCols];
  95. CDeleteMe <DBBINDING> d1(pDBBindings);
  96. if (!pDBBindings || !rghRows)
  97. return WBEM_E_OUT_OF_MEMORY;
  98. for (nCol = 0; nCol < nCols; nCol++)
  99. {
  100. pDBBindings[nCol].iOrdinal = nCol+1;
  101. pDBBindings[nCol].obValue = cbRow;
  102. pDBBindings[nCol].obLength = 0;
  103. pDBBindings[nCol].obStatus = 0;
  104. pDBBindings[nCol].pTypeInfo = NULL;
  105. pDBBindings[nCol].pObject = NULL;
  106. pDBBindings[nCol].pBindExt = NULL;
  107. pDBBindings[nCol].dwPart = DBPART_VALUE;
  108. pDBBindings[nCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
  109. pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
  110. pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
  111. if (nCol == 10)
  112. {
  113. pDBBindings[nCol].wType = DBTYPE_WSTR; // 64-bit ints must end up as strings.
  114. pDBBindings[nCol].cbMaxLen = 50;
  115. }
  116. else
  117. {
  118. if (pDBBindings[nCol].wType == DBTYPE_WSTR ||
  119. pDBBindings[nCol].wType == DBTYPE_STR ||
  120. pDBBindings[nCol].wType == DBTYPE_BSTR)
  121. pDBBindings[nCol].cbMaxLen = pColumnsInfo[nCol].ulColumnSize+1;
  122. else
  123. if (pColumnsInfo[nCol].ulColumnSize > 65535)
  124. pDBBindings[nCol].cbMaxLen = 65535;
  125. else
  126. pDBBindings[nCol].cbMaxLen = pColumnsInfo[nCol].ulColumnSize;
  127. }
  128. pDBBindings[nCol].dwFlags = 0;
  129. pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
  130. pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
  131. lpColumnName = pColumnsInfo[nCol].pwszName;
  132. cbRow += pDBBindings[nCol].cbMaxLen;
  133. }
  134. pRowValues = new BYTE[cbRow];
  135. pDBBindStatus = new DBBINDSTATUS[nCols];
  136. CDeleteMe <BYTE> r3 (pRowValues);
  137. CDeleteMe <DBBINDSTATUS> r4 (pDBBindStatus);
  138. if (!pRowValues || !pDBBindStatus)
  139. return WBEM_E_OUT_OF_MEMORY;
  140. pIRowset->QueryInterface(IID_IAccessor, (void**) &pIAccessor);
  141. CReleaseMe r7 (pIAccessor);
  142. pIAccessor->CreateAccessor(
  143. DBACCESSOR_ROWDATA,// Accessor will be used to retrieve row
  144. // data
  145. nCols, // Number of columns being bound
  146. pDBBindings, // Structure containing bind info
  147. 0,
  148. &hAccessor, // Returned accessor handle
  149. pDBBindStatus // Information about binding validity
  150. );
  151. // Get the next row.
  152. hr = pIRowset->GetNextRows( 0, // Reserved
  153. 0, // cRowsToSkip
  154. iNumRows, // cRowsDesired
  155. &cRowsObtained, // cRowsObtained
  156. &pRows ); // Filled in w/ row handles.
  157. if (FAILED(hr))
  158. {
  159. // SetWMIOLEDBError(pIRowset);
  160. }
  161. else
  162. {
  163. if (cRowsObtained > 0)
  164. {
  165. for (int i = 0; i < cRowsObtained; i++)
  166. {
  167. pIRowset->GetData(rghRows[i], hAccessor, pRowValues);
  168. DWORD dwPropertyId, dwStorage, dwPosition, dwCIMType, dwFlags, dwPropFlags;
  169. _bstr_t sPropName;
  170. SQL_ID dRefID = 0;
  171. VARIANT vValue;
  172. CClearMe c (&vValue);
  173. wchar_t wTemp[455];
  174. // We should have exactly 13 columns:
  175. // (ObjectId, ClassId, PropertyId, ArrayPos, PropertyStringValue,
  176. // PropertyNumericValue, PropertyRealValue, Flags, ClassId, ObjectPath,
  177. // RefId, RefClassId, string binding of PropertyNumericValue
  178. // ===================================================================
  179. SQL_ID dOrigClassId = 0;
  180. if (&pRowValues[pDBBindings[0].obValue] != NULL)
  181. {
  182. if (pDBBindings[1].wType == DBTYPE_NUMERIC)
  183. {
  184. DB_NUMERIC *pTemp = (DB_NUMERIC *)&pRowValues[pDBBindings[1].obValue];
  185. dOrigClassId = CSQLExecute::GetInt64(pTemp);
  186. }
  187. else
  188. dOrigClassId = *((long *)&pRowValues[pDBBindings[1].obValue]);;
  189. }
  190. dwPropertyId = *((long *)&pRowValues[pDBBindings[2].obValue]);
  191. dwPosition = *((short *)&pRowValues[pDBBindings[3].obValue]);
  192. dwFlags = *((short *)&pRowValues[pDBBindings[7].obValue]) == NULL ? 0 : *((short *)&pRowValues[pDBBindings[7].obValue]);
  193. hr = pSchema->GetPropertyInfo (dwPropertyId, &sPropName, NULL, &dwStorage,
  194. &dwCIMType, &dwPropFlags);
  195. if (FAILED(hr))
  196. break;
  197. BYTE *pBuffer = NULL;
  198. DWORD dwLen = 0;
  199. switch (dwStorage)
  200. {
  201. case WMIDB_STORAGE_STRING:
  202. if (bOnImage)
  203. {
  204. hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
  205. SetVariant(CIM_STRING, &vValue, pBuffer, dwCIMType);
  206. }
  207. else
  208. {
  209. SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[4].obValue], dwCIMType);
  210. int iLen = wcslen(vValue.bstrVal);
  211. if (bImage)
  212. *bImage = (IsTruncated(vValue.bstrVal) ? true : false);
  213. }
  214. break;
  215. case WMIDB_STORAGE_NUMERIC:
  216. if (dwCIMType == CIM_UINT64 || dwCIMType == CIM_SINT64)
  217. SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[10].obValue], dwCIMType);
  218. else
  219. {
  220. if (pDBBindings[5].wType == DBTYPE_NUMERIC)
  221. SetVariant(DBTYPE_NUMERIC, &vValue, &pRowValues[pDBBindings[5].obValue], dwCIMType);
  222. else
  223. SetVariant(VT_I4, &vValue, &pRowValues[pDBBindings[5].obValue], dwCIMType);
  224. }
  225. break;
  226. case WMIDB_STORAGE_REAL:
  227. SetVariant(VT_R8, &vValue, &pRowValues[pDBBindings[6].obValue], dwCIMType);
  228. break;
  229. case WMIDB_STORAGE_REFERENCE: // Reference or object
  230. if (bOnImage)
  231. {
  232. hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
  233. if (dwCIMType == CIM_REFERENCE)
  234. SetVariant(CIM_STRING, &vValue, pBuffer, dwCIMType);
  235. }
  236. else
  237. SetVariant(CIM_STRING, &vValue, &pRowValues[pDBBindings[4].obValue], dwCIMType);
  238. break;
  239. case WMIDB_STORAGE_IMAGE: // Used different procedure.
  240. hr = ReadImageValue(pIRowset, 5, &pRows, &pBuffer, dwLen);
  241. // Read the buffer, and attempt to set it as a safearray.
  242. if (dwCIMType != CIM_OBJECT)
  243. {
  244. if (SUCCEEDED(hr) && dwLen > 0)
  245. {
  246. long why[1];
  247. unsigned char t;
  248. SAFEARRAYBOUND aBounds[1];
  249. aBounds[0].cElements = dwLen; // This *should* be the max value!!!!
  250. aBounds[0].lLbound = 0;
  251. SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, aBounds);
  252. vValue.vt = VT_I1;
  253. for (int i2 = 0; i2 < dwLen; i2++)
  254. {
  255. why[0] = i2;
  256. t = pBuffer[i2];
  257. hr = SafeArrayPutElement(pArray, why, &t);
  258. }
  259. vValue.vt = VT_ARRAY|VT_UI1;
  260. V_ARRAY(&vValue) = pArray;
  261. CWin32DefaultArena::WbemMemFree(pBuffer);
  262. dwCIMType |= CIM_FLAG_ARRAY;
  263. }
  264. else
  265. vValue.vt = VT_NULL;
  266. }
  267. break;
  268. default:
  269. hr = WBEM_E_NOT_AVAILABLE;
  270. break;
  271. }
  272. // Qualifier's property ID, if applicable.
  273. if (dwPropFlags & REPDRVR_FLAG_QUALIFIER ||
  274. dwPropFlags & REPDRVR_FLAG_IN_PARAM ||
  275. dwPropFlags & REPDRVR_FLAG_OUT_PARAM)
  276. {
  277. if (pDBBindings[8].wType == DBTYPE_NUMERIC)
  278. {
  279. DB_NUMERIC *pTemp = (DB_NUMERIC *)&pRowValues[pDBBindings[8].obValue];
  280. dRefID = CSQLExecute::GetInt64(pTemp);
  281. }
  282. else
  283. dRefID = *((long *)&pRowValues[pDBBindings[8].obValue]);
  284. }
  285. // If this is an object (not a reference),
  286. // then we need to Get the object and set it in
  287. // the variant. Otherwise, the variant is simply
  288. // the string path to the object.
  289. // ===============================================
  290. if (dwCIMType == CIM_OBJECT)
  291. {
  292. if (!bOnImage)
  293. {
  294. IWmiDbHandle *pHand = NULL;
  295. hr = pSession->GetObject_Internal((LPWSTR)vValue.bstrVal, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHand);
  296. CReleaseMe r4 (pHand);
  297. if (SUCCEEDED(hr))
  298. {
  299. IWbemClassObject *pEmbed = NULL;
  300. hr = pHand->QueryInterface(IID_IWbemClassObject, (void **)&pEmbed);
  301. if (SUCCEEDED(hr))
  302. {
  303. VariantClear(&vValue);
  304. V_UNKNOWN(&vValue) = (IUnknown *)pEmbed;
  305. vValue.vt = VT_UNKNOWN;
  306. // VariantClear will release this, right?
  307. }
  308. }
  309. }
  310. else
  311. {
  312. IWbemClassObject *pEmbedClass = NULL, *pEmbed = NULL;
  313. _IWmiObject *pInt = NULL;
  314. hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER,
  315. IID_IWbemClassObject, (void **)&pEmbedClass);
  316. if (SUCCEEDED(hr))
  317. {
  318. VARIANT v;
  319. VariantInit(&v);
  320. CClearMe c (&v);
  321. v.bstrVal = SysAllocString(L"Z");
  322. v.vt = VT_BSTR;
  323. pEmbedClass->Put(L"__Class", 0, &v, CIM_STRING);
  324. hr = pEmbedClass->SpawnInstance(0, &pEmbed);
  325. CReleaseMe r1 (pEmbedClass);
  326. if (SUCCEEDED(hr))
  327. {
  328. hr = pEmbed->QueryInterface(IID__IWmiObject, (void **)&pInt);
  329. CReleaseMe r (pInt);
  330. if (SUCCEEDED(hr))
  331. {
  332. LPVOID pTaskMem = NULL;
  333. if (SUCCEEDED(hr))
  334. {
  335. pTaskMem = CoTaskMemAlloc( dwLen );
  336. if ( NULL != pTaskMem )
  337. {
  338. // Copy the memory
  339. CopyMemory( pTaskMem, pBuffer, dwLen );
  340. hr = pInt->SetObjectMemory(pTaskMem, dwLen);
  341. if (SUCCEEDED(hr))
  342. {
  343. VariantClear(&vValue);
  344. V_UNKNOWN(&vValue) = (IUnknown *)pEmbed;
  345. vValue.vt = VT_UNKNOWN;
  346. dwStorage = WMIDB_STORAGE_REFERENCE;
  347. }
  348. }
  349. else
  350. {
  351. hr = WBEM_E_OUT_OF_MEMORY;
  352. }
  353. }
  354. }
  355. }
  356. }
  357. }
  358. }
  359. // For array properties, what we actually need to do is
  360. // see if the property exists already. If not, we
  361. // initialize the safe array and add the first element.
  362. // If so, we simply set the value in the existing array.
  363. // ======================================================
  364. if (FAILED(hr))
  365. break;
  366. if (dwPropFlags & REPDRVR_FLAG_ARRAY && (dwStorage != WMIDB_STORAGE_IMAGE) )
  367. {
  368. dwCIMType |= CIM_FLAG_ARRAY;
  369. VARIANT vTemp;
  370. CClearMe c (&vTemp);
  371. VariantCopy(&vTemp, &vValue);
  372. long lTemp;
  373. CIMTYPE cimtype;
  374. VariantClear(&vValue);
  375. if (SUCCEEDED(pNewObj->Get(sPropName, 0, &vValue, &cimtype, &lTemp)))
  376. {
  377. if (PropIds[dwPropertyId])
  378. {
  379. SAFEARRAY *pArray = V_ARRAY(&vValue);
  380. hr = PutVariantInArray(&pArray, dwPosition, &vTemp);
  381. }
  382. else
  383. {
  384. if (vValue.vt != VT_NULL)
  385. VariantClear(&vValue);
  386. // This is a new object.
  387. SAFEARRAYBOUND aBounds[1];
  388. aBounds[0].cElements = dwPosition+1; // This *should* be the max value!!!!
  389. aBounds[0].lLbound = 0;
  390. SAFEARRAY* pArray = SafeArrayCreate(vTemp.vt, 1, aBounds);
  391. hr = PutVariantInArray(&pArray, dwPosition, &vTemp);
  392. vValue.vt = VT_ARRAY|vTemp.vt;
  393. V_ARRAY(&vValue) = pArray;
  394. PropIds[dwPropertyId] = true;
  395. }
  396. }
  397. }
  398. if (!(dwPropFlags & REPDRVR_FLAG_QUALIFIER) &&
  399. !(dwPropFlags & REPDRVR_FLAG_IN_PARAM) &&
  400. !(dwPropFlags & REPDRVR_FLAG_OUT_PARAM))
  401. {
  402. hr = pNewObj->Put(sPropName, 0, &vValue, dwCIMType);
  403. }
  404. // If this is a qualifier on a class, get the qualifier set and set the value.
  405. else if (dwPropFlags & REPDRVR_FLAG_QUALIFIER )
  406. {
  407. if (dRefID != 0)
  408. {
  409. _bstr_t sProp2;
  410. DWORD dwFlags2, dwRefID;
  411. hr = pSchema->GetPropertyInfo (dRefID, &sProp2, NULL, NULL,
  412. NULL, &dwFlags2, NULL, NULL, &dwRefID);
  413. if (SUCCEEDED(hr))
  414. {
  415. IWbemQualifierSet *pQS = NULL;
  416. hr = pNewObj->GetPropertyQualifierSet(sProp2, &pQS);
  417. CReleaseMe r4 (pQS);
  418. if (SUCCEEDED(hr))
  419. pQS->Put(sPropName, &vValue, dwFlags);
  420. }
  421. }
  422. else // Its just a class/instance qualifier. Set it.
  423. {
  424. IWbemQualifierSet *pQS = NULL;
  425. hr = pNewObj->GetQualifierSet(&pQS);
  426. CReleaseMe r5 (pQS);
  427. if (SUCCEEDED(hr))
  428. hr = pQS->Put(sPropName, &vValue, dwFlags);
  429. }
  430. }
  431. }
  432. }
  433. else
  434. hr = WBEM_S_NO_MORE_DATA;
  435. }
  436. pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL);
  437. pIAccessor->ReleaseAccessor(hAccessor, NULL);
  438. pMalloc->Free( pColumnsInfo );
  439. pMalloc->Free( pColumnStrings );
  440. if (hr == DB_S_ENDOFROWSET)
  441. hr = WBEM_S_NO_MORE_DATA;
  442. return hr;
  443. }