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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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