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