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