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