1 /* 2 * OLEDLG library 3 * 4 * Copyright 1998 Patrik Stridvall 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 23 #include <stdarg.h> 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winerror.h" 28 #include "wingdi.h" 29 #include "winuser.h" 30 #include "oledlg.h" 31 #include "ole2.h" 32 #include "oledlg_private.h" 33 #include "resource.h" 34 35 #include "wine/debug.h" 36 #include "wine/unicode.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(ole); 39 40 HINSTANCE OLEDLG_hInstance = 0; 41 42 UINT cf_embed_source; 43 UINT cf_embedded_object; 44 UINT cf_link_source; 45 UINT cf_object_descriptor; 46 UINT cf_link_src_descriptor; 47 UINT cf_ownerlink; 48 UINT cf_filename; 49 UINT cf_filenamew; 50 51 UINT oleui_msg_help; 52 UINT oleui_msg_enddialog; 53 54 static void register_clipboard_formats(void) 55 { 56 /* These used to be declared in olestd.h, but that seems to have been removed from the api */ 57 static const WCHAR CF_EMBEDSOURCEW[] = { 'E','m','b','e','d',' ','S','o','u','r','c','e',0 }; 58 static const WCHAR CF_EMBEDDEDOBJECTW[] = { 'E','m','b','e','d','d','e','d',' ','O','b','j','e','c','t',0 }; 59 static const WCHAR CF_LINKSOURCEW[] = { 'L','i','n','k',' ','S','o','u','r','c','e',0 }; 60 static const WCHAR CF_OBJECTDESCRIPTORW[] = { 'O','b','j','e','c','t',' ','D','e','s','c','r','i','p','t','o','r',0 }; 61 static const WCHAR CF_LINKSRCDESCRIPTORW[] = { 'L','i','n','k',' ','S','o','u','r','c','e',' ','D','e','s','c','r','i','p','t','o','r',0 }; 62 static const WCHAR CF_OWNERLINKW[] = { 'O','w','n','e','r','L','i','n','k',0 }; 63 static const WCHAR CF_FILENAMEW[] = { 'F','i','l','e','N','a','m','e',0 }; 64 static const WCHAR CF_FILENAMEWW[] = { 'F','i','l','e','N','a','m','e','W',0 }; 65 66 /* Load in the same order as native to make debugging easier */ 67 cf_object_descriptor = RegisterClipboardFormatW(CF_OBJECTDESCRIPTORW); 68 cf_link_src_descriptor = RegisterClipboardFormatW(CF_LINKSRCDESCRIPTORW); 69 cf_embed_source = RegisterClipboardFormatW(CF_EMBEDSOURCEW); 70 cf_embedded_object = RegisterClipboardFormatW(CF_EMBEDDEDOBJECTW); 71 cf_link_source = RegisterClipboardFormatW(CF_LINKSOURCEW); 72 cf_ownerlink = RegisterClipboardFormatW(CF_OWNERLINKW); 73 cf_filename = RegisterClipboardFormatW(CF_FILENAMEW); 74 cf_filenamew = RegisterClipboardFormatW(CF_FILENAMEWW); 75 } 76 77 static void register_messages(void) 78 { 79 oleui_msg_help = RegisterWindowMessageW(SZOLEUI_MSG_HELPW); 80 oleui_msg_enddialog = RegisterWindowMessageW(SZOLEUI_MSG_ENDDIALOGW); 81 } 82 83 /*********************************************************************** 84 * DllMain 85 */ 86 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) 87 { 88 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad); 89 90 switch(fdwReason) { 91 case DLL_PROCESS_ATTACH: 92 DisableThreadLibraryCalls(hinstDLL); 93 OLEDLG_hInstance = hinstDLL; 94 register_clipboard_formats(); 95 register_messages(); 96 break; 97 } 98 return TRUE; 99 } 100 101 102 /*********************************************************************** 103 * OleUIAddVerbMenuA (OLEDLG.1) 104 */ 105 BOOL WINAPI OleUIAddVerbMenuA(IOleObject *object, LPCSTR shorttype, 106 HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax, 107 BOOL addConvert, UINT idConvert, HMENU *lphMenu) 108 { 109 WCHAR *shorttypeW = NULL; 110 BOOL ret; 111 112 TRACE("(%p, %s, %p, %d, %d, %d, %d, %d, %p)\n", object, debugstr_a(shorttype), 113 hMenu, uPos, uIDVerbMin, uIDVerbMax, addConvert, idConvert, lphMenu); 114 115 if (shorttype) 116 { 117 INT len = MultiByteToWideChar(CP_ACP, 0, shorttype, -1, NULL, 0); 118 shorttypeW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 119 if (shorttypeW) 120 MultiByteToWideChar(CP_ACP, 0, shorttype, -1, shorttypeW, len); 121 } 122 123 ret = OleUIAddVerbMenuW(object, shorttypeW, hMenu, uPos, uIDVerbMin, uIDVerbMax, 124 addConvert, idConvert, lphMenu); 125 HeapFree(GetProcessHeap(), 0, shorttypeW); 126 return ret; 127 } 128 129 static inline BOOL is_verb_in_range(const OLEVERB *verb, UINT idmin, UINT idmax) 130 { 131 if (idmax == 0) return TRUE; 132 return (verb->lVerb + idmin <= idmax); 133 } 134 135 static HRESULT get_next_insertable_verb(IEnumOLEVERB *enumverbs, UINT idmin, UINT idmax, OLEVERB *verb) 136 { 137 memset(verb, 0, sizeof(*verb)); 138 139 while (IEnumOLEVERB_Next(enumverbs, 1, verb, NULL) == S_OK) { 140 if (is_verb_in_range(verb, idmin, idmax) && (verb->grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) 141 return S_OK; 142 143 CoTaskMemFree(verb->lpszVerbName); 144 memset(verb, 0, sizeof(*verb)); 145 } 146 147 return S_FALSE; 148 } 149 150 static void insert_verb_to_menu(HMENU menu, UINT idmin, const OLEVERB *verb) 151 { 152 InsertMenuW(menu, ~0, verb->fuFlags | MF_BYPOSITION | MF_STRING, verb->lVerb + idmin, verb->lpszVerbName); 153 } 154 155 /*********************************************************************** 156 * OleUIAddVerbMenuW (OLEDLG.14) 157 */ 158 BOOL WINAPI OleUIAddVerbMenuW(IOleObject *object, LPCWSTR shorttype, 159 HMENU hMenu, UINT uPos, UINT idmin, UINT idmax, BOOL addConvert, UINT idConvert, HMENU *ret_submenu) 160 { 161 IEnumOLEVERB *enumverbs = NULL; 162 LPOLESTR usertype = NULL; 163 OLEVERB firstverb, verb; 164 WCHAR *objecttype; 165 WCHAR resstrW[32]; /* should be enough */ 166 DWORD_PTR args[2]; 167 BOOL singleverb; 168 HMENU submenu; 169 WCHAR *str; 170 171 TRACE("(%p, %s, %p, %d, %d, %d, %d, %d, %p)\n", object, debugstr_w(shorttype), 172 hMenu, uPos, idmin, idmax, addConvert, idConvert, ret_submenu); 173 174 if (ret_submenu) 175 *ret_submenu = NULL; 176 177 if (!hMenu || !ret_submenu) 178 return FALSE; 179 180 /* check if we can get verbs at all */ 181 if (object) 182 IOleObject_EnumVerbs(object, &enumverbs); 183 184 LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_OBJECT, resstrW, sizeof(resstrW)/sizeof(WCHAR)); 185 /* no object, or object without enumeration support */ 186 if (!object || !enumverbs) { 187 RemoveMenu(hMenu, uPos, MF_BYPOSITION); 188 InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_GRAYED, idmin, resstrW); 189 return FALSE; 190 } 191 192 /* root entry string */ 193 if (!shorttype && (IOleObject_GetUserType(object, USERCLASSTYPE_SHORT, &usertype) == S_OK)) 194 objecttype = usertype; 195 else 196 objecttype = (WCHAR*)shorttype; 197 198 /* iterate through verbs */ 199 200 /* find first suitable verb */ 201 get_next_insertable_verb(enumverbs, idmin, idmax, &firstverb); 202 singleverb = get_next_insertable_verb(enumverbs, idmin, idmax, &verb) != S_OK; 203 204 if (singleverb && !addConvert) { 205 LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_SINGLEVERB_OBJECT, resstrW, sizeof(resstrW)/sizeof(WCHAR)); 206 207 args[0] = (DWORD_PTR)firstverb.lpszVerbName; 208 args[1] = (DWORD_PTR)objecttype; 209 210 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY, 211 resstrW, 0, 0, (WCHAR*)&str, 0, (__ms_va_list*)args); 212 213 RemoveMenu(hMenu, uPos, MF_BYPOSITION); 214 InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idmin, str); 215 CoTaskMemFree(firstverb.lpszVerbName); 216 HeapFree(GetProcessHeap(), 0, str); 217 IEnumOLEVERB_Release(enumverbs); 218 CoTaskMemFree(usertype); 219 return TRUE; 220 } 221 222 submenu = CreatePopupMenu(); 223 insert_verb_to_menu(submenu, idmin, &firstverb); 224 CoTaskMemFree(firstverb.lpszVerbName); 225 226 if (!singleverb) { 227 insert_verb_to_menu(submenu, idmin, &verb); 228 CoTaskMemFree(verb.lpszVerbName); 229 } 230 231 while (get_next_insertable_verb(enumverbs, idmin, idmax, &verb) == S_OK) { 232 insert_verb_to_menu(submenu, idmin, &verb); 233 CoTaskMemFree(verb.lpszVerbName); 234 } 235 236 /* convert verb is at the bottom of a popup, separated from verbs */ 237 if (addConvert) { 238 LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_CONVERT, resstrW, sizeof(resstrW)/sizeof(WCHAR)); 239 InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_SEPARATOR, 0, NULL); 240 InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_STRING, idConvert, resstrW); 241 } 242 243 if (submenu) 244 *ret_submenu = submenu; 245 246 /* now submenu is ready, add root entry to original menu, attach submenu */ 247 LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_OBJECT_WITH_NAME, resstrW, sizeof(resstrW)/sizeof(WCHAR)); 248 249 args[0] = (DWORD_PTR)objecttype; 250 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY, 251 resstrW, 0, 0, (WCHAR*)&str, 0, (__ms_va_list*)args); 252 253 InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)submenu, str); 254 HeapFree(GetProcessHeap(), 0, str); 255 IEnumOLEVERB_Release(enumverbs); 256 CoTaskMemFree(usertype); 257 return TRUE; 258 } 259 260 /*********************************************************************** 261 * OleUICanConvertOrActivateAs (OLEDLG.2) 262 */ 263 BOOL WINAPI OleUICanConvertOrActivateAs( 264 REFCLSID rClsid, BOOL fIsLinkedObject, WORD wFormat) 265 { 266 FIXME("(%p, %d, %hd): stub\n", 267 rClsid, fIsLinkedObject, wFormat 268 ); 269 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 270 return FALSE; 271 } 272 273 /*********************************************************************** 274 * OleUIInsertObjectW (OLEDLG.20) 275 */ 276 UINT WINAPI OleUIInsertObjectW(LPOLEUIINSERTOBJECTW lpOleUIInsertObject) 277 { 278 FIXME("(%p): stub\n", lpOleUIInsertObject); 279 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 280 return OLEUI_FALSE; 281 } 282 283 /*********************************************************************** 284 * OleUIEditLinksA (OLEDLG.5) 285 */ 286 UINT WINAPI OleUIEditLinksA(LPOLEUIEDITLINKSA lpOleUIEditLinks) 287 { 288 FIXME("(%p): stub\n", lpOleUIEditLinks); 289 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 290 return OLEUI_FALSE; 291 } 292 293 /*********************************************************************** 294 * OleUIEditLinksW (OLEDLG.19) 295 */ 296 UINT WINAPI OleUIEditLinksW(LPOLEUIEDITLINKSW lpOleUIEditLinks) 297 { 298 FIXME("(%p): stub\n", lpOleUIEditLinks); 299 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 300 return OLEUI_FALSE; 301 } 302 303 /*********************************************************************** 304 * OleUIChangeIconA (OLEDLG.6) 305 */ 306 UINT WINAPI OleUIChangeIconA( 307 LPOLEUICHANGEICONA lpOleUIChangeIcon) 308 { 309 FIXME("(%p): stub\n", lpOleUIChangeIcon); 310 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 311 return OLEUI_FALSE; 312 } 313 314 /*********************************************************************** 315 * OleUIChangeIconW (OLEDLG.16) 316 */ 317 UINT WINAPI OleUIChangeIconW( 318 LPOLEUICHANGEICONW lpOleUIChangeIcon) 319 { 320 FIXME("(%p): stub\n", lpOleUIChangeIcon); 321 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 322 return OLEUI_FALSE; 323 } 324 325 /*********************************************************************** 326 * OleUIConvertA (OLEDLG.7) 327 */ 328 UINT WINAPI OleUIConvertA(LPOLEUICONVERTA lpOleUIConvert) 329 { 330 FIXME("(%p): stub\n", lpOleUIConvert); 331 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 332 return OLEUI_FALSE; 333 } 334 335 /*********************************************************************** 336 * OleUIConvertW (OLEDLG.18) 337 */ 338 UINT WINAPI OleUIConvertW(LPOLEUICONVERTW lpOleUIConvert) 339 { 340 FIXME("(%p): stub\n", lpOleUIConvert); 341 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 342 return OLEUI_FALSE; 343 } 344 345 /*********************************************************************** 346 * OleUIBusyA (OLEDLG.8) 347 */ 348 UINT WINAPI OleUIBusyA(LPOLEUIBUSYA lpOleUIBusy) 349 { 350 FIXME("(%p): stub\n", lpOleUIBusy); 351 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 352 return OLEUI_FALSE; 353 } 354 355 /*********************************************************************** 356 * OleUIBusyW (OLEDLG.15) 357 */ 358 UINT WINAPI OleUIBusyW(LPOLEUIBUSYW lpOleUIBusy) 359 { 360 FIXME("(%p): stub\n", lpOleUIBusy); 361 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 362 return OLEUI_FALSE; 363 } 364 365 /*********************************************************************** 366 * OleUIUpdateLinksA (OLEDLG.9) 367 */ 368 BOOL WINAPI OleUIUpdateLinksA( 369 LPOLEUILINKCONTAINERA lpOleUILinkCntr, 370 HWND hwndParent, LPSTR lpszTitle, INT cLinks) 371 { 372 FIXME("(%p, %p, %s, %d): stub\n", 373 lpOleUILinkCntr, hwndParent, debugstr_a(lpszTitle), cLinks 374 ); 375 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 376 return FALSE; 377 } 378 379 /*********************************************************************** 380 * OleUIUpdateLinksW (OLEDLG.23) 381 */ 382 BOOL WINAPI OleUIUpdateLinksW( 383 LPOLEUILINKCONTAINERW lpOleUILinkCntr, 384 HWND hwndParent, LPWSTR lpszTitle, INT cLinks) 385 { 386 FIXME("(%p, %p, %s, %d): stub\n", 387 lpOleUILinkCntr, hwndParent, debugstr_w(lpszTitle), cLinks 388 ); 389 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 390 return FALSE; 391 } 392 393 /*********************************************************************** 394 * OleUIPromptUserA (OLEDLG.10) 395 */ 396 INT WINAPIV OleUIPromptUserA( 397 INT nTemplate, HWND hwndParent, ...) 398 { 399 FIXME("(%d, %p, ...): stub\n", nTemplate, hwndParent); 400 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 401 return OLEUI_FALSE; 402 } 403 404 /*********************************************************************** 405 * OleUIPromptUserW (OLEDLG.13) 406 */ 407 INT WINAPIV OleUIPromptUserW( 408 INT nTemplate, HWND hwndParent, ...) 409 { 410 FIXME("(%d, %p, ...): stub\n", nTemplate, hwndParent); 411 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 412 return OLEUI_FALSE; 413 } 414 415 /*********************************************************************** 416 * OleUIObjectPropertiesA (OLEDLG.11) 417 */ 418 UINT WINAPI OleUIObjectPropertiesA( 419 LPOLEUIOBJECTPROPSA lpOleUIObjectProps) 420 { 421 FIXME("(%p): stub\n", lpOleUIObjectProps); 422 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 423 return OLEUI_FALSE; 424 } 425 426 /*********************************************************************** 427 * OleUIObjectPropertiesW (OLEDLG.21) 428 */ 429 UINT WINAPI OleUIObjectPropertiesW( 430 LPOLEUIOBJECTPROPSW lpOleUIObjectProps) 431 { 432 FIXME("(%p): stub\n", lpOleUIObjectProps); 433 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 434 return OLEUI_FALSE; 435 } 436 437 /*********************************************************************** 438 * OleUIChangeSourceA (OLEDLG.12) 439 */ 440 UINT WINAPI OleUIChangeSourceA( 441 LPOLEUICHANGESOURCEA lpOleUIChangeSource) 442 { 443 FIXME("(%p): stub\n", lpOleUIChangeSource); 444 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 445 return OLEUI_FALSE; 446 } 447 448 /*********************************************************************** 449 * OleUIChangeSourceW (OLEDLG.17) 450 */ 451 UINT WINAPI OleUIChangeSourceW( 452 LPOLEUICHANGESOURCEW lpOleUIChangeSource) 453 { 454 FIXME("(%p): stub\n", lpOleUIChangeSource); 455 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 456 return OLEUI_FALSE; 457 } 458