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.

866 lines
30 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Microsoft WMI OLE DB Provider
  3. //
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // Module : CMDTEXT.CPP - ICommandText interface implementation
  7. // Also has implementation of CUtlParam class
  8. //
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "command.h"
  12. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  13. STDMETHODIMP_(ULONG) CImpICommandText::AddRef(void)
  14. {
  15. DEBUGCODE(InterlockedIncrement( (long*) &m_cRef));
  16. return m_pcmd->GetOuterUnknown()->AddRef();
  17. }
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. STDMETHODIMP_(ULONG) CImpICommandText::Release(void)
  20. {
  21. DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef));
  22. DEBUGCODE(if( lRef < 0 ){
  23. ASSERT("Reference count on Object went below 0!")
  24. })
  25. return m_pcmd->GetOuterUnknown()->Release();
  26. }
  27. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  28. STDMETHODIMP CImpICommandText::QueryInterface( REFIID riid, LPVOID * ppv )
  29. {
  30. return m_pcmd->GetOuterUnknown()->QueryInterface(riid, ppv);
  31. }
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  33. //
  34. // Echos the current command as text, including all post-processing operations added.
  35. //
  36. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. STDMETHODIMP CImpICommandText::GetCommandText( GUID* pguidDialect, LPOLESTR* ppwszCommand )
  38. {
  39. HRESULT hr = S_OK;
  40. CSetStructuredExceptionHandler seh;
  41. TRY_BLOCK;
  42. //===============================================================================
  43. // At the creation of the CAutoBlock object a critical section
  44. // is entered. This is because the method manipulates shared structures
  45. // access to which must be serialized . The critical
  46. // section is left when this method terminate and the destructor
  47. // for CAutoBlock is called.
  48. //===============================================================================
  49. CAutoBlock cab( m_pcmd->GetCriticalSection() );
  50. //===============================================================================
  51. // Clear previous Error Object for this thread
  52. //===============================================================================
  53. g_pCError->ClearErrorInfo();
  54. //===============================================================================
  55. // Check Function Arguments
  56. //===============================================================================
  57. if ( ppwszCommand == NULL ){
  58. hr = E_INVALIDARG;
  59. }
  60. else
  61. //===============================================================================
  62. // If the command has not been set, make sure the buffer
  63. // contains an empty stringt to return to the consumer
  64. //===============================================================================
  65. if(!(m_pcmd->m_pQuery->GetStatus() & CMD_TEXT_SET)){
  66. hr = DB_E_NOCOMMAND;
  67. }
  68. else
  69. {
  70. //===============================================================================
  71. // Copy our saved text into the newly allocated string
  72. //===============================================================================
  73. m_pcmd->m_pQuery->GetQuery(*ppwszCommand);
  74. //===============================================================================
  75. // If the text we're giving back is a different dialect than was
  76. // requested, let the caller know what dialect the text is in
  77. //===============================================================================
  78. if (pguidDialect && *pguidDialect != DBGUID_DEFAULT && *pguidDialect!= DBGUID_WQL &&
  79. *pguidDialect != DBGUID_LDAP && *pguidDialect != GUID_NULL && *pguidDialect != DBGUID_WMI_METHOD
  80. && *pguidDialect != DBGUID_LDAPSQL){
  81. hr = DB_S_DIALECTIGNORED;
  82. }
  83. }
  84. if ( FAILED(hr) ){
  85. if ( pguidDialect )
  86. {
  87. memset(pguidDialect, 0, sizeof(GUID));
  88. }
  89. }
  90. else
  91. {
  92. if(pguidDialect)
  93. {
  94. GUID guidTemp = m_pcmd->m_pQuery->GetDialectGuid();
  95. memcpy(pguidDialect, &guidTemp,sizeof(GUID));
  96. }
  97. }
  98. hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
  99. CATCH_BLOCK_HRESULT(hr,L"ICommandText::GetCommandText");
  100. return hr;
  101. }
  102. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  103. //
  104. // Sets the current command text
  105. //
  106. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. STDMETHODIMP CImpICommandText::SetCommandText( REFGUID rguidDialect, LPCOLESTR pwszCommand )
  108. {
  109. HRESULT hr = S_OK;
  110. VARIANT varQryLang;
  111. VariantInit(&varQryLang);
  112. CSetStructuredExceptionHandler seh;
  113. TRY_BLOCK;
  114. //=========================================================================
  115. // At the creation of the CAutoBlock object a critical section
  116. // is entered. This is because the method manipulates shared structures
  117. // access to which must be serialized . The critical
  118. // section is left when this method terminate and the destructor
  119. // for CAutoBlock is called.
  120. //=========================================================================
  121. CAutoBlock cab( m_pcmd->GetCriticalSection() );
  122. //=========================================================================
  123. // Clear previous Error Object for this thread
  124. //=========================================================================
  125. g_pCError->ClearErrorInfo();
  126. //=========================================================================
  127. // Don't allow text to be set if we've got a rowset open
  128. //=========================================================================
  129. if ( m_pcmd->IsRowsetOpen() ){
  130. return g_pCError->PostHResult((DB_E_OBJECTOPEN), &IID_ICommandText);
  131. }
  132. //=========================================================================
  133. // Check Dialect
  134. //=========================================================================
  135. if (rguidDialect != DBGUID_WQL && rguidDialect != DBGUID_DEFAULT &&
  136. rguidDialect != DBGUID_LDAP && rguidDialect != DBGUID_WMI_METHOD &&
  137. rguidDialect != DBGUID_LDAPSQL){
  138. return g_pCError->PostHResult((DB_E_DIALECTNOTSUPPORTED), &IID_ICommandText);
  139. }
  140. if(rguidDialect == DBGUID_WMI_METHOD)
  141. {
  142. m_pcmd->m_pQuery->SetType(METHOD_ROWSET);
  143. }
  144. //=========================================================================
  145. // Unprepare if we've already got something prepared
  146. //=========================================================================
  147. m_pcmd->UnprepareHelper(UNPREPARE_NEW_CMD);
  148. // NTRaid 134165
  149. if(SUCCEEDED(hr = m_pcmd->GetQueryLanguage(varQryLang)))
  150. {
  151. //=========================================================================
  152. // Delete the old text
  153. //=========================================================================
  154. if(SUCCEEDED(hr = m_pcmd->m_pQuery->InitQuery(varQryLang.bstrVal)))
  155. {
  156. //=========================================================================
  157. // Save the new text
  158. //=========================================================================
  159. if (pwszCommand && *pwszCommand){
  160. hr = m_pcmd->m_pQuery->SetQuery(pwszCommand,rguidDialect);
  161. }
  162. else{
  163. //=========================================================================
  164. // There is no text
  165. //=========================================================================
  166. hr = m_pcmd->m_pQuery->SetDefaultQuery();
  167. }
  168. }
  169. }
  170. if(SUCCEEDED(hr))
  171. {
  172. // If everything is fine then set the datasource persist info to dirty
  173. m_pcmd->m_pCDBSession->m_pCDataSource->SetPersistDirty();
  174. // Clear the column information
  175. SAFE_DELETE_PTR(m_pcmd->m_pColumns);
  176. m_pcmd->m_cTotalCols = 0;
  177. m_pcmd->m_cCols = 0;
  178. m_pcmd->m_cNestedCols = 0;
  179. }
  180. VariantClear(&varQryLang);
  181. hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
  182. CATCH_BLOCK_HRESULT(hr,L"ICommandText::SetCommandText");
  183. return hr;
  184. }
  185. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  186. //
  187. // Return an interface from the session object that created this command object
  188. //
  189. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. STDMETHODIMP CImpICommandText::GetDBSession( REFIID riid, IUnknown** ppSession)
  191. {
  192. HRESULT hr;
  193. CSetStructuredExceptionHandler seh;
  194. TRY_BLOCK;
  195. //=========================================================================
  196. // At the creation of the CAutoBlock object a critical section
  197. // is entered. This is because the method manipulates shared structures
  198. // access to which must be serialized . The critical
  199. // section is left when this method terminate and the destructor
  200. // for CAutoBlock is called.
  201. //=========================================================================
  202. CAutoBlock cab( m_pcmd->GetCriticalSection() );
  203. //=========================================================================
  204. // Clear previous Error Object for this thread
  205. //=========================================================================
  206. g_pCError->ClearErrorInfo();
  207. //=========================================================================
  208. // Check Arguments
  209. //=========================================================================
  210. if (ppSession == NULL){
  211. return g_pCError->PostHResult((E_INVALIDARG), &IID_ICommandText);
  212. }
  213. //=========================================================================
  214. // Initialize output param
  215. //=========================================================================
  216. *ppSession = NULL;
  217. //=========================================================================
  218. // Query for the interface on the session object. If failure,
  219. // return the error from QueryInterface.
  220. //=========================================================================
  221. hr = (m_pcmd->m_pCDBSession->GetOuterUnknown())->QueryInterface(riid, (VOID**)ppSession);
  222. hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
  223. CATCH_BLOCK_HRESULT(hr,L"ICommandText::GetSession");
  224. return hr;
  225. }
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. //
  228. // The consumer can allocate a secondary thread in which to cancel
  229. // the currently executing thread. This cancel will only succeed if
  230. // the result set is still being generated. If the rowset object is being
  231. // created, then it will be to late to cancel.
  232. //
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. STDMETHODIMP CImpICommandText::Cancel(void)
  235. {
  236. HRESULT hr = S_OK;
  237. CSetStructuredExceptionHandler seh;
  238. TRY_BLOCK;
  239. //=========================================================================
  240. // Clear previous Error Object for this thread
  241. //=========================================================================
  242. g_pCError->ClearErrorInfo();
  243. m_pcmd->m_pQuery->m_pcsQuery->Enter();
  244. if (m_pcmd->m_pQuery){
  245. HRESULT retcode = m_pcmd->m_pQuery->CancelQuery();
  246. if( S_OK == retcode){
  247. m_pcmd->m_pQuery->InitQuery(); // ?
  248. }
  249. else{
  250. hr = DB_E_CANTCANCEL;
  251. }
  252. m_pcmd->m_pQuery->SetCancelStatus(CMD_EXEC_CANCELED);
  253. }
  254. else{
  255. m_pcmd->m_pQuery->SetCancelStatus(CMD_EXEC_CANCELED | CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
  256. }
  257. m_pcmd->m_pQuery->m_pcsQuery->Leave();
  258. hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
  259. CATCH_BLOCK_HRESULT(hr,L"ICommandText::Cancel");
  260. return hr;
  261. }
  262. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  263. //
  264. // Execute the command.
  265. //
  266. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  267. STDMETHODIMP CImpICommandText::Execute( IUnknown* pUnkOuter,
  268. REFIID riid, //@parm IN | Interface ID of the interface being queried for.
  269. DBPARAMS* pParams, //@parm INOUT | Parameter Array
  270. DBROWCOUNT* pcRowsAffected, //@parm OUT | count of rows affected by command
  271. IUnknown** ppRowsets //@parm OUT | Pointer to interface that was instantiated
  272. )
  273. {
  274. HRESULT hr = S_OK;
  275. CSetStructuredExceptionHandler seh;
  276. VARIANT varQryLang;
  277. VariantInit(&varQryLang);
  278. TRY_BLOCK;
  279. //=========================================================================
  280. // At the creation of the CAutoBlock object a critical section is entered.
  281. // This is because the method manipulates shared structures access to which
  282. // must be serialized . The critical section is left when this method
  283. // terminate and the destructor for CAutoBlock is called.
  284. //=========================================================================
  285. CAutoBlock cab( m_pcmd->GetCriticalSection() );
  286. m_pcmd->m_pQuery->m_pcsQuery->Enter();
  287. if (m_pcmd->m_pQuery->GetCancelStatus() & CMD_EXEC_CANCELED_BEFORE_CQUERY_SET){
  288. m_pcmd->m_pQuery->ClearCancelStatus(CMD_EXEC_CANCELED | CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
  289. }
  290. if (m_pcmd->m_pQuery->GetStatus() & CMD_EXECUTED_ONCE){
  291. m_pcmd->m_pQuery->ClearStatus(CMD_EXECUTED_ONCE);
  292. }
  293. // get the QueryLanguage Property and set it on the
  294. // query object
  295. // NTRaid 134165
  296. if(SUCCEEDED(hr = m_pcmd->GetQueryLanguage(varQryLang)))
  297. {
  298. hr = m_pcmd->m_pQuery->SetQueryLanguage(varQryLang.bstrVal);
  299. }
  300. m_pcmd->m_pQuery->m_pcsQuery->Leave();
  301. //=========================================================================
  302. // Clear previous Error Object for this thread
  303. //=========================================================================
  304. g_pCError->ClearErrorInfo();
  305. if(SUCCEEDED(hr))
  306. {
  307. //=========================================================================
  308. // Execute the command
  309. //=========================================================================
  310. hr = m_pcmd->Execute(pUnkOuter, riid, pParams, pcRowsAffected, ppRowsets);
  311. }
  312. VariantClear(&varQryLang);
  313. CATCH_BLOCK_HRESULT(hr,L"ICommandText::Execute");
  314. return hr;
  315. }
  316. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  317. //*********************************************************************************************************
  318. //
  319. // CUtlParam class
  320. //
  321. //*********************************************************************************************************
  322. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  323. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  324. //
  325. // This routine builds the binding information needed to execute a command with parameters
  326. //
  327. // HRESULT indicating status
  328. // S_OK | No problem processing parameter or statement
  329. // E_FAIL | Provider specific error
  330. // E_OUTOFMEMORY | Not enough resources
  331. // E_UNEXPECTED | Zombie State
  332. // DB_E_BADACCESSORHANDLE | Accessor handle invalid
  333. // DB_E_BADACCESSORTYPE | Non-Parameter Accessor used
  334. // DB_E_BADPARAMETER | Parameter information not correct
  335. // DB_E_BADPARAMETERCOUNT | Bad Parameter Count
  336. // DB_E_DUPLICATEPARAM | Same parameter used twice
  337. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  338. STDMETHODIMP CUtlParam::BuildBindInfo( CCommand *pcmd, DBPARAMS *pParams, const IID* piid)
  339. {
  340. HRESULT hr = S_OK;
  341. // NTRaid::111812
  342. // 06/07/00
  343. PACCESSOR pAccessor = NULL;
  344. DBORDINAL iBind;
  345. DBCOUNTITEM iParamSet;
  346. DBBINDING *pBind;
  347. // DBTYPE wType;
  348. ULONG cErrors = 0;
  349. DBORDINAL iParam;
  350. BYTE *pbData;
  351. ULONG cBindInfo;
  352. ULONG iDupBind;
  353. WMIBINDINFO *pBindInfo;
  354. BOOL fDeriveParamsFromSql = FALSE;
  355. //==========================================================
  356. // Copy DBPARAMS struct (C++ bitwise copy)
  357. //==========================================================
  358. m_dbparams = *pParams;
  359. //==========================================================
  360. // Add an extra reference count to the user's accessor,
  361. // since we're now holding a pointer to it in m_dbparams
  362. //==========================================================
  363. m_pIAccessor = pcmd->GetIAccessorPtr();
  364. m_pIAccessor->AddRefAccessor(m_dbparams.hAccessor, NULL);
  365. //==========================================================
  366. // Obtain pointer to the accessor that the user passed to us
  367. //==========================================================
  368. m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer(pParams->hAccessor, &pAccessor);
  369. m_cbRowSize = 999;
  370. //==========================================================
  371. // Make sure at least one binding for each parameter
  372. //==========================================================
  373. m_cParams = pcmd->GetParamCount();
  374. if (pAccessor->cBindings < m_cParams){
  375. hr = DB_E_PARAMNOTOPTIONAL;
  376. }
  377. else
  378. {
  379. //==========================================================
  380. // Allocate mem ory for binding information
  381. //==========================================================
  382. iDupBind = m_cParams;
  383. cBindInfo = max(m_cParams, pAccessor->cBindings);
  384. m_prgBindInfo = new WMIBINDINFO[cBindInfo];
  385. if (NULL == m_prgBindInfo){
  386. hr = E_OUTOFMEMORY;
  387. }
  388. else
  389. {
  390. memset(m_prgBindInfo, 0, sizeof(WMIBINDINFO)*cBindInfo);
  391. //==========================================================
  392. // Process each binding of the given accessor
  393. //==========================================================
  394. for (iBind = 0; iBind < pAccessor->cBindings; iBind++){
  395. //======================================================
  396. // Get the pointer to the binding of interest
  397. //======================================================
  398. pBind = pAccessor->rgBindings + iBind;
  399. //======================================================
  400. // Make sure this binding's ordinal is valid
  401. //======================================================
  402. if (!pBind->iOrdinal || pBind->iOrdinal > m_cParams){
  403. //==================================================
  404. // This is a bad accessor; set status if bound
  405. //==================================================
  406. SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
  407. //==================================================
  408. // Count this error and look for more
  409. //==================================================
  410. cErrors++;
  411. continue;
  412. }
  413. iParam = pBind->iOrdinal - 1;
  414. //======================================================
  415. // Save the binding
  416. //======================================================
  417. if (NULL == m_prgBindInfo[iParam].pBinding){
  418. m_prgBindInfo[iParam].pBinding = pBind;
  419. if (pBind->eParamIO & DBPARAMIO_OUTPUT)
  420. m_prgBindInfo[iParam].wFlags |= DBPARAMIO_OUTPUT;
  421. if (pBind->eParamIO & DBPARAMIO_INPUT)
  422. m_prgBindInfo[iParam].wFlags |= DBPARAMIO_INPUT;
  423. }
  424. else {
  425. //==================================================
  426. // Multiple bindings for this parameter
  427. //==================================================
  428. pBindInfo = m_prgBindInfo + iDupBind++;
  429. pBindInfo->pBinding = pBind;
  430. pBindInfo->pNextBindInfo =
  431. m_prgBindInfo[iParam].pNextBindInfo;
  432. m_prgBindInfo[iParam].pNextBindInfo = pBindInfo;
  433. if (pBind->eParamIO & DBPARAMIO_OUTPUT)
  434. m_prgBindInfo[iParam].wFlags |= DBPARAMIO_OUTPUT;
  435. if (pBind->eParamIO & DBPARAMIO_INPUT){
  436. if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT){
  437. //==========================================
  438. // A bad accessor; set status if bound
  439. //==========================================
  440. SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
  441. //==========================================
  442. // Count this error and look for more
  443. //==========================================
  444. cErrors++;
  445. continue;
  446. }
  447. m_prgBindInfo[iParam].wFlags |= DBPARAMIO_INPUT;
  448. }
  449. }
  450. //======================================================
  451. // Get the parameter type from the accessor
  452. //======================================================
  453. switch (pBind->eParamIO){
  454. case DBPARAMIO_INPUT:
  455. case DBPARAMIO_OUTPUT:
  456. case DBPARAMIO_INPUT|DBPARAMIO_OUTPUT:
  457. break;
  458. case DBPARAMIO_NOTPARAM:
  459. default:
  460. // This is a bad accessor; set status if bound
  461. SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
  462. // Count this error and look for more
  463. cErrors++;
  464. continue;
  465. }
  466. for (pbData = (BYTE*)m_dbparams.pData, iParamSet = 0;iParamSet < m_dbparams.cParamSets;pbData += m_cbRowSize, iParamSet++ ){
  467. //=========================================================================
  468. // If this is not an output param and we aren't given a value
  469. // or a DBSTATUS_S_ISNULL, that's an error
  470. //=========================================================================
  471. BOOL fOutput = m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT;
  472. if ((!fOutput ) && !(pBind->dwPart & DBPART_VALUE) && (!(pBind->dwPart & DBPART_STATUS)
  473. || *(DBSTATUS *)((BYTE *)pbData + pBind->obStatus) != DBSTATUS_S_ISNULL) ) {
  474. // This is a bad accessor; set status if bound
  475. if (pBind->dwPart & DBPART_STATUS){
  476. *(DBSTATUS *)(pbData + pBind->obStatus) =DBSTATUS_E_BADACCESSOR;
  477. }
  478. // Count this error and look for more
  479. cErrors++;
  480. break;
  481. }
  482. if ((pBind->dwPart & DBPART_STATUS) && DBSTATUS_S_DEFAULT == *(DBSTATUS*)((BYTE*)pbData + pBind->obStatus)) {
  483. m_dwStatus |= CUTLPARAM_DEFAULT_PARAMS;
  484. }
  485. }
  486. } // end of outer for loop
  487. // Any errors in processing bindings?
  488. if (cErrors){
  489. hr = DB_E_ERRORSOCCURRED;
  490. }
  491. else
  492. if (SUCCEEDED(hr = BuildParamInfo(pcmd, piid)))
  493. {
  494. for (iParam = 0; iParam < m_cParams; iParam++){
  495. if ((m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT) && !((m_prgBindInfo[iParam].pParamInfo->dwFlags & DBPARAMFLAGS_ISINPUT))
  496. || ((m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT) && !(m_prgBindInfo[iParam].pParamInfo->dwFlags & DBPARAMFLAGS_ISOUTPUT))){
  497. // This is a bad accessor; set status if bound
  498. SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
  499. for (pBindInfo = m_prgBindInfo[iParam].pNextBindInfo; pBindInfo; pBindInfo = pBindInfo->pNextBindInfo)
  500. SetStatus(pBindInfo->pBinding, DBSTATUS_E_BADACCESSOR);
  501. // Count this error and look for more
  502. cErrors++;
  503. }
  504. }
  505. if (cErrors)
  506. {
  507. hr = DB_E_ERRORSOCCURRED;
  508. }
  509. }
  510. } // if memory is allocated properly
  511. } // else for checking for DB_E_PARAMNOTOPTIONAL error
  512. hr = hr != S_OK ? g_pCError->PostHResult(hr, piid): hr;
  513. return hr;
  514. }
  515. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  516. //
  517. // This routine builds the parameter information for the command from the binding information.
  518. //
  519. // HRESULT indicating status
  520. // S_OK | No problem processing parameter or statement
  521. // E_FAIL | Provider specific error
  522. // E_OUTOFMEMORY | Not enough resources
  523. //
  524. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  525. STDMETHODIMP CUtlParam::BuildParamInfo( CCommand *pcmd, const IID* piid )
  526. {
  527. HRESULT hr = S_OK;
  528. ULONG iParam(0);
  529. PPARAMINFO pParamInfo;
  530. DBBINDING *pBind;
  531. BYTE* pbData = NULL;
  532. DWORD* pdwLength;
  533. DWORD dwLength(0);
  534. DBSTATUS* pdwStatus;
  535. DBSTATUS dwStatus(0);
  536. DBLENGTH cbMaxLen(0);
  537. VARIANT varValue;
  538. VariantInit(&varValue);
  539. m_rgpParamInfo = new PPARAMINFO[m_cParams];
  540. if (NULL == m_rgpParamInfo)
  541. {
  542. hr = E_OUTOFMEMORY;
  543. }
  544. else
  545. {
  546. memset(m_rgpParamInfo, 0, sizeof(PPARAMINFO)*m_cParams);
  547. for (iParam = 0; iParam < m_cParams; iParam++){
  548. VariantClear(&varValue);
  549. pParamInfo = pcmd->GetParamInfo(iParam);
  550. if (pParamInfo){
  551. m_rgpParamInfo[m_cParamInfo++] = pParamInfo;
  552. pParamInfo->dwFlags = DBPARAMFLAGS_ISNULLABLE;
  553. if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT)
  554. pParamInfo->dwFlags |= DBPARAMFLAGS_ISINPUT;
  555. if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT)
  556. pParamInfo->dwFlags |= DBPARAMFLAGS_ISOUTPUT;
  557. //=========================================================
  558. // Bind the parameter
  559. //=========================================================
  560. pBind = GetBinding(m_prgBindInfo+iParam);
  561. if( pBind ){
  562. BindParamData(1, iParam+1, pBind, &pParamInfo->pbData, &pdwLength, (ULONG*)&pParamInfo->cbColLength, &pdwStatus, &dwStatus, &(pParamInfo->wOLEDBType));
  563. //=========================================================
  564. // Get the data type for variant params
  565. //=========================================================
  566. if (pParamInfo->wOLEDBType == DBTYPE_VARIANT && pParamInfo->pbData != NULL)
  567. pParamInfo->wOLEDBType = V_VT((VARIANT *)pParamInfo->pbData);
  568. // For variable length params, find the max len
  569. cbMaxLen = 0;
  570. if (DBTYPE_STR == pParamInfo->wOLEDBType || DBTYPE_WSTR == pParamInfo->wOLEDBType
  571. || DBTYPE_BSTR == pParamInfo->wOLEDBType || DBTYPE_BYTES == pParamInfo->wOLEDBType)
  572. {
  573. ULONG iParamSet;
  574. DBTYPE wDstType = (DBTYPE_BSTR == pParamInfo->wOLEDBType) ? DBTYPE_WSTR : pParamInfo->wOLEDBType;
  575. cbMaxLen = pBind->cbMaxLen;
  576. for (iParamSet = 2; iParamSet <= m_dbparams.cParamSets; iParamSet++)
  577. {
  578. DBTYPE wSrcType;
  579. //==========================================
  580. // Bind the parameter
  581. //==========================================
  582. pBind = m_prgBindInfo[iParam].pBinding;
  583. BindParamData(iParamSet, iParam+1, pBind, &pbData, &pdwLength, &dwLength, &pdwStatus, &dwStatus, &wSrcType);
  584. cbMaxLen = pBind->cbMaxLen;
  585. }
  586. // Initialize the parameter info
  587. BOOL bArray = FALSE;
  588. CDataMap Map;
  589. if(hr == S_OK)
  590. {
  591. hr = Map.MapOLEDBTypeToCIMType(pParamInfo->wOLEDBType, pParamInfo->CIMType ) ;
  592. if( S_OK == hr ){
  593. WORD wTmp = 0;
  594. DBLENGTH uSize = 0;
  595. DWORD dwFlags = 0;
  596. // if the length as obtained from BindParamData is 0 and if the parameter
  597. // is input then get the size of parameter for the type
  598. if(pParamInfo->cbColLength == 0 && (pParamInfo->dwFlags & DBPARAMIO_INPUT))
  599. {
  600. hr = Map.MapCIMTypeToOLEDBType(pParamInfo->CIMType, wTmp, uSize, dwFlags );
  601. if( hr == S_OK ){
  602. pParamInfo->cbColLength = pParamInfo->cbValueMax = pParamInfo->ulParamSize = uSize;
  603. }
  604. }
  605. }
  606. }
  607. }
  608. m_prgBindInfo[iParam].pParamInfo = pParamInfo;
  609. }
  610. }
  611. }
  612. }
  613. //Exit:
  614. hr = hr != S_OK ? g_pCError->PostHResult(E_OUTOFMEMORY, piid): hr;
  615. return hr;
  616. }
  617. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  618. //
  619. // Sets the bind status for all parameters, except the one that caused the command to fail,
  620. // to DBSTATUS_E_UNAVAILABLE.
  621. //
  622. // Nothing
  623. //
  624. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  625. void CUtlParam::SetParamsUnavailable( ULONG iParamSetFailed, ULONG iParamFailed, BOOL fBackOut )
  626. {
  627. assert(iParamSetFailed);
  628. ULONG iParam;
  629. ULONG iParamSet;
  630. BYTE* pbData;
  631. PWMIBINDINFO pBindInfo;
  632. for ( iParamSet = fBackOut? 1 : iParamSetFailed, pbData= (BYTE*)m_dbparams.pData + (iParamSet-1)*m_cbRowSize;
  633. iParamSet <= m_dbparams.cParamSets; iParamSet++, pbData += m_cbRowSize){
  634. for ( iParam = 1, pBindInfo = m_prgBindInfo; iParam <= m_cParams; iParam++, pBindInfo++){
  635. DBSTATUS* pdbstatus = (DBSTATUS *) (pbData + pBindInfo->pBinding->obStatus);
  636. if (pBindInfo->pBinding->dwPart & DBPART_STATUS){
  637. if (iParamSet != iParamSetFailed || iParam != iParamFailed
  638. || *pdbstatus == DBSTATUS_S_OK
  639. || *pdbstatus == DBSTATUS_S_ISNULL
  640. || *pdbstatus == DBSTATUS_S_DEFAULT){
  641. *pdbstatus = DBSTATUS_E_UNAVAILABLE;
  642. }
  643. }
  644. }
  645. }
  646. }
  647. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  648. void CUtlParam::BindParamData( ULONG iParamSet, ULONG iParam, DBBINDING* pBinding,BYTE** ppbValue,
  649. DWORD** ppdwLength, DWORD* pdwLength,DBSTATUS** ppdwStatus,
  650. DBSTATUS* pdwStatus, DBTYPE* pdbtype )
  651. {
  652. assert(iParamSet && iParamSet <= m_dbparams.cParamSets);
  653. assert(iParam && iParam <= m_cParams);
  654. assert(pBinding);
  655. assert(pBinding->iOrdinal == iParam);
  656. assert(ppbValue);
  657. assert(ppdwLength);
  658. assert(pdwLength);
  659. assert(ppdwStatus);
  660. assert(pdwStatus);
  661. BYTE* pbData = (BYTE*)m_dbparams.pData + (iParamSet-1)*m_cbRowSize;
  662. *pdbtype = pBinding->wType & ~DBTYPE_BYREF;
  663. if (pBinding->dwPart & DBPART_VALUE){
  664. *ppbValue = pbData + pBinding->obValue;
  665. if (pBinding->wType & DBTYPE_BYREF){
  666. assert(!IsBadReadPtr(*ppbValue,sizeof(BYTE*)));
  667. *ppbValue = *(BYTE**)*ppbValue;
  668. }
  669. }
  670. else{
  671. *ppbValue = NULL;
  672. }
  673. if (pBinding->dwPart & DBPART_STATUS){
  674. assert(!IsBadReadPtr(pbData+pBinding->obStatus,sizeof(DBSTATUS)));
  675. *ppdwStatus = (DBSTATUS*)(pbData + pBinding->obStatus);
  676. *pdwStatus = **ppdwStatus;
  677. }
  678. else{
  679. *ppdwStatus = NULL;
  680. *pdwStatus = DBSTATUS_S_OK;
  681. }
  682. *ppdwLength = (pBinding->dwPart & DBPART_LENGTH) ? (DWORD*)(pbData + pBinding->obLength) : NULL;
  683. if (*pdwStatus != DBSTATUS_S_OK || *ppbValue == NULL || pBinding->eParamIO == DBPARAMIO_OUTPUT){
  684. *pdwLength = 0;
  685. }
  686. //NTRaid:111761
  687. // 06/07/00
  688. else
  689. if(*ppdwLength)
  690. {
  691. *pdwLength = *(*ppdwLength);
  692. }
  693. else
  694. {
  695. *pdwLength = 0;
  696. }
  697. // check NULL data
  698. if (*pdwStatus == DBSTATUS_S_OK && *ppbValue && (*pdbtype == DBTYPE_VARIANT || *pdbtype == DBTYPE_PROPVARIANT)
  699. && V_VT((VARIANT *)(*ppbValue)) == VT_NULL){
  700. *pdwStatus = DBSTATUS_S_ISNULL;
  701. }
  702. }
  703. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  704. ULONG CUtlParam::AddRef ( void)
  705. {
  706. return InterlockedIncrement( (long*) &m_cRef);
  707. }
  708. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  709. ULONG CUtlParam::Release(void)
  710. {
  711. assert( m_cRef > 0 );
  712. ULONG cRef = InterlockedDecrement( (long*) &m_cRef);
  713. if (!cRef)
  714. delete this;
  715. return cRef;
  716. }
  717. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  718. CUtlParam::CUtlParam()
  719. {
  720. m_cRef = 0;
  721. m_cbRowSize = 0;
  722. m_cParams = 0;
  723. m_cParamInfo = 0;
  724. m_dwStatus = 0;
  725. m_pIAccessor = NULL;
  726. m_prgBindInfo = NULL;
  727. m_rgpParamInfo = NULL;
  728. }
  729. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  730. CUtlParam::~CUtlParam()
  731. {
  732. }