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