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.

3180 lines
90 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // CRow object implementation
  7. //
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "WmiOleDBMap.h"
  12. #define PATHSEPARATOR L"/"
  13. /////////////////////////////////////////////////////////////////////////////////////////////////
  14. // Constructor for this class
  15. /////////////////////////////////////////////////////////////////////////////////////////////////
  16. CRow::CRow(LPUNKNOWN pUnkOuter,CRowset *pRowset,PCDBSESSION pObj,CWbemConnectionWrapper *pCon ) : CBaseRowObj(pUnkOuter)
  17. {
  18. InitVars();
  19. m_pMap = pRowset->GetWmiOleDBMap();
  20. m_pMap->AddRef();
  21. m_pUtilProp = pRowset->m_pUtilProp;
  22. m_pCreator = pObj;
  23. m_pSourcesRowset = pRowset;
  24. m_pSourcesRowset->AddRef();
  25. m_pCreator->GetOuterUnknown()->AddRef();
  26. //===============================================
  27. // Add this rowset ot list of open rowset
  28. //===============================================
  29. m_pCreator->AddRowset(this);
  30. pRowset->QueryInterface(IID_IConvertType, (void **)&m_pIConvertType);
  31. m_pCon = pCon;
  32. InterlockedIncrement(&g_cObj);
  33. }
  34. /////////////////////////////////////////////////////////////////////////////////////////////////
  35. // Constructor for this class. This is called from the root binder object
  36. /////////////////////////////////////////////////////////////////////////////////////////////////
  37. CRow::CRow(LPUNKNOWN pUnkOuter, PCDBSESSION pObj ) : CBaseRowObj(pUnkOuter)
  38. {
  39. InitVars();
  40. m_pCreator = pObj;
  41. m_pSourcesRowset = NULL;
  42. m_pCreator->GetOuterUnknown()->AddRef();
  43. //===============================================
  44. // Add this rowset ot list of open rowset
  45. //===============================================
  46. m_pCreator->AddRowset(this);
  47. InterlockedIncrement(&g_cObj);
  48. }
  49. void CRow::InitVars()
  50. {
  51. m_pMap = NULL;
  52. m_pUtilProp = NULL;
  53. m_pCreator = NULL;
  54. m_pSourcesRowset = NULL;
  55. m_pRowData = NULL;
  56. m_pIBuffer = NULL;
  57. m_strURL = NULL;
  58. m_strKey = NULL;
  59. m_rgbRowData = NULL;
  60. m_pRowColumns = NULL;
  61. m_pInstance = NULL;
  62. m_pIColumnsInfo = NULL;
  63. m_pIRow = NULL;
  64. m_pIConvertType = NULL;
  65. m_pIGetSession = NULL;
  66. m_pIRowChange = NULL;
  67. m_pIScopedOperations = NULL;
  68. m_cTotalCols = 0;
  69. m_cCols = 0;
  70. m_cNestedCols = 0;
  71. m_cRef = 0;
  72. m_cbRowSize = 0;
  73. m_ulProps = 0;
  74. m_hRow = 0;
  75. m_dwStatus = 0;
  76. m_bHelperFunctionCreated = FALSE;
  77. m_bClassChanged = FALSE;
  78. m_rowType = ROW_INSTANCE;
  79. }
  80. /////////////////////////////////////////////////////////////////////////////////////////////////
  81. // Destructor for this class
  82. /////////////////////////////////////////////////////////////////////////////////////////////////
  83. CRow::~CRow()
  84. {
  85. if (NULL != m_pIBuffer){
  86. ReleaseSlotList( m_pIBuffer );
  87. }
  88. //===============================================================
  89. // NOTE: m_pMap releases the class ptr in destructor and if
  90. // the reference count goes to 0 then this will released
  91. //===============================================================
  92. m_pMap->Release();
  93. // If the row object is created from a rowset object then release all the interfaces
  94. if(m_pSourcesRowset != NULL)
  95. {
  96. m_pIConvertType->Release();
  97. m_pSourcesRowset->Release();
  98. SAFE_DELETE_PTR(m_pRowColumns);
  99. }
  100. else
  101. {
  102. SAFE_DELETE_PTR( m_pIConvertType );
  103. SAFE_DELETE_PTR( m_pUtilProp );
  104. }
  105. //===============================================================
  106. // Free contained interfaces
  107. //===============================================================
  108. SAFE_DELETE_PTR( m_pIColumnsInfo );
  109. SAFE_DELETE_PTR( m_pIRow );
  110. SAFE_DELETE_PTR( m_pIGetSession );
  111. SAFE_DELETE_PTR( m_pIRowChange );
  112. SAFE_DELETE_PTR(m_pRowData);
  113. SAFE_DELETE_PTR(m_pIScopedOperations);
  114. SAFE_DELETE_PTR(m_pISupportErrorInfo);
  115. /*
  116. if(m_pSourcesRowset == NULL)
  117. {
  118. SAFE_DELETE_PTR(m_pInstance);
  119. }
  120. */
  121. //===============================================================
  122. // Decrement the DBSession Count. GetSpecification is not
  123. // possible anymore
  124. //===============================================================
  125. if( m_pCreator ){
  126. //===========================================================
  127. // Mark the session as not having an open rowset anymore
  128. //===========================================================
  129. m_pCreator->GetOuterUnknown()->Release();
  130. }
  131. SAFE_DELETE_ARRAY(m_strKey);
  132. SAFE_DELETE_ARRAY(m_strURL);
  133. //===============================================================
  134. // Decrement global object count.
  135. //===============================================================
  136. InterlockedDecrement(&g_cObj);
  137. }
  138. /////////////////////////////////////////////////////////////////////////////////////////////////
  139. //
  140. // Returns a pointer to a specified interface. Callers use QueryInterface to determine which
  141. // interfaces the called object supports.
  142. //
  143. // HRESULT indicating the status of the method
  144. // S_OK Interface is supported and ppvObject is set.
  145. // E_NOINTERFACE Interface is not supported by the object
  146. // E_INVALIDARG One or more arguments are invalid.
  147. //
  148. /////////////////////////////////////////////////////////////////////////////////////////////////
  149. STDMETHODIMP CRow::QueryInterface ( REFIID riid, LPVOID * ppv )
  150. {
  151. HRESULT hr = S_OK;
  152. //======================================================
  153. // Check parameters, if not valid return
  154. //======================================================
  155. if (NULL == ppv)
  156. {
  157. hr = E_INVALIDARG ;
  158. }
  159. else
  160. {
  161. //======================================================
  162. // Place NULL in *ppv in case of failure
  163. //======================================================
  164. *ppv = NULL;
  165. //======================================================
  166. // This is the non-delegating IUnknown implementation
  167. //======================================================
  168. if (riid == IID_IUnknown)
  169. {
  170. *ppv = (LPVOID) this;
  171. }
  172. else if (riid == IID_IColumnsInfo)
  173. {
  174. *ppv = (LPVOID) m_pIColumnsInfo;
  175. }
  176. else if (riid == IID_IConvertType)
  177. {
  178. *ppv = (LPVOID) m_pIConvertType;
  179. }
  180. else if (riid == IID_IRow)
  181. {
  182. *ppv = (LPVOID) m_pIRow;
  183. }
  184. else if (riid == IID_IGetSession)
  185. {
  186. *ppv = (LPVOID) m_pIGetSession;
  187. }
  188. else if (riid == IID_IRowChange)
  189. {
  190. *ppv = (LPVOID) m_pIRowChange;
  191. }
  192. else if( riid == IID_ISupportErrorInfo)
  193. {
  194. *ppv = (LPVOID)m_pISupportErrorInfo;
  195. }
  196. else if(riid == IID_IScopedOperations || riid == IID_IBindResource)
  197. {
  198. *ppv = (LPVOID)m_pIScopedOperations;
  199. }
  200. //======================================================
  201. // If we're going to return an interface, AddRef first
  202. //======================================================
  203. if (*ppv){
  204. ((LPUNKNOWN) *ppv)->AddRef();
  205. hr = S_OK ;
  206. }
  207. else{
  208. hr = E_NOINTERFACE;
  209. }
  210. }
  211. return hr;
  212. }
  213. /////////////////////////////////////////////////////////////////////////////////////////////////
  214. //
  215. // Increments a persistence count for the object
  216. //
  217. // Current reference count
  218. //
  219. /////////////////////////////////////////////////////////////////////////////////////////////////
  220. STDMETHODIMP_( ULONG ) CRow::AddRef( void )
  221. {
  222. return InterlockedIncrement((long*)&m_cRef);
  223. }
  224. /////////////////////////////////////////////////////////////////////////////////////////////////
  225. //
  226. // Decrements a persistence count for the object and if persistence count is 0, the object
  227. // destroys itself.
  228. //
  229. /////////////////////////////////////////////////////////////////////////////////////////////////
  230. STDMETHODIMP_( ULONG ) CRow::Release( void )
  231. {
  232. if (!InterlockedDecrement((long*)&m_cRef)){
  233. //===========================================================
  234. // Mark the session as not having an open rowset anymore
  235. //===========================================================
  236. this->m_pCreator->RemoveRowset(this);
  237. // this->m_pCreator->DecRowsetCount();
  238. delete this;
  239. return 0;
  240. }
  241. return m_cRef;
  242. }
  243. /////////////////////////////////////////////////////////////////////////////////////////////////
  244. // The first function called for the row for initialization of the class
  245. /////////////////////////////////////////////////////////////////////////////////////////////////
  246. HRESULT CRow::InitRow(HROW hRow ,
  247. CWbemClassWrapper *pInst ,
  248. ROWCREATEBINDFLAG rowCreateFlag)
  249. {
  250. HRESULT hr = S_OK;
  251. DBCOLUMNINFO * pCol = NULL;
  252. CURLParser urlParser;
  253. m_hRow = hRow;
  254. m_pInstance = (CWbemClassInstanceWrapper *)pInst;
  255. //=================================================
  256. // If the class is not created by the rowset then
  257. //=================================================
  258. if(m_pSourcesRowset == NULL)
  259. {
  260. BSTR strTemp;
  261. strTemp = Wmioledb_SysAllocString(m_strKey);
  262. urlParser.SetPath(strTemp);
  263. SysFreeString(strTemp);
  264. if(urlParser.GetURLType() == URL_EMBEDEDCLASS)
  265. {
  266. GetEmbededInstancePtrAndSetMapClass(&urlParser);
  267. }
  268. else
  269. {
  270. VARIANT varDataSrc;
  271. VariantInit(&varDataSrc);
  272. m_pInstance = NULL;
  273. strTemp = Wmioledb_SysAllocString(m_strKey);
  274. // If the object path is same as the data src then the object has
  275. // to be obtained by just QI on the IWbemServicesEx pointer
  276. if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_INIT_DATASOURCE , varDataSrc)) &&
  277. varDataSrc.vt == VT_BSTR && varDataSrc.bstrVal != NULL)
  278. {
  279. if(_wcsicmp(m_strKey,varDataSrc.bstrVal) == 0)
  280. {
  281. SAFE_FREE_SYSSTRING(strTemp);
  282. }
  283. }
  284. m_pInstance = (CWbemClassInstanceWrapper *)m_pMap->GetInstance(strTemp);
  285. SysFreeString(strTemp);
  286. }
  287. urlParser.GetURL(strTemp);
  288. m_strURL = new WCHAR[SysStringLen(strTemp) + 1];
  289. // NTRaid:111801
  290. // 06/07/00
  291. if(m_strURL)
  292. {
  293. memset(m_strURL,0,(SysStringLen(strTemp) + 1) * sizeof(WCHAR));
  294. memcpy(m_strURL,strTemp,SysStringLen(strTemp) * sizeof(WCHAR));
  295. if( rowCreateFlag == ROWCREATE && m_pInstance != NULL)
  296. {
  297. hr = DB_E_RESOURCEEXISTS;
  298. }
  299. else
  300. {
  301. //=================================================
  302. // If an existing instance is to be created
  303. //=================================================
  304. if( rowCreateFlag == ROWCREATE || rowCreateFlag == ROWOVERWRITE )
  305. {
  306. //======================================================
  307. // If instance already exists then delete the instance
  308. //======================================================
  309. if( m_pInstance != NULL)
  310. {
  311. m_pMap->DeleteInstance(m_pInstance);
  312. m_pInstance = NULL;
  313. }
  314. //===========================
  315. // Create instance
  316. //===========================
  317. hr = CreateNewRow(&m_pInstance);
  318. }
  319. //=================================================================
  320. // If instance is pointed by the path is not found return error
  321. //=================================================================
  322. if( m_pInstance == NULL)
  323. {
  324. hr = DB_E_NOTFOUND;
  325. }
  326. else
  327. {
  328. /* //====================================================================
  329. /// Get property and Set Serach Preferences
  330. //====================================================================
  331. hr = SetSearchPreferences();
  332. //===================================================================================
  333. // Get the column information
  334. //===================================================================================
  335. if(SUCCEEDED(hr = CBaseRowObj::GetColumnInfo()))
  336. {
  337. m_cTotalCols--; // Decrementing so as not to take into account the bookmark column
  338. //===========================================================================
  339. // Initialize the columns representing the qualifiers and embeded classes
  340. //===========================================================================
  341. if(m_cNestedCols > 0)
  342. for ( int iCol = 1 ; iCol < (int)m_Columns.GetTotalNumberOfColumns(); iCol++)
  343. {
  344. pCol = m_Columns.GetColInfo(iCol);
  345. if( pCol->wType == DBTYPE_HCHAPTER)
  346. {
  347. pCol->wType = DBTYPE_UI4;
  348. pCol->ulColumnSize = sizeof(ULONG);
  349. pCol->dwFlags = DBCOLUMNFLAGS_ISCOLLECTION;
  350. }
  351. }
  352. } // Succeeded(GetCOlumnInfo())
  353. */
  354. hr = S_OK;
  355. } // Else if instance pointed by path not found
  356. } // else of if( rowCreateFlag == ROWCREATE && m_pInstance != NULL)
  357. } // if(m_strUrl)
  358. else
  359. {
  360. hr = E_OUTOFMEMORY;
  361. }
  362. }
  363. else
  364. {
  365. CBSTR strTemp;
  366. if(SUCCEEDED(hr = ((CWbemClassInstanceWrapper *)pInst)->GetKey(strTemp)))
  367. {
  368. m_strKey = new WCHAR [ SysStringLen(strTemp) + 1];
  369. wcscpy(m_strKey,strTemp);
  370. urlParser.SetPath(strTemp);
  371. strTemp.Clear();
  372. strTemp.Unbind();
  373. urlParser.GetURL((BSTR &)strTemp);
  374. m_strURL = new WCHAR[ SysStringLen(strTemp) + 1];
  375. memset(m_strURL,0,(SysStringLen(strTemp) + 1) * sizeof(WCHAR));
  376. memcpy(m_strURL,strTemp,SysStringLen(strTemp) * sizeof(WCHAR));
  377. }
  378. }
  379. if(SUCCEEDED(hr))
  380. {
  381. //===========================================================================
  382. // Call this function to allocate memory for all the contained interfaces
  383. // and utility classes
  384. //===========================================================================
  385. if(SUCCEEDED(hr = AllocateInterfacePointers()))
  386. {
  387. if(m_pSourcesRowset != NULL)
  388. {
  389. m_cTotalCols = m_pSourcesRowset->m_Columns.GetTotalNumberOfColumns();
  390. hr = GetRowColumnInfo();
  391. }
  392. else
  393. {
  394. //====================================================================
  395. /// Get property and Set Serach Preferences
  396. //====================================================================
  397. hr = SetSearchPreferences();
  398. //===================================================================================
  399. // Get the column information
  400. //===================================================================================
  401. if(SUCCEEDED(hr = CBaseRowObj::GetColumnInfo()))
  402. {
  403. m_cTotalCols--; // Decrementing so as not to take into account the bookmark column
  404. //===========================================================================
  405. // Initialize the columns representing the qualifiers and embeded classes
  406. //===========================================================================
  407. if(m_cNestedCols > 0)
  408. for ( int iCol = 1 ; iCol < (int)m_Columns.GetTotalNumberOfColumns(); iCol++)
  409. {
  410. pCol = m_Columns.GetColInfo(iCol);
  411. if( pCol->wType == DBTYPE_HCHAPTER)
  412. {
  413. pCol->wType = DBTYPE_UI4;
  414. pCol->ulColumnSize = sizeof(ULONG);
  415. pCol->dwFlags = DBCOLUMNFLAGS_ISCOLLECTION | DBCOLUMNFLAGS_ISCHAPTER;
  416. }
  417. }
  418. } // Succeeded(GetCOlumnInfo())
  419. m_pRowColumns = &m_Columns;
  420. }
  421. } // if Succeeded(hr)
  422. } // If Succeeded(hr)
  423. if(SUCCEEDED(hr))
  424. {
  425. //==========================================================
  426. // Call this function to initialize the ISupportErrorInfo;
  427. //==========================================================
  428. hr = AddInterfacesForISupportErrorInfo();
  429. }
  430. return hr;
  431. }
  432. /////////////////////////////////////////////////////////////////////////////////////////////////
  433. // This first function called for the row for initialization of the class when a row is
  434. // not created from rowset object
  435. // An overloaded function
  436. /////////////////////////////////////////////////////////////////////////////////////////////////
  437. HRESULT CRow::InitRow(LPWSTR strPath,
  438. LPWSTR strTableID ,
  439. DWORD dwFlags,
  440. ROWCREATEBINDFLAG rowCreateFlag)
  441. {
  442. HRESULT hr = S_OK;
  443. //=========================================================
  444. // Call this function to Initialize and allocate WMIOledb
  445. //=========================================================
  446. hr = InitializeWmiOledbMap(strPath,strTableID,dwFlags);
  447. if( SUCCEEDED(hr))
  448. {
  449. hr = InitRow(0,0,rowCreateFlag);
  450. }
  451. return hr;
  452. }
  453. ////////////////////////////////////////////////////////////////////////////////////////////
  454. // Function to allocate contained interface pointers and also some utility classes
  455. ////////////////////////////////////////////////////////////////////////////////////////////
  456. HRESULT CRow::AllocateInterfacePointers()
  457. {
  458. HRESULT hr = S_OK;
  459. if(m_pSourcesRowset == NULL)
  460. {
  461. m_pIConvertType = new CImpIConvertType(this);
  462. m_pUtilProp = new CUtilProp;
  463. // NTRaid: 136443
  464. // 07/05/00
  465. if(m_pUtilProp)
  466. {
  467. hr = m_pUtilProp->FInit(ROWSETPROP);
  468. }
  469. else
  470. {
  471. hr = E_OUTOFMEMORY;
  472. }
  473. }
  474. //=========================================================================
  475. // if row is created from a rowset then create a columninfo manager
  476. // instance , passing the source rowset as a parameter to constructor
  477. //=========================================================================
  478. else
  479. {
  480. m_pRowColumns = new cRowColumnInfoMemMgr(&m_pSourcesRowset->m_Columns);
  481. }
  482. if(SUCCEEDED(hr))
  483. {
  484. m_pIColumnsInfo = new CImpIColumnsInfo( this );
  485. m_pIRow = new CImpIRow( this );
  486. m_pIGetSession = new CImpIGetSession( this );
  487. m_pIRowChange = new CImpIRowChange( this );
  488. m_pISupportErrorInfo = new CImpISupportErrorInfo(this);
  489. m_pIScopedOperations = new CImpIScopedOperations(this);
  490. if( ! (m_pIColumnsInfo && m_pUtilProp && m_pIRow && m_pIGetSession && m_pIRowChange && m_pIConvertType && m_pIScopedOperations))
  491. {
  492. hr = E_OUTOFMEMORY;
  493. }
  494. }
  495. return hr;
  496. }
  497. ////////////////////////////////////////////////////////////////////////////////////////////
  498. // Function to allocate CWmiOledbMap class if row is not created from rowset
  499. ////////////////////////////////////////////////////////////////////////////////////////////
  500. HRESULT CRow::InitializeWmiOledbMap(LPWSTR strPath,
  501. LPWSTR strTableID ,
  502. DWORD dwFlags)
  503. {
  504. HRESULT hr = S_OK;
  505. assert(m_pSourcesRowset == NULL);
  506. CURLParser urlParser;
  507. CBSTR strTemp;
  508. if(strPath == NULL )
  509. {
  510. hr = E_INVALIDARG;
  511. }
  512. else
  513. {
  514. LONG lObjectType = -1;
  515. strTemp.SetStr(strPath);
  516. urlParser.SetPath(strTemp);
  517. lObjectType = urlParser.GetURLType();
  518. if(lObjectType == URL_DATASOURCE && strTableID == NULL)
  519. {
  520. hr = E_INVALIDARG;
  521. }
  522. if(lObjectType == URL_DATASOURCE) // or scope
  523. {
  524. m_rowType = ROW_SCOPE;
  525. }
  526. }
  527. if(SUCCEEDED(hr))
  528. {
  529. dwFlags = dwFlags == -1 ? GetQualifierFlags(): dwFlags;
  530. if(m_rowType == ROW_SCOPE) // this happenes only the opened scope is a namespace
  531. {
  532. /*// m_pMap = new CWmiOleDBMap( strPath,
  533. // m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
  534. if(m_pMap)
  535. {
  536. // hr = m_pMap->FInit( strPath,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
  537. }
  538. else
  539. {
  540. hr = E_OUTOFMEMORY;
  541. }
  542. */ }
  543. else
  544. {
  545. m_pMap = new CWmiOleDBMap;
  546. if(m_pMap)
  547. {
  548. hr = m_pMap->FInit(dwFlags,strTableID,m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon);
  549. }
  550. else
  551. {
  552. hr = E_OUTOFMEMORY;
  553. }
  554. }
  555. if(SUCCEEDED(hr))
  556. {
  557. VARIANT varValue;
  558. VariantInit(&varValue);
  559. // Bug which not able to get system properties from Row object
  560. // NTRaid: 145684
  561. // 05/06/00
  562. //===========================================================================================
  563. // Get the DataSource property to check if system Properties is to be fetched?
  564. //===========================================================================================
  565. if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_SYSTEMPROPERTIES,varValue)))
  566. {
  567. if( varValue.boolVal == VARIANT_TRUE)
  568. {
  569. m_pMap->SetSytemPropertiesFlag(TRUE);
  570. }
  571. m_strKey = new WCHAR [wcslen(strPath) + 1];
  572. if(m_strKey == NULL)
  573. {
  574. hr = E_OUTOFMEMORY;
  575. }
  576. else
  577. {
  578. wcscpy(m_strKey,strPath);
  579. m_pMap->AddRef();
  580. }
  581. }
  582. VariantClear(&varValue);
  583. }
  584. }
  585. return hr;
  586. }
  587. /////////////////////////////////////////////////////////////////////////////////////////////////////
  588. // Function to add interfaces to ISupportErrorInfo interface
  589. /////////////////////////////////////////////////////////////////////////////////////////////////////
  590. HRESULT CRow::AddInterfacesForISupportErrorInfo()
  591. {
  592. HRESULT hr = S_OK;
  593. if( SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IColumnsInfo)) &&
  594. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IConvertType)) &&
  595. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IGetSession)) &&
  596. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRowChange)) &&
  597. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IScopedOperations)) &&
  598. SUCCEEDED(hr = m_pISupportErrorInfo->AddInterfaceID(IID_IBindResource)))
  599. {
  600. hr = m_pISupportErrorInfo->AddInterfaceID(IID_IRow);
  601. }
  602. return hr;
  603. }
  604. /////////////////////////////////////////////////////////////////////////////////////////////////
  605. // Function to the get the value of the columns requested
  606. /////////////////////////////////////////////////////////////////////////////////////////////////
  607. HRESULT CRow::GetColumns(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
  608. {
  609. HRESULT hr = E_FAIL;
  610. for( ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
  611. {
  612. //=============================================
  613. // Initialize the output memeber variables
  614. //=============================================
  615. rgColumns[lIndex].cbDataLen = 0;
  616. rgColumns[lIndex].dwStatus = DBSTATUS_S_OK;
  617. }
  618. //======================================================
  619. // if the row object is created by the rowset then
  620. // get the data maintained by the rowset object
  621. //======================================================
  622. if(m_pSourcesRowset != NULL)
  623. {
  624. hr = GetColumnsFromRowset(cColumns,rgColumns);
  625. }
  626. else
  627. {
  628. /// Get data for the requested columns
  629. hr = GetRowData(cColumns,rgColumns);
  630. }
  631. return hr;
  632. }
  633. /////////////////////////////////////////////////////////////////////////////////////////////////
  634. // Function to the get the value of the columns when row object is created from rowset
  635. /////////////////////////////////////////////////////////////////////////////////////////////////
  636. HRESULT CRow::GetColumnsFromRowset(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
  637. {
  638. DBORDINAL icol;
  639. ROWBUFF *pRowBuff;
  640. COLUMNDATA *pColumnData;
  641. DBCOUNTITEM ulErrorCount = 0;
  642. DBTYPE dwSrcType;
  643. DBTYPE dwDstType;
  644. void *pSrc;
  645. void *pDst;
  646. DBLENGTH ulSrcLength;
  647. DBLENGTH *pulDstLength;
  648. DBLENGTH ulDstMaxLength;
  649. DBSTATUS dwSrcStatus;
  650. DBSTATUS *pdwDstStatus;
  651. HRESULT hr = S_OK;
  652. DBSTATUS dwStatus = DBSTATUS_S_OK;
  653. CDataMap dataMap;
  654. BOOL bUseDataConvert = TRUE;
  655. VARIANT varValue;
  656. VariantInit(&varValue);
  657. //=========================================================
  658. // Check if the row is already deleted
  659. //=========================================================
  660. dwStatus = m_pSourcesRowset->GetRowStatus(m_hRow);
  661. if( dwStatus != DBROWSTATUS_S_OK)
  662. {
  663. if(dwStatus == DBROWSTATUS_E_DELETED)
  664. {
  665. hr = DB_E_DELETEDROW;
  666. }
  667. else
  668. {
  669. hr = E_FAIL;
  670. }
  671. }
  672. if( SUCCEEDED(hr))
  673. {
  674. //=========================================================
  675. // if data is not yet received then fetch the data
  676. //=========================================================
  677. if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
  678. {
  679. hr = m_pSourcesRowset->GetData(m_hRow);
  680. }
  681. if(SUCCEEDED(hr))
  682. {
  683. if( (m_pSourcesRowset->m_ulProps & OTHERUPDATEDELETE) &&(m_pSourcesRowset->m_ulLastFetchedRow != m_hRow))
  684. {
  685. if(SUCCEEDED(hr = m_pSourcesRowset->GetDataToLocalBuffer(m_hRow)))
  686. {
  687. m_pSourcesRowset->m_ulLastFetchedRow = m_hRow;
  688. }
  689. }
  690. if(SUCCEEDED(hr))
  691. {
  692. //=========================================================
  693. // Get the pointer to the rowbuffer
  694. //=========================================================
  695. pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
  696. assert(pRowBuff != NULL);
  697. // Navigate for each requested column
  698. for( ULONG lIndex = 0 ; lIndex < cColumns ; lIndex++)
  699. {
  700. bUseDataConvert = TRUE;
  701. // if the column is a bookmark then continue without doing anything
  702. if(rgColumns[lIndex].columnid.eKind == DBKIND_GUID_PROPID &&
  703. rgColumns[lIndex].columnid.uGuid.guid == DBCOL_SPECIALCOL &&
  704. rgColumns[lIndex].columnid.uName.ulPropid >= 2)
  705. {
  706. if(m_pSourcesRowset->m_ulProps & BOOKMARKPROP)
  707. {
  708. dwSrcType = DBTYPE_I4;
  709. pSrc = &pRowBuff->dwBmk;
  710. ulSrcLength = pRowBuff->cbBmk;
  711. dwSrcStatus = DBSTATUS_S_OK;
  712. icol = 0;
  713. }
  714. else
  715. {
  716. continue;
  717. }
  718. }
  719. else
  720. {
  721. //=================================================================
  722. // If the columnID is not of type name then set the status
  723. // to unavialable as only this is supported
  724. //=================================================================
  725. if(rgColumns[lIndex].columnid.eKind != DBKIND_NAME)
  726. {
  727. rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
  728. continue;
  729. }
  730. icol = m_pSourcesRowset->GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
  731. //=========================================================================================
  732. // The column unavailable for the row as the class qualifier belongs to a parent rowset
  733. //=========================================================================================
  734. if(S_OK == (hr =m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_QUALIFIERS,varValue)))
  735. if( (varValue.lVal & CLASS_QUALIFIERS) &&
  736. m_bClassChanged &&
  737. icol == 1 &&
  738. m_pRowColumns->ColumnType(icol) == DBTYPE_HCHAPTER)
  739. {
  740. rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
  741. continue;
  742. }
  743. //=================================================================
  744. // If the requested column is not part of the source rowset
  745. // get it directly from the instance
  746. //=================================================================
  747. if((DB_LORDINAL) icol == -1)
  748. {
  749. hr = GetColumnData(rgColumns[lIndex]);
  750. if ( hr != S_OK )
  751. {
  752. ulErrorCount++;
  753. }
  754. continue;
  755. }
  756. pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(icol));
  757. dwSrcType = (SHORT)pColumnData->dwType;
  758. if( dwSrcType == DBTYPE_BSTR)
  759. {
  760. pSrc = &(pColumnData->pbData);
  761. }
  762. else
  763. {
  764. pSrc = (pColumnData->pbData);
  765. }
  766. ulSrcLength = pColumnData->dwLength;
  767. dwSrcStatus = pColumnData->dwStatus;
  768. }
  769. ulDstMaxLength = rgColumns[lIndex].cbMaxLen;
  770. dwDstType = rgColumns[lIndex].wType;
  771. pDst = rgColumns[lIndex].pData;
  772. pulDstLength = &rgColumns[lIndex].cbDataLen;
  773. pdwDstStatus = &rgColumns[lIndex].dwStatus;
  774. //==========================================================
  775. // if the column is of type chapter then consider that
  776. // as a of type long as HCHAPTER is a ULONG value
  777. //==========================================================
  778. if(dwSrcType == DBTYPE_HCHAPTER)
  779. {
  780. dwSrcType = DBTYPE_UI4;
  781. }
  782. if(dwDstType == DBTYPE_HCHAPTER)
  783. {
  784. dwDstType = DBTYPE_UI4;
  785. }
  786. //=================================================================
  787. // if both the source and destination type is array then don't
  788. // use IDataConvert::DataConvert for conversion
  789. //=================================================================
  790. if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
  791. {
  792. bUseDataConvert = FALSE;
  793. }
  794. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  795. {
  796. // NTRaid:138957
  797. // since for DBTYPE_UI4 the data returned from WMI
  798. // is of type DBTYPE_I4 changing the source type does not
  799. // have any effect except that the VARIANT type of the
  800. // output will be VT_I4 instead of VT_UI4
  801. DBTYPE dbSrcType = dwSrcType;
  802. if(dwDstType == DBTYPE_VARIANT)
  803. {
  804. dbSrcType = GetVBCompatibleAutomationType(dwSrcType);
  805. }
  806. hr = g_pIDataConvert->DataConvert(
  807. dbSrcType,
  808. dwDstType,
  809. ulSrcLength,
  810. pulDstLength,
  811. pSrc,
  812. pDst,
  813. ulDstMaxLength,
  814. dwSrcStatus,
  815. pdwDstStatus,
  816. rgColumns[lIndex].bPrecision, // bPrecision for conversion to DBNUMERIC
  817. rgColumns[lIndex].bScale, // bScale for conversion to DBNUMERIC
  818. DBDATACONVERT_DEFAULT);
  819. if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
  820. {
  821. *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  822. }
  823. }
  824. else
  825. if(bUseDataConvert == FALSE && pSrc != NULL)
  826. {
  827. //=================================================================
  828. // Call this function to get the array in the destination address
  829. //=================================================================
  830. hr = dataMap.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus);
  831. if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  832. {
  833. *pulDstLength = 0;
  834. }
  835. }
  836. else
  837. {
  838. *pulDstLength = 0;
  839. *pdwDstStatus = DBSTATUS_S_ISNULL;
  840. }
  841. //===================================================================
  842. // Ignoring the array for the time being
  843. // to be removed later
  844. //===================================================================
  845. if(dwSrcType & VT_ARRAY)
  846. {
  847. hr = S_OK;
  848. }
  849. if (hr != S_OK )
  850. {
  851. ulErrorCount++; // can't coerce
  852. hr = S_OK;
  853. }
  854. } // for loop
  855. } // if succeeded(hr) after getting local buffer address
  856. } // if Succeeded(hr) after getting the slot number
  857. } // if Succeeded(hr) after initial checking
  858. //===================================================================
  859. // We report any lossy conversions with a special status.
  860. // Note that DB_S_ERRORSOCCURED is a success, rather than failure.
  861. //===================================================================
  862. if ( SUCCEEDED(hr) )
  863. {
  864. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  865. }
  866. return hr;
  867. }
  868. /////////////////////////////////////////////////////////////////////////////////////////////////
  869. // Function to update a row
  870. /////////////////////////////////////////////////////////////////////////////////////////////////
  871. HRESULT CRow::UpdateRow(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
  872. {
  873. VARIANT varProp;
  874. HRESULT hr = E_FAIL;
  875. VariantInit(&varProp);
  876. if(m_pSourcesRowset != NULL)
  877. {
  878. //===================================================================
  879. // Check if updatibility is supported by the parent rowset
  880. //===================================================================
  881. if(SUCCEEDED(hr = m_pSourcesRowset->GetRowsetProperty(DBPROP_UPDATABILITY , varProp)))
  882. {
  883. //=========================================================
  884. // If the rowset is not updatable then return failure
  885. //=========================================================
  886. if(!( varProp.lVal & DBPROPVAL_UP_CHANGE))
  887. {
  888. hr = E_FAIL;
  889. }
  890. else
  891. {
  892. hr = UpdateColumnsFromRowset(cColumns,rgColumns);
  893. }
  894. }
  895. }
  896. else
  897. {
  898. hr = SetRowData(cColumns,rgColumns);
  899. }
  900. return hr;
  901. }
  902. /////////////////////////////////////////////////////////////////////////////////////////////////
  903. // Function to update a row when it is created by a rowset
  904. /////////////////////////////////////////////////////////////////////////////////////////////////
  905. HRESULT CRow::UpdateColumnsFromRowset(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[ ])
  906. {
  907. DBORDINAL icol;
  908. ROWBUFF *pRowBuff;
  909. COLUMNDATA *pColumnData;
  910. DBCOUNTITEM ulErrorCount = 0;
  911. DBTYPE dwSrcType;
  912. DBTYPE dwDstType;
  913. void *pSrc;
  914. void *pDst;
  915. void *pTemp;
  916. DBLENGTH ulSrcLength;
  917. DBLENGTH ulDstLength;
  918. DBLENGTH ulDstMaxLength;
  919. DBSTATUS dwSrcStatus;
  920. DBSTATUS dwDstStatus;
  921. HRESULT hr = S_OK;
  922. DBSTATUS dwStatus = DBSTATUS_S_OK;
  923. CVARIANT cvarData;
  924. VARIANT *pvarData = &cvarData;
  925. CDataMap map;
  926. ULONG lFlags = 0;
  927. BOOL bUseDataConvert = TRUE;
  928. DWORD dwCIMType = 0;
  929. dwStatus = m_pSourcesRowset->GetRowStatus(m_hRow);
  930. if( dwStatus != DBROWSTATUS_S_OK)
  931. {
  932. if(dwStatus == DBROWSTATUS_E_DELETED)
  933. {
  934. hr = DB_E_DELETEDROW;
  935. }
  936. else
  937. {
  938. hr = E_FAIL;
  939. }
  940. }
  941. else
  942. {
  943. //========================================================
  944. // if data is not yet received then fetch the data
  945. //========================================================
  946. if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
  947. {
  948. hr = m_pSourcesRowset->GetData(m_hRow);
  949. }
  950. if(SUCCEEDED(hr))
  951. {
  952. //========================================
  953. // Get the pointer to the rowbuffer
  954. //========================================
  955. pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
  956. assert(pRowBuff != NULL);
  957. for( ULONG lIndex = 0 ; lIndex < cColumns ; lIndex++)
  958. {
  959. bUseDataConvert = TRUE;
  960. if(rgColumns[lIndex].columnid.eKind != DBKIND_NAME)
  961. {
  962. rgColumns[lIndex].dwStatus = DBSTATUS_E_UNAVAILABLE;
  963. continue;
  964. }
  965. icol = m_pSourcesRowset->GetOrdinalFromColName(rgColumns[lIndex].columnid.uName.pwszName);
  966. //===================================================================================
  967. // If the requested column is not part of the source rowset
  968. // call SetColumnData function to set it directly from the instance
  969. //===================================================================================
  970. if((DB_LORDINAL)icol < 0)
  971. {
  972. hr = SetColumnData(rgColumns[lIndex]);
  973. if ( hr != S_OK )
  974. {
  975. ulErrorCount++;
  976. }
  977. continue;
  978. }
  979. pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(icol));
  980. //==================================================
  981. // check if the column is readonly or not
  982. //==================================================
  983. lFlags = m_pSourcesRowset->m_Columns.ColumnFlags(icol);
  984. if((m_pSourcesRowset->m_Columns.ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0)
  985. {
  986. pColumnData->dwStatus = DBSTATUS_E_READONLY;
  987. ulErrorCount++;
  988. continue;
  989. }
  990. dwSrcType = rgColumns[lIndex].wType;
  991. ulSrcLength = rgColumns[lIndex].cbDataLen;
  992. dwSrcStatus = rgColumns[lIndex].dwStatus;
  993. pSrc = rgColumns[lIndex].pData;
  994. ulDstMaxLength = -1;
  995. dwDstType = (SHORT)pColumnData->dwType;
  996. // pDst = &varData;
  997. //==========================================================
  998. // if the column is of type chapter then consider that
  999. // as a of type long as HCHAPTER is a ULONG value
  1000. //==========================================================
  1001. if(dwSrcType == DBTYPE_HCHAPTER)
  1002. {
  1003. dwSrcType = DBTYPE_UI4;
  1004. }
  1005. if(dwDstType == DBTYPE_HCHAPTER)
  1006. {
  1007. dwDstType = DBTYPE_UI4;
  1008. }
  1009. hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &ulSrcLength, &ulDstLength, pSrc);
  1010. try
  1011. {
  1012. pDst = new BYTE[ulDstLength];
  1013. }
  1014. catch(...)
  1015. {
  1016. SAFE_DELETE_ARRAY(pDst);
  1017. throw;
  1018. }
  1019. //===================================================================================
  1020. // if both the source and destination type is array then don't
  1021. // use IDataConvert::DataConvert for conversion
  1022. //===================================================================================
  1023. if( (dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY) )
  1024. {
  1025. bUseDataConvert = FALSE;
  1026. }
  1027. // this function is called to check for some non automation types
  1028. dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
  1029. //===================================================================================
  1030. // If the source type is not array or empty or null the use the conversion library
  1031. // for converting the data
  1032. //===================================================================================
  1033. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  1034. {
  1035. hr = g_pIDataConvert->DataConvert(
  1036. dwSrcType,
  1037. dwDstType,
  1038. ulSrcLength,
  1039. &ulDstLength,
  1040. pSrc,
  1041. pDst,
  1042. ulDstMaxLength,
  1043. dwSrcStatus,
  1044. &dwDstStatus,
  1045. 0, // bPrecision for conversion to DBNUMERIC
  1046. 0, // bScale for conversion to DBNUMERIC
  1047. DBDATACONVERT_DEFAULT);
  1048. if(hr == DB_E_UNSUPPORTEDCONVERSION )
  1049. {
  1050. dwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1051. }
  1052. }
  1053. else
  1054. if(bUseDataConvert == FALSE && pSrc != NULL)
  1055. {
  1056. //==================================================================
  1057. // Call this function to get the array in the destination address
  1058. //==================================================================
  1059. hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType, &dwDstStatus);
  1060. if(dwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  1061. {
  1062. ulDstLength = 0;
  1063. ulErrorCount++;
  1064. }
  1065. }
  1066. else
  1067. {
  1068. pDst = NULL;
  1069. ulDstLength = 0;
  1070. dwDstStatus = DBSTATUS_S_ISNULL;
  1071. }
  1072. if( hr == S_OK)
  1073. {
  1074. dwCIMType = -1;
  1075. //============================================================================
  1076. // if the type is array , then get the original CIMTYPE as array type will
  1077. // be given out as VT_ARRAY | VT_VARIANT
  1078. //============================================================================
  1079. if(pColumnData->dwType & DBTYPE_ARRAY)
  1080. {
  1081. dwCIMType = m_Columns.GetCIMType(icol);
  1082. }
  1083. if(pDst != NULL && pColumnData->dwType == VT_BSTR)
  1084. {
  1085. pTemp = *(BSTR **)pDst;
  1086. }
  1087. else
  1088. {
  1089. pTemp = pDst;
  1090. }
  1091. //====================================
  1092. // If data is is modified then
  1093. //====================================
  1094. if((map.CompareData(dwDstType,pColumnData->pbData,pTemp) == FALSE)
  1095. && !( pColumnData->pbData == NULL && ulDstLength == 0))
  1096. {
  1097. //===============================
  1098. // Release the Old data
  1099. //===============================
  1100. pColumnData->ReleaseColumnData();
  1101. if(ulDstLength > 0)
  1102. {
  1103. //=====================================================================
  1104. // Convert the new data to Variant. This function return the status
  1105. // if not able to conver the data
  1106. //=====================================================================
  1107. hr = map.MapAndConvertOLEDBTypeToCIMType((USHORT)pColumnData->dwType,pTemp,ulDstLength,*pvarData,dwCIMType);
  1108. }
  1109. if( hr == S_OK)
  1110. {
  1111. hr = pColumnData->SetData(cvarData,dwDstType);
  1112. //==============================
  1113. // Set the data to modified
  1114. //==============================
  1115. pColumnData->dwStatus |= COLUMNSTAT_MODIFIED;
  1116. cvarData.Clear();
  1117. }
  1118. else
  1119. {
  1120. //==============================
  1121. // Set the data to modified
  1122. //==============================
  1123. pColumnData->dwStatus |= hr;
  1124. ulErrorCount++;
  1125. }
  1126. }
  1127. }
  1128. else
  1129. {
  1130. ulErrorCount++;
  1131. rgColumns[lIndex].dwStatus = dwDstStatus;
  1132. }
  1133. SAFE_DELETE_ARRAY(pDst);
  1134. } // for loop
  1135. //===============================================================
  1136. // if the error count is less than the number of columns
  1137. // then there is atleast one column to be updated
  1138. //===============================================================
  1139. if( ulErrorCount < cColumns)
  1140. {
  1141. //====================================================================
  1142. // Update the the row
  1143. //====================================================================
  1144. hr = m_pSourcesRowset->UpdateRowData(m_hRow,cColumns,rgColumns);
  1145. }
  1146. //===================================================================
  1147. // We report any lossy conversions with a special status.
  1148. // Note that DB_S_ERRORSOCCURED is a success, rather than failure.
  1149. //===================================================================
  1150. if ( SUCCEEDED(hr) )
  1151. {
  1152. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  1153. }
  1154. }
  1155. } // else of check if deleted
  1156. return hr;
  1157. }
  1158. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1159. // Virtual overridden function which is called from IColumnInfo to get the column information
  1160. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1161. HRESULT CRow::GetColumnInfo(DBORDINAL* pcColumns, DBCOLUMNINFO** prgInfo,WCHAR** ppStringsBuffer)
  1162. {
  1163. DBORDINAL icol = 0;
  1164. DBCOLUMNINFO* rgdbcolinfo = NULL;
  1165. WCHAR* pstrBuffer = NULL;
  1166. WCHAR* pstrBufferForColInfo = NULL;
  1167. HRESULT hr = S_OK;
  1168. ptrdiff_t dp;
  1169. DBCOUNTITEM cSourcesCol = 0;
  1170. if(SUCCEEDED(hr = m_pRowColumns->CopyColumnInfoList(rgdbcolinfo,(m_pSourcesRowset != NULL))))
  1171. {
  1172. //=========================================================================
  1173. // Copy the heap for column names.
  1174. //=========================================================================
  1175. if (m_pSourcesRowset != NULL && m_pRowColumns->ColumnNameListStartingPointOfSrcRs() != NULL){
  1176. hr = m_pRowColumns->CopyColumnNamesList(pstrBuffer);
  1177. if( hr != S_OK || pstrBuffer == NULL)
  1178. {
  1179. hr = E_OUTOFMEMORY;
  1180. }
  1181. else
  1182. {
  1183. //==================================================================================
  1184. // This will give the starting pointer difference to the columns names of the
  1185. // source rowset
  1186. //==================================================================================
  1187. dp = (LONG_PTR) pstrBuffer - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPointOfSrcRs());
  1188. dp >>= 1;
  1189. //=========================================================================
  1190. // Loop through columns and adjust pointers
  1191. // to column names.
  1192. //=========================================================================
  1193. cSourcesCol = m_pRowColumns->GetNumberOfColumnsInSourceRowset();
  1194. for ( icol =0; icol < cSourcesCol; icol++ )
  1195. {
  1196. if ( rgdbcolinfo[icol].pwszName )
  1197. {
  1198. rgdbcolinfo[icol].pwszName += dp;
  1199. }
  1200. if(rgdbcolinfo[icol].wType == DBTYPE_HCHAPTER)
  1201. {
  1202. rgdbcolinfo[icol].dwFlags = DBCOLUMNFLAGS_ISCOLLECTION | DBCOLUMNFLAGS_ISCHAPTER ;
  1203. }
  1204. }
  1205. //==================================================================================================================
  1206. // This will give the starting pointer difference to the columns names of the columns which is not present in the
  1207. // sources rowset
  1208. // Here the number of bytes copied for source rowset column names has to be taken care of
  1209. //==================================================================================================================
  1210. dp = (LONG_PTR) pstrBuffer + m_pRowColumns->GetCountOfBytesCopiedForSrcRs() - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPoint());
  1211. dp >>= 1;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. if( SUCCEEDED(hr = m_pRowColumns->CopyColumnNamesList(pstrBuffer)))
  1217. {
  1218. //================================================================================
  1219. // This will give the starting pointer difference to the columns names of the
  1220. // source rowset
  1221. //================================================================================
  1222. dp = (LONG_PTR) pstrBuffer - (LONG_PTR) (m_pRowColumns->ColumnNameListStartingPoint());
  1223. dp >>= 1;
  1224. icol = 0;
  1225. }
  1226. }
  1227. if(SUCCEEDED(hr))
  1228. {
  1229. //===========================================
  1230. // Loop through columns and adjust pointers
  1231. // to column names.
  1232. //===========================================
  1233. for ( ; icol < m_cTotalCols ; icol++ )
  1234. {
  1235. if ( rgdbcolinfo[icol].pwszName )
  1236. {
  1237. rgdbcolinfo[icol].pwszName += dp;
  1238. }
  1239. }
  1240. //=======================================================
  1241. // If the row's column is of type HCHAPTER change it
  1242. // to empty and the flag to DBCOLUMNFLAGS_ISCOLLECTION
  1243. //=======================================================
  1244. if(m_cNestedCols > 0)
  1245. for(icol = 0; icol < m_cTotalCols ; icol++)
  1246. {
  1247. if(rgdbcolinfo[icol].wType == DBTYPE_HCHAPTER)
  1248. {
  1249. rgdbcolinfo[icol].wType = DBTYPE_HCHAPTER;
  1250. rgdbcolinfo[icol].dwFlags = DBCOLUMNFLAGS_ISCHAPTER | DBCOLUMNFLAGS_ISCOLLECTION;
  1251. rgdbcolinfo[icol].ulColumnSize = sizeof(DBLENGTH);
  1252. }
  1253. }
  1254. //===================================================================================================
  1255. // Setting the output parameters
  1256. //===================================================================================================
  1257. *prgInfo = &rgdbcolinfo[0];
  1258. *ppStringsBuffer = pstrBuffer;
  1259. *pcColumns = m_cTotalCols;
  1260. } // if succeeded(hr)
  1261. } // if succeeded(CopyColumnInfoList())
  1262. return hr;
  1263. }
  1264. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1265. // Function to get the column information of the row. THis function check if the class name of the
  1266. // rowset which created the row belongs to the same class as that of the instance pointing the current row
  1267. // If these two are different , this ffunction get the col info for this row
  1268. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1269. HRESULT CRow::GetRowColumnInfo()
  1270. {
  1271. WCHAR *pstrRsClassName = NULL, *pstrRowClassName = NULL;
  1272. HRESULT hr = S_OK;
  1273. //====================================================
  1274. // Get the class name to which the instance belongs
  1275. //====================================================
  1276. pstrRowClassName = m_pInstance->GetClassName();
  1277. if( pstrRowClassName != NULL)
  1278. {
  1279. //================================================
  1280. // Get the class name of the source rowset
  1281. //================================================
  1282. pstrRsClassName = m_pSourcesRowset->m_pMap->GetClassName();
  1283. }
  1284. //============================================================
  1285. // Set the bClassChanged flag to true if instance points to
  1286. // different class than that of the source rowset
  1287. //============================================================
  1288. if( pstrRsClassName == NULL && pstrRowClassName == NULL)
  1289. {
  1290. m_bClassChanged = FALSE;
  1291. }
  1292. else
  1293. if( pstrRsClassName == NULL || pstrRowClassName == NULL)
  1294. {
  1295. m_bClassChanged = TRUE;
  1296. }
  1297. else
  1298. if(_wcsicmp(pstrRsClassName,pstrRowClassName) != 0)
  1299. {
  1300. m_bClassChanged = TRUE;
  1301. }
  1302. //=====================================================================
  1303. // If the source rowset and the row points to different classes ,
  1304. // then the columnd info of the remaining columns has to be obtained
  1305. //=====================================================================
  1306. if(m_bClassChanged == TRUE)
  1307. {
  1308. //===========================================
  1309. // Get the flags of the source rowset
  1310. //===========================================
  1311. DWORD dwFlags = m_pInstance->GetFlags();
  1312. SAFE_RELEASE_PTR(m_pMap);
  1313. //===================================
  1314. // Create a new map class
  1315. //===================================
  1316. m_pMap = new CWmiOleDBMap;
  1317. if(m_pMap == NULL)
  1318. {
  1319. hr = E_OUTOFMEMORY;
  1320. }
  1321. else
  1322. {
  1323. if(SUCCEEDED(hr = m_pMap->FInit(dwFlags,pstrRowClassName,
  1324. m_pCon == NULL ?m_pCreator->m_pCDataSource->m_pWbemWrap: m_pCon)))
  1325. {
  1326. m_pMap->AddRef();
  1327. //============================
  1328. // Get the column info
  1329. //============================
  1330. hr = GetColumnInfo();
  1331. }
  1332. }
  1333. }
  1334. SAFE_DELETE_ARRAY(pstrRowClassName);
  1335. return hr;
  1336. }
  1337. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1338. // Get the number of columns in the row and allocate memory
  1339. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1340. HRESULT CRow::GetColumnInfo()
  1341. {
  1342. HRESULT hr = S_OK;
  1343. VARIANT varValue;
  1344. VariantInit(&varValue);
  1345. // Bug which not able to get system properties from Row object
  1346. // NTRaid: 140657
  1347. // 05/06/00
  1348. //===========================================================================================
  1349. // Get the DataSource property to check if system Properties is to be fetched?
  1350. //===========================================================================================
  1351. if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_SYSTEMPROPERTIES,varValue)))
  1352. {
  1353. if( varValue.boolVal == VARIANT_TRUE)
  1354. {
  1355. m_pMap->SetSytemPropertiesFlag(TRUE);
  1356. }
  1357. //==================================================================================
  1358. // switch on type of the qualifier. If it is 0 then the recordset is
  1359. // representing the instances of the class
  1360. //==================================================================================
  1361. switch( m_uRsType)
  1362. {
  1363. case 0 :
  1364. //==================================================================================
  1365. // Get the count of columns in the table
  1366. //==================================================================================
  1367. hr = m_pMap->GetColumnCount(m_cTotalCols,m_cCols,m_cNestedCols);
  1368. // If source rowset is present and
  1369. // If the property for showing system property is false and
  1370. // if the source rowset is created by a query of mixed type
  1371. // ( meaning rowset created executing a query, which results
  1372. // in heterogenous objects ) then add another column to the row
  1373. // which is part of the source rowset to show __PATH
  1374. // NTRaid : 142133 & 141923
  1375. // 07/12/00
  1376. if(m_pSourcesRowset != NULL && m_cTotalCols)
  1377. {
  1378. if( varValue.boolVal == FALSE)
  1379. {
  1380. // all types of rowset has to have an extr column as __PATH property
  1381. // which is a system property is shown in the row even if the
  1382. // DBPROP_WMIOLEDB_SYSTEMPROPERTIES is set to FALSE
  1383. if(NORMAL != m_pSourcesRowset->GetObjListType())
  1384. {
  1385. m_cTotalCols++;
  1386. m_cCols++;
  1387. }
  1388. }
  1389. VariantClear(&varValue);
  1390. }
  1391. break;
  1392. case PROPERTYQUALIFIER :
  1393. case CLASSQUALIFIER:
  1394. //==================================================================================
  1395. // Get the number of columns for the property qualifier
  1396. //==================================================================================
  1397. m_cCols = NUMBER_OF_COLUMNS_IN_QUALIFERROWSET + 1; // for bookmarkcolumn
  1398. m_cTotalCols = m_cCols;
  1399. break;
  1400. };
  1401. }
  1402. if( SUCCEEDED(hr))
  1403. {
  1404. // The column unavailable for the row as the class qualifier belongs to a parent rowset
  1405. if(m_pSourcesRowset != NULL && S_OK == (hr =m_pCreator->GetDataSrcProperty(DBPROP_WMIOLEDB_QUALIFIERS,varValue)))
  1406. if( (varValue.lVal & CLASS_QUALIFIERS) &&
  1407. m_bClassChanged)
  1408. {
  1409. m_cTotalCols++; // This is to accomodate another column which actually
  1410. // holds the class/instance qualifiers
  1411. }
  1412. if( S_OK == (hr = m_pRowColumns->AllocColumnNameList(m_cTotalCols))){
  1413. //===============================================================================
  1414. // Allocate the DBCOLUMNINFO structs to match the number of columns
  1415. //===============================================================================
  1416. if( S_OK == (hr = m_pRowColumns->AllocColumnInfoList(m_cTotalCols))){
  1417. hr = GatherColumnInfo();
  1418. }
  1419. }
  1420. }
  1421. //==================================================================================
  1422. // Free the columnlist if more is allocated
  1423. //==================================================================================
  1424. if( hr != S_OK ){
  1425. m_pRowColumns->FreeColumnNameList();
  1426. m_pRowColumns->FreeColumnInfoList();
  1427. }
  1428. return hr;
  1429. }
  1430. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1431. // Get the col info for row
  1432. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1433. HRESULT CRow::GatherColumnInfo()
  1434. {
  1435. HRESULT hr = S_OK;
  1436. switch( m_uRsType)
  1437. {
  1438. case 0 :
  1439. //=============================================================
  1440. // Get Column Names and Lengths
  1441. //=============================================================
  1442. hr = m_pMap->GetColumnInfoForParentColumns(m_pRowColumns);
  1443. break;
  1444. case PROPERTYQUALIFIER:
  1445. //==================================================================================
  1446. // Get the number of columns for the property qualifier
  1447. //==================================================================================
  1448. hr = CBaseRowObj::GatherColumnInfoForQualifierRowset();
  1449. break;
  1450. case CLASSQUALIFIER:
  1451. break;
  1452. };
  1453. if(SUCCEEDED(hr))
  1454. {
  1455. m_cbRowSize = m_pRowColumns->SetRowSize();
  1456. hr = m_pRowColumns->FreeUnusedMemory();
  1457. }
  1458. return hr;
  1459. }
  1460. //////////////////////////////////////////////////////////////////////////////////////
  1461. // Get data for a particular column
  1462. //////////////////////////////////////////////////////////////////////////////////////
  1463. HRESULT CRow::GetColumnData(DBCOLUMNACCESS &col)
  1464. {
  1465. DBORDINAL icol = 0;
  1466. DBCOUNTITEM ulErrorCount = 0;
  1467. CIMTYPE cimType = 0;
  1468. DBTYPE dwSrcType;
  1469. DBTYPE dwDstType;
  1470. void *pSrc = NULL;
  1471. void *pDst = NULL;
  1472. BYTE *pTemp = NULL;
  1473. DBLENGTH ulSrcLength;
  1474. DBLENGTH *pulDstLength = NULL;
  1475. DBLENGTH ulDstMaxLength = NULL;
  1476. DBSTATUS dwSrcStatus = 0;
  1477. DBSTATUS *pdwDstStatus = NULL;
  1478. HRESULT hr = S_OK;
  1479. DBSTATUS dwStatus = DBSTATUS_S_OK;
  1480. BSTR strProp = NULL;
  1481. DWORD dwFlags = 0;
  1482. CDataMap map;
  1483. BOOL bUseDataConvert = TRUE;
  1484. DBORDINAL lCollectionColData = 0;
  1485. icol = m_pRowColumns->GetColOrdinal(col.columnid.uName.pwszName);
  1486. if( icol > 0)
  1487. {
  1488. // If the column is of type HCHAPTER or if it is a collection ( meaning
  1489. // if the column represents any of the child rowsets) then set the
  1490. // column to ordinal of the column
  1491. if(m_pRowColumns->ColumnType(icol) == DBTYPE_HCHAPTER ||
  1492. m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_ISCOLLECTION ||
  1493. m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_ISCHAPTER)
  1494. {
  1495. col.bPrecision = 0;
  1496. col.bScale = 0;
  1497. lCollectionColData = icol;
  1498. dwSrcType = DBTYPE_UI4;
  1499. ulDstMaxLength = col.cbMaxLen;
  1500. dwDstType = (DBTYPE)col.wType;
  1501. pulDstLength = &col.cbDataLen;
  1502. pdwDstStatus = &col.dwStatus;
  1503. ulSrcLength = sizeof(lCollectionColData);
  1504. dwSrcStatus = DBSTATUS_S_OK;
  1505. pSrc = &lCollectionColData;
  1506. hr = S_OK;
  1507. }
  1508. else
  1509. {
  1510. strProp = Wmioledb_SysAllocString(col.columnid.uName.pwszName);
  1511. hr = m_pMap->GetProperty(m_pInstance,strProp, pTemp,dwSrcType ,ulSrcLength, dwFlags );
  1512. if(SUCCEEDED(hr))
  1513. {
  1514. // dwSrcType = (DBTYPE)cimType;
  1515. //==========================================
  1516. // check if the column is readonly or not
  1517. //==========================================
  1518. if((dwFlags & DBCOLUMNFLAGS_WRITE) == 0)
  1519. {
  1520. col.dwStatus = DBSTATUS_E_READONLY;
  1521. }
  1522. //=========================================================
  1523. // if the data is null set the status to null and return
  1524. //=========================================================
  1525. if(pTemp == NULL)
  1526. {
  1527. col.dwStatus = DBSTATUS_S_ISNULL;
  1528. hr = S_OK;
  1529. }
  1530. else
  1531. {
  1532. if( dwSrcType == DBTYPE_BSTR)
  1533. {
  1534. pSrc = &pTemp;
  1535. }
  1536. else
  1537. {
  1538. pSrc = pTemp;
  1539. }
  1540. ulDstMaxLength = col.cbMaxLen;
  1541. dwDstType = (DBTYPE)col.wType;
  1542. pulDstLength = &col.cbDataLen;
  1543. pdwDstStatus = &col.dwStatus;
  1544. }
  1545. }
  1546. SAFE_FREE_SYSSTRING(strProp);
  1547. }
  1548. if(SUCCEEDED(hr))
  1549. {
  1550. //==========================================================
  1551. // if the column is of type chapter then consider that
  1552. // as a of type long as HCHAPTER is a ULONG value
  1553. //==========================================================
  1554. if(dwSrcType == DBTYPE_HCHAPTER)
  1555. {
  1556. dwSrcType = DBTYPE_UI4;
  1557. }
  1558. if(dwDstType == DBTYPE_HCHAPTER)
  1559. {
  1560. dwDstType = DBTYPE_UI4;
  1561. }
  1562. pDst = (BYTE *)col.pData;
  1563. // if both the source and destination type is array then don't
  1564. // use IDataConvert::DataConvert for conversion
  1565. // Arrays are requested as VARIANTS then also do conversion using our conversion routine
  1566. // and fill the variant
  1567. if( (dwSrcType & DBTYPE_ARRAY) && ( (dwDstType & DBTYPE_ARRAY) || dwDstType == VT_VARIANT) )
  1568. {
  1569. bUseDataConvert = FALSE;
  1570. }
  1571. // this function is called to check for some non automation types
  1572. dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
  1573. // this function is called to check for some non automation types
  1574. dwDstType = GetVBCompatibleAutomationType(dwDstType);
  1575. // If the source type is not array or empty or null the use the conversion library
  1576. // for converting the data
  1577. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  1578. {
  1579. hr = g_pIDataConvert->DataConvert(
  1580. (USHORT)dwSrcType,
  1581. dwDstType,
  1582. ulSrcLength,
  1583. pulDstLength,
  1584. pSrc,
  1585. pDst,
  1586. ulDstMaxLength,
  1587. dwSrcStatus,
  1588. pdwDstStatus,
  1589. 0, // bPrecision for conversion to DBNUMERIC
  1590. 0, // bScale for conversion to DBNUMERIC
  1591. DBDATACONVERT_DEFAULT);
  1592. if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
  1593. {
  1594. *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1595. }
  1596. if ( hr != S_OK)
  1597. {
  1598. ulErrorCount++;
  1599. }
  1600. }
  1601. else
  1602. if(bUseDataConvert == FALSE && pSrc != NULL)
  1603. {
  1604. SAFEARRAY *pArray = NULL;
  1605. SAFEARRAY **pTemp = NULL;
  1606. if(pDst != NULL)
  1607. {
  1608. pTemp = (SAFEARRAY **)pDst;
  1609. if(dwDstType == VT_VARIANT)
  1610. {
  1611. pTemp = &pArray;
  1612. }
  1613. }
  1614. // Call this function to get the array in the destination address
  1615. hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,pTemp, dwSrcType,dwDstType,pdwDstStatus);
  1616. if( *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  1617. {
  1618. pulDstLength = 0;
  1619. }
  1620. if(SUCCEEDED(hr) && dwDstType == VT_VARIANT)
  1621. {
  1622. VariantInit((VARIANT *)pDst);
  1623. if(pArray && pDst != NULL)
  1624. {
  1625. ((VARIANT *)pDst)->vt = VT_ARRAY | VT_VARIANT;
  1626. ((VARIANT *)pDst)->parray = pArray;
  1627. }
  1628. }
  1629. }
  1630. else
  1631. {
  1632. if(pulDstLength)
  1633. {
  1634. *pulDstLength = 0;
  1635. }
  1636. if(pdwDstStatus)
  1637. {
  1638. *pdwDstStatus = DBSTATUS_S_ISNULL;
  1639. }
  1640. }
  1641. //===============================
  1642. // Free the data allocated
  1643. //===============================
  1644. map.FreeData(dwSrcType , pTemp);
  1645. }
  1646. }
  1647. else
  1648. {
  1649. col.dwStatus = DBSTATUS_E_UNAVAILABLE;
  1650. hr = E_FAIL;
  1651. }
  1652. return hr;
  1653. }
  1654. //////////////////////////////////////////////////////////////////////////////////////
  1655. // Set a value of a particular column
  1656. //////////////////////////////////////////////////////////////////////////////////////
  1657. HRESULT CRow::SetColumnData(DBCOLUMNACCESS &col,BOOL bNewRow)
  1658. {
  1659. DBORDINAL icol;
  1660. DBCOUNTITEM ulErrorCount = 0;
  1661. DBTYPE dwSrcType;
  1662. DBTYPE dwDstType;
  1663. void *pSrc = NULL;
  1664. void *pDst = NULL;
  1665. void *pTemp = NULL;
  1666. DBLENGTH lSrcLength;
  1667. DBLENGTH lDstLength;
  1668. DBLENGTH lDstMaxLength;
  1669. DBSTATUS dwSrcStatus;
  1670. DBSTATUS dwDstStatus;
  1671. HRESULT hr = S_OK;
  1672. CVARIANT cvarData;
  1673. VARIANT *pvarData = &cvarData;
  1674. CDataMap map;
  1675. ULONG lFlags = 0;
  1676. BSTR strProp;
  1677. BOOL bUseDataConvert = TRUE;
  1678. DWORD dwCIMType = 0;
  1679. //===============================================================
  1680. // Get the ordinal of the column from the column information
  1681. //===============================================================
  1682. icol = m_pRowColumns->GetColOrdinal(col.columnid.uName.pwszName);
  1683. if( ((LONG)icol) >= 0)
  1684. {
  1685. strProp = Wmioledb_SysAllocString(col.columnid.uName.pwszName);
  1686. //================================================
  1687. // check if the column is readonly or not
  1688. // If it is a new row continue updating
  1689. //================================================
  1690. lFlags = m_pRowColumns->ColumnFlags(icol);
  1691. if(((bNewRow == FALSE) && ((m_pRowColumns->ColumnFlags(icol) & DBCOLUMNFLAGS_WRITE) == 0)) ||
  1692. ((bNewRow == TRUE) && m_pMap->IsSystemProperty(strProp)))
  1693. {
  1694. col.dwStatus = DBSTATUS_E_READONLY;
  1695. ulErrorCount++;
  1696. hr = DB_S_ERRORSOCCURRED;
  1697. }
  1698. else
  1699. {
  1700. dwSrcType = col.wType;
  1701. lSrcLength = col.cbDataLen;
  1702. dwSrcStatus = col.dwStatus;
  1703. if(dwSrcType == DBTYPE_BSTR)
  1704. {
  1705. pSrc = &col.pData;
  1706. }
  1707. else
  1708. {
  1709. pSrc = col.pData;
  1710. }
  1711. lDstMaxLength = -1;
  1712. dwDstType = (SHORT)m_pRowColumns->ColumnType(icol);
  1713. //==========================================================
  1714. // if the column is of type chapter then consider that
  1715. // as a of type long as HCHAPTER is a ULONG value
  1716. //==========================================================
  1717. if(dwSrcType == DBTYPE_HCHAPTER)
  1718. {
  1719. dwSrcType = DBTYPE_UI4;
  1720. }
  1721. if(dwDstType == DBTYPE_HCHAPTER)
  1722. {
  1723. dwDstType = DBTYPE_UI4;
  1724. }
  1725. hr = g_pIDataConvert->GetConversionSize(dwSrcType, dwDstType, &lSrcLength, &lDstLength, pSrc);
  1726. try
  1727. {
  1728. pDst = new BYTE[lDstLength];
  1729. }
  1730. catch(...)
  1731. {
  1732. SAFE_DELETE_ARRAY(pDst);
  1733. throw;
  1734. }
  1735. // if both the source and destination type is array then don't
  1736. // use IDataConvert::DataConvert for conversion
  1737. if((dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY))
  1738. {
  1739. bUseDataConvert = FALSE;
  1740. }
  1741. // this function is called to check for some non automation types
  1742. dwSrcType = GetVBCompatibleAutomationType(dwSrcType);
  1743. // If the source type is not array or empty or null the use the conversion library
  1744. // for converting the data
  1745. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  1746. {
  1747. hr = g_pIDataConvert->DataConvert(
  1748. dwSrcType,
  1749. dwDstType,
  1750. lSrcLength,
  1751. &lDstLength,
  1752. pSrc,
  1753. pDst,
  1754. lDstMaxLength,
  1755. dwSrcStatus,
  1756. &dwDstStatus,
  1757. 0, // bPrecision for conversion to DBNUMERIC
  1758. 0, // bScale for conversion to DBNUMERIC
  1759. DBDATACONVERT_DEFAULT);
  1760. if(hr == DB_E_UNSUPPORTEDCONVERSION )
  1761. {
  1762. dwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1763. }
  1764. }
  1765. else
  1766. if(bUseDataConvert == FALSE && pSrc != NULL)
  1767. {
  1768. // Call this function to get the array in the destination address
  1769. hr = map.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,&dwDstStatus);
  1770. if( dwDstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  1771. {
  1772. lDstLength = 0;
  1773. }
  1774. }
  1775. else
  1776. {
  1777. lDstLength = 0;
  1778. dwDstStatus = DBSTATUS_S_ISNULL;
  1779. }
  1780. if(SUCCEEDED(hr))
  1781. {
  1782. dwCIMType = -1;
  1783. // if the type is array , then get the original CIMTYPE as array type will
  1784. // be given out as VT_ARRAY | VT_VARIANT
  1785. if(dwDstType & DBTYPE_ARRAY)
  1786. {
  1787. dwCIMType = m_Columns.GetCIMType(icol);
  1788. }
  1789. if(pDst != NULL && dwDstType == VT_BSTR)
  1790. {
  1791. pTemp = *(BSTR **)pDst;
  1792. }
  1793. else
  1794. {
  1795. pTemp = pDst;
  1796. }
  1797. //=========================================
  1798. // If data is is modified then
  1799. //=========================================
  1800. if( pTemp != NULL && lDstLength != 0)
  1801. {
  1802. if(lDstLength > 0)
  1803. {
  1804. //===========================================
  1805. // Convert the new data to Variant
  1806. //===========================================
  1807. map.MapAndConvertOLEDBTypeToCIMType((USHORT)dwDstType,pTemp,lDstLength,*pvarData,dwCIMType);
  1808. hr = m_pInstance->SetProperty(strProp,pvarData);
  1809. }
  1810. cvarData.Clear();
  1811. }
  1812. }
  1813. else
  1814. {
  1815. ulErrorCount++;
  1816. col.dwStatus = dwDstStatus;
  1817. }
  1818. SAFE_DELETE_PTR(pDst);
  1819. }
  1820. SysFreeString(strProp);
  1821. }
  1822. //===================================================================
  1823. // We report any lossy conversions with a special status.
  1824. // Note that DB_S_ERRORSOCCURED is a success, rather than failure.
  1825. //===================================================================
  1826. if ( SUCCEEDED(hr) )
  1827. {
  1828. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  1829. }
  1830. return hr;
  1831. }
  1832. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1833. // Get the rowdata and put it into the buffer pointed by the second parameter
  1834. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1835. HRESULT CRow::GetRowData(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
  1836. {
  1837. ULONG ulErrorCount = 0;
  1838. HRESULT hr = S_OK;
  1839. //=========================================================
  1840. // Navigate through every element in the array, get
  1841. // the value of the columns
  1842. //=========================================================
  1843. for (ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
  1844. {
  1845. hr = GetColumnData(rgColumns[lIndex]);
  1846. if ( hr != S_OK )
  1847. {
  1848. ulErrorCount++;
  1849. hr = S_OK;
  1850. }
  1851. }
  1852. if ( SUCCEEDED(hr) )
  1853. {
  1854. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  1855. }
  1856. if( ulErrorCount >= cColumns)
  1857. {
  1858. hr = E_FAIL;
  1859. }
  1860. return hr;
  1861. }
  1862. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1863. // Set the the values of the different columns. This is called when row is created directly
  1864. // and not from rowset
  1865. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  1866. HRESULT CRow::SetRowData(DBORDINAL cColumns,DBCOLUMNACCESS rgColumns[])
  1867. {
  1868. ULONG ulErrorCount = 0;
  1869. HRESULT hr = S_OK;
  1870. //=========================================================
  1871. // Navigate through every element in the array, set
  1872. // the value of the columns
  1873. //=========================================================
  1874. for (ULONG_PTR lIndex = 0 ; lIndex < cColumns ; lIndex++)
  1875. {
  1876. hr = SetColumnData(rgColumns[lIndex]);
  1877. if ( hr != S_OK )
  1878. {
  1879. ulErrorCount++;
  1880. hr = S_OK;
  1881. }
  1882. }
  1883. if(SUCCEEDED(hr))
  1884. {
  1885. //==============================================
  1886. // call this function to update the instance
  1887. //==============================================
  1888. hr = m_pMap->UpdateInstance(m_pInstance,FALSE);
  1889. }
  1890. if ( SUCCEEDED(hr) )
  1891. {
  1892. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  1893. }
  1894. if( ulErrorCount >= cColumns)
  1895. {
  1896. hr = E_FAIL;
  1897. }
  1898. return hr;
  1899. }
  1900. //////////////////////////////////////////////////////////////////////////////////////
  1901. // Open a rowset on a column which represents qualifiers or embeded classes
  1902. // NTRaid:111833
  1903. // 06/07/00
  1904. //////////////////////////////////////////////////////////////////////////////////////
  1905. HRESULT CRow::OpenChild(IUnknown *pUnkOuter,WCHAR *strColName ,REFIID riid, IUnknown **ppUnk,BOOL bIsChildRowset)
  1906. {
  1907. HRESULT hr = S_OK;
  1908. ULONG cPropSets = 1;
  1909. // NTRaid:111833
  1910. // 06/13/00
  1911. DBPROPSET* prgPropertySets = NULL;
  1912. DBPROPIDSET rgPropIDSet[1];
  1913. VARIANT varValue;
  1914. VariantInit(&varValue);
  1915. rgPropIDSet[0].cPropertyIDs = 0;
  1916. rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
  1917. //==============================================================================
  1918. // Get the properties set thru IDBBinderProperties
  1919. //==============================================================================
  1920. if(SUCCEEDED(hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets)))
  1921. {
  1922. //==============================================================================
  1923. // If the column refers to a rowset ( pointing to a qualifier) get the rowset
  1924. //==============================================================================
  1925. if(bIsChildRowset)
  1926. {
  1927. hr = GetChildRowet(pUnkOuter,strColName ,prgPropertySets,cPropSets,riid,ppUnk);
  1928. }
  1929. //======================
  1930. // else get a row
  1931. //======================
  1932. else
  1933. {
  1934. hr = GetChildRow(pUnkOuter,strColName ,prgPropertySets,cPropSets,riid,ppUnk);
  1935. }
  1936. }
  1937. //==========================================================================
  1938. // Free memory we allocated to by GetProperties
  1939. //==========================================================================
  1940. m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
  1941. return hr;
  1942. }
  1943. ///////////////////////////////////////////////////////////////
  1944. // Function to parse the column name to get the property name
  1945. // The returned pointer is to released by the caller
  1946. ///////////////////////////////////////////////////////////////
  1947. WCHAR * CRow::GetPropertyNameFromColName(WCHAR *pColName)
  1948. {
  1949. WCHAR *pQualiferSuffix = NULL;
  1950. WCHAR *pPropName = NULL;
  1951. try
  1952. {
  1953. pQualiferSuffix = new WCHAR[wcslen(SEPARATOR) + wcslen(QUALIFIER_) + 1];
  1954. }
  1955. catch(...)
  1956. {
  1957. SAFE_DELETE_ARRAY(pQualiferSuffix);
  1958. throw;
  1959. }
  1960. if(pQualiferSuffix)
  1961. {
  1962. swprintf(pQualiferSuffix,L"%s%s",SEPARATOR,QUALIFIER_);
  1963. if( wcsstr(pColName,pQualiferSuffix))
  1964. {
  1965. int nPropLen = wcslen(pColName) - wcslen(pQualiferSuffix) +1;
  1966. pPropName = new WCHAR [nPropLen];
  1967. //NTRaid:111767 & NTRaid:111768
  1968. // 06/07/00
  1969. if(pPropName)
  1970. {
  1971. memset(pPropName,0,nPropLen * sizeof(WCHAR));
  1972. memcpy(pPropName,pColName , (nPropLen-1) * sizeof(WCHAR));
  1973. }
  1974. }
  1975. SAFE_DELETE_ARRAY(pQualiferSuffix);
  1976. }
  1977. return pPropName;
  1978. }
  1979. //////////////////////////////////////////////////////////////////////////////////////
  1980. // Function which get the embeded instance given the URL of the instance
  1981. //////////////////////////////////////////////////////////////////////////////////////
  1982. HRESULT CRow::GetEmbededInstancePtrAndSetMapClass(CURLParser *urlParser)
  1983. {
  1984. BSTR strPath;
  1985. BSTR strProperty;
  1986. int nIndex = 0;
  1987. DWORD dwFlags = 0;
  1988. WCHAR * strTableName;
  1989. HRESULT hr = S_OK;
  1990. urlParser->GetPath(strPath);
  1991. urlParser->GetEmbededInstInfo(strProperty,nIndex);
  1992. m_pInstance = (CWbemClassInstanceWrapper *)m_pMap->GetEmbededInstance(strPath,strProperty,nIndex);
  1993. if( m_pInstance == NULL)
  1994. {
  1995. hr = E_FAIL;
  1996. }
  1997. else
  1998. {
  1999. //==================================================
  2000. // Set the class name of the wmioledbmap function
  2001. //==================================================
  2002. strTableName = m_pInstance->GetClassName();
  2003. hr = m_pMap->SetClass(strTableName);
  2004. delete [] strTableName;
  2005. SysFreeString(strPath);
  2006. SysFreeString(strProperty);
  2007. }
  2008. return hr;
  2009. }
  2010. //////////////////////////////////////////////////////////////////////////////////////
  2011. // Function to get a child row of the particular row which is pointed by a particular
  2012. // column
  2013. //////////////////////////////////////////////////////////////////////////////////////
  2014. HRESULT CRow::GetChildRow( IUnknown *pUnkOuter,
  2015. WCHAR *strColName,
  2016. DBPROPSET *prgPropertySets,
  2017. ULONG cPropSets,
  2018. REFIID riid,
  2019. IUnknown **ppUnk)
  2020. {
  2021. HRESULT hr = S_OK;
  2022. BSTR strPath,strTable , strURL;
  2023. CURLParser urlParser;
  2024. DBCOLUMNACCESS col;
  2025. CRow *pChildRow = NULL;
  2026. memset(&col,0,sizeof(DBCOLUMNACCESS));
  2027. col.pData = &strURL;
  2028. col.columnid.eKind = DBKIND_NAME;
  2029. col.columnid.uName.pwszName = strColName; ;
  2030. col.wType = DBTYPE_BSTR;
  2031. if(SUCCEEDED(hr = GetColumnData(col)))
  2032. {
  2033. urlParser.SetURL(strURL);
  2034. urlParser.GetClassName(strTable);
  2035. hr = urlParser.GetPathWithEmbededInstInfo(strPath);
  2036. try
  2037. {
  2038. pChildRow = new CRow(pUnkOuter, m_pCreator);
  2039. }
  2040. catch(...)
  2041. {
  2042. SAFE_DELETE_PTR(pChildRow);
  2043. throw;
  2044. }
  2045. if(SUCCEEDED(hr) && SUCCEEDED(hr = pChildRow->InitRow(strPath, strTable)))
  2046. {
  2047. hr = pChildRow->QueryInterface(riid, (void **)ppUnk);
  2048. }
  2049. SysFreeString(strTable);
  2050. SysFreeString(strPath);
  2051. }
  2052. if(FAILED(hr))
  2053. {
  2054. SAFE_DELETE_PTR(pChildRow);
  2055. }
  2056. return hr;
  2057. }
  2058. //////////////////////////////////////////////////////////////////////////////////////
  2059. // Function to get a child rowset of the particular row which is pointed by a particular
  2060. // column
  2061. //////////////////////////////////////////////////////////////////////////////////////
  2062. HRESULT CRow::GetChildRowet(IUnknown *pUnkOuter,
  2063. WCHAR *strColName,
  2064. DBPROPSET *prgPropertySets,
  2065. ULONG cPropSets,
  2066. REFIID riid,
  2067. IUnknown **ppUnk)
  2068. {
  2069. HRESULT hr = S_OK;
  2070. CRowset *pChildRowset = NULL;
  2071. int iOrdinal = 0;
  2072. WCHAR *pPropName = NULL;
  2073. ULONG lRsType = 0;
  2074. lRsType = m_pMap->ParseQualifiedNameToGetColumnType(strColName);
  2075. if(lRsType == WMI_PROPERTY_QUALIFIER)
  2076. {
  2077. //=============================================================
  2078. // Get the name of the property for which the qualifiers are
  2079. // to be retrieved as rowset
  2080. //=============================================================
  2081. pPropName = GetPropertyNameFromColName(strColName);
  2082. lRsType = PROPERTYQUALIFIER;
  2083. }
  2084. else
  2085. if(lRsType == WMI_CLASS_QUALIFIER)
  2086. {
  2087. lRsType = CLASSQUALIFIER;
  2088. }
  2089. if((pPropName != NULL && lRsType == PROPERTYQUALIFIER) ||
  2090. lRsType == CLASSQUALIFIER)
  2091. {
  2092. try
  2093. {
  2094. //================================
  2095. // Create a new rowset
  2096. //================================
  2097. pChildRowset = new CRowset(pUnkOuter,lRsType, pPropName,m_pCreator,m_pMap);
  2098. }
  2099. catch(...)
  2100. {
  2101. SAFE_DELETE_PTR(pChildRowset);
  2102. throw;
  2103. }
  2104. // Initialize the rowset
  2105. if( pChildRowset)
  2106. if(S_OK == (hr = pChildRowset->InitRowsetForRow(pUnkOuter,cPropSets,prgPropertySets,m_pInstance)))
  2107. {
  2108. hr = pChildRowset->QueryInterface(riid , (void **)ppUnk);
  2109. }
  2110. SAFE_DELETE_ARRAY(pPropName);
  2111. }
  2112. else
  2113. {
  2114. hr = DB_E_BADCOLUMNID;
  2115. }
  2116. return hr;
  2117. }
  2118. ////////////////////////////////////////////////////////////////////////////////////////
  2119. // Creates a new instance
  2120. // called from ICreateRow::CreateRow
  2121. ////////////////////////////////////////////////////////////////////////////////////////
  2122. HRESULT CRow::CreateNewRow(CWbemClassInstanceWrapper **pNewInst)
  2123. {
  2124. return m_pMap->AddNewInstance((CWbemClassWrapper **)pNewInst);
  2125. }
  2126. ////////////////////////////////////////////////////////////////////////////////////////
  2127. // Function which gets all the key values from the URL and updates it to
  2128. // the new instance
  2129. ////////////////////////////////////////////////////////////////////////////////////////
  2130. HRESULT CRow::UpdateKeysForNewInstance()
  2131. {
  2132. HRESULT hr = S_OK;
  2133. DBCOLUMNACCESS dbCol;
  2134. SAFEARRAY *psaKeyPropNames;
  2135. LONG lBound = 0 , uBound = 0;
  2136. BSTR strProperty;
  2137. LONG rgIndices[1];
  2138. CURLParser urlParser;
  2139. VARIANT varKeyValue;
  2140. CWbemClassWrapper * pTempInstance = NULL;
  2141. VariantInit(&varKeyValue);
  2142. urlParser.SetPath(m_strKey);
  2143. memset(&dbCol,0,sizeof(DBCOLUMNACCESS));
  2144. dbCol.columnid.eKind = DBKIND_NAME;
  2145. dbCol.columnid.uName.pwszName = NULL;
  2146. dbCol.cbDataLen = -1;
  2147. dbCol.wType = DBTYPE_VARIANT | DBTYPE_BYREF;
  2148. // Get the propertynames of the key values
  2149. hr = m_pMap->GetKeyPropertyNames(&psaKeyPropNames);
  2150. // Get the bounds of the array returned
  2151. hr = SafeArrayGetLBound(psaKeyPropNames,1,&lBound);
  2152. hr = SafeArrayGetUBound(psaKeyPropNames,1,&uBound);
  2153. // Navigate thru every element of the array
  2154. for( int nIndex = lBound ; nIndex <= uBound ; nIndex++)
  2155. {
  2156. rgIndices[0] = nIndex;
  2157. hr = SafeArrayGetElement(psaKeyPropNames,&rgIndices[0],(void *)&strProperty);
  2158. // Get the value of the key from the URL
  2159. if(SUCCEEDED(hr = urlParser.GetKeyValue(strProperty,varKeyValue)))
  2160. {
  2161. dbCol.columnid.uName.pwszName = (WCHAR *)strProperty;
  2162. dbCol.pData = &varKeyValue;
  2163. hr = SetColumnData(dbCol,TRUE);
  2164. VariantClear(&varKeyValue);
  2165. if(hr != S_OK)
  2166. {
  2167. break;
  2168. }
  2169. }
  2170. }
  2171. // Destroy the array created
  2172. SafeArrayDestroy(psaKeyPropNames);
  2173. if(SUCCEEDED(hr))
  2174. {
  2175. // call this function to save the new instance
  2176. hr = m_pMap->UpdateInstance(m_pInstance,TRUE);
  2177. }
  2178. // The instance may be created, but we have to
  2179. // check if the URL passed identifies the row , if no
  2180. // then return error
  2181. if( hr == S_OK)
  2182. {
  2183. // Convert it into upper case
  2184. pTempInstance = m_pMap->GetInstance(m_strKey);
  2185. if(pTempInstance == NULL)
  2186. {
  2187. hr = DB_E_NOTFOUND;
  2188. }
  2189. else
  2190. {
  2191. m_pInstance = (CWbemClassInstanceWrapper *)pTempInstance;
  2192. }
  2193. }
  2194. // Delete the instance created if there
  2195. // any failure in the process of creating new instance
  2196. if(FAILED(hr))
  2197. {
  2198. m_pMap->DeleteInstance(m_pInstance);
  2199. m_pInstance = NULL;
  2200. hr = DB_E_NOTFOUND;
  2201. }
  2202. return hr;
  2203. }
  2204. ////////////////////////////////////////////////////////////////////////////////////////
  2205. // Function to open a row pointed by the URL
  2206. ////////////////////////////////////////////////////////////////////////////////////////
  2207. HRESULT CRow::OpenRow(LPCOLESTR pwszURL,IUnknown * pUnkOuter,REFIID riid,IUnknown** ppOut)
  2208. {
  2209. HRESULT hr = S_OK;
  2210. LONG lObjType = -1;
  2211. CRow * pRow = NULL;
  2212. CURLParser urlParser;
  2213. CBSTR bstrTemp;
  2214. CBSTR bstrPath;
  2215. CBSTR bstrClassName;
  2216. bstrTemp.SetStr((LPWSTR)pwszURL);
  2217. urlParser.SetURL((BSTR)bstrTemp);
  2218. lObjType = urlParser.GetURLType();
  2219. switch(lObjType)
  2220. {
  2221. case URL_ROW:
  2222. {
  2223. urlParser.GetPath((BSTR &)bstrPath);
  2224. urlParser.GetClassName((BSTR &)bstrClassName);
  2225. }
  2226. break;
  2227. case -1 :
  2228. {
  2229. hr = DB_E_NOTFOUND;
  2230. break;
  2231. }
  2232. default:
  2233. {
  2234. urlParser.GetPath((BSTR &)bstrPath);
  2235. break;
  2236. }
  2237. }
  2238. if(SUCCEEDED(hr))
  2239. {
  2240. try
  2241. {
  2242. pRow = new CRow(pUnkOuter,m_pCreator);
  2243. }
  2244. catch(...)
  2245. {
  2246. SAFE_DELETE_PTR(pRow);
  2247. }
  2248. if(SUCCEEDED(hr))
  2249. {
  2250. hr = pRow->InitRow(bstrPath,bstrClassName,GetQualifierFlags(),ROWOPEN);
  2251. }
  2252. if(SUCCEEDED(hr))
  2253. {
  2254. DBPROPSET* prgPropertySets;
  2255. DBPROPIDSET rgPropIDSet[1];
  2256. ULONG cPropSets = 1;
  2257. rgPropIDSet[0].cPropertyIDs = 0;
  2258. rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
  2259. //==============================================================================
  2260. // Get the properties set thru of the current row and set it on the rowset
  2261. //==============================================================================
  2262. if(SUCCEEDED(hr = m_pUtilProp->GetProperties(PROPSET_ROWSET,0,rgPropIDSet, &cPropSets,&prgPropertySets)))
  2263. {
  2264. hr = pRow->SetRowProperties(cPropSets,prgPropertySets);
  2265. }
  2266. //==========================================================================
  2267. // Free memory we allocated to by GetProperties
  2268. //==========================================================================
  2269. m_pUtilProp->m_PropMemMgr.FreeDBPROPSET( cPropSets, prgPropertySets);
  2270. if(FAILED(hr = pRow->QueryInterface(riid,(void **)ppOut)))
  2271. {
  2272. SAFE_DELETE_PTR(pRow);
  2273. *ppOut = NULL;
  2274. }
  2275. }
  2276. }
  2277. return hr;
  2278. }
  2279. ////////////////////////////////////////////////////////////////////////////////////////
  2280. // Function to open a rowset which contains instance of container/scope
  2281. ////////////////////////////////////////////////////////////////////////////////////////
  2282. HRESULT CRow::OpenRowset(LPCOLESTR pwszURL,
  2283. IUnknown * pUnkOuter,
  2284. REFIID riid,
  2285. BOOL bContainer,
  2286. IUnknown** ppOut,
  2287. ULONG cPropertySets,
  2288. DBPROPSET __RPC_FAR rgPropertySets[])
  2289. {
  2290. HRESULT hr = S_OK;
  2291. WCHAR * pstrPath = NULL;
  2292. ULONG cPropSets = 1;
  2293. CRowset * pRowset = NULL;
  2294. DBPROPIDSET rgPropIDSet[1];
  2295. VARIANT varValue;
  2296. VariantInit(&varValue);
  2297. WCHAR * pstrTemp = NULL;
  2298. WCHAR * pStrRelPath = NULL;
  2299. LPWSTR pStrObjectToOpen = NULL;
  2300. rgPropIDSet[0].cPropertyIDs = 0;
  2301. rgPropIDSet[0].guidPropertySet = DBPROPSET_ROWSET;
  2302. pRowset = new CRowset(pUnkOuter,m_pCreator,m_pCon);
  2303. if(!pRowset)
  2304. {
  2305. hr = E_OUTOFMEMORY;
  2306. }
  2307. if(SUCCEEDED(hr))
  2308. {
  2309. INSTANCELISTTYPE ObjInstListType = GetObjectTypeProp(cPropertySets, rgPropertySets);
  2310. WCHAR * pStrPath = NULL;
  2311. CURLParser urlParser;
  2312. CBSTR bstrTemp;
  2313. if(!bContainer)
  2314. {
  2315. // Get the relative path of the current object
  2316. if(SUCCEEDED(hr = m_pMap->GetRelativePath(m_pInstance,pStrRelPath)))
  2317. {
  2318. //===========================================
  2319. // If URL is passed open rowset on the URL
  2320. //===========================================
  2321. if(pwszURL == NULL)
  2322. {
  2323. pstrTemp = pStrRelPath;
  2324. }
  2325. //===========================================
  2326. // else get URL of the current row
  2327. //===========================================
  2328. else
  2329. {
  2330. pstrTemp = new WCHAR[wcslen(pStrRelPath) + wcslen(pwszURL) + wcslen(PATHSEPARATOR) + 1];
  2331. if(pstrTemp)
  2332. {
  2333. wcscpy(pstrTemp,pStrRelPath);
  2334. wcscat(pstrTemp,PATHSEPARATOR);
  2335. wcscat(pstrTemp,pwszURL);
  2336. SAFE_DELETE_ARRAY(pStrRelPath);
  2337. pStrRelPath = pstrTemp;
  2338. }
  2339. else
  2340. {
  2341. hr = E_OUTOFMEMORY;
  2342. }
  2343. }
  2344. }
  2345. }
  2346. else
  2347. {
  2348. CBSTR strObjPath;
  2349. VARIANT varDataSource;
  2350. VariantInit(&varDataSource);
  2351. if(m_pCon)
  2352. {
  2353. if(SUCCEEDED(hr = m_pCon->GetNodeName(varDataSource.bstrVal)))
  2354. {
  2355. varDataSource.vt = VT_BSTR;
  2356. }
  2357. }
  2358. else
  2359. {
  2360. if(SUCCEEDED(hr = m_pCreator->GetDataSrcProperty(DBPROP_INIT_DATASOURCE,varDataSource)) &&
  2361. varDataSource.vt == VT_BSTR && varDataSource.bstrVal != NULL )
  2362. {
  2363. hr = S_OK;
  2364. }
  2365. else
  2366. {
  2367. hr = E_UNEXPECTED;
  2368. }
  2369. }
  2370. if(SUCCEEDED(hr))
  2371. {
  2372. m_pMap->GetInstanceKey(m_pInstance,strObjPath);
  2373. if(strObjPath != NULL && _wcsicmp(strObjPath,varDataSource.bstrVal) != 0)
  2374. {
  2375. hr = m_pMap->GetRelativePath(m_pInstance,pStrObjectToOpen);
  2376. }
  2377. else
  2378. {
  2379. pStrObjectToOpen = NULL;
  2380. }
  2381. }
  2382. VariantClear(&varDataSource);
  2383. pstrTemp = (WCHAR *)pwszURL;
  2384. }
  2385. /* bstrTemp.SetStr(pstrTemp);
  2386. urlParser.SetURL((BSTR)bstrTemp);
  2387. bstrTemp.Clear();
  2388. urlParser.GetPath((BSTR &)bstrTemp);
  2389. */
  2390. if(SUCCEEDED(hr))
  2391. {
  2392. // pStrPath = new WCHAR[SysStringLen(bstrTemp) + 1];
  2393. // if(pStrPath)
  2394. {
  2395. // memset(pStrPath , 0 , (SysStringLen(bstrTemp) + 1) * sizeof(WCHAR));
  2396. // memcpy(pStrPath,bstrTemp,SysStringLen(bstrTemp) * sizeof(WCHAR));
  2397. //==========================================================================
  2398. // Call this function to open the object pointed by the URL as scope or
  2399. // container
  2400. //==========================================================================
  2401. hr = pRowset->InitRowset(cPropertySets,rgPropertySets,pstrTemp,pStrObjectToOpen,ObjInstListType);
  2402. SAFE_DELETE_ARRAY(pStrPath);
  2403. }
  2404. /* else
  2405. {
  2406. hr = E_OUTOFMEMORY;
  2407. }
  2408. */ }
  2409. }
  2410. if(SUCCEEDED(hr))
  2411. {
  2412. if(FAILED(hr = pRowset->QueryInterface(riid,(void **)ppOut)))
  2413. {
  2414. SAFE_DELETE_PTR(pRowset);
  2415. *ppOut = NULL;
  2416. }
  2417. }
  2418. else
  2419. {
  2420. SAFE_DELETE_PTR(pRowset);
  2421. *ppOut = NULL;
  2422. }
  2423. SAFE_DELETE_ARRAY(pStrObjectToOpen);
  2424. SAFE_DELETE_ARRAY(pStrRelPath);
  2425. return hr;
  2426. }
  2427. ////////////////////////////////////////////////////////////////////////////////////////
  2428. // Function to set properties of the row
  2429. ////////////////////////////////////////////////////////////////////////////////////////
  2430. HRESULT CRow::SetRowProperties(const ULONG cPropertySets, const DBPROPSET rgPropertySets[] )
  2431. {
  2432. HRESULT hr = S_OK;
  2433. VARIANT varPropVal;
  2434. VariantInit(&varPropVal);
  2435. LONG lFlag = 0;
  2436. // call the base class implementation for setting properties
  2437. hr = SetProperties(cPropertySets,rgPropertySets);
  2438. //============================================================================
  2439. // call this function to set the DBPROP_UPDATIBILITY to readonly if the Datasource
  2440. // open mode is readonly
  2441. //============================================================================
  2442. if( (hr == S_OK) || (hr == DB_S_ERRORSOCCURRED) )
  2443. {
  2444. SynchronizeDataSourceMode();
  2445. }
  2446. return hr;
  2447. }
  2448. ////////////////////////////////////////////////////////////////////////////////////////
  2449. // Function to delete/unlink objects from scope/container
  2450. // Object will be deleted if the current object is opened as scope
  2451. // object will be unlinked from the current object is opened as container
  2452. ////////////////////////////////////////////////////////////////////////////////////////
  2453. HRESULT CRow::Delete(LPCOLESTR lpszURL,DWORD dwDeleteFlags,DBSTATUS &dbStatus)
  2454. {
  2455. HRESULT hr = S_OK;
  2456. BOOL bContainer = FALSE;
  2457. CURLParser urlParser;
  2458. CBSTR strTemp;
  2459. dbStatus = DBSTATUS_S_OK;
  2460. strTemp.SetStr((LPWSTR)lpszURL);
  2461. urlParser.SetURL(strTemp);
  2462. strTemp.Unbind();
  2463. strTemp.Clear();
  2464. urlParser.GetPath((BSTR &)strTemp);
  2465. bContainer = IsContainer();
  2466. if(bContainer)
  2467. {
  2468. CBSTR strContainer;
  2469. strContainer.SetStr(m_strKey);
  2470. //==============================================================
  2471. // call this function to unlink object pointed by strTemp
  2472. // from object pointed by m_strPath acting as container
  2473. //==============================================================
  2474. if(FAILED(hr = m_pMap->UnlinkObjectFromContainer(strContainer,strTemp)))
  2475. {
  2476. dbStatus = DBSTATUS_E_UNAVAILABLE;
  2477. }
  2478. }
  2479. else
  2480. {
  2481. //==============================================================
  2482. // Get the instance pointed by the path and then
  2483. // delete the object
  2484. //==============================================================
  2485. CWbemClassWrapper *pInstToDelete = NULL;
  2486. pInstToDelete = m_pMap->GetInstance(strTemp);
  2487. if(pInstToDelete)
  2488. {
  2489. hr = m_pMap->DeleteInstance(pInstToDelete);
  2490. }
  2491. else
  2492. {
  2493. dbStatus = DBSTATUS_E_UNAVAILABLE;
  2494. }
  2495. } // else
  2496. return hr;
  2497. }
  2498. ////////////////////////////////////////////////////////////////////////////////////////
  2499. // Function to move object from one container to another
  2500. ////////////////////////////////////////////////////////////////////////////////////////
  2501. HRESULT CRow::MoveObjects(WCHAR * pStrDstURL,WCHAR * pstrSrcURL, WCHAR *& pNewURL,DBSTATUS &dbStatus)
  2502. {
  2503. HRESULT hr = S_OK;
  2504. BOOL bContainer = FALSE;
  2505. CBSTR strSrcObj,strDstObj;
  2506. dbStatus = DBSTATUS_S_OK;
  2507. //============================================================
  2508. // Get the Path string for source and destination objects
  2509. //============================================================
  2510. strSrcObj.SetStr(pstrSrcURL);
  2511. if(GetPathFromURL((BSTR &)strSrcObj))
  2512. {
  2513. strDstObj.SetStr(pStrDstURL);
  2514. if(GetPathFromURL((BSTR &)strDstObj))
  2515. {
  2516. hr = E_FAIL;
  2517. dbStatus = DBSTATUS_E_INVALIDURL;
  2518. }
  2519. }
  2520. else
  2521. {
  2522. hr = E_FAIL;
  2523. dbStatus = DBSTATUS_E_INVALIDURL;
  2524. }
  2525. if(SUCCEEDED(hr))
  2526. {
  2527. CBSTR strContainer;
  2528. strContainer.SetStr(m_strKey);
  2529. //==============================================================
  2530. // call this function to unlink object pointed by strSrcObj
  2531. // from object pointed by m_strPath acting as container
  2532. //==============================================================
  2533. if(FAILED(hr = m_pMap->UnlinkObjectFromContainer(strContainer,strSrcObj)))
  2534. {
  2535. dbStatus = DBSTATUS_E_UNAVAILABLE;
  2536. }
  2537. else
  2538. //==============================================================
  2539. // call this function to link object pointed by strSrcObj
  2540. // to object pointed by strDstObj acting as container
  2541. //==============================================================
  2542. if(FAILED(hr = m_pMap->LinkObjectFromContainer(strDstObj,strSrcObj)))
  2543. {
  2544. dbStatus = DBSTATUS_E_UNAVAILABLE;
  2545. }
  2546. try
  2547. {
  2548. pNewURL = new WCHAR[wcslen(pstrSrcURL) +1];
  2549. }
  2550. catch(...)
  2551. {
  2552. SAFE_DELETE_ARRAY(pNewURL);
  2553. throw;
  2554. }
  2555. if(pNewURL)
  2556. {
  2557. //==============================================================
  2558. // URL of the object does not change as this is just a move of
  2559. // object from one container to another
  2560. //==============================================================
  2561. wcscpy(pNewURL,pstrSrcURL);
  2562. }
  2563. else
  2564. {
  2565. hr = E_OUTOFMEMORY;
  2566. }
  2567. } // If succeeded(hr)
  2568. return hr;
  2569. }
  2570. ////////////////////////////////////////////////////////////////////////////////////////
  2571. // Function to get Path from URL string
  2572. ////////////////////////////////////////////////////////////////////////////////////////
  2573. BOOL CRow::GetPathFromURL(BSTR &str)
  2574. {
  2575. BOOL bRet = FALSE;
  2576. CURLParser urlParser;
  2577. if(SUCCEEDED( urlParser.SetURL(str)))
  2578. {
  2579. SysFreeString(str);
  2580. urlParser.GetPath(str);
  2581. bRet = TRUE;
  2582. }
  2583. return bRet;
  2584. }
  2585. ////////////////////////////////////////////////////////////////////////////////////////
  2586. // Function to check if the current object is to be considered as Scope/Container
  2587. ////////////////////////////////////////////////////////////////////////////////////////
  2588. BOOL CRow::IsContainer()
  2589. {
  2590. VARIANT vValue;
  2591. BOOL bRet = FALSE;
  2592. VariantInit(&vValue);
  2593. if(SUCCEEDED(GetRowsetProperty(DBPROP_WMIOLEDB_OBJECTTYPE,vValue)))
  2594. {
  2595. bRet = (V_I4(&vValue) == DBPROPVAL_CONTAINEROBJ) ? TRUE : FALSE;
  2596. }
  2597. return bRet;
  2598. }
  2599. ////////////////////////////////////////////////////////////////////////////////////////
  2600. // Function to move object from one container to another
  2601. ////////////////////////////////////////////////////////////////////////////////////////
  2602. HRESULT CRow::CopyObjects(WCHAR * pStrDstURL,WCHAR * pstrSrcURL, WCHAR *& pNewURL,DBSTATUS &dbStatus)
  2603. {
  2604. HRESULT hr = S_OK;
  2605. BOOL bContainer = FALSE;
  2606. CBSTR strSrcObj,strDstObj;
  2607. dbStatus = DBSTATUS_S_OK;
  2608. //============================================================
  2609. // Get the Path string for source and destination objects
  2610. //============================================================
  2611. strSrcObj.SetStr(pstrSrcURL);
  2612. if(GetPathFromURL((BSTR &)strSrcObj))
  2613. {
  2614. strDstObj.SetStr(pStrDstURL);
  2615. if(GetPathFromURL((BSTR &)strDstObj))
  2616. {
  2617. hr = E_FAIL;
  2618. dbStatus = DBSTATUS_E_INVALIDURL;
  2619. }
  2620. }
  2621. else
  2622. {
  2623. hr = E_FAIL;
  2624. dbStatus = DBSTATUS_E_INVALIDURL;
  2625. }
  2626. if(SUCCEEDED(hr))
  2627. {
  2628. WCHAR * pstrNewPath = NULL;
  2629. if(IsContainer())
  2630. {
  2631. //==============================================================
  2632. // call this function to link object pointed by strSrcObj
  2633. // to object pointed by strDstObj acting as container
  2634. //==============================================================
  2635. hr = m_pMap->LinkObjectFromContainer(strDstObj,strSrcObj);
  2636. pstrNewPath = pstrSrcURL;
  2637. }
  2638. else
  2639. {
  2640. // Memory for pstrNewPath will be allocated in this function
  2641. hr = m_pMap->CloneAndAddNewObjectInScope(strSrcObj,strDstObj,pstrNewPath);
  2642. }
  2643. if(FAILED(hr))
  2644. {
  2645. dbStatus = DBSTATUS_E_UNAVAILABLE;
  2646. }
  2647. try
  2648. {
  2649. pNewURL = new WCHAR[wcslen(pstrSrcURL) +1];
  2650. }
  2651. catch(...)
  2652. {
  2653. SAFE_DELETE_ARRAY(pNewURL);
  2654. if(!IsContainer())
  2655. {
  2656. SAFE_DELETE_ARRAY(pstrNewPath);
  2657. }
  2658. throw;
  2659. }
  2660. if(pNewURL)
  2661. {
  2662. //==============================================================
  2663. // URL of the object does not change as this is just a move of
  2664. // object from one container to another
  2665. //==============================================================
  2666. wcscpy(pNewURL,pstrSrcURL);
  2667. }
  2668. else
  2669. {
  2670. hr = E_OUTOFMEMORY;
  2671. }
  2672. if(!IsContainer())
  2673. {
  2674. SAFE_DELETE_ARRAY(pstrNewPath);
  2675. }
  2676. } // If succeeded(hr)
  2677. return hr;
  2678. }
  2679. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2680. // Function to fetch IUnknown properties
  2681. // NTRaid:135384
  2682. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2683. HRESULT CRow::GetIUnknownColumnValue(DBORDINAL iCol,REFIID riid,IUnknown ** ppUnk,LPCWSTR pStrColName)
  2684. {
  2685. ROWBUFF * pRowBuff = NULL;
  2686. COLUMNDATA * pColumnData = NULL;
  2687. void * pSrc = NULL;
  2688. BSTR strProp = NULL;
  2689. DBTYPE dwDataType = 0;
  2690. BYTE * pTemp = NULL;
  2691. DBLENGTH uDatLength = 0;
  2692. DWORD dwFlags = 0;
  2693. HRESULT hr = S_OK;
  2694. BOOL bGetData = TRUE;
  2695. *ppUnk = NULL;
  2696. if(m_pSourcesRowset)
  2697. {
  2698. // if the column is part of the parent rowset then get data from the parent rowset's buffer
  2699. if(iCol == m_pSourcesRowset->GetOrdinalFromColName((WCHAR *)pStrColName))
  2700. {
  2701. // Set this flag that data to be retrieved is identified
  2702. bGetData = FALSE;
  2703. //=========================================================
  2704. // if data is not yet received then fetch the data
  2705. //=========================================================
  2706. if(S_OK != m_pSourcesRowset->IsSlotSet(m_hRow))
  2707. {
  2708. hr = m_pSourcesRowset->GetData(m_hRow);
  2709. }
  2710. if( (m_pSourcesRowset->m_ulProps & OTHERUPDATEDELETE) &&(m_pSourcesRowset->m_ulLastFetchedRow != m_hRow))
  2711. {
  2712. if(SUCCEEDED(hr = m_pSourcesRowset->GetDataToLocalBuffer(m_hRow)))
  2713. {
  2714. m_pSourcesRowset->m_ulLastFetchedRow = m_hRow;
  2715. }
  2716. }
  2717. pRowBuff = m_pSourcesRowset->GetRowBuff(m_hRow , TRUE);
  2718. pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + m_pSourcesRowset->m_Columns.GetDataOffset(iCol));
  2719. pSrc = (pColumnData->pbData);
  2720. if(pSrc != NULL)
  2721. {
  2722. hr = (*(IUnknown **)pSrc)->QueryInterface(riid,(void **)ppUnk);
  2723. }
  2724. }
  2725. }
  2726. if(bGetData)
  2727. {
  2728. strProp = Wmioledb_SysAllocString(pStrColName);
  2729. hr = m_pMap->GetProperty(m_pInstance,strProp, pTemp,dwDataType ,uDatLength, dwFlags );
  2730. if(SUCCEEDED(hr) && dwDataType == DBTYPE_IUNKNOWN && pTemp != NULL)
  2731. {
  2732. hr = (*(IUnknown **)pTemp)->QueryInterface(riid,(void **)ppUnk);
  2733. }
  2734. SAFE_FREE_SYSSTRING(strProp);
  2735. }
  2736. return hr;
  2737. }