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