filedlgbrowser.c 28.9 KB
Newer Older
1 2
/*
 *  Implementation of IShellBrowser for the File Open common dialog
3
 *
4 5
 * Copyright 1999 Francois Boisvert
 * Copyright 1999, 2000 Juergen Schmied
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 21
 */

22
#include <stdarg.h>
23
#include <stdio.h>
24
#include <string.h>
25

26 27
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
28
#include "windef.h"
29
#include "winbase.h"
30
#include "winnls.h"
31
#include "wingdi.h"
32
#include "winuser.h"
33
#include "winreg.h"
34

35
#define NO_SHLWAPI_STREAM
36
#include "shlwapi.h"
37 38 39
#include "filedlgbrowser.h"
#include "cdlg.h"
#include "shlguid.h"
40
#include "servprov.h"
41
#include "wine/debug.h"
42

43
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
44

45
typedef struct
46 47
{

48 49 50
    IShellBrowserVtbl   * lpVtbl;
    ICommDlgBrowserVtbl * lpVtblCommDlgBrowser;
    IServiceProviderVtbl* lpVtblServiceProvider;
51 52
    DWORD ref;                                  /* Reference counter */
    HWND hwndOwner;                             /* Owner dialog of the interface */
53

54 55 56 57 58
} IShellBrowserImpl;

/**************************************************************************
*   vtable
*/
59 60 61
static IShellBrowserVtbl IShellBrowserImpl_Vtbl;
static ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl;
static IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl;
62 63 64 65 66 67

/**************************************************************************
*   Local Prototypes
*/

HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, IShellView *ppshv);
68 69 70
#if 0
LPITEMIDLIST GetSelectedPidl(IShellView *ppshv);
#endif
71 72 73 74

/**************************************************************************
*   External Prototypes
*/
75
extern const char *FileOpenDlgInfosStr;
76 77 78 79 80 81 82 83 84 85 86 87 88

extern HRESULT          GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
extern HRESULT          GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
extern IShellFolder*    GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
extern LPITEMIDLIST     GetParentPidl(LPITEMIDLIST pidl);
extern LPITEMIDLIST     GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);

extern BOOL    FILEDLG95_SHELL_FillIncludedItemList(HWND hwnd,
                                                        LPITEMIDLIST pidlCurrentFolder,
                                                        LPSTR lpstrMask);

extern int     FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
extern BOOL    FILEDLG95_OnOpen(HWND hwnd);
89
extern HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode);
90 91


92 93 94 95
/*
 *   Helper functions
 */

96 97 98
static void COMDLG32_UpdateCurrentDir(FileOpenDlgInfos *fodInfos)
{
    char lpstrPath[MAX_PATH];
99 100 101 102
    if(SHGetPathFromIDListA(fodInfos->ShellInfos.pidlAbsCurrent,lpstrPath)) {
        SetCurrentDirectoryA(lpstrPath);
        TRACE("new current folder %s\n", lpstrPath);
    }
103 104
}

105
/* copied from shell32 to avoid linking to it */
106
static HRESULT COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl)
107
{
Michael Stefaniuc's avatar
Michael Stefaniuc committed
108
	TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest,len,src,pidl);
109 110 111 112 113 114 115 116

	switch (src->uType)
	{
	  case STRRET_WSTR:
	    lstrcpynW((LPWSTR)dest, src->u.pOleStr, len);
	    COMDLG32_SHFree(src->u.pOleStr);
	    break;

117
	  case STRRET_CSTR:
118 119
            if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, (LPWSTR)dest, len ))
                ((LPWSTR)dest)[len-1] = 0;
120 121
	    break;

122
	  case STRRET_OFFSET:
123 124
	    if (pidl)
	    {
125 126 127
                if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset,
                                                 -1, (LPWSTR)dest, len ))
                    ((LPWSTR)dest)[len-1] = 0;
128 129 130 131 132 133
	    }
	    break;

	  default:
	    FIXME("unknown type!\n");
	    if (len)
134
	    { *(LPWSTR)dest = '\0';
135 136 137 138 139 140 141 142 143
	    }
	    return(FALSE);
	}
	return S_OK;
}

/*
 *	IShellBrowser
 */
144

145 146 147 148 149 150 151 152
/**************************************************************************
*  IShellBrowserImpl_Construct
*/
IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
{
    IShellBrowserImpl *sb;
    FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndOwner,FileOpenDlgInfosStr);

153
    sb=(IShellBrowserImpl*)COMDLG32_SHAlloc(sizeof(IShellBrowserImpl));
154 155 156 157 158 159 160

    /* Initialisation of the member variables */
    sb->ref=1;
    sb->hwndOwner = hwndOwner;

    /* Initialisation of the vTables */
    sb->lpVtbl = &IShellBrowserImpl_Vtbl;
161 162
    sb->lpVtblCommDlgBrowser = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
    sb->lpVtblServiceProvider = &IShellBrowserImpl_IServiceProvider_Vtbl;
163
    SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP,
164 165 166 167 168 169 170 171 172 173 174
                               &fodInfos->ShellInfos.pidlAbsCurrent);

    TRACE("%p\n", sb);

    return (IShellBrowser *) sb;
}

/***************************************************************************
*  IShellBrowserImpl_QueryInterface
*/
HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
175
                                            REFIID riid,
176 177 178 179
                                            LPVOID *ppvObj)
{
    ICOM_THIS(IShellBrowserImpl, iface);

180
    TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid));
181 182 183 184

    *ppvObj = NULL;

    if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
185
    { *ppvObj = This;
186 187 188 189 190 191 192 193 194 195
    }
    else if(IsEqualIID(riid, &IID_IOleWindow))  /*IOleWindow*/
    { *ppvObj = (IOleWindow*)This;
    }

    else if(IsEqualIID(riid, &IID_IShellBrowser))  /*IShellBrowser*/
    { *ppvObj = (IShellBrowser*)This;
    }

    else if(IsEqualIID(riid, &IID_ICommDlgBrowser))  /*ICommDlgBrowser*/
196 197 198 199 200
    { *ppvObj = (ICommDlgBrowser*) &(This->lpVtblCommDlgBrowser);
    }

    else if(IsEqualIID(riid, &IID_IServiceProvider))  /* IServiceProvider */
    { *ppvObj = (ICommDlgBrowser*) &(This->lpVtblServiceProvider);
201 202 203 204 205 206
    }

    if(*ppvObj)
    { IUnknown_AddRef( (IShellBrowser*) *ppvObj);
      return S_OK;
    }
207
    FIXME("Unknown interface requested\n");
208 209 210 211 212 213 214 215 216 217
    return E_NOINTERFACE;
}

/**************************************************************************
*  IShellBrowser::AddRef
*/
ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
{
    ICOM_THIS(IShellBrowserImpl, iface);

218
    TRACE("(%p,%lu)\n", This, This->ref);
219 220 221 222 223 224 225 226 227 228 229

    return ++(This->ref);
}

/**************************************************************************
*  IShellBrowserImpl_Release
*/
ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
{
    ICOM_THIS(IShellBrowserImpl, iface);

230
    TRACE("(%p,%lu)\n", This, This->ref);
231

232 233
    if (!--(This->ref))
    {
234
      COMDLG32_SHFree(This);
235
      TRACE("-- destroyed\n");
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
      return 0;
    }
    return This->ref;
}

/*
 * IOleWindow
 */

/**************************************************************************
*  IShellBrowserImpl_GetWindow  (IOleWindow)
*
*  Inherited from IOleWindow::GetWindow
*
*  See Windows documentation for more details
*
*  Note : We will never be window less in the File Open dialog
253
*
254
*/
255
HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
256 257 258 259 260 261 262 263 264 265 266
                                           HWND * phwnd)
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    if(!This->hwndOwner)
        return E_FAIL;

    *phwnd = This->hwndOwner;

267
    return (*phwnd) ? S_OK : E_UNEXPECTED;
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

}

/**************************************************************************
*  IShellBrowserImpl_ContextSensitiveHelp
*/
HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
                                                      BOOL fEnterMode)
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
}

/*
 * IShellBrowser
 */

/**************************************************************************
*  IShellBrowserImpl_BrowseObject
*
*  See Windows documentation on IShellBrowser::BrowseObject for more details
*
294 295
*  This function will override user specified flags and will always
*  use SBSP_DEFBROWSER and SBSP_DEFMODE.
296
*/
297 298
HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
                                              LPCITEMIDLIST pidl,
299 300 301 302 303 304 305
                                              UINT wFlags)
{
    HRESULT hRes;
    IShellFolder *psfTmp;
    IShellView *psvTmp;
    FileOpenDlgInfos *fodInfos;
    LPITEMIDLIST pidlTmp;
306 307 308
    HWND hwndView;
    HWND hDlgWnd;
    BOOL bViewHasFocus;
309
    RECT rectView;
310 311 312

    ICOM_THIS(IShellBrowserImpl, iface);

313 314 315 316
    TRACE("(%p)(pidl=%p,flags=0x%08x(%s))\n", This, pidl, wFlags,
	(wFlags & SBSP_RELATIVE) ? "SBSP_RELATIVE" :
	(wFlags & SBSP_PARENT) ? "SBSP_PARENT" :
 	(wFlags & SBSP_ABSOLUTE) ? "SBSP_ABSOLUTE" : "SBPS_????");
317 318 319 320 321 322

    fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);

    /* Format the pidl according to its parameter's category */
    if(wFlags & SBSP_RELATIVE)
    {
323

324
        /* SBSP_RELATIVE  A relative pidl (relative from the current folder) */
325 326
        if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
             pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
327
        {
328 329
            ERR("bind to object failed\n");
	    return hRes;
330 331
        }
        /* create an absolute pidl */
332
        pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent,
333 334 335 336 337 338 339 340 341
                                                        (LPITEMIDLIST)pidl);
    }
    else if(wFlags & SBSP_PARENT)
    {
        /* Browse the parent folder (ignores the pidl) */
        pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
        psfTmp = GetShellFolderFromPidl(pidlTmp);

    }
342
    else /* SBSP_ABSOLUTE is 0x0000 */
343 344
    {
        /* An absolute pidl (relative from the desktop) */
345
        pidlTmp =  COMDLG32_PIDL_ILClone((LPITEMIDLIST)pidl);
346 347
        psfTmp = GetShellFolderFromPidl(pidlTmp);
    }
348

349 350 351 352 353
    if(!psfTmp)
    {
      ERR("could not browse to folder\n");
      return E_FAIL;
    }
354

355
    /* If the pidl to browse to is equal to the actual pidl ...
356 357 358 359 360
       do nothing and pretend you did it*/
    if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
    {
        IShellFolder_Release(psfTmp);
	COMDLG32_SHFree(pidlTmp);
361
        TRACE("keep current folder\n");
362 363 364
        return NOERROR;
    }

365 366 367 368 369 370 371
    /* Release the current DataObject */
    if (fodInfos->Shell.FOIDataObject)
    {
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
      fodInfos->Shell.FOIDataObject = NULL;
    }

372
    /* Create the associated view */
373
    TRACE("create view object\n");
374
    if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner,
375
           &IID_IShellView, (LPVOID *)&psvTmp))) goto error;
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

    /* Check if listview has focus */
    bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus());

    /* Get the foldersettings from the old view */
    if(fodInfos->Shell.FOIShellView)
      IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings);

    /* Release the old fodInfos->Shell.FOIShellView and update its value.
    We have to update this early since ShellView_CreateViewWindow of native
    shell32 calls OnStateChange and needs the correct view here.*/
    if(fodInfos->Shell.FOIShellView)
    {
      IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
      IShellView_Release(fodInfos->Shell.FOIShellView);
    }
    fodInfos->Shell.FOIShellView = psvTmp;

    /* Release old FOIShellFolder and update its value */
395 396
    if (fodInfos->Shell.FOIShellFolder)
      IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
397 398
    fodInfos->Shell.FOIShellFolder = psfTmp;

399 400 401
    /* Release old pidlAbsCurrent and update its value */
    COMDLG32_SHFree((LPVOID)fodInfos->ShellInfos.pidlAbsCurrent);
    fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
402

403 404
    COMDLG32_UpdateCurrentDir(fodInfos);

405 406 407
    GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
    MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);

408 409 410 411
    /* Create the window */
    TRACE("create view window\n");
    if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
         &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
412
         &rectView, &hwndView))) goto error;
413

414 415 416
    fodInfos->ShellInfos.hwndView = hwndView;

    /* Select the new folder in the Look In combo box of the Open file dialog */
417
    FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent);
418 419

    /* changes the tab order of the ListView to reflect the window's File Dialog */
420
    hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN);
421 422 423 424 425 426
    SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

    /* Since we destroyed the old view if it had focus set focus to the newly created view */
    if (bViewHasFocus)
      SetFocus(fodInfos->ShellInfos.hwndView);

427
    return hRes;
428 429 430
error:
    ERR("Failed with error 0x%08lx\n", hRes);
    return hRes;
431 432 433 434 435
}

/**************************************************************************
*  IShellBrowserImpl_EnableModelessSB
*/
436
HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
437
                                              BOOL fEnable)
438

439 440 441 442 443 444 445 446 447 448 449 450
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
}

/**************************************************************************
*  IShellBrowserImpl_GetControlWindow
*/
451 452
HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
                                              UINT id,
453
                                              HWND *lphwnd)
454

455 456 457 458 459 460 461 462 463 464 465 466
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
}
/**************************************************************************
*  IShellBrowserImpl_GetViewStateStream
*/
HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
467
                                                DWORD grfMode,
468
                                                LPSTREAM *ppStrm)
469

470 471 472
{
    ICOM_THIS(IShellBrowserImpl, iface);

473
    FIXME("(%p 0x%08lx %p)\n", This, grfMode, ppStrm);
474 475 476

    /* Feature not implemented */
    return E_NOTIMPL;
477
}
478 479 480 481 482 483
/**************************************************************************
*  IShellBrowserImpl_InsertMenusSB
*/
HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
                                           HMENU hmenuShared,
                                           LPOLEMENUGROUPWIDTHS lpMenuWidths)
484

485 486 487 488 489 490 491 492 493 494 495 496 497
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
}
/**************************************************************************
*  IShellBrowserImpl_OnViewWindowActive
*/
HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
                                                IShellView *ppshv)
498

499 500 501 502 503 504 505
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
506
}
507 508 509 510 511
/**************************************************************************
*  IShellBrowserImpl_QueryActiveShellView
*/
HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
                                                  IShellView **ppshv)
512

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
{
    ICOM_THIS(IShellBrowserImpl, iface);

    FileOpenDlgInfos *fodInfos;

    TRACE("(%p)\n", This);

    fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);

    if(!(*ppshv = fodInfos->Shell.FOIShellView))
    {
        return E_FAIL;
    }
    IShellView_AddRef(fodInfos->Shell.FOIShellView);
    return NOERROR;
528
}
529 530 531 532 533
/**************************************************************************
*  IShellBrowserImpl_RemoveMenusSB
*/
HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
                                           HMENU hmenuShared)
534

535 536 537 538 539 540 541
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
542
}
543 544 545
/**************************************************************************
*  IShellBrowserImpl_SendControlMsg
*/
546 547 548 549
HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
                                            UINT id,
                                            UINT uMsg,
                                            WPARAM wParam,
550 551
                                            LPARAM lParam,
                                            LRESULT *pret)
552

553 554
{
    ICOM_THIS(IShellBrowserImpl, iface);
555
    LRESULT lres;
556

557
    TRACE("(%p)->(0x%08x 0x%08x 0x%08x 0x%08lx %p)\n", This, id, uMsg, wParam, lParam, pret);
558

559 560 561 562 563 564 565 566 567 568 569
    switch (id)
    {
      case FCW_TOOLBAR:
        lres = SendDlgItemMessageA( This->hwndOwner, IDC_TOOLBAR, uMsg, wParam, lParam);
	break;
      default:
        FIXME("ctrl id: %x\n", id);
        return E_NOTIMPL;
    }
    if (pret) *pret = lres;
    return S_OK;
570 571 572 573 574
}
/**************************************************************************
*  IShellBrowserImpl_SetMenuSB
*/
HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
575
                                       HMENU hmenuShared,
576 577
                                       HOLEMENU holemenuReserved,
                                       HWND hwndActiveObject)
578

579 580 581 582 583 584 585
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
586
}
587 588 589 590 591
/**************************************************************************
*  IShellBrowserImpl_SetStatusTextSB
*/
HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
                                             LPCOLESTR lpszStatusText)
592

593 594 595 596 597 598 599
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
600
}
601 602 603 604
/**************************************************************************
*  IShellBrowserImpl_SetToolbarItems
*/
HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
605 606
                                             LPTBBUTTON lpButtons,
                                             UINT nButtons,
607
                                             UINT uFlags)
608

609 610 611 612 613 614 615
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
616
}
617 618 619 620
/**************************************************************************
*  IShellBrowserImpl_TranslateAcceleratorSB
*/
HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
621
                                                    LPMSG lpmsg,
622
                                                    WORD wID)
623

624 625 626 627 628 629 630 631 632
{
    ICOM_THIS(IShellBrowserImpl, iface);

    TRACE("(%p)\n", This);

    /* Feature not implemented */
    return E_NOTIMPL;
}

633
static IShellBrowserVtbl IShellBrowserImpl_Vtbl =
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
{
        /* IUnknown */
        IShellBrowserImpl_QueryInterface,
        IShellBrowserImpl_AddRef,
        IShellBrowserImpl_Release,
        /* IOleWindow */
        IShellBrowserImpl_GetWindow,
        IShellBrowserImpl_ContextSensitiveHelp,
        /*  IShellBrowser */
        IShellBrowserImpl_InsertMenusSB,
        IShellBrowserImpl_SetMenuSB,
        IShellBrowserImpl_RemoveMenusSB,
        IShellBrowserImpl_SetStatusTextSB,
        IShellBrowserImpl_EnableModelessSB,
        IShellBrowserImpl_TranslateAcceleratorSB,
        IShellBrowserImpl_BrowseObject,
        IShellBrowserImpl_GetViewStateStream,
        IShellBrowserImpl_GetControlWindow,
        IShellBrowserImpl_SendControlMsg,
        IShellBrowserImpl_QueryActiveShellView,
        IShellBrowserImpl_OnViewWindowActive,
        IShellBrowserImpl_SetToolbarItems
};



660 661 662 663 664 665 666
/*
 * ICommDlgBrowser
 */

/***************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_QueryInterface
*/
667 668
HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(
	ICommDlgBrowser *iface,
669
	REFIID riid,
670
	LPVOID *ppvObj)
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
{
    _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);

    TRACE("(%p)\n", This);

    return IShellBrowserImpl_QueryInterface(This,riid,ppvObj);
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_AddRef
*/
ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
{
    _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);

    TRACE("(%p)\n", This);

    return IShellBrowserImpl_AddRef(This);
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_Release
*/
ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
{
    _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);

    TRACE("(%p)\n", This);

    return IShellBrowserImpl_Release(This);
}
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
*
*   Called when a user double-clicks in the view or presses the ENTER key
*/
HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
                                                                  IShellView *ppshv)
{
    LPITEMIDLIST pidl;
    FileOpenDlgInfos *fodInfos;

    _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);

    TRACE("(%p)\n", This);

717 718
    fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);

719
    /* If the selected object is not a folder, send a IDOK command to parent window */
720
    if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1)))
721 722 723 724
    {
        HRESULT hRes;

        ULONG  ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
725
        IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
726 727 728
	if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
	{
          hRes = IShellBrowser_BrowseObject((IShellBrowser *)This,pidl,SBSP_RELATIVE);
729
          SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
730
	}
731
        else
732
	{
733 734
          /* Tell the dialog that the user selected a file */
	  hRes = PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
735
	}
736 737

        /* Free memory used by pidl */
738
        COMDLG32_SHFree((LPVOID)pidl);
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

        return hRes;
    }

    return E_FAIL;
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnStateChange
*/
HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
                                                               IShellView *ppshv,
                                                               ULONG uChange)
{

    _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);

756
    TRACE("(%p shv=%p)\n", This, ppshv);
757 758 759 760

    switch (uChange)
    {
        case CDBOSC_SETFOCUS:
761 762 763 764 765 766
             /* FIXME: Reset the default button.
	        This should be taken care of by defdlg. If control
	        other than button receives focus the default button
	        should be restored. */
             SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0);

767
            break;
768
        case CDBOSC_KILLFOCUS:
769 770 771 772 773
	    {
		FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
		if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
		    SetDlgItemTextA(fodInfos->ShellInfos.hwndOwner,IDOK,"&Save");
            }
774 775 776 777
            break;
        case CDBOSC_SELCHANGE:
            return IShellBrowserImpl_ICommDlgBrowser_OnSelChange(iface,ppshv);
        case CDBOSC_RENAME:
778
	    /* nothing to do */
779 780 781
            break;
    }

782
    return NOERROR;
783
}
784

785 786 787
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_IncludeObject
*/
788
HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
789 790 791 792 793 794
                                                               IShellView * ppshv,
                                                               LPCITEMIDLIST pidl)
{
    FileOpenDlgInfos *fodInfos;
    ULONG ulAttr;
    STRRET str;
795
    WCHAR szPathW[MAX_PATH];
796 797 798 799 800 801 802 803 804

    _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);

    TRACE("(%p)\n", This);

    fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);

    ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK;
    IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
805

806 807
    if( (ulAttr & SFGAO_HIDDEN)                                         /* hidden */
      | !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
808
        return S_FALSE;
809

810
    /* always include directories and links */
811
    if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
812
        return S_OK;
813

814
    /* Check if there is a mask to apply if not */
815
    if(!fodInfos->ShellInfos.lpstrCurrentFilter || !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter))
816
        return S_OK;
817

818 819 820
    if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
    {
      if (SUCCEEDED(COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl)))
821
      {
822
	  if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
823 824 825 826 827
          return S_OK;
      }
    }
    return S_FALSE;

828 829 830 831
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnSelChange
832
*/
833 834
HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, IShellView *ppshv)
{
835
    FileOpenDlgInfos *fodInfos;
836

837 838
    _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);

839
    fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
840
    TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView);
841

842 843 844
    /* release old selections */
    if (fodInfos->Shell.FOIDataObject)
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
845

846 847 848 849
    /* get a new DataObject from the ShellView */
    if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION,
                              &IID_IDataObject, (LPVOID*)&fodInfos->Shell.FOIDataObject)))
      return E_FAIL;
850

851
    FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);
Alexandre Julliard's avatar
Alexandre Julliard committed
852

853 854
    SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
855
}
856

857
static ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
{
        /* IUnknown */
        IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
        IShellBrowserImpl_ICommDlgBrowser_AddRef,
        IShellBrowserImpl_ICommDlgBrowser_Release,
        /* ICommDlgBrowser */
        IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
        IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
        IShellBrowserImpl_ICommDlgBrowser_IncludeObject
};




/*
 * IServiceProvider
 */

/***************************************************************************
*  IShellBrowserImpl_IServiceProvider_QueryInterface
*/
HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
	IServiceProvider *iface,
881
	REFIID riid,
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
	LPVOID *ppvObj)
{
    _ICOM_THIS_FromIServiceProvider(IShellBrowser,iface);

    FIXME("(%p)\n", This);

    return IShellBrowserImpl_QueryInterface(This,riid,ppvObj);
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_AddRef
*/
ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
{
    _ICOM_THIS_FromIServiceProvider(IShellBrowser,iface);

    FIXME("(%p)\n", This);

    return IShellBrowserImpl_AddRef(This);
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*/
ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
{
    _ICOM_THIS_FromIServiceProvider(IShellBrowser,iface);

    FIXME("(%p)\n", This);

    return IShellBrowserImpl_Release(This);
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*
* NOTES
919 920
*  the w2k shellview asks for (guidService = SID_STopLevelBrowser,
*  riid = IShellBrowser) to call SendControlMsg ().
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
*
* FIXME
*  this is a hack!
*/

HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
	IServiceProvider * iface,
	REFGUID guidService,
	REFIID riid,
	void** ppv)
{
    _ICOM_THIS_FromIServiceProvider(IShellBrowser,iface);

    FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) );

    *ppv = NULL;
    if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
    {
      return IShellBrowserImpl_QueryInterface(This,riid,ppv);
    }
    FIXME("(%p) unknown interface requested\n", This);
    return E_NOINTERFACE;

}

946
static IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
947 948 949 950 951 952 953 954
{
        /* IUnknown */
        IShellBrowserImpl_IServiceProvider_QueryInterface,
        IShellBrowserImpl_IServiceProvider_AddRef,
        IShellBrowserImpl_IServiceProvider_Release,
        /* IServiceProvider */
        IShellBrowserImpl_IServiceProvider_QueryService
};