filedlgbrowser.c 32.3 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
 * 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
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 28
#define NONAMELESSUNION
#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 40 41
#include "filedlgbrowser.h"
#include "cdlg.h"
#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 51 52
    const IShellBrowserVtbl *lpVtbl;
    const ICommDlgBrowserVtbl *lpVtblCommDlgBrowser;
    const IServiceProviderVtbl *lpVtblServiceProvider;
53
    LONG ref;                                   /* Reference counter */
54
    HWND hwndOwner;                             /* Owner dialog of the interface */
55

56 57
} IShellBrowserImpl;

58 59 60 61 62 63 64 65 66 67
static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface )
{
    return (IShellBrowserImpl *)((char*)iface - FIELD_OFFSET(IShellBrowserImpl, lpVtblCommDlgBrowser));
}

static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface )
{
    return (IShellBrowserImpl *)((char*)iface - FIELD_OFFSET(IShellBrowserImpl, lpVtblServiceProvider));
}

68 69 70
/**************************************************************************
*   vtable
*/
71 72 73
static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl;
static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl;
74 75 76 77 78

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

79
static HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, const IShellView *ppshv);
80

81 82 83 84
/*
 *   Helper functions
 */

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
#define add_flag(a) if (flags & a) {strcat(str, #a );strcat(str," ");}
static void COMDLG32_DumpSBSPFlags(UINT uflags)
{
    if (TRACE_ON(commdlg))
    {
	unsigned int   i;
	static const struct {
	    DWORD       mask;
	    const char  *name;
	} flags[] = {
#define FE(x) { x, #x}
            /* SBSP_DEFBROWSER == 0 */
            FE(SBSP_SAMEBROWSER),
            FE(SBSP_NEWBROWSER),

            /* SBSP_DEFMODE == 0 */
            FE(SBSP_OPENMODE),
            FE(SBSP_EXPLOREMODE),
            FE(SBSP_HELPMODE),
            FE(SBSP_NOTRANSFERHIST),

            /* SBSP_ABSOLUTE == 0 */
            FE(SBSP_RELATIVE),
            FE(SBSP_PARENT),
            FE(SBSP_NAVIGATEBACK),
            FE(SBSP_NAVIGATEFORWARD),
            FE(SBSP_ALLOW_AUTONAVIGATE),

            FE(SBSP_NOAUTOSELECT),
            FE(SBSP_WRITENOHISTORY),

            FE(SBSP_REDIRECT),
            FE(SBSP_INITIATEDBYHLINKFRAME),
        };
#undef FE
120
        TRACE("SBSP Flags: %08x =", uflags);
121 122
	for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
	    if (flags[i].mask & uflags)
123 124
		TRACE("%s ", flags[i].name);
	TRACE("\n");
125 126 127
    }
}

128
static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos)
129
{
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
    LPSHELLFOLDER psfDesktop;
    STRRET strret;
    HRESULT res;

    res = SHGetDesktopFolder(&psfDesktop);
    if (FAILED(res))
        return;
    
    res = IShellFolder_GetDisplayNameOf(psfDesktop, fodInfos->ShellInfos.pidlAbsCurrent,
                                        SHGDN_FORPARSING, &strret);
    if (SUCCEEDED(res)) {
        WCHAR wszCurrentDir[MAX_PATH];
        
        res = StrRetToBufW(&strret, fodInfos->ShellInfos.pidlAbsCurrent, wszCurrentDir, MAX_PATH);
        if (SUCCEEDED(res))
            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 157 158

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

163
	  case STRRET_CSTR:
164
            if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
165
                ((LPWSTR)dest)[len-1] = 0;
166 167
	    break;

168
	  case STRRET_OFFSET:
169 170
	    if (pidl)
	    {
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 176 177 178 179
	    }
	    break;

	  default:
	    FIXME("unknown type!\n");
	    if (len)
180
	    { *(LPWSTR)dest = '\0';
181 182 183
	    }
	    return(FALSE);
	}
184
        return TRUE;
185 186 187 188 189
}

/*
 *	IShellBrowser
 */
190

191 192 193 194 195 196
/**************************************************************************
*  IShellBrowserImpl_Construct
*/
IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
{
    IShellBrowserImpl *sb;
197
    FileOpenDlgInfos *fodInfos = GetPropA(hwndOwner,FileOpenDlgInfosStr);
198

199
    sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl));
200 201 202 203 204 205 206

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

    /* Initialisation of the vTables */
    sb->lpVtbl = &IShellBrowserImpl_Vtbl;
207 208
    sb->lpVtblCommDlgBrowser = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
    sb->lpVtblServiceProvider = &IShellBrowserImpl_IServiceProvider_Vtbl;
209
    SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP,
210 211 212 213 214 215 216 217 218 219
                               &fodInfos->ShellInfos.pidlAbsCurrent);

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

    return (IShellBrowser *) sb;
}

/***************************************************************************
*  IShellBrowserImpl_QueryInterface
*/
Mike McCormack's avatar
Mike McCormack committed
220
static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
221
                                            REFIID riid,
222 223
                                            LPVOID *ppvObj)
{
224
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
225

226
    TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid));
227 228 229 230

    *ppvObj = NULL;

    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 250 251 252
    }

    if(*ppvObj)
    { IUnknown_AddRef( (IShellBrowser*) *ppvObj);
      return S_OK;
    }
253
    FIXME("Unknown interface requested\n");
254 255 256 257 258 259
    return E_NOINTERFACE;
}

/**************************************************************************
*  IShellBrowser::AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
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 272
}

/**************************************************************************
*  IShellBrowserImpl_Release
*/
Mike McCormack's avatar
Mike McCormack committed
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 285
      return 0;
    }
286
    return ref;
287 288 289 290 291 292 293 294 295 296 297 298 299 300
}

/*
 * 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
301
*
302
*/
Mike McCormack's avatar
Mike McCormack committed
303
static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
304 305
                                           HWND * phwnd)
{
306
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
307 308 309 310 311 312 313 314

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

    if(!This->hwndOwner)
        return E_FAIL;

    *phwnd = This->hwndOwner;

315
    return (*phwnd) ? S_OK : E_UNEXPECTED;
316 317 318 319 320 321

}

/**************************************************************************
*  IShellBrowserImpl_ContextSensitiveHelp
*/
Mike McCormack's avatar
Mike McCormack committed
322
static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
323 324
                                                      BOOL fEnterMode)
{
325
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/*
 * IShellBrowser
 */

/**************************************************************************
*  IShellBrowserImpl_BrowseObject
*
*  See Windows documentation on IShellBrowser::BrowseObject for more details
*
342 343
*  This function will override user specified flags and will always
*  use SBSP_DEFBROWSER and SBSP_DEFMODE.
344
*/
Mike McCormack's avatar
Mike McCormack committed
345
static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
346
                                              LPCITEMIDLIST pidl,
347 348 349 350 351 352 353
                                              UINT wFlags)
{
    HRESULT hRes;
    IShellFolder *psfTmp;
    IShellView *psvTmp;
    FileOpenDlgInfos *fodInfos;
    LPITEMIDLIST pidlTmp;
354 355 356
    HWND hwndView;
    HWND hDlgWnd;
    BOOL bViewHasFocus;
357
    RECT rectView;
358

359
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
360

361 362
    TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
    COMDLG32_DumpSBSPFlags(wFlags);
363

364
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
365 366 367 368

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

370
        /* SBSP_RELATIVE  A relative pidl (relative from the current folder) */
371 372
        if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
             pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
373
        {
374 375
            ERR("bind to object failed\n");
	    return hRes;
376 377
        }
        /* create an absolute pidl */
378
        pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl);
379 380 381 382 383 384 385 386
    }
    else if(wFlags & SBSP_PARENT)
    {
        /* Browse the parent folder (ignores the pidl) */
        pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
        psfTmp = GetShellFolderFromPidl(pidlTmp);

    }
387
    else /* SBSP_ABSOLUTE is 0x0000 */
388 389
    {
        /* An absolute pidl (relative from the desktop) */
390
        pidlTmp =  COMDLG32_PIDL_ILClone(pidl);
391 392
        psfTmp = GetShellFolderFromPidl(pidlTmp);
    }
393

394 395 396 397 398
    if(!psfTmp)
    {
      ERR("could not browse to folder\n");
      return E_FAIL;
    }
399

400
    /* If the pidl to browse to is equal to the actual pidl ...
401 402 403 404 405
       do nothing and pretend you did it*/
    if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
    {
        IShellFolder_Release(psfTmp);
	COMDLG32_SHFree(pidlTmp);
406
        TRACE("keep current folder\n");
407 408 409
        return NOERROR;
    }

410 411 412 413 414 415 416
    /* Release the current DataObject */
    if (fodInfos->Shell.FOIDataObject)
    {
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
      fodInfos->Shell.FOIDataObject = NULL;
    }

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 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

    /* 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 */
440 441
    if (fodInfos->Shell.FOIShellFolder)
      IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
442 443
    fodInfos->Shell.FOIShellFolder = psfTmp;

444
    /* Release old pidlAbsCurrent and update its value */
445
    COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
446
    fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
447

448 449
    COMDLG32_UpdateCurrentDir(fodInfos);

450 451 452
    GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
    MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);

453 454 455 456
    /* Create the window */
    TRACE("create view window\n");
    if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
         &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
457
         &rectView, &hwndView))) goto error;
458

459 460
    fodInfos->ShellInfos.hwndView = hwndView;

461 462 463
    /* Set view window control id to 5002 */
    SetWindowLongPtrW(hwndView, GWLP_ID, lst2);

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 470 471 472 473 474
    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);

475
    return hRes;
476
error:
477
    ERR("Failed with error 0x%08x\n", hRes);
478
    return hRes;
479 480 481 482 483
}

/**************************************************************************
*  IShellBrowserImpl_EnableModelessSB
*/
Mike McCormack's avatar
Mike McCormack committed
484
static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
485
                                              BOOL fEnable)
486

487
{
488
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
489 490 491 492 493 494 495 496 497 498

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/**************************************************************************
*  IShellBrowserImpl_GetControlWindow
*/
Mike McCormack's avatar
Mike McCormack committed
499
static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
500
                                              UINT id,
501
                                              HWND *lphwnd)
502

503
{
504
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
505 506 507 508 509 510

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

    /* Feature not implemented */
    return E_NOTIMPL;
}
Mike McCormack's avatar
Mike McCormack committed
511

512 513 514
/**************************************************************************
*  IShellBrowserImpl_GetViewStateStream
*/
Mike McCormack's avatar
Mike McCormack committed
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 525

    /* Feature not implemented */
    return E_NOTIMPL;
526
}
Mike McCormack's avatar
Mike McCormack committed
527

528 529 530
/**************************************************************************
*  IShellBrowserImpl_InsertMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
531
static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
532 533
                                           HMENU hmenuShared,
                                           LPOLEMENUGROUPWIDTHS lpMenuWidths)
534

535
{
536
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
537 538 539 540 541 542

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

    /* Feature not implemented */
    return E_NOTIMPL;
}
Mike McCormack's avatar
Mike McCormack committed
543

544 545 546
/**************************************************************************
*  IShellBrowserImpl_OnViewWindowActive
*/
Mike McCormack's avatar
Mike McCormack committed
547
static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
548
                                                IShellView *ppshv)
549

550
{
551
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
552 553 554 555 556

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

    /* Feature not implemented */
    return E_NOTIMPL;
557
}
Mike McCormack's avatar
Mike McCormack committed
558

559 560 561
/**************************************************************************
*  IShellBrowserImpl_QueryActiveShellView
*/
Mike McCormack's avatar
Mike McCormack committed
562
static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
563
                                                  IShellView **ppshv)
564

565
{
566
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
567 568 569 570 571

    FileOpenDlgInfos *fodInfos;

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

572
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
573 574 575 576 577 578 579

    if(!(*ppshv = fodInfos->Shell.FOIShellView))
    {
        return E_FAIL;
    }
    IShellView_AddRef(fodInfos->Shell.FOIShellView);
    return NOERROR;
580
}
Mike McCormack's avatar
Mike McCormack committed
581

582 583 584
/**************************************************************************
*  IShellBrowserImpl_RemoveMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
585
static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
586
                                           HMENU hmenuShared)
587

588
{
589
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
590 591 592 593 594

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

    /* Feature not implemented */
    return E_NOTIMPL;
595
}
Mike McCormack's avatar
Mike McCormack committed
596

597 598 599
/**************************************************************************
*  IShellBrowserImpl_SendControlMsg
*/
Mike McCormack's avatar
Mike McCormack committed
600
static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
601 602 603
                                            UINT id,
                                            UINT uMsg,
                                            WPARAM wParam,
604 605
                                            LPARAM lParam,
                                            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 614 615 616 617 618 619 620 621 622 623
    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;
624
}
Mike McCormack's avatar
Mike McCormack committed
625

626 627 628
/**************************************************************************
*  IShellBrowserImpl_SetMenuSB
*/
Mike McCormack's avatar
Mike McCormack committed
629
static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
630
                                       HMENU hmenuShared,
631 632
                                       HOLEMENU holemenuReserved,
                                       HWND hwndActiveObject)
633

634
{
635
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
636 637 638 639 640

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

    /* Feature not implemented */
    return E_NOTIMPL;
641
}
Mike McCormack's avatar
Mike McCormack committed
642

643 644 645
/**************************************************************************
*  IShellBrowserImpl_SetStatusTextSB
*/
Mike McCormack's avatar
Mike McCormack committed
646
static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
647
                                             LPCOLESTR lpszStatusText)
648

649
{
650
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
651 652 653 654 655

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

    /* Feature not implemented */
    return E_NOTIMPL;
656
}
Mike McCormack's avatar
Mike McCormack committed
657

658 659 660
/**************************************************************************
*  IShellBrowserImpl_SetToolbarItems
*/
Mike McCormack's avatar
Mike McCormack committed
661
static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
662 663
                                             LPTBBUTTON lpButtons,
                                             UINT nButtons,
664
                                             UINT uFlags)
665

666
{
667
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
668 669 670 671 672

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

    /* Feature not implemented */
    return E_NOTIMPL;
673
}
Mike McCormack's avatar
Mike McCormack committed
674

675 676 677
/**************************************************************************
*  IShellBrowserImpl_TranslateAcceleratorSB
*/
Mike McCormack's avatar
Mike McCormack committed
678
static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
679
                                                    LPMSG lpmsg,
680
                                                    WORD wID)
681

682
{
683
    IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
684 685 686 687 688 689 690

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

691
static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
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 717
{
        /* 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
};



718 719 720 721 722 723 724
/*
 * ICommDlgBrowser
 */

/***************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_QueryInterface
*/
Mike McCormack's avatar
Mike McCormack committed
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 733

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

734
    return IShellBrowserImpl_QueryInterface((IShellBrowser *)This,riid,ppvObj);
735 736 737 738 739
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
740
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
741
{
742
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
743 744 745

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

746
    return IShellBrowserImpl_AddRef((IShellBrowser *)This);
747 748 749 750 751
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_Release
*/
Mike McCormack's avatar
Mike McCormack committed
752
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
753
{
754
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
755 756 757

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

758
    return IShellBrowserImpl_Release((IShellBrowser *)This);
759
}
Mike McCormack's avatar
Mike McCormack committed
760

761 762 763 764 765
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
*
*   Called when a user double-clicks in the view or presses the ENTER key
*/
Mike McCormack's avatar
Mike McCormack committed
766
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
767 768 769 770 771
                                                                  IShellView *ppshv)
{
    LPITEMIDLIST pidl;
    FileOpenDlgInfos *fodInfos;

772
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
773 774 775

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

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 782 783
    {
        HRESULT hRes;

        ULONG  ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
784
        IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
785 786 787
	if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
	{
          hRes = IShellBrowser_BrowseObject((IShellBrowser *)This,pidl,SBSP_RELATIVE);
788 789
          if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
              SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
790
	}
791
        else
792
	{
793
          /* Tell the dialog that the user selected a file */
Mike Hearn's avatar
Mike Hearn committed
794 795
	  PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
         hRes = S_OK;
796
	}
797 798

        /* Free memory used by pidl */
799
        COMDLG32_SHFree(pidl);
800 801 802 803 804 805 806 807 808 809

        return hRes;
    }

    return E_FAIL;
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnStateChange
*/
Mike McCormack's avatar
Mike McCormack committed
810
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
811 812 813 814
                                                               IShellView *ppshv,
                                                               ULONG uChange)
{

815
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
816

817
    TRACE("(%p shv=%p)\n", This, ppshv);
818 819 820 821

    switch (uChange)
    {
        case CDBOSC_SETFOCUS:
822 823 824 825 826 827
             /* 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);

828
            break;
829
        case CDBOSC_KILLFOCUS:
830
	    {
831
                FileOpenDlgInfos *fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
832
		if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
833 834 835 836 837
		{
		    WCHAR szSave[16];
		    LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR));
		    SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave);
		}
838
            }
839 840 841 842
            break;
        case CDBOSC_SELCHANGE:
            return IShellBrowserImpl_ICommDlgBrowser_OnSelChange(iface,ppshv);
        case CDBOSC_RENAME:
843
	    /* nothing to do */
844 845 846
            break;
    }

847
    return NOERROR;
848
}
849

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
/*         send_includeitem_notification
 *
 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg
 */
static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl)
{
    LRESULT hook_result = 0;
    FileOpenDlgInfos *fodInfos = GetPropA(hwndParentDlg, FileOpenDlgInfosStr);

    if(!fodInfos) return 0;

    if(fodInfos->DlgInfos.hwndCustomDlg)
    {
        TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl);
        if(fodInfos->unicode)
        {
                OFNOTIFYEXW ofnNotify;
                ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
                ofnNotify.pidl = (LPITEMIDLIST)pidl;
                ofnNotify.hdr.hwndFrom = hwndParentDlg;
                ofnNotify.hdr.idFrom = 0;
                ofnNotify.hdr.code = CDN_INCLUDEITEM;
                ofnNotify.lpOFN = fodInfos->ofnInfos;
                hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
        }
        else
        {
                OFNOTIFYEXA ofnNotify;
                ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
                ofnNotify.pidl = (LPITEMIDLIST)pidl;
                ofnNotify.hdr.hwndFrom = hwndParentDlg;
                ofnNotify.hdr.idFrom = 0;
                ofnNotify.hdr.code = CDN_INCLUDEITEM;
                ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos;
                hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
        }
    }
    TRACE("Retval: 0x%08lx\n", hook_result);
    return hook_result;
}

891 892 893
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_IncludeObject
*/
Mike McCormack's avatar
Mike McCormack committed
894
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
895 896 897 898 899 900
                                                               IShellView * ppshv,
                                                               LPCITEMIDLIST pidl)
{
    FileOpenDlgInfos *fodInfos;
    ULONG ulAttr;
    STRRET str;
901
    WCHAR szPathW[MAX_PATH];
902

903
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
904 905 906

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

907
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
908 909 910

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

912 913
    if( (ulAttr & SFGAO_HIDDEN) ||                                      /* hidden */
        !(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 921 922 923 924
    /* if the application takes care of including the item we are done */
    if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY &&
       send_includeitem_notification(This->hwndOwner, pidl))
        return S_OK;

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 930
    if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
    {
931
      if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl))
932
      {
933
	  if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
934 935 936 937 938
          return S_OK;
      }
    }
    return S_FALSE;

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 954 955
    /* release old selections */
    if (fodInfos->Shell.FOIDataObject)
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
956

957 958 959 960
    /* 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;
961

962
    FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);
Alexandre Julliard's avatar
Alexandre Julliard committed
963

964 965
    if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
        SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
966
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
967
}
968

969
static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
{
        /* IUnknown */
        IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
        IShellBrowserImpl_ICommDlgBrowser_AddRef,
        IShellBrowserImpl_ICommDlgBrowser_Release,
        /* ICommDlgBrowser */
        IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
        IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
        IShellBrowserImpl_ICommDlgBrowser_IncludeObject
};




/*
 * IServiceProvider
 */

/***************************************************************************
*  IShellBrowserImpl_IServiceProvider_QueryInterface
*/
Mike McCormack's avatar
Mike McCormack committed
991
static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
992
	IServiceProvider *iface,
993
	REFIID riid,
994 995
	LPVOID *ppvObj)
{
996
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
997 998 999

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

1000
    return IShellBrowserImpl_QueryInterface((IShellBrowser *)This,riid,ppvObj);
1001 1002 1003 1004 1005
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
1006
static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
1007
{
1008
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1009 1010 1011

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

1012
    return IShellBrowserImpl_AddRef((IShellBrowser *)This);
1013 1014 1015 1016 1017
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*/
Mike McCormack's avatar
Mike McCormack committed
1018
static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
1019
{
1020
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1021 1022 1023

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

1024
    return IShellBrowserImpl_Release((IShellBrowser *)This);
1025 1026 1027 1028 1029 1030
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*
* NOTES
1031 1032
*  the w2k shellview asks for (guidService = SID_STopLevelBrowser,
*  riid = IShellBrowser) to call SendControlMsg ().
1033 1034 1035 1036 1037
*
* FIXME
*  this is a hack!
*/

Mike McCormack's avatar
Mike McCormack committed
1038
static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
1039 1040 1041 1042 1043
	IServiceProvider * iface,
	REFGUID guidService,
	REFIID riid,
	void** ppv)
{
1044
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1045 1046 1047 1048 1049 1050

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

    *ppv = NULL;
    if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
    {
1051
      return IShellBrowserImpl_QueryInterface((IShellBrowser *)This,riid,ppv);
1052 1053 1054 1055 1056 1057
    }
    FIXME("(%p) unknown interface requested\n", This);
    return E_NOINTERFACE;

}

1058
static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1059 1060 1061 1062 1063 1064 1065 1066
{
        /* IUnknown */
        IShellBrowserImpl_IServiceProvider_QueryInterface,
        IShellBrowserImpl_IServiceProvider_AddRef,
        IShellBrowserImpl_IServiceProvider_Release,
        /* IServiceProvider */
        IShellBrowserImpl_IServiceProvider_QueryService
};