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