shell32/tests: Fix win8 knownfolders relative and parsed paths.
[wine.git] / dlls / oledlg / pastespl.c
blob4d3148823d052cdaceb48b664a2082f22f0ab8e7
1 /*
2 * OleUIPasteSpecial implementation
4 * Copyright 2006 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winnls.h"
33 #include "oledlg.h"
35 #include "oledlg_private.h"
36 #include "resource.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43 typedef struct
45 OLEUIPASTESPECIALW *ps;
46 DWORD flags;
47 WCHAR *source_name;
48 WCHAR *link_source_name;
49 WCHAR *type_name;
50 WCHAR *link_type_name;
51 LPOLESTR app_name;
52 } ps_struct_t;
54 static const struct ps_flag
56 DWORD flag;
57 const char *name;
58 } ps_flags[] = {
59 #define PS_FLAG_ENTRY(p) {p, #p}
60 PS_FLAG_ENTRY(PSF_SHOWHELP),
61 PS_FLAG_ENTRY(PSF_SELECTPASTE),
62 PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
63 PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
64 PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
65 PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
66 PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
67 PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
68 {-1, NULL}
69 #undef PS_FLAG_ENTRY
72 static void dump_ps_flags(DWORD flags)
74 char flagstr[1000] = "";
76 const struct ps_flag *flag = ps_flags;
77 for( ; flag->name; flag++) {
78 if(flags & flag->flag) {
79 strcat(flagstr, flag->name);
80 strcat(flagstr, "|");
83 TRACE("flags %08x %s\n", flags, flagstr);
86 static void dump_pastespecial(const OLEUIPASTESPECIALW *ps)
88 INT i;
89 UINT j;
91 dump_ps_flags(ps->dwFlags);
92 TRACE("hwnd %p caption %s hook %p custdata %lx\n",
93 ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
94 if(IS_INTRESOURCE(ps->lpszTemplate))
95 TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
96 else
97 TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
98 TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
99 ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
100 ps->arrLinkTypes, ps->cLinkTypes);
101 TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
102 ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
103 ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
104 for(i = 0; i < ps->cPasteEntries; i++)
106 TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
107 i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
108 ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
109 ps->arrPasteEntries[i].fmtetc.tymed);
110 TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
111 debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
113 for(i = 0; i < ps->cLinkTypes; i++)
114 TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
115 for(j = 0; j < ps->cClsidExclude; j++)
116 TRACE("lpClsidExclude[%u] %s\n", j, debugstr_guid(&ps->lpClsidExclude[j]));
120 static inline WCHAR *strdupAtoW(const char *str)
122 DWORD len;
123 WCHAR *ret;
124 if(!str) return NULL;
125 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
126 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
127 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
128 return ret;
131 static inline WCHAR *strdupW(const WCHAR *str)
133 DWORD len;
134 WCHAR *ret;
135 if(!str) return NULL;
136 len = lstrlenW(str) + 1;
137 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
138 memcpy(ret, str, len * sizeof(WCHAR));
139 return ret;
142 static void get_descriptors(HWND hdlg, ps_struct_t *ps_struct)
144 FORMATETC fmtetc;
145 STGMEDIUM stg;
147 fmtetc.tymed = TYMED_HGLOBAL;
148 fmtetc.dwAspect = DVASPECT_CONTENT;
149 fmtetc.ptd = NULL;
150 fmtetc.lindex = -1;
152 fmtetc.cfFormat = cf_object_descriptor;
153 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
155 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
156 if(obj_desc->dwSrcOfCopy)
157 ps_struct->source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
158 if(obj_desc->dwFullUserTypeName)
159 ps_struct->type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
160 OleRegGetUserType(&obj_desc->clsid, USERCLASSTYPE_APPNAME, &ps_struct->app_name);
161 /* Get the icon here. If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
162 native calls OleGetIconFromClass(obj_desc->clsid) */
163 GlobalUnlock(stg.u.hGlobal);
164 GlobalFree(stg.u.hGlobal);
166 else
168 /* Try to get some data using some of the other clipboard formats */
171 fmtetc.cfFormat = cf_link_src_descriptor;
172 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
174 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
175 if(obj_desc->dwSrcOfCopy)
176 ps_struct->link_source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
177 if(obj_desc->dwFullUserTypeName)
178 ps_struct->link_type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
179 GlobalUnlock(stg.u.hGlobal);
180 GlobalFree(stg.u.hGlobal);
183 if(ps_struct->source_name == NULL && ps_struct->link_source_name == NULL)
185 WCHAR buf[200];
186 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_SRC, buf, sizeof(buf)/sizeof(WCHAR));
187 ps_struct->source_name = strdupW(buf);
190 if(ps_struct->type_name == NULL && ps_struct->link_type_name == NULL)
192 WCHAR buf[200];
193 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_TYPE, buf, sizeof(buf)/sizeof(WCHAR));
194 ps_struct->type_name = strdupW(buf);
198 static BOOL add_entry_to_lb(HWND hdlg, UINT id, OLEUIPASTEENTRYW *pe)
200 HWND hwnd = GetDlgItem(hdlg, id);
201 BOOL ret = FALSE;
203 /* FIXME %s handling */
205 /* Note that this suffers from the same bug as native, in that if a new string
206 is a substring of an already added string, then the FINDSTRING will succeed
207 this is probably not what we want */
208 if(SendMessageW(hwnd, LB_FINDSTRING, 0, (LPARAM)pe->lpstrFormatName) == -1)
210 LRESULT pos = SendMessageW(hwnd, LB_ADDSTRING, 0, (LPARAM)pe->lpstrFormatName);
211 SendMessageW(hwnd, LB_SETITEMDATA, pos, (LPARAM)pe);
212 ret = TRUE;
214 return ret;
217 static DWORD init_pastelist(HWND hdlg, OLEUIPASTESPECIALW *ps)
219 IEnumFORMATETC *penum;
220 HRESULT hr;
221 FORMATETC fmts[20];
222 DWORD fetched, items_added = 0;
224 hr = IDataObject_EnumFormatEtc(ps->lpSrcDataObj, DATADIR_GET, &penum);
225 if(FAILED(hr))
227 WARN("Unable to create IEnumFORMATETC\n");
228 return 0;
231 /* The native version grabs only the first 20 fmts and we do the same */
232 hr = IEnumFORMATETC_Next(penum, sizeof(fmts)/sizeof(fmts[0]), fmts, &fetched);
233 TRACE("got %d formats hr %08x\n", fetched, hr);
235 if(SUCCEEDED(hr))
237 DWORD src_fmt, req_fmt;
238 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
240 /* This is used by update_structure() to set nSelectedIndex on exit */
241 ps->arrPasteEntries[req_fmt].dwScratchSpace = req_fmt;
242 TRACE("req_fmt %x\n", ps->arrPasteEntries[req_fmt].fmtetc.cfFormat);
243 for(src_fmt = 0; src_fmt < fetched; src_fmt++)
245 TRACE("\tenum'ed fmt %x\n", fmts[src_fmt].cfFormat);
246 if(ps->arrPasteEntries[req_fmt].fmtetc.cfFormat == fmts[src_fmt].cfFormat)
248 add_entry_to_lb(hdlg, IDC_PS_PASTELIST, ps->arrPasteEntries + req_fmt);
249 items_added++;
250 break;
256 IEnumFORMATETC_Release(penum);
257 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTE), items_added != 0);
258 return items_added;
261 static DWORD init_linklist(HWND hdlg, OLEUIPASTESPECIALW *ps)
263 HRESULT hr;
264 DWORD supported_mask = 0;
265 DWORD items_added = 0;
266 int link, req_fmt;
267 FORMATETC fmt = {0, NULL, DVASPECT_CONTENT, -1, -1};
269 for(link = 0; link < ps->cLinkTypes && link < PS_MAXLINKTYPES; link++)
271 fmt.cfFormat = ps->arrLinkTypes[link];
272 hr = IDataObject_QueryGetData(ps->lpSrcDataObj, &fmt);
273 if(hr == S_OK)
274 supported_mask |= 1 << link;
276 TRACE("supported_mask %02x\n", supported_mask);
277 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
279 DWORD linktypes;
280 if(ps->arrPasteEntries[req_fmt].dwFlags & OLEUIPASTE_LINKANYTYPE)
281 linktypes = 0xff;
282 else
283 linktypes = ps->arrPasteEntries[req_fmt].dwFlags & 0xff;
285 if(linktypes & supported_mask)
287 add_entry_to_lb(hdlg, IDC_PS_PASTELINKLIST, ps->arrPasteEntries + req_fmt);
288 items_added++;
292 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTELINK), items_added != 0);
293 return items_added;
296 /* copies src_list_id into the display list */
297 static void update_display_list(HWND hdlg, UINT src_list_id)
299 LONG count, i, old_pos;
300 WCHAR txt[256];
301 LONG item_data;
302 HWND display_list = GetDlgItem(hdlg, IDC_PS_DISPLAYLIST);
303 HWND list = GetDlgItem(hdlg, src_list_id);
305 old_pos = SendMessageW(display_list, LB_GETCURSEL, 0, 0);
306 if(old_pos == -1) old_pos = 0;
308 SendMessageW(display_list, WM_SETREDRAW, 0, 0);
309 SendMessageW(display_list, LB_RESETCONTENT, 0, 0);
310 count = SendMessageW(list, LB_GETCOUNT, 0, 0);
311 for(i = 0; i < count; i++)
313 SendMessageW(list, LB_GETTEXT, i, (LPARAM)txt);
314 item_data = SendMessageW(list, LB_GETITEMDATA, i, 0);
315 SendMessageW(display_list, LB_INSERTSTRING, i, (LPARAM)txt);
316 SendMessageW(display_list, LB_SETITEMDATA, i, item_data);
318 SendMessageW(display_list, LB_SETCURSEL, 0, 0);
319 SendMessageW(display_list, WM_SETREDRAW, 1, 0);
320 if(GetForegroundWindow() == hdlg)
321 SetFocus(display_list);
324 static void init_lists(HWND hdlg, ps_struct_t *ps_struct)
326 DWORD pastes_added = init_pastelist(hdlg, ps_struct->ps);
327 DWORD links_added = init_linklist(hdlg, ps_struct->ps);
328 UINT check_id, list_id;
330 if((ps_struct->flags & (PSF_SELECTPASTE | PSF_SELECTPASTELINK)) == 0)
331 ps_struct->flags |= PSF_SELECTPASTE;
333 if(!pastes_added && !links_added)
334 ps_struct->flags &= ~(PSF_SELECTPASTE | PSF_SELECTPASTELINK);
335 else if(!pastes_added && (ps_struct->flags & PSF_SELECTPASTE))
337 ps_struct->flags &= ~PSF_SELECTPASTE;
338 ps_struct->flags |= PSF_SELECTPASTELINK;
340 else if(!links_added && (ps_struct->flags & PSF_SELECTPASTELINK))
342 ps_struct->flags &= ~PSF_SELECTPASTELINK;
343 ps_struct->flags |= PSF_SELECTPASTE;
346 check_id = 0;
347 list_id = 0;
348 if(ps_struct->flags & PSF_SELECTPASTE)
350 check_id = IDC_PS_PASTE;
351 list_id = IDC_PS_PASTELIST;
353 else if(ps_struct->flags & PSF_SELECTPASTELINK)
355 check_id = IDC_PS_PASTELINK;
356 list_id = IDC_PS_PASTELINKLIST;
359 CheckRadioButton(hdlg, IDC_PS_PASTE, IDC_PS_PASTELINK, check_id);
361 if(list_id)
362 update_display_list(hdlg, list_id);
363 else
364 EnableWindow(GetDlgItem(hdlg, IDOK), 0);
367 static void update_src_text(HWND hdlg, const ps_struct_t *ps_struct)
369 WCHAR *str;
371 if(ps_struct->flags & PSF_SELECTPASTE)
373 if(ps_struct->source_name)
374 str = ps_struct->source_name;
375 else
376 str = ps_struct->link_source_name;
379 else
381 if(ps_struct->link_source_name)
382 str = ps_struct->link_source_name;
383 else
384 str = ps_struct->source_name;
387 SetDlgItemTextW(hdlg, IDC_PS_SOURCETEXT, str);
390 static void update_as_icon(HWND hdlg, ps_struct_t *ps_struct)
392 HWND icon_display = GetDlgItem(hdlg, IDC_PS_ICONDISPLAY);
393 HWND display_as_icon = GetDlgItem(hdlg, IDC_PS_DISPLAYASICON);
394 HWND change_icon = GetDlgItem(hdlg, IDC_PS_CHANGEICON);
396 /* FIXME. No as icon handling */
397 ps_struct->flags &= ~PSF_CHECKDISPLAYASICON;
399 CheckDlgButton(hdlg, IDC_PS_DISPLAYASICON, ps_struct->flags & PSF_CHECKDISPLAYASICON);
400 EnableWindow(display_as_icon, 0);
401 ShowWindow(icon_display, SW_HIDE);
402 EnableWindow(icon_display, 0);
403 ShowWindow(change_icon, SW_HIDE);
404 EnableWindow(change_icon, 0);
407 static void update_result_text(HWND hdlg, const ps_struct_t *ps_struct)
409 WCHAR resource_txt[200];
410 UINT res_id;
411 OLEUIPASTEENTRYW *pent;
412 LONG cur_sel;
413 static const WCHAR percent_s[] = {'%','s',0};
414 WCHAR *result_txt, *ptr;
416 cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
417 if(cur_sel == -1) return;
418 pent = (OLEUIPASTEENTRYW*)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
420 if(ps_struct->flags & PSF_SELECTPASTE)
422 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
423 res_id = IDS_PS_PASTE_OBJECT_AS_ICON;
424 else
425 res_id = IDS_PS_PASTE_DATA;
427 else
429 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
430 res_id = IDS_PS_PASTE_LINK_OBJECT_AS_ICON;
431 else
432 res_id = IDS_PS_PASTE_LINK_DATA;
435 LoadStringW(OLEDLG_hInstance, res_id, resource_txt, sizeof(resource_txt)/sizeof(WCHAR));
436 if((ptr = strstrW(resource_txt, percent_s)))
438 /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}. Else sub appropriate type name */
439 size_t result_txt_len = strlenW(pent->lpstrResultText);
440 ptrdiff_t offs = (char*)ptr - (char*)resource_txt;
441 result_txt = HeapAlloc(GetProcessHeap(), 0, (strlenW(resource_txt) + result_txt_len - 1) * sizeof(WCHAR));
442 memcpy(result_txt, resource_txt, offs);
443 memcpy((char*)result_txt + offs, pent->lpstrResultText, result_txt_len * sizeof(WCHAR));
444 memcpy((char*)result_txt + offs + result_txt_len * sizeof(WCHAR), ptr + 2, (strlenW(ptr + 2) + 1) * sizeof(WCHAR));
446 else
447 result_txt = resource_txt;
449 SetDlgItemTextW(hdlg, IDC_PS_RESULTTEXT, result_txt);
451 if(result_txt != resource_txt)
452 HeapFree(GetProcessHeap(), 0, result_txt);
456 static void selection_change(HWND hdlg, ps_struct_t *ps_struct)
458 update_as_icon(hdlg, ps_struct);
459 update_result_text(hdlg, ps_struct);
462 static void mode_change(HWND hdlg, ps_struct_t *ps_struct, UINT id)
464 if(id == IDC_PS_PASTE)
466 ps_struct->flags &= ~PSF_SELECTPASTELINK;
467 ps_struct->flags |= PSF_SELECTPASTE;
469 else
471 ps_struct->flags &= ~PSF_SELECTPASTE;
472 ps_struct->flags |= PSF_SELECTPASTELINK;
475 update_src_text(hdlg, ps_struct);
476 update_display_list(hdlg, id == IDC_PS_PASTE ? IDC_PS_PASTELIST : IDC_PS_PASTELINKLIST);
477 selection_change(hdlg, ps_struct);
480 static void post_help_msg(HWND hdlg, ps_struct_t *ps_struct)
482 PostMessageW(ps_struct->ps->hWndOwner, oleui_msg_help, (WPARAM)hdlg, IDD_PASTESPECIAL);
485 static void send_end_dialog_msg(HWND hdlg, ps_struct_t *ps_struct, UINT id)
487 SendMessageW(hdlg, oleui_msg_enddialog, id, 0);
490 static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
492 LONG cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
493 if(cur_sel != -1)
495 OLEUIPASTEENTRYW *pent;
496 pent = (OLEUIPASTEENTRYW *)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
497 ps_struct->ps->nSelectedIndex = pent->dwScratchSpace;
499 ps_struct->ps->dwFlags = ps_struct->flags;
500 ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) != 0;
503 static void free_structure(ps_struct_t *ps_struct)
505 HeapFree(GetProcessHeap(), 0, ps_struct->type_name);
506 HeapFree(GetProcessHeap(), 0, ps_struct->source_name);
507 HeapFree(GetProcessHeap(), 0, ps_struct->link_type_name);
508 HeapFree(GetProcessHeap(), 0, ps_struct->link_source_name);
509 CoTaskMemFree(ps_struct->app_name);
510 HeapFree(GetProcessHeap(), 0, ps_struct);
513 static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
515 /* native uses prop name "Structure", but we're not compatible
516 with that so we'll prepend "Wine_". */
517 static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
518 ps_struct_t *ps_struct;
520 TRACE("(%p, %04x, %08lx, %08lx)\n", hdlg, msg, wp, lp);
522 ps_struct = GetPropW(hdlg, prop_name);
524 if(msg != WM_INITDIALOG)
526 if(!ps_struct)
527 return 0;
529 if(ps_struct->ps->lpfnHook)
531 INT_PTR ret = ps_struct->ps->lpfnHook(hdlg, msg, wp, lp);
532 if(ret) return ret;
536 switch(msg)
538 case WM_INITDIALOG:
540 ps_struct = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct));
541 ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
542 ps_struct->type_name = NULL;
543 ps_struct->source_name = NULL;
544 ps_struct->link_type_name = NULL;
545 ps_struct->link_source_name = NULL;
546 ps_struct->app_name = NULL;
547 ps_struct->flags = ps_struct->ps->dwFlags;
549 SetPropW(hdlg, prop_name, ps_struct);
551 if(!(ps_struct->ps->dwFlags & PSF_SHOWHELP))
553 ShowWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), SW_HIDE);
554 EnableWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), 0);
557 if(ps_struct->ps->lpszCaption)
558 SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);
560 get_descriptors(hdlg, ps_struct);
562 init_lists(hdlg, ps_struct);
564 update_src_text(hdlg, ps_struct);
566 selection_change(hdlg, ps_struct);
568 SetFocus(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST));
570 if(ps_struct->ps->lpfnHook)
571 ps_struct->ps->lpfnHook(hdlg, msg, 0, 0);
572 return FALSE; /* use new focus */
574 case WM_COMMAND:
575 switch(LOWORD(wp))
577 case IDC_PS_DISPLAYLIST:
578 switch(HIWORD(wp))
580 case LBN_SELCHANGE:
581 selection_change(hdlg, ps_struct);
582 return FALSE;
583 default:
584 return FALSE;
586 case IDC_PS_PASTE:
587 case IDC_PS_PASTELINK:
588 switch(HIWORD(wp))
590 case BN_CLICKED:
591 mode_change(hdlg, ps_struct, LOWORD(wp));
592 return FALSE;
594 default:
595 return FALSE;
597 case IDC_OLEUIHELP:
598 switch(HIWORD(wp))
600 case BN_CLICKED:
601 post_help_msg(hdlg, ps_struct);
602 return FALSE;
603 default:
604 return FALSE;
606 case IDOK:
607 case IDCANCEL:
608 switch(HIWORD(wp))
610 case BN_CLICKED:
611 send_end_dialog_msg(hdlg, ps_struct, LOWORD(wp));
612 return FALSE;
613 default:
614 return FALSE;
617 return FALSE;
618 default:
619 if(msg == oleui_msg_enddialog)
621 if(wp == IDOK)
622 update_structure(hdlg, ps_struct);
623 EndDialog(hdlg, wp);
624 /* native does its cleanup in WM_DESTROY */
625 RemovePropW(hdlg, prop_name);
626 free_structure(ps_struct);
627 return TRUE;
629 return FALSE;
634 /***********************************************************************
635 * OleUIPasteSpecialA (OLEDLG.4)
637 UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
639 OLEUIPASTESPECIALW ps;
640 UINT ret;
641 TRACE("(%p)\n", psA);
643 memcpy(&ps, psA, psA->cbStruct);
645 ps.lpszCaption = strdupAtoW(psA->lpszCaption);
646 if(!IS_INTRESOURCE(ps.lpszTemplate))
647 ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);
649 if(psA->cPasteEntries > 0)
651 DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
652 INT i;
654 ps.arrPasteEntries = HeapAlloc(GetProcessHeap(), 0, size);
655 memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
656 for(i = 0; i < psA->cPasteEntries; i++)
658 ps.arrPasteEntries[i].lpstrFormatName =
659 strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
660 ps.arrPasteEntries[i].lpstrResultText =
661 strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
665 ret = OleUIPasteSpecialW(&ps);
667 if(psA->cPasteEntries > 0)
669 INT i;
670 for(i = 0; i < psA->cPasteEntries; i++)
672 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
673 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
675 HeapFree(GetProcessHeap(), 0, ps.arrPasteEntries);
677 if(!IS_INTRESOURCE(ps.lpszTemplate))
678 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszTemplate);
679 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszCaption);
681 /* Copy back the output fields */
682 psA->dwFlags = ps.dwFlags;
683 psA->lpSrcDataObj = ps.lpSrcDataObj;
684 psA->nSelectedIndex = ps.nSelectedIndex;
685 psA->fLink = ps.fLink;
686 psA->hMetaPict = ps.hMetaPict;
687 psA->sizel = ps.sizel;
689 return ret;
692 /***********************************************************************
693 * OleUIPasteSpecialW (OLEDLG.22)
695 UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
697 LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
698 UINT ret;
700 TRACE("(%p)\n", ps);
702 if(TRACE_ON(ole)) dump_pastespecial(ps);
704 if(!ps->lpSrcDataObj)
705 OleGetClipboard(&ps->lpSrcDataObj);
707 if(ps->hInstance || !ps->hResource)
709 HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
710 const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
711 HRSRC hrsrc;
713 if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
714 hrsrc = FindResourceW(hInst, name, (LPWSTR)RT_DIALOG);
715 if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
716 dlg_templ = LoadResource(hInst, hrsrc);
717 if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
720 ret = DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);
722 return ret;