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.

986 lines
26 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. SAFEARRY.CPP
  5. Abstract:
  6. CSafeArray implementation.
  7. Notes:
  8. (1) Support only for arrays with origin at 0 or 1.
  9. Can VB deal with a SAFEARRAY of origin zero?
  10. (2) Support only for the following OA types:
  11. VT_BSTR, VT_VARIANT,
  12. VT_UI1, VT_I2, VT_I4, VT_R8
  13. History:
  14. 08-Apr-96 a-raymcc Created.
  15. 18-Mar-99 a-dcrews Added out-of-memory exception handling
  16. --*/
  17. #include "precomp.h"
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <WT_safearry.h>
  22. #include <WT_arrtempl.h>
  23. typedef struct
  24. {
  25. DWORD m_nMaxElementUsed;
  26. DWORD m_nFlags;
  27. DWORD m_nGrowBy;
  28. DWORD m_nStatus;
  29. DWORD m_nVarType;
  30. SAFEARRAYBOUND m_bound;
  31. } PersistHeaderBlock;
  32. //***************************************************************************
  33. //
  34. // CSafeArray::CheckType
  35. //
  36. // Verifies that the constructor is being invoked with a supported type.
  37. //
  38. // PARAMETERS:
  39. // nTest
  40. // One of the supported OLE VT_ constants.
  41. //
  42. //***************************************************************************
  43. void CSafeArray::CheckType(int nTest)
  44. {
  45. if (nTest != VT_BSTR &&
  46. nTest != VT_VARIANT &&
  47. nTest != VT_UI1 &&
  48. nTest != VT_I2 &&
  49. nTest != VT_I4 &&
  50. nTest != VT_R4 &&
  51. nTest != VT_R8 &&
  52. nTest != VT_BOOL &&
  53. nTest != VT_DISPATCH &&
  54. nTest != VT_UNKNOWN
  55. )
  56. Fatal("Caller attempted to use unsupported OLE Automation Type (VT_*)");
  57. }
  58. //***************************************************************************
  59. //
  60. // CSafeArray::CSafeArray
  61. //
  62. // Constructor which creates a new SAFEARRAY.
  63. //
  64. // PARAMETERS:
  65. // vt
  66. // An OLE VT_ type indicator, indicating the element type.
  67. // nFlags
  68. // The destruct policy, either <no_delete> or <auto_delete>. With
  69. // <no_delete>, the underlying SAFEARRAY is not deallocated, whereas
  70. // with <auto_delete> the destructor destroys the SAFEARRAY.
  71. // nSize
  72. // The initial size of the SAFEARRAY.
  73. // nGrowBy
  74. // The amount the SAFEARRAY should grow by when the user attempts to
  75. // add elements to a full array.
  76. //
  77. //***************************************************************************
  78. CSafeArray::CSafeArray(
  79. IN int vt,
  80. IN int nFlags,
  81. IN int nSize,
  82. IN int nGrowBy
  83. )
  84. {
  85. CheckType(vt);
  86. m_nMaxElementUsed = -1;
  87. m_nFlags = nFlags;
  88. m_nGrowBy = nGrowBy;
  89. m_nVarType = vt;
  90. // Allocate the array.
  91. // ===================
  92. m_bound.cElements = nSize;
  93. m_bound.lLbound = 0;
  94. m_pArray = SafeArrayCreate(vt, 1, &m_bound);
  95. if (m_pArray == 0)
  96. m_nStatus = failed;
  97. else
  98. m_nStatus = no_error;
  99. }
  100. //***************************************************************************
  101. //
  102. // CSafeArray::CSafeArray
  103. //
  104. // Constructor based on an existing SAFEARRAY.
  105. //
  106. // PARAMETERS:
  107. // pSrc
  108. // A pointer to an existing SAFEARRAY which is used as a source
  109. // during object construction.
  110. // nType
  111. // One of the OLE VT_ type indicators.
  112. // nFlags
  113. // OR'ed Bit flags indicating the bind vs. copy, and the
  114. // object destruct policy.
  115. //
  116. // The destruct policy is either <no_delete> or <auto_delete>. With
  117. // <no_delete>, the underlying SAFEARRAY is not deallocated, whereas
  118. // with <auto_delete> the destructor destroys the SAFEARRAY.
  119. //
  120. // Binding is indicated by <bind>, in which case the SAFEARRAY
  121. // pointed to by <pSrc> becomes the internal SAFEARRAY of the
  122. // object. Otherwise, this constructor makes a new copy of the
  123. // SAFEARRAY for internal use.
  124. // nGrowBy
  125. // How much to grow the array by when it fills and the user attempts
  126. // to add more elements. This allows the array to grow in chunks
  127. // so that continuous Add() operations do not operate slowly on
  128. // large arrays.
  129. //
  130. //***************************************************************************
  131. CSafeArray::CSafeArray(
  132. IN SAFEARRAY *pSrcCopy,
  133. IN int nType,
  134. IN int nFlags,
  135. IN int nGrowBy
  136. )
  137. {
  138. m_nStatus = no_error;
  139. CheckType(nType);
  140. // Verify that this is only a 1-dimensional array.
  141. // ===============================================
  142. if (1 != SafeArrayGetDim(pSrcCopy))
  143. m_nStatus = failed;
  144. // Now copy the source or 'bind' the incoming array.
  145. // ====================================================
  146. if (nFlags & bind)
  147. m_pArray = pSrcCopy;
  148. else if (SafeArrayCopy(pSrcCopy, &m_pArray) != S_OK)
  149. m_nStatus = failed;
  150. // Get bound information.
  151. // ======================
  152. LONG uBound = 0;
  153. if (S_OK != SafeArrayGetUBound(m_pArray, 1, &uBound))
  154. m_nStatus = failed;
  155. // Correct the Upper Bound into a size.
  156. // ====================================
  157. m_bound.cElements = uBound + 1;
  158. m_bound.lLbound = 0;
  159. m_nMaxElementUsed = uBound;
  160. m_nVarType = nType;
  161. m_nGrowBy = nGrowBy;
  162. m_nFlags = nFlags & 3; // Mask out the acquire & copy bits.
  163. }
  164. //***************************************************************************
  165. //
  166. // CSafeArray::GetScalarAt
  167. //
  168. // For class internal use. This function returns the element at
  169. // the specified index.
  170. //
  171. // PARAMETERS:
  172. // nIndex
  173. // The index at which to retrieve the scalar.
  174. //
  175. // RETURN VALUE:
  176. // The scalar at the specified the location.
  177. //
  178. //***************************************************************************
  179. SA_ArrayScalar CSafeArray::GetScalarAt(IN int nIndex)
  180. {
  181. SA_ArrayScalar retval = {0};
  182. // Check for out-of-range condition.
  183. // =================================
  184. if (nIndex > m_nMaxElementUsed + 1)
  185. return retval;
  186. SafeArrayGetElement(m_pArray, (long *) &nIndex, &retval);
  187. return retval;
  188. }
  189. //***************************************************************************
  190. //
  191. // CSafeArray assignment operator.
  192. //
  193. //***************************************************************************
  194. CSafeArray& CSafeArray::operator =(IN CSafeArray &Src)
  195. {
  196. Empty();
  197. m_nMaxElementUsed = Src.m_nMaxElementUsed;
  198. m_nFlags = Src.m_nFlags;
  199. m_nGrowBy = Src.m_nGrowBy;
  200. m_nStatus = Src.m_nStatus;
  201. m_nVarType = Src.m_nVarType;
  202. m_bound = Src.m_bound;
  203. if (SafeArrayCopy(Src.m_pArray, &m_pArray) != S_OK)
  204. m_nStatus = failed;
  205. return *this;
  206. }
  207. //***************************************************************************
  208. //
  209. // Copy constructor.
  210. //
  211. // This is implemented primarily via the assignment operator.
  212. //
  213. //***************************************************************************
  214. CSafeArray::CSafeArray(CSafeArray &Src)
  215. {
  216. m_nMaxElementUsed = 0;
  217. m_nFlags = 0;
  218. m_nGrowBy = 0;
  219. m_nStatus = no_error;
  220. m_nVarType = VT_NULL;
  221. m_pArray = 0;
  222. m_bound.cElements = 0;
  223. m_bound.lLbound = 0;
  224. *this = Src;
  225. }
  226. //***************************************************************************
  227. //
  228. // CSafeArray::Add
  229. //
  230. // Adds the BSTR to the array, growing the array if required.
  231. //
  232. // PARAMETERS:
  233. // Src
  234. // The source BSTR to add to the array. If NULL, then a
  235. // blank string is added by the underlying SAFEARRAY implementation.
  236. // (there is no way to prevent this). This can point to
  237. // an LPWSTR as well.
  238. //
  239. // RETURN VALUE:
  240. // <no_error> or <failed>.
  241. //
  242. //***************************************************************************
  243. int CSafeArray::AddBSTR(IN BSTR Src)
  244. {
  245. // If there is no more room in the array, then expand it.
  246. // ======================================================
  247. if (m_nMaxElementUsed == (int) m_bound.cElements - 1) {
  248. if (m_nGrowBy == 0)
  249. return range_error;
  250. m_bound.cElements += m_nGrowBy;
  251. if (S_OK != SafeArrayRedim(m_pArray, &m_bound))
  252. m_nStatus = failed;
  253. }
  254. m_nMaxElementUsed++;
  255. BSTR Copy = SysAllocString(Src);
  256. CSysFreeMe auto1(Copy);
  257. if (SafeArrayPutElement(m_pArray, (long *) &m_nMaxElementUsed, Copy) != S_OK) {
  258. m_nStatus = failed;
  259. return failed;
  260. }
  261. return no_error;
  262. }
  263. //***************************************************************************
  264. //
  265. // CSafeArray::AddVariant
  266. //
  267. // Adds the specified VARIANT to the array.
  268. //
  269. // PARAMETERS:
  270. // pSrc
  271. // A pointer to the source VARIANT, which is copied.
  272. //
  273. // RETURN VALUE:
  274. // range_error, failed, no_error
  275. //
  276. //***************************************************************************
  277. int CSafeArray::AddVariant(IN VARIANT *pSrc)
  278. {
  279. // If there is no more room in the array, then expand it.
  280. // ======================================================
  281. if (m_nMaxElementUsed == (int) m_bound.cElements - 1) {
  282. if (m_nGrowBy == 0)
  283. return range_error;
  284. m_bound.cElements += m_nGrowBy;
  285. if (S_OK != SafeArrayRedim(m_pArray, &m_bound))
  286. m_nStatus = failed;
  287. }
  288. m_nMaxElementUsed++;
  289. if (SafeArrayPutElement(m_pArray, (long *) &m_nMaxElementUsed, pSrc) != S_OK) {
  290. m_nStatus = failed;
  291. return failed;
  292. }
  293. return no_error;
  294. }
  295. //***************************************************************************
  296. //
  297. // CSafeArray::AddDispatch
  298. //
  299. // Adds the specified IDispatch* to the array.
  300. //
  301. // PARAMETERS:
  302. // pSrc
  303. // A pointer to the source IDispatch*, which is AddRefed.
  304. //
  305. // RETURN VALUE:
  306. // range_error, failed, no_error
  307. //
  308. //***************************************************************************
  309. int CSafeArray::AddDispatch(IN IDispatch *pDisp)
  310. {
  311. // If there is no more room in the array, then expand it.
  312. // ======================================================
  313. if (m_nMaxElementUsed == (int) m_bound.cElements - 1) {
  314. if (m_nGrowBy == 0)
  315. return range_error;
  316. m_bound.cElements += m_nGrowBy;
  317. if (S_OK != SafeArrayRedim(m_pArray, &m_bound))
  318. m_nStatus = failed;
  319. }
  320. m_nMaxElementUsed++;
  321. if (SafeArrayPutElement(m_pArray, (long *) &m_nMaxElementUsed, pDisp) != S_OK) {
  322. m_nStatus = failed;
  323. return failed;
  324. }
  325. return no_error;
  326. }
  327. //***************************************************************************
  328. //
  329. // CSafeArray::AddUnknown
  330. //
  331. // Adds the specified IUnknown* to the array.
  332. //
  333. // PARAMETERS:
  334. // pSrc
  335. // A pointer to the source IUnknown*, which is AddRefed.
  336. //
  337. // RETURN VALUE:
  338. // range_error, failed, no_error
  339. //
  340. //***************************************************************************
  341. int CSafeArray::AddUnknown(IN IUnknown *pUnk)
  342. {
  343. // If there is no more room in the array, then expand it.
  344. // ======================================================
  345. if (m_nMaxElementUsed == (int) m_bound.cElements - 1) {
  346. if (m_nGrowBy == 0)
  347. return range_error;
  348. m_bound.cElements += m_nGrowBy;
  349. if (S_OK != SafeArrayRedim(m_pArray, &m_bound))
  350. m_nStatus = failed;
  351. }
  352. m_nMaxElementUsed++;
  353. if (SafeArrayPutElement(m_pArray, (long *) &m_nMaxElementUsed, pUnk) != S_OK) {
  354. m_nStatus = failed;
  355. return failed;
  356. }
  357. return no_error;
  358. }
  359. //***************************************************************************
  360. //
  361. // CSafeArray::GetBSTRAt
  362. //
  363. // If the array type is VT_BSTR, this returns the string at the specified
  364. // index.
  365. //
  366. // PARAMETERS:
  367. // nIndex
  368. // The array index for which the string is requried.
  369. //
  370. // RETURN VALUE:
  371. // A dynamically allocated BSTR which must be freed with SysFreeString.
  372. // NULL is returned on error. If NULL was originally added at this
  373. // location, a string with zero length will be returned, which still
  374. // must be freed with SysFreeString.
  375. //
  376. //***************************************************************************
  377. BSTR CSafeArray::GetBSTRAt(int nIndex)
  378. {
  379. BSTR StrPtr = 0;
  380. if (nIndex >= (int) m_bound.cElements)
  381. return NULL;
  382. if (S_OK != SafeArrayGetElement(m_pArray, (long *) &nIndex, &StrPtr))
  383. return NULL;
  384. return StrPtr;
  385. }
  386. //***************************************************************************
  387. //
  388. // CSafeArray::GetVariantAt
  389. //
  390. // PARAMETERS:
  391. // nIndex
  392. // The array index from which to retrieve the VARIANT.
  393. //
  394. // RETURN VALUE:
  395. // Returns a new VARIANT at the specified location. The receiver must
  396. // call VariantClear() on this VARIANT when it is no longer used.
  397. //
  398. //***************************************************************************
  399. VARIANT CSafeArray::GetVariantAt(int nIndex)
  400. {
  401. VARIANT Var;
  402. VariantInit(&Var);
  403. if (nIndex >= (int) m_bound.cElements)
  404. return Var;
  405. if (S_OK != SafeArrayGetElement(m_pArray, (long *) &nIndex, &Var))
  406. return Var;
  407. return Var;
  408. }
  409. //***************************************************************************
  410. //
  411. // CSafeArray::GetDispatchAt
  412. //
  413. // PARAMETERS:
  414. // nIndex
  415. // The array index from which to retrieve the IDispatch*.
  416. //
  417. // RETURN VALUE:
  418. // Returns the IDispatch* at the specified location. The receiver must
  419. // call Release on this pointer (if not NULL) when it is no longer used.
  420. //
  421. //***************************************************************************
  422. IDispatch* CSafeArray::GetDispatchAt(int nIndex)
  423. {
  424. IDispatch* pDisp;
  425. if (nIndex >= (int) m_bound.cElements)
  426. return NULL;
  427. if (S_OK != SafeArrayGetElement(m_pArray, (long *) &nIndex, &pDisp))
  428. return NULL;
  429. return pDisp;
  430. }
  431. //***************************************************************************
  432. //
  433. // CSafeArray::GetUnknownAt
  434. //
  435. // PARAMETERS:
  436. // nIndex
  437. // The array index from which to retrieve the IUnknown*.
  438. //
  439. // RETURN VALUE:
  440. // Returns the IUnknown* at the specified location. The receiver must
  441. // call Release on this pointer (if not NULL) when it is no longer used.
  442. //
  443. //***************************************************************************
  444. IUnknown* CSafeArray::GetUnknownAt(int nIndex)
  445. {
  446. IUnknown* pUnk;
  447. if (nIndex >= (int) m_bound.cElements)
  448. return NULL;
  449. if (S_OK != SafeArrayGetElement(m_pArray, (long *) &nIndex, &pUnk))
  450. return NULL;
  451. return pUnk;
  452. }
  453. //***************************************************************************
  454. //
  455. // CSafeArray::SetAt
  456. //
  457. // Replaces the BSTR value at the specified array index. The original
  458. // BSTR value is automatically deallocated and replaced by the new value.
  459. // You can only call this to replace an existing element or to add a
  460. // new element to the end (one position past the last element). If the
  461. // array size is 10, you can call this with 0..10, but not 11 or higher.
  462. //
  463. // PARAMETERS:
  464. // nIndex
  465. // The position at which to replace the element.
  466. // Str
  467. // The new string.
  468. // nFlags
  469. // If <acquire> this function acquires ownership of the string and
  470. // can delete it. Otherwise, the caller retains ownership of the
  471. // string.
  472. //
  473. // RETURN VALUE:
  474. // no_error
  475. // range_error
  476. // failed
  477. //
  478. //***************************************************************************
  479. int CSafeArray::SetBSTRAt(
  480. IN int nIndex,
  481. IN BSTR Str
  482. )
  483. {
  484. // Check for out-of-range condition.
  485. // =================================
  486. if (nIndex > m_nMaxElementUsed + 1)
  487. return range_error;
  488. // Check to see if we are adding a new element.
  489. // ============================================
  490. if (nIndex == m_nMaxElementUsed + 1)
  491. return AddBSTR(Str);
  492. BSTR Copy = SysAllocString(Str);
  493. CSysFreeMe auto1(Copy);
  494. // If here, we are replacing an element.
  495. // =====================================
  496. if (SafeArrayPutElement(m_pArray, (long *) &nIndex, Copy) != S_OK) {
  497. m_nStatus = failed;
  498. return failed;
  499. }
  500. return no_error;
  501. }
  502. //***************************************************************************
  503. //
  504. // CSafeArray::SetVariantAt
  505. //
  506. // Sets the VARIANT at the specified index.
  507. //
  508. // PARAMETERS:
  509. // nIndex
  510. // The index at which to set the VARIANT. The original contents
  511. // at this location are automatically deallocated and replaced.
  512. // pVal
  513. // Used as the source of the new value. This is treated as read-only.
  514. //
  515. // RETURN VALUE:
  516. // no_error, failed, range_error
  517. //
  518. //***************************************************************************
  519. int CSafeArray::SetVariantAt(
  520. IN int nIndex,
  521. IN VARIANT *pVal
  522. )
  523. {
  524. // Check for out-of-range condition.
  525. // =================================
  526. if (nIndex > m_nMaxElementUsed + 1)
  527. return range_error;
  528. // Check to see if we are adding a new element.
  529. // ============================================
  530. if (nIndex == m_nMaxElementUsed + 1)
  531. return AddVariant(pVal);
  532. // If here, we are replacing an element.
  533. // =====================================
  534. if (SafeArrayPutElement(m_pArray, (long *) &nIndex, pVal) != S_OK) {
  535. m_nStatus = failed;
  536. return failed;
  537. }
  538. return no_error;
  539. }
  540. //***************************************************************************
  541. //
  542. // CSafeArray::SetDispatchAt
  543. //
  544. // Sets the IDispatch* at the specified index.
  545. //
  546. // PARAMETERS:
  547. // nIndex
  548. // The index at which to set the IDispatch*. The original contents
  549. // at this location are automatically Released and replaced.
  550. // pVal
  551. // Used as the source of the new value. This is treated as read-only.
  552. //
  553. // RETURN VALUE:
  554. // no_error, failed, range_error
  555. //
  556. //***************************************************************************
  557. int CSafeArray::SetDispatchAt(
  558. IN int nIndex,
  559. IN IDispatch *pDisp
  560. )
  561. {
  562. // Check for out-of-range condition.
  563. // =================================
  564. if (nIndex > m_nMaxElementUsed + 1)
  565. return range_error;
  566. // Check to see if we are adding a new element.
  567. // ============================================
  568. if (nIndex == m_nMaxElementUsed + 1)
  569. return AddDispatch(pDisp);
  570. // If here, we are replacing an element.
  571. // =====================================
  572. if (SafeArrayPutElement(m_pArray, (long *) &nIndex, pDisp) != S_OK) {
  573. m_nStatus = failed;
  574. return failed;
  575. }
  576. return no_error;
  577. }
  578. //***************************************************************************
  579. //
  580. // CSafeArray::SetUnknownAt
  581. //
  582. // Sets the IUnknown* at the specified index.
  583. //
  584. // PARAMETERS:
  585. // nIndex
  586. // The index at which to set the IUnknown*. The original contents
  587. // at this location are automatically Released and replaced.
  588. // pVal
  589. // Used as the source of the new value. This is treated as read-only.
  590. //
  591. // RETURN VALUE:
  592. // no_error, failed, range_error
  593. //
  594. //***************************************************************************
  595. int CSafeArray::SetUnknownAt(
  596. IN int nIndex,
  597. IN IUnknown *pUnk
  598. )
  599. {
  600. // Check for out-of-range condition.
  601. // =================================
  602. if (nIndex > m_nMaxElementUsed + 1)
  603. return range_error;
  604. // Check to see if we are adding a new element.
  605. // ============================================
  606. if (nIndex == m_nMaxElementUsed + 1)
  607. return AddUnknown(pUnk);
  608. // If here, we are replacing an element.
  609. // =====================================
  610. if (SafeArrayPutElement(m_pArray, (long *) &nIndex, pUnk) != S_OK) {
  611. m_nStatus = failed;
  612. return failed;
  613. }
  614. return no_error;
  615. }
  616. //***************************************************************************
  617. //
  618. // CSafeArray::RemoveAt
  619. //
  620. // Removes the element at the specified index. After a series of these
  621. // operations, the caller should call the Trim() function.
  622. //
  623. // PARAMETERS:
  624. // nIndex
  625. // The target index for element removal.
  626. //
  627. // RETURN VALUE:
  628. // no_error, range_error
  629. //
  630. //***************************************************************************
  631. int CSafeArray::RemoveAt(IN int nIndex)
  632. {
  633. // Check for out-of-range condition.
  634. // =================================
  635. if (nIndex > m_nMaxElementUsed + 1)
  636. return range_error;
  637. // Copy element n+1 into n.
  638. // ========================
  639. BSTR strVal;
  640. VARIANT v;
  641. SA_ArrayScalar scalar;
  642. IDispatch* pDisp;
  643. IUnknown* pUnk;
  644. for (long i = nIndex; i < m_nMaxElementUsed; i++) {
  645. long nNext = i + 1;
  646. if (m_nVarType == VT_BSTR) {
  647. SafeArrayGetElement(m_pArray, &nNext, &strVal);
  648. SafeArrayPutElement(m_pArray, &i, strVal);
  649. SysFreeString(strVal);
  650. }
  651. else if (m_nVarType == VT_VARIANT) {
  652. SafeArrayGetElement(m_pArray, &nNext, &v);
  653. SafeArrayPutElement(m_pArray, &i, &v);
  654. VariantClear(&v);
  655. }
  656. else if (m_nVarType == VT_DISPATCH) {
  657. SafeArrayGetElement(m_pArray, &nNext, &pDisp);
  658. SafeArrayPutElement(m_pArray, &i, pDisp);
  659. if(pDisp) pDisp->Release();
  660. }
  661. else if (m_nVarType == VT_UNKNOWN) {
  662. SafeArrayGetElement(m_pArray, &nNext, &pUnk);
  663. SafeArrayPutElement(m_pArray, &i, pUnk);
  664. if(pUnk) pUnk->Release();
  665. }
  666. else {
  667. SafeArrayGetElement(m_pArray, &nNext, &scalar);
  668. SafeArrayPutElement(m_pArray, &i, &scalar);
  669. }
  670. }
  671. m_nMaxElementUsed--;
  672. return no_error;
  673. }
  674. //***************************************************************************
  675. //
  676. // CSafeArray::SetScalarAt
  677. //
  678. // For class internal use. Sets the scalar type at the specified index.
  679. //
  680. // PARAMETERS:
  681. // nIndex
  682. // The target index.
  683. // val
  684. // The new value.
  685. //
  686. // RETURN VALUES:
  687. // range_error, failed, no_error
  688. //
  689. //***************************************************************************
  690. int CSafeArray::SetScalarAt(IN int nIndex, IN SA_ArrayScalar val)
  691. {
  692. // Check for out-of-range condition.
  693. // =================================
  694. if (nIndex > m_nMaxElementUsed + 1)
  695. return range_error;
  696. // Check to see if we are adding a new element.
  697. // ============================================
  698. if (nIndex == m_nMaxElementUsed + 1)
  699. return AddScalar(val);
  700. // If here, we are replacing an element.
  701. // =====================================
  702. if (SafeArrayPutElement(m_pArray, (long *) &nIndex, &val) != S_OK) {
  703. m_nStatus = failed;
  704. return failed;
  705. }
  706. return no_error;
  707. }
  708. //***************************************************************************
  709. //
  710. // CSafeArray::AddScalar
  711. //
  712. // For class internal use only.
  713. //
  714. // Adds a new scalar to the 'end' of the array, growing it if required
  715. // and if possible.
  716. //
  717. // PARAMETERS:
  718. // val
  719. // The new value.
  720. //
  721. // RETURN VALUE:
  722. // no_error, range_error, failed
  723. //
  724. //***************************************************************************
  725. int CSafeArray::AddScalar(IN SA_ArrayScalar val)
  726. {
  727. // If there is no more room in the array, then expand it.
  728. // ======================================================
  729. if (m_nMaxElementUsed == (int) m_bound.cElements - 1) {
  730. if (m_nGrowBy == 0)
  731. return range_error;
  732. m_bound.cElements += m_nGrowBy;
  733. if (S_OK != SafeArrayRedim(m_pArray, &m_bound))
  734. m_nStatus = failed;
  735. }
  736. m_nMaxElementUsed++;
  737. if (SafeArrayPutElement(m_pArray, (long *) &m_nMaxElementUsed, &val) != S_OK) {
  738. m_nStatus = failed;
  739. return failed;
  740. }
  741. return no_error;
  742. }
  743. //***************************************************************************
  744. //
  745. // CSafeArray::Empty
  746. //
  747. // Empties the SAFEARRAY.
  748. //
  749. //***************************************************************************
  750. void CSafeArray::Empty()
  751. {
  752. m_nMaxElementUsed = 0;
  753. m_nFlags = 0;
  754. m_nGrowBy = 0;
  755. m_nStatus = no_error;
  756. m_nVarType = VT_NULL;
  757. if (m_pArray)
  758. SafeArrayDestroy(m_pArray);
  759. m_pArray = 0;
  760. m_bound.cElements = 0;
  761. m_bound.lLbound = 0;
  762. }
  763. //***************************************************************************
  764. //
  765. // CSafeArray::GetArrayCopy
  766. //
  767. // RETURN VALUE:
  768. // A copy of the internal SAFEARRAY or NULL on error.
  769. //
  770. //***************************************************************************
  771. SAFEARRAY *CSafeArray::GetArrayCopy()
  772. {
  773. SAFEARRAY *pCopy = 0;
  774. if (SafeArrayCopy(m_pArray, &pCopy) != S_OK)
  775. return 0;
  776. return pCopy;
  777. }
  778. //***************************************************************************
  779. //
  780. // CSafeArray destructor.
  781. //
  782. // If the internal flags are set to auto_delete, then the internal
  783. // SAFEARRAY is destroyed during destruction.
  784. //
  785. //***************************************************************************
  786. CSafeArray::~CSafeArray()
  787. {
  788. if (m_nFlags == auto_delete)
  789. SafeArrayDestroy(m_pArray);
  790. }
  791. //***************************************************************************
  792. //
  793. // CSafeArray::Trim
  794. //
  795. //***************************************************************************
  796. int CSafeArray::Trim()
  797. {
  798. m_bound.cElements = m_nMaxElementUsed + 1;
  799. // HACK for NT 3.51: may not redimention to size 0
  800. // ===============================================
  801. if(m_bound.cElements == 0)
  802. {
  803. SafeArrayDestroy(m_pArray);
  804. m_pArray = SafeArrayCreate(m_nVarType, 1, &m_bound);
  805. }
  806. else
  807. {
  808. SafeArrayRedim(m_pArray, &m_bound);
  809. }
  810. return no_error;
  811. }
  812. //***************************************************************************
  813. //
  814. //***************************************************************************
  815. void CSafeArray::Fatal(const char *pszMsg)
  816. {
  817. // MessageBox(0, pszMsg, "CSafeArray FATAL Error",
  818. // MB_OK | MB_SYSTEMMODAL | MB_ICONEXCLAMATION);
  819. }