1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
#include <ole2.h>
#include "ecore_win32_dnd_enumformatetc.h"
// structors
CEnumFormatEtc::CEnumFormatEtc(FORMATETC *format_etc, int formats_num)
: ref_count_(1)
, index_(0)
, formats_num_(formats_num)
, format_etc_(new FORMATETC[formats_num])
{
// make a new copy of each FORMATETC structure
for (unsigned int i = 0; i < formats_num_; i++)
{
DeepCopyFormatEtc(&format_etc_[i], &format_etc[i]);
}
}
CEnumFormatEtc::~CEnumFormatEtc()
{
if (format_etc_)
{
// first free any DVTARGETDEVICE structures
for (ULONG i = 0; i < formats_num_; i++)
{
if (format_etc_[i].ptd)
CoTaskMemFree(format_etc_[i].ptd);
}
// now free the main array
delete[] format_etc_;
}
}
// IUnknown
ULONG __stdcall CEnumFormatEtc::AddRef(void)
{
// increment object reference count
return InterlockedIncrement(&ref_count_);
}
ULONG __stdcall CEnumFormatEtc::Release(void)
{
// decrement object reference count
LONG count = InterlockedDecrement(&ref_count_);
if (count == 0)
{
delete this;
return 0;
}
else
{
return count;
}
}
HRESULT __stdcall CEnumFormatEtc::QueryInterface(REFIID iid, void **ppvObject)
{
// check to see what interface has been requested
if ((iid == IID_IEnumFORMATETC) || (iid == IID_IUnknown))
{
AddRef();
*ppvObject = this;
return S_OK;
}
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
}
// IEnumFormatEtc
HRESULT CEnumFormatEtc::Reset(void)
{
index_ = 0;
return S_OK;
}
HRESULT CEnumFormatEtc::Skip(ULONG celt)
{
index_ += celt;
return (index_ <= formats_num_) ? S_OK : S_FALSE;
}
HRESULT CEnumFormatEtc::Clone(IEnumFORMATETC **ppEnumFormatEtc)
{
HRESULT hResult;
// make a duplicate enumerator
hResult = CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
if (hResult == S_OK)
{
// manually set the index state
((CEnumFormatEtc *)*ppEnumFormatEtc)->index_ = index_;
}
return hResult;
}
HRESULT CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
{
ULONG copied = 0;
// validate arguments
if ((celt == 0) || (pFormatEtc == 0))
return E_INVALIDARG;
// copy the FORMATETC structures into the caller's buffer
while (index_ < formats_num_ && copied < celt)
{
DeepCopyFormatEtc(&pFormatEtc[copied], &format_etc_[index_]);
copied++;
index_++;
}
// store result
if (pceltFetched != 0)
*pceltFetched = copied;
// did we copy all that was requested?
return (copied == celt) ? S_OK : S_FALSE;
}
// external functions
void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
{
// copy the source FORMATETC into dest
*dest = *source;
if (source->ptd)
{
// allocate memory for the DVTARGETDEVICE if necessary
dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
// copy the contents of the source DVTARGETDEVICE into dest->ptd
*(dest->ptd) = *(source->ptd);
}
}
HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
{
if((cfmt == 0) || (afmt == 0) || (ppEnumFormatEtc == 0))
return E_INVALIDARG;
*ppEnumFormatEtc = new CEnumFormatEtc(afmt, cfmt);
return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
}
|