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