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