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.

2002 lines
49 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 != OpenClassesRootKey (szKey, &hkey))
  263. {
  264. PubMemFree(szClsid);
  265. return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
  266. }
  267. if (ERROR_SUCCESS != RegOpenKeyEx (hkey, (LPOLESTR) DATA_FORMATS, 0, KEY_READ, &hkeyFmts))
  268. {
  269. CLOSE (hkey);
  270. PubMemFree(szClsid);
  271. return ReportResult(0, REGDB_E_KEYMISSING, 0, 0);
  272. }
  273. CLOSE (hkeyFmts);
  274. CLOSE (hkey);
  275. *ppenum = new FAR CEnumFmt (szClsid, dwDirection);
  276. // hook the new interface
  277. CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IEnumFORMATETC,
  278. (IUnknown **)ppenum);
  279. // do not delete szClsid. Will be deleted on Release
  280. return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
  281. }
  282. //+-------------------------------------------------------------------------
  283. //
  284. // Function: OleRegEnumFormatEtc
  285. //
  286. // Synopsis: Creates a reg db formatetc enumerator
  287. //
  288. // Effects:
  289. //
  290. // Arguments: [clsid] -- the class ID we're interested in
  291. // [dwDirection] -- either GET or SET (for the formatetc and
  292. // IDataObject->[Get|Set]Data)
  293. // [ppenum] -- where to put the enumerator
  294. //
  295. // Requires:
  296. //
  297. // Returns: HRESULT
  298. //
  299. // Signals:
  300. //
  301. // Modifies:
  302. //
  303. // Algorithm: Creates either an OLE2 enumerator or an OLE1 enumerator
  304. //
  305. // History: dd-mmm-yy Author Comment
  306. // 29-Nov-93 ChrisWe allow more than one DATADIR_* flag at a
  307. // time
  308. // 01-Dec-93 alexgo 32bit port
  309. //
  310. // Notes:
  311. //
  312. //--------------------------------------------------------------------------
  313. #pragma SEG(OleRegEnumFormatEtc)
  314. STDAPI OleRegEnumFormatEtc
  315. (REFCLSID clsid,
  316. DWORD dwDirection,
  317. LPENUMFORMATETC FAR* ppenum)
  318. {
  319. OLETRACEIN((API_OleRegEnumFormatEtc, PARAMFMT("clsid= %I, dwDirection= %x, ppenum= %p"),
  320. &clsid, dwDirection, ppenum));
  321. VDATEHEAP();
  322. HRESULT hr;
  323. VDATEPTROUT_LABEL(ppenum, LPENUMFORMATETC, errRtn, hr);
  324. *ppenum = NULL;
  325. // check that dwDirection only has valid values
  326. if (dwDirection & ~(DATADIR_GET | DATADIR_SET))
  327. {
  328. hr = ResultFromScode(E_INVALIDARG);
  329. goto errRtn;
  330. }
  331. if (CoIsOle1Class (clsid))
  332. {
  333. hr = CreateEnumFormatEtc10 (clsid, dwDirection, ppenum);
  334. }
  335. else
  336. {
  337. hr = CreateEnumFormatEtc (clsid, dwDirection, ppenum);
  338. }
  339. errRtn:
  340. OLETRACEOUT((API_OleRegEnumFormatEtc, hr));
  341. return hr;
  342. }
  343. //+-------------------------------------------------------------------------
  344. //
  345. // Member: CEnumFmt::OpenHKey
  346. //
  347. // Synopsis: Opens a the regdb and returns a handle to the formatetc's
  348. //
  349. // Effects:
  350. //
  351. // Arguments: [phkey] -- where to put the regdb handle
  352. //
  353. // Requires:
  354. //
  355. // Returns: NOERROR, REGDB_E_KEYMISSING
  356. //
  357. // Signals:
  358. //
  359. // Modifies:
  360. //
  361. // Derivation:
  362. //
  363. // Algorithm:
  364. //
  365. // History: dd-mmm-yy Author Comment
  366. // 01-Dec-93 alexgo 32bit port
  367. //
  368. // Notes:
  369. //
  370. //--------------------------------------------------------------------------
  371. #pragma SEG(CEnumFmt_OpenHKey)
  372. STDMETHODIMP CEnumFmt::OpenHKey
  373. (HKEY FAR* phkey)
  374. {
  375. VDATEHEAP();
  376. VDATEPTRIN (phkey, HKEY);
  377. OLECHAR szBuf [MAX_STR];
  378. _xstrcpy (szBuf, szClsidRoot);
  379. _xstrcat (szBuf, m_szClsid);
  380. _xstrcat (szBuf, OLESTR("\\"));
  381. _xstrcat (szBuf, DATA_FORMATS);
  382. return ERROR_SUCCESS==OpenClassesRootKey (szBuf, phkey)
  383. ? NOERROR
  384. : ResultFromScode(REGDB_E_KEYMISSING);
  385. }
  386. //+-------------------------------------------------------------------------
  387. //
  388. // Member: CEnumFmt::Reset
  389. //
  390. // Synopsis: Resets the enumerator
  391. //
  392. // Effects:
  393. //
  394. // Arguments: void
  395. //
  396. // Requires:
  397. //
  398. // Returns: NOERROR
  399. //
  400. // Signals:
  401. //
  402. // Modifies:
  403. //
  404. // Derivation: IEnumFormatEtc
  405. //
  406. // Algorithm:
  407. //
  408. // History: dd-mmm-yy Author Comment
  409. // 01-Dec-93 alexgo 32bit port
  410. //
  411. // Notes:
  412. //
  413. //--------------------------------------------------------------------------
  414. #pragma SEG(CEnumFmt_Reset)
  415. STDMETHODIMP CEnumFmt::Reset (void)
  416. {
  417. VDATEHEAP();
  418. m_iKey = 0;
  419. return NOERROR;
  420. }
  421. //+-------------------------------------------------------------------------
  422. //
  423. // Member: CEnumFmt::Skip
  424. //
  425. // Synopsis: Skips the next [c] formatetc's
  426. //
  427. // Effects:
  428. //
  429. // Arguments: [c] -- number of formatetc's to skip
  430. //
  431. // Requires:
  432. //
  433. // Returns: HRESULT
  434. //
  435. // Signals:
  436. //
  437. // Modifies:
  438. //
  439. // Derivation: IEnumFormatEtc
  440. //
  441. // Algorithm: just calls Next [c] times :)
  442. //
  443. // History: dd-mmm-yy Author Comment
  444. // 01-Dec-93 alexgo 32bit port
  445. //
  446. // Notes:
  447. //
  448. //--------------------------------------------------------------------------
  449. #pragma SEG(CEnumFmt_Skip)
  450. STDMETHODIMP CEnumFmt::Skip
  451. (ULONG c)
  452. {
  453. VDATEHEAP();
  454. ULONG i=0;
  455. FORMATETC formatetc;
  456. HRESULT hresult = NOERROR;
  457. while (i++ < c)
  458. {
  459. // There will not be a target device to free
  460. ErrRtnH (Next (1, &formatetc, NULL));
  461. }
  462. errRtn:
  463. return hresult;
  464. }
  465. //+-------------------------------------------------------------------------
  466. //
  467. // Member: CEnumFmt::Next
  468. //
  469. // Synopsis: Gets the next formatetc from teh regdb
  470. //
  471. // Effects:
  472. //
  473. // Arguments: [cfmt] -- the number of formatetc's to return
  474. // [rgfmt] -- where to put the formatetc's
  475. // [pcfmtFetched] -- where to put how many formatetc's were
  476. // actually fetched
  477. //
  478. // Requires:
  479. //
  480. // Returns: HRESULT
  481. //
  482. // Signals:
  483. //
  484. // Modifies:
  485. //
  486. // Derivation: IEnumFORMATETC
  487. //
  488. // Algorithm: In the reg db, apps may compactly specify that a formatetc
  489. // applies to multiple aspects by simply using the numeric
  490. // value of the aspects or'ed together. Since our enumerator
  491. // should give one formatetc *per* aspect, if multiple aspects
  492. // are specified, then we cache the formatetc and use it the
  493. // next time a formatetc is requested (via next or [cfmt] > 1)
  494. // That's what the m_cache stuff is all about.
  495. //
  496. // History: dd-mmm-yy Author Comment
  497. // 01-Dec-93 alexgo 32bit port
  498. //
  499. // Notes:
  500. //
  501. //--------------------------------------------------------------------------
  502. #pragma SEG(CEnumFmt_Next)
  503. STDMETHODIMP CEnumFmt::Next
  504. (ULONG cfmt,
  505. FORMATETC FAR * rgfmt,
  506. ULONG FAR* pcfmtFetched)
  507. {
  508. VDATEHEAP();
  509. OLECHAR szBuf [MAX_STR];
  510. OLECHAR szKey [80];
  511. DWORD dwAspects;
  512. LPOLESTR psz;
  513. LONG cb = 0;
  514. HKEY hkey = NULL;
  515. ULONG ifmt = 0; // number successfully fetched so far
  516. LPOLESTR szFmt = NULL;
  517. LPOLESTR szAspects = NULL;
  518. LPOLESTR szMedia = NULL;
  519. LPOLESTR szDirection = NULL;
  520. HRESULT hresult = NOERROR;
  521. RetErr (OpenHKey (&hkey));
  522. while (ifmt < cfmt)
  523. {
  524. // use the cached value (multiple aspects specified for the
  525. // formatetc.
  526. if (m_cache.fUseMe)
  527. {
  528. rgfmt[ifmt] = m_cache.fmt;
  529. rgfmt[ifmt].dwAspect = UtRightmostBit (
  530. m_cache.dwAspects);
  531. m_cache.dwAspects = UtRemoveRightmostBit (
  532. m_cache.dwAspects);
  533. if (0==m_cache.dwAspects)
  534. m_cache.fUseMe = FALSE;
  535. ifmt++;
  536. }
  537. else
  538. {
  539. wsprintf (szKey, OLESTR("%d"), m_iKey++);
  540. cb = MAX_STR;
  541. if (ERROR_SUCCESS == RegQueryValue (hkey, szKey,
  542. szBuf, &cb))
  543. {
  544. rgfmt[ifmt].ptd = NULL;
  545. rgfmt[ifmt].lindex = DEF_LINDEX;
  546. psz = szBuf;
  547. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  548. szFmt = psz;
  549. while (*psz && *psz != DELIM[0])
  550. psz++;
  551. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  552. *psz++ = OLESTR('\0');
  553. szAspects = psz;
  554. while (*psz && *psz != DELIM[0])
  555. psz++;
  556. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  557. *psz++ = OLESTR('\0');
  558. szMedia = psz;
  559. while (*psz && *psz != DELIM[0])
  560. psz++;
  561. ErrZS(*psz, REGDB_E_INVALIDVALUE);
  562. *psz++ = OLESTR('\0');
  563. szDirection = psz;
  564. // Format
  565. rgfmt [ifmt].cfFormat = _xisdigit (szFmt[0])
  566. ? (CLIPFORMAT) Atol (szFmt)
  567. : (CLIPFORMAT) RegisterClipboardFormat (szFmt);
  568. // Aspect
  569. dwAspects = Atol (szAspects);
  570. ErrZS (dwAspects, REGDB_E_INVALIDVALUE);
  571. if (UtIsSingleBit (dwAspects))
  572. {
  573. rgfmt[ifmt].dwAspect = Atol(szAspects);
  574. }
  575. else
  576. {
  577. rgfmt[ifmt].dwAspect =
  578. UtRightmostBit(dwAspects);
  579. m_cache.fmt = rgfmt[ifmt];
  580. m_cache.dwAspects =
  581. UtRemoveRightmostBit(
  582. dwAspects) & 0xf;
  583. if (m_cache.dwAspects != 0)
  584. {
  585. m_cache.fUseMe = TRUE;
  586. }
  587. }
  588. // Media
  589. rgfmt[ifmt].tymed = Atol (szMedia);
  590. if (m_cache.fUseMe)
  591. {
  592. m_cache.fmt.tymed = rgfmt[ifmt].tymed;
  593. }
  594. // Direction
  595. if ( (Atol (szDirection) & m_dwDirection) ==
  596. m_dwDirection)
  597. {
  598. // This format supports the direction
  599. // we are interested in
  600. ifmt++;
  601. }
  602. else
  603. {
  604. m_cache.fUseMe = FALSE;
  605. }
  606. }
  607. else
  608. {
  609. break; // no more entries
  610. }
  611. }// else
  612. }// while
  613. if (pcfmtFetched)
  614. {
  615. *pcfmtFetched = ifmt;
  616. }
  617. errRtn:
  618. CLOSE (hkey);
  619. if (NOERROR==hresult)
  620. {
  621. return ifmt==cfmt ? NOERROR : ResultFromScode (S_FALSE);
  622. }
  623. else
  624. {
  625. if (pcfmtFetched)
  626. {
  627. *pcfmtFetched = 0;
  628. }
  629. m_cache.fUseMe = FALSE;
  630. return hresult;
  631. }
  632. }
  633. //+-------------------------------------------------------------------------
  634. //
  635. // Member: CEnumFmt::Clone
  636. //
  637. // Synopsis: clones the enumerator
  638. //
  639. // Effects:
  640. //
  641. // Arguments: [ppenum] -- where to put the cloned enumerator
  642. //
  643. // Requires:
  644. //
  645. // Returns: NOERROR, E_OUTOFMEMORY
  646. //
  647. // Signals:
  648. //
  649. // Modifies:
  650. //
  651. // Derivation: IEnumFORMATETC
  652. //
  653. // Algorithm:
  654. //
  655. // History: dd-mmm-yy Author Comment
  656. // 01-Dec-93 alexgo 32bit port
  657. //
  658. // Notes:
  659. //
  660. //--------------------------------------------------------------------------
  661. #pragma SEG(CEnumFmt_Clone)
  662. STDMETHODIMP CEnumFmt::Clone
  663. (LPENUMFORMATETC FAR* ppenum)
  664. {
  665. VDATEHEAP();
  666. VDATEPTRIN (ppenum, LPENUMFORMATETC);
  667. *ppenum = new FAR CEnumFmt (UtDupString(m_szClsid), m_dwDirection,
  668. m_iKey);
  669. return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
  670. }
  671. //+-------------------------------------------------------------------------
  672. //
  673. // Member: CEnumFmt::QueryInterface
  674. //
  675. // Synopsis: returns supported interfaces
  676. //
  677. // Effects:
  678. //
  679. // Arguments: [iid] -- the requested interface ID
  680. // [ppv] -- where to put the interface pointer
  681. //
  682. // Requires:
  683. //
  684. // Returns:
  685. //
  686. // Signals:
  687. //
  688. // Modifies:
  689. //
  690. // Derivation: IEnumFormatEtc
  691. //
  692. // Algorithm:
  693. //
  694. // History: dd-mmm-yy Author Comment
  695. // 01-Dec-93 alexgo 32bit port
  696. //
  697. // Notes:
  698. //
  699. //--------------------------------------------------------------------------
  700. #pragma SEG(CEnumFmt_QueryInterface)
  701. STDMETHODIMP CEnumFmt::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  702. {
  703. VDATEHEAP();
  704. M_PROLOG(this);
  705. if (IsEqualIID(iid, IID_IUnknown) ||
  706. IsEqualIID(iid, IID_IEnumFORMATETC))
  707. {
  708. *ppv = this;
  709. AddRef();
  710. return NOERROR;
  711. }
  712. else
  713. {
  714. *ppv = NULL;
  715. return ResultFromScode (E_NOINTERFACE);
  716. }
  717. }
  718. //+-------------------------------------------------------------------------
  719. //
  720. // Member: CEnumFmt::AddRef
  721. //
  722. // Synopsis: Increments the reference count
  723. //
  724. // Effects:
  725. //
  726. // Arguments: void
  727. //
  728. // Requires:
  729. //
  730. // Returns: ULONG -- the new reference count
  731. //
  732. // Signals:
  733. //
  734. // Modifies:
  735. //
  736. // Derivation: IEnumFORMATETC
  737. //
  738. // Algorithm:
  739. //
  740. // History: dd-mmm-yy Author Comment
  741. // 01-Dec-93 alexgo 32bit port
  742. //
  743. // Notes:
  744. //
  745. //--------------------------------------------------------------------------
  746. #pragma SEG(CEnumFmt_AddRef)
  747. STDMETHODIMP_(ULONG) CEnumFmt::AddRef(void)
  748. {
  749. VDATEHEAP();
  750. M_PROLOG(this);
  751. return ++m_cRef;
  752. }
  753. //+-------------------------------------------------------------------------
  754. //
  755. // Member: CEnumFmt::Release
  756. //
  757. // Synopsis: decrements the reference count
  758. //
  759. // Effects: may delete this object
  760. //
  761. // Arguments: void
  762. //
  763. // Requires:
  764. //
  765. // Returns: ULONG -- the new reference count
  766. //
  767. // Signals:
  768. //
  769. // Modifies:
  770. //
  771. // Derivation: IEnumFORMATETC
  772. //
  773. // Algorithm:
  774. //
  775. // History: dd-mmm-yy Author Comment
  776. // 01-Dec-93 alexgo 32bit port
  777. //
  778. // Notes:
  779. //
  780. //--------------------------------------------------------------------------
  781. #pragma SEG(CEnumFmt_Release)
  782. STDMETHODIMP_(ULONG) CEnumFmt::Release(void)
  783. {
  784. VDATEHEAP();
  785. M_PROLOG(this);
  786. if (--m_cRef == 0)
  787. {
  788. PubMemFree(m_szClsid);
  789. delete this;
  790. return 0;
  791. }
  792. return m_cRef;
  793. }
  794. //+-------------------------------------------------------------------------
  795. //
  796. // Member: CEnumFmt::Dump, public (_DEBUG only)
  797. //
  798. // Synopsis: return a string containing the contents of the data members
  799. //
  800. // Effects:
  801. //
  802. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  803. // [ulFlag] - flag determining prefix of all newlines of the
  804. // out character array (default is 0 - no prefix)
  805. // [nIndentLevel] - will add a indent prefix after the other prefix
  806. // for ALL newlines (including those with no prefix)
  807. //
  808. // Requires:
  809. //
  810. // Returns: HRESULT
  811. //
  812. // Signals:
  813. //
  814. // Modifies: [ppszDump] - argument
  815. //
  816. // Derivation:
  817. //
  818. // Algorithm: use dbgstream to create a string containing information on the
  819. // content of data structures
  820. //
  821. // History: dd-mmm-yy Author Comment
  822. // 01-Feb-95 t-ScottH author
  823. //
  824. // Notes:
  825. //
  826. //--------------------------------------------------------------------------
  827. #ifdef _DEBUG
  828. HRESULT CEnumFmt::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  829. {
  830. int i;
  831. char *pszPrefix;
  832. char *pszFMTCACHE;
  833. dbgstream dstrPrefix;
  834. dbgstream dstrDump;
  835. // determine prefix of newlines
  836. if ( ulFlag & DEB_VERBOSE )
  837. {
  838. dstrPrefix << this << " _VB ";
  839. }
  840. // determine indentation prefix for all newlines
  841. for (i = 0; i < nIndentLevel; i++)
  842. {
  843. dstrPrefix << DUMPTAB;
  844. }
  845. pszPrefix = dstrPrefix.str();
  846. // put data members in stream
  847. dstrDump << pszPrefix << "No. of References = " << m_cRef << endl;
  848. dstrDump << pszPrefix << "CLSID string = " << m_szClsid << endl;
  849. dstrDump << pszPrefix << "Direction = " << m_dwDirection<< endl;
  850. dstrDump << pszPrefix << "Current Key Index = " << m_iKey << endl;
  851. pszFMTCACHE = DumpFMTCACHE(&m_cache, ulFlag, nIndentLevel + 1);
  852. dstrDump << pszPrefix << "FMTCACHE: " << endl;
  853. dstrDump << pszFMTCACHE;
  854. CoTaskMemFree(pszFMTCACHE);
  855. // cleanup and provide pointer to character array
  856. *ppszDump = dstrDump.str();
  857. if (*ppszDump == NULL)
  858. {
  859. *ppszDump = UtDupStringA(szDumpErrorMessage);
  860. }
  861. CoTaskMemFree(pszPrefix);
  862. return NOERROR;
  863. }
  864. #endif // _DEBUG
  865. //+-------------------------------------------------------------------------
  866. //
  867. // Function: DumpCEnumFmt, public (_DEBUG only)
  868. //
  869. // Synopsis: calls the CEnumFmt::Dump method, takes care of errors and
  870. // returns the zero terminated string
  871. //
  872. // Effects:
  873. //
  874. // Arguments: [pEF] - pointer to CEnumFmt
  875. // [ulFlag] - flag determining prefix of all newlines of the
  876. // out character array (default is 0 - no prefix)
  877. // [nIndentLevel] - will add a indent prefix after the other prefix
  878. // for ALL newlines (including those with no prefix)
  879. //
  880. // Requires:
  881. //
  882. // Returns: character array of structure dump or error (null terminated)
  883. //
  884. // Signals:
  885. //
  886. // Modifies:
  887. //
  888. // Algorithm:
  889. //
  890. // History: dd-mmm-yy Author Comment
  891. // 01-Feb-95 t-ScottH author
  892. //
  893. // Notes:
  894. //
  895. //--------------------------------------------------------------------------
  896. #ifdef _DEBUG
  897. char *DumpCEnumFmt(CEnumFmt *pEF, ULONG ulFlag, int nIndentLevel)
  898. {
  899. HRESULT hresult;
  900. char *pszDump;
  901. if (pEF == NULL)
  902. {
  903. return UtDupStringA(szDumpBadPtr);
  904. }
  905. hresult = pEF->Dump(&pszDump, ulFlag, nIndentLevel);
  906. if (hresult != NOERROR)
  907. {
  908. CoTaskMemFree(pszDump);
  909. return DumpHRESULT(hresult);
  910. }
  911. return pszDump;
  912. }
  913. #endif // _DEBUG
  914. /////////////////////////////////////////
  915. // OLE 1.0 stuff
  916. //+-------------------------------------------------------------------------
  917. //
  918. // Function: CreateEnumFormatEtc10
  919. //
  920. // Synopsis: Creates a 1.0 format enumerator
  921. //
  922. // Effects:
  923. //
  924. // Arguments: [clsid] -- the class id we're interested in
  925. // [dwDirection] -- either GET or SET
  926. // [ppenum] -- where to put the enumerator
  927. //
  928. // Requires:
  929. //
  930. // Returns: HRESULT
  931. //
  932. // Signals:
  933. //
  934. // Modifies:
  935. //
  936. // Algorithm: checks to see if the info's in the reg db, then creates
  937. // and initializes a 1.0 enumerator object. (note that there
  938. // does not *have* to be any info in the regdb, we can
  939. // InitFromScratch)
  940. //
  941. // History: dd-mmm-yy Author Comment
  942. // 01-Dec-93 alexgo 32bit port
  943. //
  944. // Notes:
  945. //
  946. //--------------------------------------------------------------------------
  947. #pragma SEG(CreateEnumFormatEtc10)
  948. static INTERNAL CreateEnumFormatEtc10
  949. (REFCLSID clsid,
  950. DWORD dwDirection,
  951. LPENUMFORMATETC FAR* ppenum)
  952. {
  953. VDATEHEAP();
  954. LPOLESTR szClsid = NULL;
  955. HKEY hkey = NULL;
  956. HKEY hkeyFmts = NULL;
  957. HRESULT hresult = NOERROR;
  958. BOOL fInReg;
  959. CEnumFmt10 FAR* penum;
  960. VDATEPTROUT (ppenum, LPENUMFORMATETC);
  961. *ppenum = NULL;
  962. RetErr (ProgIDFromCLSID (clsid, &szClsid));
  963. if (ERROR_SUCCESS != OpenClassesRootKey (szClsid, &hkey))
  964. {
  965. PubMemFree(szClsid);
  966. return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
  967. }
  968. // Does this server have "Request/SetDataFormats" keys?
  969. fInReg = (ERROR_SUCCESS == RegOpenKeyEx (hkey,
  970. OLESTR("Protocol\\StdFileEditing\\RequestDataFormats"),
  971. 0, KEY_READ,
  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. delete 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