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