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