msvcrt: Mark some fall-throughs in a switch statement.
[wine] / dlls / shell32 / shlview.c
1 /*
2  *      ShellView
3  *
4  *      Copyright 1998,1999     <juergen.schmied@debitel.net>
5  *
6  * This is the view visualizing the data provided by the shellfolder.
7  * No direct access to data from pidls should be done from here.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * 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  * the ShellBrowser
28  *
29  * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
30  *
31  * FIXME: ShellView_FillList: consider sort orders
32  *
33  * FIXME: implement the drag and drop in the old (msg-based) way
34  *
35  * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
36  * Release() ???
37  */
38
39 #include "config.h"
40 #include "wine/port.h"
41
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #define COBJMACROS
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
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 #include "wingdi.h"
58 #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 #include "pidl.h"
67 #include "shell32_main.h"
68 #include "shellfolder.h"
69
70 WINE_DEFAULT_DEBUG_CHANNEL(shell);
71
72 static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
73
74 typedef struct
75 {   BOOL    bIsAscending;
76     INT     nHeaderID;
77     INT     nLastHeaderID;
78 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
79
80 typedef struct
81 {
82         IShellView2       IShellView2_iface;
83         IOleCommandTarget IOleCommandTarget_iface;
84         IDropTarget       IDropTarget_iface;
85         IDropSource       IDropSource_iface;
86         IViewObject       IViewObject_iface;
87         IFolderView       IFolderView_iface;
88         IShellFolderView  IShellFolderView_iface;
89         LONG              ref;
90         IShellFolder*   pSFParent;
91         IShellFolder2*  pSF2Parent;
92         IShellBrowser*  pShellBrowser;
93         ICommDlgBrowser*        pCommDlgBrowser;
94         HWND            hWnd;           /* SHELLDLL_DefView */
95         HWND            hWndList;       /* ListView control */
96         HWND            hWndParent;
97         FOLDERSETTINGS  FolderSettings;
98         HMENU           hMenu;
99         UINT            uState;
100         UINT            cidl;
101         LPITEMIDLIST    *apidl;
102         LISTVIEW_SORT_INFO ListViewSortInfo;
103         ULONG                   hNotify;        /* change notification handle */
104         HANDLE          hAccel;
105         DWORD           dwAspects;
106         DWORD           dwAdvf;
107         IAdviseSink    *pAdvSink;
108         IDropTarget*    pCurDropTarget; /* The sub-item, which is currently dragged over */
109         IDataObject*    pCurDataObject; /* The dragged data-object */
110         LONG            iDragOverItem;  /* Dragged over item's index, iff pCurDropTarget != NULL */
111         UINT            cScrollDelay;   /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
112         POINT           ptLastMousePos; /* Mouse position at last DragOver call */
113 } IShellViewImpl;
114
115 static const IShellView2Vtbl svvt;
116 static const IOleCommandTargetVtbl ctvt;
117 static const IDropTargetVtbl dtvt;
118 static const IDropSourceVtbl dsvt;
119 static const IViewObjectVtbl vovt;
120 static const IFolderViewVtbl fviewvt;
121 static const IShellFolderViewVtbl shellfolderviewvt;
122
123 static inline IShellViewImpl *impl_from_IShellView2(IShellView2 *iface)
124 {
125     return CONTAINING_RECORD(iface, IShellViewImpl, IShellView2_iface);
126 }
127
128 static inline IShellViewImpl *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
129 {
130     return CONTAINING_RECORD(iface, IShellViewImpl, IOleCommandTarget_iface);
131 }
132
133 static inline IShellViewImpl *impl_from_IDropTarget(IDropTarget *iface)
134 {
135     return CONTAINING_RECORD(iface, IShellViewImpl, IDropTarget_iface);
136 }
137
138 static inline IShellViewImpl *impl_from_IDropSource(IDropSource *iface)
139 {
140     return CONTAINING_RECORD(iface, IShellViewImpl, IDropSource_iface);
141 }
142
143 static inline IShellViewImpl *impl_from_IViewObject(IViewObject *iface)
144 {
145     return CONTAINING_RECORD(iface, IShellViewImpl, IViewObject_iface);
146 }
147
148 static inline IShellViewImpl *impl_from_IFolderView(IFolderView *iface)
149 {
150     return CONTAINING_RECORD(iface, IShellViewImpl, IFolderView_iface);
151 }
152
153 static inline IShellViewImpl *impl_from_IShellFolderView(IShellFolderView *iface)
154 {
155     return CONTAINING_RECORD(iface, IShellViewImpl, IShellFolderView_iface);
156 }
157
158 /* ListView Header IDs */
159 #define LISTVIEW_COLUMN_NAME 0
160 #define LISTVIEW_COLUMN_SIZE 1
161 #define LISTVIEW_COLUMN_TYPE 2
162 #define LISTVIEW_COLUMN_TIME 3
163 #define LISTVIEW_COLUMN_ATTRIB 4
164
165 /*menu items */
166 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
167 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
168 #define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
169
170 #define ID_LISTVIEW     1
171
172 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
173
174 /*windowsx.h */
175 #define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
176 #define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
177 #define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
178
179 /*
180   Items merged into the toolbar and the filemenu
181 */
182 typedef struct
183 {  int   idCommand;
184    int   iImage;
185    int   idButtonString;
186    int   idMenuString;
187    BYTE  bState;
188    BYTE  bStyle;
189 } MYTOOLINFO, *LPMYTOOLINFO;
190
191 static const MYTOOLINFO Tools[] =
192 {
193 { FCIDM_SHVIEW_BIGICON,    0, 0, IDS_VIEW_LARGE,   TBSTATE_ENABLED, BTNS_BUTTON },
194 { FCIDM_SHVIEW_SMALLICON,  0, 0, IDS_VIEW_SMALL,   TBSTATE_ENABLED, BTNS_BUTTON },
195 { FCIDM_SHVIEW_LISTVIEW,   0, 0, IDS_VIEW_LIST,    TBSTATE_ENABLED, BTNS_BUTTON },
196 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
197 { -1, 0, 0, 0, 0, 0}
198 };
199
200 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
201
202 /**********************************************************
203  *      IShellView_Constructor
204  */
205 IShellView * IShellView_Constructor( IShellFolder * pFolder)
206 {       IShellViewImpl * sv;
207         sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
208         sv->ref=1;
209         sv->IShellView2_iface.lpVtbl = &svvt;
210         sv->IOleCommandTarget_iface.lpVtbl = &ctvt;
211         sv->IDropTarget_iface.lpVtbl = &dtvt;
212         sv->IDropSource_iface.lpVtbl = &dsvt;
213         sv->IViewObject_iface.lpVtbl = &vovt;
214         sv->IFolderView_iface.lpVtbl = &fviewvt;
215         sv->IShellFolderView_iface.lpVtbl = &shellfolderviewvt;
216
217         sv->pSFParent = pFolder;
218         if(pFolder) IShellFolder_AddRef(pFolder);
219         IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
220
221         sv->pCurDropTarget = NULL;
222         sv->pCurDataObject = NULL;
223         sv->iDragOverItem = 0;
224         sv->cScrollDelay = 0;
225         sv->ptLastMousePos.x = 0;
226         sv->ptLastMousePos.y = 0;
227
228         TRACE("(%p)->(%p)\n",sv, pFolder);
229         return (IShellView *) sv;
230 }
231
232 /**********************************************************
233  *
234  * ##### helperfunctions for communication with ICommDlgBrowser #####
235  */
236 static BOOL IsInCommDlg(IShellViewImpl * This)
237 {       return(This->pCommDlgBrowser != NULL);
238 }
239
240 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
241 {
242         HRESULT ret = S_OK;
243
244         if ( IsInCommDlg(This) )
245         {
246           TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
247           ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
248           TRACE("--0x%08x\n", ret);
249         }
250         return ret;
251 }
252
253 static HRESULT OnDefaultCommand(IShellViewImpl * This)
254 {
255         HRESULT ret = S_FALSE;
256
257         if (IsInCommDlg(This))
258         {
259           TRACE("ICommDlgBrowser::OnDefaultCommand\n");
260           ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
261           TRACE("-- returns %08x\n", ret);
262         }
263         return ret;
264 }
265
266 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
267 {
268         HRESULT ret = S_FALSE;
269
270         if (IsInCommDlg(This))
271         {
272           TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
273           ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
274           TRACE("--\n");
275         }
276         return ret;
277 }
278 /**********************************************************
279  *      set the toolbar of the filedialog buttons
280  *
281  * - activates the buttons from the shellbrowser according to
282  *   the view state
283  */
284 static void CheckToolbar(IShellViewImpl * This)
285 {
286         LRESULT result;
287
288         TRACE("\n");
289
290         if (IsInCommDlg(This))
291         {
292           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
293                 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
294           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
295                 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
296           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
297                 FCIDM_TB_SMALLICON, TRUE, &result);
298           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
299                 FCIDM_TB_REPORTVIEW, TRUE, &result);
300         }
301 }
302
303 /**********************************************************
304  *
305  * ##### helperfunctions for initializing the view #####
306  */
307 /**********************************************************
308  *      change the style of the listview control
309  */
310 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
311 {
312         DWORD tmpstyle;
313
314         TRACE("(%p)\n", This);
315
316         tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
317         SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
318 }
319
320 static DWORD ViewModeToListStyle(UINT ViewMode)
321 {
322         DWORD dwStyle;
323
324         TRACE("%d\n", ViewMode);
325
326         switch (ViewMode)
327         {
328           case FVM_ICON:        dwStyle = LVS_ICON;             break;
329           case FVM_DETAILS:     dwStyle = LVS_REPORT;           break;
330           case FVM_SMALLICON:   dwStyle = LVS_SMALLICON;        break;
331           case FVM_LIST:        dwStyle = LVS_LIST;             break;
332           default:
333           {
334                 FIXME("ViewMode %d not implemented\n", ViewMode);
335                 dwStyle = LVS_LIST;
336                 break;
337           }
338         }
339
340         return dwStyle;
341 }
342
343 /**********************************************************
344 * ShellView_CreateList()
345 *
346 * - creates the list view window
347 */
348 static BOOL ShellView_CreateList (IShellViewImpl * This)
349 {       DWORD dwStyle, dwExStyle;
350
351         TRACE("%p\n",This);
352
353         dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
354                   LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
355         dwExStyle = WS_EX_CLIENTEDGE;
356
357         dwStyle |= ViewModeToListStyle(This->FolderSettings.ViewMode);
358
359         if (This->FolderSettings.fFlags & FWF_AUTOARRANGE)      dwStyle |= LVS_AUTOARRANGE;
360         if (This->FolderSettings.fFlags & FWF_DESKTOP)
361           This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
362         if (This->FolderSettings.fFlags & FWF_SINGLESEL)        dwStyle |= LVS_SINGLESEL;
363         if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
364           dwExStyle &= ~WS_EX_CLIENTEDGE;
365
366         This->hWndList=CreateWindowExW( dwExStyle,
367                                         WC_LISTVIEWW,
368                                         NULL,
369                                         dwStyle,
370                                         0,0,0,0,
371                                         This->hWnd,
372                                         (HMENU)ID_LISTVIEW,
373                                         shell32_hInstance,
374                                         NULL);
375
376         if(!This->hWndList)
377           return FALSE;
378
379         This->ListViewSortInfo.bIsAscending = TRUE;
380         This->ListViewSortInfo.nHeaderID = -1;
381         This->ListViewSortInfo.nLastHeaderID = -1;
382
383        if (This->FolderSettings.fFlags & FWF_DESKTOP) {
384          /*
385           * FIXME: look at the registry value
386           * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
387           * and activate drop shadows if necessary
388           */
389          if (0)
390            SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
391          else
392            SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
393
394          SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
395        }
396
397         /*  UpdateShellSettings(); */
398         return TRUE;
399 }
400
401 /**********************************************************
402 * ShellView_InitList()
403 *
404 * - adds all needed columns to the shellview
405 */
406 static void ShellView_InitList(IShellViewImpl *This)
407 {
408     IShellDetails *details = NULL;
409     LVCOLUMNW lvColumn;
410     SHELLDETAILS sd;
411     WCHAR nameW[50];
412     HRESULT hr;
413     INT i;
414
415     TRACE("(%p)\n", This);
416
417     SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
418     SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
419     SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
420
421     lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
422     lvColumn.pszText = nameW;
423
424     if (!This->pSF2Parent)
425     {
426         hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IShellDetails, (void**)&details);
427         if (hr != S_OK)
428         {
429             WARN("IShellFolder2/IShellDetails not supported\n");
430             return;
431         }
432     }
433
434     for (i = 0; 1; i++)
435     {
436         if (This->pSF2Parent)
437             hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd);
438         else
439             hr = IShellDetails_GetDetailsOf(details, NULL, i, &sd);
440         if (FAILED(hr)) break;
441
442         lvColumn.fmt = sd.fmt;
443         lvColumn.cx = sd.cxChar*8; /* chars->pixel */
444         StrRetToStrNW(nameW, sizeof(nameW)/sizeof(WCHAR), &sd.str, NULL);
445         SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
446     }
447
448     if (details) IShellDetails_Release(details);
449 }
450
451 /**********************************************************
452 * ShellView_CompareItems()
453 *
454 * NOTES
455 *  internal, CALLBACK for DSA_Sort
456 */
457 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
458 {
459         int ret;
460         TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
461
462         if(!lpData) return 0;
463
464         ret =  (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
465         TRACE("ret=%i\n",ret);
466         return ret;
467 }
468
469 /*************************************************************************
470  * ShellView_ListViewCompareItems
471  *
472  * Compare Function for the Listview (FileOpen Dialog)
473  *
474  * PARAMS
475  *     lParam1       [I] the first ItemIdList to compare with
476  *     lParam2       [I] the second ItemIdList to compare with
477  *     lpData        [I] The column ID for the header Ctrl to process
478  *
479  * RETURNS
480  *     A negative value if the first item should precede the second,
481  *     a positive value if the first item should follow the second,
482  *     or zero if the two items are equivalent
483  *
484  * NOTES
485  *      FIXME: function does what ShellView_CompareItems is supposed to do.
486  *      unify it and figure out how to use the undocumented first parameter
487  *      of IShellFolder_CompareIDs to do the job this function does and
488  *      move this code to IShellFolder.
489  *      make LISTVIEW_SORT_INFO obsolete
490  *      the way this function works is only usable if we had only
491  *      filesystemfolders  (25/10/99 jsch)
492  */
493 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
494 {
495     INT nDiff=0;
496     FILETIME fd1, fd2;
497     char strName1[MAX_PATH], strName2[MAX_PATH];
498     BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
499     LPITEMIDLIST pItemIdList1 = lParam1;
500     LPITEMIDLIST pItemIdList2 = lParam2;
501     LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
502
503
504     bIsFolder1 = _ILIsFolder(pItemIdList1);
505     bIsFolder2 = _ILIsFolder(pItemIdList2);
506     bIsBothFolder = bIsFolder1 && bIsFolder2;
507
508     /* When sorting between a File and a Folder, the Folder gets sorted first */
509     if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
510     {
511         nDiff = bIsFolder1 ? -1 : 1;
512     }
513     else
514     {
515         /* Sort by Time: Folders or Files can be sorted */
516
517         if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
518         {
519             _ILGetFileDateTime(pItemIdList1, &fd1);
520             _ILGetFileDateTime(pItemIdList2, &fd2);
521             nDiff = CompareFileTime(&fd2, &fd1);
522         }
523         /* Sort by Attribute: Folder or Files can be sorted */
524         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
525         {
526             _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
527             _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
528             nDiff = lstrcmpiA(strName1, strName2);
529         }
530         /* Sort by FileName: Folder or Files can be sorted */
531         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
532         {
533             /* Sort by Text */
534             _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
535             _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
536             nDiff = lstrcmpiA(strName1, strName2);
537         }
538         /* Sort by File Size, Only valid for Files */
539         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
540         {
541             nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
542         }
543         /* Sort by File Type, Only valid for Files */
544         else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
545         {
546             /* Sort by Type */
547             _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
548             _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
549             nDiff = lstrcmpiA(strName1, strName2);
550         }
551     }
552     /*  If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
553
554     if(nDiff == 0)
555     {
556         _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
557         _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
558         nDiff = lstrcmpiA(strName1, strName2);
559     }
560
561     if(!pSortInfo->bIsAscending)
562     {
563         nDiff = -nDiff;
564     }
565
566     return nDiff;
567
568 }
569
570 /**********************************************************
571 *  LV_FindItemByPidl()
572 */
573 static int LV_FindItemByPidl(
574         IShellViewImpl * This,
575         LPCITEMIDLIST pidl)
576 {
577         LVITEMW lvItem;
578         lvItem.iSubItem = 0;
579         lvItem.mask = LVIF_PARAM;
580         for(lvItem.iItem = 0;
581                 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
582                 lvItem.iItem++)
583         {
584           LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
585           HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
586           if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
587           {
588             return lvItem.iItem;
589           }
590         }
591         return -1;
592 }
593
594 /**********************************************************
595 * LV_AddItem()
596 */
597 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
598 {
599         LVITEMW lvItem;
600
601         TRACE("(%p)(pidl=%p)\n", This, pidl);
602
603         lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;      /*set the mask*/
604         lvItem.iItem = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0); /*add the item to the end of the list*/
605         lvItem.iSubItem = 0;
606         lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl));                           /*set the item's data*/
607         lvItem.pszText = LPSTR_TEXTCALLBACKW;                   /*get text on a callback basis*/
608         lvItem.iImage = I_IMAGECALLBACK;                        /*get the image on a callback basis*/
609         return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
610 }
611
612 /**********************************************************
613 * LV_RenameItem()
614 */
615 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
616 {
617         int nItem;
618         LVITEMW lvItem;
619
620         TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
621
622         nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
623         if ( -1 != nItem )
624         {
625           lvItem.mask = LVIF_PARAM;             /* only the pidl */
626           lvItem.iItem = nItem;
627           SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
628
629           SHFree((LPITEMIDLIST)lvItem.lParam);
630           lvItem.mask = LVIF_PARAM;
631           lvItem.iItem = nItem;
632           lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew));      /* set the item's data */
633           SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
634           SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
635           return TRUE;                                  /* FIXME: better handling */
636         }
637         return FALSE;
638 }
639 /**********************************************************
640 * ShellView_FillList()
641 *
642 * - gets the objectlist from the shellfolder
643 * - sorts the list
644 * - fills the list into the view
645 */
646
647 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
648 {
649     LPITEMIDLIST pidl = ptr;
650     IShellViewImpl *This = arg;
651     /* in a commdlg This works as a filemask*/
652     if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
653     SHFree(pidl);
654     return TRUE;
655 }
656
657 static HRESULT ShellView_FillList(IShellViewImpl *This)
658 {
659     IShellFolderView *folderview = &This->IShellFolderView_iface;
660     LPENUMIDLIST pEnumIDList;
661     LPITEMIDLIST pidl;
662     DWORD fetched;
663     HRESULT hr;
664     HDPA hdpa;
665
666     TRACE("(%p)\n", This);
667
668     /* get the itemlist from the shfolder*/
669     hr = IShellFolder_EnumObjects(This->pSFParent, This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
670     if (hr != S_OK) return hr;
671
672     /* create a pointer array */
673     hdpa = DPA_Create(16);
674     if (!hdpa)
675     {
676         IEnumIDList_Release(pEnumIDList);
677         return E_OUTOFMEMORY;
678     }
679
680     /* copy the items into the array*/
681     while((S_OK == IEnumIDList_Next(pEnumIDList, 1, &pidl, &fetched)) && fetched)
682     {
683         if (DPA_InsertPtr(hdpa, DPA_GetPtrCount(hdpa), pidl) == -1)
684         {
685             SHFree(pidl);
686         }
687     }
688
689     /* sort the array */
690     DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
691
692     IShellFolderView_SetRedraw(folderview, FALSE);
693     DPA_DestroyCallback(hdpa, fill_list, This);
694     IShellFolderView_SetRedraw(folderview, TRUE);
695
696     IEnumIDList_Release(pEnumIDList);
697
698     return S_OK;
699 }
700
701 /**********************************************************
702 *  ShellView_OnCreate()
703 */
704 static LRESULT ShellView_OnCreate(IShellViewImpl *This)
705 {
706     IShellView2 *iface = &This->IShellView2_iface;
707     static const WCHAR accel_nameW[] = {'s','h','v','_','a','c','c','e','l',0};
708     IPersistFolder2 *ppf2;
709     IDropTarget* pdt;
710     HRESULT hr;
711
712     TRACE("(%p)\n", This);
713
714     if (ShellView_CreateList(This))
715     {
716         ShellView_InitList(This);
717         ShellView_FillList(This);
718     }
719
720     hr = IShellView2_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pdt);
721     if (hr == S_OK)
722     {
723         RegisterDragDrop(This->hWnd, pdt);
724         IDropTarget_Release(pdt);
725     }
726
727     /* register for receiving notifications */
728     hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
729     if (hr == S_OK)
730     {
731         LPITEMIDLIST raw_pidl;
732         SHChangeNotifyEntry ntreg;
733
734         hr = IPersistFolder2_GetCurFolder(ppf2, &raw_pidl);
735         if(SUCCEEDED(hr))
736         {
737             LPITEMIDLIST computer_pidl;
738             SHGetFolderLocation(NULL,CSIDL_DRIVES,NULL,0,&computer_pidl);
739             if(ILIsParent(computer_pidl,raw_pidl,FALSE))
740             {
741                 /* Normalize the pidl to unixfs to workaround an issue with
742                  * sending notifications on dos paths
743                  */
744                 WCHAR path[MAX_PATH];
745                 SHGetPathFromIDListW(raw_pidl,path);
746                 SHParseDisplayName(path,NULL,(LPITEMIDLIST*)&ntreg.pidl,0,NULL);
747                 SHFree(raw_pidl);
748             }
749             else
750                 ntreg.pidl = raw_pidl;
751             ntreg.fRecursive = TRUE;
752             This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNRF_InterruptLevel, SHCNE_ALLEVENTS,
753                                                    SHV_CHANGE_NOTIFY, 1, &ntreg);
754             SHFree((LPITEMIDLIST)ntreg.pidl);
755             SHFree(computer_pidl);
756         }
757         IPersistFolder2_Release(ppf2);
758     }
759
760     This->hAccel = LoadAcceleratorsW(shell32_hInstance, accel_nameW);
761
762     return S_OK;
763 }
764
765 /**********************************************************
766  *      #### Handling of the menus ####
767  */
768
769 /**********************************************************
770 * ShellView_BuildFileMenu()
771 */
772 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
773 {       WCHAR   szText[MAX_PATH];
774         MENUITEMINFOW   mii;
775         int     nTools,i;
776         HMENU   hSubMenu;
777
778         TRACE("(%p)\n",This);
779
780         hSubMenu = CreatePopupMenu();
781         if(hSubMenu)
782         { /*get the number of items in our global array*/
783           for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
784
785           /*add the menu items*/
786           for(i = 0; i < nTools; i++)
787           {
788             LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
789
790             ZeroMemory(&mii, sizeof(mii));
791             mii.cbSize = sizeof(mii);
792             mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
793
794             if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
795             {
796               mii.fType = MFT_STRING;
797               mii.fState = MFS_ENABLED;
798               mii.dwTypeData = szText;
799               mii.wID = Tools[i].idCommand;
800             }
801             else
802             {
803               mii.fType = MFT_SEPARATOR;
804             }
805             /* tack This item onto the end of the menu */
806             InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
807           }
808         }
809         TRACE("-- return (menu=%p)\n",hSubMenu);
810         return hSubMenu;
811 }
812 /**********************************************************
813 * ShellView_MergeFileMenu()
814 */
815 static void ShellView_MergeFileMenu(IShellViewImpl *This, HMENU hSubMenu)
816 {
817      TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
818
819      if (hSubMenu)
820      {
821          static const WCHAR dummyW[] = {'d','u','m','m','y','4','5',0};
822          MENUITEMINFOW mii;
823
824          /* insert This item at the beginning of the menu */
825
826          mii.cbSize = sizeof(mii);
827          mii.fMask = MIIM_ID | MIIM_TYPE;
828          mii.wID = 0;
829          mii.fType = MFT_SEPARATOR;
830          InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
831
832          mii.cbSize = sizeof(mii);
833          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
834          mii.dwTypeData = (LPWSTR)dummyW;
835          mii.fState = MFS_ENABLED;
836          mii.wID = IDM_MYFILEITEM;
837          mii.fType = MFT_STRING;
838          InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
839     }
840
841     TRACE("--\n");
842 }
843
844 /**********************************************************
845 * ShellView_MergeViewMenu()
846 */
847
848 static void ShellView_MergeViewMenu(IShellViewImpl *This, HMENU hSubMenu)
849 {
850     TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
851
852     /* add a separator at the correct position in the menu */
853     if (hSubMenu)
854     {
855         static const WCHAR menuW[] = {'M','E','N','U','_','0','0','1',0};
856         static const WCHAR viewW[] = {'V','i','e','w',0};
857         MENUITEMINFOW mii;
858
859         memset(&mii, 0, sizeof(mii));
860         mii.cbSize = sizeof(mii);
861         mii.fMask = MIIM_ID | MIIM_TYPE;
862         mii.wID = 0;
863         mii.fType = MFT_SEPARATOR;
864         InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
865
866         mii.cbSize = sizeof(mii);
867         mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
868         mii.fType = MFT_STRING;
869         mii.dwTypeData = (LPWSTR)viewW;
870         mii.hSubMenu = LoadMenuW(shell32_hInstance, menuW);
871         InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
872     }
873 }
874
875 /**********************************************************
876 *   ShellView_GetSelections()
877 *
878 * - fills the this->apidl list with the selected objects
879 *
880 * RETURNS
881 *  number of selected items
882 */
883 static UINT ShellView_GetSelections(IShellViewImpl * This)
884 {
885         LVITEMW lvItem;
886         UINT    i = 0;
887
888         SHFree(This->apidl);
889
890         This->cidl = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
891         This->apidl = SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
892
893         TRACE("selected=%i\n", This->cidl);
894
895         if(This->apidl)
896         {
897           TRACE("-- Items selected =%u\n", This->cidl);
898
899           lvItem.mask = LVIF_STATE | LVIF_PARAM;
900           lvItem.stateMask = LVIS_SELECTED;
901           lvItem.iItem = 0;
902           lvItem.iSubItem = 0;
903
904           while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
905           {
906             if(lvItem.state & LVIS_SELECTED)
907             {
908               This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
909               i++;
910               TRACE("-- selected Item found\n");
911             }
912             lvItem.iItem++;
913           }
914         }
915         return This->cidl;
916
917 }
918
919 /**********************************************************
920  *      ShellView_OpenSelectedItems()
921  */
922 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
923 {
924         static UINT CF_IDLIST = 0;
925         HRESULT hr;
926         IDataObject* selection;
927         FORMATETC fetc;
928         STGMEDIUM stgm;
929         LPIDA pIDList;
930         LPCITEMIDLIST parent_pidl;
931         WCHAR parent_path[MAX_PATH];
932         LPCWSTR parent_dir = NULL;
933         SFGAOF attribs;
934         int i;
935
936         if (0 == ShellView_GetSelections(This))
937         {
938           return S_OK;
939         }
940         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
941                                         (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
942                                         0, (LPVOID *)&selection);
943         if (FAILED(hr))
944           return hr;
945
946         if (0 == CF_IDLIST)
947         {
948           CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
949         }
950         fetc.cfFormat = CF_IDLIST;
951         fetc.ptd = NULL;
952         fetc.dwAspect = DVASPECT_CONTENT;
953         fetc.lindex = -1;
954         fetc.tymed = TYMED_HGLOBAL;
955
956         hr = IDataObject_QueryGetData(selection, &fetc);
957         if (FAILED(hr))
958           return hr;
959
960         hr = IDataObject_GetData(selection, &fetc, &stgm);
961         if (FAILED(hr))
962           return hr;
963
964         pIDList = GlobalLock(stgm.u.hGlobal);
965
966         parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
967         hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
968         if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
969             SHGetPathFromIDListW(parent_pidl, parent_path))
970         {
971           parent_dir = parent_path;
972         }
973
974         for (i = pIDList->cidl; i > 0; --i)
975         {
976           LPCITEMIDLIST pidl;
977
978           pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
979
980           attribs = SFGAO_FOLDER;
981           hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
982
983           if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
984           {
985             SHELLEXECUTEINFOW shexinfo;
986
987             shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
988             shexinfo.fMask = SEE_MASK_INVOKEIDLIST;     /* SEE_MASK_IDLIST is also possible. */
989             shexinfo.hwnd = NULL;
990             shexinfo.lpVerb = NULL;
991             shexinfo.lpFile = NULL;
992             shexinfo.lpParameters = NULL;
993             shexinfo.lpDirectory = parent_dir;
994             shexinfo.nShow = SW_NORMAL;
995             shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
996
997             ShellExecuteExW(&shexinfo);    /* Discard error/success info */
998
999             ILFree(shexinfo.lpIDList);
1000           }
1001         }
1002
1003         GlobalUnlock(stgm.u.hGlobal);
1004         ReleaseStgMedium(&stgm);
1005
1006         IDataObject_Release(selection);
1007
1008         return S_OK;
1009 }
1010
1011 /**********************************************************
1012  *      ShellView_DoContextMenu()
1013  */
1014 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
1015 {       UINT    uCommand;
1016         DWORD   wFlags;
1017         HMENU   hMenu;
1018         BOOL    fExplore = FALSE;
1019         HWND    hwndTree = 0;
1020         LPCONTEXTMENU   pContextMenu = NULL;
1021         IContextMenu2 *pCM = NULL;
1022         CMINVOKECOMMANDINFO     cmi;
1023
1024         TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
1025
1026         /* look, what's selected and create a context menu object of it*/
1027         if( ShellView_GetSelections(This) )
1028         {
1029           IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
1030                                       &IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
1031
1032           if(pContextMenu)
1033           {
1034             TRACE("-- pContextMenu\n");
1035             hMenu = CreatePopupMenu();
1036
1037             if( hMenu )
1038             {
1039               /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1040               if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
1041               {
1042                 TRACE("-- explore mode\n");
1043                 fExplore = TRUE;
1044               }
1045
1046               /* build the flags depending on what we can do with the selected item */
1047               wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
1048
1049               /* let the ContextMenu merge its items in */
1050               if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
1051               {
1052                 if (This->FolderSettings.fFlags & FWF_DESKTOP)
1053                   SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1054
1055                 if( bDefault )
1056                 {
1057                   TRACE("-- get menu default command\n");
1058                   uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1059                 }
1060                 else
1061                 {
1062                   TRACE("-- track popup\n");
1063                   uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1064                 }
1065
1066                 if(uCommand > 0)
1067                 {
1068                   TRACE("-- uCommand=%u\n", uCommand);
1069                   if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1070                   {
1071                     TRACE("-- dlg: OnDefaultCommand\n");
1072                     if (OnDefaultCommand(This) != S_OK)
1073                     {
1074                       ShellView_OpenSelectedItems(This);
1075                     }
1076                   }
1077                   else
1078                   {
1079                     TRACE("-- explore -- invoke command\n");
1080                     ZeroMemory(&cmi, sizeof(cmi));
1081                     cmi.cbSize = sizeof(cmi);
1082                     cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1083                     cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1084                     IContextMenu_InvokeCommand(pContextMenu, &cmi);
1085                   }
1086                 }
1087                 DestroyMenu(hMenu);
1088               }
1089             }
1090             if (pContextMenu)
1091               IContextMenu_Release(pContextMenu);
1092           }
1093         }
1094         else    /* background context menu */
1095         {
1096           hMenu = CreatePopupMenu();
1097
1098           pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1099           IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1100
1101           uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1102           DestroyMenu(hMenu);
1103
1104           TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1105
1106           ZeroMemory(&cmi, sizeof(cmi));
1107           cmi.cbSize = sizeof(cmi);
1108           cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1109           cmi.hwnd = This->hWndParent;
1110           IContextMenu2_InvokeCommand(pCM, &cmi);
1111
1112           IContextMenu2_Release(pCM);
1113         }
1114 }
1115
1116 /**********************************************************
1117  *      ##### message handling #####
1118  */
1119
1120 /**********************************************************
1121 *  ShellView_OnSize()
1122 */
1123 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1124 {
1125         TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1126
1127         /*resize the ListView to fit our window*/
1128         if(This->hWndList)
1129         {
1130           MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1131         }
1132
1133         return S_OK;
1134 }
1135 /**********************************************************
1136 * ShellView_OnDeactivate()
1137 *
1138 * NOTES
1139 *  internal
1140 */
1141 static void ShellView_OnDeactivate(IShellViewImpl * This)
1142 {
1143         TRACE("%p\n",This);
1144
1145         if(This->uState != SVUIA_DEACTIVATE)
1146         {
1147           if(This->hMenu)
1148           {
1149             IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1150             IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1151             DestroyMenu(This->hMenu);
1152             This->hMenu = 0;
1153           }
1154
1155           This->uState = SVUIA_DEACTIVATE;
1156         }
1157 }
1158
1159 /**********************************************************
1160 * ShellView_OnActivate()
1161 */
1162 static LRESULT ShellView_OnActivate(IShellViewImpl *This, UINT uState)
1163 {
1164     OLEMENUGROUPWIDTHS   omw = { {0, 0, 0, 0, 0, 0} };
1165     MENUITEMINFOW mii;
1166
1167     TRACE("(%p) uState=%x\n",This,uState);
1168
1169     /* don't do anything if the state isn't really changing */
1170     if (This->uState == uState) return S_OK;
1171
1172     ShellView_OnDeactivate(This);
1173
1174     /* only do This if we are active */
1175     if (uState != SVUIA_DEACTIVATE)
1176     {
1177         /* merge the menus */
1178         This->hMenu = CreateMenu();
1179
1180         if (This->hMenu)
1181         {
1182             static const WCHAR dummyW[] = {'d','u','m','m','y',' ','3','1',0};
1183
1184             IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1185             TRACE("-- after fnInsertMenusSB\n");
1186
1187             mii.cbSize = sizeof(mii);
1188             mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1189             mii.fType = MFT_STRING;
1190             mii.fState = MFS_ENABLED;
1191             mii.wID = 0;
1192             mii.hSubMenu = ShellView_BuildFileMenu(This);
1193             mii.hbmpChecked = NULL;
1194             mii.hbmpUnchecked = NULL;
1195             mii.dwItemData = 0;
1196             /* build the top level menu get the menu item's text */
1197             mii.dwTypeData = (LPWSTR)dummyW;
1198             mii.cch = 0;
1199             mii.hbmpItem = NULL;
1200
1201             /* insert our menu into the menu bar */
1202             if (mii.hSubMenu)
1203                 InsertMenuItemW(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1204
1205             /* get the view menu so we can merge with it */
1206             memset(&mii, 0, sizeof(mii));
1207             mii.cbSize = sizeof(mii);
1208             mii.fMask = MIIM_SUBMENU;
1209
1210             if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1211                 ShellView_MergeViewMenu(This, mii.hSubMenu);
1212
1213             /* add the items that should only be added if we have the focus */
1214             if (SVUIA_ACTIVATE_FOCUS == uState)
1215             {
1216                 /* get the file menu so we can merge with it */
1217                 memset(&mii, 0, sizeof(mii));
1218                 mii.cbSize = sizeof(mii);
1219                 mii.fMask = MIIM_SUBMENU;
1220
1221                 if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1222                     ShellView_MergeFileMenu(This, mii.hSubMenu);
1223             }
1224
1225             TRACE("-- before fnSetMenuSB\n");
1226             IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1227         }
1228     }
1229     This->uState = uState;
1230     TRACE("--\n");
1231     return S_OK;
1232 }
1233
1234 /**********************************************************
1235 *  ShellView_OnSetFocus()
1236 *
1237 */
1238 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1239 {
1240         TRACE("%p\n",This);
1241
1242         /* Tell the browser one of our windows has received the focus. This
1243         should always be done before merging menus (OnActivate merges the
1244         menus) if one of our windows has the focus.*/
1245
1246         IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1247         ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1248
1249         /* Set the focus to the listview */
1250         SetFocus(This->hWndList);
1251
1252         /* Notify the ICommDlgBrowser interface */
1253         OnStateChange(This,CDBOSC_SETFOCUS);
1254
1255         return 0;
1256 }
1257
1258 /**********************************************************
1259 * ShellView_OnKillFocus()
1260 */
1261 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1262 {
1263         TRACE("(%p) stub\n",This);
1264
1265         ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1266         /* Notify the ICommDlgBrowser */
1267         OnStateChange(This,CDBOSC_KILLFOCUS);
1268
1269         return 0;
1270 }
1271
1272 /**********************************************************
1273 * ShellView_OnCommand()
1274 *
1275 * NOTES
1276 *       the CmdIDs are the ones from the context menu
1277 */
1278 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1279 {
1280         TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1281
1282         switch(dwCmdID)
1283         {
1284           case FCIDM_SHVIEW_SMALLICON:
1285             This->FolderSettings.ViewMode = FVM_SMALLICON;
1286             SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1287             CheckToolbar(This);
1288             break;
1289
1290           case FCIDM_SHVIEW_BIGICON:
1291             This->FolderSettings.ViewMode = FVM_ICON;
1292             SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1293             CheckToolbar(This);
1294             break;
1295
1296           case FCIDM_SHVIEW_LISTVIEW:
1297             This->FolderSettings.ViewMode = FVM_LIST;
1298             SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1299             CheckToolbar(This);
1300             break;
1301
1302           case FCIDM_SHVIEW_REPORTVIEW:
1303             This->FolderSettings.ViewMode = FVM_DETAILS;
1304             SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1305             CheckToolbar(This);
1306             break;
1307
1308           /* the menu IDs for sorting are 0x30... see shell32.rc */
1309           case 0x30:
1310           case 0x31:
1311           case 0x32:
1312           case 0x33:
1313             This->ListViewSortInfo.nHeaderID = dwCmdID - 0x30;
1314             This->ListViewSortInfo.bIsAscending = TRUE;
1315             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1316             SendMessageW(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1317             break;
1318
1319           default:
1320             TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1321         }
1322         return 0;
1323 }
1324
1325 /**********************************************************
1326 * ShellView_OnNotify()
1327 */
1328
1329 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1330 {       LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1331         NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1332         LPITEMIDLIST pidl;
1333
1334         TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1335
1336         switch(lpnmh->code)
1337         {
1338           case NM_SETFOCUS:
1339             TRACE("-- NM_SETFOCUS %p\n",This);
1340             ShellView_OnSetFocus(This);
1341             break;
1342
1343           case NM_KILLFOCUS:
1344             TRACE("-- NM_KILLFOCUS %p\n",This);
1345             ShellView_OnDeactivate(This);
1346             /* Notify the ICommDlgBrowser interface */
1347             OnStateChange(This,CDBOSC_KILLFOCUS);
1348             break;
1349
1350           case NM_CUSTOMDRAW:
1351             TRACE("-- NM_CUSTOMDRAW %p\n",This);
1352             return CDRF_DODEFAULT;
1353
1354           case NM_RELEASEDCAPTURE:
1355             TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1356             break;
1357
1358           case NM_CLICK:
1359             TRACE("-- NM_CLICK %p\n",This);
1360             break;
1361
1362           case NM_RCLICK:
1363             TRACE("-- NM_RCLICK %p\n",This);
1364             break;          
1365
1366           case NM_DBLCLK:
1367             TRACE("-- NM_DBLCLK %p\n",This);
1368             if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1369             break;
1370
1371           case NM_RETURN:
1372             TRACE("-- NM_RETURN %p\n",This);
1373             if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1374             break;
1375
1376           case HDN_ENDTRACKW:
1377             TRACE("-- HDN_ENDTRACKW %p\n",This);
1378             /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1379             nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1380             break;
1381
1382           case LVN_DELETEITEM:
1383             TRACE("-- LVN_DELETEITEM %p\n",This);
1384             SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
1385             break;
1386
1387           case LVN_DELETEALLITEMS:
1388             TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1389             return FALSE;
1390
1391           case LVN_INSERTITEM:
1392             TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1393             break;
1394
1395           case LVN_ITEMACTIVATE:
1396             TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1397             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1398             break;
1399
1400           case LVN_COLUMNCLICK:
1401             This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1402             if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1403             {
1404               This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1405             }
1406             else
1407             {
1408               This->ListViewSortInfo.bIsAscending = TRUE;
1409             }
1410             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1411
1412             SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1413             break;
1414
1415           case LVN_GETDISPINFOA:
1416           case LVN_GETDISPINFOW:
1417             TRACE("-- LVN_GETDISPINFO %p\n",This);
1418             pidl = (LPITEMIDLIST)lpdi->item.lParam;
1419
1420             if(lpdi->item.mask & LVIF_TEXT)     /* text requested */
1421             {
1422               static WCHAR emptyW[] = { 0 };
1423               SHELLDETAILS sd;
1424               HRESULT hr;
1425
1426               if (This->pSF2Parent)
1427               {
1428                 hr = IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1429               }
1430               else
1431               {
1432                 IShellDetails *details;
1433
1434                 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IShellDetails, (void**)&details);
1435                 if (hr == S_OK)
1436                 {
1437                   hr = IShellDetails_GetDetailsOf(details, pidl, lpdi->item.iSubItem, &sd);
1438                   IShellDetails_Release(details);
1439                 }
1440                 else
1441                   WARN("IShellFolder2/IShellDetails not supported\n");
1442               }
1443
1444               if (hr != S_OK)
1445               {
1446                   /* set to empty on failure */
1447                   sd.str.uType = STRRET_WSTR;
1448                   sd.str.u.pOleStr = emptyW;
1449               }
1450
1451               if (lpnmh->code == LVN_GETDISPINFOW)
1452               {
1453                   StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1454                   TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1455               }
1456               else
1457               {
1458                   /* LVN_GETDISPINFOA - shouldn't happen */
1459                   NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1460                   StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1461                   TRACE("-- text=%s\n", lpdiA->item.pszText);
1462               }
1463             }
1464
1465             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
1466             {
1467               lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1468             }
1469             break;
1470
1471           case LVN_ITEMCHANGED:
1472             TRACE("-- LVN_ITEMCHANGED %p\n",This);
1473             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1474             break;
1475
1476           case LVN_BEGINDRAG:
1477           case LVN_BEGINRDRAG:
1478             TRACE("-- LVN_BEGINDRAG\n");
1479
1480             if (ShellView_GetSelections(This))
1481             {
1482               IDataObject * pda;
1483               DWORD dwAttributes = SFGAO_CANLINK;
1484               DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1485
1486               if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1487               {
1488                   IDropSource *pds = &This->IDropSource_iface; /* own DropSource interface */
1489
1490                   if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1491                   {
1492                     if (dwAttributes & SFGAO_CANLINK)
1493                     {
1494                       dwEffect |= DROPEFFECT_LINK;
1495                     }
1496                   }
1497
1498                   if (pds)
1499                   {
1500                     DWORD dwEffect2;
1501                     DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1502                   }
1503                   IDataObject_Release(pda);
1504               }
1505             }
1506             break;
1507
1508           case LVN_BEGINLABELEDITW:
1509             {
1510               DWORD dwAttr = SFGAO_CANRENAME;
1511               pidl = (LPITEMIDLIST)lpdi->item.lParam;
1512
1513               TRACE("-- LVN_BEGINLABELEDITW %p\n",This);
1514
1515               IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1516               if (SFGAO_CANRENAME & dwAttr)
1517               {
1518                 return FALSE;
1519               }
1520               return TRUE;
1521             }
1522
1523           case LVN_ENDLABELEDITW:
1524             {
1525               TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1526               if (lpdi->item.pszText)
1527               {
1528                 HRESULT hr;
1529                 LVITEMW lvItem;
1530
1531                 lvItem.iItem = lpdi->item.iItem;
1532                 lvItem.iSubItem = 0;
1533                 lvItem.mask = LVIF_PARAM;
1534                 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1535
1536                 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1537                 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1538
1539                 if(SUCCEEDED(hr) && pidl)
1540                 {
1541                   lvItem.mask = LVIF_PARAM;
1542                   lvItem.lParam = (LPARAM)pidl;
1543                   SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1544                   return TRUE;
1545                 }
1546               }
1547               return FALSE;
1548             }
1549
1550           case LVN_KEYDOWN:
1551             {
1552               LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1553
1554               /* initiate a rename of the selected file or directory */
1555               switch (plvKeyDown->wVKey)
1556               {
1557               case VK_F2:
1558                 {
1559                   INT i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
1560
1561                   if (i == 1)
1562                   {
1563                     /* get selected item */
1564                     i = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, MAKELPARAM (LVNI_SELECTED, 0));
1565
1566                     SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1567                     SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1568                   }
1569                 }
1570                 break;
1571               case VK_DELETE:
1572                 {
1573                   UINT i, count;
1574                   int item_index;
1575                   LVITEMW item;
1576                   LPITEMIDLIST* pItems;
1577                   ISFHelper *psfhlp;
1578                   HRESULT hr;
1579
1580                   hr = IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (void**)&psfhlp);
1581                   if (hr != S_OK) return 0;
1582
1583                   if(!(count = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0)))
1584                   {
1585                     ISFHelper_Release(psfhlp);
1586                     return 0;
1587                   }
1588
1589                   /* allocate memory for the pidl array */
1590                   pItems = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST) * count);
1591
1592                   /* retrieve all selected items */
1593                   i = 0;
1594                   item_index = -1;
1595
1596                   while (count > i)
1597                   {
1598                     /* get selected item */
1599                     item_index = SendMessageW(This->hWndList, LVM_GETNEXTITEM, item_index,
1600                                               MAKELPARAM (LVNI_SELECTED, 0));
1601                     item.iItem = item_index;
1602                     item.mask = LVIF_PARAM;
1603                     SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM)&item);
1604
1605                     /* get item pidl */
1606                     pItems[i] = (LPITEMIDLIST)item.lParam;
1607
1608                     i++;
1609                   }
1610
1611                   /* perform the item deletion */
1612                   ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1613                   ISFHelper_Release(psfhlp);
1614
1615                   /* free pidl array memory */
1616                   HeapFree(GetProcessHeap(), 0, pItems);
1617                 }
1618                 break;
1619
1620               case VK_F5:
1621                 /* Initiate a refresh */
1622                 IShellView_Refresh((IShellView*)This);
1623                 break;
1624
1625               case VK_BACK:
1626                 {
1627                   LPSHELLBROWSER lpSb;
1628                   if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1629                   {
1630                     IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1631                   }
1632                 }
1633                 break;
1634
1635               default:
1636                 FIXME("LVN_KEYDOWN key=0x%08x\n", plvKeyDown->wVKey);
1637               }
1638             }
1639             break;
1640
1641           default:
1642             TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1643             break;
1644         }
1645         return 0;
1646 }
1647
1648 /**********************************************************
1649 * ShellView_OnChange()
1650 */
1651
1652 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST *pidls, LONG event)
1653 {
1654     BOOL ret = TRUE;
1655
1656     TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pidls[0], pidls[1], event);
1657
1658     switch (event)
1659     {
1660         case SHCNE_MKDIR:
1661         case SHCNE_CREATE:
1662             LV_AddItem(This, pidls[0]);
1663             break;
1664         case SHCNE_RMDIR:
1665         case SHCNE_DELETE:
1666         {
1667             INT i = LV_FindItemByPidl(This, ILFindLastID(pidls[0]));
1668             ret = SendMessageW(This->hWndList, LVM_DELETEITEM, i, 0);
1669             break;
1670         }
1671         case SHCNE_RENAMEFOLDER:
1672         case SHCNE_RENAMEITEM:
1673             LV_RenameItem(This, pidls[0], pidls[1]);
1674             break;
1675         case SHCNE_UPDATEITEM:
1676             break;
1677     }
1678     return ret;
1679 }
1680 /**********************************************************
1681 *  ShellView_WndProc
1682 */
1683
1684 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1685 {
1686         IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1687         LPCREATESTRUCTW lpcs;
1688
1689         TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1690
1691         switch (uMessage)
1692         {
1693           case WM_NCCREATE:
1694             lpcs = (LPCREATESTRUCTW)lParam;
1695             pThis = lpcs->lpCreateParams;
1696             SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1697             pThis->hWnd = hWnd;        /*set the window handle*/
1698             break;
1699
1700           case WM_SIZE:         return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1701           case WM_SETFOCUS:     return ShellView_OnSetFocus(pThis);
1702           case WM_KILLFOCUS:    return ShellView_OnKillFocus(pThis);
1703           case WM_CREATE:       return ShellView_OnCreate(pThis);
1704           case WM_ACTIVATE:     return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1705           case WM_NOTIFY:       return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1706           case WM_COMMAND:      return ShellView_OnCommand(pThis,
1707                                         GET_WM_COMMAND_ID(wParam, lParam),
1708                                         GET_WM_COMMAND_CMD(wParam, lParam),
1709                                         GET_WM_COMMAND_HWND(wParam, lParam));
1710           case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1711
1712           case WM_CONTEXTMENU:  ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1713                                 return 0;
1714
1715           case WM_SHOWWINDOW:   UpdateWindow(pThis->hWndList);
1716                                 break;
1717
1718           case WM_GETDLGCODE:   return SendMessageW(pThis->hWndList, uMessage, 0, 0);
1719
1720           case WM_DESTROY:      
1721                                 RevokeDragDrop(pThis->hWnd);
1722                                 SHChangeNotifyDeregister(pThis->hNotify);
1723                                 break;
1724
1725           case WM_ERASEBKGND:
1726             if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1727                 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1728               return 1;
1729             break;
1730         }
1731
1732         return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1733 }
1734 /**********************************************************
1735 *
1736 *
1737 *  The INTERFACE of the IShellView object
1738 *
1739 *
1740 **********************************************************
1741 *  IShellView_QueryInterface
1742 */
1743 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView2 *iface, REFIID riid, void **ppvObj)
1744 {
1745         IShellViewImpl *This = impl_from_IShellView2(iface);
1746
1747         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1748
1749         *ppvObj = NULL;
1750
1751         if(IsEqualIID(riid, &IID_IUnknown))
1752         {
1753           *ppvObj = This;
1754         }
1755         else if(IsEqualIID(riid, &IID_IShellView))
1756         {
1757           *ppvObj = This;
1758         }
1759         else if(IsEqualIID(riid, &IID_IShellView2))
1760         {
1761           *ppvObj = This;
1762         }
1763         else if(IsEqualIID(riid, &IID_IShellFolderView))
1764         {
1765           *ppvObj = &This->IShellFolderView_iface;
1766         }
1767         else if(IsEqualIID(riid, &IID_IFolderView))
1768         {
1769           *ppvObj = &This->IFolderView_iface;
1770         }
1771         else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1772         {
1773           *ppvObj = &This->IOleCommandTarget_iface;
1774         }
1775         else if(IsEqualIID(riid, &IID_IDropTarget))
1776         {
1777           *ppvObj = &This->IDropTarget_iface;
1778         }
1779         else if(IsEqualIID(riid, &IID_IDropSource))
1780         {
1781           *ppvObj = &This->IDropSource_iface;
1782         }
1783         else if(IsEqualIID(riid, &IID_IViewObject))
1784         {
1785           *ppvObj = &This->IViewObject_iface;
1786         }
1787
1788         if(*ppvObj)
1789         {
1790           IUnknown_AddRef( (IUnknown*)*ppvObj );
1791           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1792           return S_OK;
1793         }
1794         TRACE("-- Interface: E_NOINTERFACE\n");
1795         return E_NOINTERFACE;
1796 }
1797
1798 /**********************************************************
1799 *  IShellView_AddRef
1800 */
1801 static ULONG WINAPI IShellView_fnAddRef(IShellView2 *iface)
1802 {
1803         IShellViewImpl *This = impl_from_IShellView2(iface);
1804         ULONG refCount = InterlockedIncrement(&This->ref);
1805
1806         TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1807
1808         return refCount;
1809 }
1810 /**********************************************************
1811 *  IShellView_Release
1812 */
1813 static ULONG WINAPI IShellView_fnRelease(IShellView2 *iface)
1814 {
1815         IShellViewImpl *This = impl_from_IShellView2(iface);
1816         ULONG refCount = InterlockedDecrement(&This->ref);
1817
1818         TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1819
1820         if (!refCount)
1821         {
1822           TRACE(" destroying IShellView(%p)\n",This);
1823
1824           DestroyWindow(This->hWndList);
1825
1826           if(This->pSFParent)
1827             IShellFolder_Release(This->pSFParent);
1828
1829           if(This->pSF2Parent)
1830             IShellFolder2_Release(This->pSF2Parent);
1831
1832           SHFree(This->apidl);
1833
1834           if(This->pAdvSink)
1835             IAdviseSink_Release(This->pAdvSink);
1836
1837           HeapFree(GetProcessHeap(),0,This);
1838         }
1839         return refCount;
1840 }
1841
1842 /**********************************************************
1843 *  ShellView_GetWindow
1844 */
1845 static HRESULT WINAPI IShellView_fnGetWindow(IShellView2 *iface, HWND *phWnd)
1846 {
1847         IShellViewImpl *This = impl_from_IShellView2(iface);
1848
1849         TRACE("(%p)\n",This);
1850
1851         *phWnd = This->hWnd;
1852
1853         return S_OK;
1854 }
1855
1856 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView2 *iface, BOOL mode)
1857 {
1858     IShellViewImpl *This = impl_from_IShellView2(iface);
1859     TRACE("(%p)->(%d)\n", This, mode);
1860     return E_NOTIMPL;
1861 }
1862
1863 /**********************************************************
1864 * IShellView_TranslateAccelerator
1865 *
1866 * FIXME:
1867 *  use the accel functions
1868 */
1869 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView2 * iface,LPMSG lpmsg)
1870 {
1871 #if 0
1872         IShellViewImpl *This = (IShellViewImpl *)iface;
1873
1874         FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1875 #endif
1876
1877         if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1878         {
1879           TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1880         }
1881         return S_FALSE; /* not handled */
1882 }
1883
1884 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView2 *iface, BOOL fEnable)
1885 {
1886         IShellViewImpl *This = impl_from_IShellView2(iface);
1887
1888         FIXME("(%p) stub\n",This);
1889
1890         return E_NOTIMPL;
1891 }
1892
1893 static HRESULT WINAPI IShellView_fnUIActivate(IShellView2 *iface, UINT uState)
1894 {
1895         IShellViewImpl *This = impl_from_IShellView2(iface);
1896
1897 /*
1898         CHAR    szName[MAX_PATH];
1899 */
1900         LRESULT lResult;
1901         int     nPartArray[1] = {-1};
1902
1903         TRACE("(%p)->(state=%x) stub\n",This, uState);
1904
1905         /*don't do anything if the state isn't really changing*/
1906         if(This->uState == uState)
1907         {
1908           return S_OK;
1909         }
1910
1911         /*OnActivate handles the menu merging and internal state*/
1912         ShellView_OnActivate(This, uState);
1913
1914         /*only do This if we are active*/
1915         if(uState != SVUIA_DEACTIVATE)
1916         {
1917
1918 /*
1919           GetFolderPath is not a method of IShellFolder
1920           IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1921 */
1922           /* set the number of parts */
1923           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1924                                                         (LPARAM)nPartArray, &lResult);
1925
1926           /* set the text for the parts */
1927 /*
1928           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1929                                                         0, (LPARAM)szName, &lResult);
1930 */
1931         }
1932
1933         return S_OK;
1934 }
1935
1936 static HRESULT WINAPI IShellView_fnRefresh(IShellView2 *iface)
1937 {
1938         IShellViewImpl *This = impl_from_IShellView2(iface);
1939
1940         TRACE("(%p)\n", This);
1941
1942         SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1943         ShellView_FillList(This);
1944
1945         return S_OK;
1946 }
1947
1948 static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView2 *iface, IShellView *lpPrevView,
1949         LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
1950 {
1951     HRESULT hr;
1952     SV2CVW2_PARAMS view_params;
1953     view_params.cbSize = sizeof(view_params);
1954     view_params.psvPrev = lpPrevView;
1955     view_params.pfs = lpfs;
1956     view_params.psbOwner = psb;
1957     view_params.prcView = prcView;
1958     view_params.pvid = NULL;
1959     view_params.hwndView = 0;
1960
1961     TRACE("(%p) Forwarding to CreateViewWindow2\n", iface);
1962
1963     hr = IShellView2_CreateViewWindow2(iface, &view_params);
1964     *phWnd = view_params.hwndView;
1965
1966     return hr;
1967 }
1968
1969 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView2 *iface)
1970 {
1971         IShellViewImpl *This = impl_from_IShellView2(iface);
1972
1973         TRACE("(%p)\n",This);
1974
1975         /*Make absolutely sure all our UI is cleaned up.*/
1976         IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1977
1978         if(This->hMenu)
1979         {
1980           DestroyMenu(This->hMenu);
1981         }
1982
1983         DestroyWindow(This->hWnd);
1984         if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1985         if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1986
1987
1988         return S_OK;
1989 }
1990
1991 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView2 *iface, LPFOLDERSETTINGS lpfs)
1992 {
1993         IShellViewImpl *This = impl_from_IShellView2(iface);
1994
1995         TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1996                 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1997
1998         if (!lpfs) return E_INVALIDARG;
1999
2000         *lpfs = This->FolderSettings;
2001         return NOERROR;
2002 }
2003
2004 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView2 *iface, DWORD dwReserved,
2005                 LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2006 {
2007         IShellViewImpl *This = impl_from_IShellView2(iface);
2008
2009         FIXME("(%p) stub\n",This);
2010
2011         return E_NOTIMPL;
2012 }
2013
2014 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView2 *iface)
2015 {
2016         IShellViewImpl *This = impl_from_IShellView2(iface);
2017
2018         FIXME("(%p) stub\n",This);
2019
2020         return S_OK;
2021 }
2022
2023 static HRESULT WINAPI IShellView_fnSelectItem(IShellView2 *iface, LPCITEMIDLIST pidl, UINT flags)
2024 {
2025     IShellViewImpl *This = impl_from_IShellView2(iface);
2026     IFolderView *view = &This->IFolderView_iface;
2027     int i;
2028
2029     TRACE("(%p)->(pidl=%p, 0x%08x)\n",This, pidl, flags);
2030
2031     i = LV_FindItemByPidl(This, pidl);
2032     if (i == -1) return S_OK;
2033
2034     return IFolderView_SelectItem(view, i, flags);
2035 }
2036
2037 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView2 *iface, UINT uItem, REFIID riid,
2038         void **ppvOut)
2039 {
2040     IShellViewImpl *This = impl_from_IShellView2(iface);
2041     HRESULT hr = E_NOINTERFACE;
2042
2043     TRACE("(%p)->(0x%08x, %s, %p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2044
2045     *ppvOut = NULL;
2046
2047     switch(uItem)
2048     {
2049     case SVGIO_BACKGROUND:
2050
2051         if (IsEqualIID(&IID_IContextMenu, riid))
2052         {
2053             *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2054             hr = S_OK;
2055         }
2056         else
2057             FIXME("unsupported interface requested %s\n", debugstr_guid(riid));
2058
2059         break;
2060
2061     case SVGIO_SELECTION:
2062         ShellView_GetSelections(This);
2063         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2064         break;
2065
2066     default:
2067         FIXME("unimplemented for uItem = 0x%08x\n", uItem);
2068     }
2069     TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2070
2071     return hr;
2072 }
2073
2074 static HRESULT WINAPI IShellView2_fnGetView(IShellView2* iface, SHELLVIEWID *view_guid, ULONG view_type)
2075 {
2076     FIXME("(%p)->(view_guid %s, view_type %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2077     return E_NOTIMPL;
2078 }
2079
2080 static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView2 *iface,
2081         LPSV2CVW2_PARAMS view_params)
2082 {
2083     IShellViewImpl *This = impl_from_IShellView2(iface);
2084     WNDCLASSW wc;
2085     HRESULT hr;
2086     HWND wnd;
2087
2088     TRACE("(%p)->(view_params %p)\n", iface, view_params);
2089
2090     if (view_params->cbSize != sizeof(*view_params))
2091     {
2092         FIXME("Got unexpected cbSize %#x\n", view_params->cbSize);
2093         return E_FAIL;
2094     }
2095
2096     TRACE("-- psvPrev %p, pfs %p, psbOwner %p, prcView %p\n",
2097             view_params->psvPrev, view_params->pfs, view_params->psbOwner, view_params->prcView);
2098     TRACE("-- vmode %#x, flags %#x, view %s\n", view_params->pfs->ViewMode, view_params->pfs->fFlags, wine_dbgstr_rect(view_params->prcView));
2099
2100     if (!view_params->psbOwner) return E_UNEXPECTED;
2101
2102     /* Set up the member variables */
2103     This->pShellBrowser = view_params->psbOwner;
2104     This->FolderSettings = *view_params->pfs;
2105
2106     if (view_params->pvid)
2107     {
2108         if (IsEqualGUID(view_params->pvid, &VID_LargeIcons))
2109             This->FolderSettings.ViewMode = FVM_ICON;
2110         else if (IsEqualGUID(view_params->pvid, &VID_SmallIcons))
2111             This->FolderSettings.ViewMode = FVM_SMALLICON;
2112         else if (IsEqualGUID(view_params->pvid, &VID_List))
2113             This->FolderSettings.ViewMode = FVM_LIST;
2114         else if (IsEqualGUID(view_params->pvid, &VID_Details))
2115             This->FolderSettings.ViewMode = FVM_DETAILS;
2116         else if (IsEqualGUID(view_params->pvid, &VID_Thumbnails))
2117             This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2118         else if (IsEqualGUID(view_params->pvid, &VID_Tile))
2119             This->FolderSettings.ViewMode = FVM_TILE;
2120         else if (IsEqualGUID(view_params->pvid, &VID_ThumbStrip))
2121             This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
2122         else
2123             FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_params->pvid));
2124     }
2125
2126     /* Get our parent window */
2127     IShellBrowser_AddRef(This->pShellBrowser);
2128     IShellBrowser_GetWindow(This->pShellBrowser, &This->hWndParent);
2129
2130     /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2131     This->pCommDlgBrowser = NULL;
2132     hr = IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser);
2133     if (hr == S_OK)
2134         TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);
2135
2136     /* If our window class has not been registered, then do so */
2137     if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
2138     {
2139         wc.style            = CS_HREDRAW | CS_VREDRAW;
2140         wc.lpfnWndProc      = ShellView_WndProc;
2141         wc.cbClsExtra       = 0;
2142         wc.cbWndExtra       = 0;
2143         wc.hInstance        = shell32_hInstance;
2144         wc.hIcon            = 0;
2145         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
2146         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
2147         wc.lpszMenuName     = NULL;
2148         wc.lpszClassName    = SV_CLASS_NAME;
2149
2150         if (!RegisterClassW(&wc)) return E_FAIL;
2151     }
2152
2153     wnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP,
2154             view_params->prcView->left, view_params->prcView->top,
2155             view_params->prcView->right - view_params->prcView->left,
2156             view_params->prcView->bottom - view_params->prcView->top,
2157             This->hWndParent, 0, shell32_hInstance, This);
2158
2159     CheckToolbar(This);
2160
2161     if (!wnd)
2162     {
2163         IShellBrowser_Release(This->pShellBrowser);
2164         return E_FAIL;
2165     }
2166
2167     SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2168     UpdateWindow(wnd);
2169
2170     view_params->hwndView = wnd;
2171
2172     return S_OK;
2173 }
2174
2175 static HRESULT WINAPI IShellView2_fnHandleRename(IShellView2* iface, LPCITEMIDLIST new_pidl)
2176 {
2177     FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
2178     return E_NOTIMPL;
2179 }
2180
2181 static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(IShellView2 *iface, LPCITEMIDLIST item,
2182         UINT flags, POINT *point)
2183 {
2184     IShellViewImpl *This = impl_from_IShellView2(iface);
2185     IFolderView *view;
2186     HRESULT hr;
2187
2188     TRACE("(%p)->(item %p, flags %#x, point %p)\n", This, item, flags, point);
2189
2190     hr = IShellView2_QueryInterface(iface, &IID_IFolderView, (void**)&view);
2191     if (hr == S_OK)
2192     {
2193         hr = IFolderView_SelectAndPositionItems(view, 1, &item, point, flags);
2194         IFolderView_Release(view);
2195     }
2196
2197     return hr;
2198 }
2199
2200 static const IShellView2Vtbl svvt =
2201 {
2202         IShellView_fnQueryInterface,
2203         IShellView_fnAddRef,
2204         IShellView_fnRelease,
2205         IShellView_fnGetWindow,
2206         IShellView_fnContextSensitiveHelp,
2207         IShellView_fnTranslateAccelerator,
2208         IShellView_fnEnableModeless,
2209         IShellView_fnUIActivate,
2210         IShellView_fnRefresh,
2211         IShellView_fnCreateViewWindow,
2212         IShellView_fnDestroyViewWindow,
2213         IShellView_fnGetCurrentInfo,
2214         IShellView_fnAddPropertySheetPages,
2215         IShellView_fnSaveViewState,
2216         IShellView_fnSelectItem,
2217         IShellView_fnGetItemObject,
2218         IShellView2_fnGetView,
2219         IShellView2_fnCreateViewWindow2,
2220         IShellView2_fnHandleRename,
2221         IShellView2_fnSelectAndPositionItem,
2222 };
2223
2224
2225 /**********************************************************
2226  * ISVOleCmdTarget_QueryInterface (IUnknown)
2227  */
2228 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2229         IOleCommandTarget *     iface,
2230         REFIID                  iid,
2231         LPVOID*                 ppvObj)
2232 {
2233         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2234
2235         return IShellView2_QueryInterface(&This->IShellView2_iface, iid, ppvObj);
2236 }
2237
2238 /**********************************************************
2239  * ISVOleCmdTarget_AddRef (IUnknown)
2240  */
2241 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2242         IOleCommandTarget *     iface)
2243 {
2244         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2245
2246         return IShellView2_AddRef(&This->IShellView2_iface);
2247 }
2248
2249 /**********************************************************
2250  * ISVOleCmdTarget_Release (IUnknown)
2251  */
2252 static ULONG WINAPI ISVOleCmdTarget_Release(
2253         IOleCommandTarget *     iface)
2254 {
2255         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2256
2257         return IShellView2_Release(&This->IShellView2_iface);
2258 }
2259
2260 /**********************************************************
2261  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2262  */
2263 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2264         IOleCommandTarget *iface,
2265         const GUID *pguidCmdGroup,
2266         ULONG cCmds,
2267         OLECMD *prgCmds,
2268         OLECMDTEXT *pCmdText)
2269 {
2270     IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2271     UINT i;
2272
2273     FIXME("(%p)->(%s %d %p %p)\n",
2274               This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2275
2276     if (!prgCmds)
2277         return E_INVALIDARG;
2278     for (i = 0; i < cCmds; i++)
2279     {
2280         FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2281         prgCmds[i].cmdf = 0;
2282     }
2283     return OLECMDERR_E_UNKNOWNGROUP;
2284 }
2285
2286 /**********************************************************
2287  * ISVOleCmdTarget_Exec (IOleCommandTarget)
2288  *
2289  * nCmdID is the OLECMDID_* enumeration
2290  */
2291 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2292         IOleCommandTarget *iface,
2293         const GUID* pguidCmdGroup,
2294         DWORD nCmdID,
2295         DWORD nCmdexecopt,
2296         VARIANT* pvaIn,
2297         VARIANT* pvaOut)
2298 {
2299         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2300
2301         FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2302               This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2303
2304         if (!pguidCmdGroup)
2305             return OLECMDERR_E_UNKNOWNGROUP;
2306         if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2307            (nCmdID == 0x29) &&
2308            (nCmdexecopt == 4) && pvaOut)
2309            return S_OK;
2310         if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2311            (nCmdID == 9) &&
2312            (nCmdexecopt == 0))
2313            return 1;
2314
2315         return OLECMDERR_E_UNKNOWNGROUP;
2316 }
2317
2318 static const IOleCommandTargetVtbl ctvt =
2319 {
2320         ISVOleCmdTarget_QueryInterface,
2321         ISVOleCmdTarget_AddRef,
2322         ISVOleCmdTarget_Release,
2323         ISVOleCmdTarget_QueryStatus,
2324         ISVOleCmdTarget_Exec
2325 };
2326
2327 /**********************************************************
2328  * ISVDropTarget implementation
2329  */
2330
2331 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2332         IDropTarget *iface,
2333         REFIID riid,
2334         LPVOID *ppvObj)
2335 {
2336         IShellViewImpl *This = impl_from_IDropTarget(iface);
2337
2338         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2339
2340         return IShellView2_QueryInterface(&This->IShellView2_iface, riid, ppvObj);
2341 }
2342
2343 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2344 {
2345         IShellViewImpl *This = impl_from_IDropTarget(iface);
2346
2347         TRACE("(%p)->(count=%u)\n",This,This->ref);
2348
2349         return IShellView2_AddRef(&This->IShellView2_iface);
2350 }
2351
2352 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2353 {
2354         IShellViewImpl *This = impl_from_IDropTarget(iface);
2355
2356         TRACE("(%p)->(count=%u)\n",This,This->ref);
2357
2358         return IShellView2_Release(&This->IShellView2_iface);
2359 }
2360
2361 /******************************************************************************
2362  * drag_notify_subitem [Internal]
2363  *
2364  * Figure out the shellfolder object, which is currently under the mouse cursor
2365  * and notify it via the IDropTarget interface.
2366  */
2367
2368 #define SCROLLAREAWIDTH 20
2369
2370 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2371     DWORD *pdwEffect)
2372 {
2373     LVHITTESTINFO htinfo;
2374     LVITEMW lvItem;
2375     LONG lResult;
2376     HRESULT hr;
2377     RECT clientRect;
2378
2379     /* Map from global to client coordinates and query the index of the listview-item, which is 
2380      * currently under the mouse cursor. */
2381     htinfo.pt.x = pt.x;
2382     htinfo.pt.y = pt.y;
2383     htinfo.flags = LVHT_ONITEM;
2384     ScreenToClient(This->hWndList, &htinfo.pt);
2385     lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2386
2387     /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2388     GetClientRect(This->hWndList, &clientRect);
2389     if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2390         (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2391          htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2392     {
2393         This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2394         if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2395             if (htinfo.pt.x < SCROLLAREAWIDTH) 
2396                 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2397             if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2398                 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2399             if (htinfo.pt.y < SCROLLAREAWIDTH)
2400                 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2401             if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2402                 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2403         }
2404     } else {
2405         This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2406     }
2407     This->ptLastMousePos = htinfo.pt;
2408  
2409     /* If we are still over the previous sub-item, notify it via DragOver and return. */
2410     if (This->pCurDropTarget && lResult == This->iDragOverItem)
2411     return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2412   
2413     /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2414     if (This->pCurDropTarget) {
2415         IDropTarget_DragLeave(This->pCurDropTarget);
2416         IDropTarget_Release(This->pCurDropTarget);
2417         This->pCurDropTarget = NULL;
2418     }
2419
2420     This->iDragOverItem = lResult;
2421     if (lResult == -1) {
2422         /* We are not above one of the listview's subitems. Bind to the parent folder's
2423          * DropTarget interface. */
2424         hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget, 
2425                                          (LPVOID*)&This->pCurDropTarget);
2426     } else {
2427         /* Query the relative PIDL of the shellfolder object represented by the currently
2428          * dragged over listview-item ... */
2429         lvItem.mask = LVIF_PARAM;
2430         lvItem.iItem = lResult;
2431         lvItem.iSubItem = 0;
2432         SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2433
2434         /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2435         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2436             (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2437     }
2438
2439     /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2440     if (FAILED(hr)) 
2441         return hr;
2442
2443     /* Notify the item just entered via DragEnter. */
2444     return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2445 }
2446
2447 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2448     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2449 {
2450     IShellViewImpl *This = impl_from_IDropTarget(iface);
2451
2452     /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2453     This->pCurDataObject = pDataObject;
2454     IDataObject_AddRef(pDataObject);
2455
2456     return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2457 }
2458
2459 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2460     DWORD *pdwEffect)
2461 {
2462     IShellViewImpl *This = impl_from_IDropTarget(iface);
2463     return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2464 }
2465
2466 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface)
2467 {
2468     IShellViewImpl *This = impl_from_IDropTarget(iface);
2469
2470     if (This->pCurDropTarget)
2471     {
2472         IDropTarget_DragLeave(This->pCurDropTarget);
2473         IDropTarget_Release(This->pCurDropTarget);
2474         This->pCurDropTarget = NULL;
2475     }
2476
2477     if (This->pCurDataObject)
2478     {
2479         IDataObject_Release(This->pCurDataObject);
2480         This->pCurDataObject = NULL;
2481     }
2482
2483     This->iDragOverItem = 0;
2484
2485     return S_OK;
2486 }
2487
2488 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject, 
2489     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2490 {
2491     IShellViewImpl *This = impl_from_IDropTarget(iface);
2492
2493     IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2494
2495     IDropTarget_Release(This->pCurDropTarget);
2496     IDataObject_Release(This->pCurDataObject);
2497     This->pCurDataObject = NULL;
2498     This->pCurDropTarget = NULL;
2499     This->iDragOverItem = 0;
2500
2501     return S_OK;
2502 }
2503
2504 static const IDropTargetVtbl dtvt =
2505 {
2506         ISVDropTarget_QueryInterface,
2507         ISVDropTarget_AddRef,
2508         ISVDropTarget_Release,
2509         ISVDropTarget_DragEnter,
2510         ISVDropTarget_DragOver,
2511         ISVDropTarget_DragLeave,
2512         ISVDropTarget_Drop
2513 };
2514
2515 /**********************************************************
2516  * ISVDropSource implementation
2517  */
2518
2519 static HRESULT WINAPI ISVDropSource_QueryInterface(
2520         IDropSource *iface,
2521         REFIID riid,
2522         LPVOID *ppvObj)
2523 {
2524         IShellViewImpl *This = impl_from_IDropSource(iface);
2525
2526         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2527
2528         return IShellView2_QueryInterface(&This->IShellView2_iface, riid, ppvObj);
2529 }
2530
2531 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2532 {
2533         IShellViewImpl *This = impl_from_IDropSource(iface);
2534
2535         TRACE("(%p)->(count=%u)\n",This,This->ref);
2536
2537         return IShellView2_AddRef(&This->IShellView2_iface);
2538 }
2539
2540 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2541 {
2542         IShellViewImpl *This = impl_from_IDropSource(iface);
2543
2544         TRACE("(%p)->(count=%u)\n",This,This->ref);
2545
2546         return IShellView2_Release(&This->IShellView2_iface);
2547 }
2548
2549 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2550         IDropSource *iface,
2551         BOOL fEscapePressed,
2552         DWORD grfKeyState)
2553 {
2554         IShellViewImpl *This = impl_from_IDropSource(iface);
2555         TRACE("(%p)\n",This);
2556
2557         if (fEscapePressed)
2558           return DRAGDROP_S_CANCEL;
2559         else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2560           return DRAGDROP_S_DROP;
2561         else
2562           return NOERROR;
2563 }
2564
2565 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2566         IDropSource *iface,
2567         DWORD dwEffect)
2568 {
2569         IShellViewImpl *This = impl_from_IDropSource(iface);
2570         TRACE("(%p)\n",This);
2571
2572         return DRAGDROP_S_USEDEFAULTCURSORS;
2573 }
2574
2575 static const IDropSourceVtbl dsvt =
2576 {
2577         ISVDropSource_QueryInterface,
2578         ISVDropSource_AddRef,
2579         ISVDropSource_Release,
2580         ISVDropSource_QueryContinueDrag,
2581         ISVDropSource_GiveFeedback
2582 };
2583 /**********************************************************
2584  * ISVViewObject implementation
2585  */
2586
2587 static HRESULT WINAPI ISVViewObject_QueryInterface(
2588         IViewObject *iface,
2589         REFIID riid,
2590         LPVOID *ppvObj)
2591 {
2592         IShellViewImpl *This = impl_from_IViewObject(iface);
2593
2594         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2595
2596         return IShellView2_QueryInterface(&This->IShellView2_iface, riid, ppvObj);
2597 }
2598
2599 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2600 {
2601         IShellViewImpl *This = impl_from_IViewObject(iface);
2602
2603         TRACE("(%p)->(count=%u)\n",This,This->ref);
2604
2605         return IShellView2_AddRef(&This->IShellView2_iface);
2606 }
2607
2608 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2609 {
2610         IShellViewImpl *This = impl_from_IViewObject(iface);
2611
2612         TRACE("(%p)->(count=%u)\n",This,This->ref);
2613
2614         return IShellView2_Release(&This->IShellView2_iface);
2615 }
2616
2617 static HRESULT WINAPI ISVViewObject_Draw(
2618         IViewObject     *iface,
2619         DWORD dwDrawAspect,
2620         LONG lindex,
2621         void* pvAspect,
2622         DVTARGETDEVICE* ptd,
2623         HDC hdcTargetDev,
2624         HDC hdcDraw,
2625         LPCRECTL lprcBounds,
2626         LPCRECTL lprcWBounds,
2627         BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2628         ULONG_PTR dwContinue)
2629 {
2630
2631         IShellViewImpl *This = impl_from_IViewObject(iface);
2632
2633         FIXME("Stub: This=%p\n",This);
2634
2635         return E_NOTIMPL;
2636 }
2637 static HRESULT WINAPI ISVViewObject_GetColorSet(
2638         IViewObject     *iface,
2639         DWORD dwDrawAspect,
2640         LONG lindex,
2641         void *pvAspect,
2642         DVTARGETDEVICE* ptd,
2643         HDC hicTargetDevice,
2644         LOGPALETTE** ppColorSet)
2645 {
2646
2647         IShellViewImpl *This = impl_from_IViewObject(iface);
2648
2649         FIXME("Stub: This=%p\n",This);
2650
2651         return E_NOTIMPL;
2652 }
2653 static HRESULT WINAPI ISVViewObject_Freeze(
2654         IViewObject     *iface,
2655         DWORD dwDrawAspect,
2656         LONG lindex,
2657         void* pvAspect,
2658         DWORD* pdwFreeze)
2659 {
2660
2661         IShellViewImpl *This = impl_from_IViewObject(iface);
2662
2663         FIXME("Stub: This=%p\n",This);
2664
2665         return E_NOTIMPL;
2666 }
2667 static HRESULT WINAPI ISVViewObject_Unfreeze(
2668         IViewObject     *iface,
2669         DWORD dwFreeze)
2670 {
2671
2672         IShellViewImpl *This = impl_from_IViewObject(iface);
2673
2674         FIXME("Stub: This=%p\n",This);
2675
2676         return E_NOTIMPL;
2677 }
2678 static HRESULT WINAPI ISVViewObject_SetAdvise(
2679         IViewObject     *iface,
2680         DWORD aspects,
2681         DWORD advf,
2682         IAdviseSink* pAdvSink)
2683 {
2684
2685         IShellViewImpl *This = impl_from_IViewObject(iface);
2686
2687         FIXME("partial stub: %p %08x %08x %p\n",
2688               This, aspects, advf, pAdvSink);
2689
2690         /* FIXME: we set the AdviseSink, but never use it to send any advice */
2691         This->pAdvSink = pAdvSink;
2692         This->dwAspects = aspects;
2693         This->dwAdvf = advf;
2694
2695         return S_OK;
2696 }
2697
2698 static HRESULT WINAPI ISVViewObject_GetAdvise(
2699         IViewObject     *iface,
2700         DWORD* pAspects,
2701         DWORD* pAdvf,
2702         IAdviseSink** ppAdvSink)
2703 {
2704
2705         IShellViewImpl *This = impl_from_IViewObject(iface);
2706
2707         TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2708               This, pAspects, pAdvf, ppAdvSink);
2709
2710         if( ppAdvSink )
2711         {
2712                 IAdviseSink_AddRef( This->pAdvSink );
2713                 *ppAdvSink = This->pAdvSink;
2714         }
2715         if( pAspects )
2716                 *pAspects = This->dwAspects;
2717         if( pAdvf )
2718                 *pAdvf = This->dwAdvf;
2719
2720         return S_OK;
2721 }
2722
2723
2724 static const IViewObjectVtbl vovt =
2725 {
2726         ISVViewObject_QueryInterface,
2727         ISVViewObject_AddRef,
2728         ISVViewObject_Release,
2729         ISVViewObject_Draw,
2730         ISVViewObject_GetColorSet,
2731         ISVViewObject_Freeze,
2732         ISVViewObject_Unfreeze,
2733         ISVViewObject_SetAdvise,
2734         ISVViewObject_GetAdvise
2735 };
2736
2737 /* IFolderView */
2738 static HRESULT WINAPI IFView_QueryInterface(
2739         IFolderView *iface,
2740         REFIID riid,
2741         LPVOID *ppvObj)
2742 {
2743         IShellViewImpl *This = impl_from_IFolderView(iface);
2744         TRACE("(%p)->(IID:%s,%p)\n", This, debugstr_guid(riid), ppvObj);
2745         return IShellView2_QueryInterface(&This->IShellView2_iface, riid, ppvObj);
2746 }
2747
2748 static ULONG WINAPI IFView_AddRef( IFolderView *iface)
2749 {
2750         IShellViewImpl *This = impl_from_IFolderView(iface);
2751         TRACE("(%p)->(count=%u)\n", This, This->ref);
2752         return IShellView2_AddRef(&This->IShellView2_iface);
2753 }
2754
2755 static ULONG WINAPI IFView_Release( IFolderView *iface)
2756 {
2757         IShellViewImpl *This = impl_from_IFolderView(iface);
2758         TRACE("(%p)->(count=%u)\n", This, This->ref);
2759         return IShellView2_Release(&This->IShellView2_iface);
2760 }
2761
2762 static HRESULT WINAPI IFView_GetCurrentViewMode(IFolderView *iface, UINT *mode)
2763 {
2764     IShellViewImpl *This = impl_from_IFolderView(iface);
2765     TRACE("(%p)->(%p), stub\n", This, mode);
2766
2767     if(!mode)
2768         return E_INVALIDARG;
2769
2770     *mode = This->FolderSettings.ViewMode;
2771     return S_OK;
2772 }
2773
2774 static HRESULT WINAPI IFView_SetCurrentViewMode(IFolderView *iface, UINT mode)
2775 {
2776     IShellViewImpl *This = impl_from_IFolderView(iface);
2777     DWORD dwStyle;
2778     TRACE("(%p)->(%u), stub\n", This, mode);
2779
2780     if((mode < FVM_FIRST || mode > FVM_LAST) &&
2781        (mode != FVM_AUTO))
2782         return E_INVALIDARG;
2783
2784     /* Windows before Vista uses LVM_SETVIEW and possibly
2785        LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2786        while later versions seem to accomplish this through other
2787        means. */
2788     dwStyle = ViewModeToListStyle(mode);
2789     SetStyle(This, dwStyle, LVS_TYPEMASK);
2790
2791     /* This will not necessarily be the actual mode set above.
2792        This mimics the behavior of Windows XP. */
2793     This->FolderSettings.ViewMode = mode;
2794
2795     return S_OK;
2796 }
2797
2798 static HRESULT WINAPI IFView_GetFolder(IFolderView *iface, REFIID riid, void **ppv)
2799 {
2800     IShellViewImpl *This = impl_from_IFolderView(iface);
2801
2802     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
2803
2804     if (!ppv) return E_POINTER;
2805
2806     if (IsEqualIID(riid, &IID_IShellFolder))
2807     {
2808         *ppv = This->pSFParent;
2809         return S_OK;
2810     }
2811
2812     return E_NOINTERFACE;
2813 }
2814
2815 static HRESULT WINAPI IFView_Item(IFolderView *iface, int index, PITEMID_CHILD *ppidl)
2816 {
2817     IShellViewImpl *This = impl_from_IFolderView(iface);
2818     LVITEMW item;
2819
2820     TRACE("(%p)->(%d %p)\n", This, index, ppidl);
2821
2822     item.mask = LVIF_PARAM;
2823     item.iItem = index;
2824
2825     if (SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM)&item))
2826     {
2827         *ppidl = ILClone((PITEMID_CHILD)item.lParam);
2828         return S_OK;
2829     }
2830     else
2831     {
2832         *ppidl = 0;
2833         return E_INVALIDARG;
2834     }
2835 }
2836
2837 static HRESULT WINAPI IFView_ItemCount(IFolderView *iface, UINT flags, int *items)
2838 {
2839     IShellViewImpl *This = impl_from_IFolderView(iface);
2840
2841     TRACE("(%p)->(%u %p)\n", This, flags, items);
2842
2843     if (flags != SVGIO_ALLVIEW)
2844         FIXME("some flags unsupported, %x\n", flags & ~SVGIO_ALLVIEW);
2845
2846     *items = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0);
2847
2848     return S_OK;
2849 }
2850
2851 static HRESULT WINAPI IFView_Items(IFolderView *iface, UINT flags, REFIID riid, void **ppv)
2852 {
2853         IShellViewImpl *This = impl_from_IFolderView(iface);
2854         FIXME("(%p)->(%u %s %p), stub\n", This, flags, debugstr_guid(riid), ppv);
2855         return E_NOTIMPL;
2856 }
2857
2858 static HRESULT WINAPI IFView_GetSelectionMarkedItem(IFolderView *iface, int *item)
2859 {
2860     IShellViewImpl *This = impl_from_IFolderView(iface);
2861
2862     TRACE("(%p)->(%p)\n", This, item);
2863
2864     *item = SendMessageW(This->hWndList, LVM_GETSELECTIONMARK, 0, 0);
2865
2866     return S_OK;
2867 }
2868
2869 static HRESULT WINAPI IFView_GetFocusedItem(IFolderView *iface, int *item)
2870 {
2871     IShellViewImpl *This = impl_from_IFolderView(iface);
2872
2873     TRACE("(%p)->(%p)\n", This, item);
2874
2875     *item = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
2876
2877     return S_OK;
2878 }
2879
2880 static HRESULT WINAPI IFView_GetItemPosition(IFolderView *iface, PCUITEMID_CHILD pidl, POINT *ppt)
2881 {
2882         IShellViewImpl *This = impl_from_IFolderView(iface);
2883         FIXME("(%p)->(%p %p), stub\n", This, pidl, ppt);
2884         return E_NOTIMPL;
2885 }
2886
2887 static HRESULT WINAPI IFView_GetSpacing(IFolderView *iface, POINT *pt)
2888 {
2889     IShellViewImpl *This = impl_from_IFolderView(iface);
2890
2891     TRACE("(%p)->(%p)\n", This, pt);
2892
2893     if (!This->hWndList) return S_FALSE;
2894
2895     if (pt)
2896     {
2897         DWORD ret;
2898         ret = SendMessageW(This->hWndList, LVM_GETITEMSPACING, 0, 0);
2899
2900         pt->x = LOWORD(ret);
2901         pt->y = HIWORD(ret);
2902     }
2903
2904     return S_OK;
2905 }
2906
2907 static HRESULT WINAPI IFView_GetDefaultSpacing(IFolderView *iface, POINT *pt)
2908 {
2909         IShellViewImpl *This = impl_from_IFolderView(iface);
2910         FIXME("(%p)->(%p), stub\n", This, pt);
2911         return E_NOTIMPL;
2912 }
2913
2914 static HRESULT WINAPI IFView_GetAutoArrange(IFolderView *iface)
2915 {
2916         IShellViewImpl *This = impl_from_IFolderView(iface);
2917         FIXME("(%p), stub\n", This);
2918         return E_NOTIMPL;
2919 }
2920
2921 static HRESULT WINAPI IFView_SelectItem(IFolderView *iface, int item, DWORD flags)
2922 {
2923     IShellViewImpl *This = impl_from_IFolderView(iface);
2924     LVITEMW lvItem;
2925
2926     TRACE("(%p)->(%d, %x)\n", This, item, flags);
2927
2928     lvItem.state = 0;
2929     lvItem.stateMask = LVIS_SELECTED;
2930
2931     if (flags & SVSI_ENSUREVISIBLE)
2932         SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, item, 0);
2933
2934     /* all items */
2935     if (flags & SVSI_DESELECTOTHERS)
2936         SendMessageW(This->hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem);
2937
2938     /* this item */
2939     if (flags & SVSI_SELECT)
2940         lvItem.state |= LVIS_SELECTED;
2941
2942     if (flags & SVSI_FOCUSED)
2943         lvItem.stateMask |= LVIS_FOCUSED;
2944
2945     SendMessageW(This->hWndList, LVM_SETITEMSTATE, item, (LPARAM)&lvItem);
2946
2947     if (flags & SVSI_EDIT)
2948         SendMessageW(This->hWndList, LVM_EDITLABELW, item, 0);
2949
2950     return S_OK;
2951 }
2952
2953 static HRESULT WINAPI IFView_SelectAndPositionItems(IFolderView *iface, UINT cidl,
2954                                      PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD flags)
2955 {
2956         IShellViewImpl *This = impl_from_IFolderView(iface);
2957         FIXME("(%p)->(%u %p %p %x), stub\n", This, cidl, apidl, apt, flags);
2958         return E_NOTIMPL;
2959 }
2960
2961 static const IFolderViewVtbl fviewvt =
2962 {
2963         IFView_QueryInterface,
2964         IFView_AddRef,
2965         IFView_Release,
2966         IFView_GetCurrentViewMode,
2967         IFView_SetCurrentViewMode,
2968         IFView_GetFolder,
2969         IFView_Item,
2970         IFView_ItemCount,
2971         IFView_Items,
2972         IFView_GetSelectionMarkedItem,
2973         IFView_GetFocusedItem,
2974         IFView_GetItemPosition,
2975         IFView_GetSpacing,
2976         IFView_GetDefaultSpacing,
2977         IFView_GetAutoArrange,
2978         IFView_SelectItem,
2979         IFView_SelectAndPositionItems
2980 };
2981
2982 /* IShellFolderView */
2983 static HRESULT WINAPI IShellFolderView_fnQueryInterface(
2984     IShellFolderView *iface,
2985     REFIID riid,
2986     LPVOID *ppvObj)
2987 {
2988     IShellViewImpl *This = impl_from_IShellFolderView(iface);
2989     TRACE("(%p)->(IID:%s,%p)\n", This, debugstr_guid(riid), ppvObj);
2990     return IShellView2_QueryInterface(&This->IShellView2_iface, riid, ppvObj);
2991 }
2992
2993 static ULONG WINAPI IShellFolderView_fnAddRef(IShellFolderView *iface)
2994 {
2995     IShellViewImpl *This = impl_from_IShellFolderView(iface);
2996     TRACE("(%p)->(count=%u)\n", This, This->ref);
2997     return IShellView2_AddRef(&This->IShellView2_iface);
2998 }
2999
3000 static ULONG WINAPI IShellFolderView_fnRelease(IShellFolderView *iface)
3001 {
3002     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3003     TRACE("(%p)->(count=%u)\n", This, This->ref);
3004     return IShellView2_Release(&This->IShellView2_iface);
3005 }
3006
3007 static HRESULT WINAPI IShellFolderView_fnRearrange(IShellFolderView *iface, LPARAM sort)
3008 {
3009     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3010     FIXME("(%p)->(%ld) stub\n", This, sort);
3011     return E_NOTIMPL;
3012 }
3013
3014 static HRESULT WINAPI IShellFolderView_fnGetArrangeParam(IShellFolderView *iface, LPARAM *sort)
3015 {
3016     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3017     FIXME("(%p)->(%p) stub\n", This, sort);
3018     return E_NOTIMPL;
3019 }
3020
3021 static HRESULT WINAPI IShellFolderView_fnArrangeGrid(IShellFolderView *iface)
3022 {
3023     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3024     FIXME("(%p) stub\n", This);
3025     return E_NOTIMPL;
3026 }
3027
3028 static HRESULT WINAPI IShellFolderView_fnAutoArrange(IShellFolderView *iface)
3029 {
3030     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3031     FIXME("(%p) stub\n", This);
3032     return E_NOTIMPL;
3033 }
3034
3035 static HRESULT WINAPI IShellFolderView_fnGetAutoArrange(IShellFolderView *iface)
3036 {
3037     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3038     IFolderView *view = &This->IFolderView_iface;
3039
3040     TRACE("(%p)\n", This);
3041     return IFolderView_GetAutoArrange(view);
3042 }
3043
3044 static HRESULT WINAPI IShellFolderView_fnAddObject(
3045     IShellFolderView *iface,
3046     PITEMID_CHILD pidl,
3047     UINT *item)
3048 {
3049     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3050     FIXME("(%p)->(%p %p) stub\n", This, pidl, item);
3051     return E_NOTIMPL;
3052 }
3053
3054 static HRESULT WINAPI IShellFolderView_fnGetObject(
3055     IShellFolderView *iface,
3056     PITEMID_CHILD *pidl,
3057     UINT item)
3058 {
3059     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3060     IFolderView *view = &This->IFolderView_iface;
3061
3062     TRACE("(%p)->(%p %d)\n", This, pidl, item);
3063     return IFolderView_Item(view, item, pidl);
3064 }
3065
3066 static HRESULT WINAPI IShellFolderView_fnRemoveObject(
3067     IShellFolderView *iface,
3068     PITEMID_CHILD pidl,
3069     UINT *item)
3070 {
3071     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3072
3073     TRACE("(%p)->(%p %p)\n", This, pidl, item);
3074
3075     if (pidl)
3076     {
3077         *item = LV_FindItemByPidl(This, ILFindLastID(pidl));
3078         SendMessageW(This->hWndList, LVM_DELETEITEM, *item, 0);
3079     }
3080     else
3081     {
3082         *item = 0;
3083         SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
3084     }
3085
3086     return S_OK;
3087 }
3088
3089 static HRESULT WINAPI IShellFolderView_fnGetObjectCount(
3090     IShellFolderView *iface,
3091     UINT *count)
3092 {
3093     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3094     IFolderView *view = &This->IFolderView_iface;
3095
3096     TRACE("(%p)->(%p)\n", This, count);
3097     return IFolderView_ItemCount(view, SVGIO_ALLVIEW, (INT*)count);
3098 }
3099
3100 static HRESULT WINAPI IShellFolderView_fnSetObjectCount(
3101     IShellFolderView *iface,
3102     UINT count,
3103     UINT flags)
3104 {
3105     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3106     FIXME("(%p)->(%d %x) stub\n", This, count, flags);
3107     return E_NOTIMPL;
3108 }
3109
3110 static HRESULT WINAPI IShellFolderView_fnUpdateObject(
3111     IShellFolderView *iface,
3112     PITEMID_CHILD pidl_old,
3113     PITEMID_CHILD pidl_new,
3114     UINT *item)
3115 {
3116     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3117     FIXME("(%p)->(%p %p %p) stub\n", This, pidl_old, pidl_new, item);
3118     return E_NOTIMPL;
3119 }
3120
3121 static HRESULT WINAPI IShellFolderView_fnRefreshObject(
3122     IShellFolderView *iface,
3123     PITEMID_CHILD pidl,
3124     UINT *item)
3125 {
3126     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3127     FIXME("(%p)->(%p %p) stub\n", This, pidl, item);
3128     return E_NOTIMPL;
3129 }
3130
3131 static HRESULT WINAPI IShellFolderView_fnSetRedraw(
3132     IShellFolderView *iface,
3133     BOOL redraw)
3134 {
3135     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3136     TRACE("(%p)->(%d)\n", This, redraw);
3137
3138     SendMessageW(This->hWndList, WM_SETREDRAW, redraw, 0);
3139
3140     return S_OK;
3141 }
3142
3143 static HRESULT WINAPI IShellFolderView_fnGetSelectedCount(
3144     IShellFolderView *iface,
3145     UINT *count)
3146 {
3147     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3148     FIXME("(%p)->(%p) stub\n", This, count);
3149     return E_NOTIMPL;
3150 }
3151
3152 static HRESULT WINAPI IShellFolderView_fnGetSelectedObjects(
3153     IShellFolderView *iface,
3154     PCITEMID_CHILD **pidl,
3155     UINT *items)
3156 {
3157     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3158
3159     TRACE("(%p)->(%p %p)\n", This, pidl, items);
3160
3161     *items = ShellView_GetSelections( This );
3162
3163     if (*items)
3164     {
3165         *pidl = LocalAlloc(0, *items*sizeof(LPITEMIDLIST));
3166         if (!*pidl) return E_OUTOFMEMORY;
3167
3168         /* it's documented that caller shouldn't free PIDLs, only array itself */
3169         memcpy((PITEMID_CHILD*)*pidl, This->apidl, *items*sizeof(LPITEMIDLIST));
3170     }
3171
3172     return S_OK;
3173 }
3174
3175 static HRESULT WINAPI IShellFolderView_fnIsDropOnSource(
3176     IShellFolderView *iface,
3177     IDropTarget *drop_target)
3178 {
3179     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3180     FIXME("(%p)->(%p) stub\n", This, drop_target);
3181     return E_NOTIMPL;
3182 }
3183
3184 static HRESULT WINAPI IShellFolderView_fnGetDragPoint(
3185     IShellFolderView *iface,
3186     POINT *pt)
3187 {
3188     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3189     FIXME("(%p)->(%p) stub\n", This, pt);
3190     return E_NOTIMPL;
3191 }
3192
3193 static HRESULT WINAPI IShellFolderView_fnGetDropPoint(
3194     IShellFolderView *iface,
3195     POINT *pt)
3196 {
3197     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3198     FIXME("(%p)->(%p) stub\n", This, pt);
3199     return E_NOTIMPL;
3200 }
3201
3202 static HRESULT WINAPI IShellFolderView_fnMoveIcons(
3203     IShellFolderView *iface,
3204     IDataObject *obj)
3205 {
3206     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3207     TRACE("(%p)->(%p)\n", This, obj);
3208     return E_NOTIMPL;
3209 }
3210
3211 static HRESULT WINAPI IShellFolderView_fnSetItemPos(
3212     IShellFolderView *iface,
3213     PCUITEMID_CHILD pidl,
3214     POINT *pt)
3215 {
3216     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3217     FIXME("(%p)->(%p %p) stub\n", This, pidl, pt);
3218     return E_NOTIMPL;
3219 }
3220
3221 static HRESULT WINAPI IShellFolderView_fnIsBkDropTarget(
3222     IShellFolderView *iface,
3223     IDropTarget *drop_target)
3224 {
3225     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3226     FIXME("(%p)->(%p) stub\n", This, drop_target);
3227     return E_NOTIMPL;
3228 }
3229
3230 static HRESULT WINAPI IShellFolderView_fnSetClipboard(
3231     IShellFolderView *iface,
3232     BOOL move)
3233 {
3234     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3235     FIXME("(%p)->(%d) stub\n", This, move);
3236     return E_NOTIMPL;
3237 }
3238
3239 static HRESULT WINAPI IShellFolderView_fnSetPoints(
3240     IShellFolderView *iface,
3241     IDataObject *obj)
3242 {
3243     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3244     FIXME("(%p)->(%p) stub\n", This, obj);
3245     return E_NOTIMPL;
3246 }
3247
3248 static HRESULT WINAPI IShellFolderView_fnGetItemSpacing(
3249     IShellFolderView *iface,
3250     ITEMSPACING *spacing)
3251 {
3252     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3253     FIXME("(%p)->(%p) stub\n", This, spacing);
3254     return E_NOTIMPL;
3255 }
3256
3257 static HRESULT WINAPI IShellFolderView_fnSetCallback(
3258     IShellFolderView    *iface,
3259     IShellFolderViewCB  *new_cb,
3260     IShellFolderViewCB **old_cb)
3261
3262 {
3263     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3264     FIXME("(%p)->(%p %p) stub\n", This, new_cb, old_cb);
3265     return E_NOTIMPL;
3266 }
3267
3268 static HRESULT WINAPI IShellFolderView_fnSelect(
3269     IShellFolderView *iface,
3270     UINT flags)
3271 {
3272     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3273     FIXME("(%p)->(%d) stub\n", This, flags);
3274     return E_NOTIMPL;
3275 }
3276
3277 static HRESULT WINAPI IShellFolderView_fnQuerySupport(
3278     IShellFolderView *iface,
3279     UINT *support)
3280 {
3281     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3282     TRACE("(%p)->(%p)\n", This, support);
3283     return S_OK;
3284 }
3285
3286 static HRESULT WINAPI IShellFolderView_fnSetAutomationObject(
3287     IShellFolderView *iface,
3288     IDispatch *disp)
3289 {
3290     IShellViewImpl *This = impl_from_IShellFolderView(iface);
3291     FIXME("(%p)->(%p) stub\n", This, disp);
3292     return E_NOTIMPL;
3293 }
3294
3295 static const IShellFolderViewVtbl shellfolderviewvt =
3296 {
3297     IShellFolderView_fnQueryInterface,
3298     IShellFolderView_fnAddRef,
3299     IShellFolderView_fnRelease,
3300     IShellFolderView_fnRearrange,
3301     IShellFolderView_fnGetArrangeParam,
3302     IShellFolderView_fnArrangeGrid,
3303     IShellFolderView_fnAutoArrange,
3304     IShellFolderView_fnGetAutoArrange,
3305     IShellFolderView_fnAddObject,
3306     IShellFolderView_fnGetObject,
3307     IShellFolderView_fnRemoveObject,
3308     IShellFolderView_fnGetObjectCount,
3309     IShellFolderView_fnSetObjectCount,
3310     IShellFolderView_fnUpdateObject,
3311     IShellFolderView_fnRefreshObject,
3312     IShellFolderView_fnSetRedraw,
3313     IShellFolderView_fnGetSelectedCount,
3314     IShellFolderView_fnGetSelectedObjects,
3315     IShellFolderView_fnIsDropOnSource,
3316     IShellFolderView_fnGetDragPoint,
3317     IShellFolderView_fnGetDropPoint,
3318     IShellFolderView_fnMoveIcons,
3319     IShellFolderView_fnSetItemPos,
3320     IShellFolderView_fnIsBkDropTarget,
3321     IShellFolderView_fnSetClipboard,
3322     IShellFolderView_fnSetPoints,
3323     IShellFolderView_fnGetItemSpacing,
3324     IShellFolderView_fnSetCallback,
3325     IShellFolderView_fnSelect,
3326     IShellFolderView_fnQuerySupport,
3327     IShellFolderView_fnSetAutomationObject
3328 };