filedlgbrowser.c 32.2 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
    IShellBrowser IShellBrowser_iface;
    ICommDlgBrowser ICommDlgBrowser_iface;
    IServiceProvider IServiceProvider_iface;
53
    LONG ref;                                   /* Reference counter */
54
    HWND hwndOwner;                             /* Owner dialog of the interface */
55

56 57
} IShellBrowserImpl;

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

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

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

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

80 81 82 83
/*
 *   Helper functions
 */

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

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

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

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

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

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

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

/*
 *	IShellBrowser
 */
189

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

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

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

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

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

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

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

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

    *ppvObj = NULL;

    if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
230
    { *ppvObj = This;
231 232
    }
    else if(IsEqualIID(riid, &IID_IOleWindow))  /*IOleWindow*/
233
    { *ppvObj = This;
234 235 236
    }

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

    else if(IsEqualIID(riid, &IID_ICommDlgBrowser))  /*ICommDlgBrowser*/
241
        *ppvObj = &This->ICommDlgBrowser_iface;
242
    else if(IsEqualIID(riid, &IID_IServiceProvider))  /* IServiceProvider */
243
        *ppvObj = &This->IServiceProvider_iface;
244 245 246 247 248

    if(*ppvObj)
    { IUnknown_AddRef( (IShellBrowser*) *ppvObj);
      return S_OK;
    }
249
    FIXME("Unknown interface requested\n");
250 251 252 253 254 255
    return E_NOINTERFACE;
}

/**************************************************************************
*  IShellBrowser::AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
256
static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
257
{
258
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
259
    ULONG ref = InterlockedIncrement(&This->ref);
260

261
    TRACE("(%p,%u)\n", This, ref - 1);
262

263
    return ref;
264 265 266 267 268
}

/**************************************************************************
*  IShellBrowserImpl_Release
*/
Mike McCormack's avatar
Mike McCormack committed
269
static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
270
{
271
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
272
    ULONG ref = InterlockedDecrement(&This->ref);
273

274
    TRACE("(%p,%u)\n", This, ref + 1);
275

276
    if (!ref)
277
    {
278
      COMDLG32_SHFree(This);
279
      TRACE("-- destroyed\n");
280 281
      return 0;
    }
282
    return ref;
283 284 285 286 287 288 289 290 291 292 293 294 295 296
}

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

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

    if(!This->hwndOwner)
        return E_FAIL;

    *phwnd = This->hwndOwner;

311
    return (*phwnd) ? S_OK : E_UNEXPECTED;
312 313 314 315 316 317

}

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

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/*
 * IShellBrowser
 */

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

355
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
356

357 358
    TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
    COMDLG32_DumpSBSPFlags(wFlags);
359

360
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
361 362 363 364

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

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

    }
383
    else /* SBSP_ABSOLUTE is 0x0000 */
384 385
    {
        /* An absolute pidl (relative from the desktop) */
386
        pidlTmp =  COMDLG32_PIDL_ILClone(pidl);
387 388
        psfTmp = GetShellFolderFromPidl(pidlTmp);
    }
389

390 391 392 393 394
    if(!psfTmp)
    {
      ERR("could not browse to folder\n");
      return E_FAIL;
    }
395

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

406 407 408 409 410 411 412
    /* Release the current DataObject */
    if (fodInfos->Shell.FOIDataObject)
    {
      IDataObject_Release(fodInfos->Shell.FOIDataObject);
      fodInfos->Shell.FOIDataObject = NULL;
    }

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

    /* 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 */
436 437
    if (fodInfos->Shell.FOIShellFolder)
      IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
438 439
    fodInfos->Shell.FOIShellFolder = psfTmp;

440
    /* Release old pidlAbsCurrent and update its value */
441
    COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
442
    fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
443

444 445
    COMDLG32_UpdateCurrentDir(fodInfos);

446 447 448
    GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
    MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);

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

455 456
    fodInfos->ShellInfos.hwndView = hwndView;

457 458 459
    /* Set view window control id to 5002 */
    SetWindowLongPtrW(hwndView, GWLP_ID, lst2);

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

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

471
    return hRes;
472
error:
473
    ERR("Failed with error 0x%08x\n", hRes);
474
    return hRes;
475 476 477 478 479
}

/**************************************************************************
*  IShellBrowserImpl_EnableModelessSB
*/
Mike McCormack's avatar
Mike McCormack committed
480
static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
481
                                              BOOL fEnable)
482

483
{
484
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
485 486 487 488 489 490 491 492 493 494

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

/**************************************************************************
*  IShellBrowserImpl_GetControlWindow
*/
Mike McCormack's avatar
Mike McCormack committed
495
static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
496
                                              UINT id,
497
                                              HWND *lphwnd)
498

499
{
500
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
501 502 503 504 505 506

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

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

508 509 510
/**************************************************************************
*  IShellBrowserImpl_GetViewStateStream
*/
Mike McCormack's avatar
Mike McCormack committed
511
static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
512
                                                DWORD grfMode,
513
                                                LPSTREAM *ppStrm)
514

515
{
516
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
517

518
    FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm);
519 520 521

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

524 525 526
/**************************************************************************
*  IShellBrowserImpl_InsertMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
527
static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
528 529
                                           HMENU hmenuShared,
                                           LPOLEMENUGROUPWIDTHS lpMenuWidths)
530

531
{
532
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
533 534 535 536 537 538

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

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

540 541 542
/**************************************************************************
*  IShellBrowserImpl_OnViewWindowActive
*/
Mike McCormack's avatar
Mike McCormack committed
543
static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
544
                                                IShellView *ppshv)
545

546
{
547
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
548 549 550 551 552

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

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

555 556 557
/**************************************************************************
*  IShellBrowserImpl_QueryActiveShellView
*/
Mike McCormack's avatar
Mike McCormack committed
558
static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
559
                                                  IShellView **ppshv)
560

561
{
562
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
563 564 565 566 567

    FileOpenDlgInfos *fodInfos;

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

568
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
569 570 571 572 573 574 575

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

578 579 580
/**************************************************************************
*  IShellBrowserImpl_RemoveMenusSB
*/
Mike McCormack's avatar
Mike McCormack committed
581
static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
582
                                           HMENU hmenuShared)
583

584
{
585
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
586 587 588 589 590

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

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

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

603
{
604
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
605
    LRESULT lres;
606

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

609 610 611 612 613 614 615 616 617 618 619
    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;
620
}
Mike McCormack's avatar
Mike McCormack committed
621

622 623 624
/**************************************************************************
*  IShellBrowserImpl_SetMenuSB
*/
Mike McCormack's avatar
Mike McCormack committed
625
static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
626
                                       HMENU hmenuShared,
627 628
                                       HOLEMENU holemenuReserved,
                                       HWND hwndActiveObject)
629

630
{
631
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
632 633 634 635 636

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

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

639 640 641
/**************************************************************************
*  IShellBrowserImpl_SetStatusTextSB
*/
Mike McCormack's avatar
Mike McCormack committed
642
static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
643
                                             LPCOLESTR lpszStatusText)
644

645
{
646
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
647 648 649 650 651

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

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

654 655 656
/**************************************************************************
*  IShellBrowserImpl_SetToolbarItems
*/
Mike McCormack's avatar
Mike McCormack committed
657
static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
658 659
                                             LPTBBUTTON lpButtons,
                                             UINT nButtons,
660
                                             UINT uFlags)
661

662
{
663
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
664 665 666 667 668

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

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

671 672 673
/**************************************************************************
*  IShellBrowserImpl_TranslateAcceleratorSB
*/
Mike McCormack's avatar
Mike McCormack committed
674
static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
675
                                                    LPMSG lpmsg,
676
                                                    WORD wID)
677

678
{
679
    IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
680 681 682 683 684 685 686

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

    /* Feature not implemented */
    return E_NOTIMPL;
}

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



714 715 716 717 718 719 720
/*
 * ICommDlgBrowser
 */

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

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

730
    return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
731 732 733 734 735
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
736
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
737
{
738
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
739 740 741

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

742
    return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
743 744 745 746 747
}

/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_Release
*/
Mike McCormack's avatar
Mike McCormack committed
748
static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
749
{
750
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
751 752 753

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

754
    return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
755
}
Mike McCormack's avatar
Mike McCormack committed
756

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

768
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
769 770 771

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

772
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
773

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

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

        /* Free memory used by pidl */
795
        COMDLG32_SHFree(pidl);
796 797 798 799 800 801 802

        return hRes;
    }

    return E_FAIL;
}

803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
/**************************************************************************
*  IShellBrowserImpl_OnSelChange
*/
static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv)
{
    FileOpenDlgInfos *fodInfos;

    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
    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;
}

829 830 831
/**************************************************************************
*  IShellBrowserImpl_ICommDlgBrowser_OnStateChange
*/
Mike McCormack's avatar
Mike McCormack committed
832
static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
833 834 835 836
                                                               IShellView *ppshv,
                                                               ULONG uChange)
{

837
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
838

839
    TRACE("(%p shv=%p)\n", This, ppshv);
840 841 842 843

    switch (uChange)
    {
        case CDBOSC_SETFOCUS:
844 845 846 847 848 849
             /* 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);

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

869
    return NOERROR;
870
}
871

872 873 874 875 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 909 910 911 912
/*         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;
}

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

925
    IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
926 927 928

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

929
    fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
930 931 932

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

934 935
    if( (ulAttr & SFGAO_HIDDEN) ||                                      /* hidden */
        !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
936
        return S_FALSE;
937

938
    /* always include directories and links */
939
    if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
940
        return S_OK;
941

942 943 944 945 946
    /* 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;

947
    /* Check if there is a mask to apply if not */
948
    if(!fodInfos->ShellInfos.lpstrCurrentFilter || !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter))
949
        return S_OK;
950

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

961 962
}

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

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

994
    return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
995 996 997 998 999
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_AddRef
*/
Mike McCormack's avatar
Mike McCormack committed
1000
static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
1001
{
1002
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1003 1004 1005

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

1006
    return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
1007 1008 1009 1010 1011
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*/
Mike McCormack's avatar
Mike McCormack committed
1012
static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
1013
{
1014
    IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1015 1016 1017

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

1018
    return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
1019 1020 1021 1022 1023 1024
}

/**************************************************************************
*  IShellBrowserImpl_IServiceProvider_Release
*
* NOTES
1025 1026
*  the w2k shellview asks for (guidService = SID_STopLevelBrowser,
*  riid = IShellBrowser) to call SendControlMsg ().
1027 1028 1029 1030 1031
*
* FIXME
*  this is a hack!
*/

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

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

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

1046 1047 1048 1049 1050
    FIXME("(%p) unknown interface requested\n", This);
    return E_NOINTERFACE;

}

1051
static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1052 1053 1054 1055 1056 1057 1058 1059
{
        /* IUnknown */
        IShellBrowserImpl_IServiceProvider_QueryInterface,
        IShellBrowserImpl_IServiceProvider_AddRef,
        IShellBrowserImpl_IServiceProvider_Release,
        /* IServiceProvider */
        IShellBrowserImpl_IServiceProvider_QueryService
};