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