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