filedlgbrowser.c 32.1 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
#define NONAMELESSUNION
28

29
#include "windef.h"
30
#include "winbase.h"
31
#include "winnls.h"
32
#include "wingdi.h"
33
#include "winuser.h"
34
#include "winreg.h"
35

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

44
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
45

46
typedef struct
47 48
{

49 50 51
    IShellBrowser IShellBrowser_iface;
    ICommDlgBrowser ICommDlgBrowser_iface;
    IServiceProvider IServiceProvider_iface;
52
    LONG ref;                                   /* Reference counter */
53
    HWND hwndOwner;                             /* Owner dialog of the interface */
54

55 56
} IShellBrowserImpl;

57 58 59 60 61
static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
{
    return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
}

62 63
static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface )
{
64
    return CONTAINING_RECORD(iface, IShellBrowserImpl, ICommDlgBrowser_iface);
65 66 67 68
}

static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface )
{
69
    return CONTAINING_RECORD(iface, IShellBrowserImpl, IServiceProvider_iface);
70 71
}

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

79 80 81 82
/*
 *   Helper functions
 */

83 84 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
#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
118
        TRACE("SBSP Flags: %08x =", uflags);
119 120
	for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
	    if (flags[i].mask & uflags)
121 122
		TRACE("%s ", flags[i].name);
	TRACE("\n");
123 124 125
    }
}

126
static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos)
127
{
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    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);
144
    }
145 146
    
    IShellFolder_Release(psfDesktop);
147 148
}

149
/* copied from shell32 to avoid linking to it */
150
static BOOL COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl)
151
{
152
        TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest , len, src, pidl);
153 154 155 156

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

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

166
	  case STRRET_OFFSET:
167 168
	    if (pidl)
	    {
169
                if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset,
170
                                                 -1, dest, len ))
171
                    ((LPWSTR)dest)[len-1] = 0;
172 173 174 175 176 177
	    }
	    break;

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

/*
 *	IShellBrowser
 */
188

189 190 191 192 193
/**************************************************************************
*  IShellBrowserImpl_Construct
*/
IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
{
194
    FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndOwner);
195 196
    IShellBrowserImpl *sb;

197
    sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl));
198 199 200 201 202 203

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

    /* Initialisation of the vTables */
204 205 206
    sb->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
    sb->ICommDlgBrowser_iface.lpVtbl = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
    sb->IServiceProvider_iface.lpVtbl = &IShellBrowserImpl_IServiceProvider_Vtbl;
207
    SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP,
208 209 210 211
                               &fodInfos->ShellInfos.pidlAbsCurrent);

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

212
    return &sb->IShellBrowser_iface;
213 214 215 216 217
}

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

224
    TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid));
225 226 227

    *ppvObj = NULL;

228 229 230 231 232 233 234
    if(IsEqualIID(riid, &IID_IUnknown))
        *ppvObj = &This->IShellBrowser_iface;
    else if(IsEqualIID(riid, &IID_IOleWindow))
        *ppvObj = &This->IShellBrowser_iface;
    else if(IsEqualIID(riid, &IID_IShellBrowser))
        *ppvObj = &This->IShellBrowser_iface;
    else if(IsEqualIID(riid, &IID_ICommDlgBrowser))
235
        *ppvObj = &This->ICommDlgBrowser_iface;
236
    else if(IsEqualIID(riid, &IID_IServiceProvider))
237
        *ppvObj = &This->IServiceProvider_iface;
238

239 240 241
    if(*ppvObj) {
        IUnknown_AddRef((IUnknown*)*ppvObj);
        return S_OK;
242
    }
243

244
    FIXME("Unknown interface requested\n");
245 246 247 248 249 250
    return E_NOINTERFACE;
}

/**************************************************************************
*  IShellBrowser::AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
251
static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
252
{
253
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
254
    ULONG ref = InterlockedIncrement(&This->ref);
255

256
    TRACE("(%p,%u)\n", This, ref - 1);
257

258
    return ref;
259 260 261 262 263
}

/**************************************************************************
*  IShellBrowserImpl_Release
*/
Mike McCormack's avatar
Mike McCormack committed
264
static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
265
{
266
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
267
    ULONG ref = InterlockedDecrement(&This->ref);
268

269
    TRACE("(%p,%u)\n", This, ref + 1);
270

271
    if (!ref)
272
    {
273
      COMDLG32_SHFree(This);
274
      TRACE("-- destroyed\n");
275 276
      return 0;
    }
277
    return ref;
278 279 280 281 282 283 284 285 286 287 288 289 290 291
}

/*
 * 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
292
*
293
*/
Mike McCormack's avatar
Mike McCormack committed
294
static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
295 296
                                           HWND * phwnd)
{
297
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
298 299 300 301 302 303 304 305

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

    if(!This->hwndOwner)
        return E_FAIL;

    *phwnd = This->hwndOwner;

306
    return (*phwnd) ? S_OK : E_UNEXPECTED;
307 308 309 310 311 312

}

/**************************************************************************
*  IShellBrowserImpl_ContextSensitiveHelp
*/
Mike McCormack's avatar
Mike McCormack committed
313
static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
314 315
                                                      BOOL fEnterMode)
{
316
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/*
 * IShellBrowser
 */

/**************************************************************************
*  IShellBrowserImpl_BrowseObject
*
*  See Windows documentation on IShellBrowser::BrowseObject for more details
*
333 334
*  This function will override user specified flags and will always
*  use SBSP_DEFBROWSER and SBSP_DEFMODE.
335
*/
Mike McCormack's avatar
Mike McCormack committed
336
static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
337
                                              LPCITEMIDLIST pidl,
338 339 340 341 342 343 344
                                              UINT wFlags)
{
    HRESULT hRes;
    IShellFolder *psfTmp;
    IShellView *psvTmp;
    FileOpenDlgInfos *fodInfos;
    LPITEMIDLIST pidlTmp;
345 346 347
    HWND hwndView;
    HWND hDlgWnd;
    BOOL bViewHasFocus;
348
    RECT rectView;
349

350
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
351

352 353
    TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
    COMDLG32_DumpSBSPFlags(wFlags);
354

355
    fodInfos = get_filedlg_infoptr(This->hwndOwner);
356 357 358 359

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

361
        /* SBSP_RELATIVE  A relative pidl (relative from the current folder) */
362 363
        if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
             pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
364
        {
365 366
            ERR("bind to object failed\n");
	    return hRes;
367 368
        }
        /* create an absolute pidl */
369
        pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl);
370 371 372 373 374 375 376 377
    }
    else if(wFlags & SBSP_PARENT)
    {
        /* Browse the parent folder (ignores the pidl) */
        pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
        psfTmp = GetShellFolderFromPidl(pidlTmp);

    }
378
    else /* SBSP_ABSOLUTE is 0x0000 */
379 380
    {
        /* An absolute pidl (relative from the desktop) */
381
        pidlTmp =  COMDLG32_PIDL_ILClone(pidl);
382 383
        psfTmp = GetShellFolderFromPidl(pidlTmp);
    }
384

385 386 387 388 389
    if(!psfTmp)
    {
      ERR("could not browse to folder\n");
      return E_FAIL;
    }
390

391
    /* If the pidl to browse to is equal to the actual pidl ...
392 393 394 395 396
       do nothing and pretend you did it*/
    if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
    {
        IShellFolder_Release(psfTmp);
	COMDLG32_SHFree(pidlTmp);
397
        TRACE("keep current folder\n");
398 399 400
        return NOERROR;
    }

401 402 403 404 405 406 407
    /* Release the current DataObject */
    if (fodInfos->Shell.FOIDataObject)
    {
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
      fodInfos->Shell.FOIDataObject = NULL;
    }

408
    /* Create the associated view */
409
    TRACE("create view object\n");
410
    if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner,
411
           &IID_IShellView, (LPVOID *)&psvTmp))) goto error;
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430

    /* 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 */
431 432
    if (fodInfos->Shell.FOIShellFolder)
      IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
433 434
    fodInfos->Shell.FOIShellFolder = psfTmp;

435
    /* Release old pidlAbsCurrent and update its value */
436
    COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
437
    fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
438

439 440
    COMDLG32_UpdateCurrentDir(fodInfos);

441 442 443
    GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
    MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);

444 445 446 447
    /* Create the window */
    TRACE("create view window\n");
    if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
         &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
448
         &rectView, &hwndView))) goto error;
449

450 451
    fodInfos->ShellInfos.hwndView = hwndView;

452 453
    /* Set view window control id to 5002 */
    SetWindowLongPtrW(hwndView, GWLP_ID, lst2);
454
    SendMessageW( hwndView, WM_SETFONT, SendMessageW( GetParent(hwndView), WM_GETFONT, 0, 0 ), FALSE );
455

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

    /* changes the tab order of the ListView to reflect the window's File Dialog */
460
    hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN);
461 462 463 464 465 466
    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);

467
    return hRes;
468
error:
469
    ERR("Failed with error 0x%08x\n", hRes);
470
    return hRes;
471 472 473 474 475
}

/**************************************************************************
*  IShellBrowserImpl_EnableModelessSB
*/
Mike McCormack's avatar
Mike McCormack committed
476
static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
477
                                              BOOL fEnable)
478

479
{
480
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
481 482 483 484 485 486 487 488 489 490

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/**************************************************************************
*  IShellBrowserImpl_GetControlWindow
*/
Mike McCormack's avatar
Mike McCormack committed
491
static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
492
                                              UINT id,
493
                                              HWND *lphwnd)
494

495
{
496
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
497 498 499 500 501 502

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

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

504 505 506
/**************************************************************************
*  IShellBrowserImpl_GetViewStateStream
*/
Mike McCormack's avatar
Mike McCormack committed
507
static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
508
                                                DWORD grfMode,
509
                                                LPSTREAM *ppStrm)
510

511
{
512
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
513

514
    FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm);
515 516 517

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

520 521 522
/**************************************************************************
*  IShellBrowserImpl_InsertMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
523
static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
524 525
                                           HMENU hmenuShared,
                                           LPOLEMENUGROUPWIDTHS lpMenuWidths)
526

527
{
528
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
529 530 531 532 533 534

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

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

536 537 538
/**************************************************************************
*  IShellBrowserImpl_OnViewWindowActive
*/
Mike McCormack's avatar
Mike McCormack committed
539
static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
540
                                                IShellView *ppshv)
541

542
{
543
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
544 545 546 547 548

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

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

551 552 553
/**************************************************************************
*  IShellBrowserImpl_QueryActiveShellView
*/
Mike McCormack's avatar
Mike McCormack committed
554
static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
555
                                                  IShellView **ppshv)
556

557
{
558
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
559 560 561 562 563

    FileOpenDlgInfos *fodInfos;

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

564
    fodInfos = get_filedlg_infoptr(This->hwndOwner);
565 566 567 568 569 570 571

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

574 575 576
/**************************************************************************
*  IShellBrowserImpl_RemoveMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
577
static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
578
                                           HMENU hmenuShared)
579

580
{
581
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
582 583 584 585 586

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

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

589 590 591
/**************************************************************************
*  IShellBrowserImpl_SendControlMsg
*/
Mike McCormack's avatar
Mike McCormack committed
592
static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
593 594 595
                                            UINT id,
                                            UINT uMsg,
                                            WPARAM wParam,
596 597
                                            LPARAM lParam,
                                            LRESULT *pret)
598

599
{
600
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
601
    LRESULT lres;
602

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

605 606 607 608 609 610 611 612 613 614 615
    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;
616
}
Mike McCormack's avatar
Mike McCormack committed
617

618 619 620
/**************************************************************************
*  IShellBrowserImpl_SetMenuSB
*/
Mike McCormack's avatar
Mike McCormack committed
621
static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
622
                                       HMENU hmenuShared,
623 624
                                       HOLEMENU holemenuReserved,
                                       HWND hwndActiveObject)
625

626
{
627
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
628 629 630 631 632

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

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

635 636 637
/**************************************************************************
*  IShellBrowserImpl_SetStatusTextSB
*/
Mike McCormack's avatar
Mike McCormack committed
638
static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
639
                                             LPCOLESTR lpszStatusText)
640

641
{
642
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
643 644 645 646 647

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

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

650 651 652
/**************************************************************************
*  IShellBrowserImpl_SetToolbarItems
*/
Mike McCormack's avatar
Mike McCormack committed
653
static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
654 655
                                             LPTBBUTTON lpButtons,
                                             UINT nButtons,
656
                                             UINT uFlags)
657

658
{
659
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
660 661 662 663 664

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

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

667 668 669
/**************************************************************************
*  IShellBrowserImpl_TranslateAcceleratorSB
*/
Mike McCormack's avatar
Mike McCormack committed
670
static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
671
                                                    LPMSG lpmsg,
672
                                                    WORD wID)
673

674
{
675
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
676 677 678 679 680 681 682

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

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



710 711 712 713 714 715 716
/*
 * ICommDlgBrowser
 */

/***************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_QueryInterface
*/
Mike McCormack's avatar
Mike McCormack committed
717
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(
718
	ICommDlgBrowser *iface,
719
	REFIID riid,
720
	LPVOID *ppvObj)
721
{
722
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
723 724 725

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

726
    return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
727 728 729 730 731
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
732
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
733
{
734
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
735 736 737

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

738
    return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
739 740 741 742 743
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_Release
*/
Mike McCormack's avatar
Mike McCormack committed
744
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
745
{
746
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
747 748 749

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

750
    return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
751
}
Mike McCormack's avatar
Mike McCormack committed
752

753 754 755 756 757
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
*
*   Called when a user double-clicks in the view or presses the ENTER key
*/
Mike McCormack's avatar
Mike McCormack committed
758
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
759 760 761 762 763
                                                                  IShellView *ppshv)
{
    LPITEMIDLIST pidl;
    FileOpenDlgInfos *fodInfos;

764
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
765 766 767

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

768
    fodInfos = get_filedlg_infoptr(This->hwndOwner);
769

770
    /* If the selected object is not a folder, send an IDOK command to parent window */
771
    if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1)))
772 773 774 775
    {
        HRESULT hRes;

        ULONG  ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
776
        IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
777 778
	if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
	{
779 780 781
            hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE);
            if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
                SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
782
	}
783
        else
784
	{
785
          /* Tell the dialog that the user selected a file */
Mike Hearn's avatar
Mike Hearn committed
786 787
	  PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
         hRes = S_OK;
788
	}
789 790

        /* Free memory used by pidl */
791
        COMDLG32_SHFree(pidl);
792 793 794 795 796 797 798

        return hRes;
    }

    return E_FAIL;
}

799 800 801 802 803 804 805
/**************************************************************************
*  IShellBrowserImpl_OnSelChange
*/
static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv)
{
    FileOpenDlgInfos *fodInfos;

806
    fodInfos = get_filedlg_infoptr(This->hwndOwner);
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824
    TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView);

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

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

    FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);

    if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
        SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
    return S_OK;
}

825 826 827
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnStateChange
*/
Mike McCormack's avatar
Mike McCormack committed
828
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
829 830 831 832
                                                               IShellView *ppshv,
                                                               ULONG uChange)
{

833
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
834

835
    TRACE("(%p shv=%p)\n", This, ppshv);
836 837 838 839

    switch (uChange)
    {
        case CDBOSC_SETFOCUS:
840 841 842 843 844 845
             /* 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);

846
            break;
847
        case CDBOSC_KILLFOCUS:
848
	    {
849
                FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(This->hwndOwner);
850
		if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
851 852 853 854 855
		{
		    WCHAR szSave[16];
		    LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR));
		    SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave);
		}
856
            }
857 858
            break;
        case CDBOSC_SELCHANGE:
859
            return IShellBrowserImpl_OnSelChange(This, ppshv);
860
        case CDBOSC_RENAME:
861
	    /* nothing to do */
862 863 864
            break;
    }

865
    return NOERROR;
866
}
867

868 869 870 871 872 873 874
/*         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;
875
    FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndParentDlg);
876 877 878 879 880 881 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

    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;
}

909 910 911
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_IncludeObject
*/
Mike McCormack's avatar
Mike McCormack committed
912
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
913 914 915 916 917 918
                                                               IShellView * ppshv,
                                                               LPCITEMIDLIST pidl)
{
    FileOpenDlgInfos *fodInfos;
    ULONG ulAttr;
    STRRET str;
919
    WCHAR szPathW[MAX_PATH];
920

921
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
922 923 924

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

925
    fodInfos = get_filedlg_infoptr(This->hwndOwner);
926 927 928

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

930 931
    if( (ulAttr & SFGAO_HIDDEN) ||                                      /* hidden */
        !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
932
        return S_FALSE;
933

934
    /* always include directories and links */
935
    if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
936
        return S_OK;
937

938 939 940 941 942
    /* 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;

943
    /* Check if there is a mask to apply if not */
944
    if(!fodInfos->ShellInfos.lpstrCurrentFilter || !fodInfos->ShellInfos.lpstrCurrentFilter[0])
945
        return S_OK;
946

947 948
    if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
    {
949
      if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl))
950
      {
951
	  if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
952 953 954 955 956
          return S_OK;
      }
    }
    return S_FALSE;

957 958
}

959
static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
{
        /* 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
981
static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
982
	IServiceProvider *iface,
983
	REFIID riid,
984 985
	LPVOID *ppvObj)
{
986
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
987 988 989

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

990
    return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
991 992 993 994 995
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
996
static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
997
{
998
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
999 1000 1001

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

1002
    return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
1003 1004 1005 1006 1007
}

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

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

1014
    return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
1015 1016 1017 1018 1019 1020
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*
* NOTES
1021 1022
*  the w2k shellview asks for (guidService = SID_STopLevelBrowser,
*  riid = IShellBrowser) to call SendControlMsg ().
1023 1024 1025 1026 1027
*
* FIXME
*  this is a hack!
*/

Mike McCormack's avatar
Mike McCormack committed
1028
static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
1029 1030 1031 1032 1033
	IServiceProvider * iface,
	REFGUID guidService,
	REFIID riid,
	void** ppv)
{
1034
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1035 1036 1037 1038 1039

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

    *ppv = NULL;
    if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
1040 1041
        return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppv);

1042 1043 1044 1045 1046
    FIXME("(%p) unknown interface requested\n", This);
    return E_NOINTERFACE;

}

1047
static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1048 1049 1050 1051 1052 1053 1054 1055
{
        /* IUnknown */
        IShellBrowserImpl_IServiceProvider_QueryInterface,
        IShellBrowserImpl_IServiceProvider_AddRef,
        IShellBrowserImpl_IServiceProvider_Release,
        /* IServiceProvider */
        IShellBrowserImpl_IServiceProvider_QueryService
};