1 /*
2 * OleUIPasteSpecial implementation
3 *
4 * Copyright 2006 Huw Davies
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "oledlg.h"
33
34 #include "oledlg_private.h"
35 #include "resource.h"
36
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40
41 typedef struct
42 {
43 OLEUIPASTESPECIALW *ps;
44 DWORD flags;
45 WCHAR *source_name;
46 WCHAR *link_source_name;
47 WCHAR *type_name;
48 WCHAR *link_type_name;
49 LPOLESTR app_name;
50 } ps_struct_t;
51
52 static const struct ps_flag
53 {
54 DWORD flag;
55 const char *name;
56 } ps_flags[] = {
57 #define PS_FLAG_ENTRY(p) {p, #p}
58 PS_FLAG_ENTRY(PSF_SHOWHELP),
59 PS_FLAG_ENTRY(PSF_SELECTPASTE),
60 PS_FLAG_ENTRY(PSF_SELECTPASTELINK),
61 PS_FLAG_ENTRY(PSF_CHECKDISPLAYASICON),
62 PS_FLAG_ENTRY(PSF_DISABLEDISPLAYASICON),
63 PS_FLAG_ENTRY(PSF_HIDECHANGEICON),
64 PS_FLAG_ENTRY(PSF_STAYONCLIPBOARDCHANGE),
65 PS_FLAG_ENTRY(PSF_NOREFRESHDATAOBJECT),
66 {-1, NULL}
67 #undef PS_FLAG_ENTRY
68 };
69
dump_ps_flags(DWORD flags)70 static void dump_ps_flags(DWORD flags)
71 {
72 char flagstr[1000] = "";
73
74 const struct ps_flag *flag = ps_flags;
75 for( ; flag->name; flag++) {
76 if(flags & flag->flag) {
77 strcat(flagstr, flag->name);
78 strcat(flagstr, "|");
79 }
80 }
81 TRACE("flags %08x %s\n", flags, flagstr);
82 }
83
dump_pastespecial(const OLEUIPASTESPECIALW * ps)84 static void dump_pastespecial(const OLEUIPASTESPECIALW *ps)
85 {
86 INT i;
87 UINT j;
88
89 dump_ps_flags(ps->dwFlags);
90 TRACE("hwnd %p caption %s hook %p custdata %lx\n",
91 ps->hWndOwner, debugstr_w(ps->lpszCaption), ps->lpfnHook, ps->lCustData);
92 if(IS_INTRESOURCE(ps->lpszTemplate))
93 TRACE("hinst %p template %04x hresource %p\n", ps->hInstance, (WORD)(ULONG_PTR)ps->lpszTemplate, ps->hResource);
94 else
95 TRACE("hinst %p template %s hresource %p\n", ps->hInstance, debugstr_w(ps->lpszTemplate), ps->hResource);
96 TRACE("dataobj %p arrpasteent %p cpasteent %d arrlinktype %p clinktype %d\n",
97 ps->lpSrcDataObj, ps->arrPasteEntries, ps->cPasteEntries,
98 ps->arrLinkTypes, ps->cLinkTypes);
99 TRACE("cclsidex %d lpclsidex %p nselect %d flink %d hmetapict %p size(%d,%d)\n",
100 ps->cClsidExclude, ps->lpClsidExclude, ps->nSelectedIndex, ps->fLink,
101 ps->hMetaPict, ps->sizel.cx, ps->sizel.cy);
102 for(i = 0; i < ps->cPasteEntries; i++)
103 {
104 TRACE("arrPasteEntries[%d]: cFormat %08x pTargetDevice %p dwAspect %d lindex %d tymed %d\n",
105 i, ps->arrPasteEntries[i].fmtetc.cfFormat, ps->arrPasteEntries[i].fmtetc.ptd,
106 ps->arrPasteEntries[i].fmtetc.dwAspect, ps->arrPasteEntries[i].fmtetc.lindex,
107 ps->arrPasteEntries[i].fmtetc.tymed);
108 TRACE("\tformat name %s result text %s flags %04x\n", debugstr_w(ps->arrPasteEntries[i].lpstrFormatName),
109 debugstr_w(ps->arrPasteEntries[i].lpstrResultText), ps->arrPasteEntries[i].dwFlags);
110 }
111 for(i = 0; i < ps->cLinkTypes; i++)
112 TRACE("arrLinkTypes[%d] %08x\n", i, ps->arrLinkTypes[i]);
113 for(j = 0; j < ps->cClsidExclude; j++)
114 TRACE("lpClsidExclude[%u] %s\n", j, debugstr_guid(&ps->lpClsidExclude[j]));
115
116 }
117
strdupAtoW(const char * str)118 static inline WCHAR *strdupAtoW(const char *str)
119 {
120 DWORD len;
121 WCHAR *ret;
122 if(!str) return NULL;
123 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
124 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
125 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
126 return ret;
127 }
128
strdupW(const WCHAR * str)129 static inline WCHAR *strdupW(const WCHAR *str)
130 {
131 DWORD len;
132 WCHAR *ret;
133 if(!str) return NULL;
134 len = lstrlenW(str) + 1;
135 ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
136 memcpy(ret, str, len * sizeof(WCHAR));
137 return ret;
138 }
139
get_descriptors(HWND hdlg,ps_struct_t * ps_struct)140 static void get_descriptors(HWND hdlg, ps_struct_t *ps_struct)
141 {
142 FORMATETC fmtetc;
143 STGMEDIUM stg;
144
145 fmtetc.tymed = TYMED_HGLOBAL;
146 fmtetc.dwAspect = DVASPECT_CONTENT;
147 fmtetc.ptd = NULL;
148 fmtetc.lindex = -1;
149
150 fmtetc.cfFormat = cf_object_descriptor;
151 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
152 {
153 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
154 if(obj_desc->dwSrcOfCopy)
155 ps_struct->source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
156 if(obj_desc->dwFullUserTypeName)
157 ps_struct->type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
158 OleRegGetUserType(&obj_desc->clsid, USERCLASSTYPE_APPNAME, &ps_struct->app_name);
159 /* Get the icon here. If dwDrawAspect & DVASCPECT_ICON call GetData(CF_METAFILEPICT), otherwise
160 native calls OleGetIconFromClass(obj_desc->clsid) */
161 GlobalUnlock(stg.u.hGlobal);
162 GlobalFree(stg.u.hGlobal);
163 }
164 else
165 {
166 /* Try to get some data using some of the other clipboard formats */
167 }
168
169 fmtetc.cfFormat = cf_link_src_descriptor;
170 if(IDataObject_GetData(ps_struct->ps->lpSrcDataObj, &fmtetc, &stg) == S_OK)
171 {
172 OBJECTDESCRIPTOR *obj_desc = GlobalLock(stg.u.hGlobal);
173 if(obj_desc->dwSrcOfCopy)
174 ps_struct->link_source_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwSrcOfCopy));
175 if(obj_desc->dwFullUserTypeName)
176 ps_struct->link_type_name = strdupW((WCHAR*)((char*)obj_desc + obj_desc->dwFullUserTypeName));
177 GlobalUnlock(stg.u.hGlobal);
178 GlobalFree(stg.u.hGlobal);
179 }
180
181 if(ps_struct->source_name == NULL && ps_struct->link_source_name == NULL)
182 {
183 WCHAR buf[200];
184 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_SRC, buf, ARRAY_SIZE(buf));
185 ps_struct->source_name = strdupW(buf);
186 }
187
188 if(ps_struct->type_name == NULL && ps_struct->link_type_name == NULL)
189 {
190 WCHAR buf[200];
191 LoadStringW(OLEDLG_hInstance, IDS_PS_UNKNOWN_TYPE, buf, ARRAY_SIZE(buf));
192 ps_struct->type_name = strdupW(buf);
193 }
194 }
195
add_entry_to_lb(HWND hdlg,UINT id,OLEUIPASTEENTRYW * pe)196 static BOOL add_entry_to_lb(HWND hdlg, UINT id, OLEUIPASTEENTRYW *pe)
197 {
198 HWND hwnd = GetDlgItem(hdlg, id);
199 BOOL ret = FALSE;
200
201 /* FIXME %s handling */
202
203 /* Note that this suffers from the same bug as native, in that if a new string
204 is a substring of an already added string, then the FINDSTRING will succeed
205 this is probably not what we want */
206 if(SendMessageW(hwnd, LB_FINDSTRING, 0, (LPARAM)pe->lpstrFormatName) == -1)
207 {
208 LRESULT pos = SendMessageW(hwnd, LB_ADDSTRING, 0, (LPARAM)pe->lpstrFormatName);
209 SendMessageW(hwnd, LB_SETITEMDATA, pos, (LPARAM)pe);
210 ret = TRUE;
211 }
212 return ret;
213 }
214
init_pastelist(HWND hdlg,OLEUIPASTESPECIALW * ps)215 static DWORD init_pastelist(HWND hdlg, OLEUIPASTESPECIALW *ps)
216 {
217 IEnumFORMATETC *penum;
218 HRESULT hr;
219 FORMATETC fmts[20];
220 DWORD fetched, items_added = 0;
221
222 hr = IDataObject_EnumFormatEtc(ps->lpSrcDataObj, DATADIR_GET, &penum);
223 if(FAILED(hr))
224 {
225 WARN("Unable to create IEnumFORMATETC\n");
226 return 0;
227 }
228
229 /* The native version grabs only the first 20 fmts and we do the same */
230 hr = IEnumFORMATETC_Next(penum, ARRAY_SIZE(fmts), fmts, &fetched);
231 TRACE("got %d formats hr %08x\n", fetched, hr);
232
233 if(SUCCEEDED(hr))
234 {
235 DWORD src_fmt, req_fmt;
236 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
237 {
238 /* This is used by update_structure() to set nSelectedIndex on exit */
239 ps->arrPasteEntries[req_fmt].dwScratchSpace = req_fmt;
240 TRACE("req_fmt %x\n", ps->arrPasteEntries[req_fmt].fmtetc.cfFormat);
241 for(src_fmt = 0; src_fmt < fetched; src_fmt++)
242 {
243 TRACE("\tenum'ed fmt %x\n", fmts[src_fmt].cfFormat);
244 if(ps->arrPasteEntries[req_fmt].fmtetc.cfFormat == fmts[src_fmt].cfFormat)
245 {
246 add_entry_to_lb(hdlg, IDC_PS_PASTELIST, ps->arrPasteEntries + req_fmt);
247 items_added++;
248 break;
249 }
250 }
251 }
252 }
253
254 IEnumFORMATETC_Release(penum);
255 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTE), items_added != 0);
256 return items_added;
257 }
258
init_linklist(HWND hdlg,OLEUIPASTESPECIALW * ps)259 static DWORD init_linklist(HWND hdlg, OLEUIPASTESPECIALW *ps)
260 {
261 HRESULT hr;
262 DWORD supported_mask = 0;
263 DWORD items_added = 0;
264 int link, req_fmt;
265 FORMATETC fmt = {0, NULL, DVASPECT_CONTENT, -1, -1};
266
267 for(link = 0; link < ps->cLinkTypes && link < PS_MAXLINKTYPES; link++)
268 {
269 fmt.cfFormat = ps->arrLinkTypes[link];
270 hr = IDataObject_QueryGetData(ps->lpSrcDataObj, &fmt);
271 if(hr == S_OK)
272 supported_mask |= 1 << link;
273 }
274 TRACE("supported_mask %02x\n", supported_mask);
275 for(req_fmt = 0; req_fmt < ps->cPasteEntries; req_fmt++)
276 {
277 DWORD linktypes;
278 if(ps->arrPasteEntries[req_fmt].dwFlags & OLEUIPASTE_LINKANYTYPE)
279 linktypes = 0xff;
280 else
281 linktypes = ps->arrPasteEntries[req_fmt].dwFlags & 0xff;
282
283 if(linktypes & supported_mask)
284 {
285 add_entry_to_lb(hdlg, IDC_PS_PASTELINKLIST, ps->arrPasteEntries + req_fmt);
286 items_added++;
287 }
288 }
289
290 EnableWindow(GetDlgItem(hdlg, IDC_PS_PASTELINK), items_added != 0);
291 return items_added;
292 }
293
294 /* copies src_list_id into the display list */
update_display_list(HWND hdlg,UINT src_list_id)295 static void update_display_list(HWND hdlg, UINT src_list_id)
296 {
297 LONG count, i, old_pos;
298 WCHAR txt[256];
299 LONG item_data;
300 HWND display_list = GetDlgItem(hdlg, IDC_PS_DISPLAYLIST);
301 HWND list = GetDlgItem(hdlg, src_list_id);
302
303 old_pos = SendMessageW(display_list, LB_GETCURSEL, 0, 0);
304 if(old_pos == -1) old_pos = 0;
305
306 SendMessageW(display_list, WM_SETREDRAW, 0, 0);
307 SendMessageW(display_list, LB_RESETCONTENT, 0, 0);
308 count = SendMessageW(list, LB_GETCOUNT, 0, 0);
309 for(i = 0; i < count; i++)
310 {
311 SendMessageW(list, LB_GETTEXT, i, (LPARAM)txt);
312 item_data = SendMessageW(list, LB_GETITEMDATA, i, 0);
313 SendMessageW(display_list, LB_INSERTSTRING, i, (LPARAM)txt);
314 SendMessageW(display_list, LB_SETITEMDATA, i, item_data);
315 }
316 SendMessageW(display_list, LB_SETCURSEL, 0, 0);
317 SendMessageW(display_list, WM_SETREDRAW, 1, 0);
318 if(GetForegroundWindow() == hdlg)
319 SetFocus(display_list);
320 }
321
init_lists(HWND hdlg,ps_struct_t * ps_struct)322 static void init_lists(HWND hdlg, ps_struct_t *ps_struct)
323 {
324 DWORD pastes_added = init_pastelist(hdlg, ps_struct->ps);
325 DWORD links_added = init_linklist(hdlg, ps_struct->ps);
326 UINT check_id, list_id;
327
328 if((ps_struct->flags & (PSF_SELECTPASTE | PSF_SELECTPASTELINK)) == 0)
329 ps_struct->flags |= PSF_SELECTPASTE;
330
331 if(!pastes_added && !links_added)
332 ps_struct->flags &= ~(PSF_SELECTPASTE | PSF_SELECTPASTELINK);
333 else if(!pastes_added && (ps_struct->flags & PSF_SELECTPASTE))
334 {
335 ps_struct->flags &= ~PSF_SELECTPASTE;
336 ps_struct->flags |= PSF_SELECTPASTELINK;
337 }
338 else if(!links_added && (ps_struct->flags & PSF_SELECTPASTELINK))
339 {
340 ps_struct->flags &= ~PSF_SELECTPASTELINK;
341 ps_struct->flags |= PSF_SELECTPASTE;
342 }
343
344 check_id = 0;
345 list_id = 0;
346 if(ps_struct->flags & PSF_SELECTPASTE)
347 {
348 check_id = IDC_PS_PASTE;
349 list_id = IDC_PS_PASTELIST;
350 }
351 else if(ps_struct->flags & PSF_SELECTPASTELINK)
352 {
353 check_id = IDC_PS_PASTELINK;
354 list_id = IDC_PS_PASTELINKLIST;
355 }
356
357 CheckRadioButton(hdlg, IDC_PS_PASTE, IDC_PS_PASTELINK, check_id);
358
359 if(list_id)
360 update_display_list(hdlg, list_id);
361 else
362 EnableWindow(GetDlgItem(hdlg, IDOK), 0);
363 }
364
update_src_text(HWND hdlg,const ps_struct_t * ps_struct)365 static void update_src_text(HWND hdlg, const ps_struct_t *ps_struct)
366 {
367 WCHAR *str;
368
369 if(ps_struct->flags & PSF_SELECTPASTE)
370 {
371 if(ps_struct->source_name)
372 str = ps_struct->source_name;
373 else
374 str = ps_struct->link_source_name;
375
376 }
377 else
378 {
379 if(ps_struct->link_source_name)
380 str = ps_struct->link_source_name;
381 else
382 str = ps_struct->source_name;
383
384 }
385 SetDlgItemTextW(hdlg, IDC_PS_SOURCETEXT, str);
386 }
387
update_as_icon(HWND hdlg,ps_struct_t * ps_struct)388 static void update_as_icon(HWND hdlg, ps_struct_t *ps_struct)
389 {
390 HWND icon_display = GetDlgItem(hdlg, IDC_PS_ICONDISPLAY);
391 HWND display_as_icon = GetDlgItem(hdlg, IDC_PS_DISPLAYASICON);
392 HWND change_icon = GetDlgItem(hdlg, IDC_PS_CHANGEICON);
393
394 /* FIXME. No as icon handling */
395 ps_struct->flags &= ~PSF_CHECKDISPLAYASICON;
396
397 CheckDlgButton(hdlg, IDC_PS_DISPLAYASICON, ps_struct->flags & PSF_CHECKDISPLAYASICON);
398 EnableWindow(display_as_icon, 0);
399 ShowWindow(icon_display, SW_HIDE);
400 EnableWindow(icon_display, 0);
401 ShowWindow(change_icon, SW_HIDE);
402 EnableWindow(change_icon, 0);
403 }
404
update_result_text(HWND hdlg,const ps_struct_t * ps_struct)405 static void update_result_text(HWND hdlg, const ps_struct_t *ps_struct)
406 {
407 WCHAR resource_txt[200];
408 UINT res_id;
409 OLEUIPASTEENTRYW *pent;
410 LONG cur_sel;
411 static const WCHAR percent_s[] = {'%','s',0};
412 WCHAR *result_txt, *ptr;
413
414 cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
415 if(cur_sel == -1) return;
416 pent = (OLEUIPASTEENTRYW*)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
417
418 if(ps_struct->flags & PSF_SELECTPASTE)
419 {
420 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
421 res_id = IDS_PS_PASTE_OBJECT_AS_ICON;
422 else
423 res_id = IDS_PS_PASTE_DATA;
424 }
425 else
426 {
427 if(ps_struct->flags & PSF_CHECKDISPLAYASICON)
428 res_id = IDS_PS_PASTE_LINK_OBJECT_AS_ICON;
429 else
430 res_id = IDS_PS_PASTE_LINK_DATA;
431 }
432
433 LoadStringW(OLEDLG_hInstance, res_id, resource_txt, ARRAY_SIZE(resource_txt));
434 if((ptr = wcsstr(resource_txt, percent_s)))
435 {
436 /* FIXME handle %s in ResultText. Sub appname if IDS_PS_PASTE_OBJECT{_AS_ICON}. Else sub appropriate type name */
437 size_t result_txt_len = lstrlenW(pent->lpstrResultText);
438 ptrdiff_t offs = (char*)ptr - (char*)resource_txt;
439 result_txt = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(resource_txt) + result_txt_len - 1) * sizeof(WCHAR));
440 memcpy(result_txt, resource_txt, offs);
441 memcpy((char*)result_txt + offs, pent->lpstrResultText, result_txt_len * sizeof(WCHAR));
442 memcpy((char*)result_txt + offs + result_txt_len * sizeof(WCHAR), ptr + 2, (lstrlenW(ptr + 2) + 1) * sizeof(WCHAR));
443 }
444 else
445 result_txt = resource_txt;
446
447 SetDlgItemTextW(hdlg, IDC_PS_RESULTTEXT, result_txt);
448
449 if(result_txt != resource_txt)
450 HeapFree(GetProcessHeap(), 0, result_txt);
451
452 }
453
selection_change(HWND hdlg,ps_struct_t * ps_struct)454 static void selection_change(HWND hdlg, ps_struct_t *ps_struct)
455 {
456 update_as_icon(hdlg, ps_struct);
457 update_result_text(hdlg, ps_struct);
458 }
459
mode_change(HWND hdlg,ps_struct_t * ps_struct,UINT id)460 static void mode_change(HWND hdlg, ps_struct_t *ps_struct, UINT id)
461 {
462 if(id == IDC_PS_PASTE)
463 {
464 ps_struct->flags &= ~PSF_SELECTPASTELINK;
465 ps_struct->flags |= PSF_SELECTPASTE;
466 }
467 else
468 {
469 ps_struct->flags &= ~PSF_SELECTPASTE;
470 ps_struct->flags |= PSF_SELECTPASTELINK;
471 }
472
473 update_src_text(hdlg, ps_struct);
474 update_display_list(hdlg, id == IDC_PS_PASTE ? IDC_PS_PASTELIST : IDC_PS_PASTELINKLIST);
475 selection_change(hdlg, ps_struct);
476 }
477
post_help_msg(HWND hdlg,ps_struct_t * ps_struct)478 static void post_help_msg(HWND hdlg, ps_struct_t *ps_struct)
479 {
480 PostMessageW(ps_struct->ps->hWndOwner, oleui_msg_help, (WPARAM)hdlg, IDD_PASTESPECIAL);
481 }
482
send_end_dialog_msg(HWND hdlg,ps_struct_t * ps_struct,UINT id)483 static void send_end_dialog_msg(HWND hdlg, ps_struct_t *ps_struct, UINT id)
484 {
485 SendMessageW(hdlg, oleui_msg_enddialog, id, 0);
486 }
487
update_structure(HWND hdlg,ps_struct_t * ps_struct)488 static void update_structure(HWND hdlg, ps_struct_t *ps_struct)
489 {
490 LONG cur_sel = SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETCURSEL, 0, 0);
491 if(cur_sel != -1)
492 {
493 OLEUIPASTEENTRYW *pent;
494 pent = (OLEUIPASTEENTRYW *)SendMessageW(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST), LB_GETITEMDATA, cur_sel, 0);
495 ps_struct->ps->nSelectedIndex = pent->dwScratchSpace;
496 }
497 ps_struct->ps->dwFlags = ps_struct->flags;
498 ps_struct->ps->fLink = (ps_struct->flags & PSF_SELECTPASTELINK) != 0;
499 }
500
free_structure(ps_struct_t * ps_struct)501 static void free_structure(ps_struct_t *ps_struct)
502 {
503 HeapFree(GetProcessHeap(), 0, ps_struct->type_name);
504 HeapFree(GetProcessHeap(), 0, ps_struct->source_name);
505 HeapFree(GetProcessHeap(), 0, ps_struct->link_type_name);
506 HeapFree(GetProcessHeap(), 0, ps_struct->link_source_name);
507 CoTaskMemFree(ps_struct->app_name);
508 HeapFree(GetProcessHeap(), 0, ps_struct);
509 }
510
ps_dlg_proc(HWND hdlg,UINT msg,WPARAM wp,LPARAM lp)511 static INT_PTR CALLBACK ps_dlg_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
512 {
513 /* native uses prop name "Structure", but we're not compatible
514 with that so we'll prepend "Wine_". */
515 static const WCHAR prop_name[] = {'W','i','n','e','_','S','t','r','u','c','t','u','r','e',0};
516 ps_struct_t *ps_struct;
517
518 TRACE("(%p, %04x, %08lx, %08lx)\n", hdlg, msg, wp, lp);
519
520 ps_struct = GetPropW(hdlg, prop_name);
521
522 if(msg != WM_INITDIALOG)
523 {
524 if(!ps_struct)
525 return 0;
526
527 if(ps_struct->ps->lpfnHook)
528 {
529 INT_PTR ret = ps_struct->ps->lpfnHook(hdlg, msg, wp, lp);
530 if(ret) return ret;
531 }
532 }
533
534 switch(msg)
535 {
536 case WM_INITDIALOG:
537 {
538 ps_struct = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps_struct));
539 ps_struct->ps = (OLEUIPASTESPECIALW*)lp;
540 ps_struct->type_name = NULL;
541 ps_struct->source_name = NULL;
542 ps_struct->link_type_name = NULL;
543 ps_struct->link_source_name = NULL;
544 ps_struct->app_name = NULL;
545 ps_struct->flags = ps_struct->ps->dwFlags;
546
547 SetPropW(hdlg, prop_name, ps_struct);
548
549 if(!(ps_struct->ps->dwFlags & PSF_SHOWHELP))
550 {
551 ShowWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), SW_HIDE);
552 EnableWindow(GetDlgItem(hdlg, IDC_OLEUIHELP), 0);
553 }
554
555 if(ps_struct->ps->lpszCaption)
556 SetWindowTextW(hdlg, ps_struct->ps->lpszCaption);
557
558 get_descriptors(hdlg, ps_struct);
559
560 init_lists(hdlg, ps_struct);
561
562 update_src_text(hdlg, ps_struct);
563
564 selection_change(hdlg, ps_struct);
565
566 SetFocus(GetDlgItem(hdlg, IDC_PS_DISPLAYLIST));
567
568 if(ps_struct->ps->lpfnHook)
569 ps_struct->ps->lpfnHook(hdlg, msg, 0, 0);
570 return FALSE; /* use new focus */
571 }
572 case WM_COMMAND:
573 switch(LOWORD(wp))
574 {
575 case IDC_PS_DISPLAYLIST:
576 switch(HIWORD(wp))
577 {
578 case LBN_SELCHANGE:
579 selection_change(hdlg, ps_struct);
580 return FALSE;
581 default:
582 return FALSE;
583 }
584 case IDC_PS_PASTE:
585 case IDC_PS_PASTELINK:
586 switch(HIWORD(wp))
587 {
588 case BN_CLICKED:
589 mode_change(hdlg, ps_struct, LOWORD(wp));
590 return FALSE;
591
592 default:
593 return FALSE;
594 }
595 case IDC_OLEUIHELP:
596 switch(HIWORD(wp))
597 {
598 case BN_CLICKED:
599 post_help_msg(hdlg, ps_struct);
600 return FALSE;
601 default:
602 return FALSE;
603 }
604 case IDOK:
605 case IDCANCEL:
606 switch(HIWORD(wp))
607 {
608 case BN_CLICKED:
609 send_end_dialog_msg(hdlg, ps_struct, LOWORD(wp));
610 return FALSE;
611 default:
612 return FALSE;
613 }
614 }
615 return FALSE;
616 default:
617 if(msg == oleui_msg_enddialog)
618 {
619 if(wp == IDOK)
620 update_structure(hdlg, ps_struct);
621 EndDialog(hdlg, wp);
622 /* native does its cleanup in WM_DESTROY */
623 RemovePropW(hdlg, prop_name);
624 free_structure(ps_struct);
625 return TRUE;
626 }
627 return FALSE;
628 }
629
630 }
631
632 /***********************************************************************
633 * OleUIPasteSpecialA (OLEDLG.4)
634 */
OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)635 UINT WINAPI OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA)
636 {
637 OLEUIPASTESPECIALW ps;
638 UINT ret;
639 TRACE("(%p)\n", psA);
640
641 memcpy(&ps, psA, psA->cbStruct);
642
643 ps.lpszCaption = strdupAtoW(psA->lpszCaption);
644 if(!IS_INTRESOURCE(ps.lpszTemplate))
645 ps.lpszTemplate = strdupAtoW(psA->lpszTemplate);
646
647 if(psA->cPasteEntries > 0)
648 {
649 DWORD size = psA->cPasteEntries * sizeof(ps.arrPasteEntries[0]);
650 INT i;
651
652 ps.arrPasteEntries = HeapAlloc(GetProcessHeap(), 0, size);
653 memcpy(ps.arrPasteEntries, psA->arrPasteEntries, size);
654 for(i = 0; i < psA->cPasteEntries; i++)
655 {
656 ps.arrPasteEntries[i].lpstrFormatName =
657 strdupAtoW(psA->arrPasteEntries[i].lpstrFormatName);
658 ps.arrPasteEntries[i].lpstrResultText =
659 strdupAtoW(psA->arrPasteEntries[i].lpstrResultText);
660 }
661 }
662
663 ret = OleUIPasteSpecialW(&ps);
664
665 if(psA->cPasteEntries > 0)
666 {
667 INT i;
668 for(i = 0; i < psA->cPasteEntries; i++)
669 {
670 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrFormatName);
671 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.arrPasteEntries[i].lpstrResultText);
672 }
673 HeapFree(GetProcessHeap(), 0, ps.arrPasteEntries);
674 }
675 if(!IS_INTRESOURCE(ps.lpszTemplate))
676 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszTemplate);
677 HeapFree(GetProcessHeap(), 0, (WCHAR*)ps.lpszCaption);
678
679 /* Copy back the output fields */
680 psA->dwFlags = ps.dwFlags;
681 psA->lpSrcDataObj = ps.lpSrcDataObj;
682 psA->nSelectedIndex = ps.nSelectedIndex;
683 psA->fLink = ps.fLink;
684 psA->hMetaPict = ps.hMetaPict;
685 psA->sizel = ps.sizel;
686
687 return ret;
688 }
689
690 /***********************************************************************
691 * OleUIPasteSpecialW (OLEDLG.22)
692 */
OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)693 UINT WINAPI OleUIPasteSpecialW(LPOLEUIPASTESPECIALW ps)
694 {
695 LPCDLGTEMPLATEW dlg_templ = (LPCDLGTEMPLATEW)ps->hResource;
696 UINT ret;
697
698 TRACE("(%p)\n", ps);
699
700 if(TRACE_ON(ole)) dump_pastespecial(ps);
701
702 if(!ps->lpSrcDataObj)
703 OleGetClipboard(&ps->lpSrcDataObj);
704
705 if(ps->hInstance || !ps->hResource)
706 {
707 HINSTANCE hInst = ps->hInstance ? ps->hInstance : OLEDLG_hInstance;
708 const WCHAR *name = ps->hInstance ? ps->lpszTemplate : MAKEINTRESOURCEW(IDD_PASTESPECIAL4);
709 HRSRC hrsrc;
710
711 if(name == NULL) return OLEUI_ERR_LPSZTEMPLATEINVALID;
712 hrsrc = FindResourceW(hInst, name, (LPWSTR)RT_DIALOG);
713 if(!hrsrc) return OLEUI_ERR_FINDTEMPLATEFAILURE;
714 dlg_templ = LoadResource(hInst, hrsrc);
715 if(!dlg_templ) return OLEUI_ERR_LOADTEMPLATEFAILURE;
716 }
717
718 ret = DialogBoxIndirectParamW(OLEDLG_hInstance, dlg_templ, ps->hWndOwner, ps_dlg_proc, (LPARAM)ps);
719
720 return ret;
721 }
722