Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / FileManager / EnumFormatEtc.cpp
1 // EnumFormatEtc.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "EnumFormatEtc.h"\r
6 #include "MyCom2.h"\r
7 \r
8 class CEnumFormatEtc :\r
9 public IEnumFORMATETC,\r
10 public CMyUnknownImp\r
11 {\r
12 public:\r
13   MY_UNKNOWN_IMP1_MT(IEnumFORMATETC)\r
14     \r
15   STDMETHOD(Next)(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);\r
16   STDMETHOD(Skip)(ULONG celt);\r
17   STDMETHOD(Reset)(void);\r
18   STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);\r
19   \r
20   CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats);\r
21   ~CEnumFormatEtc();\r
22   \r
23 private:\r
24   LONG m_RefCount;\r
25   ULONG m_NumFormats;\r
26   FORMATETC *m_Formats;\r
27   ULONG m_Index;\r
28 };\r
29 \r
30 static void DeepCopyFormatEtc(FORMATETC *dest, const FORMATETC *src)\r
31 {\r
32   *dest = *src;\r
33   if(src->ptd)\r
34   {\r
35     dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));\r
36     *(dest->ptd) = *(src->ptd);\r
37   }\r
38 }\r
39 \r
40 CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats)\r
41 {\r
42   m_RefCount = 1;\r
43   m_Index = 0;\r
44   m_NumFormats = 0;\r
45   m_Formats = new FORMATETC[numFormats];\r
46   if(m_Formats)\r
47   {\r
48     m_NumFormats = numFormats;\r
49     for(ULONG i = 0; i < numFormats; i++)\r
50       DeepCopyFormatEtc(&m_Formats[i], &pFormatEtc[i]);\r
51   }\r
52 }\r
53 \r
54 CEnumFormatEtc::~CEnumFormatEtc()\r
55 {\r
56   if(m_Formats)\r
57   {\r
58     for(ULONG i = 0; i < m_NumFormats; i++)\r
59       if(m_Formats[i].ptd)\r
60         CoTaskMemFree(m_Formats[i].ptd);\r
61       delete[]m_Formats;\r
62   }\r
63 }\r
64 \r
65 STDMETHODIMP CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)\r
66 {\r
67   ULONG copied  = 0;\r
68   if(celt == 0 || pFormatEtc == 0)\r
69     return E_INVALIDARG;\r
70   while(m_Index < m_NumFormats && copied < celt)\r
71   {\r
72     DeepCopyFormatEtc(&pFormatEtc[copied], &m_Formats[m_Index]);\r
73     copied++;\r
74     m_Index++;\r
75   }\r
76   if(pceltFetched != 0)\r
77     *pceltFetched = copied;\r
78   return (copied == celt) ? S_OK : S_FALSE;\r
79 }\r
80 \r
81 STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt)\r
82 {\r
83   m_Index += celt;\r
84   return (m_Index <= m_NumFormats) ? S_OK : S_FALSE;\r
85 }\r
86 \r
87 STDMETHODIMP CEnumFormatEtc::Reset(void)\r
88 {\r
89   m_Index = 0;\r
90   return S_OK;\r
91 }\r
92 \r
93 STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc)\r
94 {\r
95   HRESULT hResult = CreateEnumFormatEtc(m_NumFormats, m_Formats, ppEnumFormatEtc);\r
96   if(hResult == S_OK)\r
97     ((CEnumFormatEtc *)*ppEnumFormatEtc)->m_Index = m_Index;\r
98   return hResult;\r
99 }\r
100 \r
101 // replacement for SHCreateStdEnumFmtEtc\r
102 HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat)\r
103 {\r
104   if(numFormats == 0 || formats == 0 || enumFormat == 0)\r
105     return E_INVALIDARG;\r
106   *enumFormat = new CEnumFormatEtc(formats, numFormats);\r
107   return (*enumFormat) ? S_OK : E_OUTOFMEMORY;\r
108 }\r