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.

2360 lines
60 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 <WT_var.h>
  16. #include <wbemidl.h>
  17. #include <WT_arrtempl.h>
  18. //#include <olewrap.h>
  19. #include "WT_SafeArry.h"
  20. class CX_MemoryException
  21. {
  22. };
  23. class CX_Exception
  24. {
  25. };
  26. typedef BYTE* LPMEMORY;
  27. BLOB BlobCopy(BLOB *pSrc)
  28. {
  29. BLOB Blob;
  30. BYTE *p = new BYTE[pSrc->cbSize];
  31. // Check for allocation failure
  32. if ( NULL == p )
  33. {
  34. throw CX_MemoryException();
  35. }
  36. Blob.cbSize = pSrc->cbSize;
  37. Blob.pBlobData = p;
  38. memcpy(p, pSrc->pBlobData, Blob.cbSize);
  39. return Blob;
  40. }
  41. #define BlobLength(p) ((p)->cbSize)
  42. #define BlobDataPtr(p) ((p)->pBlobData)
  43. void BlobClear(BLOB *pSrc)
  44. {
  45. if (pSrc->pBlobData)
  46. delete pSrc->pBlobData;
  47. pSrc->pBlobData = 0;
  48. pSrc->cbSize = 0;
  49. }
  50. HRESULT WbemVariantChangeType(VARIANT* pvDest, VARIANT* pvSrc,
  51. VARTYPE vtNew)
  52. {
  53. HRESULT hres;
  54. if(V_VT(pvSrc) == VT_NULL)
  55. {
  56. return VariantCopy(pvDest, pvSrc);
  57. }
  58. if(vtNew & VT_ARRAY)
  59. {
  60. // It's an array, we have to do our own conversion
  61. // ===============================================
  62. if((V_VT(pvSrc) & VT_ARRAY) == 0)
  63. return DISP_E_TYPEMISMATCH;
  64. SAFEARRAY* psaSrc = V_ARRAY(pvSrc);
  65. SAFEARRAYBOUND aBounds[1];
  66. long lLBound;
  67. SafeArrayGetLBound(psaSrc, 1, &lLBound);
  68. long lUBound;
  69. SafeArrayGetUBound(psaSrc, 1, &lUBound);
  70. aBounds[0].cElements = lUBound - lLBound + 1;
  71. aBounds[0].lLbound = lLBound;
  72. SAFEARRAY* psaDest = SafeArrayCreate(vtNew & ~VT_ARRAY, 1, aBounds);
  73. // Stuff the individual data pieces
  74. // ================================
  75. for(long lIndex = lLBound; lIndex <= lUBound; lIndex++)
  76. {
  77. // Load the initial data element into a VARIANT
  78. // ============================================
  79. VARIANT vSrcEl;
  80. V_VT(&vSrcEl) = V_VT(pvSrc) & ~VT_ARRAY;
  81. SafeArrayGetElement(psaSrc, &lIndex, &V_UI1(&vSrcEl));
  82. // Cast it to the new type
  83. // =======================
  84. hres = VariantChangeType(&vSrcEl, &vSrcEl, 0, vtNew & ~VT_ARRAY);
  85. if(FAILED(hres))
  86. {
  87. SafeArrayDestroy(psaDest);
  88. return hres;
  89. }
  90. // Put it into the new array
  91. // =========================
  92. if(V_VT(&vSrcEl) == VT_BSTR)
  93. {
  94. hres = SafeArrayPutElement(psaDest, &lIndex, V_BSTR(&vSrcEl));
  95. }
  96. else
  97. {
  98. hres = SafeArrayPutElement(psaDest, &lIndex, &V_UI1(&vSrcEl));
  99. }
  100. if(FAILED(hres))
  101. {
  102. SafeArrayDestroy(psaDest);
  103. return hres;
  104. }
  105. }
  106. if(pvDest == pvSrc)
  107. {
  108. VariantClear(pvSrc);
  109. }
  110. V_VT(pvDest) = vtNew;
  111. V_ARRAY(pvDest) = psaDest;
  112. return TRUE;
  113. }
  114. else
  115. {
  116. // Not an array. Can use OLE functions
  117. // ===================================
  118. return VariantChangeType(pvDest, pvSrc, VARIANT_NOVALUEPROP, vtNew);
  119. }
  120. }
  121. //***************************************************************************
  122. //
  123. // CVar::Empty
  124. //
  125. // Constructor helper.
  126. //
  127. // This merely clears everything. VT_EMPTY is the default.
  128. //
  129. //***************************************************************************
  130. void CVar::Init()
  131. {
  132. m_nStatus = no_error;
  133. m_vt = VT_EMPTY;
  134. m_bCanDelete = TRUE;
  135. memset(&m_value, 0, sizeof(METAVALUE));
  136. }
  137. //***************************************************************************
  138. //
  139. // CVar::~CVar
  140. //
  141. // Destructor.
  142. //
  143. //***************************************************************************
  144. CVar::~CVar()
  145. {
  146. Empty();
  147. }
  148. //***************************************************************************
  149. //
  150. // CVar::CVar
  151. //
  152. // Copy constructor. This is implemented via the assignment operator.
  153. //
  154. //***************************************************************************
  155. CVar::CVar(CVar &Src)
  156. {
  157. m_vt = VT_EMPTY;
  158. m_nStatus = no_error;
  159. memset(&m_value, 0, sizeof(METAVALUE));
  160. *this = Src;
  161. }
  162. //***************************************************************************
  163. //
  164. // CVar::operator =
  165. //
  166. // NOTES:
  167. // Observe that VT_EX_CVARVECTOR is dedicated to embedded CVarVector objects.
  168. // Also, only pointer types require a new allocation + copy, whereas
  169. // most of the simple types are directly assignable, in the <default>
  170. // label of the switch statement.
  171. //
  172. //***************************************************************************
  173. CVar& CVar::operator =(CVar &Src)
  174. {
  175. Empty();
  176. m_vt = Src.m_vt;
  177. m_nStatus = m_nStatus;
  178. m_bCanDelete = TRUE;
  179. switch (m_vt) {
  180. case VT_LPSTR:
  181. // Check for an allocation failure
  182. if ( NULL != Src.m_value.pStr )
  183. {
  184. m_value.pStr = new char[strlen(Src.m_value.pStr) + 1];
  185. if ( NULL == m_value.pStr )
  186. {
  187. throw CX_MemoryException();
  188. }
  189. strcpy( m_value.pStr, Src.m_value.pStr );
  190. }
  191. else
  192. {
  193. m_value.pStr = NULL;
  194. }
  195. break;
  196. case VT_LPWSTR:
  197. case VT_BSTR:
  198. // Check for an allocation failure
  199. if ( NULL != Src.m_value.pWStr )
  200. {
  201. m_value.pWStr = new wchar_t[wcslen(Src.m_value.pWStr) + 1];
  202. if ( NULL == m_value.pWStr )
  203. {
  204. throw CX_MemoryException();
  205. }
  206. wcscpy( m_value.pWStr, Src.m_value.pWStr );
  207. }
  208. else
  209. {
  210. m_value.pWStr = NULL;
  211. }
  212. break;
  213. case VT_BLOB:
  214. // This will natively throw an exception, but make sure the
  215. // original value is cleared in case an exception is thrown
  216. // so we don't AV destructing this object
  217. ZeroMemory( &m_value.Blob, sizeof( m_value.Blob ) );
  218. m_value.Blob = BlobCopy(&Src.m_value.Blob);
  219. break;
  220. case VT_CLSID:
  221. m_value.pClsId = new CLSID(*Src.m_value.pClsId);
  222. // Check for a failed allocation
  223. if ( NULL == m_value.pClsId )
  224. {
  225. throw CX_MemoryException();
  226. }
  227. break;
  228. case VT_DISPATCH:
  229. m_value.pDisp = Src.m_value.pDisp;
  230. if(m_value.pDisp) m_value.pDisp->AddRef();
  231. break;
  232. case VT_UNKNOWN:
  233. m_value.pUnk = Src.m_value.pUnk;
  234. if(m_value.pUnk) m_value.pUnk->AddRef();
  235. break;
  236. // CVarVector
  237. // ==========
  238. case VT_EX_CVARVECTOR:
  239. m_value.pVarVector = new CVarVector(*Src.m_value.pVarVector);
  240. // Check for a failed allocation
  241. if ( NULL == m_value.pVarVector )
  242. {
  243. throw CX_MemoryException();
  244. }
  245. break;
  246. // All remaining simple types.
  247. // ===========================
  248. default:
  249. m_value = Src.m_value;
  250. }
  251. return *this;
  252. }
  253. //***************************************************************************
  254. //
  255. // CVar::operator ==
  256. //
  257. // Equality test operator.
  258. //
  259. //***************************************************************************
  260. int CVar::operator ==(CVar &Src)
  261. {
  262. return CompareTo(Src, TRUE);
  263. }
  264. BOOL CVar::CompareTo(CVar& Src, BOOL bIgnoreCase)
  265. {
  266. // If types are not the same, forget the test.
  267. // ===========================================
  268. if (m_vt != Src.m_vt)
  269. return 0;
  270. // If here, the types are the same, so test
  271. // the fields.
  272. // ========================================
  273. switch (m_vt) {
  274. case VT_LPSTR:
  275. if(bIgnoreCase)
  276. {
  277. if (wbem_stricmp(m_value.pStr, Src.m_value.pStr) == 0)
  278. return 1;
  279. }
  280. else
  281. {
  282. if (strcmp(m_value.pStr, Src.m_value.pStr) == 0)
  283. return 1;
  284. }
  285. break;
  286. case VT_LPWSTR:
  287. case VT_BSTR:
  288. if(bIgnoreCase)
  289. {
  290. if (wbem_wcsicmp(m_value.pWStr, Src.m_value.pWStr) == 0)
  291. return 1;
  292. }
  293. else
  294. {
  295. if (wcscmp( m_value.pWStr, Src.m_value.pWStr) == 0)
  296. return 1;
  297. }
  298. break;
  299. case VT_BLOB:
  300. if (BlobLength(&m_value.Blob) != BlobLength(&Src.m_value.Blob))
  301. return 0;
  302. if (memcmp(BlobDataPtr(&m_value.Blob), BlobDataPtr(&Src.m_value.Blob),
  303. BlobLength(&m_value.Blob)) == 0)
  304. return 1;
  305. break;
  306. case VT_CLSID:
  307. if (memcmp(m_value.pClsId, Src.m_value.pClsId, sizeof(CLSID)) == 0)
  308. return 1;
  309. break;
  310. // CVarVector
  311. // ==========
  312. case VT_EX_CVARVECTOR:
  313. if (m_value.pVarVector == Src.m_value.pVarVector)
  314. return 1;
  315. if (m_value.pVarVector == 0 || Src.m_value.pVarVector == 0)
  316. return 0;
  317. return *m_value.pVarVector == *Src.m_value.pVarVector;
  318. // All remaining simple types.
  319. // ===========================
  320. case VT_I1:
  321. return m_value.cVal == Src.m_value.cVal;
  322. case VT_UI1:
  323. return m_value.bVal == Src.m_value.bVal;
  324. case VT_I2:
  325. return m_value.iVal == Src.m_value.iVal;
  326. case VT_UI2:
  327. return m_value.wVal == Src.m_value.wVal;
  328. case VT_I4:
  329. return m_value.lVal == Src.m_value.lVal;
  330. case VT_UI4:
  331. return m_value.dwVal == Src.m_value.dwVal;
  332. case VT_BOOL:
  333. return m_value.boolVal == Src.m_value.boolVal;
  334. case VT_R8:
  335. return m_value.dblVal == Src.m_value.dblVal;
  336. case VT_R4:
  337. return m_value.fltVal == Src.m_value.fltVal;
  338. case VT_DISPATCH:
  339. // Note: no proper comparison of embedded objects.
  340. return m_value.pDisp == Src.m_value.pDisp;
  341. case VT_UNKNOWN:
  342. // Note: no proper comparison of embedded objects.
  343. return m_value.pUnk == Src.m_value.pUnk;
  344. case VT_FILETIME:
  345. if (memcmp(&m_value.Time, &Src.m_value.Time, sizeof(FILETIME)) == 0)
  346. return 1;
  347. case VT_NULL:
  348. return 1;
  349. }
  350. return 0;
  351. }
  352. //***************************************************************************
  353. //
  354. // CVar::Empty
  355. //
  356. // Clears the CVar to 'empty', deallocates any objects based on pointers,
  357. // unless bCanDelete is set to FALSE, indicating that the stored pointer
  358. // is owned by somebody else.
  359. //
  360. //***************************************************************************
  361. void CVar::Empty()
  362. {
  363. if(m_bCanDelete)
  364. {
  365. // Only pointer types require a deallocation phase.
  366. // =================================================
  367. switch (m_vt) {
  368. case VT_LPSTR: delete m_value.pStr; break;
  369. case VT_LPWSTR: delete m_value.pWStr; break;
  370. case VT_BSTR: delete m_value.Str; break;
  371. case VT_BLOB: BlobClear(&m_value.Blob); break;
  372. case VT_CLSID: delete m_value.pClsId; break;
  373. case VT_EX_CVARVECTOR: delete m_value.pVarVector; break;
  374. case VT_DISPATCH: if(m_value.pDisp) m_value.pDisp->Release(); break;
  375. case VT_UNKNOWN: if(m_value.pUnk) m_value.pUnk->Release(); break;
  376. }
  377. }
  378. memset(&m_value, 0, sizeof(METAVALUE));
  379. m_vt = VT_EMPTY;
  380. m_nStatus = no_error;
  381. m_bCanDelete = TRUE;
  382. }
  383. //***************************************************************************
  384. //
  385. // CVar::IsDataNull
  386. //
  387. // Determines if this CVar contains a NULL pointer.
  388. //
  389. //***************************************************************************
  390. BOOL CVar::IsDataNull()
  391. {
  392. if(m_vt == VT_LPWSTR && m_value.pWStr == NULL)
  393. return TRUE;
  394. if(m_vt == VT_LPSTR && m_value.pStr == NULL)
  395. return TRUE;
  396. if(m_vt == VT_BSTR && m_value.Str == NULL)
  397. return TRUE;
  398. if(m_vt == VT_DISPATCH && m_value.pDisp == NULL)
  399. return TRUE;
  400. if(m_vt == VT_UNKNOWN && m_value.pUnk == NULL)
  401. return TRUE;
  402. return FALSE;
  403. }
  404. //***************************************************************************
  405. //
  406. // CVar::SetRaw
  407. //
  408. // Creates a CVar from raw data. Sets the type and copies the right
  409. // number of bytes from the source to METAVALUE.
  410. //
  411. //***************************************************************************
  412. void CVar::SetRaw(int vt, void* pvData, int nDataLen)
  413. {
  414. m_vt = vt;
  415. memcpy(&m_value, pvData, nDataLen);
  416. m_nStatus = no_error;
  417. m_bCanDelete = TRUE;
  418. }
  419. //***************************************************************************
  420. //
  421. // CVar::SetSafeArray
  422. //
  423. // PARAMETERS:
  424. // nType
  425. // This is the VT_ type indicator of the SAFEARRAY.
  426. // pArray
  427. // This is the pointer to the SAFEARRAY which will be used as
  428. // a source. The SAFEARRAY is not acquired; it is copied.
  429. //
  430. //***************************************************************************
  431. void CVar::SetSafeArray(int nType, SAFEARRAY *pArray)
  432. {
  433. CVarVector *pVec = NULL;
  434. m_nStatus = no_error;
  435. try
  436. {
  437. pVec = new CVarVector(nType, pArray);
  438. // Check for a failed allocation
  439. if ( NULL == pVec )
  440. {
  441. throw CX_MemoryException();
  442. }
  443. SetVarVector(pVec, TRUE);
  444. }
  445. catch (CX_MemoryException)
  446. {
  447. // SetVarVector can throw an exception
  448. // m_value aquires the pVec pointer, so auto delete will not work
  449. if (NULL != pVec)
  450. {
  451. delete pVec;
  452. pVec = NULL;
  453. }
  454. throw;
  455. }
  456. }
  457. //***************************************************************************
  458. //
  459. // CVar::GetNewSafeArray
  460. //
  461. // RETURN VALUE:
  462. // A pointer to newly allocated SAFEARRAY which must be released by
  463. // SafeArrayDestroy.
  464. //
  465. //***************************************************************************
  466. SAFEARRAY *CVar::GetNewSafeArray()
  467. {
  468. CVarVector *p = (CVarVector *) GetVarVector();
  469. return p->GetNewSafeArray();
  470. }
  471. //***************************************************************************
  472. //
  473. // CVar::SetValue
  474. //
  475. // Sets the value based on an incoming VARIANT. A VARIANT containing
  476. // a SAFEARRAY is supported as long as it is not an array of VARIANTs.
  477. // Some of the other VARIANT types, such as IUnknown, Currency, etc.,
  478. // are not supported. The complete list is:
  479. // VT_UI1, VT_I2, VT_I4, VT_BSTR, VT_BOOL
  480. // VT_R4, VT_R8, or SAFEARRAY of any of these.
  481. //
  482. // PARAMETERS:
  483. // pSrc
  484. // A pointer to the source VARIANT. This is treated as read-only.
  485. //
  486. // RETURN VALUES:
  487. // no_error
  488. // Returned on succcess.
  489. // unsupported
  490. // Returned if the VARIANT contains unsupported types.
  491. //
  492. //***************************************************************************
  493. int CVar::SetVariant(VARIANT *pSrc)
  494. {
  495. if(pSrc == NULL)
  496. {
  497. SetAsNull();
  498. return no_error;
  499. }
  500. // If a SAFEARRAY, check it.
  501. // =========================
  502. if (pSrc->vt & VT_ARRAY)
  503. {
  504. CVarVector *pVec = NULL;
  505. try
  506. {
  507. int nType = pSrc->vt & 0xFF; // Find the type of the array
  508. // BEGIN MODIFIED by a-levn
  509. // First, check if the incoming SAFEARRAY is NULL
  510. // ==============================================
  511. SAFEARRAY *pSafeArr;
  512. /*
  513. if(pSrc->parray == NULL)
  514. {
  515. pSafeArr = NULL;
  516. }
  517. else
  518. {
  519. // Make a copy of the SAFEARRAY using CSafeArray which will NOT
  520. // autodestruct
  521. // ============================================================
  522. CSafeArray array(pSrc->parray, nType, CSafeArray::no_delete, 0);
  523. pSafeArr = array.GetArray();
  524. }
  525. */
  526. pSafeArr = pSrc->parray;
  527. // Goal: Convert the SAFEARRAY to a CVarVector.
  528. // Use CVarVector itself to do the conversion.
  529. // ===========================================
  530. pVec = new CVarVector(nType, pSafeArr);
  531. // Check for an allocation failure.
  532. if ( NULL == pVec )
  533. {
  534. throw CX_MemoryException();
  535. }
  536. // END MODIFIED
  537. if (pVec->Status() != no_error)
  538. {
  539. // If here, the SAFEARRAY was not compatible.
  540. // ==========================================
  541. delete pVec;
  542. pVec = NULL;
  543. m_nStatus = unsupported;
  544. m_vt = VT_EMPTY;
  545. return unsupported;
  546. }
  547. SetVarVector(pVec, TRUE);
  548. return no_error;
  549. }
  550. catch(CX_MemoryException)
  551. {
  552. // new and SetVarVector can throw exceptions
  553. // m_value aquires the pVec pointer, so an auto delete will not work
  554. if (NULL != pVec)
  555. {
  556. delete pVec;
  557. pVec = NULL;
  558. }
  559. throw;
  560. }
  561. }
  562. // Simple copies.
  563. // ==============
  564. switch (pSrc->vt) {
  565. case VT_NULL:
  566. SetAsNull();
  567. return no_error;
  568. case VT_UI1:
  569. SetByte(pSrc->bVal);
  570. return no_error;
  571. case VT_I2:
  572. SetShort(pSrc->iVal);
  573. return no_error;
  574. case VT_I4:
  575. SetLong(pSrc->lVal);
  576. return no_error;
  577. case VT_R4:
  578. SetFloat(pSrc->fltVal);
  579. return no_error;
  580. case VT_R8:
  581. SetDouble(pSrc->dblVal);
  582. return no_error;
  583. case VT_BSTR:
  584. SetBSTR(pSrc->bstrVal);
  585. return no_error;
  586. case VT_BOOL:
  587. SetBool(pSrc->boolVal);
  588. return no_error;
  589. case VT_DISPATCH:
  590. SetDispatch(V_DISPATCH(pSrc));
  591. return no_error;
  592. case VT_UNKNOWN:
  593. SetUnknown(V_UNKNOWN(pSrc));
  594. return no_error;
  595. }
  596. m_nStatus = unsupported;
  597. return unsupported;
  598. }
  599. //***************************************************************************
  600. //
  601. // CVar::GetNewVariant
  602. //
  603. // RETURN VALUE:
  604. // A pointer to a new VARIANT which contains the value of object.
  605. // If the original value was a SAFEARRAY, then the VARIANT will contain
  606. // the embedded SAFEARRAY.
  607. //
  608. //***************************************************************************
  609. void CVar::FillVariant(VARIANT* pNew)
  610. {
  611. switch (m_vt) {
  612. case VT_NULL:
  613. V_VT(pNew) = VT_NULL;
  614. break;
  615. case VT_BOOL:
  616. V_VT(pNew) = VT_BOOL;
  617. V_BOOL(pNew) = (m_value.boolVal ? VARIANT_TRUE : VARIANT_FALSE);
  618. break;
  619. case VT_BSTR:
  620. // Set type afterwards here so if the SysAlloc throws an exception, the
  621. // type will not have been reset to a VT_BSTR which could cause a subtle
  622. // memory corruption (or worse) if VariantClear is called - SJS
  623. V_BSTR(pNew) = SysAllocString(m_value.Str);
  624. V_VT(pNew) = VT_BSTR;
  625. break;
  626. case VT_DISPATCH:
  627. V_VT(pNew) = VT_DISPATCH;
  628. V_DISPATCH(pNew) = m_value.pDisp;
  629. if(m_value.pDisp) m_value.pDisp->AddRef();
  630. break;
  631. case VT_UNKNOWN:
  632. V_VT(pNew) = VT_UNKNOWN;
  633. V_UNKNOWN(pNew) = m_value.pUnk;
  634. if(m_value.pUnk) m_value.pUnk->AddRef();
  635. break;
  636. case VT_UI1:
  637. V_VT(pNew) = VT_UI1;
  638. V_UI1(pNew) = m_value.bVal;
  639. break;
  640. case VT_I4:
  641. V_VT(pNew) = VT_I4;
  642. V_I4(pNew) = m_value.lVal;
  643. break;
  644. case VT_I2:
  645. V_VT(pNew) = VT_I2;
  646. V_I2(pNew) = m_value.iVal;
  647. break;
  648. case VT_R4:
  649. V_VT(pNew) = VT_R4;
  650. V_R4(pNew) = m_value.fltVal;
  651. break;
  652. case VT_R8:
  653. V_VT(pNew) = VT_R8;
  654. V_R8(pNew) = m_value.dblVal;
  655. break;
  656. // An embedded CVarVector which must be converted
  657. // to a SAFEARRAY.
  658. // ==============================================
  659. case VT_EX_CVARVECTOR:
  660. {
  661. // Set type afterwards here so if GetNewSafeArray throws an exception, the
  662. // type will not have been reset to an Array which could cause a subtle
  663. // memory corruption (or worse) if VariantClear is called - SJS
  664. V_ARRAY(pNew) = m_value.pVarVector->GetNewSafeArray();
  665. V_VT(pNew) = m_value.pVarVector->GetType() | VT_ARRAY;
  666. }
  667. break;
  668. default:
  669. VariantClear(pNew);
  670. }
  671. }
  672. VARIANT *CVar::GetNewVariant()
  673. {
  674. VARIANT *pNew = new VARIANT;
  675. // Check for an allocation failure.
  676. if ( NULL == pNew )
  677. {
  678. throw CX_MemoryException();
  679. }
  680. VariantInit(pNew);
  681. FillVariant(pNew);
  682. return pNew;
  683. }
  684. //***************************************************************************
  685. //
  686. //***************************************************************************
  687. int CVar::DumpText(FILE *fStream)
  688. {
  689. return unsupported;
  690. }
  691. //***************************************************************************
  692. //
  693. // CVar::SetLPWSTR
  694. //
  695. // Sets the value of the CVar to the indicated LPWSTR.
  696. //
  697. // PARAMETERS:
  698. // pStr
  699. // A pointer to the source string.
  700. // bAcquire
  701. // If TRUE, then the ownership of pStr is trasferred and becomes
  702. // the internal pointer to the string. If FALSE, then the string
  703. // is copied.
  704. //
  705. //***************************************************************************
  706. BOOL CVar::SetLPWSTR(LPWSTR pStr, BOOL bAcquire)
  707. {
  708. m_vt = VT_LPWSTR;
  709. if (bAcquire)
  710. {
  711. m_value.pWStr = pStr;
  712. return TRUE;
  713. }
  714. else
  715. {
  716. // Check for an allocation failure
  717. if ( NULL != pStr )
  718. {
  719. m_value.pWStr = new wchar_t[wcslen(pStr) + 1];
  720. if ( NULL == m_value.pWStr )
  721. {
  722. throw CX_MemoryException();
  723. }
  724. wcscpy( m_value.pWStr, pStr );
  725. }
  726. else
  727. {
  728. m_value.pWStr = NULL;
  729. }
  730. return TRUE;
  731. }
  732. }
  733. //***************************************************************************
  734. //
  735. // CVar::SetLPSTR
  736. //
  737. // Sets the value of the CVar to the indicated LPSTR.
  738. //
  739. // PARAMETERS:
  740. // pStr
  741. // A pointer to the source string.
  742. // bAcquire
  743. // If TRUE, then the ownership of pStr is trasferred and becomes
  744. // the internal pointer to the string. If FALSE, then the string
  745. // is copied (it must have been allocated with operator new).
  746. //
  747. //***************************************************************************
  748. BOOL CVar::SetLPSTR(LPSTR pStr, BOOL bAcquire)
  749. {
  750. m_vt = VT_LPSTR;
  751. if (bAcquire)
  752. {
  753. m_value.pStr = pStr;
  754. return TRUE;
  755. }
  756. else
  757. {
  758. if ( NULL != pStr)
  759. {
  760. m_value.pStr = new char[strlen(pStr) + 1];
  761. // On failure, throw an exception
  762. if ( NULL == m_value.pStr )
  763. {
  764. throw CX_MemoryException();
  765. }
  766. strcpy( m_value.pStr, pStr );
  767. }
  768. else
  769. {
  770. m_value.pStr = NULL;
  771. }
  772. return TRUE;
  773. }
  774. }
  775. //***************************************************************************
  776. //
  777. // CVar::SetBSTR
  778. //
  779. // Sets the value of the CVar to the indicated BSTR.
  780. //
  781. // NOTE: This BSTR value is actually stored as an LPWSTR to avoid
  782. // apartment-threading restrictions on real BSTR objects allocated
  783. // with SysAllocString.
  784. //
  785. // PARAMETERS:
  786. // str
  787. // A pointer to the string, which is copied into an internal LPWSTR.
  788. // bAcquire
  789. // If FALSE, then the BSTR is treated as read-only and copied.
  790. // If TRUE, then this function becomes owner of the BSTR and
  791. // frees it after the copy is made.
  792. //
  793. //***************************************************************************
  794. BOOL CVar::SetBSTR(BSTR str, BOOL bAcquire)
  795. {
  796. m_vt = VT_BSTR;
  797. if (str == 0) {
  798. m_value.pWStr = 0;
  799. return TRUE;
  800. }
  801. // Check for an allocation failure
  802. if ( NULL != str )
  803. {
  804. m_value.pWStr = new wchar_t[wcslen(str) + 1];
  805. // If allocation fails, throw an exception
  806. if ( NULL == m_value.pWStr )
  807. {
  808. throw CX_MemoryException();
  809. }
  810. wcscpy( m_value.pWStr, str );
  811. }
  812. else
  813. {
  814. m_value.pWStr = NULL;
  815. }
  816. // Check that this succeeded before we free
  817. // the string passed into us
  818. if ( NULL != m_value.pWStr )
  819. {
  820. if (bAcquire)
  821. SysFreeString(str);
  822. }
  823. // return whether or not we obtained a value
  824. return ( NULL != m_value.pWStr );
  825. }
  826. //***************************************************************************
  827. //
  828. // CVar::GetBSTR
  829. //
  830. // Returns the BSTR value of the current object.
  831. //
  832. // RETURN VALUE:
  833. // A newly allocated BSTR which must be freed with SysFreeString().
  834. //
  835. //***************************************************************************
  836. BSTR CVar::GetBSTR()
  837. {
  838. if (m_vt != VT_BSTR)
  839. return NULL;
  840. return SysAllocString(m_value.pWStr);
  841. }
  842. void CVar::SetDispatch(IDispatch* pDisp)
  843. {
  844. m_vt = VT_DISPATCH;
  845. m_value.pDisp = pDisp;
  846. if(pDisp)
  847. {
  848. pDisp->AddRef();
  849. }
  850. }
  851. void CVar::SetUnknown(IUnknown* pUnk)
  852. {
  853. m_vt = VT_UNKNOWN;
  854. m_value.pUnk = pUnk;
  855. if(pUnk)
  856. {
  857. pUnk->AddRef();
  858. }
  859. }
  860. //***************************************************************************
  861. //
  862. // CVar::SetBlob
  863. //
  864. // Sets the object to the value of the BLOB object.
  865. //
  866. // PARAMETERS:
  867. // pBlob
  868. // A pointer to a valid VT_BLOB object.
  869. // bAcquire
  870. // If TRUE, then the pointer to the data will be acquired. It must
  871. // have been allocated with operator new in the current process,
  872. // since operator delete will be used to free it.
  873. //
  874. //***************************************************************************
  875. void CVar::SetBlob(BLOB *pBlob, BOOL bAcquire)
  876. {
  877. m_vt = VT_BLOB;
  878. if (pBlob == 0)
  879. BlobClear(&m_value.Blob);
  880. else if (!bAcquire)
  881. m_value.Blob = BlobCopy(pBlob);
  882. else
  883. m_value.Blob = *pBlob;
  884. }
  885. //***************************************************************************
  886. //
  887. // CVar::SetClsId
  888. //
  889. // Sets the value of the object to a CLSID.
  890. //
  891. // PARAMETERS:
  892. // pClsId
  893. // Points the source CLSID.
  894. // bAcquire
  895. // If TRUE, the ownership of the pointer is transferred to the
  896. // object. The CLSID must have been allocated with operator new.
  897. // If FALSE, the caller retains ownership and a copy is made.
  898. //
  899. //***************************************************************************
  900. void CVar::SetClsId(CLSID *pClsId, BOOL bAcquire)
  901. {
  902. m_vt = VT_CLSID;
  903. if (pClsId == 0)
  904. m_value.pClsId = 0;
  905. else
  906. {
  907. m_value.pClsId = new CLSID(*pClsId);
  908. // Check for an allocation failure.
  909. if ( NULL == m_value.pClsId )
  910. {
  911. throw CX_MemoryException();
  912. }
  913. }
  914. }
  915. //***************************************************************************
  916. //
  917. // CVar::SetVarVector
  918. //
  919. // Sets the value of the object to the specified CVarVector. This
  920. // allows the CVar to contain a complete array.
  921. //
  922. // PARAMETERS:
  923. // pVec
  924. // A pointer to the CVarVector object which is the source.
  925. // bAcquire
  926. // If TRUE, then ownership of the CVarVector is transferred to
  927. // the object. If FALSE, a new copy of the CVarVector is made and
  928. // the caller retains ownership.
  929. //
  930. //***************************************************************************
  931. void CVar::SetVarVector(CVarVector *pVec, BOOL bAcquire)
  932. {
  933. m_vt = VT_EX_CVARVECTOR;
  934. if (bAcquire) {
  935. // If here, we acquire the caller's pointer.
  936. // =========================================
  937. m_value.pVarVector = pVec;
  938. return;
  939. }
  940. // If here, make a copy.
  941. // =====================
  942. m_value.pVarVector = new CVarVector(*pVec);
  943. // Check for an allocation failure.
  944. if ( NULL == m_value.pVarVector )
  945. {
  946. throw CX_MemoryException();
  947. }
  948. }
  949. int CVar::GetOleType()
  950. {
  951. if(m_vt == VT_EX_CVARVECTOR)
  952. {
  953. if(m_value.pVarVector == NULL) return VT_ARRAY;
  954. else return VT_ARRAY | m_value.pVarVector->GetType();
  955. }
  956. else
  957. {
  958. return m_vt;
  959. }
  960. }
  961. //***************************************************************************
  962. //
  963. // CVar::GetText
  964. //
  965. // Produces textual representation of the Var's type and data
  966. //
  967. // PARAMETERS:
  968. // long lFlags reseved, must be 0
  969. // BSTR* pstrType destination for the type representation
  970. // BSTR* pstrValue destination for the value representation.
  971. //
  972. //***************************************************************************
  973. BSTR CVar::GetText(long lFlags, long lType)
  974. {
  975. if(m_vt == VT_EX_CVARVECTOR)
  976. {
  977. // When we get the text for the array, make sure the CIM_FLAG_ARRAY is masked out
  978. BSTR strTemp = GetVarVector()->GetText(lFlags, lType & ~CIM_FLAG_ARRAY);
  979. CSysFreeMe auto1(strTemp);
  980. WCHAR* wszValue = new WCHAR[SysStringLen(strTemp) + 3];
  981. // Check for allocation failures
  982. if ( NULL == wszValue )
  983. {
  984. throw CX_MemoryException();
  985. }
  986. CVectorDeleteMe<WCHAR> auto2(wszValue);
  987. wcscpy(wszValue, L"{");
  988. wcscat(wszValue, strTemp);
  989. wcscat(wszValue, L"}");
  990. BSTR strRet = SysAllocString(wszValue);
  991. return strRet;
  992. }
  993. WCHAR* wszValue = new WCHAR[100];
  994. // Check for allocation failures
  995. if ( NULL == wszValue )
  996. {
  997. throw CX_MemoryException();
  998. }
  999. WCHAR* pwc;
  1000. int i;
  1001. if(m_vt == VT_NULL)
  1002. return NULL;
  1003. if(lType == 0)
  1004. lType = m_vt;
  1005. try
  1006. {
  1007. switch(lType)
  1008. {
  1009. case CIM_SINT8:
  1010. swprintf(wszValue, L"%d", (long)(signed char)GetByte());
  1011. break;
  1012. case CIM_UINT8:
  1013. swprintf(wszValue, L"%d", GetByte());
  1014. break;
  1015. case CIM_SINT16:
  1016. swprintf(wszValue, L"%d", (long)GetShort());
  1017. break;
  1018. case CIM_UINT16:
  1019. swprintf(wszValue, L"%d", (long)(USHORT)GetShort());
  1020. break;
  1021. case CIM_SINT32:
  1022. swprintf(wszValue, L"%d", GetLong());
  1023. break;
  1024. case CIM_UINT32:
  1025. swprintf(wszValue, L"%lu", (ULONG)GetLong());
  1026. break;
  1027. case CIM_BOOLEAN:
  1028. swprintf(wszValue, L"%s", (GetBool()?L"TRUE":L"FALSE"));
  1029. break;
  1030. case CIM_REAL32:
  1031. {
  1032. // Since the decimal point can be localized, and MOF text should
  1033. // always be english, we will return values localized to 0x409,
  1034. CVar var( GetFloat() );
  1035. // If this fails, we can't guarantee a good value,
  1036. // so throw an exception.
  1037. if ( !var.ChangeTypeToEx( VT_BSTR ) )
  1038. {
  1039. throw CX_Exception();
  1040. }
  1041. wcscpy( wszValue, var.GetLPWSTR() );
  1042. }
  1043. break;
  1044. case CIM_REAL64:
  1045. {
  1046. // Since the decimal point can be localized, and MOF text should
  1047. // always be english, we will return values localized to 0x409,
  1048. CVar var( GetDouble() );
  1049. // If this fails, we can't guarantee a good value,
  1050. // so throw an exception.
  1051. if ( !var.ChangeTypeToEx( VT_BSTR ) )
  1052. {
  1053. throw CX_Exception();
  1054. }
  1055. wcscpy( wszValue, var.GetLPWSTR() );
  1056. }
  1057. break;
  1058. case CIM_CHAR16:
  1059. if(GetShort() == 0)
  1060. wcscpy(wszValue, L"0x0");
  1061. else
  1062. swprintf(wszValue, L"'\\x%X'", (WCHAR)GetShort());
  1063. break;
  1064. case CIM_OBJECT:
  1065. swprintf(wszValue, L"\"not supported\"");
  1066. break;
  1067. case CIM_REFERENCE:
  1068. case CIM_DATETIME:
  1069. case CIM_STRING:
  1070. case CIM_SINT64:
  1071. case CIM_UINT64:
  1072. {
  1073. // Escape all the quotes
  1074. // =====================
  1075. int nStrLen = wcslen(GetLPWSTR());
  1076. delete [] wszValue;
  1077. wszValue = NULL;
  1078. wszValue = new WCHAR[nStrLen*2+10];
  1079. // Check for allocation failures
  1080. if ( NULL == wszValue )
  1081. {
  1082. throw CX_MemoryException();
  1083. }
  1084. wszValue[0] = L'"';
  1085. pwc = wszValue+1;
  1086. for(i = 0; i < (int)nStrLen; i++)
  1087. {
  1088. WCHAR wch = GetLPWSTR()[i];
  1089. if(wch == L'\n')
  1090. {
  1091. *(pwc++) = L'\\';
  1092. *(pwc++) = L'n';
  1093. }
  1094. else if(wch == L'\t')
  1095. {
  1096. *(pwc++) = L'\\';
  1097. *(pwc++) = L't';
  1098. }
  1099. else if(wch == L'"' || wch == L'\\')
  1100. {
  1101. *(pwc++) = L'\\';
  1102. *(pwc++) = wch;
  1103. }
  1104. else
  1105. {
  1106. *(pwc++) = wch;
  1107. }
  1108. }
  1109. *(pwc++) = L'"';
  1110. *pwc = 0;
  1111. }
  1112. break;
  1113. default:
  1114. swprintf(wszValue, L"\"not supported\"");
  1115. break;
  1116. }
  1117. BSTR strRes = SysAllocString(wszValue);
  1118. // Still need to clean up this value
  1119. delete [] wszValue;
  1120. return strRes;
  1121. }
  1122. catch (...)
  1123. {
  1124. // Cleanup always if this has a value
  1125. if ( NULL != wszValue )
  1126. {
  1127. delete [] wszValue;
  1128. }
  1129. // Rethrow the exception
  1130. throw;
  1131. }
  1132. }
  1133. BSTR CVar::TypeToText(int nType)
  1134. {
  1135. const WCHAR* pwcType;
  1136. switch(nType)
  1137. {
  1138. case VT_I1:
  1139. pwcType = L"sint8";
  1140. break;
  1141. case VT_UI1:
  1142. pwcType = L"uint8";
  1143. break;
  1144. case VT_I2:
  1145. pwcType = L"sint16";
  1146. break;
  1147. case VT_UI2:
  1148. pwcType = L"uint16";
  1149. break;
  1150. case VT_I4:
  1151. pwcType = L"sint32";
  1152. break;
  1153. case VT_UI4:
  1154. pwcType = L"uint32";
  1155. break;
  1156. case VT_I8:
  1157. pwcType = L"sint64";
  1158. break;
  1159. case VT_UI8:
  1160. pwcType = L"uint64";
  1161. break;
  1162. case VT_BOOL:
  1163. pwcType = L"boolean";
  1164. break;
  1165. case VT_R4:
  1166. pwcType = L"real32";
  1167. break;
  1168. case VT_R8:
  1169. pwcType = L"real64";
  1170. break;
  1171. case VT_BSTR:
  1172. pwcType = L"string";
  1173. break;
  1174. case VT_DISPATCH:
  1175. pwcType = L"object";
  1176. break;
  1177. case VT_UNKNOWN:
  1178. pwcType = L"object";
  1179. break;
  1180. default:
  1181. return NULL;
  1182. }
  1183. return SysAllocString(pwcType);
  1184. }
  1185. BSTR CVar::GetTypeText()
  1186. {
  1187. if(m_vt != VT_EX_CVARVECTOR)
  1188. {
  1189. return TypeToText(m_vt);
  1190. }
  1191. else
  1192. {
  1193. return TypeToText(GetVarVector()->GetType());
  1194. }
  1195. }
  1196. BOOL CVar::ChangeTypeTo(VARTYPE vtNew)
  1197. {
  1198. // TBD: there are more efficient ways!
  1199. // ===================================
  1200. // Create a VARIANT
  1201. // ================
  1202. VARIANT v;
  1203. CClearMe auto1(&v);
  1204. VariantInit(&v);
  1205. FillVariant(&v);
  1206. // Coerce it
  1207. // =========
  1208. HRESULT hres = WbemVariantChangeType(&v, &v, vtNew);
  1209. if(FAILED(hres))
  1210. return FALSE;
  1211. // Load it back in
  1212. // ===============
  1213. Empty();
  1214. SetVariant(&v);
  1215. return TRUE;
  1216. }
  1217. // Performs localized changes (defaults to 0x409 for this)
  1218. BOOL CVar::ChangeTypeToEx(VARTYPE vtNew, LCID lcid /*=0x409*/)
  1219. {
  1220. // TBD: there are more efficient ways!
  1221. // ===================================
  1222. // Create a VARIANT
  1223. // ================
  1224. VARIANT v;
  1225. CClearMe auto1(&v);
  1226. VariantInit(&v);
  1227. FillVariant(&v);
  1228. // Coerce it
  1229. // =========
  1230. try
  1231. {
  1232. HRESULT hres = VariantChangeTypeEx(&v, &v, lcid, 0L, vtNew);
  1233. if(FAILED(hres))
  1234. return FALSE;
  1235. }
  1236. catch(...)
  1237. {
  1238. return FALSE;
  1239. }
  1240. // Load it back in
  1241. // ===============
  1242. Empty();
  1243. SetVariant(&v);
  1244. return TRUE;
  1245. }
  1246. BOOL CVar::ToSingleChar()
  1247. {
  1248. // Defer to CVarVector for arrays
  1249. // ==============================
  1250. if(m_vt == VT_EX_CVARVECTOR)
  1251. {
  1252. return GetVarVector()->ToSingleChar();
  1253. }
  1254. // Anything that's not a string follows normal OLE rules
  1255. // =====================================================
  1256. if(m_vt != VT_BSTR)
  1257. {
  1258. return ChangeTypeTo(VT_I2);
  1259. }
  1260. // It's a string. Make sure the length is 1
  1261. // ========================================
  1262. LPCWSTR wsz = GetLPWSTR();
  1263. if(wcslen(wsz) != 1)
  1264. return FALSE;
  1265. // Take the first character
  1266. // ========================
  1267. WCHAR wc = wsz[0];
  1268. Empty();
  1269. SetShort(wc);
  1270. return TRUE;
  1271. }
  1272. BOOL CVar::ToUI4()
  1273. {
  1274. // Defer to CVarVector for arrays
  1275. // ==============================
  1276. if(m_vt == VT_EX_CVARVECTOR)
  1277. {
  1278. return GetVarVector()->ToSingleChar();
  1279. }
  1280. // Create a VARIANT
  1281. // ================
  1282. VARIANT v;
  1283. CClearMe auto1(&v);
  1284. VariantInit(&v);
  1285. FillVariant(&v);
  1286. // Coerce it
  1287. // =========
  1288. HRESULT hres = WbemVariantChangeType(&v, &v, VT_UI4);
  1289. if(FAILED(hres))
  1290. return FALSE;
  1291. // Load it back in
  1292. // ===============
  1293. Empty();
  1294. // Here we cheat and reset to VT_I4 so we can natively reset
  1295. V_VT(&v) = VT_I4;
  1296. SetVariant(&v);
  1297. return TRUE;
  1298. }
  1299. //***************************************************************************
  1300. //
  1301. // CVarVector::CVarVector
  1302. //
  1303. // Default constructor. The caller should not attempt to add any
  1304. // elements when the internal type is VT_EMPTY. Objects constructed
  1305. // with this constructor should only be used as l-values in an
  1306. // assignment of CVarVector objects.
  1307. //
  1308. //***************************************************************************
  1309. CVarVector::CVarVector()
  1310. {
  1311. m_Array.Empty();
  1312. m_nType = VT_EMPTY;
  1313. m_nStatus = no_error;
  1314. }
  1315. //***************************************************************************
  1316. //
  1317. // CVarVector::CVarVector
  1318. //
  1319. // This is the standard constructor.
  1320. //
  1321. // PARAMETERS:
  1322. // nVarType
  1323. // An OLE VT_ type indicator. Heterogeneous arrays are possible
  1324. // if the type VT_EX_CVAR is used. Embedded CVarVectors can
  1325. // occur, since a CVar can in turn hold a CVarVector.
  1326. //
  1327. // nInitSize
  1328. // The starting size of the internal CFlexArray. See FLEXARRY.CPP.
  1329. // nGrowBy
  1330. // The "grow by" factor of the internal CFlexArray. See FLEXARRAY.CPP.
  1331. //
  1332. //***************************************************************************
  1333. CVarVector::CVarVector(
  1334. int nVarType,
  1335. int nInitSize,
  1336. int nGrowBy
  1337. ) :
  1338. m_Array(nInitSize, nGrowBy)
  1339. {
  1340. m_nType = nVarType;
  1341. m_nStatus = no_error;
  1342. }
  1343. //***************************************************************************
  1344. //
  1345. // CVarVector::CVarVector
  1346. //
  1347. // Alternate constructor to build a new CVarVector based on a
  1348. // SAFEARRAY object. The only supported types for the SAFEARRAY
  1349. // are VT_BSTR, VT_UI1, VT_I2, VT_I4, VT_R4, and VT_R8.
  1350. //
  1351. // PARAMETERS:
  1352. // nVarType
  1353. // The VT_ type indicator of the incoming SAFEARRAY.
  1354. // pSrc
  1355. // A pointer to a SAFEARRAY, which is treated as read-only.
  1356. //
  1357. // NOTES:
  1358. // This will set the internal m_nStatus variable to <unsupported> if
  1359. // an unsupported VT_ type is in the SAFEARRAY. The caller can immediately
  1360. // call CVarVector::Status() after construction to see if the operation
  1361. // was successful.
  1362. //
  1363. //***************************************************************************
  1364. CVarVector::CVarVector(int nVarType, SAFEARRAY *pSrc)
  1365. {
  1366. SAFEARRAY* pNew = NULL;
  1367. try
  1368. {
  1369. m_nType = nVarType;
  1370. if(pSrc == NULL)
  1371. {
  1372. // NULL safearray --- empty
  1373. // ========================
  1374. m_nStatus = no_error;
  1375. return;
  1376. }
  1377. // Bind to the incoming SAFEARRAY, but don't delete it during destruct.
  1378. // ====================================================================
  1379. if(SafeArrayGetDim(pSrc) != 1)
  1380. {
  1381. m_nStatus = unsupported;
  1382. return;
  1383. }
  1384. long lLBound, lUBound;
  1385. SafeArrayGetLBound(pSrc, 1, &lLBound);
  1386. SafeArrayGetUBound(pSrc, 1, &lUBound);
  1387. if(lLBound != 0)
  1388. {
  1389. // Non-0-based safearray --- since CSafeArray doesn't support that, and
  1390. // we can't change pSrc, create a copy
  1391. // ====================================================================
  1392. if(FAILED(SafeArrayCopy(pSrc, &pNew)))
  1393. {
  1394. m_nStatus = failed;
  1395. return;
  1396. }
  1397. SAFEARRAYBOUND sfb;
  1398. sfb.cElements = (lUBound - lLBound) + 1;
  1399. sfb.lLbound = 0;
  1400. SafeArrayRedim(pNew, &sfb);
  1401. }
  1402. else
  1403. {
  1404. pNew = pSrc;
  1405. }
  1406. CSafeArray sa(pNew, nVarType, CSafeArray::no_delete | CSafeArray::bind);
  1407. for (int i = 0; i < sa.Size(); i++) {
  1408. CVar* pVar = NULL;
  1409. switch (m_nType) {
  1410. case VT_BOOL:
  1411. {
  1412. VARIANT_BOOL boolVal = sa.GetBoolAt(i);
  1413. pVar = new CVar(boolVal, VT_BOOL);
  1414. // Check for allocation failure
  1415. if ( NULL == pVar )
  1416. {
  1417. throw CX_MemoryException();
  1418. }
  1419. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1420. {
  1421. delete pVar;
  1422. throw CX_MemoryException();
  1423. }
  1424. break;
  1425. }
  1426. case VT_UI1:
  1427. {
  1428. BYTE b = sa.GetByteAt(i);
  1429. pVar = new CVar(b);
  1430. // Check for allocation failure
  1431. if ( NULL == pVar )
  1432. {
  1433. throw CX_MemoryException();
  1434. }
  1435. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1436. {
  1437. delete pVar;
  1438. throw CX_MemoryException();
  1439. }
  1440. break;
  1441. }
  1442. case VT_I2:
  1443. {
  1444. SHORT s = sa.GetShortAt(i);
  1445. pVar = new CVar(s);
  1446. // Check for allocation failure
  1447. if ( NULL == pVar )
  1448. {
  1449. throw CX_MemoryException();
  1450. }
  1451. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1452. {
  1453. delete pVar;
  1454. throw CX_MemoryException();
  1455. }
  1456. break;
  1457. }
  1458. case VT_I4:
  1459. {
  1460. LONG l = sa.GetLongAt(i);
  1461. pVar = new CVar(l);
  1462. // Check for allocation failure
  1463. if ( NULL == pVar )
  1464. {
  1465. throw CX_MemoryException();
  1466. }
  1467. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1468. {
  1469. delete pVar;
  1470. throw CX_MemoryException();
  1471. }
  1472. break;
  1473. }
  1474. case VT_R4:
  1475. {
  1476. float f = sa.GetFloatAt(i);
  1477. pVar = new CVar(f);
  1478. // Check for allocation failure
  1479. if ( NULL == pVar )
  1480. {
  1481. throw CX_MemoryException();
  1482. }
  1483. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1484. {
  1485. delete pVar;
  1486. throw CX_MemoryException();
  1487. }
  1488. break;
  1489. }
  1490. case VT_R8:
  1491. {
  1492. double d = sa.GetDoubleAt(i);
  1493. pVar = new CVar(d);
  1494. // Check for allocation failure
  1495. if ( NULL == pVar )
  1496. {
  1497. throw CX_MemoryException();
  1498. }
  1499. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1500. {
  1501. delete pVar;
  1502. throw CX_MemoryException();
  1503. }
  1504. break;
  1505. }
  1506. case VT_BSTR:
  1507. {
  1508. BSTR bstr = sa.GetBSTRAt(i);
  1509. CSysFreeMe auto1(bstr);
  1510. pVar = new CVar(VT_BSTR, bstr, FALSE);
  1511. // Check for allocation failure
  1512. if ( NULL == pVar )
  1513. {
  1514. throw CX_MemoryException();
  1515. }
  1516. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1517. {
  1518. delete pVar;
  1519. throw CX_MemoryException();
  1520. }
  1521. break;
  1522. }
  1523. case VT_DISPATCH:
  1524. {
  1525. IDispatch* pDisp = sa.GetDispatchAt(i);
  1526. CReleaseMe auto2(pDisp);
  1527. pVar = new CVar;
  1528. // Check for allocation failure
  1529. if ( NULL == pVar )
  1530. {
  1531. throw CX_MemoryException();
  1532. }
  1533. pVar->SetDispatch(pDisp);
  1534. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1535. {
  1536. delete pVar;
  1537. throw CX_MemoryException();
  1538. }
  1539. break;
  1540. }
  1541. case VT_UNKNOWN:
  1542. {
  1543. IUnknown* pUnk = sa.GetUnknownAt(i);
  1544. CReleaseMe auto3(pUnk);
  1545. pVar = new CVar;
  1546. // Check for allocation failure
  1547. if ( NULL == pVar )
  1548. {
  1549. throw CX_MemoryException();
  1550. }
  1551. pVar->SetUnknown(pUnk);
  1552. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1553. {
  1554. delete pVar;
  1555. throw CX_MemoryException();
  1556. }
  1557. break;
  1558. }
  1559. default:
  1560. m_nStatus = unsupported;
  1561. if(pNew != pSrc)
  1562. SafeArrayDestroy(pNew);
  1563. return;
  1564. }
  1565. }
  1566. if(pNew != pSrc)
  1567. SafeArrayDestroy(pNew);
  1568. m_nStatus = no_error;
  1569. }
  1570. catch (CX_MemoryException)
  1571. {
  1572. // SafeArrayCopy, GetBSTRAt, new can all throw exceptions
  1573. m_nStatus = failed;
  1574. if(pNew != pSrc)
  1575. SafeArrayDestroy(pNew);
  1576. throw;
  1577. }
  1578. }
  1579. //***************************************************************************
  1580. //
  1581. // CVarVector::GetNewSafeArray
  1582. //
  1583. // Allocates a new SAFEARRAY equivalent to the current CVarVector.
  1584. //
  1585. // RETURN VALUE:
  1586. // A new SAFEARRAY pointer which must be deallocated with
  1587. // SafeArrayDestroy(). Returns NULL on error or unsupported types.
  1588. //
  1589. //***************************************************************************
  1590. SAFEARRAY *CVarVector::GetNewSafeArray()
  1591. {
  1592. CSafeArray *pArray = new CSafeArray(m_nType, CSafeArray::no_delete);
  1593. // Check for an allocation failure
  1594. if ( NULL == pArray )
  1595. {
  1596. throw CX_MemoryException();
  1597. }
  1598. CDeleteMe<CSafeArray> auto1(pArray);
  1599. for (int i = 0; i < m_Array.Size(); i++) {
  1600. CVar &v = *(CVar *) m_Array[i];
  1601. switch (m_nType) {
  1602. case VT_UI1:
  1603. pArray->AddByte(v.GetByte());
  1604. break;
  1605. case VT_I2:
  1606. pArray->AddShort(v.GetShort());
  1607. break;
  1608. case VT_I4:
  1609. pArray->AddLong(v.GetLong());
  1610. break;
  1611. case VT_R4:
  1612. pArray->AddFloat(v.GetFloat());
  1613. break;
  1614. case VT_R8:
  1615. pArray->AddDouble(v.GetDouble());
  1616. break;
  1617. case VT_BOOL:
  1618. pArray->AddBool(v.GetBool());
  1619. break;
  1620. case VT_BSTR:
  1621. {
  1622. BSTR s = v.GetBSTR();
  1623. CSysFreeMe auto2(s);
  1624. pArray->AddBSTR(s);
  1625. break;
  1626. }
  1627. case VT_DISPATCH:
  1628. {
  1629. IDispatch* pDisp = v.GetDispatch();
  1630. CReleaseMe auto3(pDisp);
  1631. pArray->AddDispatch(pDisp);
  1632. break;
  1633. }
  1634. case VT_UNKNOWN:
  1635. {
  1636. IUnknown* pUnk = v.GetUnknown();
  1637. CReleaseMe auto4(pUnk);
  1638. pArray->AddUnknown(pUnk);
  1639. break;
  1640. }
  1641. default:
  1642. // For unsupported types, return a NULL.
  1643. // Since we constructed the SAFEARRAY object to
  1644. // not delete the SAFEARRAY and we have encountered
  1645. // a condition where the internal SAFEARRAY of
  1646. // CSafeArray should not be returned, we have
  1647. // to switch our destruct policy.
  1648. // ================================================
  1649. pArray->SetDestructorPolicy(CSafeArray::auto_delete);
  1650. return 0;
  1651. }
  1652. }
  1653. // Final cleanup. Get the SAFEARRAY pointer, and delete
  1654. // the wrapper.
  1655. // =====================================================
  1656. pArray->Trim();
  1657. SAFEARRAY *pRetValue = pArray->GetArray();
  1658. return pRetValue;
  1659. }
  1660. //***************************************************************************
  1661. //
  1662. // CVarVector::~CVarVector
  1663. //
  1664. // Destructor.
  1665. //
  1666. //***************************************************************************
  1667. CVarVector::~CVarVector()
  1668. {
  1669. Empty();
  1670. }
  1671. //***************************************************************************
  1672. //
  1673. // CVarVector::Empty
  1674. //
  1675. //***************************************************************************
  1676. void CVarVector::Empty()
  1677. {
  1678. for (int i = 0; i < m_Array.Size(); i++) {
  1679. delete (CVar *) m_Array[i];
  1680. }
  1681. m_Array.Empty();
  1682. m_nType = VT_EMPTY;
  1683. m_nStatus = no_error;
  1684. }
  1685. //***************************************************************************
  1686. //
  1687. // CVarVector::CVarVector
  1688. //
  1689. // Copy constructor. This is implemented via the assignment operator.
  1690. //
  1691. //***************************************************************************
  1692. CVarVector::CVarVector(CVarVector &Src)
  1693. {
  1694. m_nType = 0;
  1695. m_nStatus = no_error;
  1696. *this = Src;
  1697. }
  1698. //***************************************************************************
  1699. //
  1700. // CVarVector::operator =
  1701. //
  1702. // Assignment operator.
  1703. //
  1704. //***************************************************************************
  1705. CVarVector& CVarVector::operator =(CVarVector &Src)
  1706. {
  1707. Empty();
  1708. for (int i = 0; i < Src.m_Array.Size(); i++)
  1709. {
  1710. CVar* pVar = new CVar(*(CVar *) Src.m_Array[i]);
  1711. // Check for an allocation failure
  1712. if ( NULL == pVar )
  1713. {
  1714. throw CX_MemoryException();
  1715. }
  1716. if ( m_Array.Add( pVar ) != CFlexArray::no_error )
  1717. {
  1718. delete pVar;
  1719. throw CX_MemoryException();
  1720. }
  1721. }
  1722. m_nStatus = Src.m_nStatus;
  1723. m_nType = Src.m_nType;
  1724. return *this;
  1725. }
  1726. //***************************************************************************
  1727. //
  1728. // CVarVector::operator ==
  1729. //
  1730. // Equality test operator.
  1731. //
  1732. //***************************************************************************
  1733. int CVarVector::operator ==(CVarVector &Src)
  1734. {
  1735. return CompareTo(Src, TRUE);
  1736. }
  1737. BOOL CVarVector::CompareTo(CVarVector& Src, BOOL bIgnoreCase)
  1738. {
  1739. if (m_nType != Src.m_nType)
  1740. return 0;
  1741. if (m_Array.Size() != Src.m_Array.Size())
  1742. return 0;
  1743. for (int i = 0; i < Src.m_Array.Size(); i++) {
  1744. CVar *pThisVar = (CVar *) m_Array[i];
  1745. CVar *pThatVar = (CVar *) Src.m_Array[i];
  1746. if (!pThisVar->CompareTo(*pThatVar, bIgnoreCase))
  1747. return 0;
  1748. }
  1749. return 1;
  1750. }
  1751. //***************************************************************************
  1752. //
  1753. // CVarVector::Add
  1754. //
  1755. // Adds a new CVar to the array. A reference is used so that anonymous
  1756. // objects can be constructed in the Add() call:
  1757. //
  1758. // pVec->Add(CVar(33));
  1759. //
  1760. // PARAMETERS:
  1761. // Value
  1762. // A reference to a CVar object of the correct type for the array.
  1763. // No type checking is done.
  1764. //
  1765. // RETURN VALUE:
  1766. // no_error
  1767. // failed
  1768. //
  1769. //***************************************************************************
  1770. int CVarVector::Add(CVar &Value)
  1771. {
  1772. CVar *p = new CVar(Value);
  1773. // Check for allocation failures
  1774. if ( NULL == p )
  1775. {
  1776. return failed;
  1777. }
  1778. if (m_Array.Add(p) != CFlexArray::no_error)
  1779. {
  1780. delete p;
  1781. return failed;
  1782. }
  1783. return no_error;
  1784. }
  1785. //***************************************************************************
  1786. //
  1787. // CVarVector::Add
  1788. //
  1789. // Adds a new CVar to the array. This overload simply takes ownership
  1790. // of the incoming pointer and adds it directly.
  1791. //
  1792. // PARAMETERS:
  1793. // pAcquiredPtr
  1794. // A pointer to a CVar object which is acquired by the vector.
  1795. //
  1796. // RETURN VALUE:
  1797. // no_error
  1798. // failed
  1799. //
  1800. //***************************************************************************
  1801. int CVarVector::Add(CVar *pAcquiredPtr)
  1802. {
  1803. if (m_Array.Add(pAcquiredPtr) != CFlexArray::no_error)
  1804. {
  1805. return failed;
  1806. }
  1807. return no_error;
  1808. }
  1809. //***************************************************************************
  1810. //
  1811. // CVarVector::RemoveAt
  1812. //
  1813. // Removes the array element at the specified index.
  1814. //
  1815. // PARAMETERS:
  1816. // nIndex
  1817. // The location at which to remove the element.
  1818. //
  1819. // RETURN VALUE:
  1820. // no_error
  1821. // On success.
  1822. // failed
  1823. // On range errors, etc.
  1824. //
  1825. //***************************************************************************
  1826. int CVarVector::RemoveAt(int nIndex)
  1827. {
  1828. CVar *p = (CVar *) m_Array[nIndex];
  1829. delete p;
  1830. if (m_Array.RemoveAt(nIndex) != CFlexArray::no_error)
  1831. return failed;
  1832. return no_error;
  1833. }
  1834. //***************************************************************************
  1835. //
  1836. // CVarVector::InsertAt
  1837. //
  1838. // Inserts the new element at the specified location.
  1839. //
  1840. // PARAMETERS:
  1841. // nIndex
  1842. // The location at which to add the new element.
  1843. // Value
  1844. // A reference to the new value.
  1845. //
  1846. // RETURN VALUE:
  1847. // no_error
  1848. // On success.
  1849. // failed
  1850. // An invalid nIndex value was specified.
  1851. //
  1852. //***************************************************************************
  1853. int CVarVector::InsertAt(int nIndex, CVar &Value)
  1854. {
  1855. CVar *pNew = new CVar(Value);
  1856. // Check for allocation failures
  1857. if ( NULL == pNew )
  1858. {
  1859. return failed;
  1860. }
  1861. if (m_Array.InsertAt(nIndex, pNew) != CFlexArray::no_error)
  1862. {
  1863. delete pNew;
  1864. return failed;
  1865. }
  1866. return no_error;
  1867. }
  1868. BSTR CVarVector::GetText(long lFlags, long lType/* = 0 */)
  1869. {
  1870. // Construct an array of values
  1871. // ============================
  1872. BSTR* aTexts = NULL;
  1873. int i;
  1874. try
  1875. {
  1876. aTexts = new BSTR[Size()];
  1877. // Check for allocation failures
  1878. if ( NULL == aTexts )
  1879. {
  1880. throw CX_MemoryException();
  1881. }
  1882. memset(aTexts, 0, Size() * sizeof(BSTR));
  1883. int nTotal = 0;
  1884. for(i = 0; i < Size(); i++)
  1885. {
  1886. aTexts[i] = GetAt(i).GetText(lFlags, lType);
  1887. nTotal += SysStringLen(aTexts[i]) + 2; // 2: for ", "
  1888. }
  1889. // Allocate a BSTR to contain them all
  1890. // ===================================
  1891. BSTR strRes = SysAllocStringLen(NULL, nTotal);
  1892. CSysFreeMe auto2(strRes);
  1893. *strRes = 0;
  1894. for(i = 0; i < Size(); i++)
  1895. {
  1896. if(i != 0)
  1897. {
  1898. wcscat(strRes, L", ");
  1899. }
  1900. wcscat(strRes, aTexts[i]);
  1901. SysFreeString(aTexts[i]);
  1902. }
  1903. delete [] aTexts;
  1904. aTexts = NULL;
  1905. BSTR strPerfectRes = SysAllocString(strRes);
  1906. return strPerfectRes;
  1907. }
  1908. catch(CX_MemoryException)
  1909. {
  1910. // new, GetText, SysAllocStringLen and SysAllocString can all throw exceptions
  1911. if (NULL != aTexts)
  1912. {
  1913. for(int x = 0; x < Size(); x++)
  1914. {
  1915. if (NULL != aTexts[x])
  1916. SysFreeString(aTexts[x]);
  1917. }
  1918. delete [] aTexts;
  1919. aTexts = NULL;
  1920. }
  1921. throw;
  1922. }
  1923. }
  1924. BOOL CVarVector::ToSingleChar()
  1925. {
  1926. for(int i = 0; i < Size(); i++)
  1927. {
  1928. if(!GetAt(i).ToSingleChar())
  1929. return FALSE;
  1930. }
  1931. // Since all of the conversions succeeded, we will
  1932. // assume the vector type is now VT_I2.
  1933. m_nType = VT_I2;
  1934. return TRUE;
  1935. }
  1936. BOOL CVarVector::ToUI4()
  1937. {
  1938. for(int i = 0; i < Size(); i++)
  1939. {
  1940. if(!GetAt(i).ToUI4())
  1941. return FALSE;
  1942. }
  1943. return TRUE;
  1944. }