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.

2001 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: oregfmt.cpp
  7. //
  8. // Contents: Enumerator implementation for the regdb formatetc's
  9. //
  10. // Classes: CEnumFmt
  11. // CEnumFmt10
  12. //
  13. // Functions: OleRegEnumFormatEtc
  14. //
  15. //
  16. // History: dd-mmm-yy Author Comment
  17. // 01-Feb-95 t-ScottH add Dump methods to CEnumFmt, CEnumFmt10
  18. // and add APIs DumpCEnumFmt, DumpCEnumFmt10
  19. // DumpFMT, DumpFMTCache
  20. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  21. // memory allocations.
  22. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  23. // 31-Dec-93 erikgav chicago port
  24. // 01-Dec-93 alexgo 32bit port
  25. // 12-Nov-92 jasonful author
  26. //
  27. //--------------------------------------------------------------------------
  28. #include <le2int.h>
  29. #pragma SEG(oregfmt)
  30. #include <reterr.h>
  31. #include "oleregpv.h"
  32. #include <ctype.h>
  33. #include <string.h>
  34. #ifdef _DEBUG
  35. #include <dbgdump.h>
  36. #endif // _DEBUG
  37. ASSERTDATA
  38. #define MAX_STR 256
  39. #define UtRemoveRightmostBit(x) ((x)&((x)-1))
  40. #define UtRightmostBit(x) ((x)^UtRemoveRightmostBit(x))
  41. #define UtIsSingleBit(x) ((x) && (0==UtRemoveRightmostBit(x)))
  42. // reg db key
  43. static const LPCOLESTR DATA_FORMATS = OLESTR("DataFormats\\GetSet");
  44. static INTERNAL CreateEnumFormatEtc10
  45. (REFCLSID clsid,
  46. DWORD dwDirection,
  47. LPENUMFORMATETC FAR* ppenum);
  48. typedef struct FARSTRUCT
  49. {
  50. FORMATETC fmt;
  51. DWORD dwAspects; // aspects not yet returned
  52. BOOL fUseMe; // is the cache valid?
  53. } FMTCACHE;
  54. //+-------------------------------------------------------------------------
  55. //
  56. // Class: CEnumFmt
  57. //
  58. // Purpose: FORMATETC enumerator for regdb formats
  59. //
  60. // Interface: IEnumFORMATETC
  61. //
  62. // History: dd-mmm-yy Author Comment
  63. // 01-Dec-93 alexgo 32bit port
  64. //
  65. // Notes:
  66. //
  67. //--------------------------------------------------------------------------
  68. class FAR CEnumFmt : public IEnumFORMATETC, public CPrivAlloc
  69. {
  70. public:
  71. // *** IUnknown methods ***
  72. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  73. STDMETHOD_(ULONG,AddRef) (THIS);
  74. STDMETHOD_(ULONG,Release) (THIS);
  75. // *** IEnumFORMATETC methods ***
  76. STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt,
  77. ULONG FAR* pceltFetched) ;
  78. STDMETHOD(Skip) (THIS_ ULONG celt) ;
  79. STDMETHOD(Reset) (THIS) ;
  80. STDMETHOD(Clone) (THIS_ LPENUMFORMATETC FAR* ppenum) ;
  81. CEnumFmt (LPOLESTR szClsid, DWORD dwDirection, DWORD iKey=0);
  82. STDMETHOD(OpenHKey) (HKEY FAR*);
  83. #ifdef _DEBUG
  84. HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
  85. #endif // _DEBUG
  86. ULONG m_cRef;
  87. LPOLESTR m_szClsid;
  88. DWORD m_dwDirection;
  89. DWORD m_iKey ; // index of current key in reg db
  90. // We cannot keep an hkey open because Clone (or trying to use any 2
  91. // independent enumerators) would fail.
  92. FMTCACHE m_cache;
  93. };
  94. // For OLE 1.0
  95. typedef struct
  96. {
  97. CLIPFORMAT cf;
  98. DWORD dw; // DATADIR_GET/SET
  99. } FMT;
  100. #ifdef _DEBUG
  101. // for use in CEnumFmt[10] Dump methods
  102. char *DumpFMT(FMT *pFMT, ULONG ulFlag, int nIndentLevel);
  103. char *DumpFMTCACHE(FMTCACHE *pFMTC, ULONG ulFlag, int nIndentLevel);
  104. #endif // _DEBUG
  105. //+-------------------------------------------------------------------------
  106. //
  107. // Class: CEnumFmt10 : CEnumFmt
  108. //
  109. // Purpose: Enumerates OLE1.0 formats
  110. //
  111. // Interface: IEnumFORMATETC
  112. //
  113. // History: dd-mmm-yy Author Comment
  114. // 01-Dec-93 alexgo 32bit port
  115. //
  116. // Notes:
  117. //
  118. //--------------------------------------------------------------------------
  119. class FAR CEnumFmt10 : public CEnumFmt
  120. {
  121. public:
  122. STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt,
  123. ULONG FAR* pceltFetched) ;
  124. STDMETHOD(Skip) (THIS_ ULONG celt) ;
  125. STDMETHOD(Clone) (THIS_ LPENUMFORMATETC FAR* ppenum) ;
  126. STDMETHOD_(ULONG,Release) (THIS) ;
  127. CEnumFmt10 (LPOLESTR szClsid, DWORD dwDirection, DWORD iKey=0);
  128. STDMETHOD(InitFromRegDb) (HKEY);
  129. STDMETHOD(InitFromScratch) (void);
  130. #ifdef _DEBUG
  131. HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
  132. #endif // _DEBUG
  133. FMT FAR* m_rgFmt;
  134. size_t m_cFmt; // number of Fmts in m_rgFmt
  135. };
  136. //+-------------------------------------------------------------------------
  137. //
  138. // Member: CEnumFmt::CEnumFmt
  139. //
  140. // Synopsis: Constructor for the formatetc enumerator
  141. //
  142. // Effects:
  143. //
  144. // Arguments: [szClsid] -- the class id to look for
  145. // [dwDirection] -- (either SET or GET)
  146. // [iKey] -- index into the regdb (which formatetc)
  147. //
  148. // Requires:
  149. //
  150. // Returns:
  151. //
  152. // Signals:
  153. //
  154. // Modifies:
  155. //
  156. // Derivation:
  157. //
  158. // Algorithm:
  159. //
  160. // History: dd-mmm-yy Author Comment
  161. // 01-Dec-93 alexgo 32bit port
  162. //
  163. // Notes:
  164. //
  165. //--------------------------------------------------------------------------
  166. #pragma SEG(CEnumFmt_ctor)
  167. CEnumFmt::CEnumFmt
  168. (LPOLESTR szClsid,
  169. DWORD dwDirection,
  170. DWORD iKey)
  171. {
  172. VDATEHEAP();
  173. m_cRef = 1;
  174. m_szClsid = szClsid;
  175. m_iKey = iKey;
  176. m_dwDirection = dwDirection;
  177. m_cache.fUseMe = FALSE;
  178. }
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Member: CEnumFmt10::CEnumFmt10
  182. //
  183. // Synopsis: Constructor for the 1.0 formatetc enumerator
  184. //
  185. // Effects:
  186. //
  187. // Arguments: [szClsid] -- the class id to look for
  188. // [dwDirection] -- (either SET or GET)
  189. // [iKey] -- index into the regdb (which formatetc)
  190. //
  191. // Requires:
  192. //
  193. // Returns:
  194. //
  195. // Signals:
  196. //
  197. // Modifies:
  198. //
  199. // Derivation:
  200. //
  201. // Algorithm:
  202. //
  203. // History: dd-mmm-yy Author Comment
  204. // 01-Dec-93 alexgo 32bit port
  205. //
  206. // Notes:
  207. //
  208. //--------------------------------------------------------------------------
  209. #pragma SEG(CEnumFmt10_ctor)
  210. CEnumFmt10::CEnumFmt10
  211. (LPOLESTR szClsid,
  212. DWORD dwDirection,
  213. DWORD iKey)
  214. : CEnumFmt (szClsid, dwDirection, iKey)
  215. {
  216. VDATEHEAP();
  217. m_rgFmt = NULL;
  218. }
  219. //+-------------------------------------------------------------------------
  220. //
  221. // Function: CreateEnumFormatEtc (static)
  222. //
  223. // Synopsis: Creates a 2.0 formatetc enumerator object
  224. //
  225. // Effects:
  226. //
  227. // Arguments: [clsid] -- the class ID to look for
  228. // [dwDirection] -- the formatetc direction (SET or GET)
  229. // [ppenum] -- where to put the enumerator
  230. //
  231. // Requires:
  232. //
  233. // Returns: HRESULT
  234. //
  235. // Signals:
  236. //
  237. // Modifies:
  238. //
  239. // Algorithm: Checks to make sure that the data exists in the reg db
  240. // and then allocates an enumerator object
  241. //
  242. // History: dd-mmm-yy Author Comment
  243. // 01-Dec-93 alexgo 32bit port
  244. //
  245. // Notes:
  246. //
  247. //--------------------------------------------------------------------------
  248. #pragma SEG(CreateEnumFormatEtc)
  249. static INTERNAL CreateEnumFormatEtc
  250. (REFCLSID clsid,
  251. DWORD dwDirection,
  252. LPENUMFORMATETC FAR* ppenum)
  253. {
  254. VDATEHEAP();
  255. OLECHAR szKey[MAX_STR];
  256. LPOLESTR szClsid = NULL;
  257. HKEY hkey = NULL;
  258. HKEY hkeyFmts = NULL;
  259. RetErr (StringFromCLSID (clsid, &szClsid));
  260. _xstrcpy (szKey, szClsidRoot);
  261. _xstrcat (szKey, szClsid);
  262. if (ERROR_SUCCESS != RegOpenKey (HKEY_CLASSES_ROOT, szKey, &hkey))
  263. {
  264. PubMemFree(szClsid);
  265. return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
  266. }
  267. if (ERROR_SUCCESS != RegOpenKey (hkey, (LPOLESTR) DATA_FORMATS,
  268. &hkeyFmts))
  269. {
  270. CLOSE (hkey);
  271. PubMemFree(szClsid);
  272. return ReportResult(0, REGDB_E_KEYMISSING, 0, 0);
  273. }
  274. CLOSE (hkeyFmts);
  275. CLOSE (hkey);
  276. *ppenum = new FAR CEnumFmt (szClsid, dwDirection);
  277. // hook the new interface
  278. CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IEnumFORMATETC,
  279. (IUnknown **)ppenum);
  280. // do not delete szClsid. Will be deleted on Release
  281. return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
  282. }
  283. //+-------------------------------------------------------------------------
  284. //
  285. // Function: OleRegEnumFormatEtc
  286. //
  287. // Synopsis: Creates a reg db formatetc enumerator
  288. //
  289. // Effects:
  290. //
  291. // Arguments: [clsid] -- the class ID we're interested in
  292. // [dwDirection] -- either GET or SET (for the formatetc and
  293. // IDataObject->[Get|Set]Data)
  294. // [ppenum] -- where to put the enumerator
  295. //
  296. // Requires:
  297. //
  298. // Returns: HRESULT
  299. //
  300. // Signals:
  301. //
  302. // Modifies:
  303. //
  304. // Algorithm: Creates either an OLE2 enumerator or an OLE1 enumerator
  305. //
  306. // History: dd-mmm-yy Author Comment
  307. // 29-Nov-93 ChrisWe allow more than one DATADIR_* flag at a
  308. // time
  309. // 01-Dec-93 alexgo 32bit port
  310. //
  311. // Notes:
  312. //
  313. //--------------------------------------------------------------------------
  314. #pragma SEG(OleRegEnumFormatEtc)
  315. STDAPI OleRegEnumFormatEtc
  316. (REFCLSID clsid,
  317. DWORD dwDirection,
  318. LPENUMFORMATETC FAR* ppenum)
  319. {
  320. OLETRACEIN((API_OleRegEnumFormatEtc, PARAMFMT("clsid= %I, dwDirection= %x, ppenum= %p"),
  321. &clsid, dwDirection, ppenum));
  322. VDATEHEAP();
  323. HRESULT hr;
  324. VDATEPTROUT_LABEL(ppenum, LPENUMFORMATETC, errRtn, hr);
  325. *ppenum = NULL;
  326. // check that dwDirection only has valid values
  327. if (dwDirection & ~(DATADIR_GET | DATADIR_SET))
  328. {
  329. hr = ResultFromScode(E_INVALIDARG);
  330. goto errRtn;
  331. }
  332. if (CoIsOle1Class (clsid))
  333. {
  334. hr = CreateEnumFormatEtc10 (clsid, dwDirection, ppenum);
  335. }
  336. else
  337. {
  338. hr = CreateEnumFormatEtc (clsid, dwDirection, ppenum);
  339. }
  340. errRtn:
  341. OLETRACEOUT((API_OleRegEnumFormatEtc, hr));
  342. return hr;
  343. }
  344. //+-------------------------------------------------------------------------
  345. //
  346. // Member: CEnumFmt::OpenHKey
  347. //
  348. // Synopsis: Opens a the regdb and returns a handle to the formatetc's
  349. //
  350. // Effects:
  351. //
  352. // Arguments: [phkey] -- where to put the regdb handle
  353. //
  354. // Requires:
  355. //
  356. // Returns: NOERROR, REGDB_E_KEYMISSING
  357. //
  358. // Signals:
  359. //
  360. // Modifies:
  361. //
  362. // Derivation:
  363. //
  364. // Algorithm:
  365. //
  366. // History: dd-mmm-yy Author Comment
  367. // 01-Dec-93 alexgo 32bit port
  368. //
  369. // Notes:
  370. //
  371. //--------------------------------------------------------------------------
  372. #pragma SEG(CEnumFmt_OpenHKey)
  373. STDMETHODIMP CEnumFmt::OpenHKey
  374. (HKEY FAR* phkey)
  375. {
  376. VDATEHEAP();
  377. VDATEPTRIN (phkey, HKEY);
  378. OLECHAR szBuf [MAX_STR];
  379. _xstrcpy (szBuf, szClsidRoot);
  380. _xstrcat (szBuf, m_szClsid);
  381. _xstrcat (szBuf, OLESTR("\\"));
  382. _xstrcat (szBuf, DATA_FORMATS);
  383. return ERROR_SUCCESS==RegOpenKey (HKEY_CLASSES_ROOT, szBuf, phkey)
  384. ? NOERROR
  385. : ResultFromScode(REGDB_E_KEYMISSING);
  386. }
  387. //+-------------------------------------------------------------------------
  388. //
  389. // Member: CEnumFmt::Reset
  390. //
  391. // Synopsis: Resets the enumerator
  392. //
  393. // Effects:
  394. //
  395. // Arguments: void
  396. //
  397. // Requires:
  398. //
  399. // Returns: NOERROR
  400. //
  401. // Signals:
  402. //
  403. // Modifies:
  404. //
  405. // Derivation: IEnumFormatEtc
  406. //
  407. // Algorithm:
  408. //
  409. // History: dd-mmm-yy Author Comment
  410. // 01-Dec-93 alexgo 32bit port
  411. //
  412. // Notes:
  413. //
  414. //--------------------------------------------------------------------------
  415. #pragma SEG(CEnumFmt_Reset)
  416. STDMETHODIMP CEnumFmt::Reset (void)
  417. {
  418. VDATEHEAP();
  419. m_iKey = 0;
  420. return NOERROR;
  421. }
  422. //+-------------------------------------------------------------------------
  423. //
  424. // Member: CEnumFmt::Skip
  425. //
  426. // Synopsis: Skips the next [c] formatetc's
  427. //
  428. // Effects:
  429. //
  430. // Arguments: [c] -- number of formatetc's to skip
  431. //
  432. // Requires:
  433. //
  434. // Returns: HRESULT
  435. //
  436. // Signals:
  437. //
  438. // Modifies:
  439. //
  440. // Derivation: IEnumFormatEtc
  441. //
  442. // Algorithm: just calls Next [c] times :)
  443. //
  444. // History: dd-mmm-yy Author Comment
  445. // 01-Dec-93 alexgo 32bit port
  446. //
  447. // Notes:
  448. //
  449. //--------------------------------------------------------------------------
  450. #pragma SEG(CEnumFmt_Skip)
  451. STDMETHODIMP CEnumFmt::Skip
  452. (ULONG c)
  453. {
  454. VDATEHEAP();
  455. ULONG i=0;
  456. FORMATETC formatetc;
  457. HRESULT hresult = NOERROR;
  458. while (i++ < c)
  459. {
  460. // There will not be a target device to free
  461. ErrRtnH (Next (1, &formatetc, NULL));
  462. }
  463. errRtn:
  464. return hresult;
  465. }
  466. //+-------------------------------------------------------------------------
  467. //
  468. // Member: CEnumFmt::Next
  469. //
  470. // Synopsis: Gets the next formatetc from teh regdb
  471. //
  472. // Effects:
  473. //
  474. // Arguments: [cfmt] -- the number of formatetc's to return
  475. // [rgfmt] -- where to put the formatetc's
  476. // [pcfmtFetched] -- where to put how many formatetc's were
  477. // actually fetched
  478. //
  479. // Requires:
  480. //
  481. // Returns: HRESULT
  482. //
  483. // Signals:
  484. //
  485. // Modifies:
  486. //
  487. // Derivation: IEnumFORMATETC
  488. //
  489. // Algorithm: In the reg db, apps may compactly specify that a formatetc
  490. // applies to multiple aspects by simply using the numeric
  491. // value of the aspects or'ed together. Since our enumerator
  492. // should give one formatetc *per* aspect, if multiple aspects
  493. // are specified, then we cache the formatetc and use it the
  494. // next time a formatetc is requested (via next or [cfmt] > 1)
  495. // That's what the m_cache stuff is all about.
  496. //
  497. // History: dd-mmm-yy Author Comment
  498. // 01-Dec-93 alexgo 32bit port
  499. //
  500. // Notes:
  501. //
  502. //--------------------------------------------------------------------------
  503. #pragma SEG(CEnumFmt_Next)
  504. STDMETHODIMP CEnumFmt::Next
  505. (ULONG cfmt,
  506. FORMATETC FAR * rgfmt,
  507. ULONG FAR* pcfmtFetched)
  508. {
  509. VDATEHEAP();
  510. OLECHAR szBuf [MAX_STR];
  511. OLECHAR szKey [80];
  512. DWORD dwAspects;
  513. LPOLESTR psz;
  514. LONG cb = 0;
  515. HKEY hkey = NULL;
  516. ULONG ifmt = 0; // number successfully fetched so far
  517. LPOLESTR szFmt = NULL;
  518. LPOLESTR szAspects = NULL;
  519. LPOLESTR szMedia = NULL;
  520. LPOLESTR szDirection = NULL;
  521. HRESULT hresult = NOERROR;
  522. RetErr (OpenHKey (&hkey));
  523. while (ifmt < cfmt)
  524. {
  525. // use the cached value (multiple aspects specified for the
  526. // formatetc.
  527. if (m_cache.fUseMe)
  528. {
  529. rgfmt[ifmt] = m_cache.fmt;
  530. rgfmt[ifmt].dwAspect = UtRightmostBit (
  531. m_cache.dwAspects);
  532. m_cache.dwAspects = UtRemoveRightmostBit (
  533. m_cache.dwAspects);
  534. if (0==m_cache.dwAspects)
  535. m_cache.fUseMe = FALSE;
  536. ifmt++;
  537. }
  538. else
  539. {
  540. wsprintf (szKey, OLESTR("%d"), m_iKey++);
  541. cb = MAX_STR;
  542. if (ERROR_SUCCESS == RegQueryValue (hkey, szKey,
  543. szBuf, &cb))
  544. {
  545. rgfmt[ifmt].ptd = NULL;
  546. rgfmt[ifmt].lindex = DEF_LINDEX;
  547. psz = szBuf;
  548. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  549. szFmt = psz;
  550. while (*psz && *psz != DELIM[0])
  551. psz++;
  552. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  553. *psz++ = OLESTR('\0');
  554. szAspects = psz;
  555. while (*psz && *psz != DELIM[0])
  556. psz++;
  557. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  558. *psz++ = OLESTR('\0');
  559. szMedia = psz;
  560. while (*psz && *psz != DELIM[0])
  561. psz++;
  562. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  563. *psz++ = OLESTR('\0');
  564. szDirection = psz;
  565. // Format
  566. rgfmt [ifmt].cfFormat = _xisdigit (szFmt[0])
  567. ? (CLIPFORMAT) Atol (szFmt)
  568. : RegisterClipboardFormat (szFmt);
  569. // Aspect
  570. dwAspects = Atol (szAspects);
  571. ErrZS (dwAspects, REGDB_E_INVALIDVALUE);
  572. if (UtIsSingleBit (dwAspects))
  573. {
  574. rgfmt[ifmt].dwAspect = Atol(szAspects);
  575. }
  576. else
  577. {
  578. rgfmt[ifmt].dwAspect =
  579. UtRightmostBit(dwAspects);
  580. m_cache.fmt = rgfmt[ifmt];
  581. m_cache.dwAspects =
  582. UtRemoveRightmostBit(
  583. dwAspects) & 0xf;
  584. if (m_cache.dwAspects != 0)
  585. {
  586. m_cache.fUseMe = TRUE;
  587. }
  588. }
  589. // Media
  590. rgfmt[ifmt].tymed = Atol (szMedia);
  591. if (m_cache.fUseMe)
  592. {
  593. m_cache.fmt.tymed = rgfmt[ifmt].tymed;
  594. }
  595. // Direction
  596. if ( (Atol (szDirection) & m_dwDirection) ==
  597. m_dwDirection)
  598. {
  599. // This format supports the direction
  600. // we are interested in
  601. ifmt++;
  602. }
  603. else
  604. {
  605. m_cache.fUseMe = FALSE;
  606. }
  607. }
  608. else
  609. {
  610. break; // no more entries
  611. }
  612. }// else
  613. }// while
  614. if (pcfmtFetched)
  615. {
  616. *pcfmtFetched = ifmt;
  617. }
  618. errRtn:
  619. CLOSE (hkey);
  620. if (NOERROR==hresult)
  621. {
  622. return ifmt==cfmt ? NOERROR : ResultFromScode (S_FALSE);
  623. }
  624. else
  625. {
  626. if (pcfmtFetched)
  627. {
  628. *pcfmtFetched = 0;
  629. }
  630. m_cache.fUseMe = FALSE;
  631. return hresult;
  632. }
  633. }
  634. //+-------------------------------------------------------------------------
  635. //
  636. // Member: CEnumFmt::Clone
  637. //
  638. // Synopsis: clones the enumerator
  639. //
  640. // Effects:
  641. //
  642. // Arguments: [ppenum] -- where to put the cloned enumerator
  643. //
  644. // Requires:
  645. //
  646. // Returns: NOERROR, E_OUTOFMEMORY
  647. //
  648. // Signals:
  649. //
  650. // Modifies:
  651. //
  652. // Derivation: IEnumFORMATETC
  653. //
  654. // Algorithm:
  655. //
  656. // History: dd-mmm-yy Author Comment
  657. // 01-Dec-93 alexgo 32bit port
  658. //
  659. // Notes:
  660. //
  661. //--------------------------------------------------------------------------
  662. #pragma SEG(CEnumFmt_Clone)
  663. STDMETHODIMP CEnumFmt::Clone
  664. (LPENUMFORMATETC FAR* ppenum)
  665. {
  666. VDATEHEAP();
  667. VDATEPTRIN (ppenum, LPENUMFORMATETC);
  668. *ppenum = new FAR CEnumFmt (UtDupString(m_szClsid), m_dwDirection,
  669. m_iKey);
  670. return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
  671. }
  672. //+-------------------------------------------------------------------------
  673. //
  674. // Member: CEnumFmt::QueryInterface
  675. //
  676. // Synopsis: returns supported interfaces
  677. //
  678. // Effects:
  679. //
  680. // Arguments: [iid] -- the requested interface ID
  681. // [ppv] -- where to put the interface pointer
  682. //
  683. // Requires:
  684. //
  685. // Returns:
  686. //
  687. // Signals:
  688. //
  689. // Modifies:
  690. //
  691. // Derivation: IEnumFormatEtc
  692. //
  693. // Algorithm:
  694. //
  695. // History: dd-mmm-yy Author Comment
  696. // 01-Dec-93 alexgo 32bit port
  697. //
  698. // Notes:
  699. //
  700. //--------------------------------------------------------------------------
  701. #pragma SEG(CEnumFmt_QueryInterface)
  702. STDMETHODIMP CEnumFmt::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  703. {
  704. VDATEHEAP();
  705. M_PROLOG(this);
  706. if (IsEqualIID(iid, IID_IUnknown) ||
  707. IsEqualIID(iid, IID_IEnumFORMATETC))
  708. {
  709. *ppv = this;
  710. AddRef();
  711. return NOERROR;
  712. }
  713. else
  714. {
  715. *ppv = NULL;
  716. return ResultFromScode (E_NOINTERFACE);
  717. }
  718. }
  719. //+-------------------------------------------------------------------------
  720. //
  721. // Member: CEnumFmt::AddRef
  722. //
  723. // Synopsis: Increments the reference count
  724. //
  725. // Effects:
  726. //
  727. // Arguments: void
  728. //
  729. // Requires:
  730. //
  731. // Returns: ULONG -- the new reference count
  732. //
  733. // Signals:
  734. //
  735. // Modifies:
  736. //
  737. // Derivation: IEnumFORMATETC
  738. //
  739. // Algorithm:
  740. //
  741. // History: dd-mmm-yy Author Comment
  742. // 01-Dec-93 alexgo 32bit port
  743. //
  744. // Notes:
  745. //
  746. //--------------------------------------------------------------------------
  747. #pragma SEG(CEnumFmt_AddRef)
  748. STDMETHODIMP_(ULONG) CEnumFmt::AddRef(void)
  749. {
  750. VDATEHEAP();
  751. M_PROLOG(this);
  752. return ++m_cRef;
  753. }
  754. //+-------------------------------------------------------------------------
  755. //
  756. // Member: CEnumFmt::Release
  757. //
  758. // Synopsis: decrements the reference count
  759. //
  760. // Effects: may delete this object
  761. //
  762. // Arguments: void
  763. //
  764. // Requires:
  765. //
  766. // Returns: ULONG -- the new reference count
  767. //
  768. // Signals:
  769. //
  770. // Modifies:
  771. //
  772. // Derivation: IEnumFORMATETC
  773. //
  774. // Algorithm:
  775. //
  776. // History: dd-mmm-yy Author Comment
  777. // 01-Dec-93 alexgo 32bit port
  778. //
  779. // Notes:
  780. //
  781. //--------------------------------------------------------------------------
  782. #pragma SEG(CEnumFmt_Release)
  783. STDMETHODIMP_(ULONG) CEnumFmt::Release(void)
  784. {
  785. VDATEHEAP();
  786. M_PROLOG(this);
  787. if (--m_cRef == 0)
  788. {
  789. PubMemFree(m_szClsid);
  790. delete this;
  791. return 0;
  792. }
  793. return m_cRef;
  794. }
  795. //+-------------------------------------------------------------------------
  796. //
  797. // Member: CEnumFmt::Dump, public (_DEBUG only)
  798. //
  799. // Synopsis: return a string containing the contents of the data members
  800. //
  801. // Effects:
  802. //
  803. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  804. // [ulFlag] - flag determining prefix of all newlines of the
  805. // out character array (default is 0 - no prefix)
  806. // [nIndentLevel] - will add a indent prefix after the other prefix
  807. // for ALL newlines (including those with no prefix)
  808. //
  809. // Requires:
  810. //
  811. // Returns: HRESULT
  812. //
  813. // Signals:
  814. //
  815. // Modifies: [ppszDump] - argument
  816. //
  817. // Derivation:
  818. //
  819. // Algorithm: use dbgstream to create a string containing information on the
  820. // content of data structures
  821. //
  822. // History: dd-mmm-yy Author Comment
  823. // 01-Feb-95 t-ScottH author
  824. //
  825. // Notes:
  826. //
  827. //--------------------------------------------------------------------------
  828. #ifdef _DEBUG
  829. HRESULT CEnumFmt::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  830. {
  831. int i;
  832. char *pszPrefix;
  833. char *pszFMTCACHE;
  834. dbgstream dstrPrefix;
  835. dbgstream dstrDump;
  836. // determine prefix of newlines
  837. if ( ulFlag & DEB_VERBOSE )
  838. {
  839. dstrPrefix << this << " _VB ";
  840. }
  841. // determine indentation prefix for all newlines
  842. for (i = 0; i < nIndentLevel; i++)
  843. {
  844. dstrPrefix << DUMPTAB;
  845. }
  846. pszPrefix = dstrPrefix.str();
  847. // put data members in stream
  848. dstrDump << pszPrefix << "No. of References = " << m_cRef << endl;
  849. dstrDump << pszPrefix << "CLSID string = " << m_szClsid << endl;
  850. dstrDump << pszPrefix << "Direction = " << m_dwDirection<< endl;
  851. dstrDump << pszPrefix << "Current Key Index = " << m_iKey << endl;
  852. pszFMTCACHE = DumpFMTCACHE(&m_cache, ulFlag, nIndentLevel + 1);
  853. dstrDump << pszPrefix << "FMTCACHE: " << endl;
  854. dstrDump << pszFMTCACHE;
  855. CoTaskMemFree(pszFMTCACHE);
  856. // cleanup and provide pointer to character array
  857. *ppszDump = dstrDump.str();
  858. if (*ppszDump == NULL)
  859. {
  860. *ppszDump = UtDupStringA(szDumpErrorMessage);
  861. }
  862. CoTaskMemFree(pszPrefix);
  863. return NOERROR;
  864. }
  865. #endif // _DEBUG
  866. //+-------------------------------------------------------------------------
  867. //
  868. // Function: DumpCEnumFmt, public (_DEBUG only)
  869. //
  870. // Synopsis: calls the CEnumFmt::Dump method, takes care of errors and
  871. // returns the zero terminated string
  872. //
  873. // Effects:
  874. //
  875. // Arguments: [pEF] - pointer to CEnumFmt
  876. // [ulFlag] - flag determining prefix of all newlines of the
  877. // out character array (default is 0 - no prefix)
  878. // [nIndentLevel] - will add a indent prefix after the other prefix
  879. // for ALL newlines (including those with no prefix)
  880. //
  881. // Requires:
  882. //
  883. // Returns: character array of structure dump or error (null terminated)
  884. //
  885. // Signals:
  886. //
  887. // Modifies:
  888. //
  889. // Algorithm:
  890. //
  891. // History: dd-mmm-yy Author Comment
  892. // 01-Feb-95 t-ScottH author
  893. //
  894. // Notes:
  895. //
  896. //--------------------------------------------------------------------------
  897. #ifdef _DEBUG
  898. char *DumpCEnumFmt(CEnumFmt *pEF, ULONG ulFlag, int nIndentLevel)
  899. {
  900. HRESULT hresult;
  901. char *pszDump;
  902. if (pEF == NULL)
  903. {
  904. return UtDupStringA(szDumpBadPtr);
  905. }
  906. hresult = pEF->Dump(&pszDump, ulFlag, nIndentLevel);
  907. if (hresult != NOERROR)
  908. {
  909. CoTaskMemFree(pszDump);
  910. return DumpHRESULT(hresult);
  911. }
  912. return pszDump;
  913. }
  914. #endif // _DEBUG
  915. /////////////////////////////////////////
  916. // OLE 1.0 stuff
  917. //+-------------------------------------------------------------------------
  918. //
  919. // Function: CreateEnumFormatEtc10
  920. //
  921. // Synopsis: Creates a 1.0 format enumerator
  922. //
  923. // Effects:
  924. //
  925. // Arguments: [clsid] -- the class id we're interested in
  926. // [dwDirection] -- either GET or SET
  927. // [ppenum] -- where to put the enumerator
  928. //
  929. // Requires:
  930. //
  931. // Returns: HRESULT
  932. //
  933. // Signals:
  934. //
  935. // Modifies:
  936. //
  937. // Algorithm: checks to see if the info's in the reg db, then creates
  938. // and initializes a 1.0 enumerator object. (note that there
  939. // does not *have* to be any info in the regdb, we can
  940. // InitFromScratch)
  941. //
  942. // History: dd-mmm-yy Author Comment
  943. // 01-Dec-93 alexgo 32bit port
  944. //
  945. // Notes:
  946. //
  947. //--------------------------------------------------------------------------
  948. #pragma SEG(CreateEnumFormatEtc10)
  949. static INTERNAL CreateEnumFormatEtc10
  950. (REFCLSID clsid,
  951. DWORD dwDirection,
  952. LPENUMFORMATETC FAR* ppenum)
  953. {
  954. VDATEHEAP();
  955. LPOLESTR szClsid = NULL;
  956. HKEY hkey = NULL;
  957. HKEY hkeyFmts = NULL;
  958. HRESULT hresult = NOERROR;
  959. BOOL fInReg;
  960. CEnumFmt10 FAR* penum;
  961. VDATEPTROUT (ppenum, LPENUMFORMATETC);
  962. *ppenum = NULL;
  963. RetErr (ProgIDFromCLSID (clsid, &szClsid));
  964. if (ERROR_SUCCESS != RegOpenKey (HKEY_CLASSES_ROOT, szClsid, &hkey))
  965. {
  966. PubMemFree(szClsid);
  967. return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
  968. }
  969. // Does this server have "Request/SetDataFormats" keys?
  970. fInReg = (ERROR_SUCCESS == RegOpenKey (hkey,
  971. OLESTR("Protocol\\StdFileEditing\\RequestDataFormats"),
  972. &hkeyFmts));
  973. CLOSE(hkeyFmts);
  974. penum = new FAR CEnumFmt10 (szClsid, dwDirection);
  975. if (NULL==penum)
  976. {
  977. ErrRtnH (ResultFromScode (E_OUTOFMEMORY));
  978. }
  979. if (fInReg)
  980. {
  981. penum->InitFromRegDb (hkey);
  982. }
  983. else
  984. {
  985. penum->InitFromScratch ();
  986. }
  987. errRtn:
  988. CLOSE (hkey);
  989. if (hresult == NOERROR)
  990. {
  991. *ppenum = penum;
  992. CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IEnumFORMATETC,
  993. (IUnknown **)ppenum);
  994. }
  995. else
  996. {
  997. PubMemFree(szClsid);
  998. // If no error, szClsid will be deleted on Release
  999. }
  1000. return hresult;
  1001. }
  1002. //+-------------------------------------------------------------------------
  1003. //
  1004. // Member: CEnumFmt10::Next
  1005. //
  1006. // Synopsis: Gets the next 1.0 format
  1007. //
  1008. // Effects:
  1009. //
  1010. // Arguments: [cfmt] -- the number of formatetc's to get
  1011. // [rgfmt] -- where to put the formatetc's
  1012. // [pcfmtFetched] -- where to put the num of formatetc's fetched
  1013. //
  1014. // Requires:
  1015. //
  1016. // Returns: HRESULT
  1017. //
  1018. // Signals:
  1019. //
  1020. // Modifies:
  1021. //
  1022. // Derivation: IEnumFORMATETC
  1023. //
  1024. // Algorithm: Ole1.0 formats are retrieved when the enumerator object
  1025. // is created, so we just return ones from our internal array
  1026. //
  1027. // History: dd-mmm-yy Author Comment
  1028. // 01-Dec-93 alexgo 32bit port
  1029. //
  1030. // Notes:
  1031. //
  1032. //--------------------------------------------------------------------------
  1033. #pragma SEG(CEnumFmt10_Next)
  1034. STDMETHODIMP CEnumFmt10::Next
  1035. (ULONG cfmt,
  1036. FORMATETC FAR * rgfmt,
  1037. ULONG FAR* pcfmtFetched)
  1038. {
  1039. VDATEHEAP();
  1040. ULONG ifmt = 0; // number successfully fetched so far
  1041. while (ifmt < cfmt
  1042. && m_rgFmt != NULL
  1043. && m_rgFmt[m_iKey].cf != 0)
  1044. {
  1045. if ( (m_rgFmt[m_iKey].dw & m_dwDirection) == m_dwDirection)
  1046. {
  1047. // This format supports the direction we are
  1048. // interested in
  1049. rgfmt [ifmt].cfFormat = m_rgFmt[m_iKey].cf;
  1050. rgfmt [ifmt].ptd = NULL;
  1051. rgfmt [ifmt].lindex = DEF_LINDEX;
  1052. rgfmt [ifmt].tymed =
  1053. UtFormatToTymed(m_rgFmt[m_iKey].cf);
  1054. rgfmt [ifmt].dwAspect = DVASPECT_CONTENT;
  1055. ifmt++;
  1056. }
  1057. m_iKey++;
  1058. }
  1059. if (pcfmtFetched)
  1060. *pcfmtFetched = ifmt;
  1061. return ifmt==cfmt ? NOERROR : ResultFromScode (S_FALSE);
  1062. }
  1063. //+-------------------------------------------------------------------------
  1064. //
  1065. // Function: Index (static)
  1066. //
  1067. // Synopsis: finds the index of the given clipformat in the format
  1068. // array
  1069. //
  1070. // Effects:
  1071. //
  1072. // Arguments: [rgFmt] -- the clipformat array
  1073. // [cf] -- the clipformat to look for
  1074. // [iMax] -- size of the array
  1075. // [pi] -- where to put the index
  1076. //
  1077. // Requires:
  1078. //
  1079. // Returns: TRUE if found, FALSE otherwise
  1080. //
  1081. // Signals:
  1082. //
  1083. // Modifies:
  1084. //
  1085. // Algorithm:
  1086. //
  1087. // History: dd-mmm-yy Author Comment
  1088. // 01-Dec-93 alexgo 32bit port
  1089. //
  1090. // Notes:
  1091. //
  1092. //--------------------------------------------------------------------------
  1093. #pragma SEG(Index)
  1094. static INTERNAL_(BOOL) Index
  1095. (FMT FAR * rgFmt,
  1096. CLIPFORMAT cf, // format to search for
  1097. size_t iMax, // size of array
  1098. size_t FAR* pi) // out parm, index of found format
  1099. {
  1100. VDATEHEAP();
  1101. for (size_t i=0; i< iMax; i++)
  1102. {
  1103. if (rgFmt[i].cf==cf)
  1104. {
  1105. *pi = i;
  1106. return TRUE;
  1107. }
  1108. }
  1109. return FALSE;
  1110. }
  1111. //+-------------------------------------------------------------------------
  1112. //
  1113. // Function: String2Clipformat (static)
  1114. //
  1115. // Synopsis: Converts a string to a clipboard format number (and then
  1116. // registers the format)
  1117. //
  1118. // Effects:
  1119. //
  1120. // Arguments: [sz] -- the string to convert
  1121. //
  1122. // Requires:
  1123. //
  1124. // Returns: CLIPFORMAT
  1125. //
  1126. // Signals:
  1127. //
  1128. // Modifies:
  1129. //
  1130. // Algorithm:
  1131. //
  1132. // History: dd-mmm-yy Author Comment
  1133. // 01-Dec-93 alexgo 32bit port
  1134. //
  1135. // Notes:
  1136. //
  1137. //--------------------------------------------------------------------------
  1138. #pragma SEG(String2Clipformat)
  1139. static INTERNAL_(CLIPFORMAT) String2Clipformat
  1140. (LPOLESTR sz)
  1141. {
  1142. VDATEHEAP();
  1143. if (_xstrlen(sz) >= 3 &&
  1144. 0==memcmp (sz, OLESTR("CF_"), 3*sizeof(sz[0])))
  1145. {
  1146. #define macro(cf) if (0==_xstricmp (sz, OLESTR(#cf))) return cf
  1147. macro (CF_TEXT);
  1148. macro (CF_BITMAP);
  1149. macro (CF_METAFILEPICT);
  1150. macro (CF_SYLK);
  1151. macro (CF_DIF);
  1152. macro (CF_TIFF);
  1153. macro (CF_OEMTEXT);
  1154. macro (CF_DIB);
  1155. macro (CF_PALETTE);
  1156. macro (CF_PENDATA);
  1157. macro (CF_RIFF);
  1158. macro (CF_WAVE);
  1159. macro (CF_OWNERDISPLAY);
  1160. macro (CF_DSPTEXT);
  1161. macro (CF_DSPBITMAP);
  1162. macro (CF_DSPMETAFILEPICT);
  1163. #undef macro
  1164. }
  1165. return (CLIPFORMAT) RegisterClipboardFormat (sz);
  1166. }
  1167. //+-------------------------------------------------------------------------
  1168. //
  1169. // Member: CEnumFmt10::InitFromRegDb (internal)
  1170. //
  1171. // Synopsis: Initializes the 1.0 enumerator from the reg db (loads
  1172. // all the available formats)
  1173. //
  1174. // Effects:
  1175. //
  1176. // Arguments: [hkey] -- handle to the regdb
  1177. //
  1178. // Requires:
  1179. //
  1180. // Returns: HRESULT
  1181. //
  1182. // Signals:
  1183. //
  1184. // Modifies:
  1185. //
  1186. // Derivation:
  1187. //
  1188. // Algorithm:
  1189. //
  1190. // History: dd-mmm-yy Author Comment
  1191. // 01-Dec-93 alexgo 32bit port
  1192. //
  1193. // Notes:
  1194. // Original comment:
  1195. //
  1196. // Fill m_rgFmt with FMTs which map clipformats to Get/Set flags
  1197. //
  1198. //--------------------------------------------------------------------------
  1199. #pragma SEG(CEnumFmt10_InitFromRegDb)
  1200. STDMETHODIMP CEnumFmt10::InitFromRegDb
  1201. (HKEY hkey) // CLSID key
  1202. {
  1203. VDATEHEAP();
  1204. LPOLESTR pch;
  1205. LPOLESTR szReq = (LPOLESTR)PubMemAlloc(512 * sizeof(OLECHAR));
  1206. LPOLESTR szSet = (LPOLESTR)PubMemAlloc(512 * sizeof(OLECHAR));
  1207. LPOLESTR szFmt;
  1208. BOOL bMore;
  1209. size_t cFmts = 0;
  1210. size_t iFmt = 0;
  1211. size_t iFmtPrev;
  1212. CLIPFORMAT cf;
  1213. LONG cb;
  1214. HRESULT hresult = NOERROR;
  1215. if( !szReq )
  1216. {
  1217. // assumes delete 0 works (if szSet == 0)
  1218. PubMemFree(szSet);
  1219. return ResultFromScode (E_OUTOFMEMORY);
  1220. }
  1221. if( !szSet )
  1222. {
  1223. PubMemFree(szReq);
  1224. return ResultFromScode (E_OUTOFMEMORY);
  1225. }
  1226. cb = 512;
  1227. if (ERROR_SUCCESS == RegQueryValue (hkey,
  1228. OLESTR("Protocol\\StdFileEditing\\RequestDataFormats"),
  1229. szReq, &cb))
  1230. {
  1231. cFmts = 1; // no commas means one format
  1232. for (pch = szReq; *pch; pch++)
  1233. {
  1234. if (*pch==OLESTR(','))
  1235. cFmts++;
  1236. }
  1237. }
  1238. // the size of szSet
  1239. cb = 512;
  1240. if (ERROR_SUCCESS == RegQueryValue (hkey,
  1241. OLESTR("Protocol\\StdFileEditing\\SetDataFormats"),
  1242. szSet, &cb))
  1243. {
  1244. cFmts++; // no commas means one format
  1245. for (pch = szSet; *pch; pch++)
  1246. {
  1247. if (*pch==OLESTR(','))
  1248. cFmts++;
  1249. }
  1250. }
  1251. if (cFmts==0)
  1252. {
  1253. Assert(0);
  1254. ErrRtnH (ReportResult(0, REGDB_E_KEYMISSING, 0, 0));
  1255. }
  1256. m_rgFmt = (FMT FAR *)PrivMemAlloc(sizeof(FMT)*(cFmts+1));
  1257. if (m_rgFmt==NULL)
  1258. {
  1259. ErrRtnH (ResultFromScode (E_OUTOFMEMORY));
  1260. }
  1261. pch = szReq;
  1262. bMore = (*pch != 0);
  1263. while (bMore)
  1264. {
  1265. while (*pch == OLESTR(' '))
  1266. pch++;
  1267. szFmt = pch;
  1268. while (*pch && *pch != DELIM[0])
  1269. pch++;
  1270. if (*pch == 0)
  1271. bMore = FALSE;
  1272. *pch++ = OLESTR('\0');
  1273. m_rgFmt[iFmt].cf = String2Clipformat(szFmt);
  1274. m_rgFmt[iFmt++].dw = DATADIR_GET;
  1275. }
  1276. pch = szSet;
  1277. bMore = (*pch != 0);
  1278. while (bMore)
  1279. {
  1280. while (*pch == OLESTR(' '))
  1281. pch++;
  1282. szFmt = pch;
  1283. while (*pch && *pch != DELIM[0])
  1284. pch++;
  1285. if (*pch == 0)
  1286. bMore = FALSE;
  1287. *pch++ = OLESTR('\0');
  1288. cf = String2Clipformat(szFmt);
  1289. if (Index (m_rgFmt, cf, iFmt, &iFmtPrev))
  1290. {
  1291. // This format can also be gotten
  1292. m_rgFmt[iFmtPrev].dw |= DATADIR_SET;
  1293. }
  1294. else
  1295. {
  1296. m_rgFmt[iFmt].cf = cf;
  1297. m_rgFmt[iFmt++].dw = DATADIR_SET;
  1298. }
  1299. }
  1300. // Terminator
  1301. m_rgFmt[iFmt].cf = 0;
  1302. m_cFmt = iFmt;
  1303. errRtn:
  1304. PubMemFree(szReq);
  1305. PubMemFree(szSet);
  1306. return hresult;
  1307. }
  1308. //+-------------------------------------------------------------------------
  1309. //
  1310. // Member: CEnumFmt10::InitFromScratch
  1311. //
  1312. // Synopsis: Initialize the enumerated formats for a 1.0 server that
  1313. // does not specify any Request/SetData formats.
  1314. //
  1315. // Effects:
  1316. //
  1317. // Arguments: void
  1318. //
  1319. // Requires:
  1320. //
  1321. // Returns: HRESULT (NOERROR, E_OUTOFMEMORY)
  1322. //
  1323. // Signals:
  1324. //
  1325. // Modifies:
  1326. //
  1327. // Derivation:
  1328. //
  1329. // Algorithm: sets up Metafiles and "Native" formats
  1330. //
  1331. // History: dd-mmm-yy Author Comment
  1332. // 01-Dec-93 alexgo 32bit port
  1333. //
  1334. // Notes:
  1335. // The spec says that what EnumFormatEtc returns is not a
  1336. // guarantee of support.
  1337. //
  1338. //--------------------------------------------------------------------------
  1339. #pragma SEG(CEnumFmt10_InitFromScratch)
  1340. STDMETHODIMP CEnumFmt10::InitFromScratch
  1341. (void)
  1342. {
  1343. VDATEHEAP();
  1344. m_rgFmt = (FMT FAR *)PrivMemAlloc(10 * sizeof(FMT));
  1345. if( !m_rgFmt )
  1346. {
  1347. return ResultFromScode (E_OUTOFMEMORY);
  1348. }
  1349. m_rgFmt[0].cf = CF_METAFILEPICT;
  1350. m_rgFmt[0].dw = DATADIR_GET;
  1351. m_rgFmt[1].cf = (CLIPFORMAT) RegisterClipboardFormat (OLESTR("Native"));
  1352. m_rgFmt[1].dw = DATADIR_GET | DATADIR_SET;
  1353. m_rgFmt[2].cf = 0; // Terminator
  1354. m_cFmt = 2;
  1355. return NOERROR;
  1356. }
  1357. //+-------------------------------------------------------------------------
  1358. //
  1359. // Member: CEnumFmt10::Skip
  1360. //
  1361. // Synopsis: skips to over [c] formats
  1362. //
  1363. // Effects:
  1364. //
  1365. // Arguments: [c] -- the number of formats to skip
  1366. //
  1367. // Requires:
  1368. //
  1369. // Returns: HRESULT
  1370. //
  1371. // Signals:
  1372. //
  1373. // Modifies:
  1374. //
  1375. // Derivation: IEnumFORMATETC
  1376. //
  1377. // Algorithm:
  1378. //
  1379. // History: dd-mmm-yy Author Comment
  1380. // 01-Dec-93 alexgo 32bit port
  1381. //
  1382. // Notes: This is re-implemented so we get the right implementation
  1383. // of Next (because C++ is evil OOP).
  1384. // REVIEW32: we can probably get rid of this by clever use
  1385. // of virtual (but must make sure the vtables don't get hosed).
  1386. //
  1387. //--------------------------------------------------------------------------
  1388. #pragma SEG(CEnumFmt10_Skip)
  1389. STDMETHODIMP CEnumFmt10::Skip
  1390. (ULONG c)
  1391. {
  1392. VDATEHEAP();
  1393. ULONG i=0;
  1394. FORMATETC formatetc;
  1395. HRESULT hresult = NOERROR;
  1396. while (i++ < c)
  1397. {
  1398. // There will not be a target device to free
  1399. ErrRtnH (Next (1, &formatetc, NULL));
  1400. }
  1401. errRtn:
  1402. return hresult;
  1403. }
  1404. //+-------------------------------------------------------------------------
  1405. //
  1406. // Member: CEnumFmt10::Clone
  1407. //
  1408. // Synopsis: duplicates the 1.0 format enumerator
  1409. //
  1410. // Effects:
  1411. //
  1412. // Arguments: [ppenum] -- where to put the cloned enumerator
  1413. //
  1414. // Requires:
  1415. //
  1416. // Returns: HRESULT
  1417. //
  1418. // Signals:
  1419. //
  1420. // Modifies:
  1421. //
  1422. // Derivation: IEnumFORMATETC
  1423. //
  1424. // Algorithm:
  1425. //
  1426. // History: dd-mmm-yy Author Comment
  1427. // 01-Dec-93 alexgo 32bit port, fixed memory leak
  1428. //
  1429. // Notes:
  1430. //
  1431. //--------------------------------------------------------------------------
  1432. #pragma SEG(CEnumFmt10_Clone)
  1433. STDMETHODIMP CEnumFmt10::Clone
  1434. (LPENUMFORMATETC FAR* ppenum)
  1435. {
  1436. VDATEHEAP();
  1437. VDATEPTROUT (ppenum, LPENUMFORMATETC);
  1438. CEnumFmt10 FAR* penum;
  1439. penum = new FAR CEnumFmt10 (UtDupString(m_szClsid), m_dwDirection,
  1440. m_iKey);
  1441. if (NULL==penum)
  1442. {
  1443. return ResultFromScode (E_OUTOFMEMORY);
  1444. }
  1445. penum->m_cFmt = m_cFmt;
  1446. penum->m_rgFmt = (FMT FAR *)PrivMemAlloc((m_cFmt+1) * sizeof(FMT));
  1447. if (NULL==penum->m_rgFmt)
  1448. {
  1449. PubMemFree(penum);
  1450. return ResultFromScode (E_OUTOFMEMORY);
  1451. }
  1452. _xmemcpy (penum->m_rgFmt, m_rgFmt, (m_cFmt+1)*sizeof(FMT));
  1453. Assert (penum->m_rgFmt[penum->m_cFmt].cf==0);
  1454. *ppenum = penum;
  1455. return NOERROR;
  1456. }
  1457. //+-------------------------------------------------------------------------
  1458. //
  1459. // Member: CEnumFmt10::Release
  1460. //
  1461. // Synopsis: decrements the reference count
  1462. //
  1463. // Effects: may delete the object
  1464. //
  1465. // Arguments: void
  1466. //
  1467. // Requires:
  1468. //
  1469. // Returns: ULONG -- the new reference count
  1470. //
  1471. // Signals:
  1472. //
  1473. // Modifies:
  1474. //
  1475. // Derivation: IEnumFORMATETC
  1476. //
  1477. // Algorithm:
  1478. //
  1479. // History: dd-mmm-yy Author Comment
  1480. // 01-Dec-93 alexgo 32bit port
  1481. //
  1482. // Notes:
  1483. //
  1484. //--------------------------------------------------------------------------
  1485. #pragma SEG(CEnumFmt10_Release)
  1486. STDMETHODIMP_(ULONG) CEnumFmt10::Release(void)
  1487. {
  1488. VDATEHEAP();
  1489. M_PROLOG(this);
  1490. if (--m_cRef == 0)
  1491. {
  1492. PubMemFree(m_szClsid);
  1493. PrivMemFree(m_rgFmt);
  1494. delete this;
  1495. return 0;
  1496. }
  1497. return m_cRef;
  1498. }
  1499. //+-------------------------------------------------------------------------
  1500. //
  1501. // Member: CEnumFmt10::Dump, public (_DEBUG only)
  1502. //
  1503. // Synopsis: return a string containing the contents of the data members
  1504. //
  1505. // Effects:
  1506. //
  1507. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1508. // [ulFlag] - flag determining prefix of all newlines of the
  1509. // out character array (default is 0 - no prefix)
  1510. // [nIndentLevel] - will add a indent prefix after the other prefix
  1511. // for ALL newlines (including those with no prefix)
  1512. //
  1513. // Requires:
  1514. //
  1515. // Returns: HRESULT
  1516. //
  1517. // Signals:
  1518. //
  1519. // Modifies: [ppszDump] - argument
  1520. //
  1521. // Derivation:
  1522. //
  1523. // Algorithm: use dbgstream to create a string containing information on the
  1524. // content of data structures
  1525. //
  1526. // History: dd-mmm-yy Author Comment
  1527. // 01-Feb-95 t-ScottH author
  1528. //
  1529. // Notes:
  1530. //
  1531. //--------------------------------------------------------------------------
  1532. #ifdef _DEBUG
  1533. HRESULT CEnumFmt10::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1534. {
  1535. int i;
  1536. unsigned int ui;
  1537. char *pszPrefix;
  1538. char *pszCEnumFmt;
  1539. char *pszFMT;
  1540. dbgstream dstrPrefix;
  1541. dbgstream dstrDump;
  1542. // determine prefix of newlines
  1543. if ( ulFlag & DEB_VERBOSE )
  1544. {
  1545. dstrPrefix << this << " _VB ";
  1546. }
  1547. // determine indentation prefix for all newlines
  1548. for (i = 0; i < nIndentLevel; i++)
  1549. {
  1550. dstrPrefix << DUMPTAB;
  1551. }
  1552. pszPrefix = dstrPrefix.str();
  1553. // put data members in stream
  1554. pszCEnumFmt = DumpCEnumFmt((CEnumFmt *)this, ulFlag, nIndentLevel + 1);
  1555. dstrDump << pszPrefix << "CEnumFmt: " << endl;
  1556. dstrDump << pszCEnumFmt;
  1557. CoTaskMemFree(pszCEnumFmt);
  1558. dstrDump << pszPrefix << "No. in FMT array = " << (UINT) m_cFmt << endl;
  1559. for (ui = 0; ui < m_cFmt; ui++)
  1560. {
  1561. pszFMT = DumpFMT(&m_rgFmt[ui], ulFlag, nIndentLevel + 1);
  1562. dstrDump << pszPrefix << "FMT [" << ui << "]: " << endl;
  1563. dstrDump << pszFMT;
  1564. CoTaskMemFree(pszFMT);
  1565. }
  1566. // cleanup and provide pointer to character array
  1567. *ppszDump = dstrDump.str();
  1568. if (*ppszDump == NULL)
  1569. {
  1570. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1571. }
  1572. CoTaskMemFree(pszPrefix);
  1573. return NOERROR;
  1574. }
  1575. #endif // _DEBUG
  1576. //+-------------------------------------------------------------------------
  1577. //
  1578. // Function: DumpCEnumFmt10, public (_DEBUG only)
  1579. //
  1580. // Synopsis: calls the CEnunFmt10::Dump method, takes care of errors and
  1581. // returns the zero terminated string
  1582. //
  1583. // Effects:
  1584. //
  1585. // Arguments: [pEF] - pointer to CEnumFmt10
  1586. // [ulFlag] - flag determining prefix of all newlines of the
  1587. // out character array (default is 0 - no prefix)
  1588. // [nIndentLevel] - will add a indent prefix after the other prefix
  1589. // for ALL newlines (including those with no prefix)
  1590. //
  1591. // Requires:
  1592. //
  1593. // Returns: character array of structure dump or error (null terminated)
  1594. //
  1595. // Signals:
  1596. //
  1597. // Modifies:
  1598. //
  1599. // Algorithm:
  1600. //
  1601. // History: dd-mmm-yy Author Comment
  1602. // 01-Feb-95 t-ScottH author
  1603. //
  1604. // Notes:
  1605. //
  1606. //--------------------------------------------------------------------------
  1607. #ifdef _DEBUG
  1608. char *DumpCEnumFmt10(CEnumFmt10 *pEF, ULONG ulFlag, int nIndentLevel)
  1609. {
  1610. HRESULT hresult;
  1611. char *pszDump;
  1612. if (pEF == NULL)
  1613. {
  1614. return UtDupStringA(szDumpBadPtr);
  1615. }
  1616. hresult = pEF->Dump(&pszDump, ulFlag, nIndentLevel);
  1617. if (hresult != NOERROR)
  1618. {
  1619. CoTaskMemFree(pszDump);
  1620. return DumpHRESULT(hresult);
  1621. }
  1622. return pszDump;
  1623. }
  1624. #endif // _DEBUG
  1625. //+-------------------------------------------------------------------------
  1626. //
  1627. // Function: DumpFMT, public (_DEBUG only)
  1628. //
  1629. // Synopsis: returns a string containing the contents of the data members
  1630. //
  1631. // Effects:
  1632. //
  1633. // Arguments: [pFMT] - a pointer to a FMT object
  1634. // [ulFlag] - a flag determining the prefix of all newlines of
  1635. // the out character array(default is 0 -no prefix)
  1636. // [nIndentLevel] - will add an indent prefix after the other prefix
  1637. // for all newlines(include those with no prefix)
  1638. //
  1639. // Requires:
  1640. //
  1641. // Returns: character array of structure dump or error (null terminated)
  1642. //
  1643. // Signals:
  1644. //
  1645. // Modifies:
  1646. //
  1647. // Algorithm:
  1648. //
  1649. // History: dd-mmm-yy Author Comment
  1650. // 23-Jan-95 t-ScottH author
  1651. //
  1652. // Notes:
  1653. //
  1654. //--------------------------------------------------------------------------
  1655. #ifdef _DEBUG
  1656. char *DumpFMT(FMT *pFMT, ULONG ulFlag, int nIndentLevel)
  1657. {
  1658. int i;
  1659. char *pszPrefix;
  1660. char *pszDump;
  1661. char *pszCLIPFORMAT;
  1662. dbgstream dstrPrefix;
  1663. dbgstream dstrDump;
  1664. if (pFMT == NULL)
  1665. {
  1666. return UtDupStringA(szDumpBadPtr);
  1667. }
  1668. // determine prefix
  1669. if ( ulFlag & DEB_VERBOSE )
  1670. {
  1671. dstrPrefix << pFMT << " _VB ";
  1672. }
  1673. // determine indentation prefix
  1674. for (i = 0; i < nIndentLevel; i++)
  1675. {
  1676. dstrPrefix << DUMPTAB;
  1677. }
  1678. pszPrefix = dstrPrefix.str();
  1679. // put data members in stream
  1680. pszCLIPFORMAT = DumpCLIPFORMAT(pFMT->cf);
  1681. dstrDump << pszPrefix << "Clip format = " << pszCLIPFORMAT << endl;
  1682. CoTaskMemFree(pszCLIPFORMAT);
  1683. dstrDump << pszPrefix << "Dword = " << pFMT->dw << endl;
  1684. // cleanup and provide pointer to character array
  1685. pszDump = dstrDump.str();
  1686. if (pszDump == NULL)
  1687. {
  1688. pszDump = UtDupStringA(szDumpErrorMessage);
  1689. }
  1690. CoTaskMemFree(pszPrefix);
  1691. return pszDump;
  1692. }
  1693. #endif // _DEBUG
  1694. //+-------------------------------------------------------------------------
  1695. //
  1696. // Function: DumpFMTCACHE, public (_DEBUG only)
  1697. //
  1698. // Synopsis: returns a string containing the contents of the data members
  1699. //
  1700. // Effects:
  1701. //
  1702. // Arguments: [pFMT] - a pointer to a FMTCACHE object
  1703. // [ulFlag] - a flag determining the prefix of all newlines of
  1704. // the out character array(default is 0 -no prefix)
  1705. // [nIndentLevel] - will add an indent prefix after the other prefix
  1706. // for all newlines(include those with no prefix)
  1707. //
  1708. // Requires:
  1709. //
  1710. // Returns: character array of structure dump or error (null terminated)
  1711. //
  1712. // Signals:
  1713. //
  1714. // Modifies:
  1715. //
  1716. // Algorithm:
  1717. //
  1718. // History: dd-mmm-yy Author Comment
  1719. // 23-Jan-95 t-ScottH author
  1720. //
  1721. // Notes:
  1722. //
  1723. //--------------------------------------------------------------------------
  1724. #ifdef _DEBUG
  1725. char *DumpFMTCACHE(FMTCACHE *pFMT, ULONG ulFlag, int nIndentLevel)
  1726. {
  1727. int i;
  1728. char *pszPrefix;
  1729. char *pszDump;
  1730. char *pszFORMATETC;
  1731. char *pszDVASPECT;
  1732. dbgstream dstrPrefix;
  1733. dbgstream dstrDump;
  1734. if (pFMT == NULL)
  1735. {
  1736. return UtDupStringA(szDumpBadPtr);
  1737. }
  1738. // determine prefix
  1739. if ( ulFlag & DEB_VERBOSE )
  1740. {
  1741. dstrPrefix << pFMT << " _VB ";
  1742. }
  1743. // determine indentation prefix
  1744. for (i = 0; i < nIndentLevel; i++)
  1745. {
  1746. dstrPrefix << DUMPTAB;
  1747. }
  1748. pszPrefix = dstrPrefix.str();
  1749. // put data members in stream
  1750. pszFORMATETC = DumpFORMATETC(&pFMT->fmt, ulFlag, nIndentLevel);
  1751. dstrDump << pszPrefix << "FORMATETC: " << endl;
  1752. dstrDump << pszFORMATETC;
  1753. CoTaskMemFree(pszFORMATETC);
  1754. pszDVASPECT = DumpDVASPECTFlags(pFMT->dwAspects);
  1755. dstrDump << pszPrefix << "Aspect flags: = " << pszDVASPECT << endl;
  1756. CoTaskMemFree(pszDVASPECT);
  1757. dstrDump << pszPrefix << "IsCacheValid? = ";
  1758. if (pFMT->fUseMe == TRUE)
  1759. {
  1760. dstrDump << "TRUE" << endl;
  1761. }
  1762. else
  1763. {
  1764. dstrDump << "FALSE" << endl;
  1765. }
  1766. // cleanup and provide pointer to character array
  1767. pszDump = dstrDump.str();
  1768. if (pszDump == NULL)
  1769. {
  1770. pszDump = UtDupStringA(szDumpErrorMessage);
  1771. }
  1772. CoTaskMemFree(pszPrefix);
  1773. return pszDump;
  1774. }
  1775. #endif // _DEBUG