Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

641 lines
15 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // File: cenum.cxx
  4. //
  5. // Contents: Generic enumerator class.
  6. //
  7. // Classes: CBaseEnum
  8. // CEnumGeneric
  9. // CEnumVARIANT
  10. //
  11. // History: 05-05-93 ChrisZ Added class object caching
  12. // 05-11-93 ChrisZ Cleanup on CF caching
  13. // 02-24-93 LyleC Moved from ADs directory
  14. // 01-Sep-93 DonCl new (NullOnFail)
  15. // 08-Sep-93 LyleC Changed Next() to accept NULL 3rd param
  16. // 15-May-94 adams Added CBaseEnum, CEnumVARIANT
  17. //
  18. //-------------------------------------------------------------------------
  19. #include "procs.hxx"
  20. #pragma hdrstop
  21. // Determines whether a variant is a base type.
  22. #define ISBASEVARTYPE(vt) ((vt & ~VT_TYPEMASK) == 0)
  23. //+------------------------------------------------------------------------
  24. //
  25. // CBaseEnum Implementation
  26. //
  27. //-------------------------------------------------------------------------
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Member: CBaseEnum::Init
  31. //
  32. // Synopsis: 2nd stage initialization perADs copy of array if necessary.
  33. //
  34. // Arguments: [pary] -- Array to enumrate.
  35. // [fCopy] -- Copy array?
  36. //
  37. // Returns: HRESULT.
  38. //
  39. // Modifies: [this].
  40. //
  41. // History: 5-15-94 adams Created
  42. //
  43. //----------------------------------------------------------------------------
  44. HRESULT
  45. CBaseEnum::Init(CADsAry * pary, BOOL fCopy)
  46. {
  47. HRESULT hr = S_OK;
  48. CADsAry * paryCopy = NULL; // copied array
  49. ADsAssert(pary);
  50. // Copy array if necessary.
  51. if (fCopy)
  52. {
  53. paryCopy = new CADsAry;
  54. if (!paryCopy)
  55. {
  56. hr = E_OUTOFMEMORY;
  57. goto Cleanup;
  58. }
  59. hr = paryCopy->Copy(_cb, *pary, _fAddRef);
  60. if (hr)
  61. goto Error;
  62. pary = paryCopy;
  63. }
  64. _pary = pary;
  65. Cleanup:
  66. RRETURN(hr);
  67. Error:
  68. delete paryCopy;
  69. goto Cleanup;
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Member: CBaseEnum::CBaseEnum
  74. //
  75. // Synopsis: Constructor.
  76. //
  77. // Arguments: [iid] -- IID of enumerator interface.
  78. // [fAddRef] -- addref enumerated elements?
  79. // [fDelete] -- delete array on zero enumerators?
  80. //
  81. // Modifies: [this]
  82. //
  83. // History: 5-15-94 adams Created
  84. //
  85. //----------------------------------------------------------------------------
  86. CBaseEnum::CBaseEnum(size_t cb, REFIID iid, BOOL fAddRef, BOOL fDelete)
  87. {
  88. _ulRefs = 1;
  89. _cb = cb;
  90. _pary = NULL;
  91. _piid = &iid;
  92. _i = 0;
  93. _fAddRef = fAddRef;
  94. _fDelete = fDelete;
  95. INC_OBJECT_COUNT();
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Member: CBaseEnum::CBaseEnum
  100. //
  101. // Synopsis: Constructor.
  102. //
  103. // History: 5-15-94 adams Created
  104. //
  105. //----------------------------------------------------------------------------
  106. CBaseEnum::CBaseEnum(const CBaseEnum& benum)
  107. {
  108. _ulRefs = 1;
  109. _cb = benum._cb;
  110. _piid = benum._piid;
  111. _pary = benum._pary;
  112. _i = benum._i;
  113. _fAddRef = benum._fAddRef;
  114. _fDelete = benum._fDelete;
  115. INC_OBJECT_COUNT();
  116. }
  117. //+---------------------------------------------------------------------------
  118. //
  119. // Member: CBaseEnum::~CBaseEnum
  120. //
  121. // Synopsis: Destructor.
  122. //
  123. // History: 5-15-94 adams Created
  124. //
  125. //----------------------------------------------------------------------------
  126. CBaseEnum::~CBaseEnum(void)
  127. {
  128. IUnknown ** ppUnk;
  129. int i;
  130. if (_pary && _fDelete)
  131. {
  132. if (_fAddRef)
  133. {
  134. for (i = 0, ppUnk = (IUnknown **) Deref(0);
  135. i < _pary->Size();
  136. i++, ppUnk++)
  137. {
  138. (*ppUnk)->Release();
  139. }
  140. }
  141. delete _pary;
  142. }
  143. DEC_OBJECT_COUNT();
  144. }
  145. //+---------------------------------------------------------------------------
  146. //
  147. // Member: CBaseEnum::QueryInterface
  148. //
  149. // Synopsis: Per IUnknown::QueryInterface.
  150. //
  151. // History: 5-15-94 adams Created
  152. //
  153. //----------------------------------------------------------------------------
  154. STDMETHODIMP
  155. CBaseEnum::QueryInterface(REFIID iid, LPVOID * ppv)
  156. {
  157. if (!ppv)
  158. RRETURN(E_INVALIDARG);
  159. if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, *_piid))
  160. {
  161. AddRef();
  162. *ppv = this;
  163. return NOERROR;
  164. }
  165. return E_NOTIMPL;
  166. }
  167. //+---------------------------------------------------------------------------
  168. //
  169. // Member: CBaseEnum::Skip
  170. //
  171. // Synopsis: Per IEnum*
  172. //
  173. // History: 5-15-94 adams Created
  174. //
  175. //----------------------------------------------------------------------------
  176. STDMETHODIMP
  177. CBaseEnum::Skip(ULONG celt)
  178. {
  179. int c = min((int) celt, _pary->Size() - _i);
  180. _i += c;
  181. return ((c == (int) celt) ? NOERROR : S_FALSE);
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // Member: CBaseEnum::Reset
  186. //
  187. // Synopsis: Per IEnum*
  188. //
  189. // History: 5-15-94 adams Created
  190. //
  191. //----------------------------------------------------------------------------
  192. STDMETHODIMP
  193. CBaseEnum::Reset(void)
  194. {
  195. _i = 0;
  196. return NOERROR;
  197. }
  198. //+------------------------------------------------------------------------
  199. //
  200. // CEnumGeneric Implementation
  201. //
  202. //-------------------------------------------------------------------------
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Member: CEnumGeneric::Create
  206. //
  207. // Synopsis: Creates a new CEnumGeneric object.
  208. //
  209. // Arguments: [pary] -- Array to enumerate.
  210. // [iid] -- IID of enumerator interface.
  211. // [fAddRef] -- AddRef enumerated elements?
  212. // [fCopy] -- Copy array enumerated?
  213. // [fDelete] -- Delete array when zero enumerators of array?
  214. // [ppenum] -- Resulting CEnumGeneric object.
  215. //
  216. // Returns: HRESULT.
  217. //
  218. // History: 5-15-94 adams Created
  219. //
  220. //----------------------------------------------------------------------------
  221. HRESULT
  222. CEnumGeneric::Create(
  223. size_t cb,
  224. CADsAry * pary,
  225. REFIID iid,
  226. BOOL fAddRef,
  227. BOOL fCopy,
  228. BOOL fDelete,
  229. CEnumGeneric ** ppenum)
  230. {
  231. HRESULT hr = S_OK;
  232. CEnumGeneric * penum;
  233. ADsAssert(pary);
  234. ADsAssert(ppenum);
  235. ADsAssert(!fCopy || fDelete);
  236. *ppenum = NULL;
  237. penum = new CEnumGeneric(cb, iid, fAddRef, fDelete);
  238. if (!penum)
  239. {
  240. hr = E_OUTOFMEMORY;
  241. goto Cleanup;
  242. }
  243. hr = penum->Init(pary, fCopy);
  244. if (hr)
  245. goto Error;
  246. *ppenum = penum;
  247. Cleanup:
  248. RRETURN(hr);
  249. Error:
  250. penum->Release();
  251. goto Cleanup;
  252. }
  253. //+---------------------------------------------------------------------------
  254. //
  255. // Function: CEnumGeneric
  256. //
  257. // Synopsis: ctor.
  258. //
  259. // Arguments: [iid] -- IID of enumerator interface.
  260. // [fAddRef] -- AddRef enumerated elements?
  261. // [fDelete] -- delete array on zero enumerators?
  262. //
  263. // Modifies: [this].
  264. //
  265. // History: 5-15-94 adams Created
  266. //
  267. //----------------------------------------------------------------------------
  268. CEnumGeneric::CEnumGeneric(size_t cb, REFIID iid, BOOL fAddRef, BOOL fDelete) :
  269. CBaseEnum(cb, iid, fAddRef, fDelete)
  270. {
  271. }
  272. //+---------------------------------------------------------------------------
  273. //
  274. // Function: CEnumGeneric
  275. //
  276. // Synopsis: ctor.
  277. //
  278. // History: 5-15-94 adams Created
  279. //
  280. //----------------------------------------------------------------------------
  281. CEnumGeneric::CEnumGeneric(const CEnumGeneric& enumg) : CBaseEnum(enumg)
  282. {
  283. }
  284. //+------------------------------------------------------------------------
  285. //
  286. // Member: CEnumGeneric::Next
  287. //
  288. // Synopsis: Returns the next celt members in the enumeration. If less
  289. // than celt members remain, then the remaining members are
  290. // returned and S_FALSE is reported. In all cases, the number
  291. // of elements actually returned in placed in *pceltFetched.
  292. //
  293. // Arguments: [celt] Number of elements to fetch
  294. // [reelt] The elements are returned in reelt[]
  295. // [pceltFetched] Number of elements actually fetched
  296. //
  297. // Returns: HRESULT (STDMETHOD)
  298. //
  299. //-------------------------------------------------------------------------
  300. STDMETHODIMP
  301. CEnumGeneric::Next(ULONG celt, void * reelt, ULONG * pceltFetched)
  302. {
  303. int c;
  304. int i;
  305. IUnknown ** ppUnk;
  306. c = min((int) celt, _pary->Size() - _i);
  307. if (c > 0 && !reelt)
  308. RRETURN(E_INVALIDARG);
  309. if (_fAddRef)
  310. {
  311. for (i = 0, ppUnk = (IUnknown **) Deref(_i); i < c; i++, ppUnk++)
  312. {
  313. (*ppUnk)->AddRef();
  314. }
  315. }
  316. memcpy(reelt, (BYTE *) Deref(_i), c * _cb);
  317. if (pceltFetched)
  318. {
  319. *pceltFetched = c;
  320. }
  321. _i += c;
  322. return ((c == (int) celt) ? NOERROR : S_FALSE);
  323. }
  324. //+------------------------------------------------------------------------
  325. //
  326. // Member: CEnumGeneric::Clone
  327. //
  328. // Synopsis: Creates a copy of this enumerator; the copy should have the
  329. // same state as this enumerator.
  330. //
  331. // Arguments: [ppenum] New enumerator is returned in *ppenum
  332. //
  333. // Returns: HRESULT (STDMETHOD)
  334. //
  335. //-------------------------------------------------------------------------
  336. STDMETHODIMP
  337. CEnumGeneric::Clone(CBaseEnum ** ppenum)
  338. {
  339. HRESULT hr;
  340. if (!ppenum)
  341. RRETURN(E_INVALIDARG);
  342. *ppenum = NULL;
  343. hr = _pary->EnumElements(_cb, *_piid, (void **) ppenum, _fAddRef);
  344. if (hr)
  345. RRETURN(hr);
  346. (**(CEnumGeneric **)ppenum)._i = _i;
  347. return S_OK;
  348. }
  349. //+------------------------------------------------------------------------
  350. //
  351. // CEnumVARIANT Implementation
  352. //
  353. //-------------------------------------------------------------------------
  354. //+---------------------------------------------------------------------------
  355. //
  356. // Member: CEnumVARIANT::Create
  357. //
  358. // Synopsis: Creates a new CEnumGeneric object.
  359. //
  360. // Arguments: [pary] -- Array to enumerate.
  361. // [vt] -- Type of elements enumerated.
  362. // [fCopy] -- Copy array enumerated?
  363. // [fDelete] -- Delete array when zero enumerators of array?
  364. // [ppenum] -- Resulting CEnumGeneric object.
  365. //
  366. // Returns: HRESULT.
  367. //
  368. // History: 5-15-94 adams Created
  369. //
  370. //----------------------------------------------------------------------------
  371. HRESULT
  372. CEnumVARIANT::Create(
  373. size_t cb,
  374. CADsAry * pary,
  375. VARTYPE vt,
  376. BOOL fCopy,
  377. BOOL fDelete,
  378. IEnumVARIANT ** ppenum)
  379. {
  380. HRESULT hr = S_OK;
  381. CEnumVARIANT * penum; // enumerator to return.
  382. ADsAssert(pary);
  383. ADsAssert(ppenum);
  384. ADsAssert(ISBASEVARTYPE(vt));
  385. *ppenum = NULL;
  386. penum = new CEnumVARIANT(cb, vt, fDelete);
  387. if (!*ppenum)
  388. {
  389. hr = E_OUTOFMEMORY;
  390. goto Cleanup;
  391. }
  392. hr = penum->Init(pary, fCopy);
  393. if (hr)
  394. goto Error;
  395. *ppenum = (IEnumVARIANT *) (void *) penum;
  396. Cleanup:
  397. RRETURN(hr);
  398. Error:
  399. penum->Release();
  400. goto Cleanup;
  401. }
  402. //+---------------------------------------------------------------------------
  403. //
  404. // Function: CEnumVARIANT
  405. //
  406. // Synopsis: ctor.
  407. //
  408. // Arguments: [vt] -- Type of elements enumerated.
  409. // [fDelete] -- delete array on zero enumerators?
  410. //
  411. // Modifies: [this]
  412. //
  413. // History: 5-15-94 adams Created
  414. //
  415. //----------------------------------------------------------------------------
  416. CEnumVARIANT::CEnumVARIANT(size_t cb, VARTYPE vt, BOOL fDelete) :
  417. CBaseEnum(cb, IID_IEnumVARIANT, vt == VT_UNKNOWN || vt == VT_DISPATCH, fDelete)
  418. {
  419. ADsAssert(ISBASEVARTYPE(vt));
  420. _vt = vt;
  421. }
  422. //+---------------------------------------------------------------------------
  423. //
  424. // Function: CEnumVARIANT
  425. //
  426. // Synopsis: ctor.
  427. //
  428. // History: 5-15-94 adams Created
  429. //
  430. //----------------------------------------------------------------------------
  431. CEnumVARIANT::CEnumVARIANT(const CEnumVARIANT& enumv) : CBaseEnum(enumv)
  432. {
  433. _vt = enumv._vt;
  434. }
  435. //+------------------------------------------------------------------------
  436. //
  437. // Member: CEnumVARIANT::Next
  438. //
  439. // Synopsis: Returns the next celt members in the enumeration. If less
  440. // than celt members remain, then the remaining members are
  441. // returned and S_FALSE is reported. In all cases, the number
  442. // of elements actually returned in placed in *pceltFetched.
  443. //
  444. // Arguments: [celt] Number of elements to fetch
  445. // [reelt] The elements are returned in reelt[]
  446. // [pceltFetched] Number of elements actually fetched
  447. //
  448. // Returns: HRESULT (STDMETHOD)
  449. //
  450. //-------------------------------------------------------------------------
  451. STDMETHODIMP
  452. CEnumVARIANT::Next(ULONG celt, void * reelt, ULONG * pceltFetched)
  453. {
  454. int c;
  455. int i;
  456. BYTE * pb;
  457. VARIANT * pvar;
  458. c = min((int) celt, _pary->Size() - _i);
  459. if (c > 0 && !reelt)
  460. RRETURN(E_INVALIDARG);
  461. for (i = 0, pb = (BYTE *) Deref(_i), pvar = (VARIANT *) reelt;
  462. i < c;
  463. i++, pb += _cb, pvar++)
  464. {
  465. V_VT(pvar) = _vt;
  466. switch (_vt)
  467. {
  468. case VT_I2:
  469. ADsAssert(sizeof(V_I2(pvar)) == _cb);
  470. V_I2(pvar) = *(short *) pb;
  471. break;
  472. case VT_I4:
  473. ADsAssert(sizeof(V_I4(pvar)) == _cb);
  474. V_I4(pvar) = *(long *) pb;
  475. break;
  476. case VT_BOOL:
  477. ADsAssert(sizeof(V_BOOL(pvar)) == _cb);
  478. V_BOOL(pvar) = (short) -*(int *) pb;
  479. break;
  480. case VT_BSTR:
  481. ADsAssert(sizeof(V_BSTR(pvar)) == _cb);
  482. V_BSTR(pvar) = *(BSTR *) pb;
  483. break;
  484. case VT_UNKNOWN:
  485. case VT_DISPATCH:
  486. ADsAssert(sizeof(V_UNKNOWN(pvar)) == _cb);
  487. V_UNKNOWN(pvar) = *(IUnknown **) pb;
  488. V_UNKNOWN(pvar)->AddRef();
  489. break;
  490. default:
  491. ADsAssert(0 && "Unknown VARTYPE in IEnumVARIANT::Next");
  492. break;
  493. }
  494. }
  495. if (pceltFetched)
  496. {
  497. *pceltFetched = c;
  498. }
  499. _i += c;
  500. return ((c == (int) celt) ? NOERROR : S_FALSE);
  501. }
  502. //+------------------------------------------------------------------------
  503. //
  504. // Member: CEnumVARIANT::Clone
  505. //
  506. // Synopsis: Creates a copy of this enumerator; the copy should have the
  507. // same state as this enumerator.
  508. //
  509. // Arguments: [ppenum] New enumerator is returned in *ppenum
  510. //
  511. // Returns: HRESULT (STDMETHOD)
  512. //
  513. //-------------------------------------------------------------------------
  514. STDMETHODIMP
  515. CEnumVARIANT::Clone(CBaseEnum ** ppenum)
  516. {
  517. HRESULT hr;
  518. if (!ppenum)
  519. RRETURN(E_INVALIDARG);
  520. *ppenum = NULL;
  521. hr = _pary->EnumVARIANT(_cb, _vt, (IEnumVARIANT **)ppenum);
  522. if (hr)
  523. RRETURN(hr);
  524. (**(CEnumVARIANT **)ppenum)._i = _i;
  525. return S_OK;
  526. }