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