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