/*
 * OleUIPasteSpecial implementation
 *
 * Copyright 2006 Huw Davies
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define COBJMACROS
#define NONAMELESSUNION

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "oledlg.h"

#include "oledlg_private.h"
#include "resource.h"

#include "wine/debug.h"
#include "wine/unicode.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

typedef struct
{
    OLEUIPASTESPECIALW *ps;
    DWORD flags;
    WCHAR *source_name;
    WCHAR *link_source_name;
    WCHAR *type_name;
    WCHAR *link_type_name;
    LPOLESTR app_name;
} ps_struct_t;

static const struct ps_flag
{
    DWORD flag;
    const char *name;
} ps_flags[] = {
#define PS_FLAG_ENTRY(p) {p, #p}
    PS_FLAG_ENTRY(PSF_SHOWHELP),
    PS_FLAG_ENTRY(PSF_SELECTPASTE),
    PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
    PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
    PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
    PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
    PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
    PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
    {-1, NULL}
#undef PS_FLAG_ENTRY
};

static void dump_ps_flags(DWORD flags)
{
    char flagstr[1000] = "";

    const struct ps_flag *flag = ps_flags;
    for( ; flag->name; flag++) {
        if(flags & flag->flag) {
            strcat(flagstr, flag->name);
            strcat(flagstr, "|");
        }
    }
    TRACE("flags %08x %s\n", flags, flagstr);
}

static void dump_pastespecial(const OLEUIPASTESPECIALW *ps)
{
    INT i;
    UINT j;

    dump_ps_flags(ps->dwFlags);
    TRACE("hwnd %p caption %s hook %p custdata %lx\n",
          ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
    if(IS_INTRESOURCE(ps->lpszTemplate))
        TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
    else
        TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
    TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
          ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
          ps->arrLinkTypes, ps->cLinkTypes);
    TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
          ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
          ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
    for(i = 0; i < ps->cPasteEntries; i++)
    {
        TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
              i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
              ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
              ps->arrPasteEntries[i].fmtetc.tymed);
        TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
              debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
    }
    for(i = 0; i < ps->cLinkTypes; i++)
        TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
    for(j = 0; j < ps->cClsidExclude; j++)
        TRACE("lpClsidExclude[%u] %s\n", j, debugstr_guid(&ps->lpClsidExclude[j]));

}

static inline WCHAR *strdupAtoW(const char *str)
{
    DWORD len;
    WCHAR *ret;
    if(!str) return NULL;
    len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
    ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
    return ret;
}

static inline WCHAR *strdupW(const WCHAR *str)
{
    DWORD len;
    WCHAR *ret;
    if(!str) return NULL;
    len = lstrlenW(str) + 1;
    ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
    memcpy(ret, str, len * sizeof(WCHAR));
    return ret;
}

static void get_descriptors(HWND hdlg, ps_struct_t *ps_struct)
{
    FORMATETC fmtetc;
    STGMEDIUM stg;

    fmtetc.tymed = TYMED_HGLOBAL;
    fmtetc.dwAspect = DVASPECT_CONTENT;
    fmtetc.ptd = NULL;
    fmtetc.lindex = -1;

    fmtetc.cfFormat = cf_object_descriptor;
    if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
    {
        OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
        if(obj_desc->dwSrcOfCopy)
            ps_struct->source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
        if(obj_desc->dwFullUserTypeName)
            ps_struct->type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
        OleRegGetUserType(&obj_desc->clsid, USERCLASSTYPE_APPNAME, &ps_struct->app_name);
        /* Get the icon here.  If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
           native calls OleGetIconFromClass(obj_desc->clsid) */
        GlobalUnlock(stg.u.hGlobal);
        GlobalFree(stg.u.hGlobal);
    }
    else
    {
        /* Try to get some data using some of the other clipboard formats */
    }

    fmtetc.cfFormat = cf_link_src_descriptor;
    if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
    {
        OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
        if(obj_desc->dwSrcOfCopy)
            ps_struct->link_source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
        if(obj_desc->dwFullUserTypeName)
            ps_struct->link_type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
        GlobalUnlock(stg.u.hGlobal);
        GlobalFree(stg.u.hGlobal);
    }

    if(ps_struct->source_name == NULL && ps_struct->link_source_name == NULL)
    {
        WCHAR buf[200];
        LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_SRC, buf, sizeof(buf)/sizeof(WCHAR));
        ps_struct->source_name = strdupW(buf);
    }

    if(ps_struct->type_name == NULL && ps_struct->link_type_name == NULL)
    {
        WCHAR buf[200];
        LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_TYPE, buf, sizeof(buf)/sizeof(WCHAR));
        ps_struct->type_name = strdupW(buf);
    }
}

static BOOL add_entry_to_lb(HWND hdlg, UINT id, OLEUIPASTEENTRYW *pe)
{
    HWND hwnd = GetDlgItem(hdlg, id);
    BOOL ret = FALSE;

    /* FIXME %s handling */

    /* Note that this suffers from the same bug as native, in that if a new string
       is a substring of an already added string, then the FINDSTRING will succeed
       this is probably not what we want */
    if(SendMessageW(hwnd, LB_FINDSTRING, 0, (LPARAM)pe->lpstrFormatName) == -1)
    {
        LRESULT pos = SendMessageW(hwnd, LB_ADDSTRING, 0, (LPARAM)pe->lpstrFormatName);
        SendMessageW(hwnd, LB_SETITEMDATA, pos, (LPARAM)pe);
        ret = TRUE;
    }
    return ret;
}

static DWORD init_pastelist(HWND hdlg, OLEUIPASTESPECIALW *ps)
{
    IEnumFORMATETC *penum;
    HRESULT hr;
    FORMATETC fmts[20];
    DWORD fetched, items_added = 0;

    hr = IDataObject_EnumFormatEtc(ps->lpSrcDataObj, DATADIR_GET, &penum);
    if(FAILED(hr))
    {
        WARN("Unable to create IEnumFORMATETC\n");
        return 0;
    }

    /* The native version grabs only the first 20 fmts and we do the same */
    hr = IEnumFORMATETC_Next(penum, sizeof(fmts)/sizeof(fmts[0]), fmts, &fetched);
    TRACE("got %d formats hr %08x\n", fetched, hr);

    if(SUCCEEDED(hr))
    {
        DWORD src_fmt, req_fmt;
        for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
        {
            /* This is used by update_structure() to set nSelectedIndex on exit */
            ps->arrPasteEntries[req_fmt].dwScratchSpace = req_fmt;
            TRACE("req_fmt %x\n", ps->arrPasteEntries[req_fmt].fmtetc.cfFormat);
            for(src_fmt = 0; src_fmt < fetched; src_fmt++)
            {
                TRACE("\tenum'ed fmt %x\n", fmts[src_fmt].cfFormat);
                if(ps->arrPasteEntries[req_fmt].fmtetc.cfFormat == fmts[src_fmt].cfFormat)
                {
                    add_entry_to_lb(hdlg, IDC_PS_PASTELIST, ps->arrPasteEntries + req_fmt);
                    items_added++;
                    break;
                }
            }
        }
    }

    IEnumFORMATETC_Release(penum);
    EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTE), items_added != 0);
    return items_added;
}

static DWORD init_linklist(HWND hdlg, OLEUIPASTESPECIALW *ps)
{
    HRESULT hr;
    DWORD supported_mask = 0;
    DWORD items_added = 0;
    int link, req_fmt;
    FORMATETC fmt = {0, NULL, DVASPECT_CONTENT, -1, -1};

    for(link = 0; link < ps->cLinkTypes && link < PS_MAXLINKTYPES; link++)
    {
        fmt.cfFormat = ps->arrLinkTypes[link];
        hr = IDataObject_QueryGetData(ps->lpSrcDataObj, &fmt);
        if(hr == S_OK)
            supported_mask |= 1 << link;
    }
    TRACE("supported_mask %02x\n", supported_mask);
    for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
    {
        DWORD linktypes;
        if(ps->arrPasteEntries[req_fmt].dwFlags & OLEUIPASTE_LINKANYTYPE)
            linktypes = 0xff;
        else
            linktypes = ps->arrPasteEntries[req_fmt].dwFlags & 0xff;

        if(linktypes & supported_mask)
        {
            add_entry_to_lb(hdlg, IDC_PS_PASTELINKLIST, ps->arrPasteEntries + req_fmt);
            items_added++;
        }
    }

    EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTELINK), items_added != 0);
    return items_added;
}

/* copies src_list_id into the display list */
static void update_display_list(HWND hdlg, UINT src_list_id)
{
    LONG count, i, old_pos;
    WCHAR txt[256];
    LONG item_data;
    HWND display_list = GetDlgItem(hdlg, IDC_PS_DISPLAYLIST);
    HWND list = GetDlgItem(hdlg, src_list_id);

    old_pos = SendMessageW(display_list, LB_GETCURSEL, 0, 0);
    if(old_pos == -1) old_pos = 0;

    SendMessageW(display_list, WM_SETREDRAW, 0, 0);
    SendMessageW(display_list, LB_RESETCONTENT, 0, 0);
    count = SendMessageW(list, LB_GETCOUNT, 0, 0);
    for(i = 0; i < count; i++)
    {
        SendMessageW(list, LB_GETTEXT, i, (LPARAM)txt);
        item_data = SendMessageW(list, LB_GETITEMDATA, i, 0);
        SendMessageW(display_list, LB_INSERTSTRING, i, (LPARAM)txt);
        SendMessageW(display_list, LB_SETITEMDATA, i, item_data);
    }
    SendMessageW(display_list, LB_SETCURSEL, 0, 0);
    SendMessageW(display_list, WM_SETREDRAW, 1, 0);
    if(GetForegroundWindow() == hdlg)
        SetFocus(display_list);
}

static void init_lists(HWND hdlg, ps_struct_t *ps_struct)
{
    DWORD pastes_added = init_pastelist(hdlg, ps_struct->ps);
    DWORD links_added = init_linklist(hdlg, ps_struct->ps);
    UINT check_id, list_id;

    if((ps_struct->flags & (PSF_SELECTPASTE | PSF_SELECTPASTELINK)) == 0)
        ps_struct->flags |= PSF_SELECTPASTE;

    if(!pastes_added && !links_added)
        ps_struct->flags &= ~(PSF_SELECTPASTE | PSF_SELECTPASTELINK);
    else if(!pastes_added && (ps_struct->flags & PSF_SELECTPASTE))
    {
        ps_struct->flags &= ~PSF_SELECTPASTE;
        ps_struct->flags |= PSF_SELECTPASTELINK;
    }
    else if(!links_added && (ps_struct->flags & PSF_SELECTPASTELINK))
    {
        ps_struct->flags &= ~PSF_SELECTPASTELINK;
        ps_struct->flags |= PSF_SELECTPASTE;
    }

    check_id = 0;
    list_id = 0;
    if(ps_struct->flags & PSF_SELECTPASTE)
    {
        check_id = IDC_PS_PASTE;
        list_id = IDC_PS_PASTELIST;
    }
    else if(ps_struct->flags & PSF_SELECTPASTELINK)
    {
        check_id = IDC_PS_PASTELINK;
        list_id = IDC_PS_PASTELINKLIST;
    }

    CheckRadioButton(hdlg, IDC_PS_PASTE, IDC_PS_PASTELINK, check_id);

    if(list_id)
        update_display_list(hdlg, list_id);
    else
        EnableWindow(GetDlgItem(hdlg, IDOK), 0);
}

static void update_src_text(HWND hdlg, const ps_struct_t *ps_struct)
{
    WCHAR *str;

    if(ps_struct->flags & PSF_SELECTPASTE)
    {
        if(ps_struct->source_name)
            str = ps_struct->source_name;
        else
            str = ps_struct->link_source_name;

    }
    else
    {
        if(ps_struct->link_source_name)
            str = ps_struct->link_source_name;
        else
            str = ps_struct->source_name;

    }
    SetDlgItemTextW(hdlg, IDC_PS_SOURCETEXT, str);
}

static void update_as_icon(HWND hdlg, ps_struct_t *ps_struct)
{
    HWND icon_display = GetDlgItem(hdlg, IDC_PS_ICONDISPLAY);
    HWND display_as_icon = GetDlgItem(hdlg, IDC_PS_DISPLAYASICON);
    HWND change_icon = GetDlgItem(hdlg, IDC_PS_CHANGEICON);

    /* FIXME. No as icon handling */
    ps_struct->flags &= ~PSF_CHECKDISPLAYASICON;

    CheckDlgButton(hdlg, IDC_PS_DISPLAYASICON, ps_struct->flags & PSF_CHECKDISPLAYASICON);
    EnableWindow(display_as_icon, 0);
    ShowWindow(icon_display, SW_HIDE);
    EnableWindow(icon_display, 0);
    ShowWindow(change_icon, SW_HIDE);
    EnableWindow(change_icon, 0);
}

static void update_result_text(HWND hdlg, const ps_struct_t *ps_struct)
{
    WCHAR resource_txt[200];
    UINT res_id;
    OLEUIPASTEENTRYW *pent;
    LONG cur_sel;
    static const WCHAR percent_s[] = {'%','s',0};
    WCHAR *result_txt, *ptr;

    cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
    if(cur_sel == -1) return;
    pent = (OLEUIPASTEENTRYW*)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);

    if(ps_struct->flags & PSF_SELECTPASTE)
    {
        if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
            res_id = IDS_PS_PASTE_OBJECT_AS_ICON;
        else
            res_id = IDS_PS_PASTE_DATA;
    }
    else
    {
        if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
            res_id = IDS_PS_PASTE_LINK_OBJECT_AS_ICON;
        else
            res_id = IDS_PS_PASTE_LINK_DATA;
    }

    LoadStringW(OLEDLG_hInstance, res_id, resource_txt, sizeof(resource_txt)/sizeof(WCHAR));
    if((ptr = strstrW(resource_txt, percent_s)))
    {
        /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}.  Else sub appropriate type name */
        size_t result_txt_len = strlenW(pent->lpstrResultText);
        ptrdiff_t offs = (char*)ptr - (char*)resource_txt;
        result_txt = HeapAlloc(GetProcessHeap(), 0, (strlenW(resource_txt) + result_txt_len - 1) * sizeof(WCHAR));
        memcpy(result_txt, resource_txt, offs);
        memcpy((char*)result_txt + offs, pent->lpstrResultText, result_txt_len * sizeof(WCHAR));
        memcpy((char*)result_txt + offs + result_txt_len * sizeof(WCHAR), ptr + 2, (strlenW(ptr + 2) + 1) * sizeof(WCHAR));
    }
    else
        result_txt = resource_txt;

    SetDlgItemTextW(hdlg, IDC_PS_RESULTTEXT, result_txt);

    if(result_txt != resource_txt)
        HeapFree(GetProcessHeap(), 0, result_txt);

}

static void selection_change(HWND hdlg, ps_struct_t *ps_struct)
{
    update_as_icon(hdlg, ps_struct);
    update_result_text(hdlg, ps_struct);
}

static void mode_change(HWND hdlg, ps_struct_t *ps_struct, UINT id)
{
    if(id == IDC_PS_PASTE)
    {
        ps_struct->flags &= ~PSF_SELECTPASTELINK;
        ps_struct->flags |= PSF_SELECTPASTE;
    }
    else
    {
        ps_struct->flags &= ~PSF_SELECTPASTE;
        ps_struct->flags |= PSF_SELECTPASTELINK;
    }

    update_src_text(hdlg, ps_struct);
    update_display_list(hdlg, id == IDC_PS_PASTE ? IDC_PS_PASTELIST : IDC_PS_PASTELINKLIST);
    selection_change(hdlg, ps_struct);
}

static void post_help_msg(HWND hdlg, ps_struct_t *ps_struct)
{
    PostMessageW(ps_struct->ps->hWndOwner, oleui_msg_help, (WPARAM)hdlg, IDD_PASTESPECIAL);
}

static void send_end_dialog_msg(HWND hdlg, ps_struct_t *ps_struct, UINT id)
{
    SendMessageW(hdlg, oleui_msg_enddialog, id, 0);
}

static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
{
    LONG cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
    if(cur_sel != -1)
    {
        OLEUIPASTEENTRYW *pent;
        pent = (OLEUIPASTEENTRYW *)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
        ps_struct->ps->nSelectedIndex = pent->dwScratchSpace;
    }
    ps_struct->ps->dwFlags = ps_struct->flags;
    ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) != 0;
}

static void free_structure(ps_struct_t *ps_struct)
{
    HeapFree(GetProcessHeap(), 0, ps_struct->type_name);
    HeapFree(GetProcessHeap(), 0, ps_struct->source_name);
    HeapFree(GetProcessHeap(), 0, ps_struct->link_type_name);
    HeapFree(GetProcessHeap(), 0, ps_struct->link_source_name);
    CoTaskMemFree(ps_struct->app_name);
    HeapFree(GetProcessHeap(), 0, ps_struct);
}

static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
{
    /* native uses prop name "Structure", but we're not compatible
       with that so we'll prepend "Wine_". */
    static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
    ps_struct_t *ps_struct;

    TRACE("(%p, %04x, %08lx, %08lx)\n", hdlg, msg, wp, lp);

    ps_struct = GetPropW(hdlg, prop_name);

    if(msg != WM_INITDIALOG)
    {
        if(!ps_struct)
            return 0;

        if(ps_struct->ps->lpfnHook)
        {
            INT_PTR ret = ps_struct->ps->lpfnHook(hdlg, msg, wp, lp);
            if(ret) return ret;
        }
    }

    switch(msg)
    {
    case WM_INITDIALOG:
    {
        ps_struct = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct));
        ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
        ps_struct->type_name = NULL;
        ps_struct->source_name = NULL;
        ps_struct->link_type_name = NULL;
        ps_struct->link_source_name = NULL;
        ps_struct->app_name = NULL;
        ps_struct->flags = ps_struct->ps->dwFlags;

        SetPropW(hdlg, prop_name, ps_struct);

        if(!(ps_struct->ps->dwFlags & PSF_SHOWHELP))
        {
            ShowWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), SW_HIDE);
            EnableWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), 0);
        }

        if(ps_struct->ps->lpszCaption)
            SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);

        get_descriptors(hdlg, ps_struct);

        init_lists(hdlg, ps_struct);

        update_src_text(hdlg, ps_struct);

        selection_change(hdlg, ps_struct);

        SetFocus(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST));

        if(ps_struct->ps->lpfnHook)
            ps_struct->ps->lpfnHook(hdlg, msg, 0, 0);
        return FALSE; /* use new focus */
    }
    case WM_COMMAND:
        switch(LOWORD(wp))
        {
        case IDC_PS_DISPLAYLIST:
            switch(HIWORD(wp))
            {
            case LBN_SELCHANGE:
                selection_change(hdlg, ps_struct);
                return FALSE;
            default:
                return FALSE;
            }
        case IDC_PS_PASTE:
        case IDC_PS_PASTELINK:
            switch(HIWORD(wp))
            {
            case BN_CLICKED:
                mode_change(hdlg, ps_struct, LOWORD(wp));
                return FALSE;

            default:
                return FALSE;
            }
        case IDC_OLEUIHELP:
            switch(HIWORD(wp))
            {
            case BN_CLICKED:
                post_help_msg(hdlg, ps_struct);
                return FALSE;
            default:
                return FALSE;
            }
        case IDOK:
        case IDCANCEL:
            switch(HIWORD(wp))
            {
            case BN_CLICKED:
                send_end_dialog_msg(hdlg, ps_struct, LOWORD(wp));
                return FALSE;
            default:
                return FALSE;
            }
        }
        return FALSE;
    default:
        if(msg == oleui_msg_enddialog)
        {
            if(wp == IDOK)
                update_structure(hdlg, ps_struct);
            EndDialog(hdlg, wp);
            /* native does its cleanup in WM_DESTROY */
            RemovePropW(hdlg, prop_name);
            free_structure(ps_struct);
            return TRUE;
        }
        return FALSE;
    }

}

/***********************************************************************
 *           OleUIPasteSpecialA (OLEDLG.4)
 */
UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
{
    OLEUIPASTESPECIALW ps;
    UINT ret;
    TRACE("(%p)\n", psA);

    memcpy(&ps, psA, psA->cbStruct);

    ps.lpszCaption = strdupAtoW(psA->lpszCaption);
    if(!IS_INTRESOURCE(ps.lpszTemplate))
        ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);

    if(psA->cPasteEntries > 0)
    {
        DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
        INT i;

        ps.arrPasteEntries = HeapAlloc(GetProcessHeap(), 0, size);
        memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
        for(i = 0; i < psA->cPasteEntries; i++)
        {
            ps.arrPasteEntries[i].lpstrFormatName =
                strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
            ps.arrPasteEntries[i].lpstrResultText =
                strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
        }
    }

    ret = OleUIPasteSpecialW(&ps);

    if(psA->cPasteEntries > 0)
    {
        INT i;
        for(i = 0; i < psA->cPasteEntries; i++)
        {
            HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
            HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
        }
        HeapFree(GetProcessHeap(), 0, ps.arrPasteEntries);
    }
    if(!IS_INTRESOURCE(ps.lpszTemplate))
        HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszTemplate);
    HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszCaption);

    /* Copy back the output fields */
    psA->dwFlags = ps.dwFlags;
    psA->lpSrcDataObj = ps.lpSrcDataObj;
    psA->nSelectedIndex = ps.nSelectedIndex;
    psA->fLink = ps.fLink;
    psA->hMetaPict = ps.hMetaPict;
    psA->sizel = ps.sizel;

    return ret;
}

/***********************************************************************
 *           OleUIPasteSpecialW (OLEDLG.22)
 */
UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
{
    LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
    UINT ret;

    TRACE("(%p)\n", ps);

    if(TRACE_ON(ole)) dump_pastespecial(ps);

    if(!ps->lpSrcDataObj)
        OleGetClipboard(&ps->lpSrcDataObj);

    if(ps->hInstance || !ps->hResource)
    {
        HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
        const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
        HRSRC hrsrc;

        if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
        hrsrc = FindResourceW(hInst, name, (LPWSTR)RT_DIALOG);
        if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
        dlg_templ = LoadResource(hInst, hrsrc);
        if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
    }

    ret = DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);

    return ret;
}
