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