// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "tests/cefclient/browser/osr_dragdrop_win.h"

#if defined(CEF_USE_ATL)

#include <shellapi.h>
#include <shlobj.h>
#include <windowsx.h>

#include <algorithm>
#include <string>

#include "include/wrapper/cef_helpers.h"
#include "tests/cefclient/browser/bytes_write_handler.h"
#include "tests/cefclient/browser/resource.h"
#include "tests/shared/browser/util_win.h"

namespace client {

namespace {

DWORD DragOperationToDropEffect(CefRenderHandler::DragOperation allowed_ops) {
  DWORD effect = DROPEFFECT_NONE;
  if (allowed_ops & DRAG_OPERATION_COPY)
    effect |= DROPEFFECT_COPY;
  if (allowed_ops & DRAG_OPERATION_LINK)
    effect |= DROPEFFECT_LINK;
  if (allowed_ops & DRAG_OPERATION_MOVE)
    effect |= DROPEFFECT_MOVE;
  return effect;
}

CefRenderHandler::DragOperationsMask DropEffectToDragOperation(DWORD effect) {
  DWORD operation = DRAG_OPERATION_NONE;
  if (effect & DROPEFFECT_COPY)
    operation |= DRAG_OPERATION_COPY;
  if (effect & DROPEFFECT_LINK)
    operation |= DRAG_OPERATION_LINK;
  if (effect & DROPEFFECT_MOVE)
    operation |= DRAG_OPERATION_MOVE;
  return static_cast<CefRenderHandler::DragOperationsMask>(operation);
}

CefMouseEvent ToMouseEvent(POINTL p, DWORD key_state, HWND hWnd) {
  CefMouseEvent ev;
  POINT screen_point = {p.x, p.y};
  ScreenToClient(hWnd, &screen_point);
  ev.x = screen_point.x;
  ev.y = screen_point.y;
  ev.modifiers = GetCefMouseModifiers(key_state);
  return ev;
}

void GetStorageForBytes(STGMEDIUM* storage, const void* data, size_t bytes) {
  HANDLE handle = GlobalAlloc(GPTR, static_cast<int>(bytes));
  if (handle) {
    memcpy(handle, data, bytes);
  }

  storage->hGlobal = handle;
  storage->tymed = TYMED_HGLOBAL;
  storage->pUnkForRelease = NULL;
}

template <typename T>
void GetStorageForString(STGMEDIUM* stgmed, const std::basic_string<T>& data) {
  GetStorageForBytes(
      stgmed, data.c_str(),
      (data.size() + 1) * sizeof(typename std::basic_string<T>::value_type));
}

void GetStorageForFileDescriptor(STGMEDIUM* storage,
                                 const std::wstring& file_name) {
  DCHECK(!file_name.empty());
  HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));

  FILEGROUPDESCRIPTOR* descriptor =
      reinterpret_cast<FILEGROUPDESCRIPTOR*>(hdata);
  descriptor->cItems = 1;
  descriptor->fgd[0].dwFlags = FD_LINKUI;
  wcsncpy_s(descriptor->fgd[0].cFileName, MAX_PATH, file_name.c_str(),
            std::min(file_name.size(), static_cast<size_t>(MAX_PATH - 1u)));

  storage->tymed = TYMED_HGLOBAL;
  storage->hGlobal = hdata;
  storage->pUnkForRelease = NULL;
}

// Helper method for converting from text/html to MS CF_HTML.
// Documentation for the CF_HTML format is available at
// http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx
std::string HtmlToCFHtml(const std::string& html, const std::string& base_url) {
  if (html.empty())
    return std::string();

#define MAX_DIGITS 10
#define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
#define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
#define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)

  static const char* header =
      "Version:0.9\r\n"
      "StartHTML:" NUMBER_FORMAT
      "\r\n"
      "EndHTML:" NUMBER_FORMAT
      "\r\n"
      "StartFragment:" NUMBER_FORMAT
      "\r\n"
      "EndFragment:" NUMBER_FORMAT "\r\n";
  static const char* source_url_prefix = "SourceURL:";

  static const char* start_markup = "<html>\r\n<body>\r\n<!--StartFragment-->";
  static const char* end_markup = "<!--EndFragment-->\r\n</body>\r\n</html>";

  // Calculate offsets
  size_t start_html_offset =
      strlen(header) - strlen(NUMBER_FORMAT) * 4 + MAX_DIGITS * 4;
  if (!base_url.empty()) {
    start_html_offset +=
        strlen(source_url_prefix) + base_url.length() + 2;  // Add 2 for \r\n.
  }
  size_t start_fragment_offset = start_html_offset + strlen(start_markup);
  size_t end_fragment_offset = start_fragment_offset + html.length();
  size_t end_html_offset = end_fragment_offset + strlen(end_markup);
  char raw_result[1024];
  _snprintf(raw_result, sizeof(1024), header, start_html_offset,
            end_html_offset, start_fragment_offset, end_fragment_offset);
  std::string result = raw_result;
  if (!base_url.empty()) {
    result.append(source_url_prefix);
    result.append(base_url);
    result.append("\r\n");
  }
  result.append(start_markup);
  result.append(html);
  result.append(end_markup);

#undef MAX_DIGITS
#undef MAKE_NUMBER_FORMAT_1
#undef MAKE_NUMBER_FORMAT_2
#undef NUMBER_FORMAT

  return result;
}

void CFHtmlExtractMetadata(const std::string& cf_html,
                           std::string* base_url,
                           size_t* html_start,
                           size_t* fragment_start,
                           size_t* fragment_end) {
  // Obtain base_url if present.
  if (base_url) {
    static std::string src_url_str("SourceURL:");
    size_t line_start = cf_html.find(src_url_str);
    if (line_start != std::string::npos) {
      size_t src_end = cf_html.find("\n", line_start);
      size_t src_start = line_start + src_url_str.length();
      if (src_end != std::string::npos && src_start != std::string::npos) {
        *base_url = cf_html.substr(src_start, src_end - src_start);
      }
    }
  }

  // Find the markup between "<!--StartFragment-->" and "<!--EndFragment-->".
  // If the comments cannot be found, like copying from OpenOffice Writer,
  // we simply fall back to using StartFragment/EndFragment bytecount values
  // to determine the fragment indexes.
  std::string cf_html_lower = cf_html;
  size_t markup_start = cf_html_lower.find("<html", 0);
  if (html_start) {
    *html_start = markup_start;
  }
  size_t tag_start = cf_html.find("<!--StartFragment", markup_start);
  if (tag_start == std::string::npos) {
    static std::string start_fragment_str("StartFragment:");
    size_t start_fragment_start = cf_html.find(start_fragment_str);
    if (start_fragment_start != std::string::npos) {
      *fragment_start =
          static_cast<size_t>(atoi(cf_html.c_str() + start_fragment_start +
                                   start_fragment_str.length()));
    }

    static std::string end_fragment_str("EndFragment:");
    size_t end_fragment_start = cf_html.find(end_fragment_str);
    if (end_fragment_start != std::string::npos) {
      *fragment_end = static_cast<size_t>(atoi(
          cf_html.c_str() + end_fragment_start + end_fragment_str.length()));
    }
  } else {
    *fragment_start = cf_html.find('>', tag_start) + 1;
    size_t tag_end = cf_html.rfind("<!--EndFragment", std::string::npos);
    *fragment_end = cf_html.rfind('<', tag_end);
  }
}

void CFHtmlToHtml(const std::string& cf_html,
                  std::string* html,
                  std::string* base_url) {
  size_t frag_start = std::string::npos;
  size_t frag_end = std::string::npos;

  CFHtmlExtractMetadata(cf_html, base_url, NULL, &frag_start, &frag_end);

  if (html && frag_start != std::string::npos &&
      frag_end != std::string::npos) {
    *html = cf_html.substr(frag_start, frag_end - frag_start);
  }
}

const DWORD moz_url_format = ::RegisterClipboardFormat(L"text/x-moz-url");
const DWORD html_format = ::RegisterClipboardFormat(L"HTML Format");
const DWORD file_desc_format = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
const DWORD file_contents_format =
    ::RegisterClipboardFormat(CFSTR_FILECONTENTS);

bool DragDataToDataObject(CefRefPtr<CefDragData> drag_data,
                          IDataObject** data_object) {
  const int kMaxDataObjects = 10;
  FORMATETC fmtetcs[kMaxDataObjects];
  STGMEDIUM stgmeds[kMaxDataObjects];
  FORMATETC fmtetc = {0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  int curr_index = 0;
  CefString text = drag_data->GetFragmentText();
  if (!text.empty()) {
    fmtetc.cfFormat = CF_UNICODETEXT;
    fmtetcs[curr_index] = fmtetc;
    GetStorageForString(&stgmeds[curr_index], text.ToWString());
    curr_index++;
  }
  if (drag_data->IsLink() && !drag_data->GetLinkURL().empty()) {
    std::wstring x_moz_url_str = drag_data->GetLinkURL().ToWString();
    x_moz_url_str += '\n';
    x_moz_url_str += drag_data->GetLinkTitle().ToWString();
    fmtetc.cfFormat = moz_url_format;
    fmtetcs[curr_index] = fmtetc;
    GetStorageForString(&stgmeds[curr_index], x_moz_url_str);
    curr_index++;
  }
  CefString html = drag_data->GetFragmentHtml();
  if (!html.empty()) {
    CefString base_url = drag_data->GetFragmentBaseURL();
    std::string cfhtml = HtmlToCFHtml(html.ToString(), base_url.ToString());
    fmtetc.cfFormat = html_format;
    fmtetcs[curr_index] = fmtetc;
    GetStorageForString(&stgmeds[curr_index], cfhtml);
    curr_index++;
  }

  size_t bufferSize = drag_data->GetFileContents(NULL);
  if (bufferSize) {
    CefRefPtr<BytesWriteHandler> handler = new BytesWriteHandler(bufferSize);
    CefRefPtr<CefStreamWriter> writer =
        CefStreamWriter::CreateForHandler(handler.get());
    drag_data->GetFileContents(writer);
    DCHECK_EQ(handler->GetDataSize(), static_cast<int64>(bufferSize));
    CefString fileName = drag_data->GetFileName();
    GetStorageForFileDescriptor(&stgmeds[curr_index], fileName.ToWString());
    fmtetc.cfFormat = file_desc_format;
    fmtetcs[curr_index] = fmtetc;
    curr_index++;
    GetStorageForBytes(&stgmeds[curr_index], handler->GetData(),
                       handler->GetDataSize());
    fmtetc.cfFormat = file_contents_format;
    fmtetcs[curr_index] = fmtetc;
    curr_index++;
  }
  DCHECK_LT(curr_index, kMaxDataObjects);

  CComPtr<DataObjectWin> obj =
      DataObjectWin::Create(fmtetcs, stgmeds, curr_index);
  (*data_object) = obj.Detach();
  return true;
}

CefRefPtr<CefDragData> DataObjectToDragData(IDataObject* data_object) {
  CefRefPtr<CefDragData> drag_data = CefDragData::Create();
  IEnumFORMATETC* enumFormats = nullptr;
  HRESULT res = data_object->EnumFormatEtc(DATADIR_GET, &enumFormats);
  if (res != S_OK)
    return drag_data;
  enumFormats->Reset();
  const int kCelt = 10;

  ULONG celtFetched;
  do {
    celtFetched = kCelt;
    FORMATETC rgelt[kCelt];
    res = enumFormats->Next(kCelt, rgelt, &celtFetched);
    for (unsigned i = 0; i < celtFetched; i++) {
      CLIPFORMAT format = rgelt[i].cfFormat;
      if (!(format == CF_UNICODETEXT || format == CF_TEXT ||
            format == moz_url_format || format == html_format ||
            format == CF_HDROP) ||
          rgelt[i].tymed != TYMED_HGLOBAL)
        continue;
      STGMEDIUM medium;
      if (data_object->GetData(&rgelt[i], &medium) == S_OK) {
        if (!medium.hGlobal) {
          ReleaseStgMedium(&medium);
          continue;
        }
        void* hGlobal = GlobalLock(medium.hGlobal);
        if (!hGlobal) {
          ReleaseStgMedium(&medium);
          continue;
        }
        if (format == CF_UNICODETEXT) {
          CefString text;
          text.FromWString((std::wstring::value_type*)hGlobal);
          drag_data->SetFragmentText(text);
        } else if (format == CF_TEXT) {
          CefString text;
          text.FromString((std::string::value_type*)hGlobal);
          drag_data->SetFragmentText(text);
        } else if (format == moz_url_format) {
          std::wstring html((std::wstring::value_type*)hGlobal);
          size_t pos = html.rfind('\n');
          CefString url(html.substr(0, pos));
          CefString title(html.substr(pos + 1));
          drag_data->SetLinkURL(url);
          drag_data->SetLinkTitle(title);
        } else if (format == html_format) {
          std::string cf_html((std::string::value_type*)hGlobal);
          std::string base_url;
          std::string html;
          CFHtmlToHtml(cf_html, &html, &base_url);
          drag_data->SetFragmentHtml(html);
          drag_data->SetFragmentBaseURL(base_url);
        }
        if (format == CF_HDROP) {
          HDROP hdrop = (HDROP)hGlobal;
          const int kMaxFilenameLen = 4096;
          const unsigned num_files = DragQueryFileW(hdrop, 0xffffffff, 0, 0);
          for (unsigned int x = 0; x < num_files; ++x) {
            wchar_t filename[kMaxFilenameLen];
            if (!DragQueryFileW(hdrop, x, filename, kMaxFilenameLen))
              continue;
            WCHAR* name = wcsrchr(filename, '\\');
            drag_data->AddFile(filename, (name ? name + 1 : filename));
          }
        }
        if (medium.hGlobal)
          GlobalUnlock(medium.hGlobal);
        if (format == CF_HDROP)
          DragFinish((HDROP)hGlobal);
        else
          ReleaseStgMedium(&medium);
      }
    }
  } while (res == S_OK);
  enumFormats->Release();
  return drag_data;
}

}  // namespace

CComPtr<DropTargetWin> DropTargetWin::Create(OsrDragEvents* callback,
                                             HWND hWnd) {
  return CComPtr<DropTargetWin>(new DropTargetWin(callback, hWnd));
}

HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
                                 DWORD key_state,
                                 POINTL cursor_position,
                                 DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;

  CefRefPtr<CefDragData> drag_data = current_drag_data_;
  if (!drag_data) {
    drag_data = DataObjectToDragData(data_object);
  }
  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragEnter(drag_data, ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}

CefBrowserHost::DragOperationsMask DropTargetWin::StartDragging(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefDragData> drag_data,
    CefRenderHandler::DragOperationsMask allowed_ops,
    int x,
    int y) {
  CComPtr<IDataObject> dataObject;
  DWORD resEffect = DROPEFFECT_NONE;
  if (DragDataToDataObject(drag_data, &dataObject)) {
    CComPtr<DropSourceWin> dropSource = DropSourceWin::Create();
    DWORD effect = DragOperationToDropEffect(allowed_ops);
    current_drag_data_ = drag_data->Clone();
    current_drag_data_->ResetFileContents();
    HRESULT res = DoDragDrop(dataObject, dropSource, effect, &resEffect);
    if (res != DRAGDROP_S_DROP)
      resEffect = DROPEFFECT_NONE;
    current_drag_data_ = nullptr;
  }
  return DropEffectToDragOperation(resEffect);
}

HRESULT DropTargetWin::DragOver(DWORD key_state,
                                POINTL cursor_position,
                                DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;
  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDragOver(ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}

HRESULT DropTargetWin::DragLeave() {
  if (!callback_)
    return E_UNEXPECTED;
  callback_->OnDragLeave();
  return S_OK;
}

HRESULT DropTargetWin::Drop(IDataObject* data_object,
                            DWORD key_state,
                            POINTL cursor_position,
                            DWORD* effect) {
  if (!callback_)
    return E_UNEXPECTED;
  CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
  CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
  mask = callback_->OnDrop(ev, mask);
  *effect = DragOperationToDropEffect(mask);
  return S_OK;
}

CComPtr<DropSourceWin> DropSourceWin::Create() {
  return CComPtr<DropSourceWin>(new DropSourceWin());
}

HRESULT DropSourceWin::GiveFeedback(DWORD dwEffect) {
  return DRAGDROP_S_USEDEFAULTCURSORS;
}

HRESULT DropSourceWin::QueryContinueDrag(BOOL fEscapePressed,
                                         DWORD grfKeyState) {
  if (fEscapePressed) {
    return DRAGDROP_S_CANCEL;
  }

  if (!(grfKeyState & MK_LBUTTON)) {
    return DRAGDROP_S_DROP;
  }

  return S_OK;
}

HRESULT DragEnumFormatEtc::CreateEnumFormatEtc(
    UINT cfmt,
    FORMATETC* afmt,
    IEnumFORMATETC** ppEnumFormatEtc) {
  if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
    return E_INVALIDARG;

  *ppEnumFormatEtc = new DragEnumFormatEtc(afmt, cfmt);

  return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
}

HRESULT DragEnumFormatEtc::Next(ULONG celt,
                                FORMATETC* pFormatEtc,
                                ULONG* pceltFetched) {
  ULONG copied = 0;

  // copy the FORMATETC structures into the caller's buffer
  while (m_nIndex < m_nNumFormats && copied < celt) {
    DeepCopyFormatEtc(&pFormatEtc[copied], &m_pFormatEtc[m_nIndex]);
    copied++;
    m_nIndex++;
  }

  // store result
  if (pceltFetched != 0)
    *pceltFetched = copied;

  // did we copy all that was requested?
  return (copied == celt) ? S_OK : S_FALSE;
}
HRESULT DragEnumFormatEtc::Skip(ULONG celt) {
  m_nIndex += celt;
  return (m_nIndex <= m_nNumFormats) ? S_OK : S_FALSE;
}
HRESULT DragEnumFormatEtc::Reset(void) {
  m_nIndex = 0;
  return S_OK;
}
HRESULT DragEnumFormatEtc::Clone(IEnumFORMATETC** ppEnumFormatEtc) {
  HRESULT hResult;

  // make a duplicate enumerator
  hResult = CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);

  if (hResult == S_OK) {
    // manually set the index state
    reinterpret_cast<DragEnumFormatEtc*>(*ppEnumFormatEtc)->m_nIndex = m_nIndex;
  }

  return hResult;
}

DragEnumFormatEtc::DragEnumFormatEtc(FORMATETC* pFormatEtc, int nNumFormats) {
  AddRef();

  m_nIndex = 0;
  m_nNumFormats = nNumFormats;
  m_pFormatEtc = new FORMATETC[nNumFormats];

  // make a new copy of each FORMATETC structure
  for (int i = 0; i < nNumFormats; i++) {
    DeepCopyFormatEtc(&m_pFormatEtc[i], &pFormatEtc[i]);
  }
}
DragEnumFormatEtc::~DragEnumFormatEtc() {
  // first free any DVTARGETDEVICE structures
  for (ULONG i = 0; i < m_nNumFormats; i++) {
    if (m_pFormatEtc[i].ptd)
      CoTaskMemFree(m_pFormatEtc[i].ptd);
  }

  // now free the main array
  delete[] m_pFormatEtc;
}

void DragEnumFormatEtc::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 = reinterpret_cast<DVTARGETDEVICE*>(
        CoTaskMemAlloc(sizeof(DVTARGETDEVICE)));

    // copy the contents of the source DVTARGETDEVICE into dest->ptd
    *(dest->ptd) = *(source->ptd);
  }
}

CComPtr<DataObjectWin> DataObjectWin::Create(FORMATETC* fmtetc,
                                             STGMEDIUM* stgmed,
                                             int count) {
  return CComPtr<DataObjectWin>(new DataObjectWin(fmtetc, stgmed, count));
}

HRESULT DataObjectWin::GetDataHere(FORMATETC* pFormatEtc, STGMEDIUM* pmedium) {
  return E_NOTIMPL;
}

HRESULT DataObjectWin::QueryGetData(FORMATETC* pFormatEtc) {
  return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}

HRESULT DataObjectWin::GetCanonicalFormatEtc(FORMATETC* pFormatEct,
                                             FORMATETC* pFormatEtcOut) {
  pFormatEtcOut->ptd = NULL;
  return E_NOTIMPL;
}

HRESULT DataObjectWin::SetData(FORMATETC* pFormatEtc,
                               STGMEDIUM* pMedium,
                               BOOL fRelease) {
  return E_NOTIMPL;
}

HRESULT DataObjectWin::DAdvise(FORMATETC* pFormatEtc,
                               DWORD advf,
                               IAdviseSink*,
                               DWORD*) {
  return E_NOTIMPL;
}

HRESULT DataObjectWin::DUnadvise(DWORD dwConnection) {
  return E_NOTIMPL;
}

HRESULT DataObjectWin::EnumDAdvise(IEnumSTATDATA** ppEnumAdvise) {
  return E_NOTIMPL;
}

HRESULT DataObjectWin::EnumFormatEtc(DWORD dwDirection,
                                     IEnumFORMATETC** ppEnumFormatEtc) {
  return DragEnumFormatEtc::CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc,
                                                ppEnumFormatEtc);
}

HRESULT DataObjectWin::GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium) {
  int idx;

  // try to match the specified FORMATETC with one of our supported formats
  if ((idx = LookupFormatEtc(pFormatEtc)) == -1)
    return DV_E_FORMATETC;

  // found a match - transfer data into supplied storage medium
  pMedium->tymed = m_pFormatEtc[idx].tymed;
  pMedium->pUnkForRelease = 0;

  // copy the data into the caller's storage medium
  switch (m_pFormatEtc[idx].tymed) {
    case TYMED_HGLOBAL:
      pMedium->hGlobal = DupGlobalMem(m_pStgMedium[idx].hGlobal);
      break;

    default:
      return DV_E_FORMATETC;
  }
  return S_OK;
}

HGLOBAL DataObjectWin::DupGlobalMem(HGLOBAL hMem) {
  DWORD len = GlobalSize(hMem);
  PVOID source = GlobalLock(hMem);
  PVOID dest = GlobalAlloc(GMEM_FIXED, len);

  memcpy(dest, source, len);
  GlobalUnlock(hMem);
  return dest;
}

int DataObjectWin::LookupFormatEtc(FORMATETC* pFormatEtc) {
  // check each of our formats in turn to see if one matches
  for (int i = 0; i < m_nNumFormats; i++) {
    if ((m_pFormatEtc[i].tymed & pFormatEtc->tymed) &&
        m_pFormatEtc[i].cfFormat == pFormatEtc->cfFormat &&
        m_pFormatEtc[i].dwAspect == pFormatEtc->dwAspect) {
      // return index of stored format
      return i;
    }
  }

  // error, format not found
  return -1;
}

DataObjectWin::DataObjectWin(FORMATETC* fmtetc, STGMEDIUM* stgmed, int count)
    : ref_count_(0) {
  m_nNumFormats = count;

  m_pFormatEtc = new FORMATETC[count];
  m_pStgMedium = new STGMEDIUM[count];

  for (int i = 0; i < count; i++) {
    m_pFormatEtc[i] = fmtetc[i];
    m_pStgMedium[i] = stgmed[i];
  }
}

}  // namespace client

#endif  // defined(CEF_USE_ATL)
