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