shlview.c 112 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 *	ShellView
 *
4
 *	Copyright 1998,1999	<juergen.schmied@debitel.net>
5
 *
6
 * This is the view visualizing the data provided by the shellfolder.
7 8
 * No direct access to data from pidls should be done from here.
 *
9 10 11 12 13 14 15 16 17 18 19 20
 * 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
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22
 *
23
 * FIXME: The order by part of the background context menu should be
24
 * built according to the columns shown.
25
 *
26
 * FIXME: Load/Save the view state from/into the stream provided by
27 28 29 30 31 32 33 34 35
 * the ShellBrowser
 *
 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
 *
 * FIXME: ShellView_FillList: consider sort orders
 *
 * FIXME: implement the drag and drop in the old (msg-based) way
 *
 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
36
 * Release() ???
Alexandre Julliard's avatar
Alexandre Julliard committed
37 38
 */

39 40 41
#include "config.h"
#include "wine/port.h"

42
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
43 44
#include <stdlib.h>
#include <string.h>
45

46
#define CINTERFACE
47
#define COBJMACROS
48
#define NONAMELESSUNION
49

50
#include "windef.h"
51
#include "winerror.h"
52
#include "winbase.h"
53
#include "winnls.h"
54
#include "objbase.h"
55
#include "servprov.h"
56
#include "shlguid.h"
57 58
#include "wingdi.h"
#include "winuser.h"
59
#include "shlobj.h"
60
#include "shobjidl.h"
61
#include "undocshell.h"
62
#include "shresdef.h"
63
#include "wine/debug.h"
64

65
#include "docobj.h"
66 67
#include "pidl.h"
#include "shell32_main.h"
68
#include "shellfolder.h"
69

70
WINE_DEFAULT_DEBUG_CHANNEL(shell);
71

72 73
static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};

74 75 76 77 78 79
typedef struct
{   BOOL    bIsAscending;
    INT     nHeaderID;
    INT     nLastHeaderID;
}LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;

80
typedef struct
81
{
82
        IShellView3       IShellView3_iface;
83 84 85 86
        IOleCommandTarget IOleCommandTarget_iface;
        IDropTarget       IDropTarget_iface;
        IDropSource       IDropSource_iface;
        IViewObject       IViewObject_iface;
87
        IFolderView2      IFolderView2_iface;
88
        IShellFolderView  IShellFolderView_iface;
89
        IShellFolderViewDual3 IShellFolderViewDual3_iface;
90
        LONG              ref;
91
	IShellFolder*	pSFParent;
92
	IShellFolder2*	pSF2Parent;
93 94
	IShellBrowser*	pShellBrowser;
	ICommDlgBrowser*	pCommDlgBrowser;
95 96
	HWND		hWnd;		/* SHELLDLL_DefView */
	HWND		hWndList;	/* ListView control */
97 98 99 100
	HWND		hWndParent;
	FOLDERSETTINGS	FolderSettings;
	HMENU		hMenu;
	UINT		uState;
101 102
	UINT		cidl;
	LPITEMIDLIST	*apidl;
103
        LISTVIEW_SORT_INFO ListViewSortInfo;
104
	ULONG			hNotify;	/* change notification handle */
105
	HANDLE		hAccel;
106 107 108
	DWORD		dwAspects;
	DWORD		dwAdvf;
	IAdviseSink    *pAdvSink;
109 110 111
        IDropTarget*    pCurDropTarget; /* The sub-item, which is currently dragged over */
        IDataObject*    pCurDataObject; /* The dragged data-object */
        LONG            iDragOverItem;  /* Dragged over item's index, iff pCurDropTarget != NULL */
112 113
        UINT            cScrollDelay;   /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
        POINT           ptLastMousePos; /* Mouse position at last DragOver call */
114
        UINT            columns;        /* Number of shell folder columns */
115 116
} IShellViewImpl;

117
static inline IShellViewImpl *impl_from_IShellView3(IShellView3 *iface)
118
{
119
    return CONTAINING_RECORD(iface, IShellViewImpl, IShellView3_iface);
120 121
}

122
static inline IShellViewImpl *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
123
{
124
    return CONTAINING_RECORD(iface, IShellViewImpl, IOleCommandTarget_iface);
125 126
}

127
static inline IShellViewImpl *impl_from_IDropTarget(IDropTarget *iface)
128
{
129
    return CONTAINING_RECORD(iface, IShellViewImpl, IDropTarget_iface);
130 131
}

132
static inline IShellViewImpl *impl_from_IDropSource(IDropSource *iface)
133
{
134
    return CONTAINING_RECORD(iface, IShellViewImpl, IDropSource_iface);
135 136
}

137
static inline IShellViewImpl *impl_from_IViewObject(IViewObject *iface)
138
{
139
    return CONTAINING_RECORD(iface, IShellViewImpl, IViewObject_iface);
140
}
141

142
static inline IShellViewImpl *impl_from_IFolderView2(IFolderView2 *iface)
143
{
144
    return CONTAINING_RECORD(iface, IShellViewImpl, IFolderView2_iface);
145 146
}

147
static inline IShellViewImpl *impl_from_IShellFolderView(IShellFolderView *iface)
148
{
149
    return CONTAINING_RECORD(iface, IShellViewImpl, IShellFolderView_iface);
150 151
}

152 153 154 155 156
static inline IShellViewImpl *impl_from_IShellFolderViewDual3(IShellFolderViewDual3 *iface)
{
    return CONTAINING_RECORD(iface, IShellViewImpl, IShellFolderViewDual3_iface);
}

157
/* ListView Header IDs */
158 159 160 161 162 163
#define LISTVIEW_COLUMN_NAME 0
#define LISTVIEW_COLUMN_SIZE 1
#define LISTVIEW_COLUMN_TYPE 2
#define LISTVIEW_COLUMN_TIME 3
#define LISTVIEW_COLUMN_ATTRIB 4

164
/*menu items */
Alexandre Julliard's avatar
Alexandre Julliard committed
165 166 167
#define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
#define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
#define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
168

169
#define ID_LISTVIEW     1
170

171 172
#define SHV_CHANGE_NOTIFY WM_USER + 0x1111

173
/*windowsx.h */
Alexandre Julliard's avatar
Alexandre Julliard committed
174
#define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
175
#define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
Alexandre Julliard's avatar
Alexandre Julliard committed
176
#define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
177

178
/*
179
  Items merged into the toolbar and the filemenu
180
*/
Alexandre Julliard's avatar
Alexandre Julliard committed
181 182 183 184 185 186 187 188 189
typedef struct
{  int   idCommand;
   int   iImage;
   int   idButtonString;
   int   idMenuString;
   BYTE  bState;
   BYTE  bStyle;
} MYTOOLINFO, *LPMYTOOLINFO;

190
static const MYTOOLINFO Tools[] =
191
{
192 193 194 195
{ FCIDM_SHVIEW_BIGICON,    0, 0, IDS_VIEW_LARGE,   TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_SMALLICON,  0, 0, IDS_VIEW_SMALL,   TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_LISTVIEW,   0, 0, IDS_VIEW_LIST,    TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
196
{ -1, 0, 0, 0, 0, 0}
Alexandre Julliard's avatar
Alexandre Julliard committed
197
};
198

199
typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
Alexandre Julliard's avatar
Alexandre Julliard committed
200

201 202 203 204
/**********************************************************
 *
 * ##### helperfunctions for communication with ICommDlgBrowser #####
 */
205
static BOOL IsInCommDlg(IShellViewImpl * This)
206 207
{
    return This->pCommDlgBrowser != NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
208
}
209

210 211
static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
{
212
    HRESULT ret = S_OK;
213

214 215 216 217 218 219 220 221
    if (IsInCommDlg(This))
    {
        TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
        ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView *)&This->IShellView3_iface, pidl);
        TRACE("-- returns 0x%08x\n", ret);
    }

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
222
}
223 224 225

static HRESULT OnDefaultCommand(IShellViewImpl * This)
{
226
    HRESULT ret = S_FALSE;
227

228 229 230 231 232 233 234 235
    if (IsInCommDlg(This))
    {
        TRACE("ICommDlgBrowser::OnDefaultCommand\n");
        ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView *)&This->IShellView3_iface);
        TRACE("-- returns 0x%08x\n", ret);
    }

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
236
}
237

238
static HRESULT OnStateChange(IShellViewImpl * This, UINT change)
239
{
240
    HRESULT ret = S_FALSE;
241

242 243 244 245 246 247 248 249
    if (IsInCommDlg(This))
    {
        TRACE("ICommDlgBrowser::OnStateChange change=%d\n", change);
        ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView *)&This->IShellView3_iface, change);
        TRACE("-- returns 0x%08x\n", ret);
    }

    return ret;
250
}
251

252
/**********************************************************
253
 *	set the toolbar of the filedialog buttons
254
 *
255
 * - activates the buttons from the shellbrowser according to
256
 *   the view state
257
 */
258
static void CheckToolbar(IShellViewImpl * This)
259 260
{
	LRESULT result;
261

262
	TRACE("\n");
263

264 265 266
	if (IsInCommDlg(This))
	{
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
267
                FCIDM_TB_SMALLICON, This->FolderSettings.ViewMode == FVM_LIST, &result);
268
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
269
                FCIDM_TB_REPORTVIEW, This->FolderSettings.ViewMode == FVM_DETAILS, &result);
270
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
271
		FCIDM_TB_SMALLICON, TRUE, &result);
272
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
273
		FCIDM_TB_REPORTVIEW, TRUE, &result);
274
	}
275 276
}

277 278 279 280
/**********************************************************
 *
 * ##### helperfunctions for initializing the view #####
 */
281 282 283 284 285 286
/**********************************************************
 *	change the style of the listview control
 */
static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
{
	DWORD tmpstyle;
287

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

290 291
	tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
	SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
292
}
Alexandre Julliard's avatar
Alexandre Julliard committed
293

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
static DWORD ViewModeToListStyle(UINT ViewMode)
{
	DWORD dwStyle;

	TRACE("%d\n", ViewMode);

	switch (ViewMode)
	{
	  case FVM_ICON:	dwStyle = LVS_ICON;		break;
	  case FVM_DETAILS:	dwStyle = LVS_REPORT;		break;
	  case FVM_SMALLICON:	dwStyle = LVS_SMALLICON;	break;
	  case FVM_LIST:	dwStyle = LVS_LIST;		break;
	  default:
	  {
		FIXME("ViewMode %d not implemented\n", ViewMode);
		dwStyle = LVS_LIST;
		break;
	  }
	}

	return dwStyle;
}

317
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
318 319
* ShellView_CreateList()
*
320
* - creates the list view window
Alexandre Julliard's avatar
Alexandre Julliard committed
321
*/
322
static BOOL ShellView_CreateList (IShellViewImpl * This)
323
{	DWORD dwStyle, dwExStyle;
Alexandre Julliard's avatar
Alexandre Julliard committed
324

325
	TRACE("%p\n",This);
Alexandre Julliard's avatar
Alexandre Julliard committed
326

327
	dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
328
		  LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
329
        dwExStyle = WS_EX_CLIENTEDGE;
330

331
        dwStyle |= ViewModeToListStyle(This->FolderSettings.ViewMode);
332

333
	if (This->FolderSettings.fFlags & FWF_AUTOARRANGE)	dwStyle |= LVS_AUTOARRANGE;
334 335
	if (This->FolderSettings.fFlags & FWF_DESKTOP)
	  This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
336
	if (This->FolderSettings.fFlags & FWF_SINGLESEL)	dwStyle |= LVS_SINGLESEL;
337 338
	if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
	  dwExStyle &= ~WS_EX_CLIENTEDGE;
Alexandre Julliard's avatar
Alexandre Julliard committed
339

340 341
	This->hWndList=CreateWindowExW( dwExStyle,
					WC_LISTVIEWW,
342 343 344 345 346 347 348
					NULL,
					dwStyle,
					0,0,0,0,
					This->hWnd,
					(HMENU)ID_LISTVIEW,
					shell32_hInstance,
					NULL);
Alexandre Julliard's avatar
Alexandre Julliard committed
349

350
	if(!This->hWndList)
Alexandre Julliard's avatar
Alexandre Julliard committed
351 352
	  return FALSE;

353 354 355 356
        This->ListViewSortInfo.bIsAscending = TRUE;
        This->ListViewSortInfo.nHeaderID = -1;
        This->ListViewSortInfo.nLastHeaderID = -1;

357 358 359 360 361 362 363 364 365 366 367 368 369
        if (This->FolderSettings.fFlags & FWF_DESKTOP) {
          /*
           * FIXME: look at the registry value
           * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
           * and activate drop shadows if necessary
           */
           if (0)
             SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
           else
             SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));

           SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
        }
370

371
        /*  UpdateShellSettings(); */
Alexandre Julliard's avatar
Alexandre Julliard committed
372
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
373
}
374

375
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
376
* ShellView_InitList()
377
*
378
* - adds all needed columns to the shellview
Alexandre Julliard's avatar
Alexandre Julliard committed
379
*/
380
static void ShellView_InitList(IShellViewImpl *This)
381
{
382
    IShellDetails *details = NULL;
383
    HIMAGELIST big_icons, small_icons;
384 385 386
    LVCOLUMNW lvColumn;
    SHELLDETAILS sd;
    WCHAR nameW[50];
387
    HRESULT hr;
388 389 390
    HFONT list_font, old_font;
    HDC list_dc;
    TEXTMETRICW tm;
Alexandre Julliard's avatar
Alexandre Julliard committed
391

392
    TRACE("(%p)\n", This);
Alexandre Julliard's avatar
Alexandre Julliard committed
393

394
    Shell_GetImageLists( &big_icons, &small_icons );
395
    SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
396 397
    SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)small_icons);
    SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)big_icons);
Alexandre Julliard's avatar
Alexandre Julliard committed
398

399 400 401
    lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
    lvColumn.pszText = nameW;

402
    if (!This->pSF2Parent)
403
    {
404 405
        hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IShellDetails, (void**)&details);
        if (hr != S_OK)
406
        {
407 408
            WARN("IShellFolder2/IShellDetails not supported\n");
            return;
409 410
        }
    }
411

412 413 414 415 416 417 418
    list_font = (HFONT)SendMessageW(This->hWndList, WM_GETFONT, 0, 0);
    list_dc = GetDC(This->hWndList);
    old_font = SelectObject(list_dc, list_font);
    GetTextMetricsW(list_dc, &tm);
    SelectObject(list_dc, old_font);
    ReleaseDC(This->hWndList, list_dc);

419
    for (This->columns = 0;; This->columns++)
420
    {
421
        if (This->pSF2Parent)
422
            hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, This->columns, &sd);
423
        else
424
            hr = IShellDetails_GetDetailsOf(details, NULL, This->columns, &sd);
425 426 427
        if (FAILED(hr)) break;

        lvColumn.fmt = sd.fmt;
428
        lvColumn.cx = MulDiv(sd.cxChar, tm.tmAveCharWidth * 3, 2); /* chars->pixel */
429
        StrRetToStrNW(nameW, ARRAY_SIZE(nameW), &sd.str, NULL);
430
        SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, This->columns, (LPARAM)&lvColumn);
431
    }
432

433
    if (details) IShellDetails_Release(details);
Alexandre Julliard's avatar
Alexandre Julliard committed
434
}
435

436 437
/* LVM_SORTITEMS callback used when initially inserting items */
static INT CALLBACK ShellView_CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
438
{
439 440 441 442
    LPITEMIDLIST pidl1 = (LPITEMIDLIST)lParam1;
    LPITEMIDLIST pidl2 = (LPITEMIDLIST)lParam2;
    IShellFolder *folder = (IShellFolder *)lpData;
    int ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
443

444
    TRACE("pidl1=%p, pidl2=%p, shellfolder=%p\n", pidl1, pidl2, folder);
445

446 447 448
    ret = (SHORT)HRESULT_CODE(IShellFolder_CompareIDs(folder, 0, pidl1, pidl2));
    TRACE("ret=%i\n", ret);
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
449 450
}

451 452 453 454 455 456 457 458 459 460 461
/*************************************************************************
 * ShellView_ListViewCompareItems
 *
 * Compare Function for the Listview (FileOpen Dialog)
 *
 * PARAMS
 *     lParam1       [I] the first ItemIdList to compare with
 *     lParam2       [I] the second ItemIdList to compare with
 *     lpData        [I] The column ID for the header Ctrl to process
 *
 * RETURNS
462 463
 *     A negative value if the first item should precede the second,
 *     a positive value if the first item should follow the second,
464 465 466
 *     or zero if the two items are equivalent
 *
 * NOTES
467 468 469
 *	FIXME: function does what ShellView_CompareItems is supposed to do.
 *	unify it and figure out how to use the undocumented first parameter
 *	of IShellFolder_CompareIDs to do the job this function does and
470
 *	move this code to IShellFolder.
471
 *	make LISTVIEW_SORT_INFO obsolete
472
 *	the way this function works is only usable if we had only
473
 *	filesystemfolders  (25/10/99 jsch)
474 475 476 477 478 479 480
 */
static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
{
    INT nDiff=0;
    FILETIME fd1, fd2;
    char strName1[MAX_PATH], strName2[MAX_PATH];
    BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
481 482
    LPITEMIDLIST pItemIdList1 = lParam1;
    LPITEMIDLIST pItemIdList2 = lParam2;
483
    LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
484 485 486 487 488 489 490 491 492 493 494 495


    bIsFolder1 = _ILIsFolder(pItemIdList1);
    bIsFolder2 = _ILIsFolder(pItemIdList2);
    bIsBothFolder = bIsFolder1 && bIsFolder2;

    /* When sorting between a File and a Folder, the Folder gets sorted first */
    if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
    {
        nDiff = bIsFolder1 ? -1 : 1;
    }
    else
496
    {
497
        /* Sort by Time: Folders or Files can be sorted */
498

499
        if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
500 501 502 503 504 505
        {
            _ILGetFileDateTime(pItemIdList1, &fd1);
            _ILGetFileDateTime(pItemIdList2, &fd2);
            nDiff = CompareFileTime(&fd2, &fd1);
        }
        /* Sort by Attribute: Folder or Files can be sorted */
506
        else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
507
        {
508 509
            _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
            _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
510
            nDiff = lstrcmpiA(strName1, strName2);
511 512
        }
        /* Sort by FileName: Folder or Files can be sorted */
513
        else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
514 515 516 517
        {
            /* Sort by Text */
            _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
            _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
518
            nDiff = lstrcmpiA(strName1, strName2);
519 520
        }
        /* Sort by File Size, Only valid for Files */
521
        else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
522
        {
523
            nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
524 525
        }
        /* Sort by File Type, Only valid for Files */
526
        else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
527 528 529 530
        {
            /* Sort by Type */
            _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
            _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
531
            nDiff = lstrcmpiA(strName1, strName2);
532 533 534
        }
    }
    /*  If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
535

536 537 538 539
    if(nDiff == 0)
    {
        _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
        _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
540
        nDiff = lstrcmpiA(strName1, strName2);
541 542
    }

543 544 545 546 547
    if(!pSortInfo->bIsAscending)
    {
        nDiff = -nDiff;
    }

548 549 550 551
    return nDiff;

}

552 553
/**********************************************************
*  LV_FindItemByPidl()
554
*/
555 556
static int LV_FindItemByPidl(
	IShellViewImpl * This,
Juergen Schmied's avatar
Juergen Schmied committed
557
	LPCITEMIDLIST pidl)
558
{
559
	LVITEMW lvItem;
560
	lvItem.iSubItem = 0;
561
	lvItem.mask = LVIF_PARAM;
562
	for(lvItem.iItem = 0;
563
		SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
564
		lvItem.iItem++)
565 566 567 568 569 570 571 572 573 574 575
	{
	  LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
	  HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
	  if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
	  {
	    return lvItem.iItem;
	  }
  	}
	return -1;
}

576
static void shellview_add_item(IShellViewImpl *shellview, LPCITEMIDLIST pidl)
577
{
578 579
    LVITEMW item;
    UINT i;
580

581
    TRACE("(%p)(pidl=%p)\n", shellview, pidl);
582

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
    item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
    item.iItem = 0;
    item.iSubItem = 0;
    item.lParam = (LPARAM)pidl;
    item.pszText = LPSTR_TEXTCALLBACKW;
    item.iImage = I_IMAGECALLBACK;
    SendMessageW(shellview->hWndList, LVM_INSERTITEMW, 0, (LPARAM)&item);

    for (i = 1; i < shellview->columns; i++)
    {
        item.mask = LVIF_TEXT;
        item.iItem = 0;
        item.iSubItem = 1;
        item.pszText = LPSTR_TEXTCALLBACKW;
        SendMessageW(shellview->hWndList, LVM_SETITEMW, 0, (LPARAM)&item);
    }
599 600 601 602 603
}

/**********************************************************
* LV_RenameItem()
*/
Juergen Schmied's avatar
Juergen Schmied committed
604
static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
605 606
{
	int nItem;
607
	LVITEMW lvItem;
608

Juergen Schmied's avatar
Juergen Schmied committed
609
	TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
610 611 612 613 614 615

	nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
	if ( -1 != nItem )
	{
	  lvItem.mask = LVIF_PARAM;		/* only the pidl */
	  lvItem.iItem = nItem;
616
	  SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
617 618 619 620 621

	  SHFree((LPITEMIDLIST)lvItem.lParam);
	  lvItem.mask = LVIF_PARAM;
	  lvItem.iItem = nItem;
	  lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew));	/* set the item's data */
622 623
	  SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
	  SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
624
	  return TRUE;					/* FIXME: better handling */
625 626 627
	}
	return FALSE;
}
628
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
629 630
* ShellView_FillList()
*
631 632 633
* - gets the objectlist from the shellfolder
* - sorts the list
* - fills the list into the view
634
*/
Alexandre Julliard's avatar
Alexandre Julliard committed
635

636
static HRESULT ShellView_FillList(IShellViewImpl *This)
637
{
638
    IFolderView2 *folderview = &This->IFolderView2_iface;
639 640 641 642
    LPENUMIDLIST pEnumIDList;
    LPITEMIDLIST pidl;
    DWORD fetched;
    HRESULT hr;
Alexandre Julliard's avatar
Alexandre Julliard committed
643

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

646 647
    /* get the itemlist from the shfolder*/
    hr = IShellFolder_EnumObjects(This->pSFParent, This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
648 649
    if (hr != S_OK)
        return hr;
650

651
    IFolderView2_SetRedraw(folderview, FALSE);
652

653 654
    /* copy the items into the array */
    while ((S_OK == IEnumIDList_Next(pEnumIDList, 1, &pidl, &fetched)) && fetched)
655
    {
656 657
        if (IncludeObject(This, pidl) == S_OK)
            shellview_add_item(This, pidl);
658 659
        else
            ILFree(pidl);
660
    }
661

662
    SendMessageW(This->hWndList, LVM_SORTITEMS, (WPARAM)This->pSFParent, (LPARAM)ShellView_CompareItems);
663

664
    IFolderView2_SetRedraw(folderview, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
665

666 667
    IEnumIDList_Release(pEnumIDList);
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
668 669
}

670
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
671
*  ShellView_OnCreate()
672
*/
673
static LRESULT ShellView_OnCreate(IShellViewImpl *This)
674
{
675
    IShellView3 *iface = &This->IShellView3_iface;
676
    static const WCHAR accel_nameW[] = {'s','h','v','_','a','c','c','e','l',0};
677 678 679
    IPersistFolder2 *ppf2;
    IDropTarget* pdt;
    HRESULT hr;
680

681
    TRACE("(%p)\n", This);
Alexandre Julliard's avatar
Alexandre Julliard committed
682

683 684
    if (ShellView_CreateList(This))
    {
685 686
        ShellView_InitList(This);
        ShellView_FillList(This);
687
    }
688

689
    hr = IShellView3_QueryInterface(iface, &IID_IDropTarget, (void**)&pdt);
690 691 692 693 694
    if (hr == S_OK)
    {
        RegisterDragDrop(This->hWnd, pdt);
        IDropTarget_Release(pdt);
    }
695

696 697 698 699
    /* register for receiving notifications */
    hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
    if (hr == S_OK)
    {
700
        LPITEMIDLIST raw_pidl;
701 702
        SHChangeNotifyEntry ntreg;

703
        hr = IPersistFolder2_GetCurFolder(ppf2, &raw_pidl);
704
        if(SUCCEEDED(hr))
705
        {
706 707 708 709 710 711 712 713 714 715 716 717 718 719
            LPITEMIDLIST computer_pidl;
            SHGetFolderLocation(NULL,CSIDL_DRIVES,NULL,0,&computer_pidl);
            if(ILIsParent(computer_pidl,raw_pidl,FALSE))
            {
                /* Normalize the pidl to unixfs to workaround an issue with
                 * sending notifications on dos paths
                 */
                WCHAR path[MAX_PATH];
                SHGetPathFromIDListW(raw_pidl,path);
                SHParseDisplayName(path,NULL,(LPITEMIDLIST*)&ntreg.pidl,0,NULL);
                SHFree(raw_pidl);
            }
            else
                ntreg.pidl = raw_pidl;
720
            ntreg.fRecursive = TRUE;
721
            This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNRF_InterruptLevel, SHCNE_ALLEVENTS,
722 723
                                                   SHV_CHANGE_NOTIFY, 1, &ntreg);
            SHFree((LPITEMIDLIST)ntreg.pidl);
724
            SHFree(computer_pidl);
725 726 727
        }
        IPersistFolder2_Release(ppf2);
    }
728

729
    This->hAccel = LoadAcceleratorsW(shell32_hInstance, accel_nameW);
730

731
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
732
}
733 734 735 736 737 738

/**********************************************************
 *	#### Handling of the menus ####
 */

/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
739
* ShellView_BuildFileMenu()
740 741
*/
static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
742 743
{	WCHAR	szText[MAX_PATH];
	MENUITEMINFOW	mii;
744
	int	nTools,i;
745
	HMENU	hSubMenu;
Alexandre Julliard's avatar
Alexandre Julliard committed
746

747
	TRACE("(%p)\n",This);
Alexandre Julliard's avatar
Alexandre Julliard committed
748

749
	hSubMenu = CreatePopupMenu();
Alexandre Julliard's avatar
Alexandre Julliard committed
750 751
	if(hSubMenu)
	{ /*get the number of items in our global array*/
752
	  for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
Alexandre Julliard's avatar
Alexandre Julliard committed
753

Alexandre Julliard's avatar
Alexandre Julliard committed
754
	  /*add the menu items*/
Alexandre Julliard's avatar
Alexandre Julliard committed
755
	  for(i = 0; i < nTools; i++)
756
	  {
757
	    LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
758

Alexandre Julliard's avatar
Alexandre Julliard committed
759 760 761 762
	    ZeroMemory(&mii, sizeof(mii));
	    mii.cbSize = sizeof(mii);
	    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;

763
	    if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
764 765
	    {
	      mii.fType = MFT_STRING;
Alexandre Julliard's avatar
Alexandre Julliard committed
766 767
	      mii.fState = MFS_ENABLED;
	      mii.dwTypeData = szText;
768
	      mii.wID = Tools[i].idCommand;
Alexandre Julliard's avatar
Alexandre Julliard committed
769
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
770
	    else
771 772
	    {
	      mii.fType = MFT_SEPARATOR;
Alexandre Julliard's avatar
Alexandre Julliard committed
773
	    }
774
	    /* tack This item onto the end of the menu */
775
	    InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
Alexandre Julliard's avatar
Alexandre Julliard committed
776
	  }
Alexandre Julliard's avatar
Alexandre Julliard committed
777
	}
778
	TRACE("-- return (menu=%p)\n",hSubMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
779 780
	return hSubMenu;
}
781

782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
static void ShellView_MergeFileMenu(IShellViewImpl *This, HMENU hSubMenu)
{
     if (hSubMenu)
     {
         static const WCHAR dummyW[] = {'d','u','m','m','y','4','5',0};
         MENUITEMINFOW mii;

         /* insert This item at the beginning of the menu */

         mii.cbSize = sizeof(mii);
         mii.fMask = MIIM_ID | MIIM_TYPE;
         mii.wID = 0;
         mii.fType = MFT_SEPARATOR;
         InsertMenuItemW(hSubMenu, 0, TRUE, &mii);

         mii.cbSize = sizeof(mii);
         mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
         mii.dwTypeData = (LPWSTR)dummyW;
         mii.fState = MFS_ENABLED;
         mii.wID = IDM_MYFILEITEM;
         mii.fType = MFT_STRING;
         InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
805 806
}

807
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
808
* ShellView_MergeViewMenu()
809
*/
810

811
static void ShellView_MergeViewMenu(IShellViewImpl *This, HMENU hSubMenu)
812
{
813
    TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
814

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
    /* add a separator at the correct position in the menu */
    if (hSubMenu)
    {
        static const WCHAR menuW[] = {'M','E','N','U','_','0','0','1',0};
	static const WCHAR viewW[] = {'V','i','e','w',0};
        MENUITEMINFOW mii;

        memset(&mii, 0, sizeof(mii));
        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_ID | MIIM_TYPE;
        mii.wID = 0;
        mii.fType = MFT_SEPARATOR;
        InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);

        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
        mii.fType = MFT_STRING;
        mii.dwTypeData = (LPWSTR)viewW;
        mii.hSubMenu = LoadMenuW(shell32_hInstance, menuW);
        InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
836
}
837

838 839 840
/**********************************************************
*   ShellView_GetSelections()
*
841 842
* - fills the this->apidl list with the selected objects
*
843 844
* RETURNS
*  number of selected items
845
*/
846 847
static UINT ShellView_GetSelections(IShellViewImpl * This)
{
848
	LVITEMW	lvItem;
849 850
	UINT	i = 0;

851
	SHFree(This->apidl);
852

853
	This->cidl = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
854
	This->apidl = SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
855 856

	TRACE("selected=%i\n", This->cidl);
857

858 859 860 861 862 863
	if(This->apidl)
	{
	  TRACE("-- Items selected =%u\n", This->cidl);

	  lvItem.mask = LVIF_STATE | LVIF_PARAM;
	  lvItem.stateMask = LVIS_SELECTED;
864 865
	  lvItem.iItem = 0;
	  lvItem.iSubItem = 0;
866

867
	  while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
868 869 870 871 872 873 874 875 876 877 878 879 880
	  {
	    if(lvItem.state & LVIS_SELECTED)
	    {
	      This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
	      i++;
	      TRACE("-- selected Item found\n");
	    }
	    lvItem.iItem++;
	  }
	}
	return This->cidl;

}
881 882 883 884 885 886 887 888 889 890 891 892 893

/**********************************************************
 *	ShellView_OpenSelectedItems()
 */
static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
{
	static UINT CF_IDLIST = 0;
	HRESULT hr;
	IDataObject* selection;
	FORMATETC fetc;
	STGMEDIUM stgm;
	LPIDA pIDList;
	LPCITEMIDLIST parent_pidl;
894 895 896
	WCHAR parent_path[MAX_PATH];
	LPCWSTR parent_dir = NULL;
	SFGAOF attribs;
897 898 899 900 901 902 903 904 905 906 907 908 909 910
	int i;

	if (0 == ShellView_GetSelections(This))
	{
	  return S_OK;
	}
	hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
	                                (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
	                                0, (LPVOID *)&selection);
	if (FAILED(hr))
	  return hr;

	if (0 == CF_IDLIST)
	{
911
	  CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
	}
	fetc.cfFormat = CF_IDLIST;
	fetc.ptd = NULL;
	fetc.dwAspect = DVASPECT_CONTENT;
	fetc.lindex = -1;
	fetc.tymed = TYMED_HGLOBAL;

	hr = IDataObject_QueryGetData(selection, &fetc);
	if (FAILED(hr))
	  return hr;

	hr = IDataObject_GetData(selection, &fetc, &stgm);
	if (FAILED(hr))
	  return hr;

	pIDList = GlobalLock(stgm.u.hGlobal);

	parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
930 931 932 933 934 935 936
	hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
	if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
	    SHGetPathFromIDListW(parent_pidl, parent_path))
	{
	  parent_dir = parent_path;
	}

937 938 939 940 941 942 943 944 945 946 947
	for (i = pIDList->cidl; i > 0; --i)
	{
	  LPCITEMIDLIST pidl;

	  pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);

	  attribs = SFGAO_FOLDER;
	  hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);

	  if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
	  {
948
	    SHELLEXECUTEINFOW shexinfo;
949

950
	    shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
951 952 953 954 955
	    shexinfo.fMask = SEE_MASK_INVOKEIDLIST;	/* SEE_MASK_IDLIST is also possible. */
	    shexinfo.hwnd = NULL;
	    shexinfo.lpVerb = NULL;
	    shexinfo.lpFile = NULL;
	    shexinfo.lpParameters = NULL;
956
	    shexinfo.lpDirectory = parent_dir;
957 958 959
	    shexinfo.nShow = SW_NORMAL;
	    shexinfo.lpIDList = ILCombine(parent_pidl, pidl);

960
	    ShellExecuteExW(&shexinfo);    /* Discard error/success info */
961

962
            ILFree(shexinfo.lpIDList);
963 964 965 966 967 968 969 970 971 972 973
	  }
	}

	GlobalUnlock(stgm.u.hGlobal);
	ReleaseStgMedium(&stgm);

	IDataObject_Release(selection);

	return S_OK;
}

974 975 976 977 978 979 980 981 982 983 984
/**********************************************************
 *	ShellView_DoContextMenu()
 */
static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
{	UINT	uCommand;
	DWORD	wFlags;
	HMENU	hMenu;
	BOOL	fExplore = FALSE;
	HWND	hwndTree = 0;
	LPCONTEXTMENU	pContextMenu = NULL;
	CMINVOKECOMMANDINFO	cmi;
985

986
	TRACE("%p, %d, %d, %d.\n", This, x, y, bDefault);
987 988 989 990

	/* look, what's selected and create a context menu object of it*/
	if( ShellView_GetSelections(This) )
	{
991
	  IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
992
                                      &IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013

	  if(pContextMenu)
	  {
	    TRACE("-- pContextMenu\n");
	    hMenu = CreatePopupMenu();

	    if( hMenu )
	    {
	      /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
	      if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
	      {
	        TRACE("-- explore mode\n");
	        fExplore = TRUE;
	      }

	      /* build the flags depending on what we can do with the selected item */
	      wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);

	      /* let the ContextMenu merge its items in */
	      if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
	      {
1014 1015 1016
	        if (This->FolderSettings.fFlags & FWF_DESKTOP)
		  SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);

1017 1018 1019 1020 1021 1022 1023 1024 1025
		if( bDefault )
		{
		  TRACE("-- get menu default command\n");
		  uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
		}
		else
		{
		  TRACE("-- track popup\n");
		  uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1026
		}
1027 1028 1029 1030

		if(uCommand > 0)
		{
		  TRACE("-- uCommand=%u\n", uCommand);
1031
		  if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1032 1033
		  {
		    TRACE("-- dlg: OnDefaultCommand\n");
1034
		    if (OnDefaultCommand(This) != S_OK)
1035 1036 1037
		    {
		      ShellView_OpenSelectedItems(This);
		    }
1038 1039 1040 1041 1042 1043
		  }
		  else
		  {
		    TRACE("-- explore -- invoke command\n");
		    ZeroMemory(&cmi, sizeof(cmi));
		    cmi.cbSize = sizeof(cmi);
1044
		    cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1045
                    cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1046 1047 1048 1049 1050 1051 1052 1053
		    IContextMenu_InvokeCommand(pContextMenu, &cmi);
		  }
		}
		DestroyMenu(hMenu);
	      }
	    }
	    if (pContextMenu)
	      IContextMenu_Release(pContextMenu);
1054 1055
	  }
	}
1056
	else	/* background context menu */
1057
	{
1058 1059
	  IContextMenu2 *pCM;

1060 1061
	  hMenu = CreatePopupMenu();

1062
	  BackgroundMenu_Constructor(This->pSFParent, FALSE, &IID_IContextMenu2, (void**)&pCM);
1063
	  IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1064 1065 1066 1067

	  uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
	  DestroyMenu(hMenu);

1068
	  TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1069 1070 1071

	  ZeroMemory(&cmi, sizeof(cmi));
	  cmi.cbSize = sizeof(cmi);
1072
          cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1073
	  cmi.hwnd = This->hWndParent;
1074
	  IContextMenu2_InvokeCommand(pCM, &cmi);
1075

1076
	  IContextMenu2_Release(pCM);
1077
	}
1078 1079
}

1080 1081 1082 1083 1084 1085
/**********************************************************
 *	##### message handling #####
 */

/**********************************************************
*  ShellView_OnSize()
Alexandre Julliard's avatar
Alexandre Julliard committed
1086
*/
1087 1088 1089
static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
{
	TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
1090

1091 1092 1093 1094
	/*resize the ListView to fit our window*/
	if(This->hWndList)
	{
	  MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
1095
	}
1096

1097
	return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1098
}
1099
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1100 1101 1102 1103
* ShellView_OnDeactivate()
*
* NOTES
*  internal
1104
*/
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
static void ShellView_OnDeactivate(IShellViewImpl * This)
{
	TRACE("%p\n",This);

	if(This->uState != SVUIA_DEACTIVATE)
	{
	  if(This->hMenu)
	  {
	    IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
	    IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
	    DestroyMenu(This->hMenu);
	    This->hMenu = 0;
	  }

	  This->uState = SVUIA_DEACTIVATE;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
1121 1122
}

1123
/**********************************************************
1124
* ShellView_OnActivate()
1125
*/
1126 1127 1128 1129
static LRESULT ShellView_OnActivate(IShellViewImpl *This, UINT uState)
{
    OLEMENUGROUPWIDTHS   omw = { {0, 0, 0, 0, 0, 0} };
    MENUITEMINFOW mii;
Alexandre Julliard's avatar
Alexandre Julliard committed
1130

1131
    TRACE("(%p) uState=%x\n",This,uState);
Alexandre Julliard's avatar
Alexandre Julliard committed
1132

1133 1134 1135 1136
    /* don't do anything if the state isn't really changing */
    if (This->uState == uState) return S_OK;

    ShellView_OnDeactivate(This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1137

1138 1139 1140 1141 1142
    /* only do This if we are active */
    if (uState != SVUIA_DEACTIVATE)
    {
        /* merge the menus */
        This->hMenu = CreateMenu();
Alexandre Julliard's avatar
Alexandre Julliard committed
1143

1144
        if (This->hMenu)
1145
	{
1146
            static const WCHAR dummyW[] = {'d','u','m','m','y',' ','3','1',0};
1147

1148
            IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1149
	    TRACE("-- after fnInsertMenusSB\n");
1150

1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
            mii.cbSize = sizeof(mii);
            mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
            mii.fType = MFT_STRING;
            mii.fState = MFS_ENABLED;
            mii.wID = 0;
            mii.hSubMenu = ShellView_BuildFileMenu(This);
            mii.hbmpChecked = NULL;
            mii.hbmpUnchecked = NULL;
            mii.dwItemData = 0;
            /* build the top level menu get the menu item's text */
            mii.dwTypeData = (LPWSTR)dummyW;
            mii.cch = 0;
            mii.hbmpItem = NULL;

            /* insert our menu into the menu bar */
            if (mii.hSubMenu)
                InsertMenuItemW(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);

            /* get the view menu so we can merge with it */
            memset(&mii, 0, sizeof(mii));
            mii.cbSize = sizeof(mii);
            mii.fMask = MIIM_SUBMENU;
1173

1174 1175
            if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
                ShellView_MergeViewMenu(This, mii.hSubMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
1176

1177 1178
            /* add the items that should only be added if we have the focus */
	    if (SVUIA_ACTIVATE_FOCUS == uState)
1179
	    {
1180 1181 1182 1183
                /* get the file menu so we can merge with it */
                memset(&mii, 0, sizeof(mii));
                mii.cbSize = sizeof(mii);
                mii.fMask = MIIM_SUBMENU;
1184

1185 1186
                if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
                    ShellView_MergeFileMenu(This, mii.hSubMenu);
Alexandre Julliard's avatar
Alexandre Julliard committed
1187
	    }
1188 1189 1190

            TRACE("-- before fnSetMenuSB\n");
            IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1191
	}
1192 1193 1194 1195
    }
    This->uState = uState;
    TRACE("--\n");
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1196 1197
}

1198
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1199 1200 1201
*  ShellView_OnSetFocus()
*
*/
1202 1203 1204 1205 1206
static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
{
	TRACE("%p\n",This);

	/* Tell the browser one of our windows has received the focus. This
1207
	should always be done before merging menus (OnActivate merges the
1208 1209
	menus) if one of our windows has the focus.*/

1210
	IShellBrowser_OnViewWindowActive(This->pShellBrowser, (IShellView *)&This->IShellView3_iface);
1211
	ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
Alexandre Julliard's avatar
Alexandre Julliard committed
1212

1213 1214 1215
	/* Set the focus to the listview */
	SetFocus(This->hWndList);

1216 1217 1218
	/* Notify the ICommDlgBrowser interface */
	OnStateChange(This,CDBOSC_SETFOCUS);

Alexandre Julliard's avatar
Alexandre Julliard committed
1219
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1220 1221
}

1222
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1223
* ShellView_OnKillFocus()
1224
*/
1225 1226
static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
{
1227
	TRACE("%p.\n", This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1228

1229
	ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1230 1231
	/* Notify the ICommDlgBrowser */
	OnStateChange(This,CDBOSC_KILLFOCUS);
Alexandre Julliard's avatar
Alexandre Julliard committed
1232 1233 1234

	return 0;
}
1235 1236

/**********************************************************
1237
* ShellView_OnCommand()
1238 1239
*
* NOTES
1240
*	the CmdIDs are the ones from the context menu
1241
*/
1242 1243
static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
{
1244
	TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1245

1246 1247
	switch(dwCmdID)
	{
1248
	  case FCIDM_SHVIEW_SMALLICON:
1249 1250
	    This->FolderSettings.ViewMode = FVM_SMALLICON;
	    SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1251
	    CheckToolbar(This);
1252 1253 1254
	    break;

	  case FCIDM_SHVIEW_BIGICON:
1255 1256
	    This->FolderSettings.ViewMode = FVM_ICON;
	    SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1257
	    CheckToolbar(This);
1258 1259 1260
	    break;

	  case FCIDM_SHVIEW_LISTVIEW:
1261 1262
	    This->FolderSettings.ViewMode = FVM_LIST;
	    SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1263
	    CheckToolbar(This);
1264 1265 1266
	    break;

	  case FCIDM_SHVIEW_REPORTVIEW:
1267 1268
	    This->FolderSettings.ViewMode = FVM_DETAILS;
	    SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1269
	    CheckToolbar(This);
1270 1271
	    break;

1272
	  /* the menu IDs for sorting are 0x30... see shell32.rc */
1273 1274 1275 1276
	  case 0x30:
	  case 0x31:
	  case 0x32:
	  case 0x33:
1277
            This->ListViewSortInfo.nHeaderID = dwCmdID - 0x30;
1278 1279
	    This->ListViewSortInfo.bIsAscending = TRUE;
	    This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1280
	    SendMessageW(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1281
	    break;
1282

1283
	  default:
1284
	    TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1285 1286 1287 1288
	}
	return 0;
}

1289
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1290 1291
* ShellView_OnNotify()
*/
1292

1293
static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1294
{	LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1295
	NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
Alexandre Julliard's avatar
Alexandre Julliard committed
1296
	LPITEMIDLIST pidl;
1297

1298
	TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1299

Alexandre Julliard's avatar
Alexandre Julliard committed
1300
	switch(lpnmh->code)
1301 1302
	{
	  case NM_SETFOCUS:
1303
	    TRACE("-- NM_SETFOCUS %p\n",This);
1304
	    ShellView_OnSetFocus(This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1305 1306 1307
	    break;

	  case NM_KILLFOCUS:
1308
	    TRACE("-- NM_KILLFOCUS %p\n",This);
1309
	    ShellView_OnDeactivate(This);
1310 1311
	    /* Notify the ICommDlgBrowser interface */
	    OnStateChange(This,CDBOSC_KILLFOCUS);
Alexandre Julliard's avatar
Alexandre Julliard committed
1312 1313
	    break;

1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
	  case NM_CUSTOMDRAW:
	    TRACE("-- NM_CUSTOMDRAW %p\n",This);
	    return CDRF_DODEFAULT;

	  case NM_RELEASEDCAPTURE:
	    TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
	    break;

	  case NM_CLICK:
	    TRACE("-- NM_CLICK %p\n",This);
	    break;

	  case NM_RCLICK:
	    TRACE("-- NM_RCLICK %p\n",This);
	    break;	    

1330 1331 1332 1333 1334 1335
          case NM_DBLCLK:
            TRACE("-- NM_DBLCLK %p\n",This);
            if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
            break;

          case NM_RETURN:
1336
            TRACE("-- NM_RETURN %p\n",This);
1337 1338 1339
            if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
            break;

1340 1341
	  case HDN_ENDTRACKW:
	    TRACE("-- HDN_ENDTRACKW %p\n",This);
1342 1343
	    /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
	    nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1344
	    break;
1345

Alexandre Julliard's avatar
Alexandre Julliard committed
1346
	  case LVN_DELETEITEM:
1347
	    TRACE("-- LVN_DELETEITEM %p\n",This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1348 1349
	    SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1350

1351 1352 1353 1354
	  case LVN_DELETEALLITEMS:
	    TRACE("-- LVN_DELETEALLITEMS %p\n",This);
	    return FALSE;

1355 1356 1357 1358
	  case LVN_INSERTITEM:
	    TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
	    break;

Alexandre Julliard's avatar
Alexandre Julliard committed
1359
	  case LVN_ITEMACTIVATE:
1360
	    TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1361
	    OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
Alexandre Julliard's avatar
Alexandre Julliard committed
1362
	    break;
1363

1364
	  case LVN_COLUMNCLICK:
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
	    This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
	    if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
	    {
	      This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
	    }
	    else
	    {
	      This->ListViewSortInfo.bIsAscending = TRUE;
	    }
	    This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1375

1376
	    SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1377
	    break;
1378

1379
	  case LVN_GETDISPINFOA:
1380 1381
          case LVN_GETDISPINFOW:
	    TRACE("-- LVN_GETDISPINFO %p\n",This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1382 1383
	    pidl = (LPITEMIDLIST)lpdi->item.lParam;

1384 1385
	    if(lpdi->item.mask & LVIF_TEXT)	/* text requested */
	    {
1386 1387 1388 1389
	      static WCHAR emptyW[] = { 0 };
	      SHELLDETAILS sd;
	      HRESULT hr;

1390
	      if (This->pSF2Parent)
1391
	      {
1392
	        hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1393
	      }
1394
	      else
1395
	      {
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
	        IShellDetails *details;

	        hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IShellDetails, (void**)&details);
	        if (hr == S_OK)
	        {
	          hr = IShellDetails_GetDetailsOf(details, pidl, lpdi->item.iSubItem, &sd);
	          IShellDetails_Release(details);
	        }
	        else
	          WARN("IShellFolder2/IShellDetails not supported\n");
	      }

	      if (hr != S_OK)
	      {
	          /* set to empty on failure */
	          sd.str.uType = STRRET_WSTR;
	          sd.str.u.pOleStr = emptyW;
Alexandre Julliard's avatar
Alexandre Julliard committed
1413
	      }
1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426

              if (lpnmh->code == LVN_GETDISPINFOW)
              {
                  StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
                  TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
              }
              else
              {
                  /* LVN_GETDISPINFOA - shouldn't happen */
                  NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
                  StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
                  TRACE("-- text=%s\n", lpdiA->item.pszText);
              }
Alexandre Julliard's avatar
Alexandre Julliard committed
1427
	    }
1428

1429 1430 1431 1432
	    if(lpdi->item.mask & LVIF_IMAGE)	/* image requested */
	    {
	      lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1433
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1434

Alexandre Julliard's avatar
Alexandre Julliard committed
1435
	  case LVN_ITEMCHANGED:
1436
	    TRACE("-- LVN_ITEMCHANGED %p\n",This);
1437
	    OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
Alexandre Julliard's avatar
Alexandre Julliard committed
1438 1439
	    break;

1440 1441
	  case LVN_BEGINDRAG:
	  case LVN_BEGINRDRAG:
1442
	    TRACE("-- LVN_BEGINDRAG\n");
1443 1444

	    if (ShellView_GetSelections(This))
1445
	    {
1446
	      IDataObject * pda;
Juergen Schmied's avatar
Juergen Schmied committed
1447
	      DWORD dwAttributes = SFGAO_CANLINK;
1448
	      DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1449

1450
	      if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1451
	      {
1452
                  IDropSource *pds = &This->IDropSource_iface; /* own DropSource interface */
1453

1454
	  	  if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1455
		  {
1456 1457 1458 1459
		    if (dwAttributes & SFGAO_CANLINK)
		    {
		      dwEffect |= DROPEFFECT_LINK;
		    }
1460
		  }
1461

1462 1463
	          if (pds)
	          {
1464 1465
	            DWORD dwEffect2;
		    DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1466 1467
		  }
	          IDataObject_Release(pda);
1468 1469 1470 1471
	      }
	    }
	    break;

1472
	  case LVN_BEGINLABELEDITW:
1473 1474 1475 1476
	    {
	      DWORD dwAttr = SFGAO_CANRENAME;
	      pidl = (LPITEMIDLIST)lpdi->item.lParam;

1477
	      TRACE("-- LVN_BEGINLABELEDITW %p\n",This);
1478

1479
	      IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1480 1481 1482 1483 1484 1485 1486
	      if (SFGAO_CANRENAME & dwAttr)
	      {
	        return FALSE;
	      }
	      return TRUE;
	    }

1487
	  case LVN_ENDLABELEDITW:
1488 1489 1490 1491 1492
	    {
	      TRACE("-- LVN_ENDLABELEDITA %p\n",This);
	      if (lpdi->item.pszText)
	      {
	        HRESULT hr;
1493
		LVITEMW lvItem;
1494 1495

		lvItem.iItem = lpdi->item.iItem;
1496
		lvItem.iSubItem = 0;
1497
		lvItem.mask = LVIF_PARAM;
1498
		SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1499

1500
		pidl = (LPITEMIDLIST)lpdi->item.lParam;
1501
	        hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1502

1503 1504 1505 1506
		if(SUCCEEDED(hr) && pidl)
		{
	          lvItem.mask = LVIF_PARAM;
		  lvItem.lParam = (LPARAM)pidl;
1507
		  SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1508 1509 1510 1511 1512
		  return TRUE;
		}
	      }
	      return FALSE;
	    }
1513

1514 1515 1516
	  case LVN_KEYDOWN:
	    {
	      LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1517 1518

              /* initiate a rename of the selected file or directory */
1519
              switch (plvKeyDown->wVKey)
1520
              {
1521
              case VK_F2:
1522
                {
1523
                  INT i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
1524

1525 1526 1527 1528 1529 1530 1531 1532
                  if (i == 1)
                  {
                    /* get selected item */
                    i = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, MAKELPARAM (LVNI_SELECTED, 0));

                    SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
                    SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
                  }
1533
                }
1534 1535 1536 1537 1538 1539 1540 1541 1542
                break;
              case VK_DELETE:
                {
		  UINT i, count;
		  int item_index;
		  LVITEMW item;
		  LPITEMIDLIST* pItems;
		  ISFHelper *psfhlp;
		  HRESULT hr;
1543

1544 1545
		  hr = IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (void**)&psfhlp);
		  if (hr != S_OK) return 0;
1546

1547 1548 1549 1550 1551
		  if(!(count = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0)))
		  {
		    ISFHelper_Release(psfhlp);
		    return 0;
		  }
1552

1553
		  /* allocate memory for the pidl array */
1554
		  pItems = heap_alloc(sizeof(LPITEMIDLIST) * count);
1555

1556 1557 1558
		  /* retrieve all selected items */
		  i = 0;
		  item_index = -1;
1559

1560 1561 1562 1563 1564 1565 1566 1567
		  while (count > i)
		  {
		    /* get selected item */
		    item_index = SendMessageW(This->hWndList, LVM_GETNEXTITEM, item_index,
                                              MAKELPARAM (LVNI_SELECTED, 0));
		    item.iItem = item_index;
		    item.mask = LVIF_PARAM;
		    SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM)&item);
1568

1569 1570
		    /* get item pidl */
		    pItems[i] = (LPITEMIDLIST)item.lParam;
1571

1572 1573
		    i++;
		  }
1574

1575 1576 1577
		  /* perform the item deletion */
		  ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
		  ISFHelper_Release(psfhlp);
1578

1579
		  /* free pidl array memory */
1580
		  heap_free(pItems);
1581 1582
                }
		break;
1583

1584 1585
	      case VK_F5:
                /* Initiate a refresh */
1586
		IShellView3_Refresh(&This->IShellView3_iface);
1587
		break;
1588

1589
	      case VK_BACK:
1590
		{
1591 1592 1593 1594 1595 1596 1597
		  LPSHELLBROWSER lpSb;
		  if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
		  {
		    IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
		  }
	        }
		break;
1598

1599 1600 1601
	      default:
		FIXME("LVN_KEYDOWN key=0x%08x\n", plvKeyDown->wVKey);
	      }
1602 1603
	    }
	    break;
1604

Alexandre Julliard's avatar
Alexandre Julliard committed
1605
	  default:
1606
	    TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1607
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1608 1609
	}
	return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1610 1611
}

1612 1613 1614 1615
/**********************************************************
* ShellView_OnChange()
*/

1616
static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST *pidls, LONG event)
1617
{
1618
    LPCITEMIDLIST pidl;
1619
    BOOL ret = TRUE;
1620

1621 1622 1623 1624 1625 1626
    TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pidls[0], pidls[1], event);

    switch (event)
    {
        case SHCNE_MKDIR:
        case SHCNE_CREATE:
1627 1628
            pidl = ILClone(ILFindLastID(pidls[0]));
            shellview_add_item(This, pidl);
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641
            break;
        case SHCNE_RMDIR:
        case SHCNE_DELETE:
        {
            INT i = LV_FindItemByPidl(This, ILFindLastID(pidls[0]));
            ret = SendMessageW(This->hWndList, LVM_DELETEITEM, i, 0);
            break;
        }
        case SHCNE_RENAMEFOLDER:
        case SHCNE_RENAMEITEM:
            LV_RenameItem(This, pidls[0], pidls[1]);
            break;
        case SHCNE_UPDATEITEM:
1642
	    break;
1643 1644
    }
    return ret;
1645
}
1646
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1647 1648 1649
*  ShellView_WndProc
*/

1650 1651
static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
1652
	IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1653
	LPCREATESTRUCTW lpcs;
1654

1655
	TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1656 1657 1658 1659

	switch (uMessage)
	{
	  case WM_NCCREATE:
1660
	    lpcs = (LPCREATESTRUCTW)lParam;
1661
            pThis = lpcs->lpCreateParams;
1662
	    SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1663 1664 1665 1666 1667 1668 1669 1670 1671
	    pThis->hWnd = hWnd;        /*set the window handle*/
	    break;

	  case WM_SIZE:		return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
	  case WM_SETFOCUS:	return ShellView_OnSetFocus(pThis);
	  case WM_KILLFOCUS:	return ShellView_OnKillFocus(pThis);
	  case WM_CREATE:	return ShellView_OnCreate(pThis);
	  case WM_ACTIVATE:	return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
	  case WM_NOTIFY:	return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1672 1673 1674
	  case WM_COMMAND:      return ShellView_OnCommand(pThis,
					GET_WM_COMMAND_ID(wParam, lParam),
					GET_WM_COMMAND_CMD(wParam, lParam),
1675
					GET_WM_COMMAND_HWND(wParam, lParam));
1676
	  case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1677

1678 1679 1680
	  case WM_CONTEXTMENU:  ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
	                        return 0;

1681 1682 1683
	  case WM_SHOWWINDOW:	UpdateWindow(pThis->hWndList);
				break;

1684
	  case WM_GETDLGCODE:   return SendMessageW(pThis->hWndList, uMessage, 0, 0);
1685 1686
          case WM_SETFONT:      return SendMessageW(pThis->hWndList, WM_SETFONT, wParam, lParam);
          case WM_GETFONT:      return SendMessageW(pThis->hWndList, WM_GETFONT, wParam, lParam);
1687

1688 1689
	  case WM_DESTROY:	
	  			RevokeDragDrop(pThis->hWnd);
1690
				SHChangeNotifyDeregister(pThis->hNotify);
1691
	                        break;
1692 1693 1694 1695 1696 1697

	  case WM_ERASEBKGND:
	    if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
	        (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
	      return 1;
	    break;
1698 1699
	}

1700
	return DefWindowProcW(hWnd, uMessage, wParam, lParam);
Alexandre Julliard's avatar
Alexandre Julliard committed
1701
}
1702
/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1703 1704 1705 1706 1707
*
*
*  The INTERFACE of the IShellView object
*
*
1708
**********************************************************
1709
*  IShellView_QueryInterface
Alexandre Julliard's avatar
Alexandre Julliard committed
1710
*/
1711
static HRESULT WINAPI IShellView_fnQueryInterface(IShellView3 *iface, REFIID riid, void **ppvObj)
1712
{
1713
	IShellViewImpl *This = impl_from_IShellView3(iface);
Alexandre Julliard's avatar
Alexandre Julliard committed
1714

1715
	TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj);
1716 1717 1718

	*ppvObj = NULL;

1719 1720
	if(IsEqualIID(riid, &IID_IUnknown) ||
	   IsEqualIID(riid, &IID_IShellView) ||
1721
	   IsEqualIID(riid, &IID_IShellView2) ||
1722 1723
	   IsEqualIID(riid, &IID_IShellView3) ||
	   IsEqualIID(riid, &IID_CDefView))
1724
	{
1725
	  *ppvObj = &This->IShellView3_iface;
1726
	}
1727 1728
	else if(IsEqualIID(riid, &IID_IShellFolderView))
	{
1729
          *ppvObj = &This->IShellFolderView_iface;
1730
	}
1731 1732
	else if(IsEqualIID(riid, &IID_IFolderView) ||
		IsEqualIID(riid, &IID_IFolderView2))
1733
	{
1734
          *ppvObj = &This->IFolderView2_iface;
1735
	}
1736 1737
	else if(IsEqualIID(riid, &IID_IOleCommandTarget))
	{
1738
          *ppvObj = &This->IOleCommandTarget_iface;
1739
	}
1740 1741
	else if(IsEqualIID(riid, &IID_IDropTarget))
	{
1742
          *ppvObj = &This->IDropTarget_iface;
1743
	}
1744 1745
	else if(IsEqualIID(riid, &IID_IDropSource))
	{
1746
          *ppvObj = &This->IDropSource_iface;
1747
	}
1748 1749
	else if(IsEqualIID(riid, &IID_IViewObject))
	{
1750
          *ppvObj = &This->IViewObject_iface;
1751 1752 1753
	}

	if(*ppvObj)
1754 1755
	{
	  IUnknown_AddRef( (IUnknown*)*ppvObj );
1756
	  TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1757 1758
	  return S_OK;
	}
1759
	TRACE("-- Interface: E_NOINTERFACE\n");
1760 1761
	return E_NOINTERFACE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1762

1763
/**********************************************************
Juergen Schmied's avatar
Juergen Schmied committed
1764
*  IShellView_AddRef
Alexandre Julliard's avatar
Alexandre Julliard committed
1765
*/
1766
static ULONG WINAPI IShellView_fnAddRef(IShellView3 *iface)
1767
{
1768 1769
    IShellViewImpl *This = impl_from_IShellView3(iface);
    ULONG refCount = InterlockedIncrement(&This->ref);
1770

1771
    TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1772

1773
    return refCount;
Alexandre Julliard's avatar
Alexandre Julliard committed
1774
}
1775
/**********************************************************
1776
*  IShellView_Release
Alexandre Julliard's avatar
Alexandre Julliard committed
1777
*/
1778
static ULONG WINAPI IShellView_fnRelease(IShellView3 *iface)
1779
{
1780
	IShellViewImpl *This = impl_from_IShellView3(iface);
1781
	ULONG refCount = InterlockedDecrement(&This->ref);
1782

1783
	TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1784

1785
	if (!refCount)
1786 1787
	{
	  TRACE(" destroying IShellView(%p)\n",This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1788

1789 1790
	  DestroyWindow(This->hWndList);

1791 1792
	  if(This->pSFParent)
	    IShellFolder_Release(This->pSFParent);
Alexandre Julliard's avatar
Alexandre Julliard committed
1793

1794 1795 1796
	  if(This->pSF2Parent)
	    IShellFolder2_Release(This->pSF2Parent);

1797
	  SHFree(This->apidl);
1798

1799 1800 1801
	  if(This->pAdvSink)
	    IAdviseSink_Release(This->pAdvSink);

1802
	  heap_free(This);
1803
	}
1804
	return refCount;
Alexandre Julliard's avatar
Alexandre Julliard committed
1805
}
1806 1807

/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1808
*  ShellView_GetWindow
Alexandre Julliard's avatar
Alexandre Julliard committed
1809
*/
1810
static HRESULT WINAPI IShellView_fnGetWindow(IShellView3 *iface, HWND *phWnd)
1811
{
1812
    IShellViewImpl *This = impl_from_IShellView3(iface);
1813

1814
    TRACE("(%p)\n", This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1815

1816 1817
    *phWnd = This->hWnd;
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1818
}
1819

1820
static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView3 *iface, BOOL mode)
1821
{
1822
    IShellViewImpl *This = impl_from_IShellView3(iface);
1823 1824
    TRACE("(%p)->(%d)\n", This, mode);
    return E_NOTIMPL;
Alexandre Julliard's avatar
Alexandre Julliard committed
1825
}
1826 1827

/**********************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
1828 1829 1830 1831 1832
* IShellView_TranslateAccelerator
*
* FIXME:
*  use the accel functions
*/
1833
static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView3 *iface, MSG *lpmsg)
1834
{
1835
#if 0
1836
	IShellViewImpl *This = (IShellViewImpl *)iface;
1837

1838
	FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1839
#endif
1840

1841
	if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message<=WM_KEYLAST))
1842
	{
1843
	  TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1844
	}
1845
	return S_FALSE; /* not handled */
Alexandre Julliard's avatar
Alexandre Julliard committed
1846
}
1847

1848
static HRESULT WINAPI IShellView_fnEnableModeless(IShellView3 *iface, BOOL fEnable)
1849
{
1850
    IShellViewImpl *This = impl_from_IShellView3(iface);
1851

1852
    FIXME("(%p) stub\n", This);
1853

1854
    return E_NOTIMPL;
Alexandre Julliard's avatar
Alexandre Julliard committed
1855
}
1856

1857
static HRESULT WINAPI IShellView_fnUIActivate(IShellView3 *iface, UINT uState)
1858
{
1859
	IShellViewImpl *This = impl_from_IShellView3(iface);
1860

1861
/*
1862
	CHAR	szName[MAX_PATH];
1863
*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1864
	LRESULT	lResult;
1865
	int	nPartArray[1] = {-1};
Alexandre Julliard's avatar
Alexandre Julliard committed
1866

1867
	TRACE("%p, %d.\n", This, uState);
1868

Alexandre Julliard's avatar
Alexandre Julliard committed
1869
	/*don't do anything if the state isn't really changing*/
1870
	if(This->uState == uState)
1871 1872
	{
	  return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1873
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
1874

Alexandre Julliard's avatar
Alexandre Julliard committed
1875
	/*OnActivate handles the menu merging and internal state*/
1876
	ShellView_OnActivate(This, uState);
Alexandre Julliard's avatar
Alexandre Julliard committed
1877

1878
	/*only do This if we are active*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1879
	if(uState != SVUIA_DEACTIVATE)
1880
	{
1881

1882 1883
/*
	  GetFolderPath is not a method of IShellFolder
1884
	  IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1885
*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1886
	  /* set the number of parts */
1887
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1888
	  						(LPARAM)nPartArray, &lResult);
Alexandre Julliard's avatar
Alexandre Julliard committed
1889 1890

	  /* set the text for the parts */
1891
/*
1892
	  IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1893
							0, (LPARAM)szName, &lResult);
1894
*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1895
	}
1896

Alexandre Julliard's avatar
Alexandre Julliard committed
1897 1898
	return S_OK;
}
1899

1900
static HRESULT WINAPI IShellView_fnRefresh(IShellView3 *iface)
1901
{
1902
    IShellViewImpl *This = impl_from_IShellView3(iface);
Alexandre Julliard's avatar
Alexandre Julliard committed
1903

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

1906 1907
    SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
    ShellView_FillList(This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1908

1909
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1910
}
1911

1912 1913
static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView3 *iface, IShellView *prev_view,
        const FOLDERSETTINGS *settings, IShellBrowser *owner, RECT *rect, HWND *hWnd)
1914
{
1915 1916 1917 1918
    IShellViewImpl *This = impl_from_IShellView3(iface);
    TRACE("(%p)->(%p %p %p %p %p)\n", This, prev_view, settings, owner, rect, hWnd);
    return IShellView3_CreateViewWindow3(iface, owner, prev_view, SV3CVW3_DEFAULT,
        settings->fFlags, settings->fFlags, settings->ViewMode, NULL, rect, hWnd);
Alexandre Julliard's avatar
Alexandre Julliard committed
1919 1920
}

1921
static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView3 *iface)
1922
{
1923
    IShellViewImpl *This = impl_from_IShellView3(iface);
1924

1925
    TRACE("(%p)\n", This);
Alexandre Julliard's avatar
Alexandre Julliard committed
1926

1927 1928
    if (!This->hWnd)
        return S_OK;
1929

1930 1931
    /* Make absolutely sure all our UI is cleaned up. */
    IShellView3_UIActivate(iface, SVUIA_DEACTIVATE);
1932

1933 1934
    if (This->hMenu)
        DestroyMenu(This->hMenu);
1935

1936 1937 1938
    DestroyWindow(This->hWnd);
    if (This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
    if (This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1939

1940 1941 1942 1943 1944 1945
    This->hMenu = NULL;
    This->hWnd = NULL;
    This->pShellBrowser = NULL;
    This->pCommDlgBrowser = NULL;

    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1946
}
1947

1948
static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView3 *iface, LPFOLDERSETTINGS lpfs)
1949
{
1950
    IShellViewImpl *This = impl_from_IShellView3(iface);
1951

1952 1953
    TRACE("(%p)->(%p) vmode=%x flags=%x\n", This, lpfs,
        This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1954

1955 1956 1957
    if (!lpfs) return E_INVALIDARG;
    *lpfs = This->FolderSettings;
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1958
}
1959

1960
static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView3 *iface, DWORD dwReserved,
1961
		LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1962
{
1963 1964 1965
    IShellViewImpl *This = impl_from_IShellView3(iface);
    FIXME("(%p) stub\n", This);
    return E_NOTIMPL;
Alexandre Julliard's avatar
Alexandre Julliard committed
1966
}
1967

1968
static HRESULT WINAPI IShellView_fnSaveViewState(IShellView3 *iface)
1969
{
1970 1971 1972
    IShellViewImpl *This = impl_from_IShellView3(iface);
    FIXME("(%p) stub\n", This);
    return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
1973
}
1974

1975
static HRESULT WINAPI IShellView_fnSelectItem(IShellView3 *iface, LPCITEMIDLIST pidl, UINT flags)
1976
{
1977
    IShellViewImpl *This = impl_from_IShellView3(iface);
1978
    int i;
1979

1980
    TRACE("(%p)->(pidl=%p, 0x%08x)\n",This, pidl, flags);
1981

1982 1983
    i = LV_FindItemByPidl(This, pidl);
    if (i == -1) return S_OK;
1984

1985
    return IFolderView2_SelectItem(&This->IFolderView2_iface, i, flags);
Alexandre Julliard's avatar
Alexandre Julliard committed
1986
}
1987

1988
static HRESULT WINAPI IShellView_fnGetItemObject(IShellView3 *iface, UINT uItem, REFIID riid,
1989
        void **ppvOut)
1990
{
1991
    IShellViewImpl *This = impl_from_IShellView3(iface);
1992
    HRESULT hr = E_NOINTERFACE;
1993

1994
    TRACE("(%p)->(0x%08x, %s, %p)\n",This, uItem, debugstr_guid(riid), ppvOut);
Alexandre Julliard's avatar
Alexandre Julliard committed
1995

1996
    *ppvOut = NULL;
1997

1998 1999 2000
    switch(uItem)
    {
    case SVGIO_BACKGROUND:
2001

2002
        if (IsEqualIID(&IID_IContextMenu, riid))
2003
            return BackgroundMenu_Constructor(This->pSFParent, FALSE, riid, ppvOut);
2004 2005 2006 2007 2008
        else if (IsEqualIID(&IID_IDispatch, riid)) {
            *ppvOut = &This->IShellFolderViewDual3_iface;
            IShellFolderViewDual3_AddRef(&This->IShellFolderViewDual3_iface);
            return S_OK;
        }
2009 2010
        else
            FIXME("unsupported interface requested %s\n", debugstr_guid(riid));
Alexandre Julliard's avatar
Alexandre Julliard committed
2011

2012
        break;
2013

2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
    case SVGIO_SELECTION:
	ShellView_GetSelections(This);
	hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
	break;

    default:
        FIXME("unimplemented for uItem = 0x%08x\n", uItem);
    }
    TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);

    return hr;
Alexandre Julliard's avatar
Alexandre Julliard committed
2025
}
2026

2027
static HRESULT WINAPI IShellView2_fnGetView(IShellView3 *iface, SHELLVIEWID *view_guid, ULONG view_type)
2028
{
2029
    FIXME("(%p)->(%s, %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2030 2031 2032
    return E_NOTIMPL;
}

2033
static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView3 *iface, SV2CVW2_PARAMS *view_params)
2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
{
    IShellViewImpl *This = impl_from_IShellView3(iface);
    TRACE("(%p)->(%p)\n", This, view_params);
    return IShellView3_CreateViewWindow3(iface, view_params->psbOwner, view_params->psvPrev,
        SV3CVW3_DEFAULT, view_params->pfs->fFlags, view_params->pfs->fFlags,
        view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView);
}

static HRESULT WINAPI IShellView2_fnHandleRename(IShellView3 *iface, LPCITEMIDLIST new_pidl)
{
    FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(IShellView3 *iface, LPCITEMIDLIST item,
        UINT flags, POINT *point)
{
    IShellViewImpl *This = impl_from_IShellView3(iface);
    TRACE("(%p)->(item %p, flags %#x, point %p)\n", This, item, flags, point);
    return IFolderView2_SelectAndPositionItems(&This->IFolderView2_iface, 1, &item, point, flags);
}

static HRESULT WINAPI IShellView3_fnCreateViewWindow3(IShellView3 *iface, IShellBrowser *owner,
    IShellView *prev_view, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags,
    FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, const RECT *rect, HWND *hwnd)
2059
{
2060
    IShellViewImpl *This = impl_from_IShellView3(iface);
2061
    INITCOMMONCONTROLSEX icex;
2062
    WNDCLASSW wc;
2063
    HRESULT hr;
2064 2065
    HWND wnd;

2066 2067
    TRACE("(%p)->(%p %p 0x%08x 0x%08x 0x%08x %d %s %s %p)\n", This, owner, prev_view, view_flags,
        mask, flags, mode, debugstr_guid(view_id), wine_dbgstr_rect(rect), hwnd);
2068

2069 2070 2071
    icex.dwSize = sizeof(icex);
    icex.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&icex);
2072

2073
    *hwnd = NULL;
2074

2075
    if (!owner || This->hWnd)
2076
        return E_UNEXPECTED;
2077

2078 2079
    if (view_flags != SV3CVW3_DEFAULT)
        FIXME("unsupported view flags 0x%08x\n", view_flags);
2080

2081
    /* Set up the member variables */
2082 2083 2084
    This->pShellBrowser = owner;
    This->FolderSettings.ViewMode = mode;
    This->FolderSettings.fFlags = mask & flags;
2085

2086
    if (view_id)
2087
    {
2088
        if (IsEqualGUID(view_id, &VID_LargeIcons))
2089
            This->FolderSettings.ViewMode = FVM_ICON;
2090
        else if (IsEqualGUID(view_id, &VID_SmallIcons))
2091
            This->FolderSettings.ViewMode = FVM_SMALLICON;
2092
        else if (IsEqualGUID(view_id, &VID_List))
2093
            This->FolderSettings.ViewMode = FVM_LIST;
2094
        else if (IsEqualGUID(view_id, &VID_Details))
2095
            This->FolderSettings.ViewMode = FVM_DETAILS;
2096
        else if (IsEqualGUID(view_id, &VID_Thumbnails))
2097
            This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2098
        else if (IsEqualGUID(view_id, &VID_Tile))
2099
            This->FolderSettings.ViewMode = FVM_TILE;
2100
        else if (IsEqualGUID(view_id, &VID_ThumbStrip))
2101 2102
            This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
        else
2103
            FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
2104 2105 2106 2107
    }

    /* Get our parent window */
    IShellBrowser_AddRef(This->pShellBrowser);
2108
    IShellBrowser_GetWindow(This->pShellBrowser, &This->hWndParent);
2109 2110 2111

    /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
    This->pCommDlgBrowser = NULL;
2112 2113
    hr = IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser);
    if (hr == S_OK)
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
        TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);

    /* If our window class has not been registered, then do so */
    if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
    {
        wc.style            = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc      = ShellView_WndProc;
        wc.cbClsExtra       = 0;
        wc.cbWndExtra       = 0;
        wc.hInstance        = shell32_hInstance;
        wc.hIcon            = 0;
        wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
        wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
        wc.lpszMenuName     = NULL;
        wc.lpszClassName    = SV_CLASS_NAME;

        if (!RegisterClassW(&wc)) return E_FAIL;
    }

2133
    wnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP,
2134 2135 2136
            rect->left, rect->top,
            rect->right - rect->left,
            rect->bottom - rect->top,
2137
            This->hWndParent, 0, shell32_hInstance, This);
2138 2139 2140

    CheckToolbar(This);

2141 2142 2143 2144 2145
    if (!wnd)
    {
        IShellBrowser_Release(This->pShellBrowser);
        return E_FAIL;
    }
2146 2147 2148 2149

    SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
    UpdateWindow(wnd);

2150
    *hwnd = wnd;
2151 2152

    return S_OK;
2153 2154
}

2155
static const IShellView3Vtbl shellviewvtbl =
2156
{
2157
	IShellView_fnQueryInterface,
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
	IShellView_fnAddRef,
	IShellView_fnRelease,
	IShellView_fnGetWindow,
	IShellView_fnContextSensitiveHelp,
	IShellView_fnTranslateAccelerator,
	IShellView_fnEnableModeless,
	IShellView_fnUIActivate,
	IShellView_fnRefresh,
	IShellView_fnCreateViewWindow,
	IShellView_fnDestroyViewWindow,
	IShellView_fnGetCurrentInfo,
	IShellView_fnAddPropertySheetPages,
	IShellView_fnSaveViewState,
	IShellView_fnSelectItem,
2172 2173 2174 2175 2176
	IShellView_fnGetItemObject,
	IShellView2_fnGetView,
	IShellView2_fnCreateViewWindow2,
	IShellView2_fnHandleRename,
	IShellView2_fnSelectAndPositionItem,
2177
	IShellView3_fnCreateViewWindow3
2178 2179
};

2180

2181
/**********************************************************
2182 2183
 * ISVOleCmdTarget_QueryInterface (IUnknown)
 */
2184
static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(IOleCommandTarget *iface, REFIID iid, void **ppvObj)
2185
{
2186 2187
    IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
    return IShellView3_QueryInterface(&This->IShellView3_iface, iid, ppvObj);
2188 2189
}

2190
/**********************************************************
2191 2192
 * ISVOleCmdTarget_AddRef (IUnknown)
 */
2193
static ULONG WINAPI ISVOleCmdTarget_AddRef(IOleCommandTarget *iface)
2194
{
2195 2196
    IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
    return IShellView3_AddRef(&This->IShellView3_iface);
2197 2198
}

2199
/**********************************************************
2200 2201
 * ISVOleCmdTarget_Release (IUnknown)
 */
2202
static ULONG WINAPI ISVOleCmdTarget_Release(IOleCommandTarget *iface)
2203
{
2204 2205
    IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
    return IShellView3_Release(&This->IShellView3_iface);
2206 2207
}

2208
/**********************************************************
Juergen Schmied's avatar
Juergen Schmied committed
2209
 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2210 2211 2212
 */
static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
	IOleCommandTarget *iface,
2213
	const GUID *pguidCmdGroup,
2214
	ULONG cCmds,
2215 2216
	OLECMD *prgCmds,
	OLECMDTEXT *pCmdText)
2217
{
2218
    IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2219
    UINT i;
2220

2221 2222
    FIXME("(%p)->(%s %d %p %p)\n",
              This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2223 2224

    if (!prgCmds)
2225
        return E_INVALIDARG;
2226 2227
    for (i = 0; i < cCmds; i++)
    {
2228
        FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2229 2230 2231
        prgCmds[i].cmdf = 0;
    }
    return OLECMDERR_E_UNKNOWNGROUP;
2232 2233
}

2234
/**********************************************************
2235
 * ISVOleCmdTarget_Exec (IOleCommandTarget)
Juergen Schmied's avatar
Juergen Schmied committed
2236 2237
 *
 * nCmdID is the OLECMDID_* enumeration
2238 2239 2240 2241 2242 2243 2244 2245 2246
 */
static HRESULT WINAPI ISVOleCmdTarget_Exec(
	IOleCommandTarget *iface,
	const GUID* pguidCmdGroup,
	DWORD nCmdID,
	DWORD nCmdexecopt,
	VARIANT* pvaIn,
	VARIANT* pvaOut)
{
2247
	IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2248

2249 2250
	FIXME("(%p)->(%s %d 0x%08x %s %p)\n",
              This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, debugstr_variant(pvaIn), pvaOut);
2251

2252 2253
	if (!pguidCmdGroup)
	    return OLECMDERR_E_UNKNOWNGROUP;
2254

2255
	if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2256
	   (nCmdID == OLECMDID_SHOWMESSAGE) &&
2257 2258 2259
	   (nCmdexecopt == 4) && pvaOut)
	   return S_OK;
	if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2260 2261 2262
	   (nCmdID == OLECMDID_SPELL) &&
	   (nCmdexecopt == OLECMDEXECOPT_DODEFAULT))
	   return S_FALSE;
2263 2264

	return OLECMDERR_E_UNKNOWNGROUP;
2265 2266
}

2267
static const IOleCommandTargetVtbl olecommandtargetvtbl =
2268 2269 2270 2271 2272 2273 2274 2275
{
	ISVOleCmdTarget_QueryInterface,
	ISVOleCmdTarget_AddRef,
	ISVOleCmdTarget_Release,
	ISVOleCmdTarget_QueryStatus,
	ISVOleCmdTarget_Exec
};

2276
/**********************************************************
2277 2278 2279
 * ISVDropTarget implementation
 */

2280
static HRESULT WINAPI ISVDropTarget_QueryInterface(IDropTarget *iface, REFIID riid, void **ppvObj)
2281
{
2282 2283
    IShellViewImpl *This = impl_from_IDropTarget(iface);
    return IShellView3_QueryInterface(&This->IShellView3_iface, riid, ppvObj);
2284 2285
}

2286
static ULONG WINAPI ISVDropTarget_AddRef(IDropTarget *iface)
2287
{
2288 2289
    IShellViewImpl *This = impl_from_IDropTarget(iface);
    return IShellView3_AddRef(&This->IShellView3_iface);
2290 2291
}

2292
static ULONG WINAPI ISVDropTarget_Release(IDropTarget *iface)
2293
{
2294 2295
    IShellViewImpl *This = impl_from_IDropTarget(iface);
    return IShellView3_Release(&This->IShellView3_iface);
2296 2297
}

2298 2299 2300 2301 2302 2303
/******************************************************************************
 * drag_notify_subitem [Internal]
 *
 * Figure out the shellfolder object, which is currently under the mouse cursor
 * and notify it via the IDropTarget interface.
 */
2304 2305 2306

#define SCROLLAREAWIDTH 20

2307 2308 2309 2310
static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
    DWORD *pdwEffect)
{
    LVHITTESTINFO htinfo;
2311
    LVITEMW lvItem;
2312 2313
    LONG lResult;
    HRESULT hr;
2314
    RECT clientRect;
2315 2316 2317 2318 2319 2320

    /* Map from global to client coordinates and query the index of the listview-item, which is 
     * currently under the mouse cursor. */
    htinfo.pt.x = pt.x;
    htinfo.pt.y = pt.y;
    htinfo.flags = LVHT_ONITEM;
2321
    ScreenToClient(This->hWndList, &htinfo.pt);
2322 2323
    lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);

2324
    /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2325
    GetClientRect(This->hWndList, &clientRect);
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345
    if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
        (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
         htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
    {
        This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
        if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
            if (htinfo.pt.x < SCROLLAREAWIDTH) 
                SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
            if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
                SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
            if (htinfo.pt.y < SCROLLAREAWIDTH)
                SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
            if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
                SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
        }
    } else {
        This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
    }
    This->ptLastMousePos = htinfo.pt;
 
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
    /* If we are still over the previous sub-item, notify it via DragOver and return. */
    if (This->pCurDropTarget && lResult == This->iDragOverItem)
    return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
  
    /* We've left the previous sub-item, notify it via DragLeave and Release it. */
    if (This->pCurDropTarget) {
        IDropTarget_DragLeave(This->pCurDropTarget);
        IDropTarget_Release(This->pCurDropTarget);
        This->pCurDropTarget = NULL;
    }
2356

2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367
    This->iDragOverItem = lResult;
    if (lResult == -1) {
        /* We are not above one of the listview's subitems. Bind to the parent folder's
         * DropTarget interface. */
        hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget, 
                                         (LPVOID*)&This->pCurDropTarget);
    } else {
        /* Query the relative PIDL of the shellfolder object represented by the currently
         * dragged over listview-item ... */
        lvItem.mask = LVIF_PARAM;
        lvItem.iItem = lResult;
2368
        lvItem.iSubItem = 0;
2369
        SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2370

2371 2372 2373
        /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
        hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
            (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2374
    }
2375

2376 2377 2378
    /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
    if (FAILED(hr)) 
        return hr;
2379

2380 2381
    /* Notify the item just entered via DragEnter. */
    return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2382 2383
}

2384 2385
static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2386
{
2387
    IShellViewImpl *This = impl_from_IDropTarget(iface);
2388

2389 2390 2391
    /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
    This->pCurDataObject = pDataObject;
    IDataObject_AddRef(pDataObject);
2392

2393
    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2394 2395
}

2396 2397
static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
    DWORD *pdwEffect)
2398
{
2399 2400 2401
    IShellViewImpl *This = impl_from_IDropTarget(iface);
    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
}
2402

2403 2404
static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface)
{
2405
    IShellViewImpl *This = impl_from_IDropTarget(iface);
2406

2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
    if (This->pCurDropTarget)
    {
        IDropTarget_DragLeave(This->pCurDropTarget);
        IDropTarget_Release(This->pCurDropTarget);
        This->pCurDropTarget = NULL;
    }

    if (This->pCurDataObject)
    {
        IDataObject_Release(This->pCurDataObject);
        This->pCurDataObject = NULL;
    }
2419 2420

    This->iDragOverItem = 0;
2421

2422
    return S_OK;
2423 2424
}

2425 2426
static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject, 
    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2427
{
2428
    IShellViewImpl *This = impl_from_IDropTarget(iface);
2429

2430 2431
    if (!This->pCurDropTarget) return DRAGDROP_E_INVALIDHWND;

2432
    IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2433

2434 2435 2436 2437 2438 2439 2440
    IDropTarget_Release(This->pCurDropTarget);
    IDataObject_Release(This->pCurDataObject);
    This->pCurDataObject = NULL;
    This->pCurDropTarget = NULL;
    This->iDragOverItem = 0;

    return S_OK;
2441 2442
}

2443
static const IDropTargetVtbl droptargetvtbl =
2444 2445 2446 2447 2448 2449 2450 2451 2452 2453
{
	ISVDropTarget_QueryInterface,
	ISVDropTarget_AddRef,
	ISVDropTarget_Release,
	ISVDropTarget_DragEnter,
	ISVDropTarget_DragOver,
	ISVDropTarget_DragLeave,
	ISVDropTarget_Drop
};

2454 2455 2456 2457
/**********************************************************
 * ISVDropSource implementation
 */

2458
static HRESULT WINAPI ISVDropSource_QueryInterface(IDropSource *iface, REFIID riid, void **ppvObj)
2459
{
2460 2461
    IShellViewImpl *This = impl_from_IDropSource(iface);
    return IShellView3_QueryInterface(&This->IShellView3_iface, riid, ppvObj);
2462 2463
}

2464
static ULONG WINAPI ISVDropSource_AddRef(IDropSource *iface)
2465
{
2466 2467
    IShellViewImpl *This = impl_from_IDropSource(iface);
    return IShellView3_AddRef(&This->IShellView3_iface);
2468 2469
}

2470
static ULONG WINAPI ISVDropSource_Release(IDropSource *iface)
2471
{
2472 2473
    IShellViewImpl *This = impl_from_IDropSource(iface);
    return IShellView3_Release(&This->IShellView3_iface);
2474
}
2475

2476 2477 2478 2479 2480
static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
	IDropSource *iface,
	BOOL fEscapePressed,
	DWORD grfKeyState)
{
2481
	IShellViewImpl *This = impl_from_IDropSource(iface);
2482 2483 2484 2485 2486 2487 2488
	TRACE("(%p)\n",This);

	if (fEscapePressed)
	  return DRAGDROP_S_CANCEL;
	else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
	  return DRAGDROP_S_DROP;
	else
2489
	  return S_OK;
2490 2491 2492 2493 2494 2495
}

static HRESULT WINAPI ISVDropSource_GiveFeedback(
	IDropSource *iface,
	DWORD dwEffect)
{
2496
	IShellViewImpl *This = impl_from_IDropSource(iface);
2497 2498 2499 2500 2501
	TRACE("(%p)\n",This);

	return DRAGDROP_S_USEDEFAULTCURSORS;
}

2502
static const IDropSourceVtbl dropsourcevtbl =
2503 2504 2505 2506 2507 2508 2509
{
	ISVDropSource_QueryInterface,
	ISVDropSource_AddRef,
	ISVDropSource_Release,
	ISVDropSource_QueryContinueDrag,
	ISVDropSource_GiveFeedback
};
2510
/**********************************************************
2511 2512 2513
 * ISVViewObject implementation
 */

2514
static HRESULT WINAPI ISVViewObject_QueryInterface(IViewObject *iface, REFIID riid, void **ppvObj)
2515
{
2516 2517
    IShellViewImpl *This = impl_from_IViewObject(iface);
    return IShellView3_QueryInterface(&This->IShellView3_iface, riid, ppvObj);
2518 2519
}

2520
static ULONG WINAPI ISVViewObject_AddRef(IViewObject *iface)
2521
{
2522 2523
    IShellViewImpl *This = impl_from_IViewObject(iface);
    return IShellView3_AddRef(&This->IShellView3_iface);
2524 2525
}

2526
static ULONG WINAPI ISVViewObject_Release(IViewObject *iface)
2527
{
2528 2529
    IShellViewImpl *This = impl_from_IViewObject(iface);
    return IShellView3_Release(&This->IShellView3_iface);
2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540
}

static HRESULT WINAPI ISVViewObject_Draw(
	IViewObject 	*iface,
	DWORD dwDrawAspect,
	LONG lindex,
	void* pvAspect,
	DVTARGETDEVICE* ptd,
	HDC hdcTargetDev,
	HDC hdcDraw,
	LPCRECTL lprcBounds,
2541
	LPCRECTL lprcWBounds,
2542
	BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2543
	ULONG_PTR dwContinue)
2544
{
2545

2546
	IShellViewImpl *This = impl_from_IViewObject(iface);
2547

2548
	FIXME("Stub: This=%p\n",This);
2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559

	return E_NOTIMPL;
}
static HRESULT WINAPI ISVViewObject_GetColorSet(
	IViewObject 	*iface,
	DWORD dwDrawAspect,
	LONG lindex,
	void *pvAspect,
	DVTARGETDEVICE* ptd,
	HDC hicTargetDevice,
	LOGPALETTE** ppColorSet)
2560
{
2561

2562
	IShellViewImpl *This = impl_from_IViewObject(iface);
2563

2564
	FIXME("Stub: This=%p\n",This);
2565 2566 2567 2568 2569 2570 2571 2572 2573

	return E_NOTIMPL;
}
static HRESULT WINAPI ISVViewObject_Freeze(
	IViewObject 	*iface,
	DWORD dwDrawAspect,
	LONG lindex,
	void* pvAspect,
	DWORD* pdwFreeze)
2574
{
2575

2576
	IShellViewImpl *This = impl_from_IViewObject(iface);
2577

2578
	FIXME("Stub: This=%p\n",This);
2579 2580 2581 2582 2583 2584

	return E_NOTIMPL;
}
static HRESULT WINAPI ISVViewObject_Unfreeze(
	IViewObject 	*iface,
	DWORD dwFreeze)
2585
{
2586

2587
	IShellViewImpl *This = impl_from_IViewObject(iface);
2588

2589
	FIXME("Stub: This=%p\n",This);
2590 2591 2592 2593 2594 2595 2596 2597

	return E_NOTIMPL;
}
static HRESULT WINAPI ISVViewObject_SetAdvise(
	IViewObject 	*iface,
	DWORD aspects,
	DWORD advf,
	IAdviseSink* pAdvSink)
2598
{
2599

2600
	IShellViewImpl *This = impl_from_IViewObject(iface);
2601

2602
	FIXME("partial stub: %p %08x %08x %p\n",
2603
              This, aspects, advf, pAdvSink);
2604

2605 2606 2607 2608 2609 2610
	/* FIXME: we set the AdviseSink, but never use it to send any advice */
	This->pAdvSink = pAdvSink;
	This->dwAspects = aspects;
	This->dwAdvf = advf;

	return S_OK;
2611
}
2612

2613 2614 2615 2616 2617
static HRESULT WINAPI ISVViewObject_GetAdvise(
	IViewObject 	*iface,
	DWORD* pAspects,
	DWORD* pAdvf,
	IAdviseSink** ppAdvSink)
2618
{
2619

2620
	IShellViewImpl *This = impl_from_IViewObject(iface);
2621

2622 2623
	TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
              This, pAspects, pAdvf, ppAdvSink);
2624

2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
	if( ppAdvSink )
	{
		IAdviseSink_AddRef( This->pAdvSink );
		*ppAdvSink = This->pAdvSink;
	}
	if( pAspects )
		*pAspects = This->dwAspects;
	if( pAdvf )
		*pAdvf = This->dwAdvf;

	return S_OK;
2636 2637 2638
}


2639
static const IViewObjectVtbl viewobjectvtbl =
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
{
	ISVViewObject_QueryInterface,
	ISVViewObject_AddRef,
	ISVViewObject_Release,
	ISVViewObject_Draw,
	ISVViewObject_GetColorSet,
	ISVViewObject_Freeze,
	ISVViewObject_Unfreeze,
	ISVViewObject_SetAdvise,
	ISVViewObject_GetAdvise
};
2651

2652 2653
/* IFolderView2 */
static HRESULT WINAPI FolderView_QueryInterface(IFolderView2 *iface, REFIID riid, void **ppvObj)
2654
{
2655
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2656
    return IShellView3_QueryInterface(&This->IShellView3_iface, riid, ppvObj);
2657 2658
}

2659
static ULONG WINAPI FolderView_AddRef(IFolderView2 *iface)
2660
{
2661
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2662
    return IShellView3_AddRef(&This->IShellView3_iface);
2663 2664
}

2665
static ULONG WINAPI FolderView_Release(IFolderView2 *iface)
2666
{
2667
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2668
    return IShellView3_Release(&This->IShellView3_iface);
2669 2670
}

2671
static HRESULT WINAPI FolderView_GetCurrentViewMode(IFolderView2 *iface, UINT *mode)
2672
{
2673
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2674
    TRACE("%p, %p.\n", This, mode);
2675 2676 2677 2678 2679 2680

    if(!mode)
        return E_INVALIDARG;

    *mode = This->FolderSettings.ViewMode;
    return S_OK;
2681 2682
}

2683
static HRESULT WINAPI FolderView_SetCurrentViewMode(IFolderView2 *iface, UINT mode)
2684
{
2685
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2686
    DWORD dwStyle;
2687 2688

    TRACE("%p, %u.\n", This, mode);
2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705

    if((mode < FVM_FIRST || mode > FVM_LAST) &&
       (mode != FVM_AUTO))
        return E_INVALIDARG;

    /* Windows before Vista uses LVM_SETVIEW and possibly
       LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
       while later versions seem to accomplish this through other
       means. */
    dwStyle = ViewModeToListStyle(mode);
    SetStyle(This, dwStyle, LVS_TYPEMASK);

    /* This will not necessarily be the actual mode set above.
       This mimics the behavior of Windows XP. */
    This->FolderSettings.ViewMode = mode;

    return S_OK;
2706 2707
}

2708
static HRESULT WINAPI FolderView_GetFolder(IFolderView2 *iface, REFIID riid, void **ppv)
2709
{
2710
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2711 2712 2713

    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);

2714
    return IShellFolder_QueryInterface(This->pSFParent, riid, ppv);
2715 2716
}

2717
static HRESULT WINAPI FolderView_Item(IFolderView2 *iface, int index, PITEMID_CHILD *ppidl)
2718
{
2719
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736
    LVITEMW item;

    TRACE("(%p)->(%d %p)\n", This, index, ppidl);

    item.mask = LVIF_PARAM;
    item.iItem = index;

    if (SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM)&item))
    {
        *ppidl = ILClone((PITEMID_CHILD)item.lParam);
        return S_OK;
    }
    else
    {
        *ppidl = 0;
        return E_INVALIDARG;
    }
2737 2738
}

2739
static HRESULT WINAPI FolderView_ItemCount(IFolderView2 *iface, UINT flags, int *items)
2740
{
2741
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2742 2743 2744 2745 2746 2747 2748 2749 2750

    TRACE("(%p)->(%u %p)\n", This, flags, items);

    if (flags != SVGIO_ALLVIEW)
        FIXME("some flags unsupported, %x\n", flags & ~SVGIO_ALLVIEW);

    *items = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0);

    return S_OK;
2751 2752
}

2753
static HRESULT WINAPI FolderView_Items(IFolderView2 *iface, UINT flags, REFIID riid, void **ppv)
2754
{
2755 2756 2757
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%u %s %p), stub\n", This, flags, debugstr_guid(riid), ppv);
    return E_NOTIMPL;
2758 2759
}

2760
static HRESULT WINAPI FolderView_GetSelectionMarkedItem(IFolderView2 *iface, int *item)
2761
{
2762
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2763 2764 2765 2766 2767 2768

    TRACE("(%p)->(%p)\n", This, item);

    *item = SendMessageW(This->hWndList, LVM_GETSELECTIONMARK, 0, 0);

    return S_OK;
2769 2770
}

2771
static HRESULT WINAPI FolderView_GetFocusedItem(IFolderView2 *iface, int *item)
2772
{
2773
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2774 2775 2776 2777 2778 2779

    TRACE("(%p)->(%p)\n", This, item);

    *item = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);

    return S_OK;
2780 2781
}

2782
static HRESULT WINAPI FolderView_GetItemPosition(IFolderView2 *iface, PCUITEMID_CHILD pidl, POINT *ppt)
2783
{
2784 2785 2786
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p), stub\n", This, pidl, ppt);
    return E_NOTIMPL;
2787 2788
}

2789
static HRESULT WINAPI FolderView_GetSpacing(IFolderView2 *iface, POINT *pt)
2790
{
2791
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806

    TRACE("(%p)->(%p)\n", This, pt);

    if (!This->hWndList) return S_FALSE;

    if (pt)
    {
        DWORD ret;
        ret = SendMessageW(This->hWndList, LVM_GETITEMSPACING, 0, 0);

        pt->x = LOWORD(ret);
        pt->y = HIWORD(ret);
    }

    return S_OK;
2807 2808
}

2809
static HRESULT WINAPI FolderView_GetDefaultSpacing(IFolderView2 *iface, POINT *pt)
2810
{
2811 2812 2813
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p), stub\n", This, pt);
    return E_NOTIMPL;
2814 2815
}

2816
static HRESULT WINAPI FolderView_GetAutoArrange(IFolderView2 *iface)
2817
{
2818 2819 2820
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p), stub\n", This);
    return E_NOTIMPL;
2821 2822
}

2823
static HRESULT WINAPI FolderView_SelectItem(IFolderView2 *iface, int item, DWORD flags)
2824
{
2825
    IShellViewImpl *This = impl_from_IFolderView2(iface);
2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852
    LVITEMW lvItem;

    TRACE("(%p)->(%d, %x)\n", This, item, flags);

    lvItem.state = 0;
    lvItem.stateMask = LVIS_SELECTED;

    if (flags & SVSI_ENSUREVISIBLE)
        SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, item, 0);

    /* all items */
    if (flags & SVSI_DESELECTOTHERS)
        SendMessageW(This->hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem);

    /* this item */
    if (flags & SVSI_SELECT)
        lvItem.state |= LVIS_SELECTED;

    if (flags & SVSI_FOCUSED)
        lvItem.stateMask |= LVIS_FOCUSED;

    SendMessageW(This->hWndList, LVM_SETITEMSTATE, item, (LPARAM)&lvItem);

    if (flags & SVSI_EDIT)
        SendMessageW(This->hWndList, LVM_EDITLABELW, item, 0);

    return S_OK;
2853 2854
}

2855
static HRESULT WINAPI FolderView_SelectAndPositionItems(IFolderView2 *iface, UINT cidl,
2856 2857
                                     PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD flags)
{
2858 2859 2860 2861 2862 2863 2864 2865 2866 2867
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%u %p %p %x), stub\n", This, cidl, apidl, apt, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetGroupBy(IFolderView2 *iface, REFPROPERTYKEY key, BOOL ascending)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %d), stub\n", This, key, ascending);
    return E_NOTIMPL;
2868 2869
}

2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030
static HRESULT WINAPI FolderView2_GetGroupBy(IFolderView2 *iface, PROPERTYKEY *pkey, BOOL *ascending)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p), stub\n", This, pkey, ascending);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetViewProperty(IFolderView2 *iface, PCUITEMID_CHILD pidl,
    REFPROPERTYKEY propkey, REFPROPVARIANT propvar)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p %p), stub\n", This, pidl, propkey, propvar);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetViewProperty(IFolderView2 *iface, PCUITEMID_CHILD pidl,
    REFPROPERTYKEY propkey, PROPVARIANT *propvar)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p %p), stub\n", This, pidl, propkey, propvar);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetTileViewProperties(IFolderView2 *iface, PCUITEMID_CHILD pidl,
    LPCWSTR prop_list)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %s), stub\n", This, pidl, debugstr_w(prop_list));
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetExtendedTileViewProperties(IFolderView2 *iface, PCUITEMID_CHILD pidl,
    LPCWSTR prop_list)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %s), stub\n", This, pidl, debugstr_w(prop_list));
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetText(IFolderView2 *iface, FVTEXTTYPE type, LPCWSTR text)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %s), stub\n", This, type, debugstr_w(text));
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetCurrentFolderFlags(IFolderView2 *iface, DWORD mask, DWORD flags)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(0x%08x 0x%08x), stub\n", This, mask, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetCurrentFolderFlags(IFolderView2 *iface, DWORD *flags)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p), stub\n", This, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetSortColumnCount(IFolderView2 *iface, int *columns)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p), stub\n", This, columns);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetSortColumns(IFolderView2 *iface, const SORTCOLUMN *columns,
    int count)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %d), stub\n", This, columns, count);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetSortColumns(IFolderView2 *iface, SORTCOLUMN *columns,
    int count)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %d), stub\n", This, columns, count);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetItem(IFolderView2 *iface, int item, REFIID riid, void **ppv)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %s %p), stub\n", This, item, debugstr_guid(riid), ppv);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetVisibleItem(IFolderView2 *iface, int start, BOOL previous,
    int *item)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %d %p), stub\n", This, start, previous, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetSelectedItem(IFolderView2 *iface, int start, int *item)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %p), stub\n", This, start, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetSelection(IFolderView2 *iface, BOOL none_implies_folder,
    IShellItemArray **array)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %p), stub\n", This, none_implies_folder, array);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetSelectionState(IFolderView2 *iface, PCUITEMID_CHILD pidl,
    DWORD *flags)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p), stub\n", This, pidl, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_InvokeVerbOnSelection(IFolderView2 *iface, LPCSTR verb)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%s), stub\n", This, debugstr_a(verb));
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetViewModeAndIconSize(IFolderView2 *iface, FOLDERVIEWMODE mode,
    int size)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%d %d), stub\n", This, mode, size);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetViewModeAndIconSize(IFolderView2 *iface, FOLDERVIEWMODE *mode,
    int *size)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p %p), stub\n", This, mode, size);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetGroupSubsetCount(IFolderView2 *iface, UINT visible_rows)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%u), stub\n", This, visible_rows);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_GetGroupSubsetCount(IFolderView2 *iface, UINT *visible_rows)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p)->(%p), stub\n", This, visible_rows);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_SetRedraw(IFolderView2 *iface, BOOL redraw)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
3031 3032 3033
    TRACE("(%p)->(%d)\n", This, redraw);
    SendMessageW(This->hWndList, WM_SETREDRAW, redraw, 0);
    return S_OK;
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093
}

static HRESULT WINAPI FolderView2_IsMoveInSameFolder(IFolderView2 *iface)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p), stub\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI FolderView2_DoRename(IFolderView2 *iface)
{
    IShellViewImpl *This = impl_from_IFolderView2(iface);
    FIXME("(%p), stub\n", This);
    return E_NOTIMPL;
}

static const IFolderView2Vtbl folderviewvtbl =
{
    FolderView_QueryInterface,
    FolderView_AddRef,
    FolderView_Release,
    FolderView_GetCurrentViewMode,
    FolderView_SetCurrentViewMode,
    FolderView_GetFolder,
    FolderView_Item,
    FolderView_ItemCount,
    FolderView_Items,
    FolderView_GetSelectionMarkedItem,
    FolderView_GetFocusedItem,
    FolderView_GetItemPosition,
    FolderView_GetSpacing,
    FolderView_GetDefaultSpacing,
    FolderView_GetAutoArrange,
    FolderView_SelectItem,
    FolderView_SelectAndPositionItems,
    FolderView2_SetGroupBy,
    FolderView2_GetGroupBy,
    FolderView2_SetViewProperty,
    FolderView2_GetViewProperty,
    FolderView2_SetTileViewProperties,
    FolderView2_SetExtendedTileViewProperties,
    FolderView2_SetText,
    FolderView2_SetCurrentFolderFlags,
    FolderView2_GetCurrentFolderFlags,
    FolderView2_GetSortColumnCount,
    FolderView2_SetSortColumns,
    FolderView2_GetSortColumns,
    FolderView2_GetItem,
    FolderView2_GetVisibleItem,
    FolderView2_GetSelectedItem,
    FolderView2_GetSelection,
    FolderView2_GetSelectionState,
    FolderView2_InvokeVerbOnSelection,
    FolderView2_SetViewModeAndIconSize,
    FolderView2_GetViewModeAndIconSize,
    FolderView2_SetGroupSubsetCount,
    FolderView2_GetGroupSubsetCount,
    FolderView2_SetRedraw,
    FolderView2_IsMoveInSameFolder,
    FolderView2_DoRename
3094
};
3095 3096

/* IShellFolderView */
3097
static HRESULT WINAPI IShellFolderView_fnQueryInterface(IShellFolderView *iface, REFIID riid, void **ppvObj)
3098 3099
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3100
    return IShellView3_QueryInterface(&This->IShellView3_iface, riid, ppvObj);
3101 3102 3103 3104 3105
}

static ULONG WINAPI IShellFolderView_fnAddRef(IShellFolderView *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3106
    return IShellView3_AddRef(&This->IShellView3_iface);
3107 3108 3109 3110 3111
}

static ULONG WINAPI IShellFolderView_fnRelease(IShellFolderView *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3112
    return IShellView3_Release(&This->IShellView3_iface);
3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138
}

static HRESULT WINAPI IShellFolderView_fnRearrange(IShellFolderView *iface, LPARAM sort)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%ld) stub\n", This, sort);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnGetArrangeParam(IShellFolderView *iface, LPARAM *sort)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, sort);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnArrangeGrid(IShellFolderView *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p) stub\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnAutoArrange(IShellFolderView *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3139 3140
    TRACE("(%p)\n", This);
    return IFolderView2_SetCurrentFolderFlags(&This->IFolderView2_iface, FWF_AUTOARRANGE, FWF_AUTOARRANGE);
3141 3142 3143 3144 3145
}

static HRESULT WINAPI IShellFolderView_fnGetAutoArrange(IShellFolderView *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3146
    TRACE("(%p)\n", This);
3147
    return IFolderView2_GetAutoArrange(&This->IFolderView2_iface);
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165
}

static HRESULT WINAPI IShellFolderView_fnAddObject(
    IShellFolderView *iface,
    PITEMID_CHILD pidl,
    UINT *item)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p %p) stub\n", This, pidl, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnGetObject(
    IShellFolderView *iface,
    PITEMID_CHILD *pidl,
    UINT item)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3166
    TRACE("(%p)->(%p %d)\n", This, pidl, item);
3167
    return IFolderView2_Item(&This->IFolderView2_iface, item, pidl);
3168 3169 3170 3171 3172 3173 3174 3175
}

static HRESULT WINAPI IShellFolderView_fnRemoveObject(
    IShellFolderView *iface,
    PITEMID_CHILD pidl,
    UINT *item)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190

    TRACE("(%p)->(%p %p)\n", This, pidl, item);

    if (pidl)
    {
        *item = LV_FindItemByPidl(This, ILFindLastID(pidl));
        SendMessageW(This->hWndList, LVM_DELETEITEM, *item, 0);
    }
    else
    {
        *item = 0;
        SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
    }

    return S_OK;
3191 3192 3193 3194 3195 3196 3197
}

static HRESULT WINAPI IShellFolderView_fnGetObjectCount(
    IShellFolderView *iface,
    UINT *count)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3198
    TRACE("(%p)->(%p)\n", This, count);
3199
    return IFolderView2_ItemCount(&This->IFolderView2_iface, SVGIO_ALLVIEW, (INT*)count);
3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237
}

static HRESULT WINAPI IShellFolderView_fnSetObjectCount(
    IShellFolderView *iface,
    UINT count,
    UINT flags)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%d %x) stub\n", This, count, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnUpdateObject(
    IShellFolderView *iface,
    PITEMID_CHILD pidl_old,
    PITEMID_CHILD pidl_new,
    UINT *item)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p %p %p) stub\n", This, pidl_old, pidl_new, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnRefreshObject(
    IShellFolderView *iface,
    PITEMID_CHILD pidl,
    UINT *item)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p %p) stub\n", This, pidl, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSetRedraw(
    IShellFolderView *iface,
    BOOL redraw)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3238
    TRACE("(%p)->(%d)\n", This, redraw);
3239
    return IFolderView2_SetRedraw(&This->IFolderView2_iface, redraw);
3240 3241 3242 3243 3244 3245 3246
}

static HRESULT WINAPI IShellFolderView_fnGetSelectedCount(
    IShellFolderView *iface,
    UINT *count)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259
    IShellItemArray *selection;
    HRESULT hr;

    TRACE("(%p)->(%p)\n", This, count);

    *count = 0;
    hr = IFolderView2_GetSelection(&This->IFolderView2_iface, FALSE, &selection);
    if (FAILED(hr))
        return hr;

    hr = IShellItemArray_GetCount(selection, count);
    IShellItemArray_Release(selection);
    return hr;
3260 3261 3262 3263 3264 3265 3266 3267
}

static HRESULT WINAPI IShellFolderView_fnGetSelectedObjects(
    IShellFolderView *iface,
    PCITEMID_CHILD **pidl,
    UINT *items)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3268 3269 3270 3271 3272 3273 3274 3275 3276 3277

    TRACE("(%p)->(%p %p)\n", This, pidl, items);

    *items = ShellView_GetSelections( This );

    if (*items)
    {
        *pidl = LocalAlloc(0, *items*sizeof(LPITEMIDLIST));
        if (!*pidl) return E_OUTOFMEMORY;

3278
        /* it's documented that caller shouldn't free PIDLs, only array itself */
3279 3280 3281 3282
        memcpy((PITEMID_CHILD*)*pidl, This->apidl, *items*sizeof(LPITEMIDLIST));
    }

    return S_OK;
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
}

static HRESULT WINAPI IShellFolderView_fnIsDropOnSource(
    IShellFolderView *iface,
    IDropTarget *drop_target)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, drop_target);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnGetDragPoint(
    IShellFolderView *iface,
    POINT *pt)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, pt);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnGetDropPoint(
    IShellFolderView *iface,
    POINT *pt)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, pt);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnMoveIcons(
    IShellFolderView *iface,
    IDataObject *obj)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3317
    TRACE("(%p)->(%p)\n", This, obj);
3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSetItemPos(
    IShellFolderView *iface,
    PCUITEMID_CHILD pidl,
    POINT *pt)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p %p) stub\n", This, pidl, pt);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnIsBkDropTarget(
    IShellFolderView *iface,
    IDropTarget *drop_target)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, drop_target);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSetClipboard(
    IShellFolderView *iface,
    BOOL move)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%d) stub\n", This, move);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSetPoints(
    IShellFolderView *iface,
    IDataObject *obj)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, obj);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnGetItemSpacing(
    IShellFolderView *iface,
    ITEMSPACING *spacing)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, spacing);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSetCallback(
    IShellFolderView    *iface,
    IShellFolderViewCB  *new_cb,
    IShellFolderViewCB **old_cb)

{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p %p) stub\n", This, new_cb, old_cb);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnSelect(
    IShellFolderView *iface,
    UINT flags)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%d) stub\n", This, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI IShellFolderView_fnQuerySupport(
    IShellFolderView *iface,
    UINT *support)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
3392 3393
    TRACE("(%p)->(%p)\n", This, support);
    return S_OK;
3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404
}

static HRESULT WINAPI IShellFolderView_fnSetAutomationObject(
    IShellFolderView *iface,
    IDispatch *disp)
{
    IShellViewImpl *This = impl_from_IShellFolderView(iface);
    FIXME("(%p)->(%p) stub\n", This, disp);
    return E_NOTIMPL;
}

3405
static const IShellFolderViewVtbl shellfolderviewvtbl =
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
{
    IShellFolderView_fnQueryInterface,
    IShellFolderView_fnAddRef,
    IShellFolderView_fnRelease,
    IShellFolderView_fnRearrange,
    IShellFolderView_fnGetArrangeParam,
    IShellFolderView_fnArrangeGrid,
    IShellFolderView_fnAutoArrange,
    IShellFolderView_fnGetAutoArrange,
    IShellFolderView_fnAddObject,
    IShellFolderView_fnGetObject,
    IShellFolderView_fnRemoveObject,
    IShellFolderView_fnGetObjectCount,
    IShellFolderView_fnSetObjectCount,
    IShellFolderView_fnUpdateObject,
    IShellFolderView_fnRefreshObject,
    IShellFolderView_fnSetRedraw,
    IShellFolderView_fnGetSelectedCount,
    IShellFolderView_fnGetSelectedObjects,
    IShellFolderView_fnIsDropOnSource,
    IShellFolderView_fnGetDragPoint,
    IShellFolderView_fnGetDropPoint,
    IShellFolderView_fnMoveIcons,
    IShellFolderView_fnSetItemPos,
    IShellFolderView_fnIsBkDropTarget,
    IShellFolderView_fnSetClipboard,
    IShellFolderView_fnSetPoints,
    IShellFolderView_fnGetItemSpacing,
    IShellFolderView_fnSetCallback,
    IShellFolderView_fnSelect,
    IShellFolderView_fnQuerySupport,
    IShellFolderView_fnSetAutomationObject
};
3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463

static HRESULT WINAPI shellfolderviewdual_QueryInterface(IShellFolderViewDual3 *iface, REFIID riid, void **ppvObj)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);

    TRACE("(%p)->(IID:%s,%p)\n", This, debugstr_guid(riid), ppvObj);

    if (IsEqualIID(riid, &IID_IShellFolderViewDual3) ||
        IsEqualIID(riid, &IID_IShellFolderViewDual2) ||
        IsEqualIID(riid, &IID_IShellFolderViewDual) ||
        IsEqualIID(riid, &IID_IDispatch) ||
        IsEqualIID(riid, &IID_IUnknown))
    {
        *ppvObj = iface;
        IShellFolderViewDual3_AddRef(iface);
        return S_OK;
    }

    WARN("unsupported interface %s\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI shellfolderviewdual_AddRef(IShellFolderViewDual3 *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3464
    return IShellView3_AddRef(&This->IShellView3_iface);
3465 3466 3467 3468 3469
}

static ULONG WINAPI shellfolderviewdual_Release(IShellFolderViewDual3 *iface)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3470
    return IShellView3_Release(&This->IShellView3_iface);
3471 3472 3473 3474 3475
}

static HRESULT WINAPI shellfolderviewdual_GetTypeInfoCount(IShellFolderViewDual3 *iface, UINT *pctinfo)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3476 3477 3478
    TRACE("%p %p\n", This, pctinfo);
    *pctinfo = 1;
    return S_OK;
3479 3480 3481 3482 3483 3484
}

static HRESULT WINAPI shellfolderviewdual_GetTypeInfo(IShellFolderViewDual3 *iface,
        UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3485 3486 3487 3488 3489 3490 3491 3492
    HRESULT hr;

    TRACE("(%p,%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);

    hr = get_typeinfo(IShellFolderViewDual3_tid, ppTInfo);
    if (SUCCEEDED(hr))
        ITypeInfo_AddRef(*ppTInfo);
    return hr;
3493 3494 3495 3496 3497 3498 3499
}

static HRESULT WINAPI shellfolderviewdual_GetIDsOfNames(
        IShellFolderViewDual3 *iface, REFIID riid, LPOLESTR *rgszNames, UINT
        cNames, LCID lcid, DISPID *rgDispId)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3500 3501 3502
    ITypeInfo *ti;
    HRESULT hr;

3503 3504
    TRACE("(%p, %s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames,
            cNames, lcid, rgDispId);
3505 3506 3507 3508 3509

    hr = get_typeinfo(IShellFolderViewDual3_tid, &ti);
    if (SUCCEEDED(hr))
        hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
    return hr;
3510 3511 3512 3513 3514 3515 3516 3517
}

static HRESULT WINAPI shellfolderviewdual_Invoke(IShellFolderViewDual3 *iface,
        DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
        DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
        UINT *puArgErr)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3518 3519 3520
    ITypeInfo *ti;
    HRESULT hr;

3521 3522 3523
    TRACE("(%p, %d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember,
            debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
            pExcepInfo, puArgErr);
3524 3525 3526 3527 3528 3529 3530

    hr = get_typeinfo(IShellFolderViewDual3_tid, &ti);
    if (SUCCEEDED(hr))
        hr = ITypeInfo_Invoke(ti, &This->IShellFolderViewDual3_iface, dispIdMember, wFlags, pDispParams,
            pVarResult, pExcepInfo, puArgErr);
    return hr;

3531 3532 3533 3534 3535 3536
}

static HRESULT WINAPI shellfolderviewdual_get_Application(IShellFolderViewDual3 *iface,
    IDispatch **disp)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
3537 3538 3539 3540 3541 3542 3543

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

    if (!disp)
        return E_INVALIDARG;

    return IShellDispatch_Constructor(NULL, &IID_IDispatch, (void**)disp);
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719
}

static HRESULT WINAPI shellfolderviewdual_get_Parent(IShellFolderViewDual3 *iface, IDispatch **disp)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, disp);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_Folder(IShellFolderViewDual3 *iface, Folder **folder)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, folder);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_SelectedItems(IShellFolderViewDual3 *iface, FolderItems **items)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, items);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_FocusedItem(IShellFolderViewDual3 *iface,
    FolderItem **item)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, item);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_SelectItem(IShellFolderViewDual3 *iface,
    VARIANT *v, int flags)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %s %x\n", This, debugstr_variant(v), flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_PopupItemMenu(IShellFolderViewDual3 *iface,
    FolderItem *item, VARIANT vx, VARIANT vy, BSTR *command)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p %s %s %p\n", This, item, debugstr_variant(&vx), debugstr_variant(&vy), command);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_Script(IShellFolderViewDual3 *iface, IDispatch **disp)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, disp);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_ViewOptions(IShellFolderViewDual3 *iface, LONG *options)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, options);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_CurrentViewMode(IShellFolderViewDual3 *iface, UINT *mode)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, mode);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_put_CurrentViewMode(IShellFolderViewDual3 *iface, UINT mode)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %u\n", This, mode);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_SelectItemRelative(IShellFolderViewDual3 *iface, int relative)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %d\n", This, relative);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_GroupBy(IShellFolderViewDual3 *iface, BSTR *groupby)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, groupby);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_put_GroupBy(IShellFolderViewDual3 *iface, BSTR groupby)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %s\n", This, debugstr_w(groupby));
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_FolderFlags(IShellFolderViewDual3 *iface, DWORD *flags)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_put_FolderFlags(IShellFolderViewDual3 *iface, DWORD flags)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p 0x%08x\n", This, flags);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_SortColumns(IShellFolderViewDual3 *iface, BSTR *sortcolumns)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, sortcolumns);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_put_SortColumns(IShellFolderViewDual3 *iface, BSTR sortcolumns)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %s\n", This, debugstr_w(sortcolumns));
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_put_IconSize(IShellFolderViewDual3 *iface, int icon_size)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %d\n", This, icon_size);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_get_IconSize(IShellFolderViewDual3 *iface, int *icon_size)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %p\n", This, icon_size);
    return E_NOTIMPL;
}

static HRESULT WINAPI shellfolderviewdual_FilterView(IShellFolderViewDual3 *iface, BSTR filter_text)
{
    IShellViewImpl *This = impl_from_IShellFolderViewDual3(iface);
    FIXME("%p %s\n", This, debugstr_w(filter_text));
    return E_NOTIMPL;
}

static const IShellFolderViewDual3Vtbl shellfolderviewdualvtbl =
{
    shellfolderviewdual_QueryInterface,
    shellfolderviewdual_AddRef,
    shellfolderviewdual_Release,
    shellfolderviewdual_GetTypeInfoCount,
    shellfolderviewdual_GetTypeInfo,
    shellfolderviewdual_GetIDsOfNames,
    shellfolderviewdual_Invoke,
    shellfolderviewdual_get_Application,
    shellfolderviewdual_get_Parent,
    shellfolderviewdual_get_Folder,
    shellfolderviewdual_SelectedItems,
    shellfolderviewdual_get_FocusedItem,
    shellfolderviewdual_SelectItem,
    shellfolderviewdual_PopupItemMenu,
    shellfolderviewdual_get_Script,
    shellfolderviewdual_get_ViewOptions,
    shellfolderviewdual_get_CurrentViewMode,
    shellfolderviewdual_put_CurrentViewMode,
    shellfolderviewdual_SelectItemRelative,
    shellfolderviewdual_get_GroupBy,
    shellfolderviewdual_put_GroupBy,
    shellfolderviewdual_get_FolderFlags,
    shellfolderviewdual_put_FolderFlags,
    shellfolderviewdual_get_SortColumns,
    shellfolderviewdual_put_SortColumns,
    shellfolderviewdual_put_IconSize,
    shellfolderviewdual_get_IconSize,
    shellfolderviewdual_FilterView
};
3720 3721 3722 3723 3724 3725 3726 3727

/**********************************************************
 *	IShellView_Constructor
 */
IShellView *IShellView_Constructor(IShellFolder *folder)
{
    IShellViewImpl *sv;

3728
    sv = heap_alloc_zero(sizeof(*sv));
3729 3730 3731 3732 3733 3734 3735 3736 3737
    if (!sv)
        return NULL;

    sv->ref = 1;
    sv->IShellView3_iface.lpVtbl = &shellviewvtbl;
    sv->IOleCommandTarget_iface.lpVtbl = &olecommandtargetvtbl;
    sv->IDropTarget_iface.lpVtbl = &droptargetvtbl;
    sv->IDropSource_iface.lpVtbl = &dropsourcevtbl;
    sv->IViewObject_iface.lpVtbl = &viewobjectvtbl;
3738
    sv->IFolderView2_iface.lpVtbl = &folderviewvtbl;
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755
    sv->IShellFolderView_iface.lpVtbl = &shellfolderviewvtbl;
    sv->IShellFolderViewDual3_iface.lpVtbl = &shellfolderviewdualvtbl;

    sv->pSFParent = folder;
    if (folder) IShellFolder_AddRef(folder);
    IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (void**)&sv->pSF2Parent);

    sv->pCurDropTarget = NULL;
    sv->pCurDataObject = NULL;
    sv->iDragOverItem = 0;
    sv->cScrollDelay = 0;
    sv->ptLastMousePos.x = 0;
    sv->ptLastMousePos.y = 0;

    TRACE("(%p)->(%p)\n", sv, folder);
    return (IShellView*)&sv->IShellView3_iface;
}
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786

/*************************************************************************
 * SHCreateShellFolderView			[SHELL32.256]
 *
 * Create a new instance of the default Shell folder view object.
 *
 * RETURNS
 *  Success: S_OK
 *  Failure: error value
 *
 * NOTES
 *  see IShellFolder::CreateViewObject
 */
HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *desc, IShellView **shellview)
{
    TRACE("(%p, %p)\n", desc, shellview);

    *shellview = NULL;

    if (!desc || desc->cbSize != sizeof(*desc))
        return E_INVALIDARG;

    TRACE("sf=%p outer=%p callback=%p\n", desc->pshf, desc->psvOuter, desc->psfvcb);

    if (!desc->pshf)
        return E_UNEXPECTED;

    *shellview = IShellView_Constructor(desc->pshf);
    if (!*shellview)
        return E_OUTOFMEMORY;

3787 3788 3789 3790 3791 3792 3793 3794
    if (desc->psfvcb)
    {
        IShellFolderView *view;
        IShellView_QueryInterface(*shellview, &IID_IShellFolderView, (void **)&view);
        IShellFolderView_SetCallback(view, desc->psfvcb, NULL);
        IShellFolderView_Release(view);
    }

3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816
    return S_OK;
}

/*************************************************************************
 * SHCreateShellFolderViewEx			[SHELL32.174]
 *
 * Create a new instance of the default Shell folder view object.
 *
 * RETURNS
 *  Success: S_OK
 *  Failure: error value
 *
 * NOTES
 *  see IShellFolder::CreateViewObject
 */
HRESULT WINAPI SHCreateShellFolderViewEx(CSFV *desc, IShellView **shellview)
{
    TRACE("(%p, %p)\n", desc, shellview);

    TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", desc->pshf, desc->pidl, desc->pfnCallback,
        desc->fvm, desc->psvOuter);

3817 3818 3819
    if (!desc->pshf)
        return E_UNEXPECTED;

3820 3821 3822 3823 3824 3825
    *shellview = IShellView_Constructor(desc->pshf);
    if (!*shellview)
        return E_OUTOFMEMORY;

    return S_OK;
}