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