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.

1257 lines
35 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // IRowsetChange interface implementation
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////////////////
  9. #include "headers.h"
  10. ///////////////////////////////////////////////////////////////////////////////////////////
  11. //
  12. // Sets new data values into fields of a row.
  13. //
  14. // HRESULT
  15. // S_OK The method succeeded
  16. // E_OUTOFMEMORY Out of memory
  17. // DB_E_BADACCESSORHANDLE Bad accessor handle
  18. // DB_E_READONLYACCESSOR Tried to write through a read-only accessor
  19. // DB_E_BADROWHANDLE Invalid row handle
  20. // E_INVALIDARG pData was NULL
  21. // E_FAIL Provider-specific error
  22. // OTHER Other HRESULTs returned by called functions
  23. //
  24. ///////////////////////////////////////////////////////////////////////////////////////////
  25. STDMETHODIMP CImpIRowsetChange::SetData ( HROW hRow, // IN Handle of the row in which to set the data
  26. HACCESSOR hAccessor, // IN Handle to the accessor to use
  27. void* pData // IN Pointer to the data
  28. )
  29. {
  30. BYTE* pbProvRow;
  31. HRESULT hr = S_OK;
  32. PACCESSOR paccessor = NULL;
  33. DWORD dwErrorCount = 0 , dwStatus = DBROWSTATUS_S_OK;
  34. VARIANT varProp;
  35. BOOL bNewRow = FALSE;
  36. CSetStructuredExceptionHandler seh;
  37. TRY_BLOCK;
  38. VariantInit(&varProp);
  39. // Seriliaze the object
  40. CAutoBlock cab(ROWSET->GetCriticalSection());
  41. // Clear Error information
  42. g_pCError->ClearErrorInfo();
  43. hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp);
  44. if(m_pObj->IsZoombie())
  45. {
  46. hr = E_UNEXPECTED;
  47. }
  48. else
  49. // If updation is allowed then
  50. if( !(hr == 0 && (DBPROPVAL_UP_CHANGE & varProp.lVal)))
  51. {
  52. hr = DB_E_NOTSUPPORTED;
  53. }
  54. else
  55. //===========================================================================
  56. // validate the arguments and get the accessor and row pointers
  57. //===========================================================================
  58. if( SUCCEEDED(hr = ValidateArguments(hRow,hAccessor,pData,(PROWBUFF *)&pbProvRow,&paccessor)))
  59. {
  60. //===========================================================================
  61. // If the number of bindings is zero then there is nothing to update
  62. //===========================================================================
  63. if( paccessor->cBindings == 0)
  64. {
  65. hr = S_OK;
  66. }
  67. else
  68. {
  69. //============================================================================
  70. // Is row handle deleted?
  71. //============================================================================
  72. dwStatus = m_pObj->GetRowStatus(hRow);
  73. if(dwStatus == DBROWSTATUS_E_NEWLYINSERTED)
  74. {
  75. bNewRow = TRUE;
  76. }
  77. else
  78. if( dwStatus != DBROWSTATUS_S_OK)
  79. {
  80. if(dwStatus == DBROWSTATUS_E_DELETED)
  81. {
  82. hr = DB_E_DELETEDROW;
  83. }
  84. else
  85. {
  86. hr = E_FAIL;
  87. }
  88. }
  89. if(SUCCEEDED(hr))
  90. {
  91. // Get data from accessor an put it into the row buffer
  92. hr = ApplyAccessorToData(paccessor->cBindings,paccessor->rgBindings,pbProvRow,pData,dwErrorCount);
  93. if( hr == NOCOLSCHANGED && dwErrorCount > 0)
  94. {
  95. hr = DB_E_ERRORSOCCURRED;
  96. LogMessage("IRowsetChange::SetData:No columns has been modified");
  97. }
  98. else
  99. // If there is no change in any of the columns then
  100. // there is no need to update
  101. if( !FAILED(hr))
  102. {
  103. //==================================================
  104. // update the data on the instance
  105. //==================================================
  106. if(SUCCEEDED(hr = m_pObj->UpdateRowData(hRow,paccessor,bNewRow)))
  107. {
  108. m_pObj->SetRowStatus(hRow,DBROWSTATUS_S_OK);
  109. }
  110. }
  111. }
  112. }
  113. }
  114. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
  115. CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::SetData");
  116. return hr;
  117. }
  118. /////////////////////////////////////////////////////////////////////////////////////////////
  119. // Deletes rows from the provider. If Errors on individual rows occur, the DBERRORINFO
  120. // array is updated to reflect the error and S_FALSE is returned instead of S_OK.
  121. //
  122. // HRESULT indicating the status of the method
  123. // S_OK All row handles deleted
  124. // DB_S_ERRORSOCCURRED Some, but not all, row handles deleted
  125. // E_INVALIDARG Arguments did not match spec.
  126. // E_OUTOFMEMORY Could not allocated error array
  127. //
  128. ///////////////////////////////////////////////////////////////////////////////////////////
  129. STDMETHODIMP CImpIRowsetChange::DeleteRows (HCHAPTER hChapter, // IN The Chapter handle.
  130. DBCOUNTITEM cRows, // IN Number of rows to delete
  131. const HROW rghRows[], // IN Array of handles to delete
  132. DBROWSTATUS rgRowStatus[] // OUT Error information
  133. )
  134. {
  135. ULONG ihRow = 0L;
  136. ULONG cErrors = 0L;
  137. ULONG cRowReleased = 0L;
  138. BYTE* pbProvRow = NULL;
  139. HRESULT hr = S_OK;
  140. DBROWSTATUS * pRowStatus = NULL;
  141. VARIANT varProp;
  142. CSetStructuredExceptionHandler seh;
  143. TRY_BLOCK;
  144. VariantInit(&varProp);
  145. // Seriliaze the object
  146. CAutoBlock cab(ROWSET->GetCriticalSection());
  147. // Clear Error information
  148. g_pCError->ClearErrorInfo();
  149. hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp);
  150. if(m_pObj->IsZoombie())
  151. {
  152. hr = E_UNEXPECTED;
  153. }
  154. else
  155. // If updation is allowed then
  156. if( !(hr == 0 && (DBPROPVAL_UP_DELETE & varProp.lVal)))
  157. {
  158. hr = DB_E_NOTSUPPORTED;
  159. }
  160. else
  161. //=====================================================
  162. // If No Row handle, just return.
  163. //=====================================================
  164. if ( cRows > 0 )
  165. {
  166. //=================================================
  167. // Check for Invalid Arguments
  168. //=================================================
  169. if ( (cRows >= 1) && (NULL == rghRows) ){
  170. hr = E_INVALIDARG;
  171. }
  172. else
  173. {
  174. //=================================================
  175. // Process row handles
  176. //=================================================
  177. while (ihRow < cRows){
  178. pRowStatus = NULL;
  179. if ( rgRowStatus )
  180. {
  181. rgRowStatus[ihRow] = DBROWSTATUS_S_OK;
  182. pRowStatus = &rgRowStatus[ihRow];
  183. }
  184. //=============================================
  185. // Is row handle valid
  186. //=============================================
  187. if(FALSE == m_pObj->IsRowExists(rghRows[ihRow])){
  188. // Log Error
  189. if ( rgRowStatus ){
  190. rgRowStatus[ihRow]= DBROWSTATUS_E_INVALID;
  191. }
  192. cErrors++;
  193. ihRow++;
  194. continue;
  195. }
  196. //=======================================================
  197. // Delete the Row
  198. //=======================================================
  199. if( S_OK != (hr = m_pObj->DeleteRow(rghRows[ihRow],pRowStatus)))
  200. cErrors++;
  201. ihRow++;
  202. } //while
  203. }
  204. //=================================================
  205. // If everything went OK except errors in rows use
  206. // DB_S_ERRORSOCCURRED.
  207. //=================================================
  208. hr = cErrors ? ( cErrors < cRows ) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED : S_OK ;
  209. }
  210. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
  211. CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::DeleteRows");
  212. return hr;
  213. }
  214. /////////////////////////////////////////////////////////////////////////////////////////////
  215. //
  216. // Insert row into provider
  217. //
  218. // Returns: S_OK if data changed successfully
  219. // E_FAIL if Catch all (NULL pData, etc.)
  220. // E_INVALIDARG if pcErrors!=NULL and paErrors==NULL
  221. // E_OUTOFMEMORY if output error array couldn't be allocated
  222. // DB_E_BADACCESSORHANDLE if invalid accessor
  223. //
  224. /////////////////////////////////////////////////////////////////////////////////////////////
  225. STDMETHODIMP CImpIRowsetChange::InsertRow (HCHAPTER hChapter, // IN The Chapter handle.
  226. HACCESSOR hAccessor,
  227. void* pData,
  228. HROW* phRow )
  229. {
  230. HRESULT hr = S_OK;
  231. CSetStructuredExceptionHandler seh;
  232. TRY_BLOCK;
  233. //====================================================
  234. // Initialize values
  235. //====================================================
  236. if ( phRow ){
  237. *phRow = NULL;
  238. }
  239. hr = E_FAIL;
  240. DBORDINAL ibind = 0;
  241. BYTE* pbProvRow = NULL;
  242. HROW irow = 0;
  243. DBCOUNTITEM cBindings = 0;
  244. DBBINDING* pBinding = NULL;
  245. DBCOUNTITEM dwErrorCount = 0;
  246. PACCESSOR paccessor = NULL;
  247. BOOL fCanHoldRows = FALSE;
  248. BSTR strKey = Wmioledb_SysAllocString(NULL);
  249. HROW hRowNew = 0;
  250. DBORDINAL lQualifColIndex = -1;
  251. BOOL bCleanUp = FALSE;
  252. VARIANT varProp;
  253. CVARIANT cvarData;
  254. CDataMap dataMap;
  255. VARIANT* pvarData;
  256. CWbemClassWrapper *pNewInst = NULL;
  257. pvarData = &cvarData;
  258. VariantInit(&varProp);
  259. // Seriliaze the object
  260. CAutoBlock cab(ROWSET->GetCriticalSection());
  261. // Clear Error information
  262. g_pCError->ClearErrorInfo();
  263. hr = m_pObj->GetRowsetProperty(DBPROP_UPDATABILITY,varProp);
  264. if(m_pObj->IsZoombie())
  265. {
  266. hr = E_UNEXPECTED;
  267. }
  268. else
  269. // If updation is allowed then
  270. if( !(hr == 0 && (DBPROPVAL_UP_INSERT & varProp.lVal)))
  271. {
  272. hr = DB_E_NOTSUPPORTED;
  273. }
  274. else
  275. //====================================================
  276. // Check the Accessor Handle
  277. //====================================================
  278. if ( m_pObj->m_pIAccessor->GetAccessorPtr() == NULL || FAILED( m_pObj->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &paccessor)) ||
  279. paccessor == NULL )
  280. {
  281. hr = DB_E_BADACCESSORHANDLE;
  282. }
  283. else
  284. {
  285. assert( paccessor );
  286. //====================================================
  287. // Check to see if it is a row accessor
  288. //====================================================
  289. if ( !(paccessor->dwAccessorFlags & DBACCESSOR_ROWDATA) )
  290. hr = DB_E_BADACCESSORTYPE;
  291. // Ensure a source of data.
  292. if ( pData == NULL && paccessor->cBindings )
  293. {
  294. hr = E_INVALIDARG ;
  295. }
  296. else
  297. {
  298. if (m_pObj->m_ulProps & CANHOLDROWS)
  299. {
  300. fCanHoldRows = TRUE;
  301. }
  302. // Are there any unreleased rows?
  303. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && (!fCanHoldRows) )
  304. {
  305. hr = DB_E_ROWSNOTRELEASED;
  306. }
  307. else
  308. // Create the data members to manage the data only the first time
  309. if(!m_pObj->m_bHelperFunctionCreated)
  310. {
  311. if( SUCCEEDED(hr = m_pObj->CreateHelperFunctions()))
  312. {
  313. m_pObj->m_bHelperFunctionCreated = TRUE;
  314. }
  315. }
  316. if(SUCCEEDED(hr))
  317. {
  318. // Get new slots for the new row
  319. if (FAILED( hr = GetNextSlots( m_pObj->m_pIBuffer, 1, (HSLOT *)&irow )))
  320. {
  321. ;
  322. }
  323. else
  324. // Bind the slot for the row
  325. if (FAILED( m_pObj->Rebind((BYTE *) m_pObj->GetRowBuffFromSlot( (HSLOT)irow, TRUE ))))
  326. {
  327. ReleaseSlots( m_pObj->m_pIBuffer, irow,1 );
  328. }
  329. else
  330. {
  331. if(IsNullAccessor(paccessor,(BYTE *)pData))
  332. {
  333. if(SUCCEEDED(hr = InsertNewRow(irow,hChapter,pNewInst)))
  334. {
  335. m_pObj->SetRowStatus(irow,DBROWSTATUS_E_NEWLYINSERTED);
  336. if(phRow)
  337. {
  338. *phRow = irow;
  339. }
  340. }
  341. else
  342. {
  343. bCleanUp = TRUE;
  344. }
  345. }
  346. else
  347. {
  348. // Get the rowbuffer and set the new bookmark
  349. pbProvRow = (BYTE *) (m_pObj->GetRowBuffFromSlot((HSLOT)irow, TRUE ));
  350. cBindings = paccessor->cBindings;
  351. pBinding = paccessor->rgBindings;
  352. // NULL Accessor (set Status to NULL)
  353. // Apply accessor to data.
  354. for (ibind = 0, dwErrorCount = 0; ibind < cBindings; ibind++)
  355. {
  356. // If the column is value then get the type of the col is given by the
  357. // qualifier type column
  358. if(( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER) &&
  359. pBinding[ibind].iOrdinal == QUALIFIERVALCOL && ibind < cBindings-1)
  360. {
  361. lQualifColIndex = ibind;
  362. continue;
  363. }
  364. hr = UpdateDataToRowBuffer(ibind,pbProvRow,pBinding,(BYTE *)pData);
  365. if( hr == E_FAIL)
  366. {
  367. dwErrorCount++;
  368. continue;
  369. }
  370. }
  371. // if the recordset is of qualifer type then update the qualifier value
  372. if( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER)
  373. {
  374. if((DB_LORDINAL)lQualifColIndex == -1)
  375. {
  376. dwErrorCount = cBindings; // to escape the next if condition to throw error
  377. hr = E_FAIL; // the value of the qualifer is not provided for adding
  378. // a new qualifer
  379. }
  380. else
  381. {
  382. //update the qualifier value
  383. ibind = lQualifColIndex;
  384. hr = UpdateDataToRowBuffer(ibind,pbProvRow,pBinding,(BYTE *)pData);
  385. if( hr == E_FAIL)
  386. {
  387. dwErrorCount = cBindings; // to escape the next if condition to throw error
  388. }
  389. }
  390. }
  391. // If all bindings are bad and not a NULL Accessor
  392. if ( ( !cBindings ) || ( dwErrorCount < cBindings ) )
  393. {
  394. if(SUCCEEDED(hr = InsertNewRow(irow,hChapter,pNewInst)))
  395. {
  396. m_pObj->SetRowStatus(irow,DBROWSTATUS_E_NEWLYINSERTED);
  397. //=======================================================
  398. // Update the row data ie. put the property values
  399. // and save the instance
  400. //=======================================================
  401. hr = m_pObj->UpdateRowData(irow,paccessor, TRUE);
  402. if (SUCCEEDED(hr))
  403. {
  404. if(phRow)
  405. {
  406. *phRow = irow;
  407. }
  408. m_pObj->SetRowStatus(irow,DBSTATUS_S_OK);
  409. //=======================================================
  410. // If the rowset is bookmark enabled
  411. //=======================================================
  412. if(m_pObj->m_ulProps & BOOKMARKPROP)
  413. {
  414. //=======================================================
  415. // Add the bookmark to the bookmark hash table
  416. //=======================================================
  417. m_pObj->m_lLastFetchPos++;
  418. ((PROWBUFF)pbProvRow)->dwBmk = m_pObj->m_lLastFetchPos;
  419. ((PROWBUFF)pbProvRow)->cbBmk = BOOKMARKSIZE;
  420. m_pObj->m_pHashTblBkmark->InsertFindBmk(FALSE,irow,BOOKMARKSIZE,(BYTE *)&((PROWBUFF)pbProvRow)->dwBmk,&irow);
  421. }
  422. }
  423. else
  424. {
  425. bCleanUp = TRUE;
  426. }
  427. } // if succeeded(hr) after inserting row and initializing chapters
  428. else
  429. {
  430. bCleanUp = TRUE;
  431. }
  432. }
  433. }
  434. } // else if(FAILED(REbind())
  435. } // succeeded(hr) after CreateHelperFunctions
  436. }
  437. }
  438. if(!(FAILED(hr)))
  439. {
  440. //======================================================================
  441. // If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
  442. //======================================================================
  443. hr = dwErrorCount ? ( dwErrorCount < cBindings ) ?
  444. DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED : S_OK ;
  445. }
  446. //==============================================================
  447. // If any failure release the memory allocated for the row
  448. //==============================================================
  449. if( FAILED (hr) && bCleanUp)
  450. {
  451. //======================================================================
  452. // release the memory allocated for the different columns
  453. //======================================================================
  454. m_pObj->m_pRowData->ReleaseRowData();
  455. ReleaseSlots( m_pObj->m_pIBuffer, irow,1 );
  456. //======================================================================
  457. // release the rows from the instance manager and chapter manager
  458. //======================================================================
  459. m_pObj->ReleaseInstancePointer(irow);
  460. }
  461. SysFreeString(strKey);
  462. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetChange);
  463. CATCH_BLOCK_HRESULT(hr,L"IRowsetChange::InsertRow");
  464. return hr;
  465. }
  466. ///////////////////////////////////////////////////////////////////////////////////////////
  467. HRESULT CImpIRowsetChange::ApplyAccessorToData( DBCOUNTITEM cBindings, DBBINDING* pBinding,BYTE* pbProvRow, void* pData,DWORD & dwErrorCount )
  468. {
  469. PCOLUMNDATA pColumnData;
  470. DBORDINAL icol, ibind;
  471. DBTYPE dwSrcType;
  472. DBTYPE dwDstType;
  473. DBLENGTH dwSrcLength;
  474. DBLENGTH* pdwDstLength;
  475. DBLENGTH dwDstMaxLength;
  476. DBSTATUS dwSrcStatus;
  477. DBSTATUS* pdwDstStatus;
  478. DBSTATUS* pdwSrcStatus;
  479. DWORD dwPart;
  480. BYTE b;
  481. void* pDst;
  482. void* pSrc;
  483. void* pTemp;
  484. CDataMap dataMap;
  485. CVARIANT cvarData;
  486. VARIANT *pvarData = &cvarData;
  487. CDataMap map;
  488. ULONG cColChanged = 0;
  489. BOOL bUseDataConvert = TRUE;
  490. LONG_PTR lCIMType = 0;
  491. HRESULT hr = NOCOLSCHANGED;
  492. for (ibind = 0, dwErrorCount = 0; ibind < cBindings; ibind++)
  493. {
  494. bUseDataConvert = TRUE;
  495. icol = pBinding[ibind].iOrdinal;
  496. pColumnData = (COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(icol));
  497. dwSrcType = pBinding[ibind].wType;
  498. dwDstType = (DBTYPE)pColumnData->dwType; // m_pObj->m_Columns.ColumnType(icol);
  499. if(dwDstType == DBTYPE_EMPTY || dwDstType == DBTYPE_NULL)
  500. {
  501. dwDstType = m_pObj->m_Columns.ColumnType(icol);
  502. }
  503. dwSrcType = pBinding[ibind].wType;
  504. pdwDstLength = &(pColumnData->dwLength);
  505. pdwDstStatus = &(pColumnData->dwStatus);
  506. dwDstMaxLength = pBinding[ibind].cbMaxLen;
  507. dwPart = pBinding[ibind].dwPart;
  508. if ((dwPart & DBPART_VALUE) == 0){
  509. if (((dwPart & DBPART_STATUS) && (*(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) & DBSTATUS_S_ISNULL))
  510. || ((dwPart & DBPART_LENGTH) && *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) == 0)) {
  511. pSrc = &b;
  512. b = 0x00;
  513. }
  514. else{
  515. hr = E_FAIL ;
  516. break;
  517. }
  518. }
  519. else{
  520. pSrc = (void *) ((BYTE*) pData + pBinding[ibind].obValue);
  521. }
  522. dwSrcLength = (dwPart & DBPART_LENGTH) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : 0;
  523. dwSrcStatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : DBSTATUS_S_OK;
  524. pdwSrcStatus = (dwPart & DBPART_STATUS) ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
  525. //==========================================================================
  526. // if the columnd is of type readonly then don't do anything
  527. //==========================================================================
  528. if((m_pObj->m_Columns.ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0)
  529. {
  530. if(pdwSrcStatus != NULL)
  531. *pdwSrcStatus = DBSTATUS_E_READONLY;
  532. dwErrorCount++;
  533. continue;
  534. }
  535. hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &dwSrcLength, pdwDstLength, pSrc);
  536. try
  537. {
  538. pDst = new BYTE[*pdwDstLength];
  539. }
  540. catch(...)
  541. {
  542. SAFE_DELETE_ARRAY(pDst);
  543. throw;
  544. }
  545. // if both the source and destination type is array then don't
  546. // use IDataConvert::DataConvert for conversion
  547. if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
  548. {
  549. bUseDataConvert = FALSE;
  550. }
  551. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  552. {
  553. hr = g_pIDataConvert->DataConvert( dwSrcType, dwDstType, dwSrcLength, pdwDstLength, pSrc,
  554. pDst, dwDstMaxLength, dwSrcStatus, pdwDstStatus,
  555. pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
  556. pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
  557. DBDATACONVERT_SETDATABEHAVIOR);
  558. if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
  559. {
  560. *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  561. }
  562. }
  563. else
  564. if(bUseDataConvert == FALSE && pSrc != NULL)
  565. {
  566. // Call this function to get the array in the destination address
  567. hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus);
  568. if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  569. {
  570. *pdwDstLength = 0;
  571. dwErrorCount++;
  572. }
  573. }
  574. else
  575. {
  576. pDst = NULL;
  577. *pdwDstLength = 0;
  578. *pdwDstStatus = DBSTATUS_S_ISNULL;
  579. }
  580. if( SUCCEEDED(hr))
  581. {
  582. if(pDst != NULL && dwDstType == VT_BSTR)
  583. {
  584. pTemp = *(BSTR **)pDst;
  585. }
  586. else
  587. {
  588. pTemp = pDst;
  589. }
  590. }
  591. // If data is modified then
  592. if(hr == S_OK && (map.CompareData(dwDstType,pColumnData->pbData,pTemp) == FALSE)
  593. && !( pColumnData->pbData == NULL && *pdwDstLength == 0))
  594. {
  595. // Release the previous data
  596. pColumnData->ReleaseColumnData();
  597. // If no data is there in the column ie. data i null then
  598. if(*pdwDstLength > 0)
  599. {
  600. // this variable gets value only if the CIMTYPE is array
  601. lCIMType = -1;
  602. // if the type is array , then get the original CIMTYPE as array type will
  603. // be given out as VT_ARRAY | VT_VARIANT
  604. if(dwDstType & DBTYPE_ARRAY)
  605. {
  606. lCIMType = m_pObj->m_Columns.GetCIMType(icol);
  607. }
  608. if(dwDstType == VT_BSTR)
  609. {
  610. pTemp = *(BSTR **)pDst;
  611. }
  612. else
  613. {
  614. pTemp = pDst;
  615. }
  616. // Convert the new data to Variant , THis function returns the status if not
  617. // able to conver the data
  618. hr = dataMap.MapAndConvertOLEDBTypeToCIMType(dwDstType,pTemp,*pdwDstLength,*pvarData,lCIMType);
  619. }
  620. if( SUCCEEDED(hr))
  621. {
  622. // Set the data
  623. if( S_OK == (hr = pColumnData->SetData(cvarData,dwDstType)))
  624. {
  625. cColChanged++;
  626. }
  627. // Set the data to modified
  628. pColumnData->dwStatus |= COLUMNSTAT_MODIFIED;
  629. cvarData.Clear();
  630. }
  631. else
  632. {
  633. // Set the data to modified
  634. *pdwDstStatus |= hr;
  635. }
  636. }
  637. SAFE_DELETE_ARRAY(pDst);
  638. if (FAILED(hr)){
  639. dwErrorCount++; // rounding or truncation or can't coerce
  640. }
  641. hr = S_OK;
  642. }
  643. // If the number of errors is equal or greater than
  644. // the number of bindings and the error is only
  645. // due to the readonly attribute of every column then
  646. // set the error
  647. if(cColChanged == 0)
  648. {
  649. hr = NOCOLSCHANGED;
  650. }
  651. else
  652. {
  653. hr = dwErrorCount ? DB_S_ERRORSOCCURRED : S_OK ;
  654. }
  655. return hr;
  656. }
  657. /////////////////////////////////////////////////////////////////////////////////////////////
  658. // Function to validate the arguments
  659. /////////////////////////////////////////////////////////////////////////////////////////////
  660. STDMETHODIMP CImpIRowsetChange::ValidateArguments( HROW hRow,
  661. HACCESSOR hAccessor,
  662. const void *pData,
  663. PROWBUFF *pprowbuff,
  664. PACCESSOR *ppkgaccessor)
  665. {
  666. HRESULT hr = S_OK;
  667. // NTRaid:111831 - 111832
  668. // 06/07/00
  669. PROWBUFF pRowBuff = NULL ;
  670. PACCESSOR pAccessor = NULL;
  671. //========================================================
  672. // Check if the row exists
  673. //========================================================
  674. if(FALSE == m_pObj->IsRowExists(hRow))
  675. {
  676. hr = DB_E_BADROWHANDLE;
  677. }
  678. else
  679. {
  680. //============================================================================
  681. // Row is fetched but data is not yet fetched??
  682. //============================================================================
  683. if ( m_pObj->IsSlotSet(hRow) != S_OK )
  684. {
  685. hr = m_pObj->GetData(hRow);
  686. if(FAILED(hr))
  687. {
  688. hr = DB_E_BADROWHANDLE ;
  689. }
  690. }
  691. if (SUCCEEDED(hr) && m_pObj->m_pIAccessor->GetAccessorPtr() == NULL ||
  692. FAILED( m_pObj->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &pAccessor)) ||
  693. pAccessor == NULL ){
  694. //========================================================================
  695. // Check the Accessor Handle
  696. //========================================================================
  697. return DB_E_BADACCESSORHANDLE ;
  698. }
  699. if(SUCCEEDED(hr))
  700. {
  701. assert( pAccessor );
  702. //============================================================================
  703. // Check to see if it is a row accessor
  704. //============================================================================
  705. if ( !((pAccessor)->dwAccessorFlags & DBACCESSOR_ROWDATA) )
  706. {
  707. hr = DB_E_BADACCESSORTYPE;
  708. }
  709. else if ( pData == NULL){
  710. //============================================================================
  711. // Ensure a source of data.
  712. //============================================================================
  713. hr = E_INVALIDARG;
  714. }
  715. else
  716. {
  717. pRowBuff = m_pObj->GetRowBuff((ULONG) hRow, TRUE );
  718. }
  719. }
  720. }
  721. if(pprowbuff != NULL)
  722. {
  723. *pprowbuff = pRowBuff;
  724. }
  725. if(ppkgaccessor != NULL)
  726. {
  727. *ppkgaccessor = pAccessor;
  728. }
  729. return hr;
  730. }
  731. /////////////////////////////////////////////////////////////////////////////////////////////
  732. // Function with compares dat of a particular type and checks whether both are same or not
  733. /////////////////////////////////////////////////////////////////////////////////////////////
  734. BOOL CImpIRowsetChange::CompareData(DBTYPE dwType,void * pData1 , void *pData2)
  735. {
  736. BOOL bRet = FALSE;
  737. long lType = VT_NULL;
  738. if(pData1 == NULL || pData2 == NULL)
  739. {
  740. if(pData1 == pData2)
  741. {
  742. bRet = TRUE;
  743. }
  744. }
  745. if(bRet == FALSE)
  746. {
  747. // If the type is of some array
  748. if (dwType & VT_ARRAY)
  749. {
  750. lType = VT_ARRAY;
  751. }
  752. else
  753. {
  754. lType = dwType;
  755. }
  756. switch( lType ){
  757. case VT_NULL:
  758. case VT_EMPTY:
  759. bRet = TRUE;
  760. break;
  761. case CIM_FLAG_ARRAY:
  762. bRet = FALSE;
  763. break;
  764. case CIM_SINT8:
  765. case CIM_UINT8:
  766. if(!memcmp(pData1,pData2,1))
  767. bRet = TRUE;
  768. break;
  769. case CIM_CHAR16:
  770. case CIM_SINT16:
  771. case CIM_UINT16:
  772. case CIM_BOOLEAN:
  773. if(!memcmp(pData1,pData2,2))
  774. bRet = TRUE;
  775. break;
  776. case CIM_SINT32:
  777. case CIM_UINT32:
  778. case CIM_REAL32:
  779. if(!memcmp(pData1,pData2,4))
  780. bRet = TRUE;
  781. break;
  782. case CIM_SINT64:
  783. case CIM_UINT64:
  784. case CIM_REAL64:
  785. case CIM_DATETIME:
  786. if(!memcmp(pData1,pData2,8))
  787. bRet = TRUE;
  788. break;
  789. case CIM_STRING:
  790. if( pData1 != NULL && pData2 != NULL)
  791. {
  792. if(!_wcsicmp((WCHAR *)pData1,(WCHAR *)pData2))
  793. bRet = TRUE;
  794. }
  795. break;
  796. case CIM_REFERENCE:
  797. break;
  798. case CIM_OBJECT:
  799. break;
  800. case VT_VARIANT:
  801. break;
  802. default:
  803. assert( !"Unmatched OLEDB Data Type to CIMTYPE." );
  804. }
  805. }
  806. return bRet;
  807. }
  808. HRESULT CImpIRowsetChange::UpdateDataToRowBuffer(DBCOUNTITEM ibind,BYTE * pbProvRow,DBBINDING* pBinding,BYTE *pData)
  809. {
  810. //====================================================
  811. // Initialize values
  812. //====================================================
  813. HRESULT hr = S_OK;
  814. DBORDINAL icol = 0;
  815. DBTYPE dwSrcType = 0;
  816. DBTYPE dwDstType = 0;
  817. void* pSrc = NULL;
  818. void* pDst = NULL;
  819. void* pTemp = NULL;
  820. DBLENGTH dwSrcLength = 0;
  821. DBLENGTH* pdwDstLength = 0;
  822. DBLENGTH dwDstMaxLength = 0;
  823. DWORD dwSrcStatus = 0;
  824. DWORD* pdwDstStatus = 0;
  825. DWORD dwPart = 0;
  826. PCOLUMNDATA pColumnData = NULL;
  827. BYTE b = 0;
  828. VARIANT* pvarData = NULL;
  829. BSTR strPropName = Wmioledb_SysAllocString(NULL);
  830. BOOL bUseDataConvert = TRUE;
  831. DWORD dwCIMType = 0;
  832. CVARIANT cvarData;
  833. CDataMap dataMap;
  834. pvarData = &cvarData;
  835. icol = pBinding[ibind].iOrdinal;
  836. pColumnData = (COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(icol));
  837. dwSrcType = pBinding[ibind].wType;
  838. pDst = &(pColumnData->pbData);
  839. pdwDstLength = &(pColumnData->dwLength);
  840. pdwDstStatus = &(pColumnData->dwStatus);
  841. dwDstMaxLength = pBinding[ibind].cbMaxLen;
  842. dwPart = pBinding[ibind].dwPart;
  843. // If the column is value then get the type of the col is given by the
  844. // qualifier type column
  845. if(( m_pObj->m_uRsType == PROPERTYQUALIFIER || m_pObj->m_uRsType == CLASSQUALIFIER) &&
  846. pBinding[ibind].iOrdinal == QUALIFIERVALCOL )
  847. {
  848. dwDstType = *(DBTYPE *)((COLUMNDATA *) (pbProvRow + m_pObj->m_Columns.GetDataOffset(QUALIFIERTYPECOL)))->pbData;
  849. pColumnData->dwType = VT_VARIANT;
  850. }
  851. else
  852. {
  853. dwDstType = m_pObj->m_Columns.ColumnType(icol);
  854. pColumnData->dwType = dwDstType;
  855. }
  856. if ((dwPart & DBPART_VALUE) == 0)
  857. {
  858. if (((dwPart & DBPART_STATUS)
  859. && (*(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) & DBSTATUS_S_ISNULL))
  860. || ((dwPart & DBPART_LENGTH) && *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) == 0))
  861. {
  862. pSrc = &b;
  863. b = 0x00;
  864. }
  865. else
  866. {
  867. if ( dwPart & DBPART_STATUS )
  868. {
  869. *(DBSTATUS *) ((BYTE*) pData + pBinding[ibind].obStatus) = DBSTATUS_E_UNAVAILABLE;
  870. }
  871. hr = E_FAIL;
  872. }
  873. }
  874. else
  875. {
  876. pSrc = (void *) ((BYTE*) pData + pBinding[ibind].obValue);
  877. }
  878. if(SUCCEEDED(hr))
  879. {
  880. dwSrcLength = (dwPart & DBPART_LENGTH) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : 0;
  881. dwSrcStatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : DBSTATUS_S_OK;
  882. if(!( dwSrcType == DBTYPE_HCHAPTER || dwDstType == DBTYPE_HCHAPTER))
  883. {
  884. strPropName = Wmioledb_SysAllocString(m_pObj->m_Columns.ColumnName(icol));
  885. //==========================================================================
  886. // if the columnd is a system property then set it to readonly
  887. //==========================================================================
  888. if(TRUE == m_pObj->m_pMap->IsSystemProperty(strPropName))
  889. {
  890. SysFreeString(strPropName);
  891. pColumnData->dwStatus = DBSTATUS_E_READONLY;
  892. hr = E_FAIL;
  893. }
  894. else
  895. {
  896. SysFreeString(strPropName);
  897. // Get the conversion size for the column
  898. if(SUCCEEDED(hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &dwSrcLength, pdwDstLength, pSrc)))
  899. {
  900. hr = E_OUTOFMEMORY;
  901. try
  902. {
  903. pDst = new BYTE[*pdwDstLength];
  904. }
  905. catch(...)
  906. {
  907. SAFE_DELETE_ARRAY(pDst);
  908. throw;
  909. }
  910. if(pDst)
  911. {
  912. hr = S_OK;
  913. // if both the source and destination type is array then don't
  914. // use IDataConvert::DataConvert for conversion
  915. if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
  916. {
  917. bUseDataConvert = FALSE;
  918. }
  919. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  920. {
  921. // Convert the data to the type which can be update to WBEM
  922. hr = g_pIDataConvert->DataConvert( dwSrcType, dwDstType, dwSrcLength, pdwDstLength, pSrc,
  923. pDst, dwDstMaxLength, dwSrcStatus, pdwDstStatus,
  924. pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
  925. pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
  926. DBDATACONVERT_SETDATABEHAVIOR);
  927. if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
  928. {
  929. *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  930. }
  931. }
  932. else
  933. if(bUseDataConvert == FALSE && pSrc != NULL)
  934. {
  935. // Call this function to get the array in the destination address
  936. hr = dataMap.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus);
  937. if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE || FAILED(hr))
  938. {
  939. *pdwDstLength = 0;
  940. hr = E_FAIL;
  941. }
  942. }
  943. else
  944. {
  945. pDst = NULL;
  946. *pdwDstLength = 0;
  947. *pdwDstStatus = DBSTATUS_S_ISNULL;
  948. }
  949. if (SUCCEEDED(hr))
  950. {
  951. if(pDst != NULL && pColumnData->dwType == VT_BSTR)
  952. {
  953. pTemp = *(BSTR **)pDst;
  954. }
  955. else
  956. {
  957. pTemp = pDst;
  958. }
  959. // If no data is there in the column ie. data i null then
  960. if(*pdwDstLength > 0)
  961. {
  962. // this variable gets value only if the CIMTYPE is array
  963. dwCIMType = -1;
  964. // if the type is array , then get the original CIMTYPE as array type will
  965. // be given out as VT_ARRAY | VT_VARIANT
  966. if(pColumnData->dwType & DBTYPE_ARRAY)
  967. {
  968. dwCIMType = m_pObj->m_Columns.GetCIMType(icol);
  969. }
  970. if(pColumnData->dwType == VT_BSTR)
  971. {
  972. pTemp = *(BSTR **)pDst;
  973. }
  974. else
  975. {
  976. pTemp = pDst;
  977. }
  978. // Convert the new data to Variant, this function return DBSTATUS if
  979. // not able to convert
  980. hr = dataMap.MapAndConvertOLEDBTypeToCIMType(dwDstType,pTemp,*pdwDstLength,*pvarData,dwCIMType);
  981. }
  982. if(SUCCEEDED(hr))
  983. {
  984. // Set the data
  985. hr = pColumnData->SetData(cvarData,pColumnData->dwType);
  986. }
  987. else
  988. {
  989. pColumnData->dwStatus |= hr;
  990. }
  991. if (SUCCEEDED(hr))
  992. {
  993. // Set the data to modified
  994. pColumnData->dwStatus |= COLUMNSTAT_MODIFIED;
  995. }
  996. cvarData.Clear();
  997. }
  998. } // if (pDst)
  999. } // IF succeeded(getting conversion size)
  1000. } // if valid property name
  1001. } // if the column in not a chapter
  1002. }
  1003. SAFE_DELETE_ARRAY(pDst);
  1004. return hr;
  1005. }
  1006. BOOL CImpIRowsetChange::IsNullAccessor(PACCESSOR phAccessor,BYTE * pData )
  1007. {
  1008. BOOL bNullAccessor = TRUE;
  1009. DWORD dwPart = 0;
  1010. DWORD dwStatatus = 0;
  1011. if(phAccessor->cBindings)
  1012. {
  1013. for(DBORDINAL cBinding = 0 ; cBinding < phAccessor->cBindings ; cBinding++)
  1014. {
  1015. dwPart = phAccessor->rgBindings[cBinding].dwPart;
  1016. dwStatatus = (dwPart & DBPART_STATUS) ? *(ULONG *) ((BYTE*) pData + phAccessor->rgBindings[cBinding].obStatus) : DBSTATUS_S_OK;
  1017. if(dwStatatus != DBSTATUS_S_IGNORE)
  1018. {
  1019. bNullAccessor = FALSE;
  1020. break;
  1021. }
  1022. }
  1023. }
  1024. return bNullAccessor;
  1025. }
  1026. HRESULT CImpIRowsetChange::InsertNewRow(HROW hRow, HCHAPTER hChapter,CWbemClassWrapper *& pNewInst)
  1027. {
  1028. HRESULT hr = S_OK;
  1029. BSTR strKey = NULL;
  1030. //==========================
  1031. // Carry out the insert.
  1032. // Set the RowHandle
  1033. //==========================
  1034. if(SUCCEEDED(hr = m_pObj->InsertNewRow(&pNewInst)))
  1035. {
  1036. //===========================================================================
  1037. // if there is atleast one row retrieved and there are neseted columns
  1038. // then allocate rows for the child recordsets
  1039. //===========================================================================
  1040. if(m_pObj->m_cNestedCols > 0 )
  1041. {
  1042. if(m_pObj->m_ppChildRowsets == NULL)
  1043. m_pObj->AllocateAndInitializeChildRowsets();
  1044. //=====================================================================
  1045. // Fill the HCHAPTERS for the column
  1046. //=====================================================================
  1047. hr = m_pObj->FillHChaptersForRow(pNewInst,strKey);
  1048. }
  1049. if(SUCCEEDED(hr))
  1050. {
  1051. //===================================================
  1052. // if the class is not representing qualilfiers
  1053. //===================================================
  1054. if(m_pObj->m_bIsChildRs == FALSE)
  1055. {
  1056. //=================================================
  1057. // add instance pointer to instance manager
  1058. //=================================================
  1059. hr = m_pObj->m_InstMgr->AddInstanceToList(hRow,pNewInst,strKey,hRow);
  1060. }
  1061. //=================================================================================
  1062. // if rowset is refering to qualifiers then add the row to the particular chapter
  1063. //=================================================================================
  1064. else
  1065. {
  1066. // add instance pointer to instance manager
  1067. hr = m_pObj->m_pChapterMgr->AddHRowForChapter(hChapter,hRow, NULL ,hRow);
  1068. }
  1069. }
  1070. }
  1071. return hr;
  1072. }