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