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