aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ecore_win32/ecore_win32_dnd_enumformatetc.cpp
blob: a3858bcdd875f1fa612fae72535e477653bebe33 (plain) (blame)
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;
}