Unicodify wineesd.
[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               else
1510                 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1511             }
1512             break;
1513
1514           default:
1515             TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1516             break;
1517         }
1518         return 0;
1519 }
1520
1521 /**********************************************************
1522 * ShellView_OnChange()
1523 */
1524
1525 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1526 {
1527
1528         TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1529         switch(wEventId)
1530         {
1531           case SHCNE_MKDIR:
1532           case SHCNE_CREATE:
1533             LV_AddItem(This, Pidls[0]);
1534             break;
1535           case SHCNE_RMDIR:
1536           case SHCNE_DELETE:
1537             LV_DeleteItem(This, Pidls[0]);
1538             break;
1539           case SHCNE_RENAMEFOLDER:
1540           case SHCNE_RENAMEITEM:
1541             LV_RenameItem(This, Pidls[0], Pidls[1]);
1542             break;
1543           case SHCNE_UPDATEITEM:
1544             break;
1545         }
1546         return TRUE;
1547 }
1548 /**********************************************************
1549 *  ShellView_WndProc
1550 */
1551
1552 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1553 {
1554         IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1555         LPCREATESTRUCTA lpcs;
1556
1557         TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1558
1559         switch (uMessage)
1560         {
1561           case WM_NCCREATE:
1562             lpcs = (LPCREATESTRUCTA)lParam;
1563             pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1564             SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1565             pThis->hWnd = hWnd;        /*set the window handle*/
1566             break;
1567
1568           case WM_SIZE:         return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1569           case WM_SETFOCUS:     return ShellView_OnSetFocus(pThis);
1570           case WM_KILLFOCUS:    return ShellView_OnKillFocus(pThis);
1571           case WM_CREATE:       return ShellView_OnCreate(pThis);
1572           case WM_ACTIVATE:     return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1573           case WM_NOTIFY:       return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1574           case WM_COMMAND:      return ShellView_OnCommand(pThis,
1575                                         GET_WM_COMMAND_ID(wParam, lParam),
1576                                         GET_WM_COMMAND_CMD(wParam, lParam),
1577                                         GET_WM_COMMAND_HWND(wParam, lParam));
1578           case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1579
1580           case WM_CONTEXTMENU:  ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1581                                 return 0;
1582
1583           case WM_SHOWWINDOW:   UpdateWindow(pThis->hWndList);
1584                                 break;
1585
1586           case WM_GETDLGCODE:   return SendMessageA(pThis->hWndList,uMessage,0,0);
1587
1588           case WM_DESTROY:      
1589                                 RevokeDragDrop(pThis->hWnd);
1590                                 SHChangeNotifyDeregister(pThis->hNotify);
1591                                 break;
1592
1593           case WM_ERASEBKGND:
1594             if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1595                 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1596               return 1;
1597             break;
1598         }
1599
1600         return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1601 }
1602 /**********************************************************
1603 *
1604 *
1605 *  The INTERFACE of the IShellView object
1606 *
1607 *
1608 **********************************************************
1609 *  IShellView_QueryInterface
1610 */
1611 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1612 {
1613         IShellViewImpl *This = (IShellViewImpl *)iface;
1614
1615         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1616
1617         *ppvObj = NULL;
1618
1619         if(IsEqualIID(riid, &IID_IUnknown))
1620         {
1621           *ppvObj = This;
1622         }
1623         else if(IsEqualIID(riid, &IID_IShellView))
1624         {
1625           *ppvObj = (IShellView*)This;
1626         }
1627         else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1628         {
1629           *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1630         }
1631         else if(IsEqualIID(riid, &IID_IDropTarget))
1632         {
1633           *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1634         }
1635         else if(IsEqualIID(riid, &IID_IDropSource))
1636         {
1637           *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1638         }
1639         else if(IsEqualIID(riid, &IID_IViewObject))
1640         {
1641           *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1642         }
1643
1644         if(*ppvObj)
1645         {
1646           IUnknown_AddRef( (IUnknown*)*ppvObj );
1647           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1648           return S_OK;
1649         }
1650         TRACE("-- Interface: E_NOINTERFACE\n");
1651         return E_NOINTERFACE;
1652 }
1653
1654 /**********************************************************
1655 *  IShellView_AddRef
1656 */
1657 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1658 {
1659         IShellViewImpl *This = (IShellViewImpl *)iface;
1660         ULONG refCount = InterlockedIncrement(&This->ref);
1661
1662         TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1663
1664         return refCount;
1665 }
1666 /**********************************************************
1667 *  IShellView_Release
1668 */
1669 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1670 {
1671         IShellViewImpl *This = (IShellViewImpl *)iface;
1672         ULONG refCount = InterlockedDecrement(&This->ref);
1673
1674         TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1675
1676         if (!refCount)
1677         {
1678           TRACE(" destroying IShellView(%p)\n",This);
1679
1680           DestroyWindow(This->hWndList);
1681
1682           if(This->pSFParent)
1683             IShellFolder_Release(This->pSFParent);
1684
1685           if(This->pSF2Parent)
1686             IShellFolder2_Release(This->pSF2Parent);
1687
1688           if(This->apidl)
1689             SHFree(This->apidl);
1690
1691           if(This->pAdvSink)
1692             IAdviseSink_Release(This->pAdvSink);
1693
1694           HeapFree(GetProcessHeap(),0,This);
1695         }
1696         return refCount;
1697 }
1698
1699 /**********************************************************
1700 *  ShellView_GetWindow
1701 */
1702 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1703 {
1704         IShellViewImpl *This = (IShellViewImpl *)iface;
1705
1706         TRACE("(%p)\n",This);
1707
1708         *phWnd = This->hWnd;
1709
1710         return S_OK;
1711 }
1712
1713 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1714 {
1715         IShellViewImpl *This = (IShellViewImpl *)iface;
1716
1717         FIXME("(%p) stub\n",This);
1718
1719         return E_NOTIMPL;
1720 }
1721
1722 /**********************************************************
1723 * IShellView_TranslateAccelerator
1724 *
1725 * FIXME:
1726 *  use the accel functions
1727 */
1728 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1729 {
1730 #if 0
1731         IShellViewImpl *This = (IShellViewImpl *)iface;
1732
1733         FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1734 #endif
1735
1736         if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1737         {
1738           TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1739         }
1740         return S_FALSE; /* not handled */
1741 }
1742
1743 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1744 {
1745         IShellViewImpl *This = (IShellViewImpl *)iface;
1746
1747         FIXME("(%p) stub\n",This);
1748
1749         return E_NOTIMPL;
1750 }
1751
1752 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1753 {
1754         IShellViewImpl *This = (IShellViewImpl *)iface;
1755
1756 /*
1757         CHAR    szName[MAX_PATH];
1758 */
1759         LRESULT lResult;
1760         int     nPartArray[1] = {-1};
1761
1762         TRACE("(%p)->(state=%x) stub\n",This, uState);
1763
1764         /*don't do anything if the state isn't really changing*/
1765         if(This->uState == uState)
1766         {
1767           return S_OK;
1768         }
1769
1770         /*OnActivate handles the menu merging and internal state*/
1771         ShellView_OnActivate(This, uState);
1772
1773         /*only do This if we are active*/
1774         if(uState != SVUIA_DEACTIVATE)
1775         {
1776
1777 /*
1778           GetFolderPath is not a method of IShellFolder
1779           IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1780 */
1781           /* set the number of parts */
1782           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1783                                                         (LPARAM)nPartArray, &lResult);
1784
1785           /* set the text for the parts */
1786 /*
1787           IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1788                                                         0, (LPARAM)szName, &lResult);
1789 */
1790         }
1791
1792         return S_OK;
1793 }
1794
1795 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1796 {
1797         IShellViewImpl *This = (IShellViewImpl *)iface;
1798
1799         TRACE("(%p)\n",This);
1800
1801         ListView_DeleteAllItems(This->hWndList);
1802         ShellView_FillList(This);
1803
1804         return S_OK;
1805 }
1806
1807 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1808         IShellView * iface,
1809         IShellView *lpPrevView,
1810         LPCFOLDERSETTINGS lpfs,
1811         IShellBrowser * psb,
1812         RECT * prcView,
1813         HWND  *phWnd)
1814 {
1815         IShellViewImpl *This = (IShellViewImpl *)iface;
1816
1817         WNDCLASSA wc;
1818         *phWnd = 0;
1819
1820
1821         TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1822         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);
1823
1824         /*set up the member variables*/
1825         This->pShellBrowser = psb;
1826         This->FolderSettings = *lpfs;
1827
1828         /*get our parent window*/
1829         IShellBrowser_AddRef(This->pShellBrowser);
1830         IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1831
1832         /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1833         This->pCommDlgBrowser=NULL;
1834         if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1835                         (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1836         {
1837           TRACE("-- CommDlgBrowser\n");
1838         }
1839
1840         /*if our window class has not been registered, then do so*/
1841         if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1842         {
1843           ZeroMemory(&wc, sizeof(wc));
1844           wc.style              = CS_HREDRAW | CS_VREDRAW;
1845           wc.lpfnWndProc        = ShellView_WndProc;
1846           wc.cbClsExtra         = 0;
1847           wc.cbWndExtra         = 0;
1848           wc.hInstance          = shell32_hInstance;
1849           wc.hIcon              = 0;
1850           wc.hCursor            = LoadCursorA (0, (LPSTR)IDC_ARROW);
1851           wc.hbrBackground      = (HBRUSH) (COLOR_WINDOW + 1);
1852           wc.lpszMenuName       = NULL;
1853           wc.lpszClassName      = SV_CLASS_NAME;
1854
1855           if(!RegisterClassA(&wc))
1856             return E_FAIL;
1857         }
1858
1859         *phWnd = CreateWindowExA(0,
1860                                 SV_CLASS_NAME,
1861                                 NULL,
1862                                 WS_CHILD | WS_VISIBLE | WS_TABSTOP,
1863                                 prcView->left,
1864                                 prcView->top,
1865                                 prcView->right - prcView->left,
1866                                 prcView->bottom - prcView->top,
1867                                 This->hWndParent,
1868                                 0,
1869                                 shell32_hInstance,
1870                                 (LPVOID)This);
1871
1872         CheckToolbar(This);
1873
1874         if(!*phWnd) return E_FAIL;
1875
1876         return S_OK;
1877 }
1878
1879 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1880 {
1881         IShellViewImpl *This = (IShellViewImpl *)iface;
1882
1883         TRACE("(%p)\n",This);
1884
1885         /*Make absolutely sure all our UI is cleaned up.*/
1886         IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1887
1888         if(This->hMenu)
1889         {
1890           DestroyMenu(This->hMenu);
1891         }
1892
1893         DestroyWindow(This->hWnd);
1894         if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1895         if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1896
1897
1898         return S_OK;
1899 }
1900
1901 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1902 {
1903         IShellViewImpl *This = (IShellViewImpl *)iface;
1904
1905         TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1906                 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1907
1908         if (!lpfs) return E_INVALIDARG;
1909
1910         *lpfs = This->FolderSettings;
1911         return NOERROR;
1912 }
1913
1914 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1915 {
1916         IShellViewImpl *This = (IShellViewImpl *)iface;
1917
1918         FIXME("(%p) stub\n",This);
1919
1920         return E_NOTIMPL;
1921 }
1922
1923 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1924 {
1925         IShellViewImpl *This = (IShellViewImpl *)iface;
1926
1927         FIXME("(%p) stub\n",This);
1928
1929         return S_OK;
1930 }
1931
1932 static HRESULT WINAPI IShellView_fnSelectItem(
1933         IShellView * iface,
1934         LPCITEMIDLIST pidl,
1935         UINT uFlags)
1936 {
1937         IShellViewImpl *This = (IShellViewImpl *)iface;
1938         int i;
1939
1940         TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1941
1942         i = LV_FindItemByPidl(This, pidl);
1943
1944         if (i != -1)
1945         {
1946           LVITEMA lvItem;
1947
1948           if(uFlags & SVSI_ENSUREVISIBLE)
1949             ListView_EnsureVisible(This->hWndList, i, 0);
1950
1951           ZeroMemory(&lvItem, sizeof(LVITEMA));
1952           lvItem.mask = LVIF_STATE;
1953           lvItem.iItem = 0;
1954
1955           while(ListView_GetItemA(This->hWndList, &lvItem))
1956           {
1957             if (lvItem.iItem == i)
1958             {
1959               if (uFlags & SVSI_SELECT)
1960                 lvItem.state |= LVIS_SELECTED;
1961               else
1962                 lvItem.state &= ~LVIS_SELECTED;
1963
1964               if(uFlags & SVSI_FOCUSED)
1965                 lvItem.state &= ~LVIS_FOCUSED;
1966             }
1967             else
1968             {
1969               if (uFlags & SVSI_DESELECTOTHERS)
1970                 lvItem.state &= ~LVIS_SELECTED;
1971             }
1972             ListView_SetItemA(This->hWndList, &lvItem);
1973             lvItem.iItem++;
1974           }
1975
1976
1977           if(uFlags & SVSI_EDIT)
1978             ListView_EditLabelA(This->hWndList, i);
1979
1980         }
1981         return S_OK;
1982 }
1983
1984 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
1985 {
1986         IShellViewImpl *This = (IShellViewImpl *)iface;
1987
1988         TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
1989
1990         *ppvOut = NULL;
1991
1992         switch(uItem)
1993         {
1994           case SVGIO_BACKGROUND:
1995             *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
1996             break;
1997
1998           case SVGIO_SELECTION:
1999             ShellView_GetSelections(This);
2000             IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2001             break;
2002         }
2003         TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2004
2005         if(!*ppvOut) return E_OUTOFMEMORY;
2006
2007         return S_OK;
2008 }
2009
2010 static const IShellViewVtbl svvt =
2011 {
2012         IShellView_fnQueryInterface,
2013         IShellView_fnAddRef,
2014         IShellView_fnRelease,
2015         IShellView_fnGetWindow,
2016         IShellView_fnContextSensitiveHelp,
2017         IShellView_fnTranslateAccelerator,
2018         IShellView_fnEnableModeless,
2019         IShellView_fnUIActivate,
2020         IShellView_fnRefresh,
2021         IShellView_fnCreateViewWindow,
2022         IShellView_fnDestroyViewWindow,
2023         IShellView_fnGetCurrentInfo,
2024         IShellView_fnAddPropertySheetPages,
2025         IShellView_fnSaveViewState,
2026         IShellView_fnSelectItem,
2027         IShellView_fnGetItemObject
2028 };
2029
2030
2031 /**********************************************************
2032  * ISVOleCmdTarget_QueryInterface (IUnknown)
2033  */
2034 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2035         IOleCommandTarget *     iface,
2036         REFIID                  iid,
2037         LPVOID*                 ppvObj)
2038 {
2039         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2040
2041         return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2042 }
2043
2044 /**********************************************************
2045  * ISVOleCmdTarget_AddRef (IUnknown)
2046  */
2047 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2048         IOleCommandTarget *     iface)
2049 {
2050         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2051
2052         return IShellFolder_AddRef((IShellFolder*)This);
2053 }
2054
2055 /**********************************************************
2056  * ISVOleCmdTarget_Release (IUnknown)
2057  */
2058 static ULONG WINAPI ISVOleCmdTarget_Release(
2059         IOleCommandTarget *     iface)
2060 {
2061         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2062
2063         return IShellFolder_Release((IShellFolder*)This);
2064 }
2065
2066 /**********************************************************
2067  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2068  */
2069 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2070         IOleCommandTarget *iface,
2071         const GUID* pguidCmdGroup,
2072         ULONG cCmds,
2073         OLECMD * prgCmds,
2074         OLECMDTEXT* pCmdText)
2075 {
2076     UINT i;
2077     IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2078
2079     FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2080               This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2081
2082     if (!prgCmds)
2083         return E_POINTER;
2084     for (i = 0; i < cCmds; i++)
2085     {
2086         FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2087         prgCmds[i].cmdf = 0;
2088     }
2089     return OLECMDERR_E_UNKNOWNGROUP;
2090 }
2091
2092 /**********************************************************
2093  * ISVOleCmdTarget_Exec (IOleCommandTarget)
2094  *
2095  * nCmdID is the OLECMDID_* enumeration
2096  */
2097 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2098         IOleCommandTarget *iface,
2099         const GUID* pguidCmdGroup,
2100         DWORD nCmdID,
2101         DWORD nCmdexecopt,
2102         VARIANT* pvaIn,
2103         VARIANT* pvaOut)
2104 {
2105         IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2106
2107         FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2108               This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2109
2110         if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2111            (nCmdID == 0x29) &&
2112            (nCmdexecopt == 4) && pvaOut)
2113            return S_OK;
2114         if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2115            (nCmdID == 9) &&
2116            (nCmdexecopt == 0))
2117            return 1;
2118
2119         return OLECMDERR_E_UNKNOWNGROUP;
2120 }
2121
2122 static const IOleCommandTargetVtbl ctvt =
2123 {
2124         ISVOleCmdTarget_QueryInterface,
2125         ISVOleCmdTarget_AddRef,
2126         ISVOleCmdTarget_Release,
2127         ISVOleCmdTarget_QueryStatus,
2128         ISVOleCmdTarget_Exec
2129 };
2130
2131 /**********************************************************
2132  * ISVDropTarget implementation
2133  */
2134
2135 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2136         IDropTarget *iface,
2137         REFIID riid,
2138         LPVOID *ppvObj)
2139 {
2140         IShellViewImpl *This = impl_from_IDropTarget(iface);
2141
2142         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2143
2144         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2145 }
2146
2147 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2148 {
2149         IShellViewImpl *This = impl_from_IDropTarget(iface);
2150
2151         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2152
2153         return IShellFolder_AddRef((IShellFolder*)This);
2154 }
2155
2156 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2157 {
2158         IShellViewImpl *This = impl_from_IDropTarget(iface);
2159
2160         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2161
2162         return IShellFolder_Release((IShellFolder*)This);
2163 }
2164
2165 static HRESULT WINAPI ISVDropTarget_DragEnter(
2166         IDropTarget     *iface,
2167         IDataObject     *pDataObject,
2168         DWORD           grfKeyState,
2169         POINTL          pt,
2170         DWORD           *pdwEffect)
2171 {
2172
2173         IShellViewImpl *This = impl_from_IDropTarget(iface);
2174
2175         FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
2176
2177         return E_NOTIMPL;
2178 }
2179
2180 static HRESULT WINAPI ISVDropTarget_DragOver(
2181         IDropTarget     *iface,
2182         DWORD           grfKeyState,
2183         POINTL          pt,
2184         DWORD           *pdwEffect)
2185 {
2186         IShellViewImpl *This = impl_from_IDropTarget(iface);
2187
2188         FIXME("Stub: This=%p\n",This);
2189
2190         return E_NOTIMPL;
2191 }
2192
2193 static HRESULT WINAPI ISVDropTarget_DragLeave(
2194         IDropTarget     *iface)
2195 {
2196         IShellViewImpl *This = impl_from_IDropTarget(iface);
2197
2198         FIXME("Stub: This=%p\n",This);
2199
2200         return E_NOTIMPL;
2201 }
2202
2203 static HRESULT WINAPI ISVDropTarget_Drop(
2204         IDropTarget     *iface,
2205         IDataObject*    pDataObject,
2206         DWORD           grfKeyState,
2207         POINTL          pt,
2208         DWORD           *pdwEffect)
2209 {
2210         IShellViewImpl *This = impl_from_IDropTarget(iface);
2211
2212         FIXME("Stub: This=%p\n",This);
2213
2214         return E_NOTIMPL;
2215 }
2216
2217 static const IDropTargetVtbl dtvt =
2218 {
2219         ISVDropTarget_QueryInterface,
2220         ISVDropTarget_AddRef,
2221         ISVDropTarget_Release,
2222         ISVDropTarget_DragEnter,
2223         ISVDropTarget_DragOver,
2224         ISVDropTarget_DragLeave,
2225         ISVDropTarget_Drop
2226 };
2227
2228 /**********************************************************
2229  * ISVDropSource implementation
2230  */
2231
2232 static HRESULT WINAPI ISVDropSource_QueryInterface(
2233         IDropSource *iface,
2234         REFIID riid,
2235         LPVOID *ppvObj)
2236 {
2237         IShellViewImpl *This = impl_from_IDropSource(iface);
2238
2239         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2240
2241         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2242 }
2243
2244 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2245 {
2246         IShellViewImpl *This = impl_from_IDropSource(iface);
2247
2248         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2249
2250         return IShellFolder_AddRef((IShellFolder*)This);
2251 }
2252
2253 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2254 {
2255         IShellViewImpl *This = impl_from_IDropSource(iface);
2256
2257         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2258
2259         return IShellFolder_Release((IShellFolder*)This);
2260 }
2261 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2262         IDropSource *iface,
2263         BOOL fEscapePressed,
2264         DWORD grfKeyState)
2265 {
2266         IShellViewImpl *This = impl_from_IDropSource(iface);
2267         TRACE("(%p)\n",This);
2268
2269         if (fEscapePressed)
2270           return DRAGDROP_S_CANCEL;
2271         else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2272           return DRAGDROP_S_DROP;
2273         else
2274           return NOERROR;
2275 }
2276
2277 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2278         IDropSource *iface,
2279         DWORD dwEffect)
2280 {
2281         IShellViewImpl *This = impl_from_IDropSource(iface);
2282         TRACE("(%p)\n",This);
2283
2284         return DRAGDROP_S_USEDEFAULTCURSORS;
2285 }
2286
2287 static const IDropSourceVtbl dsvt =
2288 {
2289         ISVDropSource_QueryInterface,
2290         ISVDropSource_AddRef,
2291         ISVDropSource_Release,
2292         ISVDropSource_QueryContinueDrag,
2293         ISVDropSource_GiveFeedback
2294 };
2295 /**********************************************************
2296  * ISVViewObject implementation
2297  */
2298
2299 static HRESULT WINAPI ISVViewObject_QueryInterface(
2300         IViewObject *iface,
2301         REFIID riid,
2302         LPVOID *ppvObj)
2303 {
2304         IShellViewImpl *This = impl_from_IViewObject(iface);
2305
2306         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2307
2308         return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2309 }
2310
2311 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2312 {
2313         IShellViewImpl *This = impl_from_IViewObject(iface);
2314
2315         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2316
2317         return IShellFolder_AddRef((IShellFolder*)This);
2318 }
2319
2320 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2321 {
2322         IShellViewImpl *This = impl_from_IViewObject(iface);
2323
2324         TRACE("(%p)->(count=%lu)\n",This,This->ref);
2325
2326         return IShellFolder_Release((IShellFolder*)This);
2327 }
2328
2329 static HRESULT WINAPI ISVViewObject_Draw(
2330         IViewObject     *iface,
2331         DWORD dwDrawAspect,
2332         LONG lindex,
2333         void* pvAspect,
2334         DVTARGETDEVICE* ptd,
2335         HDC hdcTargetDev,
2336         HDC hdcDraw,
2337         LPCRECTL lprcBounds,
2338         LPCRECTL lprcWBounds,
2339         BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2340         ULONG_PTR dwContinue)
2341 {
2342
2343         IShellViewImpl *This = impl_from_IViewObject(iface);
2344
2345         FIXME("Stub: This=%p\n",This);
2346
2347         return E_NOTIMPL;
2348 }
2349 static HRESULT WINAPI ISVViewObject_GetColorSet(
2350         IViewObject     *iface,
2351         DWORD dwDrawAspect,
2352         LONG lindex,
2353         void *pvAspect,
2354         DVTARGETDEVICE* ptd,
2355         HDC hicTargetDevice,
2356         LOGPALETTE** ppColorSet)
2357 {
2358
2359         IShellViewImpl *This = impl_from_IViewObject(iface);
2360
2361         FIXME("Stub: This=%p\n",This);
2362
2363         return E_NOTIMPL;
2364 }
2365 static HRESULT WINAPI ISVViewObject_Freeze(
2366         IViewObject     *iface,
2367         DWORD dwDrawAspect,
2368         LONG lindex,
2369         void* pvAspect,
2370         DWORD* pdwFreeze)
2371 {
2372
2373         IShellViewImpl *This = impl_from_IViewObject(iface);
2374
2375         FIXME("Stub: This=%p\n",This);
2376
2377         return E_NOTIMPL;
2378 }
2379 static HRESULT WINAPI ISVViewObject_Unfreeze(
2380         IViewObject     *iface,
2381         DWORD dwFreeze)
2382 {
2383
2384         IShellViewImpl *This = impl_from_IViewObject(iface);
2385
2386         FIXME("Stub: This=%p\n",This);
2387
2388         return E_NOTIMPL;
2389 }
2390 static HRESULT WINAPI ISVViewObject_SetAdvise(
2391         IViewObject     *iface,
2392         DWORD aspects,
2393         DWORD advf,
2394         IAdviseSink* pAdvSink)
2395 {
2396
2397         IShellViewImpl *This = impl_from_IViewObject(iface);
2398
2399         FIXME("partial stub: %p %08lx %08lx %p\n",
2400               This, aspects, advf, pAdvSink);
2401
2402         /* FIXME: we set the AdviseSink, but never use it to send any advice */
2403         This->pAdvSink = pAdvSink;
2404         This->dwAspects = aspects;
2405         This->dwAdvf = advf;
2406
2407         return S_OK;
2408 }
2409
2410 static HRESULT WINAPI ISVViewObject_GetAdvise(
2411         IViewObject     *iface,
2412         DWORD* pAspects,
2413         DWORD* pAdvf,
2414         IAdviseSink** ppAdvSink)
2415 {
2416
2417         IShellViewImpl *This = impl_from_IViewObject(iface);
2418
2419         TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2420               This, pAspects, pAdvf, ppAdvSink);
2421
2422         if( ppAdvSink )
2423         {
2424                 IAdviseSink_AddRef( This->pAdvSink );
2425                 *ppAdvSink = This->pAdvSink;
2426         }
2427         if( pAspects )
2428                 *pAspects = This->dwAspects;
2429         if( pAdvf )
2430                 *pAdvf = This->dwAdvf;
2431
2432         return S_OK;
2433 }
2434
2435
2436 static const IViewObjectVtbl vovt =
2437 {
2438         ISVViewObject_QueryInterface,
2439         ISVViewObject_AddRef,
2440         ISVViewObject_Release,
2441         ISVViewObject_Draw,
2442         ISVViewObject_GetColorSet,
2443         ISVViewObject_Freeze,
2444         ISVViewObject_Unfreeze,
2445         ISVViewObject_SetAdvise,
2446         ISVViewObject_GetAdvise
2447 };