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