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.

1071 lines
36 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMI OLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // COMMAND.CPP - CCommand object implementation
  7. // File also contain the implementation of CQuery class
  8. //
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "command.h"
  12. #define NO_ROWCOUNT_TOTAL (-1)
  13. #define PARAM_LIST_SIZE 2056
  14. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. #pragma warning (disable:4355)
  17. CCommand::CCommand( CDBSession* pCDBSession, LPUNKNOWN pUnkOuter ) : CBaseObj(BOT_COMMAND,pUnkOuter)
  18. {
  19. //===============================================================
  20. // Initially, NULL all contained interfaces
  21. //===============================================================
  22. m_pIAccessor = NULL;
  23. m_pIColumnsInfo = NULL;
  24. m_pIConvertType = NULL;
  25. //=======================================================
  26. // Establish the parent object
  27. //=======================================================
  28. m_pCDBSession = pCDBSession;
  29. m_pCDBSession->GetOuterUnknown()->AddRef();
  30. //=======================================================
  31. // Initialize all ptrs to embedded interfaces
  32. //=======================================================
  33. m_pICommandText = NULL;
  34. m_pICommandWithParameters = NULL;
  35. m_pICommandProperties = NULL;
  36. m_pISupportErrorInfo = NULL;
  37. //=======================================================
  38. // Initialize simple member vars
  39. //=======================================================
  40. m_cRowsetsOpen = 0;
  41. m_guidImpersonate = GUID_NULL;
  42. // m_pdbc = pCDBSession->GetDBConnection();
  43. m_pQuery = NULL;
  44. m_pColumns = NULL;
  45. m_cTotalCols = 0;
  46. m_cCols = 0;
  47. m_cNestedCols = 0;
  48. }
  49. #pragma warning (default:4355)
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. //
  52. // Destructor for this class
  53. //
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  55. CCommand::~CCommand (void)
  56. {
  57. SAFE_DELETE_PTR( m_pUtilProps);
  58. SAFE_DELETE_PTR( m_pQuery );
  59. //====================================================================
  60. // Free Statement
  61. //====================================================================
  62. if (m_pQuery)
  63. {
  64. m_pQuery->InitQuery();
  65. }
  66. //=======================================================
  67. // Delete the embedded pointers
  68. //=======================================================
  69. SAFE_DELETE_PTR( m_pICommandText );
  70. SAFE_DELETE_PTR( m_pICommandWithParameters );
  71. SAFE_DELETE_PTR( m_pICommandProperties );
  72. SAFE_DELETE_PTR(m_pIAccessor);
  73. SAFE_DELETE_PTR(m_pIConvertType);
  74. SAFE_DELETE_PTR(m_pISupportErrorInfo);
  75. SAFE_DELETE_PTR(m_pIColumnsInfo);
  76. SAFE_DELETE_PTR(m_pColumns);
  77. //====================================================================
  78. // Since Command Object is going away, we can decrement
  79. // our count on the session object.
  80. // Note that this typically deletes our hdbc, DataSource, Session.
  81. // (So do this last.)
  82. //====================================================================
  83. if (m_pCDBSession)
  84. {
  85. m_pCDBSession->GetOuterUnknown()->Release();
  86. }
  87. }
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. //
  90. // Initialize the command Object. This Init routine should be used by CreateCommand and also be called
  91. // as a secondary initialization routine for the other FInit on the command object.
  92. //
  93. // If this initialization routine fails, it is the callers responsibility to delete this object.
  94. // The destructor will then clean up any allocated resources
  95. //
  96. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  97. HRESULT CCommand::FInit( WORD wRowsetProps )
  98. {
  99. HRESULT hr = S_OK;
  100. //===============================================
  101. // Get the query class going
  102. //===============================================
  103. m_pQuery = new CQuery;
  104. //===============================================
  105. // Initialize rowset properties
  106. //===============================================
  107. m_pUtilProps = new CUtilProp;
  108. // NTRaid: 136443
  109. // 07/05/00
  110. if(m_pUtilProps == NULL)
  111. {
  112. hr = E_OUTOFMEMORY;
  113. }
  114. else
  115. if(SUCCEEDED(hr = m_pUtilProps->FInit(COMMANDPROP)))
  116. {
  117. //===============================================
  118. // Initialize ErrorData
  119. //===============================================
  120. if (FAILED(m_CError.FInit()))
  121. hr = (E_OUTOFMEMORY);
  122. else
  123. {
  124. m_pIAccessor = new CImpIAccessor(this,FALSE);
  125. if( m_pIAccessor ){
  126. hr = m_pIAccessor->FInit();
  127. }
  128. if(SUCCEEDED(hr))
  129. {
  130. m_pICommandText = new CImpICommandText(this);
  131. m_pICommandWithParameters = new CImpICommandWithParameters(this);
  132. m_pICommandProperties = new CImpICommandProperties(this);
  133. m_pIConvertType = new CImpIConvertType(this);
  134. m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
  135. m_pIColumnsInfo = new CImpIColumnsInfoCmd(this);
  136. //===============================================
  137. // Initialize name pool
  138. //===============================================
  139. m_extNamePool.FInit(1,0,256);
  140. if( m_pUtilProps && m_pIAccessor && m_pICommandText && m_pICommandWithParameters &&
  141. m_pIConvertType && m_pIColumnsInfo && m_pISupportErrorInfo)
  142. {
  143. hr = S_OK;
  144. }
  145. else
  146. {
  147. hr = E_OUTOFMEMORY;
  148. }
  149. }
  150. }
  151. }
  152. if(SUCCEEDED(hr))
  153. {
  154. hr = AddInterfacesForISupportErrorInfo();
  155. }
  156. return hr;
  157. }
  158. /////////////////////////////////////////////////////////////////////////////////////////////////////
  159. // Function to add interfaces to ISupportErrorInfo interface
  160. /////////////////////////////////////////////////////////////////////////////////////////////////////
  161. HRESULT CCommand::AddInterfacesForISupportErrorInfo()
  162. {
  163. HRESULT hr = S_OK;
  164. if(SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IAccessor)) &&
  165. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommand)) &&
  166. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandText)) &&
  167. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandProperties)) &&
  168. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_ICommandWithParameters)) &&
  169. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IColumnsInfo)))
  170. {
  171. hr = m_pISupportErrorInfo->AddInterfaceID(IID_IConvertType);
  172. }
  173. return hr;
  174. }
  175. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. //
  177. // Determines if command is canceled and if not sets the currently active CQuery.
  178. //
  179. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. inline HRESULT CCommand::CheckCanceledHelper(CQuery* pstmt)
  181. {
  182. HRESULT hr;
  183. DWORD dwCancelStatus = m_pQuery->GetCancelStatus();
  184. // Set the currently active CQuery, for use by the cancel routine
  185. m_pQuery->m_pcsQuery->Enter();
  186. if (dwCancelStatus & CMD_EXEC_CANCELED){
  187. dwCancelStatus &= ~(CMD_EXEC_CANCELED|CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
  188. hr = DB_E_CANCELED;
  189. }
  190. else{
  191. hr = S_OK;
  192. }
  193. m_pQuery->m_pcsQuery->Leave();
  194. return hr;
  195. }
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. //
  198. // Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
  199. // the called object supports.
  200. //
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. STDMETHODIMP CCommand::QueryInterface( REFIID riid, LPVOID * ppv )
  203. {
  204. HRESULT hr = S_OK;
  205. if ( ppv == NULL )
  206. {
  207. hr = E_INVALIDARG;
  208. }
  209. else
  210. {
  211. //=======================================================
  212. // This is the non-delegating IUnknown implementation
  213. //=======================================================
  214. if ( riid == IID_IUnknown )
  215. *ppv = (LPVOID)this;
  216. else if ( riid == IID_IAccessor )
  217. *ppv = (LPVOID)m_pIAccessor;
  218. else if ( riid == IID_ICommand || riid == IID_ICommandText)
  219. *ppv = (LPVOID)m_pICommandText;
  220. else if ( riid == IID_ICommandProperties )
  221. *ppv = (LPVOID)m_pICommandProperties;
  222. else if ( riid == IID_IColumnsInfo )
  223. *ppv = (LPVOID)m_pIColumnsInfo;
  224. else if ( riid == IID_ICommandWithParameters )
  225. *ppv = (LPVOID)m_pICommandWithParameters;
  226. else if ( riid == IID_ISupportErrorInfo )
  227. *ppv = (LPVOID)m_pISupportErrorInfo;
  228. else if ( riid == IID_IConvertType )
  229. *ppv = (LPVOID)m_pIConvertType;
  230. else{
  231. *ppv = NULL;
  232. hr = E_NOINTERFACE;
  233. }
  234. if( *ppv ){
  235. ((LPUNKNOWN)*ppv)->AddRef();
  236. }
  237. }
  238. return hr;
  239. }
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. //
  242. // Increments a persistence count for the object
  243. //
  244. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. STDMETHODIMP_(ULONG) CCommand::AddRef (void)
  246. {
  247. ULONG cRef = InterlockedIncrement( (long*) &m_cRef);
  248. return cRef;
  249. }
  250. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  251. //
  252. // Decrements a persistence count for the object and if persistence count is 0, the object destroys itself.
  253. //
  254. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. STDMETHODIMP_(ULONG) CCommand::Release (void)
  256. {
  257. ULONG cRef = InterlockedDecrement( (long *) &m_cRef);
  258. if ( !cRef ){
  259. delete this;
  260. return 0;
  261. }
  262. return cRef;
  263. }
  264. //////////////////////////////////////////////////////////////////////////////
  265. //////////////////////////////////////////////////////////////////////////////
  266. // UTILITY FUNCTIONS UTILITY FUNCTIONS
  267. //////////////////////////////////////////////////////////////////////////////
  268. //////////////////////////////////////////////////////////////////////////////
  269. ////////////////////////////////////////////////////////////////////////////////////////////////
  270. //
  271. // Errors that can occur may result in another HRESULT other than E_FAIL, thus this routine
  272. // determines that HRESULT and posts the errors
  273. //
  274. ////////////////////////////////////////////////////////////////////////////////////////////////
  275. HRESULT CCommand::PostExecuteWarnings( CErrorData* pError, const IID* piid )
  276. {
  277. HRESULT hr = S_OK;
  278. if (*piid == IID_ITableDefinition){
  279. }
  280. if (*piid == IID_IIndexDefinition){
  281. }
  282. //==========================================================
  283. // If we are not posting errors for IID_IOpenRowset
  284. //==========================================================
  285. if (*piid == IID_IOpenRowset){
  286. //======================================================
  287. // Map errors in command to DB_E_NOTABLE.
  288. // Other errors should flow through. (Some like
  289. // _DATAOVERFLOW we should never get.)
  290. //======================================================
  291. if (hr == DB_E_ERRORSINCOMMAND)
  292. {
  293. hr = (DB_E_NOTABLE);
  294. }
  295. else if (hr == DB_E_ABORTLIMITREACHED || hr == DB_E_CANCELED)
  296. {
  297. hr = (E_FAIL);
  298. }
  299. }
  300. g_pCError->PostWMIErrors(hr, piid, pError);
  301. return hr;
  302. }
  303. ////////////////////////////////////////////////////////////////////////////////////////////////
  304. //
  305. // Errors that can occur may result in another HRESULT other than E_FAIL, thus this routine
  306. // determines that HRESULT and posts the errors
  307. //
  308. ////////////////////////////////////////////////////////////////////////////////////////////////
  309. HRESULT CCommand::PostExecuteErrors( CErrorData* pError, const IID* piid )
  310. {
  311. HRESULT hr = S_OK;
  312. if (*piid == IID_ITableDefinition){
  313. }
  314. if (*piid == IID_IIndexDefinition){
  315. }
  316. //==========================================================
  317. // If we are not posting errors for IID_IOpenRowset
  318. //==========================================================
  319. if (*piid == IID_IOpenRowset){
  320. //======================================================
  321. // Map errors in command to DB_E_NOTABLE.
  322. // Other errors should flow through. (Some like
  323. // _DATAOVERFLOW we should never get.)
  324. //======================================================
  325. if (hr == DB_E_ERRORSINCOMMAND)
  326. {
  327. hr = (DB_E_NOTABLE);
  328. }
  329. else if (hr == DB_E_ABORTLIMITREACHED || hr == DB_E_CANCELED)
  330. {
  331. hr = (E_FAIL);
  332. }
  333. }
  334. g_pCError->PostWMIErrors(hr, piid, pError);
  335. return hr;
  336. }
  337. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  338. //
  339. // Marks command as unprepared, and may force this state.
  340. //
  341. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  342. STDMETHODIMP CCommand::UnprepareHelper( DWORD dwUnprepareType )
  343. {
  344. // Unprepare the statement - free it from WBEM
  345. // Free memory for the row metadata for the first rowset in the command.
  346. // m_extNamePool.Free();
  347. DWORD dwStatus = m_pQuery->GetStatus();
  348. dwStatus &= ~CMD_HAVE_COLUMNINFO;
  349. if (UNPREPARE_NEW_CMD == dwUnprepareType) // A new command is being set
  350. {
  351. // We need to remember that we have to rebuild our parameter info
  352. dwStatus &= ~(CMD_TEXT_PARSED
  353. | CMD_READY
  354. | CMD_PARAMS_USED
  355. | CMD_EXECUTED_ONCE );
  356. // Reset parameter information.
  357. if (m_pQuery->GetParamCount()){
  358. if (m_pQuery->m_prgbCallParams){
  359. delete [] m_pQuery->m_prgbCallParams;
  360. m_pQuery->m_prgbCallParams = NULL;
  361. }
  362. if (m_pQuery->m_prgProviderParamInfo){
  363. delete [] m_pQuery->m_prgProviderParamInfo;
  364. m_pQuery->m_prgProviderParamInfo = NULL;
  365. }
  366. //@devnote We do not delete the consumer parameter information.
  367. // The only reference in the OLE DB spec to removing the consumer
  368. // parameter info is via ICommandWithParameters::SetParameterInfo.
  369. }
  370. }
  371. else if (UNPREPARE_RESET_CMD == dwUnprepareType){
  372. dwStatus &= ~CMD_READY;
  373. }
  374. m_pQuery->InitStatus(dwStatus);
  375. return S_OK;
  376. }
  377. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  378. //
  379. // Determines if bookmarks are present.
  380. //
  381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. BOOL CCommand::FHaveBookmarks()
  383. {
  384. BOOL flag = FALSE;
  385. // flag = (m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_BOOKMARKS)
  386. // || m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_IRowsetLocate)
  387. // || m_pUtilProps.IsRequiredTrue(CUtilProp::eid_DBPROPSET_ROWSET, CUtilProp::eid_DBPROPVAL_CANHOLDROWS) );
  388. return flag;
  389. }
  390. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  391. //
  392. // Re-executes a command to reposition to reposition to the beginning of the rowset.
  393. //
  394. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  395. HRESULT CCommand::ReExecute( PCROWSET pCRowset,LONG* pcCursorRows, WORD* pcCols )
  396. {
  397. DWORD dwFlags = EXECUTE_RESTART;
  398. // return ExecuteHelper(&IID_IRowset, pCRowset->GetStmt(), &dwFlags, pCRowset->GetRowsetProps(), NULL, NULL, pcCursorRows, pcCols, NULL);
  399. return S_OK;
  400. }
  401. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  402. STDMETHODIMP CCommand::Execute( IUnknown* pUnkOuter, //@parm IN | Outer Unknown
  403. REFIID riid, //@parm IN | Interface ID of the interface being queried for.
  404. DBPARAMS* pParams, //@parm INOUT | Parameter Array
  405. DBROWCOUNT* pcRowsAffected, //@parm OUT | count of rows affected by command
  406. IUnknown** ppRowsets //@parm OUT | Pointer to interface that was instantiated
  407. )
  408. {
  409. HRESULT hr = S_OK;
  410. HRESULT hrProp = S_OK;
  411. DWORD dwFlags = 0;
  412. CRowset* pCRowset = NULL;
  413. DWORD dwStatus = 0;
  414. LPWSTR pwstrWQL = NULL;
  415. ULONG cwchWQL = 0;
  416. const IID* pIID = &IID_ICommand;
  417. CUtilProp* pRowsetProps = NULL;
  418. CUtlParam *pCUtlParam = NULL;
  419. LONG cCursorCount = 0;
  420. //==========================================================================
  421. // Initialize Return Buffers
  422. //==========================================================================
  423. if ( ppRowsets )
  424. {
  425. *ppRowsets = NULL;
  426. }
  427. if ( pcRowsAffected )
  428. {
  429. *pcRowsAffected = NO_ROWCOUNT_TOTAL;
  430. }
  431. //==========================================================================
  432. // If the IID asked for is IID_NULL, then we can expect that this is a
  433. // non-row returning statement
  434. //==========================================================================
  435. if (riid == IID_NULL)
  436. {
  437. dwFlags |= EXECUTE_NOROWSET;
  438. }
  439. //==========================================================================
  440. // Check to see if IID_IOpenRowset is calling Execute to open a rowset.
  441. //==========================================================================
  442. if (m_guidImpersonate != GUID_NULL)
  443. {
  444. pIID = &m_guidImpersonate;
  445. }
  446. //==========================================================================
  447. // Check Arguments - Only check on row returning statements
  448. //==========================================================================
  449. if (!(dwFlags & EXECUTE_NOROWSET) && (ppRowsets == NULL))
  450. {
  451. hr = E_INVALIDARG;
  452. // return g_pCError->PostHResult((E_INVALIDARG), pIID);
  453. }
  454. else
  455. //==========================================================================
  456. // At least 1 ParamSet and pData is null
  457. //==========================================================================
  458. if (pParams && (pParams->cParamSets > 0) && (NULL == pParams->pData))
  459. {
  460. hr = E_INVALIDARG;
  461. // return g_pCError->PostHResult((E_INVALIDARG), pIID);
  462. }
  463. else
  464. //==========================================================================
  465. // Check that a command has been set
  466. //==========================================================================
  467. if(!(m_pQuery->GetStatus() & CMD_TEXT_SET))
  468. {
  469. hr = DB_E_NOCOMMAND;
  470. // return g_pCError->PostHResult((DB_E_NOCOMMAND), pIID);
  471. }
  472. else
  473. //==========================================================================
  474. // The outer object must explicitly ask for IUnknown
  475. //==========================================================================
  476. if (pUnkOuter != NULL && riid != IID_IUnknown)
  477. {
  478. hr = DB_E_NOAGGREGATION;
  479. // return g_pCError->PostHResult((DB_E_NOAGGREGATION), pIID);
  480. }
  481. else
  482. {
  483. //==========================================================================
  484. // If there are parameters
  485. //==========================================================================
  486. if (pParams){
  487. //======================================================================
  488. // Build the bind information
  489. //======================================================================
  490. pCUtlParam = new CUtlParam;
  491. if (NULL == pCUtlParam){
  492. hr = E_OUTOFMEMORY;
  493. // hr = g_pCError->PostHResult((E_OUTOFMEMORY), pIID);
  494. }
  495. else
  496. {
  497. pCUtlParam->AddRef();
  498. hr = pCUtlParam->BuildBindInfo(this, pParams, pIID);
  499. /* if (SUCCEEDED(hr = pCUtlParam->BuildBindInfo(this, pParams, pIID)))
  500. {
  501. m_pQuery->SetType(METHOD_ROWSET);
  502. }
  503. */ }
  504. }
  505. if( SUCCEEDED(hr))
  506. {
  507. if (!(m_pQuery->GetStatus() & CMD_EXECUTED_ONCE)){
  508. //======================================================================
  509. // Set the parameter binding information for the statement
  510. //======================================================================
  511. if (pCUtlParam)
  512. {
  513. m_pQuery->SetBindInfo(pCUtlParam);
  514. }
  515. //======================================================================
  516. // If command not prepared, prepare it now
  517. //======================================================================
  518. m_pQuery->SetStatus(CMD_READY);
  519. }
  520. //==========================================================================
  521. // For Row Returning statements, we need to make a copy of the
  522. // command object's Property object to hand off to the Rowset Object
  523. //==========================================================================
  524. if ( !(dwFlags & EXECUTE_NOROWSET) ){
  525. pCRowset = new CRowset(pUnkOuter,m_pCDBSession);
  526. if (pCRowset == NULL){
  527. hr = E_OUTOFMEMORY;
  528. // hr = g_pCError->PostHResult((E_OUTOFMEMORY), pIID);
  529. }
  530. else
  531. {
  532. //=========================================================================
  533. // We need to take a reference count on the pCRowset Ptr so if a
  534. // called method calls Addref and then Release on this
  535. // pointer, we do not go back to zero and delete ourselve.
  536. //=========================================================================
  537. pCRowset->AddRef();
  538. /*
  539. //=========================================================================
  540. // AddRef Session Object
  541. //=========================================================================
  542. if (m_pCDBSession)
  543. m_pCDBSession->AddRef(); // AddRef is not required as the Rowset Constuctor
  544. // does the AddRef on the passed session
  545. */
  546. if (IID_ICommand == *pIID){
  547. //=====================================================================
  548. // AddRef ourself (as Parent)
  549. //=====================================================================
  550. // GetOuterUnknown()->AddRef();
  551. }
  552. else{
  553. //=====================================================================
  554. // AddRef Session Object (as Parent)
  555. //=====================================================================
  556. if (m_pCDBSession)
  557. {
  558. m_pCDBSession->GetOuterUnknown()->AddRef();
  559. }
  560. }
  561. //=========================================================================
  562. // AddRef ourself (as Command)
  563. //=========================================================================
  564. //AddRef();
  565. //=========================================================================
  566. // Do initialization.
  567. //=========================================================================
  568. ULONG cPropSets = 0;
  569. DBPROPSET* prgPropertySets = NULL;
  570. DBPROPIDSET rgPropIDSet[2];
  571. DBPROPID rgPropId[1];
  572. memset(rgPropIDSet,0,2 * sizeof(DBPROPIDSET));
  573. // Get the property DBPROP_WMIOLEDB_ISMETHOD
  574. rgPropId[0] = DBPROP_WMIOLEDB_ISMETHOD;
  575. rgPropIDSet[0].cPropertyIDs = 1;
  576. rgPropIDSet[0].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
  577. rgPropIDSet[0].rgPropertyIDs = rgPropId;
  578. // if this property is true then set the command type to METHOD
  579. if(SUCCEEDED(hr = m_pUtilProps->GetProperties(PROPSET_COMMAND,1,rgPropIDSet, &cPropSets,&prgPropertySets)))
  580. {
  581. if(prgPropertySets->rgProperties->vValue.boolVal == VARIANT_TRUE)
  582. {
  583. m_pQuery->SetType(METHOD_ROWSET);
  584. }
  585. else
  586. {
  587. m_pQuery->SetType(COMMAND_ROWSET);
  588. }
  589. }
  590. hr = S_OK;
  591. //==========================================================================
  592. // Free memory we allocated to by GetProperties
  593. //==========================================================================
  594. m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
  595. memset(rgPropIDSet,0,2 * sizeof(DBPROPIDSET));
  596. // NTRaid: 135246
  597. // Getting only the rowset properties
  598. rgPropIDSet[0].cPropertyIDs = 0;
  599. rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
  600. rgPropIDSet[0].rgPropertyIDs = NULL;
  601. rgPropIDSet[1].cPropertyIDs = 0;
  602. rgPropIDSet[1].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
  603. rgPropIDSet[1].rgPropertyIDs = NULL;
  604. //=========================================================================
  605. // Get the properties- get the rowset properties
  606. //=========================================================================
  607. hr = m_pUtilProps->GetProperties(PROPSET_ROWSET,2,rgPropIDSet, &cPropSets,&prgPropertySets);
  608. if( hr == S_OK ){
  609. hr = pCRowset->InitRowset(cPropSets, prgPropertySets,-1,m_pQuery , this );
  610. if ( FAILED(hr) ){
  611. g_pCError->PostHResult(hr, pIID);
  612. *ppRowsets = NULL;
  613. }
  614. }
  615. else{
  616. if ( FAILED(hr) ){
  617. g_pCError->PostHResult(hr, pIID);
  618. *ppRowsets = NULL;
  619. }
  620. }
  621. if (DB_S_ERRORSOCCURRED == hr){
  622. hrProp = DB_S_ERRORSOCCURRED;
  623. }
  624. //==========================================================================
  625. // Free memory we allocated to by GetProperties
  626. //==========================================================================
  627. m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
  628. //=========================================================================
  629. // We are guaranteed to have handed off the pRowsetProps value,
  630. // so set the NULL it flag
  631. //=========================================================================
  632. dwFlags |= EXECUTE_NULL_PROWSETPROPS;
  633. } // Else for failure of allocation of CRowset
  634. }
  635. else
  636. {
  637. // 07/12/2000
  638. // Modified after finding NTBug : 142348, debugging of which
  639. // revealed that nothing was being done if a query is to be
  640. // executed without requiring a resultant rowset
  641. // Just execute the query here, without worring about
  642. // building the resulting rowset
  643. hr = m_pCDBSession->ExecuteQuery(m_pQuery);
  644. }
  645. if (!FAILED(hr))
  646. {
  647. //=========================================================================
  648. // We are guarunteed to have handed off the pRowsetProps value, so set
  649. // the NULL it flag
  650. //=========================================================================
  651. dwFlags |= EXECUTE_NULL_PROWSETPROPS;
  652. // 07/12/2000
  653. // NTRaid : 142348
  654. // Query for the rowset only if any rowset is asked for
  655. if ( !(dwFlags & EXECUTE_NOROWSET) )
  656. {
  657. //=========================================================================
  658. // Get the requested interface
  659. //=========================================================================
  660. if ( FAILED(hr = pCRowset->QueryInterface( riid, (LPVOID*) ppRowsets)) ){
  661. // g_pCError->PostHResult(hr, pIID);
  662. }
  663. else{
  664. //=====================================================================
  665. // If IID_NULL was specified, it is assumed that you
  666. // are not getting a rowset set back, but just in case
  667. // we'll close the statement handle
  668. //=====================================================================
  669. }
  670. }
  671. } // If(!Failed(hr))
  672. } // if succeeded(hr) after BuildBindInfo()
  673. }
  674. if (pCRowset)
  675. {
  676. pCRowset->Release();
  677. }
  678. if (pCUtlParam)
  679. {
  680. pCUtlParam->Release();
  681. }
  682. hr = FAILED(hr) ? hr : hrProp;
  683. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,pIID);
  684. return hr;
  685. /*
  686. EXIT_EXECUTE:
  687. //=========================================================================
  688. // It is possible that we have gotten to this point and have handled off
  689. // our pRowsetProps pointer to the rowset, but have no NULL'd the
  690. // pointer. NULL it if flag is on.
  691. //=========================================================================
  692. if (dwFlags & EXECUTE_NULL_PROWSETPROPS)
  693. pRowsetProps = NULL;
  694. if (pCRowset)
  695. pCRowset->Release();
  696. if (pCUtlParam){
  697. pCUtlParam->Release();
  698. }
  699. delete pRowsetProps;
  700. return hr;*/
  701. }
  702. //////////////////////////////////////////////////////////////////////////////////////////////
  703. // Function to get the DBPROP_WMIOLEDB_QUERYLANGUAGE property
  704. // NTRaid 134165
  705. //////////////////////////////////////////////////////////////////////////////////////////////
  706. HRESULT CCommand::GetQueryLanguage(VARIANT &varProp)
  707. {
  708. HRESULT hr = S_OK;
  709. ULONG cPropertySets = 0;
  710. DBPROPSET* prgPropertySets = NULL;
  711. DBPROPIDSET rgPropertyIDSets[1];
  712. DBPROPID rgPropId[1];
  713. VariantClear(&varProp);
  714. //========================================================================
  715. // Get the value of the required rowset property
  716. //========================================================================
  717. rgPropertyIDSets[0].guidPropertySet = DBPROPSET_WMIOLEDB_ROWSET;
  718. rgPropertyIDSets[0].rgPropertyIDs = rgPropId;
  719. rgPropertyIDSets[0].cPropertyIDs = 1;
  720. rgPropId[0] = DBPROP_WMIOLEDB_QUERYLANGUAGE;
  721. if( S_OK == (hr = m_pUtilProps->GetProperties( PROPSET_COMMAND, 1, rgPropertyIDSets,&cPropertySets, &prgPropertySets )))
  722. VariantCopy(&varProp,&prgPropertySets->rgProperties->vValue);
  723. //==========================================================================
  724. // Free memory we allocated to by GetProperties
  725. //==========================================================================
  726. m_pUtilProps->m_PropMemMgr.FreeDBPROPSET( cPropertySets, prgPropertySets);
  727. return hr;
  728. }
  729. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  730. //***********************************************************************************************************
  731. //
  732. // Class CQuery
  733. //
  734. //***********************************************************************************************************
  735. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  736. CQuery::CQuery()
  737. {
  738. m_prgbCallParams = NULL;
  739. m_dwStatus = 0;
  740. m_dwCancelStatus = 0;
  741. m_prgProviderParamInfo = NULL;
  742. m_pwstrWMIText = NULL;
  743. m_pwstrQryLang = NULL;
  744. //===============================================
  745. // Init critical section
  746. //===============================================
  747. m_pcsQuery = new CCriticalSection(TRUE);
  748. m_uRsType = COMMAND_ROWSET; // By default, set it for commands, can reset it to methods when needed.
  749. m_pParamList = NULL;
  750. }
  751. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  752. CQuery::~CQuery()
  753. {
  754. DeleteConsumerParamInfo();
  755. SAFE_DELETE_ARRAY( m_prgProviderParamInfo );
  756. SAFE_DELETE_ARRAY( m_prgbCallParams );
  757. SAFE_DELETE_PTR( m_pcsQuery );
  758. SAFE_DELETE_ARRAY( m_pwstrWMIText );
  759. SAFE_DELETE_ARRAY( m_pwstrQryLang );
  760. }
  761. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  762. //
  763. // Deletes the consumer specified parameter information.
  764. //
  765. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  766. void CQuery::DeleteConsumerParamInfo(void)
  767. {
  768. ULONG iElem;
  769. if( m_pParamList ){
  770. ULONG cElem = GetParamCount();
  771. for (iElem = 0; iElem < cElem; iElem++) {
  772. PPARAMINFO pParamInfo;
  773. pParamInfo = (PPARAMINFO) m_pParamList->GetAt(iElem);
  774. delete pParamInfo;
  775. }
  776. SAFE_DELETE_PTR(m_pParamList);
  777. }
  778. }
  779. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  780. //
  781. // Deletes the consumer specified parameter information.
  782. //
  783. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  784. HRESULT CQuery::AddConsumerParamInfo(ULONG_PTR ulParams,PPARAMINFO pParamInfo)
  785. {
  786. HRESULT hr = E_FAIL;
  787. if( !m_pParamList ){
  788. m_pParamList = new CFlexArray(PARAM_LIST_SIZE,50);
  789. }
  790. if( m_pParamList ){
  791. if( ulParams < PARAM_LIST_SIZE ){
  792. m_pParamList->InsertAt((int)ulParams,pParamInfo);
  793. hr = S_OK;
  794. }
  795. else{
  796. // There is a bug here with CFlexArray, when you add to it, it messes up the ordinal position
  797. // need to work with the owners of CFlexArray to fix this
  798. }
  799. }
  800. return hr;
  801. }
  802. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  803. //
  804. // Gets the parameter information for a specific parameter.
  805. //
  806. //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  807. PPARAMINFO CQuery::GetParamInfo( ULONG iParams )
  808. {
  809. PPARAMINFO pParamInfo = NULL;
  810. ULONG uSize = GetParamCount();
  811. if( uSize > 0 ){
  812. if ( iParams <= uSize){
  813. pParamInfo = (PPARAMINFO)m_pParamList->GetAt(iParams);
  814. if (pParamInfo)
  815. return pParamInfo;
  816. }
  817. pParamInfo = m_prgProviderParamInfo ? m_prgProviderParamInfo + iParams : NULL;
  818. }
  819. return pParamInfo;
  820. }
  821. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  822. HRESULT CQuery::InitQuery(BSTR strQryLang)
  823. {
  824. HRESULT hr = S_OK;
  825. if( m_pwstrWMIText ){
  826. delete []m_pwstrWMIText;
  827. }
  828. m_pwstrWMIText = NULL;
  829. // NTRaid 135165
  830. hr = SetQueryLanguage(strQryLang);
  831. return hr;
  832. }
  833. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  834. HRESULT CQuery::GetQuery(WCHAR *& wcsQuery)
  835. {
  836. HRESULT hr = E_FAIL;
  837. //===============================================================================
  838. // Initialize output parameter
  839. //===============================================================================
  840. wcsQuery = NULL;
  841. //===============================================================================
  842. // Allocate memory for the string we're going to return to the caller
  843. //===============================================================================
  844. wcsQuery = (LPWSTR)g_pIMalloc->Alloc((wcslen(m_pwstrWMIText) + 1) * sizeof(WCHAR));
  845. if ( !wcsQuery ){
  846. hr = g_pCError->PostHResult((E_OUTOFMEMORY), &IID_ICommandText);
  847. hr = E_OUTOFMEMORY;
  848. }
  849. else{
  850. wcscpy(wcsQuery, m_pwstrWMIText);
  851. }
  852. return hr;
  853. }
  854. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  855. HRESULT CQuery::SetQuery(LPCOLESTR wcsQuery, GUID rguidDialect)
  856. {
  857. HRESULT hr = E_FAIL;
  858. ULONG cwch = wcslen(wcsQuery);
  859. LPWSTR pwstr = new WCHAR[cwch+2];
  860. if (pwstr){
  861. //=================================================================
  862. // Save the text and dialect
  863. //=================================================================
  864. m_cwchWMIText = cwch;
  865. m_pwstrWMIText = pwstr;
  866. wcscpy(pwstr, wcsQuery);
  867. m_guidCmdDialect = rguidDialect;
  868. //=================================================================
  869. // Set status flag that we have set text
  870. //=================================================================
  871. m_dwStatus = CMD_TEXT_SET;
  872. //=================================================================
  873. // Count the number of parameters
  874. //pcmd->m_cParams = pcmd->CountParamMarkers(pwstr, cwch);
  875. //=================================================================
  876. hr = S_OK;
  877. }
  878. else{
  879. hr = g_pCError->PostHResult((E_OUTOFMEMORY),&IID_ICommandText);
  880. }
  881. return hr;
  882. }
  883. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  884. HRESULT CQuery::SetDefaultQuery()
  885. {
  886. m_cwchWMIText = 0;
  887. InitQuery();
  888. m_guidCmdDialect = DBGUID_WQL;
  889. m_dwStatus &= ~CMD_TEXT_SET;
  890. return S_OK;
  891. }
  892. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  893. HRESULT CQuery::CancelQuery()
  894. {
  895. return E_FAIL;
  896. }
  897. DBTYPE CQuery::GetParamType(DBORDINAL lOrdinal)
  898. {
  899. PPARAMINFO param = NULL;
  900. param = (PPARAMINFO)m_pParamList->GetAt((int)lOrdinal);
  901. assert(param);
  902. return param->wOLEDBType;
  903. }
  904. ////////////////////////////////////////////////////////////////////////
  905. // set the query language
  906. // NTRaid 135165
  907. ////////////////////////////////////////////////////////////////////////
  908. HRESULT CQuery::SetQueryLanguage(BSTR strQryLang)
  909. {
  910. HRESULT hr = S_OK;
  911. if(strQryLang)
  912. {
  913. SAFE_DELETE_ARRAY( m_pwstrQryLang );
  914. m_pwstrQryLang = new WCHAR[(SysStringLen(strQryLang) + 1) * sizeof(WCHAR)];
  915. if(m_pwstrQryLang)
  916. {
  917. wcscpy(m_pwstrQryLang,strQryLang);
  918. }
  919. else
  920. {
  921. hr = E_OUTOFMEMORY;
  922. }
  923. }
  924. else
  925. if(m_pwstrQryLang == NULL)
  926. {
  927. m_pwstrQryLang = new WCHAR[wcslen(DEFAULTQUERYLANG) + 1];
  928. if(m_pwstrQryLang)
  929. {
  930. wcscpy(m_pwstrQryLang,DEFAULTQUERYLANG);
  931. }
  932. else
  933. {
  934. hr = E_OUTOFMEMORY;
  935. }
  936. }
  937. return hr;
  938. }