1 /* 2 * Implementation of IShellBrowser for the File Open common dialog 3 * 4 * Copyright 1999 Francois Boisvert 5 * Copyright 1999, 2000 Juergen Schmied 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #define COBJMACROS 27 #define NONAMELESSUNION 28 29 #include "windef.h" 30 #include "winbase.h" 31 #include "winnls.h" 32 #include "wingdi.h" 33 #include "winuser.h" 34 #include "winreg.h" 35 36 #define NO_SHLWAPI_STREAM 37 #include "shlwapi.h" 38 #include "filedlgbrowser.h" 39 #include "cdlg.h" 40 #include "shlguid.h" 41 #include "servprov.h" 42 #include "wine/debug.h" 43 44 WINE_DEFAULT_DEBUG_CHANNEL(commdlg); 45 46 typedef struct 47 { 48 49 IShellBrowser IShellBrowser_iface; 50 ICommDlgBrowser ICommDlgBrowser_iface; 51 IServiceProvider IServiceProvider_iface; 52 LONG ref; /* Reference counter */ 53 HWND hwndOwner; /* Owner dialog of the interface */ 54 55 } IShellBrowserImpl; 56 57 static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface) 58 { 59 return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface); 60 } 61 62 static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface ) 63 { 64 return CONTAINING_RECORD(iface, IShellBrowserImpl, ICommDlgBrowser_iface); 65 } 66 67 static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface ) 68 { 69 return CONTAINING_RECORD(iface, IShellBrowserImpl, IServiceProvider_iface); 70 } 71 72 /************************************************************************** 73 * vtable 74 */ 75 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl; 76 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl; 77 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl; 78 79 /* 80 * Helper functions 81 */ 82 83 #define add_flag(a) if (flags & a) {strcat(str, #a );strcat(str," ");} 84 static void COMDLG32_DumpSBSPFlags(UINT uflags) 85 { 86 if (TRACE_ON(commdlg)) 87 { 88 unsigned int i; 89 static const struct { 90 DWORD mask; 91 const char *name; 92 } flags[] = { 93 #define FE(x) { x, #x} 94 /* SBSP_DEFBROWSER == 0 */ 95 FE(SBSP_SAMEBROWSER), 96 FE(SBSP_NEWBROWSER), 97 98 /* SBSP_DEFMODE == 0 */ 99 FE(SBSP_OPENMODE), 100 FE(SBSP_EXPLOREMODE), 101 FE(SBSP_HELPMODE), 102 FE(SBSP_NOTRANSFERHIST), 103 104 /* SBSP_ABSOLUTE == 0 */ 105 FE(SBSP_RELATIVE), 106 FE(SBSP_PARENT), 107 FE(SBSP_NAVIGATEBACK), 108 FE(SBSP_NAVIGATEFORWARD), 109 FE(SBSP_ALLOW_AUTONAVIGATE), 110 111 FE(SBSP_NOAUTOSELECT), 112 FE(SBSP_WRITENOHISTORY), 113 114 FE(SBSP_REDIRECT), 115 FE(SBSP_INITIATEDBYHLINKFRAME), 116 }; 117 #undef FE 118 TRACE("SBSP Flags: %08x =", uflags); 119 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) 120 if (flags[i].mask & uflags) 121 TRACE("%s ", flags[i].name); 122 TRACE("\n"); 123 } 124 } 125 126 static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos) 127 { 128 LPSHELLFOLDER psfDesktop; 129 STRRET strret; 130 HRESULT res; 131 132 res = SHGetDesktopFolder(&psfDesktop); 133 if (FAILED(res)) 134 return; 135 136 res = IShellFolder_GetDisplayNameOf(psfDesktop, fodInfos->ShellInfos.pidlAbsCurrent, 137 SHGDN_FORPARSING, &strret); 138 if (SUCCEEDED(res)) { 139 WCHAR wszCurrentDir[MAX_PATH]; 140 141 res = StrRetToBufW(&strret, fodInfos->ShellInfos.pidlAbsCurrent, wszCurrentDir, MAX_PATH); 142 if (SUCCEEDED(res)) 143 SetCurrentDirectoryW(wszCurrentDir); 144 } 145 146 IShellFolder_Release(psfDesktop); 147 } 148 149 /* copied from shell32 to avoid linking to it */ 150 static BOOL COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl) 151 { 152 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest , len, src, pidl); 153 154 switch (src->uType) 155 { 156 case STRRET_WSTR: 157 lstrcpynW(dest, src->u.pOleStr, len); 158 COMDLG32_SHFree(src->u.pOleStr); 159 break; 160 161 case STRRET_CSTR: 162 if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len )) 163 ((LPWSTR)dest)[len-1] = 0; 164 break; 165 166 case STRRET_OFFSET: 167 if (pidl) 168 { 169 if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, 170 -1, dest, len )) 171 ((LPWSTR)dest)[len-1] = 0; 172 } 173 break; 174 175 default: 176 FIXME("unknown type!\n"); 177 if (len) 178 { *(LPWSTR)dest = '\0'; 179 } 180 return(FALSE); 181 } 182 return TRUE; 183 } 184 185 /* 186 * IShellBrowser 187 */ 188 189 /************************************************************************** 190 * IShellBrowserImpl_Construct 191 */ 192 IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner) 193 { 194 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndOwner); 195 IShellBrowserImpl *sb; 196 197 sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl)); 198 199 /* Initialisation of the member variables */ 200 sb->ref=1; 201 sb->hwndOwner = hwndOwner; 202 203 /* Initialisation of the vTables */ 204 sb->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl; 205 sb->ICommDlgBrowser_iface.lpVtbl = &IShellBrowserImpl_ICommDlgBrowser_Vtbl; 206 sb->IServiceProvider_iface.lpVtbl = &IShellBrowserImpl_IServiceProvider_Vtbl; 207 SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP, 208 &fodInfos->ShellInfos.pidlAbsCurrent); 209 210 TRACE("%p\n", sb); 211 212 return &sb->IShellBrowser_iface; 213 } 214 215 /*************************************************************************** 216 * IShellBrowserImpl_QueryInterface 217 */ 218 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppvObj) 219 { 220 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 221 222 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj); 223 224 *ppvObj = NULL; 225 226 if(IsEqualIID(riid, &IID_IUnknown)) 227 *ppvObj = &This->IShellBrowser_iface; 228 else if(IsEqualIID(riid, &IID_IOleWindow)) 229 *ppvObj = &This->IShellBrowser_iface; 230 else if(IsEqualIID(riid, &IID_IShellBrowser)) 231 *ppvObj = &This->IShellBrowser_iface; 232 else if(IsEqualIID(riid, &IID_ICommDlgBrowser)) 233 *ppvObj = &This->ICommDlgBrowser_iface; 234 else if(IsEqualIID(riid, &IID_IServiceProvider)) 235 *ppvObj = &This->IServiceProvider_iface; 236 237 if(*ppvObj) { 238 IUnknown_AddRef((IUnknown*)*ppvObj); 239 return S_OK; 240 } 241 242 FIXME("unsupported interface, %s\n", debugstr_guid(riid)); 243 return E_NOINTERFACE; 244 } 245 246 /************************************************************************** 247 * IShellBrowser::AddRef 248 */ 249 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface) 250 { 251 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 252 ULONG ref = InterlockedIncrement(&This->ref); 253 254 TRACE("(%p,%u)\n", This, ref - 1); 255 256 return ref; 257 } 258 259 /************************************************************************** 260 * IShellBrowserImpl_Release 261 */ 262 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface) 263 { 264 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 265 ULONG ref = InterlockedDecrement(&This->ref); 266 267 TRACE("(%p,%u)\n", This, ref + 1); 268 269 if (!ref) 270 { 271 COMDLG32_SHFree(This); 272 TRACE("-- destroyed\n"); 273 } 274 return ref; 275 } 276 277 /* 278 * IOleWindow 279 */ 280 281 /************************************************************************** 282 * IShellBrowserImpl_GetWindow (IOleWindow) 283 * 284 * Inherited from IOleWindow::GetWindow 285 * 286 * See Windows documentation for more details 287 * 288 * Note : We will never be window less in the File Open dialog 289 * 290 */ 291 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface, 292 HWND * phwnd) 293 { 294 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 295 296 TRACE("(%p)\n", This); 297 298 if(!This->hwndOwner) 299 return E_FAIL; 300 301 *phwnd = This->hwndOwner; 302 303 return (*phwnd) ? S_OK : E_UNEXPECTED; 304 305 } 306 307 /************************************************************************** 308 * IShellBrowserImpl_ContextSensitiveHelp 309 */ 310 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface, 311 BOOL fEnterMode) 312 { 313 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 314 315 TRACE("(%p)\n", This); 316 317 /* Feature not implemented */ 318 return E_NOTIMPL; 319 } 320 321 /* 322 * IShellBrowser 323 */ 324 325 /************************************************************************** 326 * IShellBrowserImpl_BrowseObject 327 * 328 * See Windows documentation on IShellBrowser::BrowseObject for more details 329 * 330 * This function will override user specified flags and will always 331 * use SBSP_DEFBROWSER and SBSP_DEFMODE. 332 */ 333 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface, 334 LPCITEMIDLIST pidl, 335 UINT wFlags) 336 { 337 HRESULT hRes; 338 IShellFolder *psfTmp; 339 IShellView *psvTmp; 340 FileOpenDlgInfos *fodInfos; 341 LPITEMIDLIST pidlTmp; 342 HWND hwndView; 343 HWND hDlgWnd; 344 BOOL bViewHasFocus; 345 RECT rectView; 346 347 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 348 349 TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags); 350 COMDLG32_DumpSBSPFlags(wFlags); 351 352 fodInfos = get_filedlg_infoptr(This->hwndOwner); 353 354 /* Format the pidl according to its parameter's category */ 355 if(wFlags & SBSP_RELATIVE) 356 { 357 358 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */ 359 if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder, 360 pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp))) 361 { 362 ERR("bind to object failed\n"); 363 return hRes; 364 } 365 /* create an absolute pidl */ 366 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl); 367 } 368 else if(wFlags & SBSP_PARENT) 369 { 370 /* Browse the parent folder (ignores the pidl) */ 371 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent); 372 psfTmp = GetShellFolderFromPidl(pidlTmp); 373 374 } 375 else /* SBSP_ABSOLUTE is 0x0000 */ 376 { 377 /* An absolute pidl (relative from the desktop) */ 378 pidlTmp = COMDLG32_PIDL_ILClone(pidl); 379 psfTmp = GetShellFolderFromPidl(pidlTmp); 380 } 381 382 if(!psfTmp) 383 { 384 ERR("could not browse to folder\n"); 385 return E_FAIL; 386 } 387 388 /* If the pidl to browse to is equal to the actual pidl ... 389 do nothing and pretend you did it*/ 390 if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent)) 391 { 392 IShellFolder_Release(psfTmp); 393 COMDLG32_SHFree(pidlTmp); 394 TRACE("keep current folder\n"); 395 return NOERROR; 396 } 397 398 /* Release the current DataObject */ 399 if (fodInfos->Shell.FOIDataObject) 400 { 401 IDataObject_Release(fodInfos->Shell.FOIDataObject); 402 fodInfos->Shell.FOIDataObject = NULL; 403 } 404 405 /* Create the associated view */ 406 TRACE("create view object\n"); 407 if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner, 408 &IID_IShellView, (LPVOID *)&psvTmp))) goto error; 409 410 /* Check if listview has focus */ 411 bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus()); 412 413 /* Get the foldersettings from the old view */ 414 if(fodInfos->Shell.FOIShellView) 415 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings); 416 417 /* Release the old fodInfos->Shell.FOIShellView and update its value. 418 We have to update this early since ShellView_CreateViewWindow of native 419 shell32 calls OnStateChange and needs the correct view here.*/ 420 if(fodInfos->Shell.FOIShellView) 421 { 422 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView); 423 IShellView_Release(fodInfos->Shell.FOIShellView); 424 } 425 fodInfos->Shell.FOIShellView = psvTmp; 426 427 /* Release old FOIShellFolder and update its value */ 428 if (fodInfos->Shell.FOIShellFolder) 429 IShellFolder_Release(fodInfos->Shell.FOIShellFolder); 430 fodInfos->Shell.FOIShellFolder = psfTmp; 431 432 /* Release old pidlAbsCurrent and update its value */ 433 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent); 434 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp; 435 436 COMDLG32_UpdateCurrentDir(fodInfos); 437 438 GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView); 439 MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2); 440 441 /* Create the window */ 442 TRACE("create view window\n"); 443 if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL, 444 &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser, 445 &rectView, &hwndView))) goto error; 446 447 fodInfos->ShellInfos.hwndView = hwndView; 448 449 /* Set view window control id to 5002 */ 450 SetWindowLongPtrW(hwndView, GWLP_ID, lst2); 451 SendMessageW( hwndView, WM_SETFONT, SendMessageW( GetParent(hwndView), WM_GETFONT, 0, 0 ), FALSE ); 452 453 /* Select the new folder in the Look In combo box of the Open file dialog */ 454 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent); 455 456 /* changes the tab order of the ListView to reflect the window's File Dialog */ 457 hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN); 458 SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); 459 460 /* Since we destroyed the old view if it had focus set focus to the newly created view */ 461 if (bViewHasFocus) 462 SetFocus(fodInfos->ShellInfos.hwndView); 463 464 return hRes; 465 error: 466 ERR("Failed with error 0x%08x\n", hRes); 467 return hRes; 468 } 469 470 /************************************************************************** 471 * IShellBrowserImpl_EnableModelessSB 472 */ 473 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface, 474 BOOL fEnable) 475 476 { 477 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 478 479 TRACE("(%p)\n", This); 480 481 /* Feature not implemented */ 482 return E_NOTIMPL; 483 } 484 485 /************************************************************************** 486 * IShellBrowserImpl_GetControlWindow 487 */ 488 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface, 489 UINT id, 490 HWND *lphwnd) 491 492 { 493 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 494 495 TRACE("(%p)\n", This); 496 497 /* Feature not implemented */ 498 return E_NOTIMPL; 499 } 500 501 /************************************************************************** 502 * IShellBrowserImpl_GetViewStateStream 503 */ 504 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface, 505 DWORD grfMode, 506 LPSTREAM *ppStrm) 507 508 { 509 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 510 511 FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm); 512 513 /* Feature not implemented */ 514 return E_NOTIMPL; 515 } 516 517 /************************************************************************** 518 * IShellBrowserImpl_InsertMenusSB 519 */ 520 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface, 521 HMENU hmenuShared, 522 LPOLEMENUGROUPWIDTHS lpMenuWidths) 523 524 { 525 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 526 527 TRACE("(%p)\n", This); 528 529 /* Feature not implemented */ 530 return E_NOTIMPL; 531 } 532 533 /************************************************************************** 534 * IShellBrowserImpl_OnViewWindowActive 535 */ 536 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface, 537 IShellView *ppshv) 538 539 { 540 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 541 542 TRACE("(%p)\n", This); 543 544 /* Feature not implemented */ 545 return E_NOTIMPL; 546 } 547 548 /************************************************************************** 549 * IShellBrowserImpl_QueryActiveShellView 550 */ 551 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface, 552 IShellView **ppshv) 553 554 { 555 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 556 557 FileOpenDlgInfos *fodInfos; 558 559 TRACE("(%p)\n", This); 560 561 fodInfos = get_filedlg_infoptr(This->hwndOwner); 562 563 if(!(*ppshv = fodInfos->Shell.FOIShellView)) 564 { 565 return E_FAIL; 566 } 567 IShellView_AddRef(fodInfos->Shell.FOIShellView); 568 return NOERROR; 569 } 570 571 /************************************************************************** 572 * IShellBrowserImpl_RemoveMenusSB 573 */ 574 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface, 575 HMENU hmenuShared) 576 577 { 578 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 579 580 TRACE("(%p)\n", This); 581 582 /* Feature not implemented */ 583 return E_NOTIMPL; 584 } 585 586 /************************************************************************** 587 * IShellBrowserImpl_SendControlMsg 588 */ 589 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface, 590 UINT id, 591 UINT uMsg, 592 WPARAM wParam, 593 LPARAM lParam, 594 LRESULT *pret) 595 596 { 597 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 598 LRESULT lres; 599 600 TRACE("(%p)->(0x%08x 0x%08x 0x%08lx 0x%08lx %p)\n", This, id, uMsg, wParam, lParam, pret); 601 602 switch (id) 603 { 604 case FCW_TOOLBAR: 605 lres = SendDlgItemMessageA( This->hwndOwner, IDC_TOOLBAR, uMsg, wParam, lParam); 606 break; 607 default: 608 FIXME("ctrl id: %x\n", id); 609 return E_NOTIMPL; 610 } 611 if (pret) *pret = lres; 612 return S_OK; 613 } 614 615 /************************************************************************** 616 * IShellBrowserImpl_SetMenuSB 617 */ 618 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface, 619 HMENU hmenuShared, 620 HOLEMENU holemenuReserved, 621 HWND hwndActiveObject) 622 623 { 624 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 625 626 TRACE("(%p)\n", This); 627 628 /* Feature not implemented */ 629 return E_NOTIMPL; 630 } 631 632 /************************************************************************** 633 * IShellBrowserImpl_SetStatusTextSB 634 */ 635 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface, 636 LPCOLESTR lpszStatusText) 637 638 { 639 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 640 641 TRACE("(%p)\n", This); 642 643 /* Feature not implemented */ 644 return E_NOTIMPL; 645 } 646 647 /************************************************************************** 648 * IShellBrowserImpl_SetToolbarItems 649 */ 650 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface, 651 LPTBBUTTON lpButtons, 652 UINT nButtons, 653 UINT uFlags) 654 655 { 656 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 657 658 TRACE("(%p)\n", This); 659 660 /* Feature not implemented */ 661 return E_NOTIMPL; 662 } 663 664 /************************************************************************** 665 * IShellBrowserImpl_TranslateAcceleratorSB 666 */ 667 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface, 668 LPMSG lpmsg, 669 WORD wID) 670 671 { 672 IShellBrowserImpl *This = impl_from_IShellBrowser(iface); 673 674 TRACE("(%p)\n", This); 675 676 /* Feature not implemented */ 677 return E_NOTIMPL; 678 } 679 680 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl = 681 { 682 /* IUnknown */ 683 IShellBrowserImpl_QueryInterface, 684 IShellBrowserImpl_AddRef, 685 IShellBrowserImpl_Release, 686 /* IOleWindow */ 687 IShellBrowserImpl_GetWindow, 688 IShellBrowserImpl_ContextSensitiveHelp, 689 /* IShellBrowser */ 690 IShellBrowserImpl_InsertMenusSB, 691 IShellBrowserImpl_SetMenuSB, 692 IShellBrowserImpl_RemoveMenusSB, 693 IShellBrowserImpl_SetStatusTextSB, 694 IShellBrowserImpl_EnableModelessSB, 695 IShellBrowserImpl_TranslateAcceleratorSB, 696 IShellBrowserImpl_BrowseObject, 697 IShellBrowserImpl_GetViewStateStream, 698 IShellBrowserImpl_GetControlWindow, 699 IShellBrowserImpl_SendControlMsg, 700 IShellBrowserImpl_QueryActiveShellView, 701 IShellBrowserImpl_OnViewWindowActive, 702 IShellBrowserImpl_SetToolbarItems 703 }; 704 705 706 707 /* 708 * ICommDlgBrowser 709 */ 710 711 /*************************************************************************** 712 * IShellBrowserImpl_ICommDlgBrowser_QueryInterface 713 */ 714 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface( 715 ICommDlgBrowser *iface, 716 REFIID riid, 717 LPVOID *ppvObj) 718 { 719 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 720 721 TRACE("(%p)\n", This); 722 723 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj); 724 } 725 726 /************************************************************************** 727 * IShellBrowserImpl_ICommDlgBrowser_AddRef 728 */ 729 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface) 730 { 731 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 732 733 TRACE("(%p)\n", This); 734 735 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface); 736 } 737 738 /************************************************************************** 739 * IShellBrowserImpl_ICommDlgBrowser_Release 740 */ 741 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface) 742 { 743 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 744 745 TRACE("(%p)\n", This); 746 747 return IShellBrowserImpl_Release(&This->IShellBrowser_iface); 748 } 749 750 /************************************************************************** 751 * IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand 752 * 753 * Called when a user double-clicks in the view or presses the ENTER key 754 */ 755 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface, 756 IShellView *ppshv) 757 { 758 LPITEMIDLIST pidl; 759 FileOpenDlgInfos *fodInfos; 760 761 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 762 763 TRACE("(%p)\n", This); 764 765 fodInfos = get_filedlg_infoptr(This->hwndOwner); 766 767 /* If the selected object is not a folder, send an IDOK command to parent window */ 768 if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1))) 769 { 770 HRESULT hRes; 771 772 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER; 773 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr); 774 if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) ) 775 { 776 hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE); 777 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) 778 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE); 779 } 780 else 781 { 782 /* Tell the dialog that the user selected a file */ 783 PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L); 784 hRes = S_OK; 785 } 786 787 /* Free memory used by pidl */ 788 COMDLG32_SHFree(pidl); 789 790 return hRes; 791 } 792 793 return E_FAIL; 794 } 795 796 /************************************************************************** 797 * IShellBrowserImpl_OnSelChange 798 */ 799 static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv) 800 { 801 FileOpenDlgInfos *fodInfos; 802 803 fodInfos = get_filedlg_infoptr(This->hwndOwner); 804 TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView); 805 806 /* release old selections */ 807 if (fodInfos->Shell.FOIDataObject) 808 IDataObject_Release(fodInfos->Shell.FOIDataObject); 809 810 /* get a new DataObject from the ShellView */ 811 if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION, 812 &IID_IDataObject, (void**)&fodInfos->Shell.FOIDataObject))) 813 return E_FAIL; 814 815 FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner); 816 817 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) 818 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE); 819 return S_OK; 820 } 821 822 /************************************************************************** 823 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange 824 */ 825 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface, 826 IShellView *ppshv, 827 ULONG uChange) 828 { 829 830 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 831 832 TRACE("(%p shv=%p)\n", This, ppshv); 833 834 switch (uChange) 835 { 836 case CDBOSC_SETFOCUS: 837 /* FIXME: Reset the default button. 838 This should be taken care of by defdlg. If control 839 other than button receives focus the default button 840 should be restored. */ 841 SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0); 842 843 break; 844 case CDBOSC_KILLFOCUS: 845 { 846 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(This->hwndOwner); 847 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) 848 { 849 WCHAR szSave[16]; 850 LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR)); 851 SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave); 852 } 853 } 854 break; 855 case CDBOSC_SELCHANGE: 856 return IShellBrowserImpl_OnSelChange(This, ppshv); 857 case CDBOSC_RENAME: 858 /* nothing to do */ 859 break; 860 } 861 862 return NOERROR; 863 } 864 865 /* send_includeitem_notification 866 * 867 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg 868 */ 869 static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl) 870 { 871 LRESULT hook_result = 0; 872 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndParentDlg); 873 874 if(!fodInfos) return 0; 875 876 if(fodInfos->DlgInfos.hwndCustomDlg) 877 { 878 TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl); 879 if(fodInfos->unicode) 880 { 881 OFNOTIFYEXW ofnNotify; 882 ofnNotify.psf = fodInfos->Shell.FOIShellFolder; 883 ofnNotify.pidl = (LPITEMIDLIST)pidl; 884 ofnNotify.hdr.hwndFrom = hwndParentDlg; 885 ofnNotify.hdr.idFrom = 0; 886 ofnNotify.hdr.code = CDN_INCLUDEITEM; 887 ofnNotify.lpOFN = fodInfos->ofnInfos; 888 hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify); 889 } 890 else 891 { 892 OFNOTIFYEXA ofnNotify; 893 ofnNotify.psf = fodInfos->Shell.FOIShellFolder; 894 ofnNotify.pidl = (LPITEMIDLIST)pidl; 895 ofnNotify.hdr.hwndFrom = hwndParentDlg; 896 ofnNotify.hdr.idFrom = 0; 897 ofnNotify.hdr.code = CDN_INCLUDEITEM; 898 ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos; 899 hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify); 900 } 901 } 902 TRACE("Retval: 0x%08lx\n", hook_result); 903 return hook_result; 904 } 905 906 /************************************************************************** 907 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject 908 */ 909 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface, 910 IShellView * ppshv, 911 LPCITEMIDLIST pidl) 912 { 913 FileOpenDlgInfos *fodInfos; 914 ULONG ulAttr; 915 STRRET str; 916 WCHAR szPathW[MAX_PATH]; 917 918 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 919 920 TRACE("(%p)\n", This); 921 922 fodInfos = get_filedlg_infoptr(This->hwndOwner); 923 924 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK; 925 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr); 926 927 if( (ulAttr & SFGAO_HIDDEN) || /* hidden */ 928 !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */ 929 return S_FALSE; 930 931 /* always include directories and links */ 932 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK)) 933 return S_OK; 934 935 /* if the application takes care of including the item we are done */ 936 if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY && 937 send_includeitem_notification(This->hwndOwner, pidl)) 938 return S_OK; 939 940 /* Check if there is a mask to apply if not */ 941 if(!fodInfos->ShellInfos.lpstrCurrentFilter || !fodInfos->ShellInfos.lpstrCurrentFilter[0]) 942 return S_OK; 943 944 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str))) 945 { 946 if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl)) 947 { 948 if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter)) 949 return S_OK; 950 } 951 } 952 return S_FALSE; 953 954 } 955 956 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl = 957 { 958 /* IUnknown */ 959 IShellBrowserImpl_ICommDlgBrowser_QueryInterface, 960 IShellBrowserImpl_ICommDlgBrowser_AddRef, 961 IShellBrowserImpl_ICommDlgBrowser_Release, 962 /* ICommDlgBrowser */ 963 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand, 964 IShellBrowserImpl_ICommDlgBrowser_OnStateChange, 965 IShellBrowserImpl_ICommDlgBrowser_IncludeObject 966 }; 967 968 969 970 971 /* 972 * IServiceProvider 973 */ 974 975 /*************************************************************************** 976 * IShellBrowserImpl_IServiceProvider_QueryInterface 977 */ 978 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface( 979 IServiceProvider *iface, 980 REFIID riid, 981 LPVOID *ppvObj) 982 { 983 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 984 985 FIXME("(%p)\n", This); 986 987 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj); 988 } 989 990 /************************************************************************** 991 * IShellBrowserImpl_IServiceProvider_AddRef 992 */ 993 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface) 994 { 995 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 996 997 FIXME("(%p)\n", This); 998 999 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface); 1000 } 1001 1002 /************************************************************************** 1003 * IShellBrowserImpl_IServiceProvider_Release 1004 */ 1005 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface) 1006 { 1007 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 1008 1009 FIXME("(%p)\n", This); 1010 1011 return IShellBrowserImpl_Release(&This->IShellBrowser_iface); 1012 } 1013 1014 /************************************************************************** 1015 * IShellBrowserImpl_IServiceProvider_Release 1016 * 1017 * NOTES 1018 * the w2k shellview asks for (guidService = SID_STopLevelBrowser, 1019 * riid = IShellBrowser) to call SendControlMsg (). 1020 * 1021 * FIXME 1022 * this is a hack! 1023 */ 1024 1025 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService( 1026 IServiceProvider * iface, 1027 REFGUID guidService, 1028 REFIID riid, 1029 void** ppv) 1030 { 1031 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 1032 1033 FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) ); 1034 1035 *ppv = NULL; 1036 if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser)) 1037 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppv); 1038 1039 FIXME("(%p) unknown interface requested\n", This); 1040 return E_NOINTERFACE; 1041 1042 } 1043 1044 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl = 1045 { 1046 /* IUnknown */ 1047 IShellBrowserImpl_IServiceProvider_QueryInterface, 1048 IShellBrowserImpl_IServiceProvider_AddRef, 1049 IShellBrowserImpl_IServiceProvider_Release, 1050 /* IServiceProvider */ 1051 IShellBrowserImpl_IServiceProvider_QueryService 1052 }; 1053