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