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