shell32: Stub IShellView2::SelectAndPositionItem() over IFolderView::SelectAndPositio...
[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           dwFetched;
642         HRESULT         hRes;
643         HDPA            hdpa;
644
645         TRACE("%p\n",This);
646
647         /* get the itemlist from the shfolder*/
648         hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
649         if (hRes != S_OK)
650         {
651           if (hRes==S_FALSE)
652             return(NOERROR);
653           return(hRes);
654         }
655
656         /* create a pointer array */
657         hdpa = DPA_Create(16);
658         if (!hdpa)
659         {
660           return(E_OUTOFMEMORY);
661         }
662
663         /* copy the items into the array*/
664         while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
665         {
666           if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
667           {
668             SHFree(pidl);
669           }
670         }
671
672         /* sort the array */
673         DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
674
675         /*turn the listview's redrawing off*/
676         SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
677
678         DPA_DestroyCallback( hdpa, fill_list, This );
679
680         /*turn the listview's redrawing back on and force it to draw*/
681         SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
682
683         IEnumIDList_Release(pEnumIDList); /* destroy the list*/
684
685         return S_OK;
686 }
687
688 /**********************************************************
689 *  ShellView_OnCreate()
690 */
691 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
692 {
693         IDropTarget* pdt;
694         SHChangeNotifyEntry ntreg;
695         IPersistFolder2 * ppf2 = NULL;
696
697         TRACE("%p\n",This);
698
699         if(ShellView_CreateList(This))
700         {
701           if(ShellView_InitList(This))
702           {
703             ShellView_FillList(This);
704           }
705         }
706
707         if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
708         {
709             RegisterDragDrop(This->hWnd, pdt);
710             IDropTarget_Release(pdt);
711         }
712
713         /* register for receiving notifications */
714         IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
715         if (ppf2)
716         {
717           IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
718           ntreg.fRecursive = TRUE;
719           This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
720           SHFree((LPITEMIDLIST)ntreg.pidl);
721           IPersistFolder2_Release(ppf2);
722         }
723
724         This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
725
726         return S_OK;
727 }
728
729 /**********************************************************
730  *      #### Handling of the menus ####
731  */
732
733 /**********************************************************
734 * ShellView_BuildFileMenu()
735 */
736 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
737 {       WCHAR   szText[MAX_PATH];
738         MENUITEMINFOW   mii;
739         int     nTools,i;
740         HMENU   hSubMenu;
741
742         TRACE("(%p)\n",This);
743
744         hSubMenu = CreatePopupMenu();
745         if(hSubMenu)
746         { /*get the number of items in our global array*/
747           for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
748
749           /*add the menu items*/
750           for(i = 0; i < nTools; i++)
751           {
752             LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
753
754             ZeroMemory(&mii, sizeof(mii));
755             mii.cbSize = sizeof(mii);
756             mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
757
758             if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
759             {
760               mii.fType = MFT_STRING;
761               mii.fState = MFS_ENABLED;
762               mii.dwTypeData = szText;
763               mii.wID = Tools[i].idCommand;
764             }
765             else
766             {
767               mii.fType = MFT_SEPARATOR;
768             }
769             /* tack This item onto the end of the menu */
770             InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
771           }
772         }
773         TRACE("-- return (menu=%p)\n",hSubMenu);
774         return hSubMenu;
775 }
776 /**********************************************************
777 * ShellView_MergeFileMenu()
778 */
779 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
780 {       TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
781
782         if(hSubMenu)
783         { /*insert This item at the beginning of the menu */
784             MENUITEMINFOA mii;
785
786             mii.cbSize = sizeof(mii);
787             mii.fMask = MIIM_ID | MIIM_TYPE;
788             mii.wID = 0;
789             mii.fType = MFT_SEPARATOR;
790             InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
791
792             mii.cbSize = sizeof(mii);
793             mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
794             mii.dwTypeData = (LPSTR)"dummy45";
795             mii.fState = MFS_ENABLED;
796             mii.wID = IDM_MYFILEITEM;
797             mii.fType = MFT_STRING;
798             InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
799         }
800         TRACE("--\n");
801 }
802
803 /**********************************************************
804 * ShellView_MergeViewMenu()
805 */
806
807 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
808 {
809         TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
810
811         if(hSubMenu)
812         { /*add a separator at the correct position in the menu*/
813           MENUITEMINFOA mii;
814           static char view[] = "View";
815
816           ZeroMemory(&mii, sizeof(mii));
817           mii.cbSize = sizeof(mii);
818           mii.fMask = MIIM_ID | MIIM_TYPE;
819           mii.wID = 0;
820           mii.fType = MFT_SEPARATOR;
821           InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
822
823           mii.cbSize = sizeof(mii);
824           mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
825           mii.fType = MFT_STRING;
826           mii.dwTypeData = view;
827           mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
828           InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
829         }
830 }
831
832 /**********************************************************
833 *   ShellView_GetSelections()
834 *
835 * - fills the this->apidl list with the selected objects
836 *
837 * RETURNS
838 *  number of selected items
839 */
840 static UINT ShellView_GetSelections(IShellViewImpl * This)
841 {
842         LVITEMW lvItem;
843         UINT    i = 0;
844
845         SHFree(This->apidl);
846
847         This->cidl = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
848         This->apidl = SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
849
850         TRACE("selected=%i\n", This->cidl);
851
852         if(This->apidl)
853         {
854           TRACE("-- Items selected =%u\n", This->cidl);
855
856           lvItem.mask = LVIF_STATE | LVIF_PARAM;
857           lvItem.stateMask = LVIS_SELECTED;
858           lvItem.iItem = 0;
859           lvItem.iSubItem = 0;
860
861           while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
862           {
863             if(lvItem.state & LVIS_SELECTED)
864             {
865               This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
866               i++;
867               TRACE("-- selected Item found\n");
868             }
869             lvItem.iItem++;
870           }
871         }
872         return This->cidl;
873
874 }
875
876 /**********************************************************
877  *      ShellView_OpenSelectedItems()
878  */
879 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
880 {
881         static UINT CF_IDLIST = 0;
882         HRESULT hr;
883         IDataObject* selection;
884         FORMATETC fetc;
885         STGMEDIUM stgm;
886         LPIDA pIDList;
887         LPCITEMIDLIST parent_pidl;
888         WCHAR parent_path[MAX_PATH];
889         LPCWSTR parent_dir = NULL;
890         SFGAOF attribs;
891         int i;
892
893         if (0 == ShellView_GetSelections(This))
894         {
895           return S_OK;
896         }
897         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
898                                         (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
899                                         0, (LPVOID *)&selection);
900         if (FAILED(hr))
901           return hr;
902
903         if (0 == CF_IDLIST)
904         {
905           CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
906         }
907         fetc.cfFormat = CF_IDLIST;
908         fetc.ptd = NULL;
909         fetc.dwAspect = DVASPECT_CONTENT;
910         fetc.lindex = -1;
911         fetc.tymed = TYMED_HGLOBAL;
912
913         hr = IDataObject_QueryGetData(selection, &fetc);
914         if (FAILED(hr))
915           return hr;
916
917         hr = IDataObject_GetData(selection, &fetc, &stgm);
918         if (FAILED(hr))
919           return hr;
920
921         pIDList = GlobalLock(stgm.u.hGlobal);
922
923         parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
924         hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
925         if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
926             SHGetPathFromIDListW(parent_pidl, parent_path))
927         {
928           parent_dir = parent_path;
929         }
930
931         for (i = pIDList->cidl; i > 0; --i)
932         {
933           LPCITEMIDLIST pidl;
934
935           pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
936
937           attribs = SFGAO_FOLDER;
938           hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
939
940           if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
941           {
942             SHELLEXECUTEINFOW shexinfo;
943
944             shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
945             shexinfo.fMask = SEE_MASK_INVOKEIDLIST;     /* SEE_MASK_IDLIST is also possible. */
946             shexinfo.hwnd = NULL;
947             shexinfo.lpVerb = NULL;
948             shexinfo.lpFile = NULL;
949             shexinfo.lpParameters = NULL;
950             shexinfo.lpDirectory = parent_dir;
951             shexinfo.nShow = SW_NORMAL;
952             shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
953
954             ShellExecuteExW(&shexinfo);    /* Discard error/success info */
955
956             ILFree(shexinfo.lpIDList);
957           }
958         }
959
960         GlobalUnlock(stgm.u.hGlobal);
961         ReleaseStgMedium(&stgm);
962
963         IDataObject_Release(selection);
964
965         return S_OK;
966 }
967
968 /**********************************************************
969  *      ShellView_DoContextMenu()
970  */
971 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
972 {       UINT    uCommand;
973         DWORD   wFlags;
974         HMENU   hMenu;
975         BOOL    fExplore = FALSE;
976         HWND    hwndTree = 0;
977         LPCONTEXTMENU   pContextMenu = NULL;
978         IContextMenu2 *pCM = NULL;
979         CMINVOKECOMMANDINFO     cmi;
980
981         TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
982
983         /* look, what's selected and create a context menu object of it*/
984         if( ShellView_GetSelections(This) )
985         {
986           IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
987                                       &IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
988
989           if(pContextMenu)
990           {
991             TRACE("-- pContextMenu\n");
992             hMenu = CreatePopupMenu();
993
994             if( hMenu )
995             {
996               /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
997               if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
998               {
999                 TRACE("-- explore mode\n");
1000                 fExplore = TRUE;
1001               }
1002
1003               /* build the flags depending on what we can do with the selected item */
1004               wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
1005
1006               /* let the ContextMenu merge its items in */
1007               if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
1008               {
1009                 if (This->FolderSettings.fFlags & FWF_DESKTOP)
1010                   SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1011
1012                 if( bDefault )
1013                 {
1014                   TRACE("-- get menu default command\n");
1015                   uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1016                 }
1017                 else
1018                 {
1019                   TRACE("-- track popup\n");
1020                   uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1021                 }
1022
1023                 if(uCommand > 0)
1024                 {
1025                   TRACE("-- uCommand=%u\n", uCommand);
1026                   if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1027                   {
1028                     TRACE("-- dlg: OnDefaultCommand\n");
1029                     if (OnDefaultCommand(This) != S_OK)
1030                     {
1031                       ShellView_OpenSelectedItems(This);
1032                     }
1033                   }
1034                   else
1035                   {
1036                     TRACE("-- explore -- invoke command\n");
1037                     ZeroMemory(&cmi, sizeof(cmi));
1038                     cmi.cbSize = sizeof(cmi);
1039                     cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1040                     cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1041                     IContextMenu_InvokeCommand(pContextMenu, &cmi);
1042                   }
1043                 }
1044                 DestroyMenu(hMenu);
1045               }
1046             }
1047             if (pContextMenu)
1048               IContextMenu_Release(pContextMenu);
1049           }
1050         }
1051         else    /* background context menu */
1052         {
1053           hMenu = CreatePopupMenu();
1054
1055           pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1056           IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1057
1058           uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1059           DestroyMenu(hMenu);
1060
1061           TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1062
1063           ZeroMemory(&cmi, sizeof(cmi));
1064           cmi.cbSize = sizeof(cmi);
1065           cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1066           cmi.hwnd = This->hWndParent;
1067           IContextMenu2_InvokeCommand(pCM, &cmi);
1068
1069           IContextMenu2_Release(pCM);
1070         }
1071 }
1072
1073 /**********************************************************
1074  *      ##### message handling #####
1075  */
1076
1077 /**********************************************************
1078 *  ShellView_OnSize()
1079 */
1080 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1081 {
1082         TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1083
1084         /*resize the ListView to fit our window*/
1085         if(This->hWndList)
1086         {
1087           MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1088         }
1089
1090         return S_OK;
1091 }
1092 /**********************************************************
1093 * ShellView_OnDeactivate()
1094 *
1095 * NOTES
1096 *  internal
1097 */
1098 static void ShellView_OnDeactivate(IShellViewImpl * This)
1099 {
1100         TRACE("%p\n",This);
1101
1102         if(This->uState != SVUIA_DEACTIVATE)
1103         {
1104           if(This->hMenu)
1105           {
1106             IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1107             IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1108             DestroyMenu(This->hMenu);
1109             This->hMenu = 0;
1110           }
1111
1112           This->uState = SVUIA_DEACTIVATE;
1113         }
1114 }
1115
1116 /**********************************************************
1117 * ShellView_OnActivate()
1118 */
1119 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1120 {       OLEMENUGROUPWIDTHS   omw = { {0, 0, 0, 0, 0, 0} };
1121         MENUITEMINFOA         mii;
1122         CHAR                szText[MAX_PATH];
1123
1124         TRACE("%p uState=%x\n",This,uState);
1125
1126         /*don't do anything if the state isn't really changing */
1127         if(This->uState == uState)
1128         {
1129           return S_OK;
1130         }
1131
1132         ShellView_OnDeactivate(This);
1133
1134         /*only do This if we are active */
1135         if(uState != SVUIA_DEACTIVATE)
1136         {
1137           /*merge the menus */
1138           This->hMenu = CreateMenu();
1139
1140           if(This->hMenu)
1141           {
1142             IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1143             TRACE("-- after fnInsertMenusSB\n");
1144
1145             /*build the top level menu get the menu item's text*/
1146             strcpy(szText,"dummy 31");
1147
1148             ZeroMemory(&mii, sizeof(mii));
1149             mii.cbSize = sizeof(mii);
1150             mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1151             mii.fType = MFT_STRING;
1152             mii.fState = MFS_ENABLED;
1153             mii.dwTypeData = szText;
1154             mii.hSubMenu = ShellView_BuildFileMenu(This);
1155
1156             /*insert our menu into the menu bar*/
1157             if(mii.hSubMenu)
1158             {
1159               InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1160             }
1161
1162             /*get the view menu so we can merge with it*/
1163             ZeroMemory(&mii, sizeof(mii));
1164             mii.cbSize = sizeof(mii);
1165             mii.fMask = MIIM_SUBMENU;
1166
1167             if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1168             {
1169               ShellView_MergeViewMenu(This, mii.hSubMenu);
1170             }
1171
1172             /*add the items that should only be added if we have the focus*/
1173             if(SVUIA_ACTIVATE_FOCUS == uState)
1174             {
1175               /*get the file menu so we can merge with it */
1176               ZeroMemory(&mii, sizeof(mii));
1177               mii.cbSize = sizeof(mii);
1178               mii.fMask = MIIM_SUBMENU;
1179
1180               if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1181               {
1182                 ShellView_MergeFileMenu(This, mii.hSubMenu);
1183               }
1184             }
1185             TRACE("-- before fnSetMenuSB\n");
1186             IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1187           }
1188         }
1189         This->uState = uState;
1190         TRACE("--\n");
1191         return S_OK;
1192 }
1193
1194 /**********************************************************
1195 *  ShellView_OnSetFocus()
1196 *
1197 */
1198 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1199 {
1200         TRACE("%p\n",This);
1201
1202         /* Tell the browser one of our windows has received the focus. This
1203         should always be done before merging menus (OnActivate merges the
1204         menus) if one of our windows has the focus.*/
1205
1206         IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1207         ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1208
1209         /* Set the focus to the listview */
1210         SetFocus(This->hWndList);
1211
1212         /* Notify the ICommDlgBrowser interface */
1213         OnStateChange(This,CDBOSC_SETFOCUS);
1214
1215         return 0;
1216 }
1217
1218 /**********************************************************
1219 * ShellView_OnKillFocus()
1220 */
1221 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1222 {
1223         TRACE("(%p) stub\n",This);
1224
1225         ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1226         /* Notify the ICommDlgBrowser */
1227         OnStateChange(This,CDBOSC_KILLFOCUS);
1228
1229         return 0;
1230 }
1231
1232 /**********************************************************
1233 * ShellView_OnCommand()
1234 *
1235 * NOTES
1236 *       the CmdID's are the ones from the context menu
1237 */
1238 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1239 {
1240         TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1241
1242         switch(dwCmdID)
1243         {
1244           case FCIDM_SHVIEW_SMALLICON:
1245             This->FolderSettings.ViewMode = FVM_SMALLICON;
1246             SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1247             CheckToolbar(This);
1248             break;
1249
1250           case FCIDM_SHVIEW_BIGICON:
1251             This->FolderSettings.ViewMode = FVM_ICON;
1252             SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1253             CheckToolbar(This);
1254             break;
1255
1256           case FCIDM_SHVIEW_LISTVIEW:
1257             This->FolderSettings.ViewMode = FVM_LIST;
1258             SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1259             CheckToolbar(This);
1260             break;
1261
1262           case FCIDM_SHVIEW_REPORTVIEW:
1263             This->FolderSettings.ViewMode = FVM_DETAILS;
1264             SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1265             CheckToolbar(This);
1266             break;
1267
1268           /* the menu-ID's for sorting are 0x30... see shrec.rc */
1269           case 0x30:
1270           case 0x31:
1271           case 0x32:
1272           case 0x33:
1273             This->ListViewSortInfo.nHeaderID = dwCmdID - 0x30;
1274             This->ListViewSortInfo.bIsAscending = TRUE;
1275             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1276             SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1277             break;
1278
1279           default:
1280             TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1281         }
1282         return 0;
1283 }
1284
1285 /**********************************************************
1286 * ShellView_OnNotify()
1287 */
1288
1289 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1290 {       LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1291         NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1292         LPITEMIDLIST pidl;
1293
1294         TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1295
1296         switch(lpnmh->code)
1297         {
1298           case NM_SETFOCUS:
1299             TRACE("-- NM_SETFOCUS %p\n",This);
1300             ShellView_OnSetFocus(This);
1301             break;
1302
1303           case NM_KILLFOCUS:
1304             TRACE("-- NM_KILLFOCUS %p\n",This);
1305             ShellView_OnDeactivate(This);
1306             /* Notify the ICommDlgBrowser interface */
1307             OnStateChange(This,CDBOSC_KILLFOCUS);
1308             break;
1309
1310           case NM_CUSTOMDRAW:
1311             TRACE("-- NM_CUSTOMDRAW %p\n",This);
1312             return CDRF_DODEFAULT;
1313
1314           case NM_RELEASEDCAPTURE:
1315             TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1316             break;
1317
1318           case NM_CLICK:
1319             TRACE("-- NM_CLICK %p\n",This);
1320             break;
1321
1322           case NM_RCLICK:
1323             TRACE("-- NM_RCLICK %p\n",This);
1324             break;          
1325
1326           case NM_DBLCLK:
1327             TRACE("-- NM_DBLCLK %p\n",This);
1328             if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1329             break;
1330
1331           case NM_RETURN:
1332             TRACE("-- NM_RETURN %p\n",This);
1333             if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1334             break;
1335
1336           case HDN_ENDTRACKW:
1337             TRACE("-- HDN_ENDTRACKW %p\n",This);
1338             /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1339             nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1340             break;
1341
1342           case LVN_DELETEITEM:
1343             TRACE("-- LVN_DELETEITEM %p\n",This);
1344             SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
1345             break;
1346
1347           case LVN_DELETEALLITEMS:
1348             TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1349             return FALSE;
1350
1351           case LVN_INSERTITEM:
1352             TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1353             break;
1354
1355           case LVN_ITEMACTIVATE:
1356             TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1357             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1358             break;
1359
1360           case LVN_COLUMNCLICK:
1361             This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1362             if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1363             {
1364               This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1365             }
1366             else
1367             {
1368               This->ListViewSortInfo.bIsAscending = TRUE;
1369             }
1370             This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1371
1372             SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1373             break;
1374
1375           case LVN_GETDISPINFOA:
1376           case LVN_GETDISPINFOW:
1377             TRACE("-- LVN_GETDISPINFO %p\n",This);
1378             pidl = (LPITEMIDLIST)lpdi->item.lParam;
1379
1380             if(lpdi->item.mask & LVIF_TEXT)     /* text requested */
1381             {
1382               if (This->pSF2Parent)
1383               {
1384                 SHELLDETAILS sd;
1385                 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1386                 if (lpnmh->code == LVN_GETDISPINFOA)
1387                 {
1388                     /* shouldn't happen */
1389                     NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1390                     StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1391                     TRACE("-- text=%s\n",lpdiA->item.pszText);
1392                 }
1393                 else /* LVN_GETDISPINFOW */
1394                 {
1395                     StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1396                     TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1397                 }
1398               }
1399               else
1400               {
1401                 FIXME("no SF2\n");
1402               }
1403             }
1404             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
1405             {
1406               lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1407             }
1408             break;
1409
1410           case LVN_ITEMCHANGED:
1411             TRACE("-- LVN_ITEMCHANGED %p\n",This);
1412             OnStateChange(This, CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1413             break;
1414
1415           case LVN_BEGINDRAG:
1416           case LVN_BEGINRDRAG:
1417             TRACE("-- LVN_BEGINDRAG\n");
1418
1419             if (ShellView_GetSelections(This))
1420             {
1421               IDataObject * pda;
1422               DWORD dwAttributes = SFGAO_CANLINK;
1423               DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1424
1425               if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1426               {
1427                   IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource);  /* own DropSource interface */
1428
1429                   if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1430                   {
1431                     if (dwAttributes & SFGAO_CANLINK)
1432                     {
1433                       dwEffect |= DROPEFFECT_LINK;
1434                     }
1435                   }
1436
1437                   if (pds)
1438                   {
1439                     DWORD dwEffect2;
1440                     DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1441                   }
1442                   IDataObject_Release(pda);
1443               }
1444             }
1445             break;
1446
1447           case LVN_BEGINLABELEDITW:
1448             {
1449               DWORD dwAttr = SFGAO_CANRENAME;
1450               pidl = (LPITEMIDLIST)lpdi->item.lParam;
1451
1452               TRACE("-- LVN_BEGINLABELEDITW %p\n",This);
1453
1454               IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1455               if (SFGAO_CANRENAME & dwAttr)
1456               {
1457                 return FALSE;
1458               }
1459               return TRUE;
1460             }
1461
1462           case LVN_ENDLABELEDITW:
1463             {
1464               TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1465               if (lpdi->item.pszText)
1466               {
1467                 HRESULT hr;
1468                 LVITEMW lvItem;
1469
1470                 lvItem.iItem = lpdi->item.iItem;
1471                 lvItem.iSubItem = 0;
1472                 lvItem.mask = LVIF_PARAM;
1473                 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1474
1475                 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1476                 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1477
1478                 if(SUCCEEDED(hr) && pidl)
1479                 {
1480                   lvItem.mask = LVIF_PARAM;
1481                   lvItem.lParam = (LPARAM)pidl;
1482                   SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1483                   return TRUE;
1484                 }
1485               }
1486               return FALSE;
1487             }
1488
1489           case LVN_KEYDOWN:
1490             {
1491             /*  MSG msg;
1492               msg.hwnd = This->hWnd;
1493               msg.message = WM_KEYDOWN;
1494               msg.wParam = plvKeyDown->wVKey;
1495               msg.lParam = 0;
1496               msg.time = 0;
1497               msg.pt = 0;*/
1498
1499               LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1500
1501               /* initiate a rename of the selected file or directory */
1502               if(plvKeyDown->wVKey == VK_F2)
1503               {
1504                 /* see how many files are selected */
1505                 int i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
1506
1507                 /* get selected item */
1508                 if(i == 1)
1509                 {
1510                   /* get selected item */
1511                   i = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, MAKELPARAM (LVNI_SELECTED, 0));
1512
1513                   SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1514                   SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1515                 }
1516               }
1517 #if 0
1518               TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1519 #endif
1520               else if(plvKeyDown->wVKey == VK_DELETE)
1521               {
1522                 UINT i;
1523                 int item_index;
1524                 LVITEMA item;
1525                 LPITEMIDLIST* pItems;
1526                 ISFHelper *psfhlp;
1527
1528                 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1529                         (LPVOID*)&psfhlp);
1530
1531                 if (psfhlp == NULL)
1532                   break;
1533
1534                 if(!(i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0)))
1535                   break;
1536
1537                 /* allocate memory for the pidl array */
1538                 pItems = HeapAlloc(GetProcessHeap(), 0,
1539                         sizeof(LPITEMIDLIST) * i);
1540
1541                 /* retrieve all selected items */
1542                 i = 0;
1543                 item_index = -1;
1544                 while(SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0) > i)
1545                 {
1546                   /* get selected item */
1547                   item_index = SendMessageW(This->hWndList, LVM_GETNEXTITEM, item_index,
1548                                             MAKELPARAM (LVNI_SELECTED, 0));
1549                   item.iItem = item_index;
1550                   item.mask = LVIF_PARAM;
1551                   SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1552
1553                   /* get item pidl */
1554                   pItems[i] = (LPITEMIDLIST)item.lParam;
1555
1556                   i++;
1557                 }
1558
1559                 /* perform the item deletion */
1560                 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1561
1562                 /* free pidl array memory */
1563                 HeapFree(GetProcessHeap(), 0, pItems);
1564               }
1565
1566               /* Initiate a refresh */
1567               else if(plvKeyDown->wVKey == VK_F5)
1568               {
1569                 IShellView_Refresh((IShellView*)This);
1570               }
1571
1572               else if(plvKeyDown->wVKey == VK_BACK)
1573               {
1574                 LPSHELLBROWSER lpSb;
1575                 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1576                 {
1577                   IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1578                 }
1579               }
1580
1581               else
1582                 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1583             }
1584             break;
1585
1586           default:
1587             TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1588             break;
1589         }
1590         return 0;
1591 }
1592
1593 /**********************************************************
1594 * ShellView_OnChange()
1595 */
1596
1597 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1598 {
1599
1600         TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1601         switch(wEventId)
1602         {
1603           case SHCNE_MKDIR:
1604           case SHCNE_CREATE:
1605             LV_AddItem(This, Pidls[0]);
1606             break;
1607           case SHCNE_RMDIR:
1608           case SHCNE_DELETE:
1609             LV_DeleteItem(This, Pidls[0]);
1610             break;
1611           case SHCNE_RENAMEFOLDER:
1612           case SHCNE_RENAMEITEM:
1613             LV_RenameItem(This, Pidls[0], Pidls[1]);
1614             break;
1615           case SHCNE_UPDATEITEM:
1616             break;
1617         }
1618         return TRUE;
1619 }
1620 /**********************************************************
1621 *  ShellView_WndProc
1622 */
1623
1624 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1625 {
1626         IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1627         LPCREATESTRUCTW lpcs;
1628
1629         TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1630
1631         switch (uMessage)
1632         {
1633           case WM_NCCREATE:
1634             lpcs = (LPCREATESTRUCTW)lParam;
1635             pThis = lpcs->lpCreateParams;
1636             SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1637             pThis->hWnd = hWnd;        /*set the window handle*/
1638             break;
1639
1640           case WM_SIZE:         return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1641           case WM_SETFOCUS:     return ShellView_OnSetFocus(pThis);
1642           case WM_KILLFOCUS:    return ShellView_OnKillFocus(pThis);
1643           case WM_CREATE:       return ShellView_OnCreate(pThis);
1644           case WM_ACTIVATE:     return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1645           case WM_NOTIFY:       return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1646           case WM_COMMAND:      return ShellView_OnCommand(pThis,
1647                                         GET_WM_COMMAND_ID(wParam, lParam),
1648                                         GET_WM_COMMAND_CMD(wParam, lParam),
1649                                         GET_WM_COMMAND_HWND(wParam, lParam));
1650           case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1651
1652           case WM_CONTEXTMENU:  ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1653                                 return 0;
1654
1655           case WM_SHOWWINDOW:   UpdateWindow(pThis->hWndList);
1656                                 break;
1657
1658           case WM_GETDLGCODE:   return SendMessageA(pThis->hWndList,uMessage,0,0);
1659
1660           case WM_DESTROY:      
1661                                 RevokeDragDrop(pThis->hWnd);
1662                                 SHChangeNotifyDeregister(pThis->hNotify);
1663                                 break;
1664
1665           case WM_ERASEBKGND:
1666             if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1667                 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1668               return 1;
1669             break;
1670         }
1671
1672         return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1673 }
1674 /**********************************************************
1675 *
1676 *
1677 *  The INTERFACE of the IShellView object
1678 *
1679 *
1680 **********************************************************
1681 *  IShellView_QueryInterface
1682 */
1683 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView2 * iface,REFIID riid, LPVOID *ppvObj)
1684 {
1685         IShellViewImpl *This = (IShellViewImpl *)iface;
1686
1687         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1688
1689         *ppvObj = NULL;
1690
1691         if(IsEqualIID(riid, &IID_IUnknown))
1692         {
1693           *ppvObj = This;
1694         }
1695         else if(IsEqualIID(riid, &IID_IShellView))
1696         {
1697           *ppvObj = This;
1698         }
1699         else if(IsEqualIID(riid, &IID_IShellView2))
1700         {
1701           *ppvObj = This;
1702         }
1703         else if(IsEqualIID(riid, &IID_IFolderView))
1704         {
1705           *ppvObj = &This->lpvtblFolderView;
1706         }
1707         else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1708         {
1709           *ppvObj = &This->lpvtblOleCommandTarget;
1710         }
1711         else if(IsEqualIID(riid, &IID_IDropTarget))
1712         {
1713           *ppvObj = &This->lpvtblDropTarget;
1714         }
1715         else if(IsEqualIID(riid, &IID_IDropSource))
1716         {
1717           *ppvObj = &This->lpvtblDropSource;
1718         }
1719         else if(IsEqualIID(riid, &IID_IViewObject))
1720         {
1721           *ppvObj = &This->lpvtblViewObject;
1722         }
1723
1724         if(*ppvObj)
1725         {
1726           IUnknown_AddRef( (IUnknown*)*ppvObj );
1727           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1728           return S_OK;
1729         }
1730         TRACE("-- Interface: E_NOINTERFACE\n");
1731         return E_NOINTERFACE;
1732 }
1733
1734 /**********************************************************
1735 *  IShellView_AddRef
1736 */
1737 static ULONG WINAPI IShellView_fnAddRef(IShellView2 * iface)
1738 {
1739         IShellViewImpl *This = (IShellViewImpl *)iface;
1740         ULONG refCount = InterlockedIncrement(&This->ref);
1741
1742         TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1743
1744         return refCount;
1745 }
1746 /**********************************************************
1747 *  IShellView_Release
1748 */
1749 static ULONG WINAPI IShellView_fnRelease(IShellView2 * iface)
1750 {
1751         IShellViewImpl *This = (IShellViewImpl *)iface;
1752         ULONG refCount = InterlockedDecrement(&This->ref);
1753
1754         TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1755
1756         if (!refCount)
1757         {
1758           TRACE(" destroying IShellView(%p)\n",This);
1759
1760           DestroyWindow(This->hWndList);
1761
1762           if(This->pSFParent)
1763             IShellFolder_Release(This->pSFParent);
1764
1765           if(This->pSF2Parent)
1766             IShellFolder2_Release(This->pSF2Parent);
1767
1768           SHFree(This->apidl);
1769
1770           if(This->pAdvSink)
1771             IAdviseSink_Release(This->pAdvSink);
1772
1773           HeapFree(GetProcessHeap(),0,This);
1774         }
1775         return refCount;
1776 }
1777
1778 /**********************************************************
1779 *  ShellView_GetWindow
1780 */
1781 static HRESULT WINAPI IShellView_fnGetWindow(IShellView2 * iface,HWND * phWnd)
1782 {
1783         IShellViewImpl *This = (IShellViewImpl *)iface;
1784
1785         TRACE("(%p)\n",This);
1786
1787         *phWnd = This->hWnd;
1788
1789         return S_OK;
1790 }
1791
1792 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView2 * iface,BOOL fEnterMode)
1793 {
1794         IShellViewImpl *This = (IShellViewImpl *)iface;
1795
1796         FIXME("(%p) stub\n",This);
1797
1798         return E_NOTIMPL;
1799 }
1800
1801 /**********************************************************
1802 * IShellView_TranslateAccelerator
1803 *
1804 * FIXME:
1805 *  use the accel functions
1806 */
1807 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView2 * iface,LPMSG lpmsg)
1808 {
1809 #if 0
1810         IShellViewImpl *This = (IShellViewImpl *)iface;
1811
1812         FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1813 #endif
1814
1815         if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1816         {
1817           TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1818         }
1819         return S_FALSE; /* not handled */
1820 }
1821
1822 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView2 * iface,BOOL fEnable)
1823 {
1824         IShellViewImpl *This = (IShellViewImpl *)iface;
1825
1826         FIXME("(%p) stub\n",This);
1827
1828         return E_NOTIMPL;
1829 }
1830
1831 static HRESULT WINAPI IShellView_fnUIActivate(IShellView2 * iface,UINT uState)
1832 {
1833         IShellViewImpl *This = (IShellViewImpl *)iface;
1834
1835 /*
1836         CHAR    szName[MAX_PATH];
1837 */
1838         LRESULT lResult;
1839         int     nPartArray[1] = {-1};
1840
1841         TRACE("(%p)->(state=%x) stub\n",This, uState);
1842
1843         /*don't do anything if the state isn't really changing*/
1844         if(This->uState == uState)
1845         {
1846           return S_OK;
1847         }
1848
1849         /*OnActivate handles the menu merging and internal state*/
1850         ShellView_OnActivate(This, uState);
1851
1852         /*only do This if we are active*/
1853         if(uState != SVUIA_DEACTIVATE)
1854         {
1855
1856 /*
1857           GetFolderPath is not a method of IShellFolder
1858           IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1859 */
1860           /* set the number of parts */
1861           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1862                                                         (LPARAM)nPartArray, &lResult);
1863
1864           /* set the text for the parts */
1865 /*
1866           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1867                                                         0, (LPARAM)szName, &lResult);
1868 */
1869         }
1870
1871         return S_OK;
1872 }
1873
1874 static HRESULT WINAPI IShellView_fnRefresh(IShellView2 * iface)
1875 {
1876         IShellViewImpl *This = (IShellViewImpl *)iface;
1877
1878         TRACE("(%p)\n",This);
1879
1880         SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1881         ShellView_FillList(This);
1882
1883         return S_OK;
1884 }
1885
1886 static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView2 *iface, IShellView *lpPrevView,
1887         LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
1888 {
1889     HRESULT hr;
1890     SV2CVW2_PARAMS view_params;
1891     view_params.cbSize = sizeof(view_params);
1892     view_params.psvPrev = lpPrevView;
1893     view_params.pfs = lpfs;
1894     view_params.psbOwner = psb;
1895     view_params.prcView = prcView;
1896     view_params.pvid = NULL;
1897     view_params.hwndView = 0;
1898
1899     TRACE("(%p) Forwarding to CreateViewWindow2\n", iface);
1900
1901     hr = IShellView2_CreateViewWindow2(iface, &view_params);
1902     *phWnd = view_params.hwndView;
1903
1904     return hr;
1905 }
1906
1907 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView2 * iface)
1908 {
1909         IShellViewImpl *This = (IShellViewImpl *)iface;
1910
1911         TRACE("(%p)\n",This);
1912
1913         /*Make absolutely sure all our UI is cleaned up.*/
1914         IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1915
1916         if(This->hMenu)
1917         {
1918           DestroyMenu(This->hMenu);
1919         }
1920
1921         DestroyWindow(This->hWnd);
1922         if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1923         if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1924
1925
1926         return S_OK;
1927 }
1928
1929 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView2 * iface, LPFOLDERSETTINGS lpfs)
1930 {
1931         IShellViewImpl *This = (IShellViewImpl *)iface;
1932
1933         TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1934                 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1935
1936         if (!lpfs) return E_INVALIDARG;
1937
1938         *lpfs = This->FolderSettings;
1939         return NOERROR;
1940 }
1941
1942 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView2 * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1943 {
1944         IShellViewImpl *This = (IShellViewImpl *)iface;
1945
1946         FIXME("(%p) stub\n",This);
1947
1948         return E_NOTIMPL;
1949 }
1950
1951 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView2 * iface)
1952 {
1953         IShellViewImpl *This = (IShellViewImpl *)iface;
1954
1955         FIXME("(%p) stub\n",This);
1956
1957         return S_OK;
1958 }
1959
1960 static HRESULT WINAPI IShellView_fnSelectItem(
1961         IShellView2 * iface,
1962         LPCITEMIDLIST pidl,
1963         UINT flags)
1964 {
1965     IShellViewImpl *This = (IShellViewImpl *)iface;
1966     IFolderView *view;
1967     HRESULT hr;
1968     int i;
1969
1970     TRACE("(%p)->(pidl=%p, 0x%08x)\n",This, pidl, flags);
1971
1972     i = LV_FindItemByPidl(This, pidl);
1973     if (i == -1) return S_OK;
1974
1975     hr = IShellView2_QueryInterface(iface, &IID_IFolderView, (void**)&view);
1976     if (hr == S_OK)
1977     {
1978         hr = IFolderView_SelectItem(view, i, flags);
1979         IFolderView_Release(view);
1980     }
1981
1982     return hr;
1983 }
1984
1985 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView2 * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
1986 {
1987         IShellViewImpl *This = (IShellViewImpl *)iface;
1988
1989         TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
1990
1991         *ppvOut = NULL;
1992
1993         switch(uItem)
1994         {
1995           case SVGIO_BACKGROUND:
1996             *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
1997             break;
1998
1999           case SVGIO_SELECTION:
2000             ShellView_GetSelections(This);
2001             IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2002             break;
2003         }
2004         TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2005
2006         if(!*ppvOut) return E_OUTOFMEMORY;
2007
2008         return S_OK;
2009 }
2010
2011 static HRESULT WINAPI IShellView2_fnGetView(IShellView2* iface, SHELLVIEWID *view_guid, ULONG view_type)
2012 {
2013     FIXME("(%p)->(view_guid %s, view_type %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2014     return E_NOTIMPL;
2015 }
2016
2017 static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView2* iface, LPSV2CVW2_PARAMS view_params)
2018 {
2019     IShellViewImpl *This = (IShellViewImpl *)iface;
2020     WNDCLASSW wc;
2021     HWND wnd;
2022
2023     TRACE("(%p)->(view_params %p)\n", iface, view_params);
2024
2025     if (view_params->cbSize != sizeof(*view_params))
2026     {
2027         FIXME("Got unexpected cbSize %#x\n", view_params->cbSize);
2028         return E_FAIL;
2029     }
2030
2031     TRACE("-- psvPrev %p, pfs %p, psbOwner %p, prcView %p\n",
2032             view_params->psvPrev, view_params->pfs, view_params->psbOwner, view_params->prcView);
2033     TRACE("-- vmode %#x, flags %#x, left %d, top %d, right %d, bottom %d\n",
2034             view_params->pfs->ViewMode, view_params->pfs->fFlags, view_params->prcView->left,
2035             view_params->prcView->top, view_params->prcView->right, view_params->prcView->bottom);
2036
2037     /* Set up the member variables */
2038     This->pShellBrowser = view_params->psbOwner;
2039     This->FolderSettings = *view_params->pfs;
2040
2041     if (view_params->pvid)
2042     {
2043         if (IsEqualGUID(view_params->pvid, &VID_LargeIcons))
2044             This->FolderSettings.ViewMode = FVM_ICON;
2045         else if (IsEqualGUID(view_params->pvid, &VID_SmallIcons))
2046             This->FolderSettings.ViewMode = FVM_SMALLICON;
2047         else if (IsEqualGUID(view_params->pvid, &VID_List))
2048             This->FolderSettings.ViewMode = FVM_LIST;
2049         else if (IsEqualGUID(view_params->pvid, &VID_Details))
2050             This->FolderSettings.ViewMode = FVM_DETAILS;
2051         else if (IsEqualGUID(view_params->pvid, &VID_Thumbnails))
2052             This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2053         else if (IsEqualGUID(view_params->pvid, &VID_Tile))
2054             This->FolderSettings.ViewMode = FVM_TILE;
2055         else if (IsEqualGUID(view_params->pvid, &VID_ThumbStrip))
2056             This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
2057         else
2058             FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_params->pvid));
2059     }
2060
2061     /* Get our parent window */
2062     IShellBrowser_AddRef(This->pShellBrowser);
2063     IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
2064
2065     /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2066     This->pCommDlgBrowser = NULL;
2067     if (SUCCEEDED(IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser)))
2068     {
2069         TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);
2070     }
2071
2072     /* If our window class has not been registered, then do so */
2073     if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
2074     {
2075         ZeroMemory(&wc, sizeof(wc));
2076         wc.style            = CS_HREDRAW | CS_VREDRAW;
2077         wc.lpfnWndProc      = ShellView_WndProc;
2078         wc.cbClsExtra       = 0;
2079         wc.cbWndExtra       = 0;
2080         wc.hInstance        = shell32_hInstance;
2081         wc.hIcon            = 0;
2082         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
2083         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
2084         wc.lpszMenuName     = NULL;
2085         wc.lpszClassName    = SV_CLASS_NAME;
2086
2087         if (!RegisterClassW(&wc)) return E_FAIL;
2088     }
2089
2090     wnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP,
2091             view_params->prcView->left, view_params->prcView->top,
2092             view_params->prcView->right - view_params->prcView->left,
2093             view_params->prcView->bottom - view_params->prcView->top,
2094             This->hWndParent, 0, shell32_hInstance, This);
2095
2096     CheckToolbar(This);
2097
2098     if (!wnd) return E_FAIL;
2099
2100     SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2101     UpdateWindow(wnd);
2102
2103     view_params->hwndView = wnd;
2104
2105     return S_OK;
2106 }
2107
2108 static HRESULT WINAPI IShellView2_fnHandleRename(IShellView2* iface, LPCITEMIDLIST new_pidl)
2109 {
2110     FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
2111     return E_NOTIMPL;
2112 }
2113
2114 static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(
2115     IShellView2* iface,
2116     LPCITEMIDLIST item,
2117     UINT flags,
2118     POINT *point)
2119 {
2120     IShellViewImpl *This = (IShellViewImpl *)iface;
2121     IFolderView *view;
2122     HRESULT hr;
2123
2124     TRACE("(%p)->(item %p, flags %#x, point %p)\n", This, item, flags, point);
2125
2126     hr = IShellView2_QueryInterface(iface, &IID_IFolderView, (void**)&view);
2127     if (hr == S_OK)
2128     {
2129         hr = IFolderView_SelectAndPositionItems(view, 1, &item, point, flags);
2130         IFolderView_Release(view);
2131     }
2132
2133     return hr;
2134 }
2135
2136 static const IShellView2Vtbl svvt =
2137 {
2138         IShellView_fnQueryInterface,
2139         IShellView_fnAddRef,
2140         IShellView_fnRelease,
2141         IShellView_fnGetWindow,
2142         IShellView_fnContextSensitiveHelp,
2143         IShellView_fnTranslateAccelerator,
2144         IShellView_fnEnableModeless,
2145         IShellView_fnUIActivate,
2146         IShellView_fnRefresh,
2147         IShellView_fnCreateViewWindow,
2148         IShellView_fnDestroyViewWindow,
2149         IShellView_fnGetCurrentInfo,
2150         IShellView_fnAddPropertySheetPages,
2151         IShellView_fnSaveViewState,
2152         IShellView_fnSelectItem,
2153         IShellView_fnGetItemObject,
2154         IShellView2_fnGetView,
2155         IShellView2_fnCreateViewWindow2,
2156         IShellView2_fnHandleRename,
2157         IShellView2_fnSelectAndPositionItem,
2158 };
2159
2160
2161 /**********************************************************
2162  * ISVOleCmdTarget_QueryInterface (IUnknown)
2163  */
2164 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2165         IOleCommandTarget *     iface,
2166         REFIID                  iid,
2167         LPVOID*                 ppvObj)
2168 {
2169         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2170
2171         return IShellView2_QueryInterface((IShellView2*)This, iid, ppvObj);
2172 }
2173
2174 /**********************************************************
2175  * ISVOleCmdTarget_AddRef (IUnknown)
2176  */
2177 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2178         IOleCommandTarget *     iface)
2179 {
2180         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2181
2182         return IShellView2_AddRef((IShellView2*)This);
2183 }
2184
2185 /**********************************************************
2186  * ISVOleCmdTarget_Release (IUnknown)
2187  */
2188 static ULONG WINAPI ISVOleCmdTarget_Release(
2189         IOleCommandTarget *     iface)
2190 {
2191         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2192
2193         return IShellView2_Release((IShellView2*)This);
2194 }
2195
2196 /**********************************************************
2197  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2198  */
2199 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2200         IOleCommandTarget *iface,
2201         const GUID* pguidCmdGroup,
2202         ULONG cCmds,
2203         OLECMD * prgCmds,
2204         OLECMDTEXT* pCmdText)
2205 {
2206     UINT i;
2207     IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2208
2209     FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2210               This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2211
2212     if (!prgCmds)
2213         return E_POINTER;
2214     for (i = 0; i < cCmds; i++)
2215     {
2216         FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2217         prgCmds[i].cmdf = 0;
2218     }
2219     return OLECMDERR_E_UNKNOWNGROUP;
2220 }
2221
2222 /**********************************************************
2223  * ISVOleCmdTarget_Exec (IOleCommandTarget)
2224  *
2225  * nCmdID is the OLECMDID_* enumeration
2226  */
2227 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2228         IOleCommandTarget *iface,
2229         const GUID* pguidCmdGroup,
2230         DWORD nCmdID,
2231         DWORD nCmdexecopt,
2232         VARIANT* pvaIn,
2233         VARIANT* pvaOut)
2234 {
2235         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2236
2237         FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2238               This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2239
2240         if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2241            (nCmdID == 0x29) &&
2242            (nCmdexecopt == 4) && pvaOut)
2243            return S_OK;
2244         if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2245            (nCmdID == 9) &&
2246            (nCmdexecopt == 0))
2247            return 1;
2248
2249         return OLECMDERR_E_UNKNOWNGROUP;
2250 }
2251
2252 static const IOleCommandTargetVtbl ctvt =
2253 {
2254         ISVOleCmdTarget_QueryInterface,
2255         ISVOleCmdTarget_AddRef,
2256         ISVOleCmdTarget_Release,
2257         ISVOleCmdTarget_QueryStatus,
2258         ISVOleCmdTarget_Exec
2259 };
2260
2261 /**********************************************************
2262  * ISVDropTarget implementation
2263  */
2264
2265 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2266         IDropTarget *iface,
2267         REFIID riid,
2268         LPVOID *ppvObj)
2269 {
2270         IShellViewImpl *This = impl_from_IDropTarget(iface);
2271
2272         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2273
2274         return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2275 }
2276
2277 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2278 {
2279         IShellViewImpl *This = impl_from_IDropTarget(iface);
2280
2281         TRACE("(%p)->(count=%u)\n",This,This->ref);
2282
2283         return IShellView2_AddRef((IShellView2*)This);
2284 }
2285
2286 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2287 {
2288         IShellViewImpl *This = impl_from_IDropTarget(iface);
2289
2290         TRACE("(%p)->(count=%u)\n",This,This->ref);
2291
2292         return IShellView2_Release((IShellView2*)This);
2293 }
2294
2295 /******************************************************************************
2296  * drag_notify_subitem [Internal]
2297  *
2298  * Figure out the shellfolder object, which is currently under the mouse cursor
2299  * and notify it via the IDropTarget interface.
2300  */
2301
2302 #define SCROLLAREAWIDTH 20
2303
2304 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2305     DWORD *pdwEffect)
2306 {
2307     LVHITTESTINFO htinfo;
2308     LVITEMW lvItem;
2309     LONG lResult;
2310     HRESULT hr;
2311     RECT clientRect;
2312
2313     /* Map from global to client coordinates and query the index of the listview-item, which is 
2314      * currently under the mouse cursor. */
2315     htinfo.pt.x = pt.x;
2316     htinfo.pt.y = pt.y;
2317     htinfo.flags = LVHT_ONITEM;
2318     ScreenToClient(This->hWndList, &htinfo.pt);
2319     lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2320
2321     /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2322     GetClientRect(This->hWndList, &clientRect);
2323     if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2324         (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2325          htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2326     {
2327         This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2328         if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2329             if (htinfo.pt.x < SCROLLAREAWIDTH) 
2330                 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2331             if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2332                 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2333             if (htinfo.pt.y < SCROLLAREAWIDTH)
2334                 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2335             if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2336                 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2337         }
2338     } else {
2339         This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2340     }
2341     This->ptLastMousePos = htinfo.pt;
2342  
2343     /* If we are still over the previous sub-item, notify it via DragOver and return. */
2344     if (This->pCurDropTarget && lResult == This->iDragOverItem)
2345     return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2346   
2347     /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2348     if (This->pCurDropTarget) {
2349         IDropTarget_DragLeave(This->pCurDropTarget);
2350         IDropTarget_Release(This->pCurDropTarget);
2351         This->pCurDropTarget = NULL;
2352     }
2353
2354     This->iDragOverItem = lResult;
2355     if (lResult == -1) {
2356         /* We are not above one of the listview's subitems. Bind to the parent folder's
2357          * DropTarget interface. */
2358         hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget, 
2359                                          (LPVOID*)&This->pCurDropTarget);
2360     } else {
2361         /* Query the relative PIDL of the shellfolder object represented by the currently
2362          * dragged over listview-item ... */
2363         lvItem.mask = LVIF_PARAM;
2364         lvItem.iItem = lResult;
2365         lvItem.iSubItem = 0;
2366         SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2367
2368         /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2369         hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2370             (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2371     }
2372
2373     /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2374     if (FAILED(hr)) 
2375         return hr;
2376
2377     /* Notify the item just entered via DragEnter. */
2378     return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2379 }
2380
2381 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2382     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2383 {
2384     IShellViewImpl *This = impl_from_IDropTarget(iface);
2385
2386     /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2387     This->pCurDataObject = pDataObject;
2388     IDataObject_AddRef(pDataObject);
2389
2390     return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2391 }
2392
2393 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2394     DWORD *pdwEffect)
2395 {
2396     IShellViewImpl *This = impl_from_IDropTarget(iface);
2397     return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2398 }
2399
2400 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2401     IShellViewImpl *This = impl_from_IDropTarget(iface);
2402
2403     IDropTarget_DragLeave(This->pCurDropTarget);
2404
2405     IDropTarget_Release(This->pCurDropTarget);
2406     IDataObject_Release(This->pCurDataObject);
2407     This->pCurDataObject = NULL;
2408     This->pCurDropTarget = NULL;
2409     This->iDragOverItem = 0;
2410      
2411     return S_OK;
2412 }
2413
2414 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject, 
2415     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2416 {
2417     IShellViewImpl *This = impl_from_IDropTarget(iface);
2418
2419     IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2420
2421     IDropTarget_Release(This->pCurDropTarget);
2422     IDataObject_Release(This->pCurDataObject);
2423     This->pCurDataObject = NULL;
2424     This->pCurDropTarget = NULL;
2425     This->iDragOverItem = 0;
2426
2427     return S_OK;
2428 }
2429
2430 static const IDropTargetVtbl dtvt =
2431 {
2432         ISVDropTarget_QueryInterface,
2433         ISVDropTarget_AddRef,
2434         ISVDropTarget_Release,
2435         ISVDropTarget_DragEnter,
2436         ISVDropTarget_DragOver,
2437         ISVDropTarget_DragLeave,
2438         ISVDropTarget_Drop
2439 };
2440
2441 /**********************************************************
2442  * ISVDropSource implementation
2443  */
2444
2445 static HRESULT WINAPI ISVDropSource_QueryInterface(
2446         IDropSource *iface,
2447         REFIID riid,
2448         LPVOID *ppvObj)
2449 {
2450         IShellViewImpl *This = impl_from_IDropSource(iface);
2451
2452         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2453
2454         return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2455 }
2456
2457 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2458 {
2459         IShellViewImpl *This = impl_from_IDropSource(iface);
2460
2461         TRACE("(%p)->(count=%u)\n",This,This->ref);
2462
2463         return IShellView2_AddRef((IShellView2*)This);
2464 }
2465
2466 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2467 {
2468         IShellViewImpl *This = impl_from_IDropSource(iface);
2469
2470         TRACE("(%p)->(count=%u)\n",This,This->ref);
2471
2472         return IShellView2_Release((IShellView2*)This);
2473 }
2474
2475 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2476         IDropSource *iface,
2477         BOOL fEscapePressed,
2478         DWORD grfKeyState)
2479 {
2480         IShellViewImpl *This = impl_from_IDropSource(iface);
2481         TRACE("(%p)\n",This);
2482
2483         if (fEscapePressed)
2484           return DRAGDROP_S_CANCEL;
2485         else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2486           return DRAGDROP_S_DROP;
2487         else
2488           return NOERROR;
2489 }
2490
2491 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2492         IDropSource *iface,
2493         DWORD dwEffect)
2494 {
2495         IShellViewImpl *This = impl_from_IDropSource(iface);
2496         TRACE("(%p)\n",This);
2497
2498         return DRAGDROP_S_USEDEFAULTCURSORS;
2499 }
2500
2501 static const IDropSourceVtbl dsvt =
2502 {
2503         ISVDropSource_QueryInterface,
2504         ISVDropSource_AddRef,
2505         ISVDropSource_Release,
2506         ISVDropSource_QueryContinueDrag,
2507         ISVDropSource_GiveFeedback
2508 };
2509 /**********************************************************
2510  * ISVViewObject implementation
2511  */
2512
2513 static HRESULT WINAPI ISVViewObject_QueryInterface(
2514         IViewObject *iface,
2515         REFIID riid,
2516         LPVOID *ppvObj)
2517 {
2518         IShellViewImpl *This = impl_from_IViewObject(iface);
2519
2520         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2521
2522         return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2523 }
2524
2525 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2526 {
2527         IShellViewImpl *This = impl_from_IViewObject(iface);
2528
2529         TRACE("(%p)->(count=%u)\n",This,This->ref);
2530
2531         return IShellView2_AddRef((IShellView2*)This);
2532 }
2533
2534 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2535 {
2536         IShellViewImpl *This = impl_from_IViewObject(iface);
2537
2538         TRACE("(%p)->(count=%u)\n",This,This->ref);
2539
2540         return IShellView2_Release((IShellView2*)This);
2541 }
2542
2543 static HRESULT WINAPI ISVViewObject_Draw(
2544         IViewObject     *iface,
2545         DWORD dwDrawAspect,
2546         LONG lindex,
2547         void* pvAspect,
2548         DVTARGETDEVICE* ptd,
2549         HDC hdcTargetDev,
2550         HDC hdcDraw,
2551         LPCRECTL lprcBounds,
2552         LPCRECTL lprcWBounds,
2553         BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2554         ULONG_PTR dwContinue)
2555 {
2556
2557         IShellViewImpl *This = impl_from_IViewObject(iface);
2558
2559         FIXME("Stub: This=%p\n",This);
2560
2561         return E_NOTIMPL;
2562 }
2563 static HRESULT WINAPI ISVViewObject_GetColorSet(
2564         IViewObject     *iface,
2565         DWORD dwDrawAspect,
2566         LONG lindex,
2567         void *pvAspect,
2568         DVTARGETDEVICE* ptd,
2569         HDC hicTargetDevice,
2570         LOGPALETTE** ppColorSet)
2571 {
2572
2573         IShellViewImpl *This = impl_from_IViewObject(iface);
2574
2575         FIXME("Stub: This=%p\n",This);
2576
2577         return E_NOTIMPL;
2578 }
2579 static HRESULT WINAPI ISVViewObject_Freeze(
2580         IViewObject     *iface,
2581         DWORD dwDrawAspect,
2582         LONG lindex,
2583         void* pvAspect,
2584         DWORD* pdwFreeze)
2585 {
2586
2587         IShellViewImpl *This = impl_from_IViewObject(iface);
2588
2589         FIXME("Stub: This=%p\n",This);
2590
2591         return E_NOTIMPL;
2592 }
2593 static HRESULT WINAPI ISVViewObject_Unfreeze(
2594         IViewObject     *iface,
2595         DWORD dwFreeze)
2596 {
2597
2598         IShellViewImpl *This = impl_from_IViewObject(iface);
2599
2600         FIXME("Stub: This=%p\n",This);
2601
2602         return E_NOTIMPL;
2603 }
2604 static HRESULT WINAPI ISVViewObject_SetAdvise(
2605         IViewObject     *iface,
2606         DWORD aspects,
2607         DWORD advf,
2608         IAdviseSink* pAdvSink)
2609 {
2610
2611         IShellViewImpl *This = impl_from_IViewObject(iface);
2612
2613         FIXME("partial stub: %p %08x %08x %p\n",
2614               This, aspects, advf, pAdvSink);
2615
2616         /* FIXME: we set the AdviseSink, but never use it to send any advice */
2617         This->pAdvSink = pAdvSink;
2618         This->dwAspects = aspects;
2619         This->dwAdvf = advf;
2620
2621         return S_OK;
2622 }
2623
2624 static HRESULT WINAPI ISVViewObject_GetAdvise(
2625         IViewObject     *iface,
2626         DWORD* pAspects,
2627         DWORD* pAdvf,
2628         IAdviseSink** ppAdvSink)
2629 {
2630
2631         IShellViewImpl *This = impl_from_IViewObject(iface);
2632
2633         TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2634               This, pAspects, pAdvf, ppAdvSink);
2635
2636         if( ppAdvSink )
2637         {
2638                 IAdviseSink_AddRef( This->pAdvSink );
2639                 *ppAdvSink = This->pAdvSink;
2640         }
2641         if( pAspects )
2642                 *pAspects = This->dwAspects;
2643         if( pAdvf )
2644                 *pAdvf = This->dwAdvf;
2645
2646         return S_OK;
2647 }
2648
2649
2650 static const IViewObjectVtbl vovt =
2651 {
2652         ISVViewObject_QueryInterface,
2653         ISVViewObject_AddRef,
2654         ISVViewObject_Release,
2655         ISVViewObject_Draw,
2656         ISVViewObject_GetColorSet,
2657         ISVViewObject_Freeze,
2658         ISVViewObject_Unfreeze,
2659         ISVViewObject_SetAdvise,
2660         ISVViewObject_GetAdvise
2661 };
2662
2663 /* IFolderView */
2664 static HRESULT WINAPI IFView_QueryInterface(
2665         IFolderView *iface,
2666         REFIID riid,
2667         LPVOID *ppvObj)
2668 {
2669         IShellViewImpl *This = impl_from_IFolderView(iface);
2670         TRACE("(%p)->(IID:%s,%p)\n", This, debugstr_guid(riid), ppvObj);
2671         return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2672 }
2673
2674 static ULONG WINAPI IFView_AddRef( IFolderView *iface)
2675 {
2676         IShellViewImpl *This = impl_from_IFolderView(iface);
2677         TRACE("(%p)->(count=%u)\n", This, This->ref);
2678         return IShellView2_AddRef((IShellView2*)This);
2679 }
2680
2681 static ULONG WINAPI IFView_Release( IFolderView *iface)
2682 {
2683         IShellViewImpl *This = impl_from_IFolderView(iface);
2684         TRACE("(%p)->(count=%u)\n", This, This->ref);
2685         return IShellView2_Release((IShellView2*)This);
2686 }
2687
2688 static HRESULT WINAPI IFView_GetCurrentViewMode(IFolderView *iface, UINT *mode)
2689 {
2690         IShellViewImpl *This = impl_from_IFolderView(iface);
2691         FIXME("(%p)->(%p), stub\n", This, mode);
2692         return E_NOTIMPL;
2693 }
2694
2695 static HRESULT WINAPI IFView_SetCurrentViewMode(IFolderView *iface, UINT mode)
2696 {
2697         IShellViewImpl *This = impl_from_IFolderView(iface);
2698         FIXME("(%p)->(%u), stub\n", This, mode);
2699         return E_NOTIMPL;
2700 }
2701
2702 static HRESULT WINAPI IFView_GetFolder(IFolderView *iface, REFIID riid, void **ppv)
2703 {
2704         IShellViewImpl *This = impl_from_IFolderView(iface);
2705         FIXME("(%p)->(%s, %p), stub\n", This, debugstr_guid(riid), ppv);
2706         return E_NOTIMPL;
2707 }
2708
2709 static HRESULT WINAPI IFView_Item(IFolderView *iface, int index, PITEMID_CHILD *ppidl)
2710 {
2711         IShellViewImpl *This = impl_from_IFolderView(iface);
2712         FIXME("(%p)->(%d %p), stub\n", This, index, ppidl);
2713         return E_NOTIMPL;
2714 }
2715
2716 static HRESULT WINAPI IFView_ItemCount(IFolderView *iface, UINT flags, int *items)
2717 {
2718         IShellViewImpl *This = impl_from_IFolderView(iface);
2719         FIXME("(%p)->(%u %p), stub\n", This, flags, items);
2720         return E_NOTIMPL;
2721 }
2722
2723 static HRESULT WINAPI IFView_Items(IFolderView *iface, UINT flags, REFIID riid, void **ppv)
2724 {
2725         IShellViewImpl *This = impl_from_IFolderView(iface);
2726         FIXME("(%p)->(%u %s %p), stub\n", This, flags, debugstr_guid(riid), ppv);
2727         return E_NOTIMPL;
2728 }
2729
2730 static HRESULT WINAPI IFView_GetSelectionMarkedItem(IFolderView *iface, int *item)
2731 {
2732         IShellViewImpl *This = impl_from_IFolderView(iface);
2733         FIXME("(%p)->(%p), stub\n", This, item);
2734         return E_NOTIMPL;
2735 }
2736
2737 static HRESULT WINAPI IFView_GetFocusedItem(IFolderView *iface, int *item)
2738 {
2739         IShellViewImpl *This = impl_from_IFolderView(iface);
2740         FIXME("(%p)->(%p), stub\n", This, item);
2741         return E_NOTIMPL;
2742 }
2743
2744 static HRESULT WINAPI IFView_GetItemPosition(IFolderView *iface, PCUITEMID_CHILD pidl, POINT *ppt)
2745 {
2746         IShellViewImpl *This = impl_from_IFolderView(iface);
2747         FIXME("(%p)->(%p %p), stub\n", This, pidl, ppt);
2748         return E_NOTIMPL;
2749 }
2750
2751 static HRESULT WINAPI IFView_GetSpacing(IFolderView *iface, POINT *pt)
2752 {
2753         IShellViewImpl *This = impl_from_IFolderView(iface);
2754         FIXME("(%p)->(%p), stub\n", This, pt);
2755         return E_NOTIMPL;
2756 }
2757
2758 static HRESULT WINAPI IFView_GetDefaultSpacing(IFolderView *iface, POINT *pt)
2759 {
2760         IShellViewImpl *This = impl_from_IFolderView(iface);
2761         FIXME("(%p)->(%p), stub\n", This, pt);
2762         return E_NOTIMPL;
2763 }
2764
2765 static HRESULT WINAPI IFView_GetAutoArrange(IFolderView *iface)
2766 {
2767         IShellViewImpl *This = impl_from_IFolderView(iface);
2768         FIXME("(%p), stub\n", This);
2769         return E_NOTIMPL;
2770 }
2771
2772 static HRESULT WINAPI IFView_SelectItem(IFolderView *iface, int item, DWORD flags)
2773 {
2774     IShellViewImpl *This = impl_from_IFolderView(iface);
2775     LVITEMW lvItem;
2776
2777     TRACE("(%p)->(%d, %x)\n", This, item, flags);
2778
2779     lvItem.state = 0;
2780     lvItem.stateMask = LVIS_SELECTED;
2781
2782     if (flags & SVSI_ENSUREVISIBLE)
2783         SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, item, 0);
2784
2785     /* all items */
2786     if (flags & SVSI_DESELECTOTHERS)
2787         SendMessageW(This->hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem);
2788
2789     /* this item */
2790     if (flags & SVSI_SELECT)
2791         lvItem.state |= LVIS_SELECTED;
2792
2793     if (flags & SVSI_FOCUSED)
2794         lvItem.stateMask |= LVIS_FOCUSED;
2795
2796     SendMessageW(This->hWndList, LVM_SETITEMSTATE, item, (LPARAM)&lvItem);
2797
2798     if (flags & SVSI_EDIT)
2799         SendMessageW(This->hWndList, LVM_EDITLABELW, item, 0);
2800
2801     return S_OK;
2802 }
2803
2804 static HRESULT WINAPI IFView_SelectAndPositionItems(IFolderView *iface, UINT cidl,
2805                                      PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD flags)
2806 {
2807         IShellViewImpl *This = impl_from_IFolderView(iface);
2808         FIXME("(%p)->(%u %p %p %x), stub\n", This, cidl, apidl, apt, flags);
2809         return E_NOTIMPL;
2810 }
2811
2812 static const IFolderViewVtbl fviewvt =
2813 {
2814         IFView_QueryInterface,
2815         IFView_AddRef,
2816         IFView_Release,
2817         IFView_GetCurrentViewMode,
2818         IFView_SetCurrentViewMode,
2819         IFView_GetFolder,
2820         IFView_Item,
2821         IFView_ItemCount,
2822         IFView_Items,
2823         IFView_GetSelectionMarkedItem,
2824         IFView_GetFocusedItem,
2825         IFView_GetItemPosition,
2826         IFView_GetSpacing,
2827         IFView_GetDefaultSpacing,
2828         IFView_GetAutoArrange,
2829         IFView_SelectItem,
2830         IFView_SelectAndPositionItems
2831 };