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