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