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.

2960 lines
66 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. VAR.H
  5. Abstract:
  6. CVar & CVarVector implemntation
  7. History:
  8. 16-Apr-96 a-raymcc Created.
  9. 12//17/98 sanjes - Partially Reviewed for Out of Memory.
  10. 18-Mar-99 a-dcrews Added out-of-memory exception handling
  11. --*/
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <var.h>
  16. #include <wbemutil.h>
  17. #include <genutils.h>
  18. #include <wbemidl.h>
  19. #include <corex.h>
  20. #include <arrtempl.h>
  21. #include <olewrap.h>
  22. static wchar_t g_szNullVarString[1] = {0};
  23. static wchar_t* g_pszNullVarString = &g_szNullVarString[0];
  24. //***************************************************************************
  25. //
  26. // CVar::Empty
  27. //
  28. // Constructor helper.
  29. //
  30. // This merely clears everything. VT_EMPTY is the default.
  31. //
  32. //***************************************************************************
  33. void CVar::Init()
  34. {
  35. m_nStatus = no_error;
  36. m_vt = VT_EMPTY;
  37. m_bCanDelete = TRUE;
  38. memset(&m_value, 0, sizeof(METAVALUE));
  39. }
  40. //***************************************************************************
  41. //
  42. // CVar::~CVar
  43. //
  44. // Destructor.
  45. //
  46. //***************************************************************************
  47. CVar::~CVar()
  48. {
  49. Empty();
  50. }
  51. //***************************************************************************
  52. //
  53. // CVar::CVar
  54. //
  55. // Copy constructor. This is implemented via the assignment operator.
  56. //
  57. //***************************************************************************
  58. CVar::CVar(CVar &Src)
  59. {
  60. m_vt = VT_EMPTY;
  61. m_nStatus = no_error;
  62. memset(&m_value, 0, sizeof(METAVALUE));
  63. *this = Src;
  64. }
  65. //***************************************************************************
  66. //
  67. // CVar::operator =
  68. //
  69. // NOTES:
  70. // Observe that VT_EX_CVARVECTOR is dedicated to embedded CVarVector objects.
  71. // Also, only pointer types require a new allocation + copy, whereas
  72. // most of the simple types are directly assignable, in the <default>
  73. // label of the switch statement.
  74. //
  75. //***************************************************************************
  76. CVar& CVar::operator =(CVar &Src)
  77. {
  78. Empty();
  79. m_vt = Src.m_vt;
  80. m_nStatus = m_nStatus;
  81. m_bCanDelete = TRUE;
  82. switch (m_vt) {
  83. case VT_LPSTR:
  84. // Check for an allocation failure
  85. if ( NULL != Src.m_value.pStr )
  86. {
  87. m_value.pStr = new char[strlen(Src.m_value.pStr) + 1];
  88. if ( NULL == m_value.pStr )
  89. {
  90. throw CX_MemoryException();
  91. }
  92. strcpy( m_value.pStr, Src.m_value.pStr );
  93. }
  94. else
  95. {
  96. m_value.pStr = NULL;
  97. }
  98. break;
  99. case VT_LPWSTR:
  100. case VT_BSTR:
  101. // Check for an allocation failure
  102. if ( NULL != Src.m_value.pWStr )
  103. {
  104. m_value.pWStr = new wchar_t[wcslen(Src.m_value.pWStr) + 1];
  105. if ( NULL == m_value.pWStr )
  106. {
  107. throw CX_MemoryException();
  108. }
  109. wcscpy( m_value.pWStr, Src.m_value.pWStr );
  110. }
  111. else
  112. {
  113. m_value.pWStr = NULL;
  114. }
  115. break;
  116. case VT_BLOB:
  117. // This will natively throw an exception, but make sure the
  118. // original value is cleared in case an exception is thrown
  119. // so we don't AV destructing this object
  120. ZeroMemory( &m_value.Blob, sizeof( m_value.Blob ) );
  121. m_value.Blob = BlobCopy(&Src.m_value.Blob);
  122. break;
  123. case VT_CLSID:
  124. m_value.pClsId = new CLSID(*Src.m_value.pClsId);
  125. // Check for a failed allocation
  126. if ( NULL == m_value.pClsId )
  127. {
  128. throw CX_MemoryException();
  129. }
  130. break;
  131. case VT_DISPATCH:
  132. m_value.pDisp = Src.m_value.pDisp;
  133. if(m_value.pDisp) m_value.pDisp->AddRef();
  134. break;
  135. case VT_UNKNOWN:
  136. m_value.pUnk = Src.m_value.pUnk;
  137. if(m_value.pUnk) m_value.pUnk->AddRef();
  138. break;
  139. // CVarVector
  140. // ==========
  141. case VT_EX_CVARVECTOR:
  142. m_value.pVarVector = new CVarVector(*Src.m_value.pVarVector);
  143. // Check for a failed allocation
  144. if ( NULL == m_value.pVarVector )
  145. {
  146. throw CX_MemoryException();
  147. }
  148. break;
  149. // All remaining simple types.
  150. // ===========================
  151. default:
  152. m_value = Src.m_value;
  153. }
  154. return *this;
  155. }
  156. //***************************************************************************
  157. //
  158. // CVar::operator ==
  159. //
  160. // Equality test operator.
  161. //
  162. //***************************************************************************
  163. int CVar::operator ==(CVar &Src)
  164. {
  165. return CompareTo(Src, TRUE);
  166. }
  167. BOOL CVar::CompareTo(CVar& Src, BOOL bIgnoreCase)
  168. {
  169. // If types are not the same, forget the test.
  170. // ===========================================
  171. if (m_vt != Src.m_vt)
  172. return 0;
  173. // If here, the types are the same, so test
  174. // the fields.
  175. // ========================================
  176. switch (m_vt) {
  177. case VT_LPSTR:
  178. if(bIgnoreCase)
  179. {
  180. if (_stricmp(m_value.pStr, Src.m_value.pStr) == 0)
  181. return 1;
  182. }
  183. else
  184. {
  185. if (strcmp(m_value.pStr, Src.m_value.pStr) == 0)
  186. return 1;
  187. }
  188. break;
  189. case VT_LPWSTR:
  190. case VT_BSTR:
  191. if(bIgnoreCase)
  192. {
  193. if (wbem_wcsicmp(m_value.pWStr, Src.m_value.pWStr) == 0)
  194. return 1;
  195. }
  196. else
  197. {
  198. if (wcscmp( m_value.pWStr, Src.m_value.pWStr) == 0)
  199. return 1;
  200. }
  201. break;
  202. case VT_BLOB:
  203. if (BlobLength(&m_value.Blob) != BlobLength(&Src.m_value.Blob))
  204. return 0;
  205. if (memcmp(BlobDataPtr(&m_value.Blob), BlobDataPtr(&Src.m_value.Blob),
  206. BlobLength(&m_value.Blob)) == 0)
  207. return 1;
  208. break;
  209. case VT_CLSID:
  210. if (memcmp(m_value.pClsId, Src.m_value.pClsId, sizeof(CLSID)) == 0)
  211. return 1;
  212. break;
  213. // CVarVector
  214. // ==========
  215. case VT_EX_CVARVECTOR:
  216. if (m_value.pVarVector == Src.m_value.pVarVector)
  217. return 1;
  218. if (m_value.pVarVector == 0 || Src.m_value.pVarVector == 0)
  219. return 0;
  220. return *m_value.pVarVector == *Src.m_value.pVarVector;
  221. // All remaining simple types.
  222. // ===========================
  223. case VT_I1:
  224. return m_value.cVal == Src.m_value.cVal;
  225. case VT_UI1:
  226. return m_value.bVal == Src.m_value.bVal;
  227. case VT_I2:
  228. return m_value.iVal == Src.m_value.iVal;
  229. case VT_UI2:
  230. return m_value.wVal == Src.m_value.wVal;
  231. case VT_I4:
  232. return m_value.lVal == Src.m_value.lVal;
  233. case VT_UI4:
  234. return m_value.dwVal == Src.m_value.dwVal;
  235. case VT_BOOL:
  236. return m_value.boolVal == Src.m_value.boolVal;
  237. case VT_R8:
  238. return m_value.dblVal == Src.m_value.dblVal;
  239. case VT_R4:
  240. return m_value.fltVal == Src.m_value.fltVal;
  241. case VT_DISPATCH:
  242. // Note: no proper comparison of embedded objects.
  243. return m_value.pDisp == Src.m_value.pDisp;
  244. case VT_UNKNOWN:
  245. // Note: no proper comparison of embedded objects.
  246. return m_value.pUnk == Src.m_value.pUnk;
  247. case VT_FILETIME:
  248. if (memcmp(&m_value.Time, &Src.m_value.Time, sizeof(FILETIME)) == 0)
  249. return 1;
  250. case VT_NULL:
  251. return 1;
  252. }
  253. return 0;
  254. }
  255. //***************************************************************************
  256. //
  257. // CVar::Empty
  258. //
  259. // Clears the CVar to 'empty', deallocates any objects based on pointers,
  260. // unless bCanDelete is set to FALSE, indicating that the stored pointer
  261. // is owned by somebody else.
  262. //
  263. //***************************************************************************
  264. void CVar::Empty()
  265. {
  266. if(m_bCanDelete)
  267. {
  268. // Only pointer types require a deallocation phase.
  269. // =================================================
  270. switch (m_vt) {
  271. case VT_LPSTR: delete m_value.pStr; break;
  272. case VT_LPWSTR: delete m_value.pWStr; break;
  273. case VT_BSTR: delete m_value.Str; break;
  274. case VT_BLOB: BlobClear(&m_value.Blob); break;
  275. case VT_CLSID: delete m_value.pClsId; break;
  276. case VT_EX_CVARVECTOR: delete m_value.pVarVector; break;
  277. case VT_DISPATCH: if(m_value.pDisp) m_value.pDisp->Release(); break;
  278. case VT_UNKNOWN: if(m_value.pUnk) m_value.pUnk->Release(); break;
  279. }
  280. }
  281. memset(&m_value, 0, sizeof(METAVALUE));
  282. m_vt = VT_EMPTY;
  283. m_nStatus = no_error;
  284. m_bCanDelete = TRUE;
  285. }
  286. //***************************************************************************
  287. //
  288. // CVar::IsDataNull
  289. //
  290. // Determines if this CVar contains a NULL pointer.
  291. //
  292. //***************************************************************************
  293. BOOL CVar::IsDataNull()
  294. {
  295. if(m_vt == VT_LPWSTR && m_value.pWStr == NULL)
  296. return TRUE;
  297. if(m_vt == VT_LPSTR && m_value.pStr == NULL)
  298. return TRUE;
  299. if(m_vt == VT_BSTR && m_value.Str == NULL)
  300. return TRUE;
  301. if(m_vt == VT_DISPATCH && m_value.pDisp == NULL)
  302. return TRUE;
  303. if(m_vt == VT_UNKNOWN && m_value.pUnk == NULL)
  304. return TRUE;
  305. return FALSE;
  306. }
  307. //***************************************************************************
  308. //
  309. // CVar::SetRaw
  310. //
  311. // Creates a CVar from raw data. Sets the type and copies the right
  312. // number of bytes from the source to METAVALUE.
  313. //
  314. //***************************************************************************
  315. void CVar::SetRaw(int vt, void* pvData, int nDataLen)
  316. {
  317. m_vt = vt;
  318. memcpy(&m_value, pvData, nDataLen);
  319. m_nStatus = no_error;
  320. m_bCanDelete = TRUE;
  321. }
  322. //***************************************************************************
  323. //
  324. // CVar::SetSafeArray
  325. //
  326. // PARAMETERS:
  327. // nType
  328. // This is the VT_ type indicator of the SAFEARRAY.
  329. // pArray
  330. // This is the pointer to the SAFEARRAY which will be used as
  331. // a source. The SAFEARRAY is not acquired; it is copied.
  332. //
  333. //***************************************************************************
  334. void CVar::SetSafeArray(int nType, SAFEARRAY *pArray)
  335. {
  336. CVarVector *pVec = NULL;
  337. m_nStatus = no_error;
  338. try
  339. {
  340. pVec = new CVarVector(nType, pArray);
  341. // Check for a failed allocation
  342. if ( NULL == pVec )
  343. {
  344. throw CX_MemoryException();
  345. }
  346. SetVarVector(pVec, TRUE);
  347. }
  348. catch (CX_MemoryException)
  349. {
  350. // SetVarVector can throw an exception
  351. // m_value aquires the pVec pointer, so auto delete will not work
  352. if (NULL != pVec)
  353. {
  354. delete pVec;
  355. pVec = NULL;
  356. }
  357. throw;
  358. }
  359. }
  360. //***************************************************************************
  361. //
  362. // CVar::GetNewSafeArray
  363. //
  364. // RETURN VALUE:
  365. // A pointer to newly allocated SAFEARRAY which must be released by
  366. // SafeArrayDestroy.
  367. //
  368. //***************************************************************************
  369. SAFEARRAY *CVar::GetNewSafeArray()
  370. {
  371. CVarVector *p = (CVarVector *) GetVarVector();
  372. return p->GetNewSafeArray();
  373. }
  374. //***************************************************************************
  375. //
  376. // CVar::SetValue
  377. //
  378. // Sets the value based on an incoming VARIANT. A VARIANT containing
  379. // a SAFEARRAY is supported as long as it is not an array of VARIANTs.
  380. // Some of the other VARIANT types, such as IUnknown, Currency, etc.,
  381. // are not supported. The complete list is:
  382. // VT_UI1, VT_I2, VT_I4, VT_BSTR, VT_BOOL
  383. // VT_R4, VT_R8, or SAFEARRAY of any of these.
  384. //
  385. // PARAMETERS:
  386. // pSrc
  387. // A pointer to the source VARIANT. This is treated as read-only.
  388. //
  389. // RETURN VALUES:
  390. // no_error
  391. // Returned on succcess.
  392. // unsupported
  393. // Returned if the VARIANT contains unsupported types.
  394. //
  395. //***************************************************************************
  396. int CVar::SetVariant(VARIANT *pSrc, BOOL fOptimize /*=FALSE*/)
  397. {
  398. if(pSrc == NULL)
  399. {
  400. SetAsNull();
  401. return no_error;
  402. }
  403. // If a SAFEARRAY, check it.
  404. // =========================
  405. if (pSrc->vt & VT_ARRAY)
  406. {
  407. CVarVector *pVec = NULL;
  408. try
  409. {
  410. int nType = pSrc->vt & 0xFF; // Find the type of the array
  411. // BEGIN MODIFIED by a-levn
  412. // First, check if the incoming SAFEARRAY is NULL
  413. // ==============================================
  414. SAFEARRAY *pSafeArr;
  415. /*
  416. if(pSrc->parray == NULL)
  417. {
  418. pSafeArr = NULL;
  419. }
  420. else
  421. {
  422. // Make a copy of the SAFEARRAY using CSafeArray which will NOT
  423. // autodestruct
  424. // ============================================================
  425. CSafeArray array(pSrc->parray, nType, CSafeArray::no_delete, 0);
  426. pSafeArr = array.GetArray();
  427. }
  428. */
  429. pSafeArr = pSrc->parray;
  430. pVec = new CVarVector( nType, pSafeArr, fOptimize );
  431. // Check for an allocation failure.
  432. if ( NULL == pVec )
  433. {
  434. throw CX_MemoryException();
  435. }
  436. // END MODIFIED
  437. if (pVec->Status() != no_error)
  438. {
  439. // If here, the SAFEARRAY was not compatible.
  440. // ==========================================
  441. delete pVec;
  442. pVec = NULL;
  443. m_nStatus = unsupported;
  444. m_vt = VT_EMPTY;
  445. return unsupported;
  446. }
  447. SetVarVector(pVec, TRUE);
  448. return no_error;
  449. }
  450. catch(CX_MemoryException)
  451. {
  452. // new and SetVarVector can throw exceptions
  453. // m_value aquires the pVec pointer, so an auto delete will not work
  454. if (NULL != pVec)
  455. {
  456. delete pVec;
  457. pVec = NULL;
  458. }
  459. throw;
  460. }
  461. }
  462. // Simple copies.
  463. // ==============
  464. switch (pSrc->vt) {
  465. case VT_NULL:
  466. SetAsNull();
  467. return no_error;
  468. case VT_UI1:
  469. SetByte(pSrc->bVal);
  470. return no_error;
  471. case VT_I2:
  472. SetShort(pSrc->iVal);
  473. return no_error;
  474. case VT_I4:
  475. SetLong(pSrc->lVal);
  476. return no_error;
  477. case VT_R4:
  478. SetFloat(pSrc->fltVal);
  479. return no_error;
  480. case VT_R8:
  481. SetDouble(pSrc->dblVal);
  482. return no_error;
  483. case VT_BSTR:
  484. SetBSTR(pSrc->bstrVal);
  485. return no_error;
  486. case VT_BOOL:
  487. SetBool(pSrc->boolVal);
  488. return no_error;
  489. case VT_DISPATCH:
  490. SetDispatch(V_DISPATCH(pSrc));
  491. return no_error;
  492. case VT_UNKNOWN:
  493. SetUnknown(V_UNKNOWN(pSrc));
  494. return no_error;
  495. }
  496. m_nStatus = unsupported;
  497. return unsupported;
  498. }
  499. //***************************************************************************
  500. //
  501. // CVar::GetNewVariant
  502. //
  503. // RETURN VALUE:
  504. // A pointer to a new VARIANT which contains the value of object.
  505. // If the original value was a SAFEARRAY, then the VARIANT will contain
  506. // the embedded SAFEARRAY.
  507. //
  508. //***************************************************************************
  509. void CVar::FillVariant(VARIANT* pNew, BOOL fOptimized/* = FALSE*/)
  510. {
  511. switch (m_vt) {
  512. case VT_NULL:
  513. V_VT(pNew) = VT_NULL;
  514. break;
  515. case VT_BOOL:
  516. V_VT(pNew) = VT_BOOL;
  517. V_BOOL(pNew) = (m_value.boolVal ? VARIANT_TRUE : VARIANT_FALSE);
  518. break;
  519. case VT_BSTR:
  520. // Set type afterwards here so if the SysAlloc throws an exception, the
  521. // type will not have been reset to a VT_BSTR which could cause a subtle
  522. // memory corruption (or worse) if VariantClear is called - SJS
  523. V_BSTR(pNew) = COleAuto::_SysAllocString(m_value.Str);
  524. V_VT(pNew) = VT_BSTR;
  525. break;
  526. case VT_DISPATCH:
  527. V_VT(pNew) = VT_DISPATCH;
  528. V_DISPATCH(pNew) = m_value.pDisp;
  529. if(m_value.pDisp) m_value.pDisp->AddRef();
  530. break;
  531. case VT_UNKNOWN:
  532. V_VT(pNew) = VT_UNKNOWN;
  533. V_UNKNOWN(pNew) = m_value.pUnk;
  534. if(m_value.pUnk) m_value.pUnk->AddRef();
  535. break;
  536. case VT_UI1:
  537. V_VT(pNew) = VT_UI1;
  538. V_UI1(pNew) = m_value.bVal;
  539. break;
  540. case VT_I4:
  541. V_VT(pNew) = VT_I4;
  542. V_I4(pNew) = m_value.lVal;
  543. break;
  544. case VT_I2:
  545. V_VT(pNew) = VT_I2;
  546. V_I2(pNew) = m_value.iVal;
  547. break;
  548. case VT_R4:
  549. V_VT(pNew) = VT_R4;
  550. V_R4(pNew) = m_value.fltVal;
  551. break;
  552. case VT_R8:
  553. V_VT(pNew) = VT_R8;
  554. V_R8(pNew) = m_value.dblVal;
  555. break;
  556. // An embedded CVarVector which must be converted
  557. // to a SAFEARRAY.
  558. // ==============================================
  559. case VT_EX_CVARVECTOR:
  560. {
  561. // Set type afterwards here so if GetNewSafeArray throws an exception, the
  562. // type will not have been reset to an Array which could cause a subtle
  563. // memory corruption (or worse) if VariantClear is called - SJS
  564. if ( fOptimized && m_value.pVarVector->IsOptimized() )
  565. {
  566. // This will get the actual SAFEARRAY pointer without
  567. // copying what's underneath. Underlying code should
  568. // not clear the array, since it is being acquired
  569. V_ARRAY(pNew) = m_value.pVarVector->GetSafeArray( TRUE );
  570. V_VT(pNew) = m_value.pVarVector->GetType() | VT_ARRAY;
  571. }
  572. else
  573. {
  574. V_ARRAY(pNew) = m_value.pVarVector->GetNewSafeArray();
  575. V_VT(pNew) = m_value.pVarVector->GetType() | VT_ARRAY;
  576. }
  577. }
  578. break;
  579. default:
  580. COleAuto::_VariantClear(pNew);
  581. }
  582. }
  583. VARIANT *CVar::GetNewVariant()
  584. {
  585. VARIANT *pNew = new VARIANT;
  586. // Check for an allocation failure.
  587. if ( NULL == pNew )
  588. {
  589. throw CX_MemoryException();
  590. }
  591. COleAuto::_VariantInit(pNew);
  592. FillVariant(pNew);
  593. return pNew;
  594. }
  595. //***************************************************************************
  596. //
  597. //***************************************************************************
  598. int CVar::DumpText(FILE *fStream)
  599. {
  600. return unsupported;
  601. }
  602. //***************************************************************************
  603. //
  604. // CVar::SetLPWSTR
  605. //
  606. // Sets the value of the CVar to the indicated LPWSTR.
  607. //
  608. // PARAMETERS:
  609. // pStr
  610. // A pointer to the source string.
  611. // bAcquire
  612. // If TRUE, then the ownership of pStr is trasferred and becomes
  613. // the internal pointer to the string. If FALSE, then the string
  614. // is copied.
  615. //
  616. //***************************************************************************
  617. BOOL CVar::SetLPWSTR(LPWSTR pStr, BOOL bAcquire)
  618. {
  619. m_vt = VT_LPWSTR;
  620. if (bAcquire)
  621. {
  622. m_value.pWStr = pStr;
  623. return TRUE;
  624. }
  625. else
  626. {
  627. // Check for an allocation failure
  628. if ( NULL != pStr )
  629. {
  630. m_value.pWStr = new wchar_t[wcslen(pStr) + 1];
  631. if ( NULL == m_value.pWStr )
  632. {
  633. throw CX_MemoryException();
  634. }
  635. wcscpy( m_value.pWStr, pStr );
  636. }
  637. else
  638. {
  639. m_value.pWStr = NULL;
  640. }
  641. return TRUE;
  642. }
  643. }
  644. //***************************************************************************
  645. //
  646. // CVar::SetLPSTR
  647. //
  648. // Sets the value of the CVar to the indicated LPSTR.
  649. //
  650. // PARAMETERS:
  651. // pStr
  652. // A pointer to the source string.
  653. // bAcquire
  654. // If TRUE, then the ownership of pStr is trasferred and becomes
  655. // the internal pointer to the string. If FALSE, then the string
  656. // is copied (it must have been allocated with operator new).
  657. //
  658. //***************************************************************************
  659. BOOL CVar::SetLPSTR(LPSTR pStr, BOOL bAcquire)
  660. {
  661. m_vt = VT_LPSTR;
  662. if (bAcquire)
  663. {
  664. m_value.pStr = pStr;
  665. return TRUE;
  666. }
  667. else
  668. {
  669. if ( NULL != pStr)
  670. {
  671. m_value.pStr = new char[strlen(pStr) + 1];
  672. // On failure, throw an exception
  673. if ( NULL == m_value.pStr )
  674. {
  675. throw CX_MemoryException();
  676. }
  677. strcpy( m_value.pStr, pStr );
  678. }
  679. else
  680. {
  681. m_value.pStr = NULL;
  682. }
  683. return TRUE;
  684. }
  685. }
  686. //***************************************************************************
  687. //
  688. // CVar::SetBSTR
  689. //
  690. // Sets the value of the CVar to the indicated BSTR.
  691. //
  692. // NOTE: This BSTR value is actually stored as an LPWSTR to avoid
  693. // apartment-threading restrictions on real BSTR objects allocated
  694. // with COleAuto::_SysAllocString.
  695. //
  696. // PARAMETERS:
  697. // str
  698. // A pointer to the string, which is copied into an internal LPWSTR.
  699. // bAcquire
  700. // If FALSE, then the BSTR is treated as read-only and copied.
  701. // If TRUE, then this function becomes owner of the BSTR and
  702. // frees it after the copy is made.
  703. //
  704. //***************************************************************************
  705. BOOL CVar::SetBSTR(BSTR str, BOOL bAcquire)
  706. {
  707. m_vt = VT_BSTR;
  708. if (str == 0) {
  709. m_value.pWStr = 0;
  710. return TRUE;
  711. }
  712. // Check for an allocation failure
  713. if ( NULL != str )
  714. {
  715. m_value.pWStr = new wchar_t[wcslen(str) + 1];
  716. // If allocation fails, throw an exception
  717. if ( NULL == m_value.pWStr )
  718. {
  719. throw CX_MemoryException();
  720. }
  721. wcscpy( m_value.pWStr, str );
  722. }
  723. else
  724. {
  725. m_value.pWStr = NULL;
  726. }
  727. // Check that this succeeded before we free
  728. // the string passed into us
  729. if ( NULL != m_value.pWStr )
  730. {
  731. if (bAcquire)
  732. COleAuto::_SysFreeString(str);
  733. }
  734. // return whether or not we obtained a value
  735. return ( NULL != m_value.pWStr );
  736. }
  737. //***************************************************************************
  738. //
  739. // CVar::GetBSTR
  740. //
  741. // Returns the BSTR value of the current object.
  742. //
  743. // RETURN VALUE:
  744. // A newly allocated BSTR which must be freed with COleAuto::_SysFreeString().
  745. //
  746. //***************************************************************************
  747. BSTR CVar::GetBSTR()
  748. {
  749. if (m_vt != VT_BSTR)
  750. return NULL;
  751. return COleAuto::_SysAllocString(m_value.pWStr);
  752. }
  753. void CVar::SetDispatch(IDispatch* pDisp)
  754. {
  755. m_vt = VT_DISPATCH;
  756. m_value.pDisp = pDisp;
  757. if(pDisp)
  758. {
  759. pDisp->AddRef();
  760. }
  761. }
  762. void CVar::SetUnknown(IUnknown* pUnk)
  763. {
  764. m_vt = VT_UNKNOWN;
  765. m_value.pUnk = pUnk;
  766. if(pUnk)
  767. {
  768. pUnk->AddRef();
  769. }
  770. }
  771. //***************************************************************************
  772. //
  773. // CVar::SetBlob
  774. //
  775. // Sets the object to the value of the BLOB object.
  776. //
  777. // PARAMETERS:
  778. // pBlob
  779. // A pointer to a valid VT_BLOB object.
  780. // bAcquire
  781. // If TRUE, then the pointer to the data will be acquired. It must
  782. // have been allocated with operator new in the current process,
  783. // since operator delete will be used to free it.
  784. //
  785. //***************************************************************************
  786. void CVar::SetBlob(BLOB *pBlob, BOOL bAcquire)
  787. {
  788. m_vt = VT_BLOB;
  789. if (pBlob == 0)
  790. BlobClear(&m_value.Blob);
  791. else if (!bAcquire)
  792. m_value.Blob = BlobCopy(pBlob);
  793. else
  794. m_value.Blob = *pBlob;
  795. }
  796. //***************************************************************************
  797. //
  798. // CVar::SetClsId
  799. //
  800. // Sets the value of the object to a CLSID.
  801. //
  802. // PARAMETERS:
  803. // pClsId
  804. // Points the source CLSID.
  805. // bAcquire
  806. // If TRUE, the ownership of the pointer is transferred to the
  807. // object. The CLSID must have been allocated with operator new.
  808. // If FALSE, the caller retains ownership and a copy is made.
  809. //
  810. //***************************************************************************
  811. void CVar::SetClsId(CLSID *pClsId, BOOL bAcquire)
  812. {
  813. m_vt = VT_CLSID;
  814. if (pClsId == 0)
  815. m_value.pClsId = 0;
  816. else
  817. {
  818. m_value.pClsId = new CLSID(*pClsId);
  819. // Check for an allocation failure.
  820. if ( NULL == m_value.pClsId )
  821. {
  822. throw CX_MemoryException();
  823. }
  824. }
  825. }
  826. //***************************************************************************
  827. //
  828. // CVar::SetVarVector
  829. //
  830. // Sets the value of the object to the specified CVarVector. This
  831. // allows the CVar to contain a complete array.
  832. //
  833. // PARAMETERS:
  834. // pVec
  835. // A pointer to the CVarVector object which is the source.
  836. // bAcquire
  837. // If TRUE, then ownership of the CVarVector is transferred to
  838. // the object. If FALSE, a new copy of the CVarVector is made and
  839. // the caller retains ownership.
  840. //
  841. //***************************************************************************
  842. void CVar::SetVarVector(CVarVector *pVec, BOOL bAcquire)
  843. {
  844. m_vt = VT_EX_CVARVECTOR;
  845. if (bAcquire) {
  846. // If here, we acquire the caller's pointer.
  847. // =========================================
  848. m_value.pVarVector = pVec;
  849. return;
  850. }
  851. // If here, make a copy.
  852. // =====================
  853. m_value.pVarVector = new CVarVector(*pVec);
  854. // Check for an allocation failure.
  855. if ( NULL == m_value.pVarVector )
  856. {
  857. throw CX_MemoryException();
  858. }
  859. }
  860. int CVar::GetOleType()
  861. {
  862. if(m_vt == VT_EX_CVARVECTOR)
  863. {
  864. if(m_value.pVarVector == NULL) return VT_ARRAY;
  865. else return VT_ARRAY | m_value.pVarVector->GetType();
  866. }
  867. else
  868. {
  869. return m_vt;
  870. }
  871. }
  872. //***************************************************************************
  873. //
  874. // CVar::GetText
  875. //
  876. // Produces textual representation of the Var's type and data
  877. //
  878. // PARAMETERS:
  879. // long lFlags reseved, must be 0
  880. // long lType CIM_TYPE
  881. // LPCWSTR szFormat optional formatting string
  882. //
  883. //
  884. //***************************************************************************
  885. BSTR CVar::GetText(long lFlags, long lType, LPCWSTR szFormat)
  886. {
  887. if(m_vt == VT_EX_CVARVECTOR)
  888. {
  889. // When we get the text for the array, make sure the CIM_FLAG_ARRAY is masked out
  890. BSTR strTemp = GetVarVector()->GetText(lFlags, lType & ~CIM_FLAG_ARRAY);
  891. CSysFreeMe auto1(strTemp);
  892. WCHAR* wszValue = new WCHAR[COleAuto::_SysStringLen(strTemp) + 3];
  893. // Check for allocation failures
  894. if ( NULL == wszValue )
  895. {
  896. throw CX_MemoryException();
  897. }
  898. CVectorDeleteMe<WCHAR> auto2(wszValue);
  899. wcscpy(wszValue, L"{");
  900. wcscat(wszValue, strTemp);
  901. wcscat(wszValue, L"}");
  902. BSTR strRet = COleAuto::_SysAllocString(wszValue);
  903. return strRet;
  904. }
  905. WCHAR* wszValue = new WCHAR[100];
  906. // Check for allocation failures
  907. if ( NULL == wszValue )
  908. {
  909. throw CX_MemoryException();
  910. }
  911. WCHAR* pwc;
  912. int i;
  913. if(m_vt == VT_NULL)
  914. {
  915. delete [] wszValue;
  916. return NULL;
  917. }
  918. if(lType == 0)
  919. lType = m_vt;
  920. try
  921. {
  922. switch(lType)
  923. {
  924. case CIM_SINT8:
  925. swprintf(wszValue, szFormat ? szFormat : L"%d", (long)(signed char)GetByte());
  926. break;
  927. case CIM_UINT8:
  928. swprintf(wszValue, szFormat ? szFormat : L"%d", GetByte());
  929. break;
  930. case CIM_SINT16:
  931. swprintf(wszValue, szFormat ? szFormat : L"%d", (long)GetShort());
  932. break;
  933. case CIM_UINT16:
  934. swprintf(wszValue, szFormat ? szFormat : L"%d", (long)(USHORT)GetShort());
  935. break;
  936. case CIM_SINT32:
  937. swprintf(wszValue, szFormat ? szFormat : L"%d", GetLong());
  938. break;
  939. case CIM_UINT32:
  940. swprintf(wszValue, szFormat ? szFormat : L"%lu", (ULONG)GetLong());
  941. break;
  942. case CIM_BOOLEAN:
  943. swprintf(wszValue, L"%s", (GetBool()?L"TRUE":L"FALSE"));
  944. break;
  945. case CIM_REAL32:
  946. {
  947. // Since the decimal point can be localized, and MOF text should
  948. // always be english, we will return values localized to 0x409,
  949. CVar var( GetFloat() );
  950. // If this fails, we can't guarantee a good value,
  951. // so throw an exception.
  952. if ( !var.ChangeTypeToEx( VT_BSTR ) )
  953. {
  954. throw CX_Exception();
  955. }
  956. wcscpy( wszValue, var.GetLPWSTR() );
  957. }
  958. break;
  959. case CIM_REAL64:
  960. {
  961. // Since the decimal point can be localized, and MOF text should
  962. // always be english, we will return values localized to 0x409,
  963. CVar var( GetDouble() );
  964. // If this fails, we can't guarantee a good value,
  965. // so throw an exception.
  966. if ( !var.ChangeTypeToEx( VT_BSTR ) )
  967. {
  968. throw CX_Exception();
  969. }
  970. wcscpy( wszValue, var.GetLPWSTR() );
  971. }
  972. break;
  973. case CIM_CHAR16:
  974. if(GetShort() == 0)
  975. wcscpy(wszValue, L"0x0");
  976. else
  977. swprintf(wszValue, L"'\\x%X'", (WCHAR)GetShort());
  978. break;
  979. case CIM_OBJECT:
  980. swprintf(wszValue, L"\"not supported\"");
  981. break;
  982. case CIM_REFERENCE:
  983. case CIM_DATETIME:
  984. case CIM_STRING:
  985. case CIM_SINT64:
  986. case CIM_UINT64:
  987. {
  988. // Escape all the quotes
  989. // =====================
  990. int nStrLen = wcslen(GetLPWSTR());
  991. delete [] wszValue;
  992. wszValue = NULL;
  993. wszValue = new WCHAR[nStrLen*2+10];
  994. // Check for allocation failures
  995. if ( NULL == wszValue )
  996. {
  997. throw CX_MemoryException();
  998. }
  999. wszValue[0] = L'"';
  1000. pwc = wszValue+1;
  1001. for(i = 0; i < (int)nStrLen; i++)
  1002. {
  1003. WCHAR wch = GetLPWSTR()[i];
  1004. if(wch == L'\n')
  1005. {
  1006. *(pwc++) = L'\\';
  1007. *(pwc++) = L'n';
  1008. }
  1009. else if(wch == L'\t')
  1010. {
  1011. *(pwc++) = L'\\';
  1012. *(pwc++) = L't';
  1013. }
  1014. else if(wch == L'"' || wch == L'\\')
  1015. {
  1016. *(pwc++) = L'\\';
  1017. *(pwc++) = wch;
  1018. }
  1019. else
  1020. {
  1021. *(pwc++) = wch;
  1022. }
  1023. }
  1024. *(pwc++) = L'"';
  1025. *pwc = 0;
  1026. }
  1027. break;
  1028. default:
  1029. swprintf(wszValue, L"\"not supported\"");
  1030. break;
  1031. }
  1032. BSTR strRes = COleAuto::_SysAllocString(wszValue);
  1033. // Still need to clean up this value
  1034. delete [] wszValue;
  1035. return strRes;
  1036. }
  1037. catch (...)
  1038. {
  1039. // Cleanup always if this has a value
  1040. if ( NULL != wszValue )
  1041. {
  1042. delete [] wszValue;
  1043. }
  1044. // Rethrow the exception
  1045. throw;
  1046. }
  1047. }
  1048. BSTR CVar::TypeToText(int nType)
  1049. {
  1050. const WCHAR* pwcType;
  1051. switch(nType)
  1052. {
  1053. case VT_I1:
  1054. pwcType = L"sint8";
  1055. break;
  1056. case VT_UI1:
  1057. pwcType = L"uint8";
  1058. break;
  1059. case VT_I2:
  1060. pwcType = L"sint16";
  1061. break;
  1062. case VT_UI2:
  1063. pwcType = L"uint16";
  1064. break;
  1065. case VT_I4:
  1066. pwcType = L"sint32";
  1067. break;
  1068. case VT_UI4:
  1069. pwcType = L"uint32";
  1070. break;
  1071. case VT_I8:
  1072. pwcType = L"sint64";
  1073. break;
  1074. case VT_UI8:
  1075. pwcType = L"uint64";
  1076. break;
  1077. case VT_BOOL:
  1078. pwcType = L"boolean";
  1079. break;
  1080. case VT_R4:
  1081. pwcType = L"real32";
  1082. break;
  1083. case VT_R8:
  1084. pwcType = L"real64";
  1085. break;
  1086. case VT_BSTR:
  1087. pwcType = L"string";
  1088. break;
  1089. case VT_DISPATCH:
  1090. pwcType = L"object";
  1091. break;
  1092. case VT_UNKNOWN:
  1093. pwcType = L"object";
  1094. break;
  1095. default:
  1096. return NULL;
  1097. }
  1098. return COleAuto::_SysAllocString(pwcType);
  1099. }
  1100. BSTR CVar::GetTypeText()
  1101. {
  1102. if ( m_vt == VT_EX_CVARVECTOR )
  1103. {
  1104. return TypeToText(GetVarVector()->GetType());
  1105. }
  1106. else
  1107. {
  1108. return TypeToText(m_vt);
  1109. }
  1110. }
  1111. BOOL CVar::ChangeTypeTo(VARTYPE vtNew)
  1112. {
  1113. // TBD: there are more efficient ways!
  1114. // ===================================
  1115. // Create a VARIANT
  1116. // ================
  1117. VARIANT v;
  1118. CClearMe auto1(&v);
  1119. COleAuto::_VariantInit(&v);
  1120. FillVariant(&v);
  1121. // Coerce it
  1122. // =========
  1123. HRESULT hres = COleAuto::_WbemVariantChangeType(&v, &v, vtNew);
  1124. if(FAILED(hres))
  1125. return FALSE;
  1126. // Load it back in
  1127. // ===============
  1128. Empty();
  1129. SetVariant(&v, TRUE);
  1130. // If this is an array, we will now be sitting on an optimized array
  1131. // meaning that we will have acquired the actual safe array - so we should
  1132. // make sure that the CVarVector cleans up the array when it is no longer
  1133. // necessary. We will clear out the variant so it doesn't get deleted
  1134. // when VariantClear is called.
  1135. if ( m_vt == VT_EX_CVARVECTOR )
  1136. {
  1137. m_value.pVarVector->SetRawArrayBinding( CSafeArray::auto_delete );
  1138. ZeroMemory( &v, sizeof(v) );
  1139. }
  1140. return TRUE;
  1141. }
  1142. // Performs localized changes (defaults to 0x409 for this)
  1143. BOOL CVar::ChangeTypeToEx(VARTYPE vtNew, LCID lcid /*=0x409*/)
  1144. {
  1145. // TBD: there are more efficient ways!
  1146. // ===================================
  1147. // Create a VARIANT
  1148. // ================
  1149. VARIANT v;
  1150. CClearMe auto1(&v);
  1151. COleAuto::_VariantInit(&v);
  1152. FillVariant(&v);
  1153. // Coerce it
  1154. // =========
  1155. try
  1156. {
  1157. HRESULT hres = COleAuto::_VariantChangeTypeEx(&v, &v, lcid, 0L, vtNew);
  1158. if(FAILED(hres))
  1159. return FALSE;
  1160. }
  1161. catch(...)
  1162. {
  1163. return FALSE;
  1164. }
  1165. // Load it back in
  1166. // ===============
  1167. Empty();
  1168. SetVariant(&v, TRUE);
  1169. // If this is an array, we will now be sitting on an optimized array
  1170. // meaning that we will have acquired the actual safe array - so we should
  1171. // make sure that the CVarVector cleans up the array when it is no longer
  1172. // necessary. We will clear out the variant so it doesn't get deleted
  1173. // when VariantClear is called.
  1174. if ( m_vt == VT_EX_CVARVECTOR )
  1175. {
  1176. m_value.pVarVector->SetRawArrayBinding( CSafeArray::auto_delete );
  1177. ZeroMemory( &v, sizeof(v) );
  1178. }
  1179. return TRUE;
  1180. }
  1181. BOOL CVar::ToSingleChar()
  1182. {
  1183. // Defer to CVarVector for arrays
  1184. // ==============================
  1185. if(m_vt == VT_EX_CVARVECTOR)
  1186. {
  1187. return GetVarVector()->ToSingleChar();
  1188. }
  1189. // Anything that's not a string follows normal OLE rules
  1190. // =====================================================
  1191. if(m_vt != VT_BSTR)
  1192. {
  1193. return ChangeTypeTo(VT_I2);
  1194. }
  1195. // It's a string. Make sure the length is 1
  1196. // ========================================
  1197. LPCWSTR wsz = GetLPWSTR();
  1198. if(wcslen(wsz) != 1)
  1199. return FALSE;
  1200. // Take the first character
  1201. // ========================
  1202. WCHAR wc = wsz[0];
  1203. Empty();
  1204. SetShort(wc);
  1205. return TRUE;
  1206. }
  1207. BOOL CVar::ToUI4()
  1208. {
  1209. // Defer to CVarVector for arrays
  1210. // ==============================
  1211. if(m_vt == VT_EX_CVARVECTOR)
  1212. {
  1213. return GetVarVector()->ToUI4();
  1214. }
  1215. // Create a VARIANT
  1216. // ================
  1217. VARIANT v;
  1218. CClearMe auto1(&v);
  1219. COleAuto::_VariantInit(&v);
  1220. FillVariant(&v);
  1221. // Coerce it
  1222. // =========
  1223. HRESULT hres = COleAuto::_WbemVariantChangeType(&v, &v, VT_UI4);
  1224. if(FAILED(hres))
  1225. return FALSE;
  1226. // Load it back in
  1227. // ===============
  1228. Empty();
  1229. // Here we cheat and reset to VT_I4 so we can natively reset
  1230. V_VT(&v) = VT_I4;
  1231. SetVariant(&v);
  1232. return TRUE;
  1233. }
  1234. //***************************************************************************
  1235. //
  1236. // CVarVector::CVarVector
  1237. //
  1238. // Default constructor. The caller should not attempt to add any
  1239. // elements when the internal type is VT_EMPTY. Objects constructed
  1240. // with this constructor should only be used as l-values in an
  1241. // assignment of CVarVector objects.
  1242. //
  1243. //***************************************************************************
  1244. CVarVector::CVarVector()
  1245. : m_pSafeArray( NULL ),
  1246. m_pRawData( NULL )
  1247. {
  1248. m_Array.Empty();
  1249. m_nType = VT_EMPTY;
  1250. m_nStatus = no_error;
  1251. }
  1252. //***************************************************************************
  1253. //
  1254. // CVarVector::CVarVector
  1255. //
  1256. // This is the standard constructor.
  1257. //
  1258. // PARAMETERS:
  1259. // nVarType
  1260. // An OLE VT_ type indicator. Heterogeneous arrays are possible
  1261. // if the type VT_EX_CVAR is used. Embedded CVarVectors can
  1262. // occur, since a CVar can in turn hold a CVarVector.
  1263. //
  1264. // nInitSize
  1265. // The starting size of the internal CFlexArray. See FLEXARRY.CPP.
  1266. // nGrowBy
  1267. // The "grow by" factor of the internal CFlexArray. See FLEXARRAY.CPP.
  1268. //
  1269. //***************************************************************************
  1270. CVarVector::CVarVector(
  1271. int nVarType,
  1272. int nInitSize,
  1273. int nGrowBy
  1274. ) :
  1275. m_Array(nInitSize, nGrowBy),
  1276. m_pSafeArray( NULL ),
  1277. m_pRawData( NULL )
  1278. {
  1279. m_nType = nVarType;
  1280. m_nStatus = no_error;
  1281. }
  1282. //***************************************************************************
  1283. //
  1284. // CVarVector::CVarVector
  1285. //
  1286. // Alternate constructor to build a new CVarVector based on a
  1287. // SAFEARRAY object. The only supported types for the SAFEARRAY
  1288. // are VT_BSTR, VT_UI1, VT_I2, VT_I4, VT_R4, and VT_R8.
  1289. //
  1290. // PARAMETERS:
  1291. // nVarType
  1292. // The VT_ type indicator of the incoming SAFEARRAY.
  1293. // pSrc
  1294. // A pointer to a SAFEARRAY, which is treated as read-only.
  1295. //
  1296. // NOTES:
  1297. // This will set the internal m_nStatus variable to <unsupported> if
  1298. // an unsupported VT_ type is in the SAFEARRAY. The caller can immediately
  1299. // call CVarVector::Status() after construction to see if the operation
  1300. // was successful.
  1301. //
  1302. //***************************************************************************
  1303. CVarVector::CVarVector(int nVarType, SAFEARRAY *pSrc, BOOL fOptimized /*= FALSE*/)
  1304. : m_pSafeArray( NULL ),
  1305. m_pRawData( NULL )
  1306. {
  1307. SAFEARRAY* pNew = NULL;
  1308. try
  1309. {
  1310. m_nType = nVarType;
  1311. // If not a valid vector type, this is unsupported
  1312. if ( !IsValidVectorArray( nVarType, pSrc ) )
  1313. {
  1314. m_nStatus = unsupported;
  1315. return;
  1316. }
  1317. if(pSrc == NULL)
  1318. {
  1319. // NULL safearray --- empty
  1320. // ========================
  1321. m_nStatus = no_error;
  1322. return;
  1323. }
  1324. // Bind to the incoming SAFEARRAY, but don't delete it during destruct.
  1325. // ====================================================================
  1326. if(COleAuto::_SafeArrayGetDim(pSrc) != 1)
  1327. {
  1328. m_nStatus = unsupported;
  1329. return;
  1330. }
  1331. long lLBound, lUBound;
  1332. COleAuto::_SafeArrayGetLBound(pSrc, 1, &lLBound);
  1333. COleAuto::_SafeArrayGetUBound(pSrc, 1, &lUBound);
  1334. if(lLBound != 0)
  1335. {
  1336. // Non-0-based safearray --- since CSafeArray doesn't support that, and
  1337. // we can't change pSrc, create a copy
  1338. // ====================================================================
  1339. if(FAILED(COleAuto::_SafeArrayCopy(pSrc, &pNew)))
  1340. {
  1341. m_nStatus = failed;
  1342. return;
  1343. }
  1344. SAFEARRAYBOUND sfb;
  1345. sfb.cElements = (lUBound - lLBound) + 1;
  1346. sfb.lLbound = 0;
  1347. COleAuto::_SafeArrayRedim(pNew, &sfb);
  1348. }
  1349. else
  1350. {
  1351. pNew = pSrc;
  1352. }
  1353. if ( fOptimized )
  1354. {
  1355. // If we rebased the array, then we need to clean it up on delete, otherwise,
  1356. // we don't
  1357. if ( pNew != pSrc )
  1358. {
  1359. m_pSafeArray = new CSafeArray( pNew, nVarType, CSafeArray::auto_delete | CSafeArray::bind);
  1360. }
  1361. else
  1362. {
  1363. m_pSafeArray = new CSafeArray( pNew, nVarType, CSafeArray::no_delete | CSafeArray::bind);
  1364. }
  1365. if ( NULL == m_pSafeArray )
  1366. {
  1367. throw CX_MemoryException();
  1368. }
  1369. if ( m_pSafeArray->Status() != CSafeArray::no_error )
  1370. {
  1371. delete m_pSafeArray;
  1372. m_pSafeArray = NULL;
  1373. m_nStatus = failed;
  1374. }
  1375. m_nStatus = no_error;
  1376. }
  1377. else
  1378. {
  1379. CSafeArray sa(pNew, nVarType, CSafeArray::no_delete | CSafeArray::bind);
  1380. for (int i = 0; i < sa.Size(); i++) {
  1381. CVar* pVar = NULL;
  1382. switch (m_nType) {
  1383. case VT_BOOL:
  1384. {
  1385. VARIANT_BOOL boolVal = sa.GetBoolAt(i);
  1386. pVar = new CVar(boolVal, VT_BOOL);
  1387. // Check for allocation failure
  1388. if ( NULL == pVar )
  1389. {
  1390. throw CX_MemoryException();
  1391. }
  1392. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1393. {
  1394. delete pVar;
  1395. throw CX_MemoryException();
  1396. }
  1397. break;
  1398. }
  1399. case VT_UI1:
  1400. {
  1401. BYTE b = sa.GetByteAt(i);
  1402. pVar = new CVar(b);
  1403. // Check for allocation failure
  1404. if ( NULL == pVar )
  1405. {
  1406. throw CX_MemoryException();
  1407. }
  1408. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1409. {
  1410. delete pVar;
  1411. throw CX_MemoryException();
  1412. }
  1413. break;
  1414. }
  1415. case VT_I2:
  1416. {
  1417. SHORT s = sa.GetShortAt(i);
  1418. pVar = new CVar(s);
  1419. // Check for allocation failure
  1420. if ( NULL == pVar )
  1421. {
  1422. throw CX_MemoryException();
  1423. }
  1424. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1425. {
  1426. delete pVar;
  1427. throw CX_MemoryException();
  1428. }
  1429. break;
  1430. }
  1431. case VT_I4:
  1432. {
  1433. LONG l = sa.GetLongAt(i);
  1434. pVar = new CVar(l);
  1435. // Check for allocation failure
  1436. if ( NULL == pVar )
  1437. {
  1438. throw CX_MemoryException();
  1439. }
  1440. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1441. {
  1442. delete pVar;
  1443. throw CX_MemoryException();
  1444. }
  1445. break;
  1446. }
  1447. case VT_R4:
  1448. {
  1449. float f = sa.GetFloatAt(i);
  1450. pVar = new CVar(f);
  1451. // Check for allocation failure
  1452. if ( NULL == pVar )
  1453. {
  1454. throw CX_MemoryException();
  1455. }
  1456. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1457. {
  1458. delete pVar;
  1459. throw CX_MemoryException();
  1460. }
  1461. break;
  1462. }
  1463. case VT_R8:
  1464. {
  1465. double d = sa.GetDoubleAt(i);
  1466. pVar = new CVar(d);
  1467. // Check for allocation failure
  1468. if ( NULL == pVar )
  1469. {
  1470. throw CX_MemoryException();
  1471. }
  1472. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1473. {
  1474. delete pVar;
  1475. throw CX_MemoryException();
  1476. }
  1477. break;
  1478. }
  1479. case VT_BSTR:
  1480. {
  1481. BSTR bstr = sa.GetBSTRAtThrow(i);
  1482. CSysFreeMe auto1(bstr);
  1483. pVar = new CVar(VT_BSTR, bstr, FALSE);
  1484. // Check for allocation failure
  1485. if ( NULL == pVar )
  1486. {
  1487. throw CX_MemoryException();
  1488. }
  1489. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1490. {
  1491. delete pVar;
  1492. throw CX_MemoryException();
  1493. }
  1494. break;
  1495. }
  1496. case VT_DISPATCH:
  1497. {
  1498. IDispatch* pDisp = sa.GetDispatchAt(i);
  1499. CReleaseMe auto2(pDisp);
  1500. pVar = new CVar;
  1501. // Check for allocation failure
  1502. if ( NULL == pVar )
  1503. {
  1504. throw CX_MemoryException();
  1505. }
  1506. pVar->SetDispatch(pDisp);
  1507. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1508. {
  1509. delete pVar;
  1510. throw CX_MemoryException();
  1511. }
  1512. break;
  1513. }
  1514. case VT_UNKNOWN:
  1515. {
  1516. IUnknown* pUnk = sa.GetUnknownAt(i);
  1517. CReleaseMe auto3(pUnk);
  1518. pVar = new CVar;
  1519. // Check for allocation failure
  1520. if ( NULL == pVar )
  1521. {
  1522. throw CX_MemoryException();
  1523. }
  1524. pVar->SetUnknown(pUnk);
  1525. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1526. {
  1527. delete pVar;
  1528. throw CX_MemoryException();
  1529. }
  1530. break;
  1531. }
  1532. default:
  1533. m_nStatus = unsupported;
  1534. if(pNew != pSrc)
  1535. COleAuto::_SafeArrayDestroy(pNew);
  1536. return;
  1537. }
  1538. }
  1539. if(pNew != pSrc)
  1540. COleAuto::_SafeArrayDestroy(pNew);
  1541. m_nStatus = no_error;
  1542. } // Else not bound
  1543. }
  1544. catch (CX_MemoryException)
  1545. {
  1546. // SafeArrayCopy, GetBSTRAtThrow, new can all throw exceptions
  1547. m_nStatus = failed;
  1548. if(pNew != pSrc)
  1549. COleAuto::_SafeArrayDestroy(pNew);
  1550. throw;
  1551. }
  1552. }
  1553. //***************************************************************************
  1554. //
  1555. // CVarVector::GetNewSafeArray
  1556. //
  1557. // Allocates a new SAFEARRAY equivalent to the current CVarVector.
  1558. //
  1559. // RETURN VALUE:
  1560. // A new SAFEARRAY pointer which must be deallocated with
  1561. // SafeArrayDestroy(). Returns NULL on error or unsupported types.
  1562. //
  1563. //***************************************************************************
  1564. SAFEARRAY *CVarVector::GetNewSafeArray()
  1565. {
  1566. SAFEARRAY *pRetValue = NULL;
  1567. CSafeArray *pArray = new CSafeArray(m_nType, CSafeArray::no_delete);
  1568. // Check for an allocation failure
  1569. if ( NULL == pArray )
  1570. {
  1571. throw CX_MemoryException();
  1572. }
  1573. CDeleteMe<CSafeArray> auto1(pArray);
  1574. int nSize = Size();
  1575. for (int i = 0; i < nSize; i++) {
  1576. CVar v;
  1577. FillCVarAt( i, v );
  1578. switch (m_nType) {
  1579. case VT_UI1:
  1580. pArray->AddByte(v.GetByte());
  1581. break;
  1582. case VT_I2:
  1583. pArray->AddShort(v.GetShort());
  1584. break;
  1585. case VT_I4:
  1586. pArray->AddLong(v.GetLong());
  1587. break;
  1588. case VT_R4:
  1589. pArray->AddFloat(v.GetFloat());
  1590. break;
  1591. case VT_R8:
  1592. pArray->AddDouble(v.GetDouble());
  1593. break;
  1594. case VT_BOOL:
  1595. pArray->AddBool(v.GetBool());
  1596. break;
  1597. case VT_BSTR:
  1598. {
  1599. BSTR s = v.GetBSTR();
  1600. CSysFreeMe auto2(s);
  1601. pArray->AddBSTR(s);
  1602. break;
  1603. }
  1604. case VT_DISPATCH:
  1605. {
  1606. IDispatch* pDisp = v.GetDispatch();
  1607. CReleaseMe auto3(pDisp);
  1608. pArray->AddDispatch(pDisp);
  1609. break;
  1610. }
  1611. case VT_UNKNOWN:
  1612. {
  1613. IUnknown* pUnk = v.GetUnknown();
  1614. CReleaseMe auto4(pUnk);
  1615. pArray->AddUnknown(pUnk);
  1616. break;
  1617. }
  1618. default:
  1619. // For unsupported types, return a NULL.
  1620. // Since we constructed the SAFEARRAY object to
  1621. // not delete the SAFEARRAY and we have encountered
  1622. // a condition where the internal SAFEARRAY of
  1623. // CSafeArray should not be returned, we have
  1624. // to switch our destruct policy.
  1625. // ================================================
  1626. pArray->SetDestructorPolicy(CSafeArray::auto_delete);
  1627. return 0;
  1628. } // SWITCH
  1629. }// FOR enum elements
  1630. // Final cleanup. Get the SAFEARRAY pointer, and delete
  1631. // the wrapper.
  1632. // =====================================================
  1633. pArray->Trim();
  1634. pRetValue = pArray->GetArray();
  1635. return pRetValue;
  1636. }
  1637. //***************************************************************************
  1638. //
  1639. // CVarVector::GetSafeArray
  1640. //
  1641. // Returns a direct pointer to the underlying SafeArray. If fAcquire is
  1642. // set, the array is returned, and cleared from underneath
  1643. //
  1644. // RETURN VALUE:
  1645. // A SAFEARRAY pointer which must be deallocated with
  1646. // SafeArrayDestroy() if fAcquire is set to TRUE
  1647. //
  1648. //***************************************************************************
  1649. SAFEARRAY *CVarVector::GetSafeArray( BOOL fAcquire /* = FALSE */)
  1650. {
  1651. SAFEARRAY* psa = NULL;
  1652. _DBG_ASSERT( NULL != m_pSafeArray );
  1653. if ( NULL != m_pSafeArray )
  1654. {
  1655. if ( fAcquire )
  1656. {
  1657. // Unaccess data if appropriate
  1658. if ( NULL != m_pRawData )
  1659. {
  1660. m_pSafeArray->Unaccess();
  1661. m_pRawData = NULL;
  1662. }
  1663. psa = m_pSafeArray->GetArray();
  1664. // Now clear the array
  1665. m_pSafeArray->SetDestructorPolicy( CSafeArray::no_delete );
  1666. delete m_pSafeArray;
  1667. m_pSafeArray = NULL;
  1668. }
  1669. else
  1670. {
  1671. psa = m_pSafeArray->GetArray();
  1672. }
  1673. }
  1674. return psa;
  1675. }
  1676. //***************************************************************************
  1677. //
  1678. // CVarVector::~CVarVector
  1679. //
  1680. // Destructor.
  1681. //
  1682. //***************************************************************************
  1683. CVarVector::~CVarVector()
  1684. {
  1685. Empty();
  1686. }
  1687. //***************************************************************************
  1688. //
  1689. // CVarVector::Empty
  1690. //
  1691. //***************************************************************************
  1692. void CVarVector::Empty()
  1693. {
  1694. if ( NULL != m_pSafeArray )
  1695. {
  1696. delete m_pSafeArray;
  1697. }
  1698. for (int i = 0; i < m_Array.Size(); i++) {
  1699. delete (CVar *) m_Array[i];
  1700. }
  1701. m_Array.Empty();
  1702. m_nType = VT_EMPTY;
  1703. m_nStatus = no_error;
  1704. m_pSafeArray = NULL;
  1705. m_pRawData = NULL;
  1706. }
  1707. //***************************************************************************
  1708. //
  1709. // CVarVector::CVarVector
  1710. //
  1711. // Copy constructor. This is implemented via the assignment operator.
  1712. //
  1713. //***************************************************************************
  1714. CVarVector::CVarVector(CVarVector &Src)
  1715. : m_pSafeArray( NULL ),
  1716. m_pRawData( NULL )
  1717. {
  1718. m_nType = 0;
  1719. m_nStatus = no_error;
  1720. *this = Src;
  1721. }
  1722. //***************************************************************************
  1723. //
  1724. // CVarVector::operator =
  1725. //
  1726. // Assignment operator.
  1727. //
  1728. //***************************************************************************
  1729. CVarVector& CVarVector::operator =(CVarVector &Src)
  1730. {
  1731. Empty();
  1732. if ( NULL != Src.m_pSafeArray )
  1733. {
  1734. m_pSafeArray = new CSafeArray( *Src.m_pSafeArray );
  1735. if ( NULL != m_pSafeArray )
  1736. {
  1737. if ( m_pSafeArray->Status() != CSafeArray::no_error )
  1738. {
  1739. delete m_pSafeArray;
  1740. throw CX_MemoryException();
  1741. }
  1742. }
  1743. else
  1744. {
  1745. throw CX_MemoryException();
  1746. }
  1747. }
  1748. else
  1749. {
  1750. for (int i = 0; i < Src.m_Array.Size(); i++)
  1751. {
  1752. CVar* pVar = new CVar(*(CVar *) Src.m_Array[i]);
  1753. // Check for an allocation failure
  1754. if ( NULL == pVar )
  1755. {
  1756. throw CX_MemoryException();
  1757. }
  1758. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1759. {
  1760. delete pVar;
  1761. throw CX_MemoryException();
  1762. }
  1763. }
  1764. }
  1765. m_nStatus = Src.m_nStatus;
  1766. m_nType = Src.m_nType;
  1767. return *this;
  1768. }
  1769. //***************************************************************************
  1770. //
  1771. // CVarVector::operator ==
  1772. //
  1773. // Equality test operator.
  1774. //
  1775. //***************************************************************************
  1776. int CVarVector::operator ==(CVarVector &Src)
  1777. {
  1778. return CompareTo(Src, TRUE);
  1779. }
  1780. BOOL CVarVector::CompareTo(CVarVector& Src, BOOL bIgnoreCase)
  1781. {
  1782. if (m_nType != Src.m_nType)
  1783. return 0;
  1784. // Need to do things indirectly here, since we are possibly mixing
  1785. // CVarVectors not on SAFEARRAYs and those on SAFEARRAYs
  1786. int Src_Size = Src.Size();
  1787. if ( Size() != Src_Size )
  1788. return 0;
  1789. // Allocate the variants
  1790. for (int i = 0; i < Src_Size; i++)
  1791. {
  1792. CVar varThis;
  1793. CVar varThat;
  1794. FillCVarAt( i, varThis );
  1795. Src.FillCVarAt( i, varThat );
  1796. if ( !varThis.CompareTo( varThat, bIgnoreCase ) )
  1797. return 0;
  1798. }
  1799. return 1;
  1800. }
  1801. //***************************************************************************
  1802. //
  1803. // CVarVector::Add
  1804. //
  1805. // Adds a new CVar to the array. A reference is used so that anonymous
  1806. // objects can be constructed in the Add() call:
  1807. //
  1808. // pVec->Add(CVar(33));
  1809. //
  1810. // PARAMETERS:
  1811. // Value
  1812. // A reference to a CVar object of the correct type for the array.
  1813. // No type checking is done.
  1814. //
  1815. // RETURN VALUE:
  1816. // no_error
  1817. // failed
  1818. //
  1819. //***************************************************************************
  1820. int CVarVector::Add(CVar &Value)
  1821. {
  1822. if ( NULL != m_pSafeArray )
  1823. {
  1824. switch ( Value.GetType() )
  1825. {
  1826. case VT_BOOL:
  1827. // We can store differently from what is expected in Variants, hence we
  1828. // need to make sure to convert
  1829. m_pSafeArray->AddBool( Value.GetBool() ? VARIANT_TRUE : VARIANT_FALSE );
  1830. break;
  1831. case VT_UI1:
  1832. m_pSafeArray->AddByte( Value.GetByte() );
  1833. break;
  1834. case VT_I2:
  1835. m_pSafeArray->AddShort( Value.GetShort() );
  1836. break;
  1837. case VT_I4:
  1838. m_pSafeArray->AddLong( Value.GetLong() );
  1839. break;
  1840. case VT_R4:
  1841. m_pSafeArray->AddFloat( Value.GetFloat() );
  1842. break;
  1843. case VT_R8:
  1844. m_pSafeArray->AddDouble( Value.GetDouble() );
  1845. break;
  1846. case VT_BSTR:
  1847. m_pSafeArray->AddBSTR( Value.GetBSTR() );
  1848. break;
  1849. case VT_UNKNOWN:
  1850. m_pSafeArray->AddUnknown( Value.GetUnknown() );
  1851. break;
  1852. default:
  1853. return failed;
  1854. }
  1855. return no_error;
  1856. }
  1857. else
  1858. {
  1859. CVar *p = new CVar(Value);
  1860. // Check for allocation failures
  1861. if ( NULL == p )
  1862. {
  1863. return failed;
  1864. }
  1865. if (m_Array.Add(p) != CFlexArray::no_error)
  1866. {
  1867. delete p;
  1868. return failed;
  1869. }
  1870. return no_error;
  1871. }
  1872. }
  1873. //***************************************************************************
  1874. //
  1875. // CVarVector::Add
  1876. //
  1877. // Adds a new CVar to the array. This overload simply takes ownership
  1878. // of the incoming pointer and adds it directly.
  1879. //
  1880. // PARAMETERS:
  1881. // pAcquiredPtr
  1882. // A pointer to a CVar object which is acquired by the vector.
  1883. //
  1884. // RETURN VALUE:
  1885. // no_error
  1886. // failed
  1887. //
  1888. //***************************************************************************
  1889. int CVarVector::Add(CVar *pAcquiredPtr)
  1890. {
  1891. // Not a valid operation if we are sitting on a SAFEARRAY
  1892. _DBG_ASSERT( NULL == m_pSafeArray );
  1893. // We don't support this if we are optimized to
  1894. // us a safe array directly
  1895. if ( NULL != m_pSafeArray )
  1896. {
  1897. return failed;
  1898. }
  1899. if (m_Array.Add(pAcquiredPtr) != CFlexArray::no_error)
  1900. {
  1901. return failed;
  1902. }
  1903. return no_error;
  1904. }
  1905. //***************************************************************************
  1906. //
  1907. // CVarVector::RemoveAt
  1908. //
  1909. // Removes the array element at the specified index.
  1910. //
  1911. // PARAMETERS:
  1912. // nIndex
  1913. // The location at which to remove the element.
  1914. //
  1915. // RETURN VALUE:
  1916. // no_error
  1917. // On success.
  1918. // failed
  1919. // On range errors, etc.
  1920. //
  1921. //***************************************************************************
  1922. int CVarVector::RemoveAt(int nIndex)
  1923. {
  1924. if ( NULL != m_pSafeArray )
  1925. {
  1926. if ( m_pSafeArray->RemoveAt( nIndex ) != CSafeArray::no_error )
  1927. {
  1928. return failed;
  1929. }
  1930. }
  1931. else
  1932. {
  1933. CVar *p = (CVar *) m_Array[nIndex];
  1934. delete p;
  1935. if (m_Array.RemoveAt(nIndex) != CFlexArray::no_error)
  1936. return failed;
  1937. }
  1938. return no_error;
  1939. }
  1940. //***************************************************************************
  1941. //
  1942. // CVarVector::InsertAt
  1943. //
  1944. // Inserts the new element at the specified location.
  1945. //
  1946. // PARAMETERS:
  1947. // nIndex
  1948. // The location at which to add the new element.
  1949. // Value
  1950. // A reference to the new value.
  1951. //
  1952. // RETURN VALUE:
  1953. // no_error
  1954. // On success.
  1955. // failed
  1956. // An invalid nIndex value was specified.
  1957. //
  1958. //***************************************************************************
  1959. int CVarVector::InsertAt(int nIndex, CVar &Value)
  1960. {
  1961. // We don't support this if we are optimized to
  1962. // us a safe array directly
  1963. _DBG_ASSERT( NULL == m_pSafeArray );
  1964. if ( NULL != m_pSafeArray )
  1965. {
  1966. return failed;
  1967. }
  1968. CVar *pNew = new CVar(Value);
  1969. // Check for allocation failures
  1970. if ( NULL == pNew )
  1971. {
  1972. return failed;
  1973. }
  1974. if (m_Array.InsertAt(nIndex, pNew) != CFlexArray::no_error)
  1975. {
  1976. delete pNew;
  1977. return failed;
  1978. }
  1979. return no_error;
  1980. }
  1981. BSTR CVarVector::GetText(long lFlags, long lType/* = 0 */)
  1982. {
  1983. // Construct an array of values
  1984. // ============================
  1985. BSTR* aTexts = NULL;
  1986. int i;
  1987. try
  1988. {
  1989. aTexts = new BSTR[Size()];
  1990. // Check for allocation failures
  1991. if ( NULL == aTexts )
  1992. {
  1993. throw CX_MemoryException();
  1994. }
  1995. memset(aTexts, 0, Size() * sizeof(BSTR));
  1996. int nTotal = 0;
  1997. for(i = 0; i < Size(); i++)
  1998. {
  1999. CVar v;
  2000. FillCVarAt( i, v );
  2001. aTexts[i] = v.GetText(lFlags, lType);
  2002. nTotal += COleAuto::_SysStringLen(aTexts[i]) + 2; // 2: for ", "
  2003. }
  2004. // Allocate a BSTR to contain them all
  2005. // ===================================
  2006. BSTR strRes = COleAuto::_SysAllocStringLen(NULL, nTotal);
  2007. CSysFreeMe auto2(strRes);
  2008. *strRes = 0;
  2009. for(i = 0; i < Size(); i++)
  2010. {
  2011. if(i != 0)
  2012. {
  2013. wcscat(strRes, L", ");
  2014. }
  2015. wcscat(strRes, aTexts[i]);
  2016. COleAuto::_SysFreeString(aTexts[i]);
  2017. }
  2018. delete [] aTexts;
  2019. aTexts = NULL;
  2020. BSTR strPerfectRes = COleAuto::_SysAllocString(strRes);
  2021. return strPerfectRes;
  2022. }
  2023. catch(CX_MemoryException)
  2024. {
  2025. // new, GetText, COleAuto::_SysAllocStringLen and COleAuto::_SysAllocString can all throw exceptions
  2026. if (NULL != aTexts)
  2027. {
  2028. for(int x = 0; x < Size(); x++)
  2029. {
  2030. if (NULL != aTexts[x])
  2031. COleAuto::_SysFreeString(aTexts[x]);
  2032. }
  2033. delete [] aTexts;
  2034. aTexts = NULL;
  2035. }
  2036. throw;
  2037. }
  2038. }
  2039. BOOL CVarVector::ToSingleChar()
  2040. {
  2041. // Handle this differently if we are sitting directly on a safearray
  2042. if ( NULL != m_pSafeArray )
  2043. {
  2044. int nSize = Size();
  2045. // One element at a time is converted and copied into the new array
  2046. CSafeArray* pNewArray = new CSafeArray( VT_I2, CSafeArray::auto_delete, nSize );
  2047. for ( int i = 0; i < nSize; i++ )
  2048. {
  2049. CVar v;
  2050. FillCVarAt( i, v );
  2051. if ( !v.ToSingleChar() )
  2052. {
  2053. delete pNewArray;
  2054. return FALSE;
  2055. }
  2056. if ( pNewArray->AddShort( v.GetShort() ) != CSafeArray::no_error )
  2057. {
  2058. delete pNewArray;
  2059. return FALSE;
  2060. }
  2061. }
  2062. // Now replace the old pointer
  2063. delete m_pSafeArray;
  2064. m_pSafeArray = pNewArray;
  2065. }
  2066. else
  2067. {
  2068. // One element at a time, convert in place
  2069. for(int i = 0; i < Size(); i++)
  2070. {
  2071. if(!GetAt(i).ToSingleChar())
  2072. return FALSE;
  2073. }
  2074. }
  2075. // Since all of the conversions succeeded, we will
  2076. // assume the vector type is now VT_I2.
  2077. m_nType = VT_I2;
  2078. return TRUE;
  2079. }
  2080. BOOL CVarVector::ToUI4()
  2081. {
  2082. // Handle this differently if we are sitting directly on a safearray
  2083. if ( NULL != m_pSafeArray )
  2084. {
  2085. int nSize = Size();
  2086. // One element at a time is converted and copied into the new array
  2087. CSafeArray* pNewArray = new CSafeArray( VT_I4, CSafeArray::auto_delete, nSize );
  2088. for ( int i = 0; i < nSize; i++ )
  2089. {
  2090. CVar v;
  2091. FillCVarAt( i, v );
  2092. if ( !v.ToUI4() )
  2093. {
  2094. delete pNewArray;
  2095. return FALSE;
  2096. }
  2097. if ( pNewArray->AddLong( v.GetLong() ) != CSafeArray::no_error )
  2098. {
  2099. delete pNewArray;
  2100. return FALSE;
  2101. }
  2102. }
  2103. // Now replace the old pointer
  2104. delete m_pSafeArray;
  2105. m_pSafeArray = pNewArray;
  2106. }
  2107. else
  2108. {
  2109. // One element at a time, convert in place
  2110. for(int i = 0; i < Size(); i++)
  2111. {
  2112. if(!GetAt(i).ToUI4())
  2113. return FALSE;
  2114. }
  2115. }
  2116. // Since all of the conversions succeeded, we will
  2117. // assume the vector type is now VT_I4.
  2118. m_nType = VT_I4;
  2119. return TRUE;
  2120. }
  2121. BOOL CVarVector::IsValidVectorType( int nVarType )
  2122. {
  2123. if ( VT_BOOL == nVarType ||
  2124. VT_UI1 == nVarType ||
  2125. VT_I2 == nVarType ||
  2126. VT_I4 == nVarType ||
  2127. VT_R4 == nVarType ||
  2128. VT_R8 == nVarType ||
  2129. VT_BSTR == nVarType ||
  2130. VT_DISPATCH == nVarType ||
  2131. VT_UNKNOWN == nVarType )
  2132. {
  2133. return TRUE;
  2134. }
  2135. else
  2136. {
  2137. return FALSE;
  2138. }
  2139. }
  2140. BOOL CVarVector::IsValidVectorArray( int nVarType, SAFEARRAY* pArray )
  2141. {
  2142. BOOL fReturn = IsValidVectorType( nVarType );
  2143. if ( !fReturn )
  2144. {
  2145. // We do supprt VT_VARIANT if the array is zero length
  2146. if ( VT_VARIANT == nVarType )
  2147. {
  2148. if ( NULL != pArray )
  2149. {
  2150. // If lUBound is 1 less than lLBound, it's a zero length array
  2151. long lLBound = 0,
  2152. lUBound = 0;
  2153. COleAuto::_SafeArrayGetLBound(pArray, 1, &lLBound);
  2154. COleAuto::_SafeArrayGetUBound(pArray, 1, &lUBound);
  2155. fReturn = ( lUBound == ( lLBound - 1 ) );
  2156. }
  2157. } // IF VT_VARIANT
  2158. } // IF Invalid Type
  2159. return fReturn;
  2160. }
  2161. int CVarVector::Size()
  2162. {
  2163. if ( NULL == m_pSafeArray )
  2164. {
  2165. return m_Array.Size();
  2166. }
  2167. else
  2168. {
  2169. return m_pSafeArray->Size();
  2170. }
  2171. }
  2172. HRESULT CVarVector::AccessRawArray( void** ppv )
  2173. {
  2174. if ( NULL == m_pSafeArray )
  2175. {
  2176. return E_FAIL;
  2177. }
  2178. return m_pSafeArray->Access( ppv );
  2179. }
  2180. HRESULT CVarVector::UnaccessRawArray( void )
  2181. {
  2182. if ( NULL == m_pSafeArray )
  2183. {
  2184. return E_FAIL;
  2185. }
  2186. if ( NULL != m_pRawData )
  2187. {
  2188. m_pRawData = NULL;
  2189. }
  2190. return m_pSafeArray->Unaccess();
  2191. }
  2192. HRESULT CVarVector::InternalRawArrayAccess( void )
  2193. {
  2194. if ( NULL == m_pSafeArray )
  2195. {
  2196. return E_FAIL;
  2197. }
  2198. if ( NULL != m_pRawData )
  2199. {
  2200. return WBEM_E_INVALID_OPERATION;
  2201. }
  2202. return m_pSafeArray->Access( &m_pRawData );
  2203. }
  2204. CVar& CVarVector::GetAt(int nIndex)
  2205. {
  2206. // Not a valid operation if we are sitting on a SAFEARRAY
  2207. _DBG_ASSERT( NULL == m_pSafeArray );
  2208. if ( NULL == m_pSafeArray )
  2209. {
  2210. return *(CVar *) m_Array[nIndex];
  2211. }
  2212. else
  2213. {
  2214. throw CX_VarVectorException();
  2215. }
  2216. }
  2217. CVar& CVarVector::operator [](int nIndex)
  2218. {
  2219. // Not a valid operation if we are sitting on a SAFEARRAY
  2220. _DBG_ASSERT( NULL == m_pSafeArray );
  2221. if ( NULL == m_pSafeArray )
  2222. {
  2223. return *(CVar *) m_Array[nIndex];
  2224. }
  2225. else
  2226. {
  2227. throw CX_VarVectorException();
  2228. }
  2229. }
  2230. void CVarVector::FillCVarAt(int nIndex, CVar& vTemp)
  2231. {
  2232. if ( NULL == m_pSafeArray )
  2233. {
  2234. vTemp = *(CVar *) m_Array[nIndex];
  2235. }
  2236. else if ( NULL == m_pRawData )
  2237. {
  2238. switch( m_nType )
  2239. {
  2240. case VT_BOOL:
  2241. vTemp.SetBool( m_pSafeArray->GetBoolAt( nIndex ) );
  2242. break;
  2243. case VT_UI1:
  2244. vTemp.SetByte( m_pSafeArray->GetByteAt( nIndex ) );
  2245. break;
  2246. case VT_I2:
  2247. vTemp.SetShort( m_pSafeArray->GetShortAt( nIndex ) );
  2248. break;
  2249. case VT_I4:
  2250. vTemp.SetLong( m_pSafeArray->GetLongAt( nIndex ) );
  2251. break;
  2252. case VT_R4:
  2253. vTemp.SetFloat( m_pSafeArray->GetFloatAt( nIndex ) );
  2254. break;
  2255. case VT_R8:
  2256. vTemp.SetDouble( m_pSafeArray->GetDoubleAt( nIndex ) );
  2257. break;
  2258. case VT_BSTR:
  2259. vTemp.SetBSTR( m_pSafeArray->GetBSTRAtThrow( nIndex ), TRUE );
  2260. break;
  2261. case VT_UNKNOWN:
  2262. IUnknown* pUnk = m_pSafeArray->GetUnknownAt(nIndex);
  2263. CReleaseMe rm( pUnk );
  2264. vTemp.SetUnknown( pUnk );
  2265. break;
  2266. }
  2267. }
  2268. else
  2269. {
  2270. // When we pull data in this state, we're using the CVar as a
  2271. // passthrough, so it won't do any allocations or addref()
  2272. // hence it shouldn't do any cleanup either.
  2273. int nDataLen = 0L;
  2274. void* pvElement = m_pRawData;
  2275. switch( m_nType )
  2276. {
  2277. case VT_UI1:
  2278. nDataLen = sizeof(BYTE);
  2279. pvElement = (void*) &((BYTE*) m_pRawData)[nIndex];
  2280. break;
  2281. case VT_BOOL:
  2282. case VT_I2:
  2283. nDataLen = sizeof(short);
  2284. pvElement = (void*) &((short*) m_pRawData)[nIndex];
  2285. break;
  2286. case VT_I4:
  2287. nDataLen = sizeof(long);
  2288. pvElement = (void*) &((long*) m_pRawData)[nIndex];
  2289. break;
  2290. case VT_R4:
  2291. nDataLen = sizeof(float);
  2292. pvElement = (void*) &((float*) m_pRawData)[nIndex];
  2293. break;
  2294. case VT_R8:
  2295. nDataLen = sizeof(double);
  2296. pvElement = (void*) &((double*) m_pRawData)[nIndex];
  2297. break;
  2298. case VT_BSTR:
  2299. nDataLen = sizeof(BSTR);
  2300. pvElement = (void*) &((BSTR*) m_pRawData)[nIndex];
  2301. // If the BSTR is a NULL, old code converted to "", so
  2302. // we will point to a pointer to "".
  2303. if ( (*(BSTR*) pvElement ) == NULL )
  2304. {
  2305. pvElement = (void*) &g_pszNullVarString;
  2306. }
  2307. break;
  2308. case VT_UNKNOWN:
  2309. nDataLen = sizeof(IUnknown*);
  2310. pvElement = (void*) &((IUnknown**) m_pRawData)[nIndex];
  2311. break;
  2312. }
  2313. // Splat the raw value in, and Can Delete is FALSE
  2314. // This is strictly to support optimized pass-through logic
  2315. vTemp.SetRaw( m_nType, pvElement, nDataLen);
  2316. vTemp.SetCanDelete( FALSE );
  2317. }
  2318. }
  2319. // This only works if there are no elements in the safe array
  2320. BOOL CVarVector::MakeOptimized( int nVarType, int nInitSize, int nGrowBy )
  2321. {
  2322. BOOL fReturn = FALSE;
  2323. if ( NULL == m_pSafeArray )
  2324. {
  2325. if ( m_Array.Size() == 0 )
  2326. {
  2327. m_pSafeArray = new CSafeArray( nVarType, CSafeArray::auto_delete, nInitSize, nGrowBy );
  2328. if ( NULL != m_pSafeArray )
  2329. {
  2330. if ( m_pSafeArray->Status() == CSafeArray::no_error )
  2331. {
  2332. m_nType = nVarType;
  2333. m_nStatus = no_error;
  2334. fReturn = TRUE;
  2335. }
  2336. else
  2337. {
  2338. delete m_pSafeArray;
  2339. m_pSafeArray = NULL;
  2340. m_nStatus = failed;
  2341. }
  2342. }
  2343. else
  2344. {
  2345. m_nStatus = failed;
  2346. }
  2347. } // IF no elements in array
  2348. }
  2349. return fReturn;
  2350. }
  2351. BOOL CVarVector::DoesVectorTypeMatchArrayType( void )
  2352. {
  2353. // If we have an underlying safe array, sometimes the actualy type of the
  2354. // data in the safe array may be different from the type that was reported
  2355. // to us in VARANTARG. This info is critical in determining how we will
  2356. // go about handling certain operations
  2357. BOOL fReturn = TRUE;
  2358. if ( NULL != m_pSafeArray )
  2359. {
  2360. VARTYPE vt;
  2361. // Only return TRUE if the actual types are equal
  2362. if ( m_pSafeArray->GetActualVarType( &vt ) == no_error )
  2363. {
  2364. fReturn = ( vt == m_nType );
  2365. }
  2366. else
  2367. {
  2368. fReturn = FALSE;
  2369. }
  2370. }
  2371. return fReturn;
  2372. }
  2373. void CVarVector::SetRawArrayBinding( int nBinding )
  2374. {
  2375. if ( NULL != m_pSafeArray )
  2376. {
  2377. m_pSafeArray->SetDestructorPolicy( nBinding );
  2378. }
  2379. }
  2380. HRESULT CVarVector::SetRawArrayData( void* pvData, int nNumElements, int nElementSize )
  2381. {
  2382. _DBG_ASSERT( NULL != m_pSafeArray );
  2383. HRESULT hr = WBEM_S_NO_ERROR;
  2384. if ( NULL != m_pSafeArray )
  2385. {
  2386. if ( m_pSafeArray->SetRawData( pvData, nNumElements, nElementSize ) != CSafeArray::no_error )
  2387. hr = WBEM_E_FAILED;
  2388. }
  2389. else
  2390. {
  2391. hr = WBEM_E_FAILED;
  2392. }
  2393. return hr;
  2394. }
  2395. HRESULT CVarVector::GetRawArrayData( void* pvDest, int nBuffSize )
  2396. {
  2397. _DBG_ASSERT( NULL != m_pSafeArray );
  2398. HRESULT hr = WBEM_S_NO_ERROR;
  2399. if ( NULL != m_pSafeArray )
  2400. {
  2401. if ( m_pSafeArray->GetRawData( pvDest, nBuffSize ) != CSafeArray::no_error )
  2402. hr = WBEM_E_FAILED;
  2403. }
  2404. else
  2405. {
  2406. hr = WBEM_E_FAILED;
  2407. }
  2408. return hr;
  2409. }
  2410. BOOL CVarVector::SetRawArraySize( int nSize )
  2411. {
  2412. _DBG_ASSERT( NULL != m_pSafeArray );
  2413. BOOL fReturn = FALSE;
  2414. if ( NULL != m_pSafeArray )
  2415. {
  2416. m_pSafeArray->SetRawArrayMaxElement( nSize - 1 );
  2417. fReturn = TRUE;
  2418. }
  2419. return fReturn;
  2420. }
  2421. int CVarVector::GetElementSize( void )
  2422. {
  2423. _DBG_ASSERT( NULL != m_pSafeArray );
  2424. int nReturn = 0L;
  2425. if ( NULL != m_pSafeArray )
  2426. {
  2427. nReturn = m_pSafeArray->ElementSize();
  2428. }
  2429. return nReturn;
  2430. }