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