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