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