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 #define NONAMELESSSTRUCT 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "winnls.h" 33 #include "wingdi.h" 34 #include "winuser.h" 35 #include "winreg.h" 36 37 #define NO_SHLWAPI_STREAM 38 #include "shlwapi.h" 39 #include "filedlgbrowser.h" 40 #include "cdlg.h" 41 #include "shlguid.h" 42 #include "servprov.h" 43 #include "wine/debug.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(commdlg); 46 47 typedef struct 48 { 49 50 const IShellBrowserVtbl *lpVtbl; 51 const ICommDlgBrowserVtbl *lpVtblCommDlgBrowser; 52 const IServiceProviderVtbl *lpVtblServiceProvider; 53 LONG ref; /* Reference counter */ 54 HWND hwndOwner; /* Owner dialog of the interface */ 55 56 } IShellBrowserImpl; 57 58 static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface ) 59 { 60 return (IShellBrowserImpl *)((char*)iface - FIELD_OFFSET(IShellBrowserImpl, lpVtblCommDlgBrowser)); 61 } 62 63 static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface ) 64 { 65 return (IShellBrowserImpl *)((char*)iface - FIELD_OFFSET(IShellBrowserImpl, lpVtblServiceProvider)); 66 } 67 68 /************************************************************************** 69 * vtable 70 */ 71 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl; 72 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl; 73 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl; 74 75 /************************************************************************** 76 * Local Prototypes 77 */ 78 79 static HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, const IShellView *ppshv); 80 81 /* 82 * Helper functions 83 */ 84 85 #define add_flag(a) if (flags & a) {strcat(str, #a );strcat(str," ");} 86 static void COMDLG32_DumpSBSPFlags(UINT uflags) 87 { 88 if (TRACE_ON(commdlg)) 89 { 90 unsigned int i; 91 static const struct { 92 DWORD mask; 93 const char *name; 94 } flags[] = { 95 #define FE(x) { x, #x} 96 /* SBSP_DEFBROWSER == 0 */ 97 FE(SBSP_SAMEBROWSER), 98 FE(SBSP_NEWBROWSER), 99 100 /* SBSP_DEFMODE == 0 */ 101 FE(SBSP_OPENMODE), 102 FE(SBSP_EXPLOREMODE), 103 FE(SBSP_HELPMODE), 104 FE(SBSP_NOTRANSFERHIST), 105 106 /* SBSP_ABSOLUTE == 0 */ 107 FE(SBSP_RELATIVE), 108 FE(SBSP_PARENT), 109 FE(SBSP_NAVIGATEBACK), 110 FE(SBSP_NAVIGATEFORWARD), 111 FE(SBSP_ALLOW_AUTONAVIGATE), 112 113 FE(SBSP_NOAUTOSELECT), 114 FE(SBSP_WRITENOHISTORY), 115 116 FE(SBSP_REDIRECT), 117 FE(SBSP_INITIATEDBYHLINKFRAME), 118 }; 119 #undef FE 120 TRACE("SBSP Flags: %08x =", uflags); 121 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) 122 if (flags[i].mask & uflags) 123 TRACE("%s ", flags[i].name); 124 TRACE("\n"); 125 } 126 } 127 128 static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos) 129 { 130 LPSHELLFOLDER psfDesktop; 131 STRRET strret; 132 HRESULT res; 133 134 res = SHGetDesktopFolder(&psfDesktop); 135 if (FAILED(res)) 136 return; 137 138 res = IShellFolder_GetDisplayNameOf(psfDesktop, fodInfos->ShellInfos.pidlAbsCurrent, 139 SHGDN_FORPARSING, &strret); 140 if (SUCCEEDED(res)) { 141 WCHAR wszCurrentDir[MAX_PATH]; 142 143 res = StrRetToBufW(&strret, fodInfos->ShellInfos.pidlAbsCurrent, wszCurrentDir, MAX_PATH); 144 if (SUCCEEDED(res)) 145 SetCurrentDirectoryW(wszCurrentDir); 146 } 147 148 IShellFolder_Release(psfDesktop); 149 } 150 151 /* copied from shell32 to avoid linking to it */ 152 static BOOL COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl) 153 { 154 TRACE("dest=%p len=0x%x strret=%p pidl=%p stub\n",dest,len,src,pidl); 155 156 switch (src->uType) 157 { 158 case STRRET_WSTR: 159 lstrcpynW(dest, src->u.pOleStr, len); 160 COMDLG32_SHFree(src->u.pOleStr); 161 break; 162 163 case STRRET_CSTR: 164 if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len )) 165 ((LPWSTR)dest)[len-1] = 0; 166 break; 167 168 case STRRET_OFFSET: 169 if (pidl) 170 { 171 if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, 172 -1, dest, len )) 173 ((LPWSTR)dest)[len-1] = 0; 174 } 175 break; 176 177 default: 178 FIXME("unknown type!\n"); 179 if (len) 180 { *(LPWSTR)dest = '\0'; 181 } 182 return(FALSE); 183 } 184 return TRUE; 185 } 186 187 /* 188 * IShellBrowser 189 */ 190 191 /************************************************************************** 192 * IShellBrowserImpl_Construct 193 */ 194 IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner) 195 { 196 IShellBrowserImpl *sb; 197 FileOpenDlgInfos *fodInfos = GetPropA(hwndOwner,FileOpenDlgInfosStr); 198 199 sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl)); 200 201 /* Initialisation of the member variables */ 202 sb->ref=1; 203 sb->hwndOwner = hwndOwner; 204 205 /* Initialisation of the vTables */ 206 sb->lpVtbl = &IShellBrowserImpl_Vtbl; 207 sb->lpVtblCommDlgBrowser = &IShellBrowserImpl_ICommDlgBrowser_Vtbl; 208 sb->lpVtblServiceProvider = &IShellBrowserImpl_IServiceProvider_Vtbl; 209 SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP, 210 &fodInfos->ShellInfos.pidlAbsCurrent); 211 212 TRACE("%p\n", sb); 213 214 return (IShellBrowser *) sb; 215 } 216 217 /*************************************************************************** 218 * IShellBrowserImpl_QueryInterface 219 */ 220 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface, 221 REFIID riid, 222 LPVOID *ppvObj) 223 { 224 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 225 226 TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid)); 227 228 *ppvObj = NULL; 229 230 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ 231 { *ppvObj = This; 232 } 233 else if(IsEqualIID(riid, &IID_IOleWindow)) /*IOleWindow*/ 234 { *ppvObj = This; 235 } 236 237 else if(IsEqualIID(riid, &IID_IShellBrowser)) /*IShellBrowser*/ 238 { *ppvObj = This; 239 } 240 241 else if(IsEqualIID(riid, &IID_ICommDlgBrowser)) /*ICommDlgBrowser*/ 242 { *ppvObj = &(This->lpVtblCommDlgBrowser); 243 } 244 245 else if(IsEqualIID(riid, &IID_IServiceProvider)) /* IServiceProvider */ 246 { *ppvObj = &(This->lpVtblServiceProvider); 247 } 248 249 if(*ppvObj) 250 { IUnknown_AddRef( (IShellBrowser*) *ppvObj); 251 return S_OK; 252 } 253 FIXME("Unknown interface requested\n"); 254 return E_NOINTERFACE; 255 } 256 257 /************************************************************************** 258 * IShellBrowser::AddRef 259 */ 260 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface) 261 { 262 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 263 ULONG ref = InterlockedIncrement(&This->ref); 264 265 TRACE("(%p,%u)\n", This, ref - 1); 266 267 return ref; 268 } 269 270 /************************************************************************** 271 * IShellBrowserImpl_Release 272 */ 273 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface) 274 { 275 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 276 ULONG ref = InterlockedDecrement(&This->ref); 277 278 TRACE("(%p,%u)\n", This, ref + 1); 279 280 if (!ref) 281 { 282 COMDLG32_SHFree(This); 283 TRACE("-- destroyed\n"); 284 return 0; 285 } 286 return ref; 287 } 288 289 /* 290 * IOleWindow 291 */ 292 293 /************************************************************************** 294 * IShellBrowserImpl_GetWindow (IOleWindow) 295 * 296 * Inherited from IOleWindow::GetWindow 297 * 298 * See Windows documentation for more details 299 * 300 * Note : We will never be window less in the File Open dialog 301 * 302 */ 303 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface, 304 HWND * phwnd) 305 { 306 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 307 308 TRACE("(%p)\n", This); 309 310 if(!This->hwndOwner) 311 return E_FAIL; 312 313 *phwnd = This->hwndOwner; 314 315 return (*phwnd) ? S_OK : E_UNEXPECTED; 316 317 } 318 319 /************************************************************************** 320 * IShellBrowserImpl_ContextSensitiveHelp 321 */ 322 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface, 323 BOOL fEnterMode) 324 { 325 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 326 327 TRACE("(%p)\n", This); 328 329 /* Feature not implemented */ 330 return E_NOTIMPL; 331 } 332 333 /* 334 * IShellBrowser 335 */ 336 337 /************************************************************************** 338 * IShellBrowserImpl_BrowseObject 339 * 340 * See Windows documentation on IShellBrowser::BrowseObject for more details 341 * 342 * This function will override user specified flags and will always 343 * use SBSP_DEFBROWSER and SBSP_DEFMODE. 344 */ 345 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface, 346 LPCITEMIDLIST pidl, 347 UINT wFlags) 348 { 349 HRESULT hRes; 350 IShellFolder *psfTmp; 351 IShellView *psvTmp; 352 FileOpenDlgInfos *fodInfos; 353 LPITEMIDLIST pidlTmp; 354 HWND hwndView; 355 HWND hDlgWnd; 356 BOOL bViewHasFocus; 357 RECT rectView; 358 359 IShellBrowserImpl *This = (IShellBrowserImpl *)iface; 360 361 TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags); 362 COMDLG32_DumpSBSPFlags(wFlags); 363 364 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 365 366 /* Format the pidl according to its parameter's category */ 367 if(wFlags & SBSP_RELATIVE) 368 { 369 370 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */ 371 if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder, 372 pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp))) 373 { 374 ERR("bind to object failed\n"); 375 return hRes; 376 } 377 /* create an absolute pidl */ 378 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl); 379 } 380 else if(wFlags & SBSP_PARENT) 381 { 382 /* Browse the parent folder (ignores the pidl) */ 383 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent); 384 psfTmp = GetShellFolderFromPidl(pidlTmp); 385 386 } 387 else /* SBSP_ABSOLUTE is 0x0000 */ 388 { 389 /* An absolute pidl (relative from the desktop) */ 390 pidlTmp = COMDLG32_PIDL_ILClone(pidl); 391 psfTmp = GetShellFolderFromPidl(pidlTmp); 392 } 393 394 if(!psfTmp) 395 { 396 ERR("could not browse to folder\n"); 397 return E_FAIL; 398 } 399 400 /* If the pidl to browse to is equal to the actual pidl ... 401 do nothing and pretend you did it*/ 402 if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent)) 403 { 404 IShellFolder_Release(psfTmp); 405 COMDLG32_SHFree(pidlTmp); 406 TRACE("keep current folder\n"); 407 return NOERROR; 408 } 409 410 /* Release the current DataObject */ 411 if (fodInfos->Shell.FOIDataObject) 412 { 413 IDataObject_Release(fodInfos->Shell.FOIDataObject); 414 fodInfos->Shell.FOIDataObject = NULL; 415 } 416 417 /* Create the associated view */ 418 TRACE("create view object\n"); 419 if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner, 420 &IID_IShellView, (LPVOID *)&psvTmp))) goto error; 421 422 /* Check if listview has focus */ 423 bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus()); 424 425 /* Get the foldersettings from the old view */ 426 if(fodInfos->Shell.FOIShellView) 427 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings); 428 429 /* Release the old fodInfos->Shell.FOIShellView and update its value. 430 We have to update this early since ShellView_CreateViewWindow of native 431 shell32 calls OnStateChange and needs the correct view here.*/ 432 if(fodInfos->Shell.FOIShellView) 433 { 434 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView); 435 IShellView_Release(fodInfos->Shell.FOIShellView); 436 } 437 fodInfos->Shell.FOIShellView = psvTmp; 438 439 /* Release old FOIShellFolder and update its value */ 440 if (fodInfos->Shell.FOIShellFolder) 441 IShellFolder_Release(fodInfos->Shell.FOIShellFolder); 442 fodInfos->Shell.FOIShellFolder = psfTmp; 443 444 /* Release old pidlAbsCurrent and update its value */ 445 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent); 446 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp; 447 448 COMDLG32_UpdateCurrentDir(fodInfos); 449 450 GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView); 451 MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2); 452 453 /* Create the window */ 454 TRACE("create view window\n"); 455 if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL, 456 &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser, 457 &rectView, &hwndView))) goto error; 458 459 fodInfos->ShellInfos.hwndView = hwndView; 460 461 /* Set view window control id to 5002 */ 462 SetWindowLongPtrW(hwndView, GWLP_ID, lst2); 463 464 /* Select the new folder in the Look In combo box of the Open file dialog */ 465 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent); 466 467 /* changes the tab order of the ListView to reflect the window's File Dialog */ 468 hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN); 469 SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); 470 471 /* Since we destroyed the old view if it had focus set focus to the newly created view */ 472 if (bViewHasFocus) 473 SetFocus(fodInfos->ShellInfos.hwndView); 474 475 return hRes; 476 error: 477 ERR("Failed with error 0x%08x\n", hRes); 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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)iface; 567 568 FileOpenDlgInfos *fodInfos; 569 570 TRACE("(%p)\n", This); 571 572 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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 = (IShellBrowserImpl *)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((IShellBrowser *)This,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((IShellBrowser *)This); 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((IShellBrowser *)This); 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 = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 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; 784 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr); 785 if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) ) 786 { 787 hRes = IShellBrowser_BrowseObject((IShellBrowser *)This,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 /* Free memory used by pidl */ 799 COMDLG32_SHFree(pidl); 800 801 return hRes; 802 } 803 804 return E_FAIL; 805 } 806 807 /************************************************************************** 808 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange 809 */ 810 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface, 811 IShellView *ppshv, 812 ULONG uChange) 813 { 814 815 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 816 817 TRACE("(%p shv=%p)\n", This, ppshv); 818 819 switch (uChange) 820 { 821 case CDBOSC_SETFOCUS: 822 /* FIXME: Reset the default button. 823 This should be taken care of by defdlg. If control 824 other than button receives focus the default button 825 should be restored. */ 826 SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0); 827 828 break; 829 case CDBOSC_KILLFOCUS: 830 { 831 FileOpenDlgInfos *fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 832 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) 833 { 834 WCHAR szSave[16]; 835 LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR)); 836 SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave); 837 } 838 } 839 break; 840 case CDBOSC_SELCHANGE: 841 return IShellBrowserImpl_ICommDlgBrowser_OnSelChange(iface,ppshv); 842 case CDBOSC_RENAME: 843 /* nothing to do */ 844 break; 845 } 846 847 return NOERROR; 848 } 849 850 /* send_includeitem_notification 851 * 852 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg 853 */ 854 static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl) 855 { 856 LRESULT hook_result = 0; 857 FileOpenDlgInfos *fodInfos = GetPropA(hwndParentDlg, FileOpenDlgInfosStr); 858 859 if(!fodInfos) return 0; 860 861 if(fodInfos->DlgInfos.hwndCustomDlg) 862 { 863 TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl); 864 if(fodInfos->unicode) 865 { 866 OFNOTIFYEXW ofnNotify; 867 ofnNotify.psf = fodInfos->Shell.FOIShellFolder; 868 ofnNotify.pidl = (LPITEMIDLIST)pidl; 869 ofnNotify.hdr.hwndFrom = hwndParentDlg; 870 ofnNotify.hdr.idFrom = 0; 871 ofnNotify.hdr.code = CDN_INCLUDEITEM; 872 ofnNotify.lpOFN = fodInfos->ofnInfos; 873 hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify); 874 } 875 else 876 { 877 OFNOTIFYEXA ofnNotify; 878 ofnNotify.psf = fodInfos->Shell.FOIShellFolder; 879 ofnNotify.pidl = (LPITEMIDLIST)pidl; 880 ofnNotify.hdr.hwndFrom = hwndParentDlg; 881 ofnNotify.hdr.idFrom = 0; 882 ofnNotify.hdr.code = CDN_INCLUDEITEM; 883 ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos; 884 hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify); 885 } 886 } 887 TRACE("Retval: 0x%08lx\n", hook_result); 888 return hook_result; 889 } 890 891 /************************************************************************** 892 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject 893 */ 894 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface, 895 IShellView * ppshv, 896 LPCITEMIDLIST pidl) 897 { 898 FileOpenDlgInfos *fodInfos; 899 ULONG ulAttr; 900 STRRET str; 901 WCHAR szPathW[MAX_PATH]; 902 903 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 904 905 TRACE("(%p)\n", This); 906 907 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 908 909 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK; 910 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr); 911 912 if( (ulAttr & SFGAO_HIDDEN) || /* hidden */ 913 !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */ 914 return S_FALSE; 915 916 /* always include directories and links */ 917 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK)) 918 return S_OK; 919 920 /* if the application takes care of including the item we are done */ 921 if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY && 922 send_includeitem_notification(This->hwndOwner, pidl)) 923 return S_OK; 924 925 /* Check if there is a mask to apply if not */ 926 if(!fodInfos->ShellInfos.lpstrCurrentFilter || !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter)) 927 return S_OK; 928 929 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str))) 930 { 931 if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl)) 932 { 933 if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter)) 934 return S_OK; 935 } 936 } 937 return S_FALSE; 938 939 } 940 941 /************************************************************************** 942 * IShellBrowserImpl_ICommDlgBrowser_OnSelChange 943 */ 944 static HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, const IShellView *ppshv) 945 { 946 FileOpenDlgInfos *fodInfos; 947 948 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface); 949 950 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr); 951 TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView); 952 953 /* release old selections */ 954 if (fodInfos->Shell.FOIDataObject) 955 IDataObject_Release(fodInfos->Shell.FOIDataObject); 956 957 /* get a new DataObject from the ShellView */ 958 if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION, 959 &IID_IDataObject, (LPVOID*)&fodInfos->Shell.FOIDataObject))) 960 return E_FAIL; 961 962 FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner); 963 964 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER) 965 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE); 966 return S_OK; 967 } 968 969 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl = 970 { 971 /* IUnknown */ 972 IShellBrowserImpl_ICommDlgBrowser_QueryInterface, 973 IShellBrowserImpl_ICommDlgBrowser_AddRef, 974 IShellBrowserImpl_ICommDlgBrowser_Release, 975 /* ICommDlgBrowser */ 976 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand, 977 IShellBrowserImpl_ICommDlgBrowser_OnStateChange, 978 IShellBrowserImpl_ICommDlgBrowser_IncludeObject 979 }; 980 981 982 983 984 /* 985 * IServiceProvider 986 */ 987 988 /*************************************************************************** 989 * IShellBrowserImpl_IServiceProvider_QueryInterface 990 */ 991 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface( 992 IServiceProvider *iface, 993 REFIID riid, 994 LPVOID *ppvObj) 995 { 996 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 997 998 FIXME("(%p)\n", This); 999 1000 return IShellBrowserImpl_QueryInterface((IShellBrowser *)This,riid,ppvObj); 1001 } 1002 1003 /************************************************************************** 1004 * IShellBrowserImpl_IServiceProvider_AddRef 1005 */ 1006 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface) 1007 { 1008 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 1009 1010 FIXME("(%p)\n", This); 1011 1012 return IShellBrowserImpl_AddRef((IShellBrowser *)This); 1013 } 1014 1015 /************************************************************************** 1016 * IShellBrowserImpl_IServiceProvider_Release 1017 */ 1018 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface) 1019 { 1020 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 1021 1022 FIXME("(%p)\n", This); 1023 1024 return IShellBrowserImpl_Release((IShellBrowser *)This); 1025 } 1026 1027 /************************************************************************** 1028 * IShellBrowserImpl_IServiceProvider_Release 1029 * 1030 * NOTES 1031 * the w2k shellview asks for (guidService = SID_STopLevelBrowser, 1032 * riid = IShellBrowser) to call SendControlMsg (). 1033 * 1034 * FIXME 1035 * this is a hack! 1036 */ 1037 1038 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService( 1039 IServiceProvider * iface, 1040 REFGUID guidService, 1041 REFIID riid, 1042 void** ppv) 1043 { 1044 IShellBrowserImpl *This = impl_from_IServiceProvider(iface); 1045 1046 FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) ); 1047 1048 *ppv = NULL; 1049 if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser)) 1050 { 1051 return IShellBrowserImpl_QueryInterface((IShellBrowser *)This,riid,ppv); 1052 } 1053 FIXME("(%p) unknown interface requested\n", This); 1054 return E_NOINTERFACE; 1055 1056 } 1057 1058 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl = 1059 { 1060 /* IUnknown */ 1061 IShellBrowserImpl_IServiceProvider_QueryInterface, 1062 IShellBrowserImpl_IServiceProvider_AddRef, 1063 IShellBrowserImpl_IServiceProvider_Release, 1064 /* IServiceProvider */ 1065 IShellBrowserImpl_IServiceProvider_QueryService 1066 }; 1067