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