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.

355 lines
12 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // sqlit.cpp
  6. //
  7. // cvadai 19-Mar-99 Created as prototype for Quasar.
  8. //
  9. //***************************************************************************
  10. #define _SQLIT_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. #define DBINITCONSTANTS // Initialize OLE constants...
  14. #define INITGUID // ...once in each app.
  15. #define _WIN32_DCOM
  16. #include "precomp.h"
  17. #include <std.h>
  18. #include <sqlutils.h>
  19. #include <repdrvr.h>
  20. #include <sqlit.h>
  21. #include <wbemint.h>
  22. //***************************************************************************
  23. //
  24. // CWmiDbIterator::CWmiDbIterator
  25. //
  26. //***************************************************************************
  27. CWmiDbIterator::CWmiDbIterator()
  28. {
  29. m_pStatus = NULL;
  30. m_pRowset = NULL;
  31. m_pSession = NULL;
  32. m_pIMalloc = NULL;
  33. m_pConn = NULL;
  34. m_uRefCount = 0;
  35. }
  36. //***************************************************************************
  37. //
  38. // CWmiDbIterator::~CWmiDbIterator
  39. //
  40. //***************************************************************************
  41. CWmiDbIterator::~CWmiDbIterator()
  42. {
  43. Cancel(0);
  44. if (m_pSession)
  45. m_pSession->Release();
  46. if (m_pIMalloc)
  47. m_pIMalloc->Release();
  48. }
  49. //***************************************************************************
  50. //
  51. // CWmiDbIterator::QueryInterface
  52. //
  53. //***************************************************************************
  54. HRESULT STDMETHODCALLTYPE CWmiDbIterator::QueryInterface
  55. (REFIID riid,
  56. void __RPC_FAR *__RPC_FAR *ppvObject)
  57. {
  58. *ppvObject = 0;
  59. if (IID_IUnknown==riid || IID_IWmiDbIterator==riid )
  60. {
  61. *ppvObject = (IWmiDbIterator *)this;
  62. AddRef();
  63. return S_OK;
  64. }
  65. return E_NOINTERFACE;
  66. }
  67. //***************************************************************************
  68. //
  69. // CWmiDbIterator::AddRef
  70. //
  71. //***************************************************************************
  72. ULONG STDMETHODCALLTYPE CWmiDbIterator::AddRef()
  73. {
  74. InterlockedIncrement((LONG *) &m_uRefCount);
  75. return m_uRefCount;
  76. }
  77. //***************************************************************************
  78. //
  79. // CWmiDbIterator::Release
  80. //
  81. //***************************************************************************
  82. ULONG STDMETHODCALLTYPE CWmiDbIterator::Release()
  83. {
  84. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  85. if (0 != uNewCount)
  86. return uNewCount;
  87. delete this;
  88. return WBEM_S_NO_ERROR;
  89. }
  90. //***************************************************************************
  91. //
  92. // CWmiDbIterator::Cancel
  93. //
  94. //***************************************************************************
  95. HRESULT STDMETHODCALLTYPE CWmiDbIterator::Cancel(
  96. /* [in] */ DWORD dwFlags)
  97. {
  98. HRESULT hr = WBEM_S_NO_ERROR;
  99. hr = CSQLExecute::CancelQuery(m_pStatus);
  100. if (m_pStatus)
  101. m_pStatus->Release();
  102. m_pStatus = NULL;
  103. if (m_pConn)
  104. {
  105. ((CWmiDbController *)m_pSession->m_pController)->ConnCache.ReleaseConnection(m_pConn, hr);
  106. m_pConn = NULL;
  107. }
  108. if (m_pRowset)
  109. m_pRowset->Release();
  110. m_pRowset = NULL;
  111. return hr;
  112. }
  113. //***************************************************************************
  114. //
  115. // CWmiDbIterator::NextBatch
  116. //
  117. //***************************************************************************
  118. HRESULT STDMETHODCALLTYPE CWmiDbIterator::NextBatch(
  119. /* [in] */ DWORD dwNumRequested,
  120. /* [in] */ DWORD dwTimeOutSeconds,
  121. /* [in] */ DWORD dwFlags,
  122. /* [in] */ DWORD dwRequestedHandleType,
  123. /* [in] */ REFIID riid,
  124. /* [out] */ DWORD __RPC_FAR *pdwNumReturned,
  125. /* [iid_is][length_is][size_is][out] */ LPVOID __RPC_FAR *ppObjects)
  126. {
  127. HRESULT hr = WBEM_S_NO_ERROR, hrRet = WBEM_S_NO_ERROR;
  128. bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED);
  129. if (!m_pSession || !(m_pSession->m_pController) ||
  130. ((CWmiDbController *)m_pSession->m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  131. return WBEM_E_SHUTTING_DOWN;
  132. if (!dwNumRequested || !ppObjects)
  133. return WBEM_E_INVALID_PARAMETER;
  134. if (dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID &&
  135. riid == IID_IWmiDbHandle)
  136. return WBEM_E_INVALID_PARAMETER;
  137. // FIXME: We need to create a readahead cache.
  138. if (dwFlags & WMIDB_FLAG_LOOKAHEAD ||
  139. (riid != IID_IWmiDbHandle &&
  140. riid != IID_IWbemClassObject &&
  141. riid != IID__IWmiObject))
  142. /// UuidCompare(pIIDRequestedInterface, &IID_IWmiDbHandle, NULL) ||
  143. // UuidCompare(pIIDRequestedInterface, &IID_IWbemClassObject, NULL))
  144. return WBEM_E_NOT_SUPPORTED;
  145. if (pdwNumReturned)
  146. *pdwNumReturned = 0;
  147. if (!m_pStatus && !m_pRowset)
  148. return WBEM_S_NO_MORE_DATA;
  149. // For each ObjectId, do we instantiate a new handle,
  150. // and increment a background ref count on the object itself?
  151. // How do we keep track of the handles that are in use??
  152. try
  153. {
  154. HROW *pRow = NULL;
  155. VARIANT vTemp;
  156. VariantInit(&vTemp);
  157. int iNumRetrieved = 0;
  158. IRowset *pIRowset = NULL;
  159. if (m_pStatus)
  160. {
  161. hr = CSQLExecute::IsDataReady(m_pStatus);
  162. // TO DO: Wait if we are pending. Fail for now.
  163. if (SUCCEEDED(hr))
  164. {
  165. hr = m_pStatus->QueryInterface(IID_IRowset, (void **)&pIRowset);
  166. }
  167. }
  168. else
  169. pIRowset = m_pRowset;
  170. if (SUCCEEDED(hr) && pIRowset)
  171. {
  172. // TO DO: Take the timeout value into consideration!!!
  173. hr = CSQLExecute::GetColumnValue(pIRowset, 1, m_pIMalloc, &pRow, vTemp);
  174. while (SUCCEEDED(hr) && hr != WBEM_S_NO_MORE_DATA && iNumRetrieved < dwNumRequested)
  175. {
  176. if (!m_pSession || !(m_pSession->m_pController) ||
  177. ((CWmiDbController *)m_pSession->m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  178. {
  179. hrRet = WBEM_E_SHUTTING_DOWN;
  180. break;
  181. }
  182. // At this point, we need to check the cache
  183. // to make sure we don't already have one of these,
  184. // and that its not locked.
  185. SQL_ID dID = 0;
  186. if (vTemp.vt == VT_BSTR)
  187. dID = _wtoi64(vTemp.bstrVal);
  188. else if (vTemp.vt == VT_I4)
  189. dID = vTemp.lVal;
  190. SQL_ID dClassID = 0, dScopeID = 0;
  191. DWORD dwLockType = 0;
  192. VariantClear(&vTemp);
  193. hr = CSQLExecute::GetColumnValue(pIRowset, 2, m_pIMalloc, &pRow, vTemp);
  194. if (vTemp.vt == VT_BSTR)
  195. dClassID = _wtoi64(vTemp.bstrVal);
  196. else if (vTemp.vt == VT_I4)
  197. dClassID = vTemp.lVal;
  198. VariantClear(&vTemp);
  199. hr = CSQLExecute::GetColumnValue(pIRowset, 3, m_pIMalloc, &pRow, vTemp);
  200. if (vTemp.vt == VT_BSTR)
  201. dScopeID = _wtoi64(vTemp.bstrVal);
  202. else if (vTemp.vt == VT_I4)
  203. dScopeID = vTemp.lVal;
  204. VariantClear(&vTemp);
  205. //hr = ((CWmiDbSession *)m_pSession)->VerifyObjectSecurity(NULL, dID, dClassID, dScopeID, 0, WBEM_ENABLE);
  206. if (SUCCEEDED(hr))
  207. {
  208. CWmiDbHandle *pTemp = new CWmiDbHandle;
  209. if (pTemp)
  210. {
  211. DWORD dwVersion = 0;
  212. // Obtain a lock for this object
  213. // =============================
  214. pTemp->m_pSession = m_pSession;
  215. hr = ((CWmiDbController *)m_pSession->m_pController)->LockCache.AddLock(bImmediate, dID, dwRequestedHandleType, pTemp,
  216. dScopeID, dClassID, &((CWmiDbController *)m_pSession->m_pController)->SchemaCache, false,
  217. 0, 0, &dwVersion);
  218. if (FAILED(hr))
  219. {
  220. delete pTemp;
  221. // If they failed to get a handle, what do we do?
  222. // Ignore it and continue, I guess.
  223. hrRet = WBEM_S_PARTIAL_RESULTS;
  224. ppObjects[iNumRetrieved] = NULL;
  225. }
  226. else
  227. {
  228. ((CWmiDbController *)m_pSession->m_pController)->AddHandle();
  229. pTemp->AddRef();
  230. pTemp->m_dwVersion = dwVersion;
  231. pTemp->m_dwHandleType = dwRequestedHandleType;
  232. pTemp->m_dClassId = dClassID;
  233. pTemp->m_dObjectId = dID;
  234. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  235. pTemp->m_bSecDesc = TRUE;
  236. if (pTemp->m_dClassId == MAPPEDNSCLASSID)
  237. pTemp->m_bDefault = FALSE;
  238. pTemp->m_dScopeId = dScopeID;
  239. if (riid == IID_IWmiDbHandle)
  240. {
  241. ppObjects[iNumRetrieved] = pTemp;
  242. iNumRetrieved++;
  243. }
  244. else if (riid == IID_IWbemClassObject ||
  245. riid == IID__IWmiObject)
  246. {
  247. IWbemClassObject *pTemp2 = NULL;
  248. hr = pTemp->QueryInterface(IID_IWbemClassObject, (void **)&pTemp2);
  249. ppObjects[iNumRetrieved] = pTemp2;
  250. if (FAILED(hr))
  251. hrRet = WBEM_S_PARTIAL_RESULTS;
  252. else
  253. iNumRetrieved++;
  254. pTemp->Release();
  255. }
  256. }
  257. }
  258. else
  259. {
  260. // *pQueryResult = NULL; // What do we do here? Cancel, I assume.
  261. hrRet = WBEM_E_OUT_OF_MEMORY;
  262. break;
  263. }
  264. }
  265. else
  266. hrRet = WBEM_S_PARTIAL_RESULTS;
  267. if (m_pSession && ((CWmiDbSession *)m_pSession)->m_pController)
  268. ((CWmiDbController *)m_pSession->m_pController)->IncrementHitCount(false);
  269. VariantClear(&vTemp);
  270. hr = pIRowset->ReleaseRows(1, pRow, NULL, NULL, NULL);
  271. delete pRow;
  272. pRow = NULL;
  273. if (iNumRetrieved == dwNumRequested)
  274. break;
  275. hr = CSQLExecute::GetColumnValue(pIRowset, 1, m_pIMalloc, &pRow, vTemp);
  276. }
  277. }
  278. if (pdwNumReturned)
  279. *pdwNumReturned = iNumRetrieved;
  280. // Null out m_pStatus if there are no more results!!!
  281. if (hr == WBEM_S_NO_MORE_DATA)
  282. {
  283. hrRet = WBEM_S_NO_MORE_DATA;
  284. Cancel(0);
  285. }
  286. }
  287. catch (...)
  288. {
  289. hrRet = WBEM_E_CRITICAL_ERROR;
  290. }
  291. return hrRet;
  292. }