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