Leaked source code of windows server 2003
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.

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