xref: /reactos/dll/win32/shell32/CDefView.cpp (revision 92aabb07)
1 /*
2  *    ShellView
3  *
4  *    Copyright 1998,1999    <juergen.schmied@debitel.net>
5  *
6  * This is the view visualizing the data provided 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
24  */
25 
26 /*
27 TODO:
28 - Load/Save the view state from/into the stream provided by the ShellBrowser.
29 - When editing starts on item, set edit text to for editing value.
30 - Fix shell view to handle view mode popup exec.
31 - The background context menu should have a pidl just like foreground menus. This
32    causes crashes when dynamic handlers try to use the NULL pidl.
33 - Reorder of columns doesn't work - might be bug in comctl32
34 */
35 
36 #include "precomp.h"
37 
38 #include <atlwin.h>
39 #include <rosctrls.h>
40 
41 WINE_DEFAULT_DEBUG_CHANNEL(shell);
42 
43 #undef SV_CLASS_NAME
44 
45 static const WCHAR SV_CLASS_NAME[] = {'S', 'H', 'E', 'L', 'L', 'D', 'L', 'L', '_', 'D', 'e', 'f', 'V', 'i', 'e', 'w', 0};
46 
47 typedef struct
48 {
49     BOOL    bIsAscending;
50     INT     nHeaderID;
51     INT     nLastHeaderID;
52 } LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
53 
54 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
55 
56 /* For the context menu of the def view, the id of the items are based on 1 because we need
57    to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled */
58 #define CONTEXT_MENU_BASE_ID 1
59 
60 class CDefView :
61     public CWindowImpl<CDefView, CWindow, CControlWinTraits>,
62     public CComObjectRootEx<CComMultiThreadModelNoCS>,
63     public IShellView2,
64     public IFolderView,
65     public IShellFolderView,
66     public IOleCommandTarget,
67     public IDropTarget,
68     public IDropSource,
69     public IViewObject,
70     public IServiceProvider
71 {
72     private:
73         CComPtr<IShellFolder>     m_pSFParent;
74         CComPtr<IShellFolder2>    m_pSF2Parent;
75         CComPtr<IShellFolderViewCB> m_pShellFolderViewCB;
76         CComPtr<IShellBrowser>    m_pShellBrowser;
77         CComPtr<ICommDlgBrowser>  m_pCommDlgBrowser;
78         CComPtr<IShellFolderViewDual> m_pShellFolderViewDual;
79         CListView                 m_ListView;
80         HWND                      m_hWndParent;
81         FOLDERSETTINGS            m_FolderSettings;
82         HMENU                     m_hMenu;                /* Handle to the menu bar of the browser */
83         HMENU                     m_hMenuArrangeModes;    /* Handle to the popup menu with the arrange modes */
84         HMENU                     m_hMenuViewModes;       /* Handle to the popup menu with the view modes */
85         HMENU                     m_hContextMenu;         /* Handle to the open context menu */
86         BOOL                      m_bmenuBarInitialized;
87         UINT                      m_uState;
88         UINT                      m_cidl;
89         PCUITEMID_CHILD          *m_apidl;
90         PIDLIST_ABSOLUTE          m_pidlParent;
91         LISTVIEW_SORT_INFO        m_sortInfo;
92         ULONG                     m_hNotify;            /* Change notification handle */
93         HACCEL                    m_hAccel;
94         DWORD                     m_dwAspects;
95         DWORD                     m_dwAdvf;
96         CComPtr<IAdviseSink>      m_pAdvSink;
97         // for drag and drop
98         CComPtr<IDataObject>      m_pSourceDataObject;
99         CComPtr<IDropTarget>      m_pCurDropTarget;     /* The sub-item, which is currently dragged over */
100         CComPtr<IDataObject>      m_pCurDataObject;     /* The dragged data-object */
101         LONG                      m_iDragOverItem;      /* Dragged over item's index, iff m_pCurDropTarget != NULL */
102         UINT                      m_cScrollDelay;       /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
103         POINT                     m_ptLastMousePos;     /* Mouse position at last DragOver call */
104         POINT                     m_ptFirstMousePos;    /* Mouse position when the drag operation started */
105         DWORD                     m_grfKeyState;
106         //
107         CComPtr<IContextMenu>     m_pCM;
108 
109         BOOL                      m_isEditing;
110 
111         CLSID m_Category;
112         BOOL  m_Destroyed;
113         SFVM_CUSTOMVIEWINFO_DATA  m_viewinfo_data;
114 
115     private:
116         HRESULT _MergeToolbar();
117         BOOL _Sort();
118         HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
119 
120     public:
121         CDefView();
122         ~CDefView();
123         HRESULT WINAPI Initialize(IShellFolder *shellFolder);
124         HRESULT IncludeObject(PCUITEMID_CHILD pidl);
125         HRESULT OnDefaultCommand();
126         HRESULT OnStateChange(UINT uFlags);
127         void UpdateStatusbar();
128         void CheckToolbar();
129         BOOL CreateList();
130         void UpdateListColors();
131         BOOL InitList();
132         HRESULT DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
133         static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
134 
135         PCUITEMID_CHILD _PidlByItem(int i);
136         PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem);
137         int LV_FindItemByPidl(PCUITEMID_CHILD pidl);
138         int LV_AddItem(PCUITEMID_CHILD pidl);
139         BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl);
140         BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew);
141         BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl);
142         static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg);
143         HRESULT FillList();
144         HRESULT FillFileMenu();
145         HRESULT FillEditMenu();
146         HRESULT FillViewMenu();
147         HRESULT FillArrangeAsMenu(HMENU hmenuArrange);
148         HRESULT CheckViewMode(HMENU hmenuView);
149         UINT GetSelections();
150         HRESULT OpenSelectedItems();
151         void OnDeactivate();
152         void DoActivate(UINT uState);
153         HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
154         HRESULT InvokeContextMenuCommand(UINT uCommand);
155         LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
156 
157         // *** IOleWindow methods ***
158         virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
159         virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
160 
161         // *** IShellView methods ***
162         virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg);
163         virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable);
164         virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState);
165         virtual HRESULT STDMETHODCALLTYPE Refresh();
166         virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd);
167         virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow();
168         virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs);
169         virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam);
170         virtual HRESULT STDMETHODCALLTYPE SaveViewState();
171         virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags);
172         virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv);
173 
174         // *** IShellView2 methods ***
175         virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type);
176         virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params);
177         virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl);
178         virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point);
179 
180         // *** IShellView3 methods ***
181         virtual HRESULT STDMETHODCALLTYPE CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd);
182 
183         // *** IFolderView methods ***
184         virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode);
185         virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode);
186         virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv);
187         virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, PITEMID_CHILD *ppidl);
188         virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems);
189         virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv);
190         virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem);
191         virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem);
192         virtual HRESULT STDMETHODCALLTYPE GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt);
193         virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt);
194         virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt);
195         virtual HRESULT STDMETHODCALLTYPE GetAutoArrange();
196         virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags);
197         virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags);
198 
199         // *** IShellFolderView methods ***
200         virtual HRESULT STDMETHODCALLTYPE Rearrange(LPARAM sort);
201         virtual HRESULT STDMETHODCALLTYPE GetArrangeParam(LPARAM *sort);
202         virtual HRESULT STDMETHODCALLTYPE ArrangeGrid();
203         virtual HRESULT STDMETHODCALLTYPE AutoArrange();
204         virtual HRESULT STDMETHODCALLTYPE AddObject(PITEMID_CHILD pidl, UINT *item);
205         virtual HRESULT STDMETHODCALLTYPE GetObject(PITEMID_CHILD *pidl, UINT item);
206         virtual HRESULT STDMETHODCALLTYPE RemoveObject(PITEMID_CHILD pidl, UINT *item);
207         virtual HRESULT STDMETHODCALLTYPE GetObjectCount(UINT *count);
208         virtual HRESULT STDMETHODCALLTYPE SetObjectCount(UINT count, UINT flags);
209         virtual HRESULT STDMETHODCALLTYPE UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item);
210         virtual HRESULT STDMETHODCALLTYPE RefreshObject(PITEMID_CHILD pidl, UINT *item);
211         virtual HRESULT STDMETHODCALLTYPE SetRedraw(BOOL redraw);
212         virtual HRESULT STDMETHODCALLTYPE GetSelectedCount(UINT *count);
213         virtual HRESULT STDMETHODCALLTYPE GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items);
214         virtual HRESULT STDMETHODCALLTYPE IsDropOnSource(IDropTarget *drop_target);
215         virtual HRESULT STDMETHODCALLTYPE GetDragPoint(POINT *pt);
216         virtual HRESULT STDMETHODCALLTYPE GetDropPoint(POINT *pt);
217         virtual HRESULT STDMETHODCALLTYPE MoveIcons(IDataObject *obj);
218         virtual HRESULT STDMETHODCALLTYPE SetItemPos(PCUITEMID_CHILD pidl, POINT *pt);
219         virtual HRESULT STDMETHODCALLTYPE IsBkDropTarget(IDropTarget *drop_target);
220         virtual HRESULT STDMETHODCALLTYPE SetClipboard(BOOL move);
221         virtual HRESULT STDMETHODCALLTYPE SetPoints(IDataObject *obj);
222         virtual HRESULT STDMETHODCALLTYPE GetItemSpacing(ITEMSPACING *spacing);
223         virtual HRESULT STDMETHODCALLTYPE SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb);
224         virtual HRESULT STDMETHODCALLTYPE Select(UINT flags);
225         virtual HRESULT STDMETHODCALLTYPE QuerySupport(UINT *support);
226         virtual HRESULT STDMETHODCALLTYPE SetAutomationObject(IDispatch *disp);
227 
228         // *** IOleCommandTarget methods ***
229         virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[  ], OLECMDTEXT *pCmdText);
230         virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
231 
232         // *** IDropTarget methods ***
233         virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
234         virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
235         virtual HRESULT STDMETHODCALLTYPE DragLeave();
236         virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
237 
238         // *** IDropSource methods ***
239         virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
240         virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect);
241 
242         // *** IViewObject methods ***
243         virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
244                                                HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
245                                                BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue);
246         virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
247                 DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet);
248         virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze);
249         virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze);
250         virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink);
251         virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink);
252 
253         // *** IServiceProvider methods ***
254         virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
255 
256         // Message handlers
257         LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
258         LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
259         LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
260         LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
261         LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
262         LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
263         LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
264         LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
265         LRESULT OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
266         LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
267         LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
268         LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
269         LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
270         LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
271         LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
272         LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
273         LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
274         LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
275         LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
276         LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
277         LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
278 
279         static ATL::CWndClassInfo& GetWndClassInfo()
280         {
281             static ATL::CWndClassInfo wc =
282             {
283                 {   sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc,
284                     0, 0, NULL, NULL,
285                     LoadCursor(NULL, IDC_ARROW), NULL, NULL, SV_CLASS_NAME, NULL
286                 },
287                 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
288             };
289             return wc;
290         }
291 
292         virtual WNDPROC GetWindowProc()
293         {
294             return WindowProc;
295         }
296 
297         static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
298         {
299             CDefView *pThis;
300             LRESULT  result;
301 
302             // Must hold a reference during message handling
303             pThis = reinterpret_cast<CDefView *>(hWnd);
304             pThis->AddRef();
305             result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam);
306             pThis->Release();
307             return result;
308         }
309 
310         BEGIN_MSG_MAP(CDefView)
311         MESSAGE_HANDLER(WM_SIZE, OnSize)
312         MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
313         MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
314         MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate)
315         MESSAGE_HANDLER(WM_NCDESTROY, OnNCDestroy)
316         MESSAGE_HANDLER(WM_CREATE, OnCreate)
317         MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
318         MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
319         MESSAGE_HANDLER(WM_COMMAND, OnCommand)
320         MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify)
321         MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
322         MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem)
323         MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem)
324         MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow)
325         MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
326         MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
327         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
328         MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient)
329         MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
330         MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser)
331         MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
332         MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
333         END_MSG_MAP()
334 
335         BEGIN_COM_MAP(CDefView)
336         // Windows returns E_NOINTERFACE for IOleWindow
337         // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
338         COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView)
339         COM_INTERFACE_ENTRY_IID(IID_CDefView, IShellView)
340         COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2)
341         COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView)
342         COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView)
343         COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
344         COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
345         COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource)
346         COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject)
347         COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
348         END_COM_MAP()
349 };
350 
351 /*menu items */
352 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
353 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
354 #define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
355 
356 #define ID_LISTVIEW     1
357 
358 /*windowsx.h */
359 #define GET_WM_COMMAND_ID(wp, lp)       LOWORD(wp)
360 #define GET_WM_COMMAND_HWND(wp, lp)     (HWND)(lp)
361 #define GET_WM_COMMAND_CMD(wp, lp)      HIWORD(wp)
362 
363 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
364 
365 CDefView::CDefView() :
366     m_ListView(),
367     m_hWndParent(NULL),
368     m_hMenu(NULL),
369     m_hMenuArrangeModes(NULL),
370     m_hMenuViewModes(NULL),
371     m_hContextMenu(NULL),
372     m_bmenuBarInitialized(FALSE),
373     m_uState(0),
374     m_cidl(0),
375     m_apidl(NULL),
376     m_pidlParent(NULL),
377     m_hNotify(0),
378     m_hAccel(NULL),
379     m_dwAspects(0),
380     m_dwAdvf(0),
381     m_iDragOverItem(0),
382     m_cScrollDelay(0),
383     m_isEditing(FALSE),
384     m_Destroyed(FALSE)
385 {
386     ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
387     ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
388     ZeroMemory(&m_ptLastMousePos, sizeof(m_ptLastMousePos));
389     ZeroMemory(&m_Category, sizeof(m_Category));
390     m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT);
391     m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW);
392     m_viewinfo_data.hbmBack = NULL;
393 }
394 
395 CDefView::~CDefView()
396 {
397     TRACE(" destroying IShellView(%p)\n", this);
398 
399     if (m_viewinfo_data.hbmBack)
400     {
401         ::DeleteObject(m_viewinfo_data.hbmBack);
402         m_viewinfo_data.hbmBack = NULL;
403     }
404 
405     if (m_hWnd)
406     {
407         DestroyViewWindow();
408     }
409 
410     SHFree(m_apidl);
411 }
412 
413 HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder)
414 {
415     m_pSFParent = shellFolder;
416     shellFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, &m_pSF2Parent));
417 
418     return S_OK;
419 }
420 
421 /**********************************************************
422  *
423  * ##### helperfunctions for communication with ICommDlgBrowser #####
424  */
425 HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl)
426 {
427     HRESULT ret = S_OK;
428 
429     if (m_pCommDlgBrowser.p != NULL)
430     {
431         TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
432         ret = m_pCommDlgBrowser->IncludeObject(this, pidl);
433         TRACE("-- returns 0x%08x\n", ret);
434     }
435 
436     return ret;
437 }
438 
439 HRESULT CDefView::OnDefaultCommand()
440 {
441     HRESULT ret = S_FALSE;
442 
443     if (m_pCommDlgBrowser.p != NULL)
444     {
445         TRACE("ICommDlgBrowser::OnDefaultCommand\n");
446         ret = m_pCommDlgBrowser->OnDefaultCommand(this);
447         TRACE("-- returns 0x%08x\n", ret);
448     }
449 
450     return ret;
451 }
452 
453 HRESULT CDefView::OnStateChange(UINT uFlags)
454 {
455     HRESULT ret = S_FALSE;
456 
457     if (m_pCommDlgBrowser.p != NULL)
458     {
459         TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
460         ret = m_pCommDlgBrowser->OnStateChange(this, uFlags);
461         TRACE("--\n");
462     }
463 
464     return ret;
465 }
466 /**********************************************************
467  *    set the toolbar of the filedialog buttons
468  *
469  * - activates the buttons from the shellbrowser according to
470  *   the view state
471  */
472 void CDefView::CheckToolbar()
473 {
474     LRESULT result;
475 
476     TRACE("\n");
477 
478     if (m_pCommDlgBrowser != NULL)
479     {
480         m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
481                                       FCIDM_TB_SMALLICON, (m_FolderSettings.ViewMode == FVM_LIST) ? TRUE : FALSE, &result);
482         m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
483                                       FCIDM_TB_REPORTVIEW, (m_FolderSettings.ViewMode == FVM_DETAILS) ? TRUE : FALSE, &result);
484         m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
485                                       FCIDM_TB_SMALLICON, TRUE, &result);
486         m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
487                                       FCIDM_TB_REPORTVIEW, TRUE, &result);
488     }
489 }
490 
491 void CDefView::UpdateStatusbar()
492 {
493     WCHAR szFormat[MAX_PATH] = {0};
494     WCHAR szObjects[MAX_PATH] = {0};
495     UINT cSelectedItems;
496 
497     cSelectedItems = m_ListView.GetSelectedCount();
498     if (cSelectedItems)
499     {
500         LoadStringW(shell32_hInstance, IDS_OBJECTS_SELECTED, szFormat, _countof(szFormat));
501         StringCchPrintfW(szObjects, MAX_PATH, szFormat, cSelectedItems);
502     }
503     else
504     {
505         LoadStringW(shell32_hInstance, IDS_OBJECTS, szFormat, _countof(szFormat));
506         StringCchPrintfW(szObjects, MAX_PATH, szFormat, m_ListView.GetItemCount());
507     }
508     m_pShellBrowser->SetStatusTextSB(szObjects);
509 }
510 
511 /**********************************************************
512  *
513  * ##### helperfunctions for initializing the view #####
514  */
515 
516 /**********************************************************
517 * ShellView_CreateList()
518 *
519 * - creates the list view window
520 */
521 BOOL CDefView::CreateList()
522 {
523     HRESULT hr;
524     DWORD dwStyle, dwExStyle;
525     UINT ViewMode;
526 
527     TRACE("%p\n", this);
528 
529     dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
530               LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE;
531     dwExStyle = WS_EX_CLIENTEDGE;
532 
533     if (m_FolderSettings.fFlags & FWF_DESKTOP)
534         dwStyle |= LVS_ALIGNLEFT;
535     else
536         dwStyle |= LVS_ALIGNTOP | LVS_SHOWSELALWAYS;
537 
538     ViewMode = m_FolderSettings.ViewMode;
539     hr = _DoFolderViewCB(SFVM_DEFVIEWMODE, NULL, (LPARAM)&ViewMode);
540     if (SUCCEEDED(hr))
541     {
542         if (ViewMode >= FVM_FIRST && ViewMode <= FVM_LAST)
543             m_FolderSettings.ViewMode = ViewMode;
544         else
545             ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode, m_FolderSettings.ViewMode);
546     }
547 
548     switch (m_FolderSettings.ViewMode)
549     {
550         case FVM_ICON:
551             dwStyle |= LVS_ICON;
552             break;
553 
554         case FVM_DETAILS:
555             dwStyle |= LVS_REPORT;
556             break;
557 
558         case FVM_SMALLICON:
559             dwStyle |= LVS_SMALLICON;
560             break;
561 
562         case FVM_LIST:
563             dwStyle |= LVS_LIST;
564             break;
565 
566         default:
567             dwStyle |= LVS_LIST;
568             break;
569     }
570 
571     if (m_FolderSettings.fFlags & FWF_AUTOARRANGE)
572         dwStyle |= LVS_AUTOARRANGE;
573 
574     if (m_FolderSettings.fFlags & FWF_DESKTOP)
575         m_FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
576 
577     if (m_FolderSettings.fFlags & FWF_SINGLESEL)
578         dwStyle |= LVS_SINGLESEL;
579 
580     if (m_FolderSettings.fFlags & FWF_NOCLIENTEDGE)
581         dwExStyle &= ~WS_EX_CLIENTEDGE;
582 
583     RECT rcListView = {0,0,0,0};
584     m_ListView.Create(m_hWnd, rcListView, L"FolderView", dwStyle, dwExStyle, ID_LISTVIEW);
585 
586     if (!m_ListView)
587         return FALSE;
588 
589     m_sortInfo.bIsAscending = TRUE;
590     m_sortInfo.nHeaderID = -1;
591     m_sortInfo.nLastHeaderID = -1;
592 
593     /*  UpdateShellSettings(); */
594     return TRUE;
595 }
596 
597 void CDefView::UpdateListColors()
598 {
599     if (m_FolderSettings.fFlags & FWF_DESKTOP)
600     {
601         /* Check if drop shadows option is enabled */
602         BOOL bDropShadow = FALSE;
603         DWORD cbDropShadow = sizeof(bDropShadow);
604 
605         /*
606          * The desktop ListView always take the default desktop colours, by
607          * remaining transparent and letting user32/win32k paint itself the
608          * desktop background color, if any.
609          */
610         m_ListView.SetBkColor(CLR_NONE);
611 
612         SHGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
613                      L"ListviewShadow", NULL, &bDropShadow, &cbDropShadow);
614         if (bDropShadow)
615         {
616             /* Set the icon background transparent */
617             m_ListView.SetTextBkColor(CLR_NONE);
618             m_ListView.SetTextColor(RGB(255, 255, 255));
619             m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT, LVS_EX_TRANSPARENTSHADOWTEXT);
620         }
621         else
622         {
623             /* Set the icon background as the same colour as the desktop */
624             COLORREF crDesktop = GetSysColor(COLOR_DESKTOP);
625             m_ListView.SetTextBkColor(crDesktop);
626             if (GetRValue(crDesktop) + GetGValue(crDesktop) + GetBValue(crDesktop) > 128 * 3)
627                 m_ListView.SetTextColor(RGB(0, 0, 0));
628             else
629                 m_ListView.SetTextColor(RGB(255, 255, 255));
630             m_ListView.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT);
631         }
632     }
633     else
634     {
635         // text background color
636         COLORREF clrTextBack = m_viewinfo_data.clrTextBack;
637         m_ListView.SetTextBkColor(clrTextBack);
638 
639         // text color
640         COLORREF clrText;
641         if (m_viewinfo_data.clrText != CLR_INVALID)
642             clrText = m_viewinfo_data.clrText;
643         else
644             clrText = GetSysColor(COLOR_WINDOWTEXT);
645 
646         m_ListView.SetTextColor(clrText);
647 
648         // Background is painted by the parent via WM_PRINTCLIENT.
649         m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND);
650     }
651 }
652 
653 /**********************************************************
654 * ShellView_InitList()
655 *
656 * - adds all needed columns to the shellview
657 */
658 BOOL CDefView::InitList()
659 {
660     SHELLDETAILS sd;
661     WCHAR szTemp[50];
662     HIMAGELIST big_icons, small_icons;
663 
664     TRACE("%p\n", this);
665 
666     m_ListView.DeleteAllItems();
667 
668     m_hMenuArrangeModes = CreateMenu();
669 
670     if (m_pSF2Parent)
671     {
672         for (int i = 0; 1; i++)
673         {
674             if (FAILED(m_pSF2Parent->GetDetailsOf(NULL, i, &sd)))
675                 break;
676             StrRetToStrNW( szTemp, 50, &sd.str, NULL);
677             m_ListView.InsertColumn(i, szTemp, sd.fmt, sd.cxChar * 8);
678 
679             InsertMenuW(m_hMenuArrangeModes, -1, MF_STRING, 0x30 + i,  szTemp);
680         }
681 
682         InsertMenuW(m_hMenuArrangeModes, -1, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
683     }
684     else
685     {
686         FIXME("no m_pSF2Parent\n");
687     }
688 
689     Shell_GetImageLists(&big_icons, &small_icons);
690     m_ListView.SetImageList(big_icons, LVSIL_NORMAL);
691     m_ListView.SetImageList(small_icons, LVSIL_SMALL);
692 
693     return TRUE;
694 }
695 
696 /*************************************************************************
697  * ShellView_ListViewCompareItems
698  *
699  * Compare Function for the Listview (FileOpen Dialog)
700  *
701  * PARAMS
702  *     lParam1       [I] the first ItemIdList to compare with
703  *     lParam2       [I] the second ItemIdList to compare with
704  *     lpData        [I] The column ID for the header Ctrl to process
705  *
706  * RETURNS
707  *     A negative value if the first item should precede the second,
708  *     a positive value if the first item should follow the second,
709  *     or zero if the two items are equivalent
710  */
711 INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
712 {
713     PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
714     PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
715     CDefView *pThis = reinterpret_cast<CDefView*>(lpData);
716 
717     HRESULT hres = pThis->m_pSFParent->CompareIDs(pThis->m_sortInfo.nHeaderID, pidl1, pidl2);
718     if (FAILED_UNEXPECTEDLY(hres))
719         return 0;
720 
721     SHORT nDiff = HRESULT_CODE(hres);
722     if (!pThis->m_sortInfo.bIsAscending)
723         nDiff = -nDiff;
724     return nDiff;
725 }
726 
727 BOOL CDefView::_Sort()
728 {
729     HWND hHeader;
730     HDITEM hColumn;
731 
732     if (m_ListView.GetWindowLongPtr(GWL_STYLE) & LVS_NOSORTHEADER)
733         return TRUE;
734 
735     hHeader = (HWND)m_ListView.SendMessage(LVM_GETHEADER, 0, 0);
736     ZeroMemory(&hColumn, sizeof(hColumn));
737 
738     /* If the sorting column changed, remove the sorting style from the old column */
739     if ( (m_sortInfo.nLastHeaderID != -1) &&
740          (m_sortInfo.nLastHeaderID != m_sortInfo.nHeaderID) )
741     {
742         hColumn.mask = HDI_FORMAT;
743         Header_GetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn);
744         hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
745         Header_SetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn);
746     }
747 
748     /* Set the sorting style to the new column */
749     hColumn.mask = HDI_FORMAT;
750     Header_GetItem(hHeader, m_sortInfo.nHeaderID, &hColumn);
751 
752     hColumn.fmt &= (m_sortInfo.bIsAscending ? ~HDF_SORTDOWN : ~HDF_SORTUP );
753     hColumn.fmt |= (m_sortInfo.bIsAscending ?  HDF_SORTUP   : HDF_SORTDOWN);
754     Header_SetItem(hHeader, m_sortInfo.nHeaderID, &hColumn);
755 
756     /* Sort the list, using the current values of nHeaderID and bIsAscending */
757     m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
758     return m_ListView.SortItems(ListViewCompareItems, this);
759 }
760 
761 PCUITEMID_CHILD CDefView::_PidlByItem(int i)
762 {
763     return reinterpret_cast<PCUITEMID_CHILD>(m_ListView.GetItemData(i));
764 }
765 
766 PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem)
767 {
768     return reinterpret_cast<PCUITEMID_CHILD>(lvItem.lParam);
769 }
770 
771 /**********************************************************
772 *  LV_FindItemByPidl()
773 */
774 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
775 {
776     int cItems = m_ListView.GetItemCount();
777 
778     for (int i = 0; i<cItems; i++)
779     {
780         PCUITEMID_CHILD currentpidl = _PidlByItem(i);
781         HRESULT hr = m_pSFParent->CompareIDs(0, pidl, currentpidl);
782 
783         if (SUCCEEDED(hr) && !HRESULT_CODE(hr))
784         {
785             return i;
786         }
787     }
788     return -1;
789 }
790 
791 /**********************************************************
792 * LV_AddItem()
793 */
794 int CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
795 {
796     LVITEMW lvItem;
797 
798     TRACE("(%p)(pidl=%p)\n", this, pidl);
799 
800     lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;    /*set the mask*/
801     lvItem.iItem = m_ListView.GetItemCount();             /*add the item to the end of the list*/
802     lvItem.iSubItem = 0;
803     lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/
804     lvItem.pszText = LPSTR_TEXTCALLBACKW;                 /*get text on a callback basis*/
805     lvItem.iImage = I_IMAGECALLBACK;                      /*get the image on a callback basis*/
806     lvItem.stateMask = LVIS_CUT;
807 
808     return m_ListView.InsertItem(&lvItem);
809 }
810 
811 /**********************************************************
812 * LV_DeleteItem()
813 */
814 BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl)
815 {
816     int nIndex;
817 
818     TRACE("(%p)(pidl=%p)\n", this, pidl);
819 
820     nIndex = LV_FindItemByPidl(pidl);
821 
822     return (-1 == m_ListView.DeleteItem(nIndex)) ? FALSE : TRUE;
823 }
824 
825 /**********************************************************
826 * LV_RenameItem()
827 */
828 BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew)
829 {
830     int nItem;
831     LVITEMW lvItem;
832 
833     TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew);
834 
835     nItem = LV_FindItemByPidl(pidlOld);
836 
837     if ( -1 != nItem )
838     {
839         lvItem.mask = LVIF_PARAM;        /* only the pidl */
840         lvItem.iItem = nItem;
841         lvItem.iSubItem = 0;
842         m_ListView.GetItem(&lvItem);
843 
844         SHFree(reinterpret_cast<LPVOID>(lvItem.lParam));
845         lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
846         lvItem.iItem = nItem;
847         lvItem.iSubItem = 0;
848         lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew));    /* set the item's data */
849         lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
850         m_ListView.SetItem(&lvItem);
851         m_ListView.Update(nItem);
852         return TRUE;                    /* FIXME: better handling */
853     }
854 
855     return FALSE;
856 }
857 
858 /**********************************************************
859 * LV_ProdItem()
860 */
861 BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
862 {
863     int nItem;
864     LVITEMW lvItem;
865 
866     TRACE("(%p)(pidl=%p)\n", this, pidl);
867 
868     nItem = LV_FindItemByPidl(pidl);
869 
870     if (-1 != nItem)
871     {
872         lvItem.mask = LVIF_IMAGE;
873         lvItem.iItem = nItem;
874         lvItem.iSubItem = 0;
875         lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
876         m_ListView.SetItem(&lvItem);
877         m_ListView.Update(nItem);
878         return TRUE;
879     }
880 
881     return FALSE;
882 }
883 
884 /**********************************************************
885 * ShellView_FillList()
886 *
887 * - gets the objectlist from the shellfolder
888 * - sorts the list
889 * - fills the list into the view
890 */
891 INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg)
892 {
893     PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr);
894     CDefView *pThis = static_cast<CDefView *>(arg);
895 
896     /* in a commdlg This works as a filemask*/
897     if (pThis->IncludeObject(pidl) == S_OK)
898         pThis->LV_AddItem(pidl);
899 
900     SHFree(pidl);
901     return TRUE;
902 }
903 
904 HRESULT CDefView::FillList()
905 {
906     CComPtr<IEnumIDList> pEnumIDList;
907     PITEMID_CHILD pidl;
908     DWORD         dwFetched;
909     HRESULT       hRes;
910     HDPA          hdpa;
911     DWORD         dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS;
912     DWORD dwValue, cbValue;
913 
914     TRACE("%p\n", this);
915 
916     /* determine if there is a setting to show all the hidden files/folders */
917     dwValue = 1;
918     cbValue = sizeof(dwValue);
919     SHGetValueW(HKEY_CURRENT_USER,
920                 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
921                 L"Hidden", NULL, &dwValue, &cbValue);
922     if (dwValue == 1)
923     {
924         dFlags |= SHCONTF_INCLUDEHIDDEN;
925         m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
926     }
927 
928     dwValue = 0;
929     cbValue = sizeof(dwValue);
930     SHGetValueW(HKEY_CURRENT_USER,
931                 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
932                 L"ShowSuperHidden", NULL, &dwValue, &cbValue);
933     if (dwValue)
934     {
935         dFlags |= SHCONTF_INCLUDESUPERHIDDEN;
936         m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
937     }
938 
939     /* get the itemlist from the shfolder */
940     hRes = m_pSFParent->EnumObjects(m_hWnd, dFlags, &pEnumIDList);
941     if (hRes != S_OK)
942     {
943         if (hRes == S_FALSE)
944             return(NOERROR);
945         return(hRes);
946     }
947 
948     /* create a pointer array */
949     hdpa = DPA_Create(16);
950     if (!hdpa)
951     {
952         return(E_OUTOFMEMORY);
953     }
954 
955     /* copy the items into the array*/
956     while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
957     {
958         if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
959         {
960             SHFree(pidl);
961         }
962     }
963 
964     /*turn the listview's redrawing off*/
965     m_ListView.SetRedraw(FALSE);
966 
967     DPA_DestroyCallback( hdpa, fill_list, this);
968 
969     /* sort the array */
970     if (m_pSF2Parent)
971     {
972         m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL);
973     }
974     else
975     {
976         FIXME("no m_pSF2Parent\n");
977     }
978     m_sortInfo.bIsAscending = TRUE;
979     _Sort();
980 
981     if (m_viewinfo_data.hbmBack)
982     {
983         ::DeleteObject(m_viewinfo_data.hbmBack);
984         m_viewinfo_data.hbmBack = NULL;
985     }
986 
987     // load custom background image and custom text color
988     m_viewinfo_data.cbSize = sizeof(m_viewinfo_data);
989     _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data);
990 
991     /*turn the listview's redrawing back on and force it to draw*/
992     m_ListView.SetRedraw(TRUE);
993 
994     UpdateListColors();
995 
996     if (!(m_FolderSettings.fFlags & FWF_DESKTOP))
997     {
998         // redraw now
999         m_ListView.InvalidateRect(NULL, TRUE);
1000     }
1001 
1002     _DoFolderViewCB(SFVM_LISTREFRESHED, NULL, NULL);
1003 
1004     return S_OK;
1005 }
1006 
1007 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1008 {
1009     m_ListView.UpdateWindow();
1010     bHandled = FALSE;
1011     return 0;
1012 }
1013 
1014 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1015 {
1016     return m_ListView.SendMessageW(uMsg, 0, 0);
1017 }
1018 
1019 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1020 {
1021     if (!m_Destroyed)
1022     {
1023         m_Destroyed = TRUE;
1024         if (m_hMenu)
1025         {
1026             DestroyMenu(m_hMenu);
1027             m_hMenu = NULL;
1028         }
1029         RevokeDragDrop(m_hWnd);
1030         SHChangeNotifyDeregister(m_hNotify);
1031         m_hNotify = NULL;
1032         SHFree(m_pidlParent);
1033         m_pidlParent = NULL;
1034     }
1035     bHandled = FALSE;
1036     return 0;
1037 }
1038 
1039 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1040 {
1041     /* redirect to parent */
1042     if (m_FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT))
1043         return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam);
1044 
1045     bHandled = FALSE;
1046     return 0;
1047 }
1048 
1049 static VOID
1050 DrawTileBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm, INT nWidth, INT nHeight, INT dx, INT dy)
1051 {
1052     INT x0 = prc->left, y0 = prc->top, x1 = prc->right, y1 = prc->bottom;
1053     x0 += dx;
1054     y0 += dy;
1055 
1056     HDC hMemDC = CreateCompatibleDC(hDC);
1057     HGDIOBJ hbmOld = SelectObject(hMemDC, hbm);
1058 
1059     for (INT y = y0; y < y1; y += nHeight)
1060     {
1061         for (INT x = x0; x < x1; x += nWidth)
1062         {
1063             BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
1064         }
1065     }
1066 
1067     SelectObject(hMemDC, hbmOld);
1068     DeleteDC(hMemDC);
1069 }
1070 
1071 LRESULT CDefView::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1072 {
1073     HDC hDC = (HDC)wParam;
1074 
1075     RECT rc;
1076     ::GetClientRect(m_ListView, &rc);
1077 
1078     if (m_viewinfo_data.hbmBack)
1079     {
1080         BITMAP bm;
1081         if (::GetObject(m_viewinfo_data.hbmBack, sizeof(BITMAP), &bm))
1082         {
1083             INT dx = -(::GetScrollPos(m_ListView, SB_HORZ) % bm.bmWidth);
1084             INT dy = -(::GetScrollPos(m_ListView, SB_VERT) % bm.bmHeight);
1085             DrawTileBitmap(hDC, &rc, m_viewinfo_data.hbmBack, bm.bmWidth, bm.bmHeight, dx, dy);
1086         }
1087     }
1088     else
1089     {
1090         FillRect(hDC, &rc, GetSysColorBrush(COLOR_WINDOW));
1091     }
1092 
1093     bHandled = TRUE;
1094 
1095     return TRUE;
1096 }
1097 
1098 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1099 {
1100     /* Update desktop labels color */
1101     UpdateListColors();
1102 
1103     /* Forward WM_SYSCOLORCHANGE to common controls */
1104     return m_ListView.SendMessageW(uMsg, 0, 0);
1105 }
1106 
1107 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1108 {
1109     return reinterpret_cast<LRESULT>(m_pShellBrowser.p);
1110 }
1111 
1112 LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1113 {
1114     this->AddRef();
1115     bHandled = FALSE;
1116     return 0;
1117 }
1118 
1119 LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1120 {
1121     this->Release();
1122     bHandled = FALSE;
1123     return 0;
1124 }
1125 
1126 /**********************************************************
1127 *  ShellView_OnCreate()
1128 */
1129 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1130 {
1131     CComPtr<IDropTarget>     pdt;
1132     SHChangeNotifyEntry      ntreg;
1133     CComPtr<IPersistFolder2> ppf2;
1134 
1135     TRACE("%p\n", this);
1136 
1137     if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt))))
1138     {
1139         if (FAILED(RegisterDragDrop(m_hWnd, pdt)))
1140             ERR("Registering Drag Drop Failed");
1141     }
1142 
1143     /* register for receiving notifications */
1144     m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
1145     if (ppf2)
1146     {
1147         ppf2->GetCurFolder(&m_pidlParent);
1148         ntreg.fRecursive = TRUE;
1149         ntreg.pidl = m_pidlParent;
1150         m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
1151     }
1152 
1153     if (CreateList())
1154     {
1155         if (InitList())
1156         {
1157             FillList();
1158         }
1159     }
1160 
1161     /* _DoFolderViewCB(SFVM_GETNOTIFY, ??  ??) */
1162 
1163     m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
1164 
1165     UpdateStatusbar();
1166 
1167     return S_OK;
1168 }
1169 
1170 /**********************************************************
1171  *    #### Handling of the menus ####
1172  */
1173 
1174 extern "C" DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID);
1175 
1176 HMENU GetSubmenuByID(HMENU hmenu, UINT id)
1177 {
1178     MENUITEMINFOW mii = {sizeof(mii), MIIM_SUBMENU};
1179     if (::GetMenuItemInfoW(hmenu, id, FALSE, &mii))
1180         return mii.hSubMenu;
1181 
1182     return NULL;
1183 }
1184 
1185 /* ReallyGetMenuItemID returns the id of an item even if it opens a submenu,
1186    GetMenuItemID returns -1 if the specified item opens a submenu */
1187 UINT ReallyGetMenuItemID(HMENU hmenu, int i)
1188 {
1189     MENUITEMINFOW mii = {sizeof(mii), MIIM_ID};
1190     if (::GetMenuItemInfoW(hmenu, i, TRUE, &mii))
1191         return mii.wID;
1192 
1193     return UINT_MAX;
1194 }
1195 
1196 HRESULT CDefView::FillFileMenu()
1197 {
1198     HMENU hFileMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_FILE);
1199     if (!hFileMenu)
1200         return E_FAIL;
1201 
1202     /* Cleanup the items added previously */
1203     for (int i = GetMenuItemCount(hFileMenu) - 1; i >= 0; i--)
1204     {
1205         UINT id = GetMenuItemID(hFileMenu, i);
1206         if (id < FCIDM_BROWSERFIRST || id > FCIDM_BROWSERLAST)
1207             DeleteMenu(hFileMenu, i, MF_BYPOSITION);
1208     }
1209 
1210     m_cidl = m_ListView.GetSelectedCount();
1211 
1212     /* Store the context menu in m_pCM and keep it in order to invoke the selected command later on */
1213     HRESULT hr = GetItemObject((m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND),
1214                                IID_PPV_ARG(IContextMenu, &m_pCM));
1215     if (FAILED_UNEXPECTEDLY(hr))
1216         return hr;
1217 
1218     HMENU hmenu = CreatePopupMenu();
1219 
1220     hr = m_pCM->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1221     if (FAILED_UNEXPECTEDLY(hr))
1222         return hr;
1223 
1224     // TODO: filter or something
1225 
1226     Shell_MergeMenus(hFileMenu, hmenu, 0, 0, 0xFFFF, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
1227 
1228     ::DestroyMenu(hmenu);
1229 
1230     return S_OK;
1231 }
1232 
1233 HRESULT CDefView::FillEditMenu()
1234 {
1235     HMENU hEditMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_EDIT);
1236     if (!hEditMenu)
1237         return E_FAIL;
1238 
1239     HMENU hmenuContents = ::LoadMenuW(shell32_hInstance, L"MENU_003");
1240     if (!hmenuContents)
1241         return E_FAIL;
1242 
1243     Shell_MergeMenus(hEditMenu, hmenuContents, 0, 0, 0xFFFF, 0);
1244 
1245     ::DestroyMenu(hmenuContents);
1246 
1247     return S_OK;
1248 }
1249 
1250 HRESULT CDefView::FillViewMenu()
1251 {
1252     HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
1253     if (!hViewMenu)
1254         return E_FAIL;
1255 
1256     m_hMenuViewModes = ::LoadMenuW(shell32_hInstance, L"MENU_001");
1257     if (!m_hMenuViewModes)
1258         return E_FAIL;
1259 
1260     UINT i = SHMenuIndexFromID(hViewMenu, FCIDM_MENU_VIEW_SEP_OPTIONS);
1261     Shell_MergeMenus(hViewMenu, m_hMenuViewModes, i, 0, 0xFFFF, MM_ADDSEPARATOR | MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
1262 
1263     return S_OK;
1264 }
1265 
1266 HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange)
1267 {
1268     /* We only need to fill this once */
1269     if (GetMenuItemID(hmenuArrange, 0) == FCIDM_SHVIEW_AUTOARRANGE)
1270     {
1271         Shell_MergeMenus(hmenuArrange, m_hMenuArrangeModes, 0, 0, 0xFFFF,0);
1272     }
1273 
1274     /* Also check the menu item according to which we sort */
1275     CheckMenuRadioItem(hmenuArrange,
1276                        0x30,
1277                        0x100,
1278                        m_sortInfo.nHeaderID + 0x30,
1279                        MF_BYCOMMAND);
1280 
1281     if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST)
1282     {
1283         EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED);
1284     }
1285     else
1286     {
1287         EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND);
1288 
1289         if (GetAutoArrange() == S_OK)
1290             CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED);
1291     }
1292 
1293 
1294     return S_OK;
1295 }
1296 
1297 HRESULT CDefView::CheckViewMode(HMENU hmenuView)
1298 {
1299     if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST)
1300     {
1301         UINT iItemFirst = FCIDM_SHVIEW_BIGICON;
1302         UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST;
1303         UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST;
1304         CheckMenuRadioItem(hmenuView, iItemFirst, iItemLast, iItem, MF_BYCOMMAND);
1305     }
1306 
1307     return S_OK;
1308 }
1309 
1310 /**********************************************************
1311 *   ShellView_GetSelections()
1312 *
1313 * - fills the m_apidl list with the selected objects
1314 *
1315 * RETURNS
1316 *  number of selected items
1317 */
1318 UINT CDefView::GetSelections()
1319 {
1320     SHFree(m_apidl);
1321 
1322     m_cidl = m_ListView.GetSelectedCount();
1323     m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
1324     if (!m_apidl)
1325     {
1326         m_cidl = 0;
1327         return 0;
1328     }
1329 
1330     TRACE("-- Items selected =%u\n", m_cidl);
1331 
1332     UINT i = 0;
1333     int lvIndex = -1;
1334     while ((lvIndex = m_ListView.GetNextItem(lvIndex,  LVNI_SELECTED)) > -1)
1335     {
1336         m_apidl[i] = _PidlByItem(lvIndex);
1337         i++;
1338         if (i == m_cidl)
1339              break;
1340         TRACE("-- selected Item found\n");
1341     }
1342 
1343     return m_cidl;
1344 }
1345 
1346 HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
1347 {
1348     CMINVOKECOMMANDINFO cmi;
1349 
1350     ZeroMemory(&cmi, sizeof(cmi));
1351     cmi.cbSize = sizeof(cmi);
1352     cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1353     cmi.hwnd = m_hWnd;
1354 
1355     if (GetKeyState(VK_SHIFT) & 0x8000)
1356         cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
1357 
1358     if (GetKeyState(VK_CONTROL) & 0x8000)
1359         cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
1360 
1361     HRESULT hr = m_pCM->InvokeCommand(&cmi);
1362     if (FAILED_UNEXPECTEDLY(hr))
1363         return hr;
1364 
1365     return S_OK;
1366 }
1367 
1368 /**********************************************************
1369  *    ShellView_OpenSelectedItems()
1370  */
1371 HRESULT CDefView::OpenSelectedItems()
1372 {
1373     HMENU hMenu;
1374     UINT uCommand;
1375     HRESULT hResult;
1376 
1377     m_cidl = m_ListView.GetSelectedCount();
1378     if (m_cidl == 0)
1379         return S_OK;
1380 
1381     hResult = OnDefaultCommand();
1382     if (hResult == S_OK)
1383         return hResult;
1384 
1385     hMenu = CreatePopupMenu();
1386     if (!hMenu)
1387         return E_FAIL;
1388 
1389     hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1390     if (FAILED_UNEXPECTEDLY(hResult))
1391         goto cleanup;
1392 
1393     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY);
1394     if (FAILED_UNEXPECTEDLY(hResult))
1395         goto cleanup;
1396 
1397     uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1398     if (uCommand == (UINT)-1)
1399     {
1400         hResult = E_FAIL;
1401         goto cleanup;
1402     }
1403 
1404     InvokeContextMenuCommand(uCommand);
1405 
1406 cleanup:
1407 
1408     if (hMenu)
1409         DestroyMenu(hMenu);
1410 
1411     if (m_pCM)
1412     {
1413         IUnknown_SetSite(m_pCM, NULL);
1414         m_pCM.Release();
1415     }
1416 
1417     return hResult;
1418 }
1419 
1420 /**********************************************************
1421  *    ShellView_DoContextMenu()
1422  */
1423 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1424 {
1425     int     x, y;
1426     UINT    uCommand;
1427     HRESULT hResult;
1428 
1429     TRACE("(%p)\n", this);
1430 
1431     m_hContextMenu = CreatePopupMenu();
1432     if (!m_hContextMenu)
1433         return E_FAIL;
1434 
1435     if (lParam != ~0)   // unless app key (menu key) was pressed
1436     {
1437         x = GET_X_LPARAM(lParam);
1438         y = GET_Y_LPARAM(lParam);
1439 
1440         LV_HITTESTINFO hittest = { { x, y } };
1441         ScreenToClient(&hittest.pt);
1442         m_ListView.HitTest(&hittest);
1443 
1444         // Right-Clicked item is selected? If selected, no selection change.
1445         // If not selected, then reset the selection and select the item.
1446         if ((hittest.flags & LVHT_ONITEM) &&
1447             m_ListView.GetItemState(hittest.iItem, LVIS_SELECTED) != LVIS_SELECTED)
1448         {
1449             SelectItem(hittest.iItem, SVSI_SELECT | SVSI_DESELECTOTHERS | SVSI_ENSUREVISIBLE);
1450         }
1451     }
1452 
1453     m_cidl = m_ListView.GetSelectedCount();
1454 
1455     hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1456     if (FAILED_UNEXPECTEDLY(hResult))
1457         goto cleanup;
1458 
1459     /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */
1460     hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL);
1461     if (FAILED_UNEXPECTEDLY(hResult))
1462         goto cleanup;
1463 
1464     /* There is no position requested, so try to find one */
1465     if (lParam == ~0)
1466     {
1467         HWND hFocus = ::GetFocus();
1468         int lvIndex = -1;
1469         POINT pt;
1470 
1471         if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus))
1472         {
1473             /* Is there an item focused and selected? */
1474             lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED|LVIS_FOCUSED);
1475             /* If not, find the first selected item */
1476             if (lvIndex < 0)
1477                 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED);
1478         }
1479 
1480         /* We got something */
1481         if (lvIndex > -1)
1482         {
1483             /* Let's find the center of the icon */
1484             RECT rc = { LVIR_ICON };
1485             m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc);
1486             pt.x = (rc.right + rc.left) / 2;
1487             pt.y = (rc.bottom + rc.top) / 2;
1488         }
1489         else
1490         {
1491             /* We have to drop it somewhere.. */
1492             pt.x = pt.y = 0;
1493         }
1494 
1495         m_ListView.ClientToScreen(&pt);
1496         x = pt.x;
1497         y = pt.y;
1498     }
1499 
1500     uCommand = TrackPopupMenu(m_hContextMenu,
1501                               TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1502                               x, y, 0, m_hWnd, NULL);
1503     if (uCommand == 0)
1504         goto cleanup;
1505 
1506     if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1507         goto cleanup;
1508 
1509     InvokeContextMenuCommand(uCommand - CONTEXT_MENU_BASE_ID);
1510 
1511 cleanup:
1512     if (m_pCM)
1513     {
1514         IUnknown_SetSite(m_pCM, NULL);
1515         m_pCM.Release();
1516     }
1517 
1518     if (m_hContextMenu)
1519     {
1520         DestroyMenu(m_hContextMenu);
1521         m_hContextMenu = NULL;
1522     }
1523 
1524     return 0;
1525 }
1526 
1527 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1528 {
1529     HRESULT hResult;
1530     HMENU hMenu;
1531 
1532     hMenu = CreatePopupMenu();
1533     if (!hMenu)
1534         return 0;
1535 
1536     hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1537     if (FAILED_UNEXPECTEDLY( hResult))
1538         goto cleanup;
1539 
1540     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1541     if (FAILED_UNEXPECTEDLY( hResult))
1542         goto cleanup;
1543 
1544     InvokeContextMenuCommand(uCommand);
1545 
1546 cleanup:
1547     if (m_pCM)
1548     {
1549         IUnknown_SetSite(m_pCM, NULL);
1550         m_pCM.Release();
1551     }
1552 
1553     if (hMenu)
1554         DestroyMenu(hMenu);
1555 
1556     return 0;
1557 }
1558 
1559 /**********************************************************
1560  *    ##### message handling #####
1561  */
1562 
1563 /**********************************************************
1564 *  ShellView_OnSize()
1565 */
1566 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1567 {
1568     WORD wWidth, wHeight;
1569 
1570     wWidth  = LOWORD(lParam);
1571     wHeight = HIWORD(lParam);
1572 
1573     TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1574 
1575     /* Resize the ListView to fit our window */
1576     if (m_ListView)
1577     {
1578         ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1579     }
1580 
1581     _DoFolderViewCB(SFVM_SIZE, 0, 0);
1582 
1583     return 0;
1584 }
1585 
1586 /**********************************************************
1587 * ShellView_OnDeactivate()
1588 *
1589 * NOTES
1590 *  internal
1591 */
1592 void CDefView::OnDeactivate()
1593 {
1594     TRACE("%p\n", this);
1595 
1596     if (m_uState != SVUIA_DEACTIVATE)
1597     {
1598         // TODO: cleanup menu after deactivation
1599 
1600         m_uState = SVUIA_DEACTIVATE;
1601     }
1602 }
1603 
1604 void CDefView::DoActivate(UINT uState)
1605 {
1606     TRACE("%p uState=%x\n", this, uState);
1607 
1608     /*don't do anything if the state isn't really changing */
1609     if (m_uState == uState)
1610     {
1611         return;
1612     }
1613 
1614     if (uState == SVUIA_DEACTIVATE)
1615     {
1616         OnDeactivate();
1617     }
1618     else
1619     {
1620         if(m_hMenu && !m_bmenuBarInitialized)
1621         {
1622             FillEditMenu();
1623             FillViewMenu();
1624             m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1625             m_bmenuBarInitialized = TRUE;
1626         }
1627 
1628         if (SVUIA_ACTIVATE_FOCUS == uState)
1629         {
1630             m_ListView.SetFocus();
1631         }
1632     }
1633 
1634     m_uState = uState;
1635     TRACE("--\n");
1636 }
1637 
1638 /**********************************************************
1639 * ShellView_OnActivate()
1640 */
1641 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1642 {
1643     DoActivate(SVUIA_ACTIVATE_FOCUS);
1644     return 0;
1645 }
1646 
1647 /**********************************************************
1648 *  ShellView_OnSetFocus()
1649 *
1650 */
1651 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1652 {
1653     TRACE("%p\n", this);
1654 
1655     /* Tell the browser one of our windows has received the focus. This
1656     should always be done before merging menus (OnActivate merges the
1657     menus) if one of our windows has the focus.*/
1658 
1659     m_pShellBrowser->OnViewWindowActive(this);
1660     DoActivate(SVUIA_ACTIVATE_FOCUS);
1661 
1662     /* Set the focus to the listview */
1663     m_ListView.SetFocus();
1664 
1665     /* Notify the ICommDlgBrowser interface */
1666     OnStateChange(CDBOSC_SETFOCUS);
1667 
1668     return 0;
1669 }
1670 
1671 /**********************************************************
1672 * ShellView_OnKillFocus()
1673 */
1674 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1675 {
1676     TRACE("(%p) stub\n", this);
1677 
1678     DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1679     /* Notify the ICommDlgBrowser */
1680     OnStateChange(CDBOSC_KILLFOCUS);
1681 
1682     return 0;
1683 }
1684 
1685 /**********************************************************
1686 * ShellView_OnCommand()
1687 *
1688 * NOTES
1689 *    the CmdID's are the ones from the context menu
1690 */
1691 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1692 {
1693     DWORD dwCmdID;
1694     DWORD dwCmd;
1695     HWND  hwndCmd;
1696     int   nCount;
1697 
1698     dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1699     dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1700     hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1701 
1702     TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1703 
1704     switch (dwCmdID)
1705     {
1706         case FCIDM_SHVIEW_SMALLICON:
1707             m_FolderSettings.ViewMode = FVM_SMALLICON;
1708             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
1709             CheckToolbar();
1710             break;
1711 
1712         case FCIDM_SHVIEW_BIGICON:
1713             m_FolderSettings.ViewMode = FVM_ICON;
1714             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
1715             CheckToolbar();
1716             break;
1717 
1718         case FCIDM_SHVIEW_LISTVIEW:
1719             m_FolderSettings.ViewMode = FVM_LIST;
1720             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
1721             CheckToolbar();
1722             break;
1723 
1724         case FCIDM_SHVIEW_REPORTVIEW:
1725             m_FolderSettings.ViewMode = FVM_DETAILS;
1726             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
1727             CheckToolbar();
1728             break;
1729 
1730         /* the menu-ID's for sorting are 0x30... see shrec.rc */
1731         case 0x30:
1732         case 0x31:
1733         case 0x32:
1734         case 0x33:
1735             m_sortInfo.nHeaderID = dwCmdID - 0x30;
1736             m_sortInfo.bIsAscending = TRUE;
1737             _Sort();
1738             break;
1739 
1740         case FCIDM_SHVIEW_SNAPTOGRID:
1741             //FIXME
1742             break;
1743         case FCIDM_SHVIEW_AUTOARRANGE:
1744             if (GetAutoArrange() == S_OK)
1745                 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0);
1746             else
1747                 AutoArrange();
1748             break;
1749         case FCIDM_SHVIEW_SELECTALL:
1750             m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
1751             break;
1752 
1753         case FCIDM_SHVIEW_INVERTSELECTION:
1754             nCount = m_ListView.GetItemCount();
1755             for (int i=0; i < nCount; i++)
1756                 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
1757             break;
1758 
1759         case FCIDM_SHVIEW_REFRESH:
1760             Refresh();
1761             break;
1762 
1763         case FCIDM_SHVIEW_DELETE:
1764         case FCIDM_SHVIEW_CUT:
1765         case FCIDM_SHVIEW_COPY:
1766         case FCIDM_SHVIEW_RENAME:
1767         case FCIDM_SHVIEW_PROPERTIES:
1768             return OnExplorerCommand(dwCmdID, TRUE);
1769 
1770         case FCIDM_SHVIEW_INSERT:
1771         case FCIDM_SHVIEW_UNDO:
1772         case FCIDM_SHVIEW_INSERTLINK:
1773         case FCIDM_SHVIEW_NEWFOLDER:
1774             return OnExplorerCommand(dwCmdID, FALSE);
1775         default:
1776             /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1777             if (m_pCM && dwCmd == 0)
1778             {
1779                 InvokeContextMenuCommand(dwCmdID);
1780             }
1781     }
1782 
1783     return 0;
1784 }
1785 
1786 static BOOL
1787 SelectExtOnRename(void)
1788 {
1789     HKEY hKey;
1790     LONG error;
1791     DWORD dwValue = FALSE, cbValue;
1792 
1793     error = RegOpenKeyExW(HKEY_CURRENT_USER,
1794                           L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1795                           0, KEY_READ, &hKey);
1796     if (error)
1797         return dwValue;
1798 
1799     cbValue = sizeof(dwValue);
1800     RegQueryValueExW(hKey, L"SelectExtOnRename", NULL, NULL, (LPBYTE)&dwValue, &cbValue);
1801 
1802     RegCloseKey(hKey);
1803     return !!dwValue;
1804 }
1805 
1806 /**********************************************************
1807 * ShellView_OnNotify()
1808 */
1809 
1810 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1811 {
1812     UINT                                CtlID;
1813     LPNMHDR                                lpnmh;
1814     LPNMLISTVIEW                        lpnmlv;
1815     NMLVDISPINFOW                        *lpdi;
1816     PCUITEMID_CHILD                     pidl;
1817     BOOL                                unused;
1818 
1819     CtlID = wParam;
1820     lpnmh = (LPNMHDR)lParam;
1821     lpnmlv = (LPNMLISTVIEW)lpnmh;
1822     lpdi = (NMLVDISPINFOW *)lpnmh;
1823 
1824     TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1825 
1826     switch (lpnmh->code)
1827     {
1828         case NM_SETFOCUS:
1829             TRACE("-- NM_SETFOCUS %p\n", this);
1830             OnSetFocus(0, 0, 0, unused);
1831             break;
1832 
1833         case NM_KILLFOCUS:
1834             TRACE("-- NM_KILLFOCUS %p\n", this);
1835             OnDeactivate();
1836             /* Notify the ICommDlgBrowser interface */
1837             OnStateChange(CDBOSC_KILLFOCUS);
1838             break;
1839 
1840         case NM_CUSTOMDRAW:
1841             TRACE("-- NM_CUSTOMDRAW %p\n", this);
1842             return CDRF_DODEFAULT;
1843 
1844         case NM_RELEASEDCAPTURE:
1845             TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1846             break;
1847 
1848         case NM_CLICK:
1849             TRACE("-- NM_CLICK %p\n", this);
1850             break;
1851 
1852         case NM_RCLICK:
1853             TRACE("-- NM_RCLICK %p\n", this);
1854             break;
1855 
1856         case NM_DBLCLK:
1857             TRACE("-- NM_DBLCLK %p\n", this);
1858             OpenSelectedItems();
1859             break;
1860 
1861         case NM_RETURN:
1862             TRACE("-- NM_RETURN %p\n", this);
1863             OpenSelectedItems();
1864             break;
1865 
1866         case HDN_ENDTRACKW:
1867             TRACE("-- HDN_ENDTRACKW %p\n", this);
1868             /*nColumn1 = m_ListView.GetColumnWidth(0);
1869             nColumn2 = m_ListView.GetColumnWidth(1);*/
1870             break;
1871 
1872         case LVN_DELETEITEM:
1873             TRACE("-- LVN_DELETEITEM %p\n", this);
1874 
1875             /*delete the pidl because we made a copy of it*/
1876             SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1877 
1878             break;
1879 
1880         case LVN_DELETEALLITEMS:
1881             TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1882             return FALSE;
1883 
1884         case LVN_INSERTITEM:
1885             TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1886             break;
1887 
1888         case LVN_ITEMACTIVATE:
1889             TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1890             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1891             break;
1892 
1893         case LVN_COLUMNCLICK:
1894             m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1895             if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1896                 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1897             else
1898                 m_sortInfo.bIsAscending = TRUE;
1899             _Sort();
1900             break;
1901 
1902         case LVN_GETDISPINFOA:
1903         case LVN_GETDISPINFOW:
1904             TRACE("-- LVN_GETDISPINFO %p\n", this);
1905             pidl = _PidlByItem(lpdi->item);
1906 
1907             if (lpdi->item.mask & LVIF_TEXT)    /* text requested */
1908             {
1909                 if (m_pSF2Parent)
1910                 {
1911                     SHELLDETAILS sd;
1912                     if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1913                         break;
1914 
1915                     if (lpnmh->code == LVN_GETDISPINFOA)
1916                     {
1917                         /* shouldn't happen */
1918                         NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1919                         StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1920                         TRACE("-- text=%s\n", lpdiA->item.pszText);
1921                     }
1922                     else /* LVN_GETDISPINFOW */
1923                     {
1924                         StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1925                         TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1926                     }
1927                 }
1928                 else
1929                 {
1930                     FIXME("no m_pSF2Parent\n");
1931                 }
1932             }
1933             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
1934             {
1935                 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1936             }
1937             if(lpdi->item.mask & LVIF_STATE)
1938             {
1939                 ULONG attributes = SFGAO_HIDDEN;
1940                 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
1941                 {
1942                     if (attributes & SFGAO_HIDDEN)
1943                     {
1944                         lpdi->item.state |= LVIS_CUT;
1945                     }
1946                 }
1947             }
1948             lpdi->item.mask |= LVIF_DI_SETITEM;
1949             break;
1950 
1951         case LVN_ITEMCHANGED:
1952             TRACE("-- LVN_ITEMCHANGED %p\n", this);
1953             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1954             UpdateStatusbar();
1955             _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */);
1956             break;
1957 
1958         case LVN_BEGINDRAG:
1959         case LVN_BEGINRDRAG:
1960             TRACE("-- LVN_BEGINDRAG\n");
1961 
1962             if (GetSelections())
1963             {
1964                 CComPtr<IDataObject> pda;
1965                 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK;
1966                 DWORD dwEffect = DROPEFFECT_MOVE;
1967 
1968                 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1969                 {
1970                     LPNMLISTVIEW params = (LPNMLISTVIEW)lParam;
1971 
1972                     if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1973                     {
1974                         dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK);
1975                     }
1976 
1977                     CComPtr<IAsyncOperation> piaso;
1978                     if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1979                     {
1980                         piaso->SetAsyncMode(TRUE);
1981                     }
1982 
1983                     DWORD dwEffect2;
1984 
1985                     m_pSourceDataObject = pda;
1986                     m_ptFirstMousePos = params->ptAction;
1987                     ClientToScreen(&m_ptFirstMousePos);
1988 
1989                     HIMAGELIST big_icons, small_icons;
1990                     Shell_GetImageLists(&big_icons, &small_icons);
1991                     PCUITEMID_CHILD pidl = _PidlByItem(params->iItem);
1992                     int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1993                     POINT ptItem;
1994                     m_ListView.GetItemPosition(params->iItem, &ptItem);
1995 
1996                     ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y);
1997 
1998                     DoDragDrop(pda, this, dwEffect, &dwEffect2);
1999 
2000                     m_pSourceDataObject.Release();
2001                 }
2002             }
2003             break;
2004 
2005         case LVN_BEGINLABELEDITW:
2006         {
2007             DWORD dwAttr = SFGAO_CANRENAME;
2008             pidl = _PidlByItem(lpdi->item);
2009 
2010             TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
2011 
2012             m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
2013             if (SFGAO_CANRENAME & dwAttr)
2014             {
2015                 HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL));
2016                 SHLimitInputEdit(hEdit, m_pSFParent);
2017 
2018                 if (!(dwAttr & SFGAO_LINK) && (lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename())
2019                 {
2020                     LPWSTR pszText = lpdi->item.pszText;
2021                     LPWSTR pchDotExt = PathFindExtensionW(pszText);
2022                     ::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText);
2023                     ::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0);
2024                 }
2025 
2026                 m_isEditing = TRUE;
2027                 return FALSE;
2028             }
2029 
2030             return TRUE;
2031         }
2032 
2033         case LVN_ENDLABELEDITW:
2034         {
2035             TRACE("-- LVN_ENDLABELEDITW %p\n", this);
2036 
2037             m_isEditing = FALSE;
2038 
2039             if (lpdi->item.pszText)
2040             {
2041                 HRESULT hr;
2042                 LVITEMW lvItem;
2043 
2044                 pidl = _PidlByItem(lpdi->item);
2045                 PITEMID_CHILD pidlNew = NULL;
2046                 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
2047 
2048                 if (SUCCEEDED(hr) && pidlNew)
2049                 {
2050                     lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
2051                     lvItem.iItem = lpdi->item.iItem;
2052                     lvItem.iSubItem = 0;
2053                     lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
2054                     lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
2055                     m_ListView.SetItem(&lvItem);
2056                     m_ListView.Update(lpdi->item.iItem);
2057                     return TRUE;
2058                 }
2059             }
2060 
2061             return FALSE;
2062         }
2063 
2064         default:
2065             TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
2066             break;
2067     }
2068 
2069     return 0;
2070 }
2071 
2072 /*
2073  * This is just a quick hack to make the desktop work correctly.
2074  * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
2075  * a folder should know if it should update upon a change notification.
2076  * It is exported by merged folders at a minimum.
2077  */
2078 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
2079 {
2080     if (!pidl1 || !pidl2)
2081         return FALSE;
2082     if (ILIsParent(pidl1, pidl2, TRUE))
2083         return TRUE;
2084 
2085     if (_ILIsDesktop(pidl1))
2086     {
2087         PIDLIST_ABSOLUTE deskpidl;
2088         SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2089         if (ILIsParent(deskpidl, pidl2, TRUE))
2090         {
2091             ILFree(deskpidl);
2092             return TRUE;
2093         }
2094         ILFree(deskpidl);
2095         SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2096         if (ILIsParent(deskpidl, pidl2, TRUE))
2097         {
2098             ILFree(deskpidl);
2099             return TRUE;
2100         }
2101         ILFree(deskpidl);
2102     }
2103     return FALSE;
2104 }
2105 
2106 /**********************************************************
2107 * ShellView_OnChange()
2108 */
2109 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2110 {
2111     PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
2112     BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
2113     BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
2114 
2115     TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
2116 
2117     switch (lParam &~ SHCNE_INTERRUPT)
2118     {
2119         case SHCNE_MKDIR:
2120         case SHCNE_CREATE:
2121             if (bParent0)
2122             {
2123                 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
2124                 {
2125                     LV_AddItem(ILFindLastID(Pidls[0]));
2126                 }
2127                 else
2128                 {
2129                     LV_ProdItem(ILFindLastID(Pidls[0]));
2130                 }
2131             }
2132             break;
2133 
2134         case SHCNE_RMDIR:
2135         case SHCNE_DELETE:
2136             if (bParent0)
2137                 LV_DeleteItem(ILFindLastID(Pidls[0]));
2138             break;
2139 
2140         case SHCNE_RENAMEFOLDER:
2141         case SHCNE_RENAMEITEM:
2142             if (bParent0 && bParent1)
2143                 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
2144             else if (bParent0)
2145                 LV_DeleteItem(ILFindLastID(Pidls[0]));
2146             else if (bParent1)
2147                 LV_AddItem(ILFindLastID(Pidls[1]));
2148             break;
2149 
2150         case SHCNE_UPDATEITEM:
2151             if (bParent0)
2152                 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
2153             break;
2154 
2155         case SHCNE_UPDATEDIR:
2156             Refresh();
2157             break;
2158     }
2159     return TRUE;
2160 }
2161 
2162 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId);
2163 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId);
2164 
2165 /**********************************************************
2166 *  CDefView::OnCustomItem
2167 */
2168 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2169 {
2170     if (!m_pCM.p)
2171     {
2172         /* no menu */
2173         ERR("no menu!!!\n");
2174         return FALSE;
2175     }
2176 
2177     /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to
2178        be changed to a menu identifier offset */
2179     UINT CmdID;
2180     HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID);
2181     if (SUCCEEDED(hres))
2182         SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID);
2183 
2184     /* Forward the message to the IContextMenu2 */
2185     LRESULT result;
2186     hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
2187 
2188     return (SUCCEEDED(hres));
2189 }
2190 
2191 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2192 {
2193     /* Wallpaper setting affects drop shadows effect */
2194     if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
2195         UpdateListColors();
2196 
2197     return S_OK;
2198 }
2199 
2200 /**********************************************************
2201 *  CDefView::OnInitMenuPopup
2202 */
2203 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2204 {
2205     HMENU hmenu = (HMENU) wParam;
2206     int nPos = LOWORD(lParam);
2207     UINT  menuItemId;
2208 
2209     OnCustomItem(uMsg, wParam, lParam, bHandled);
2210 
2211     HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
2212 
2213     /* Lets try to find out what the hell wParam is */
2214     if (hmenu == GetSubMenu(m_hMenu, nPos))
2215         menuItemId = ReallyGetMenuItemID(m_hMenu, nPos);
2216     else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos))
2217         menuItemId = ReallyGetMenuItemID(hViewMenu, nPos);
2218     else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos))
2219         menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos);
2220     else
2221         return FALSE;
2222 
2223     switch (menuItemId)
2224     {
2225     case FCIDM_MENU_FILE:
2226         FillFileMenu();
2227         break;
2228     case FCIDM_MENU_VIEW:
2229     case FCIDM_SHVIEW_VIEW:
2230         CheckViewMode(hmenu);
2231         break;
2232     case FCIDM_SHVIEW_ARRANGE:
2233         FillArrangeAsMenu(hmenu);
2234         break;
2235     }
2236 
2237     return FALSE;
2238 }
2239 
2240 /**********************************************************
2241 *
2242 *
2243 *  The INTERFACE of the IShellView object
2244 *
2245 *
2246 **********************************************************
2247 */
2248 
2249 /**********************************************************
2250 *  ShellView_GetWindow
2251 */
2252 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2253 {
2254     TRACE("(%p)\n", this);
2255 
2256     *phWnd = m_hWnd;
2257 
2258     return S_OK;
2259 }
2260 
2261 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2262 {
2263     FIXME("(%p) stub\n", this);
2264 
2265     return E_NOTIMPL;
2266 }
2267 
2268 /**********************************************************
2269 * IShellView_TranslateAccelerator
2270 *
2271 * FIXME:
2272 *  use the accel functions
2273 */
2274 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2275 {
2276     if (m_isEditing)
2277         return S_FALSE;
2278 
2279     if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2280     {
2281         if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2282             return S_OK;
2283 
2284         TRACE("-- key=0x%04lx\n", lpmsg->wParam) ;
2285     }
2286 
2287     return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2288 }
2289 
2290 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2291 {
2292     FIXME("(%p) stub\n", this);
2293 
2294     return E_NOTIMPL;
2295 }
2296 
2297 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2298 {
2299     // CHAR szName[MAX_PATH];
2300     LRESULT lResult;
2301     int nPartArray[1] = { -1};
2302 
2303     TRACE("(%p)->(state=%x) stub\n", this, uState);
2304 
2305     /* don't do anything if the state isn't really changing */
2306     if (m_uState == uState)
2307     {
2308         return S_OK;
2309     }
2310 
2311     /* OnActivate handles the menu merging and internal state */
2312     DoActivate(uState);
2313 
2314     /* only do This if we are active */
2315     if (uState != SVUIA_DEACTIVATE)
2316     {
2317 
2318         /*
2319             GetFolderPath is not a method of IShellFolder
2320             IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2321         */
2322         /* set the number of parts */
2323         m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2324 
2325         /* set the text for the parts */
2326         /*
2327             m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2328         */
2329     }
2330 
2331     return S_OK;
2332 }
2333 
2334 HRESULT WINAPI CDefView::Refresh()
2335 {
2336     TRACE("(%p)\n", this);
2337 
2338     m_ListView.DeleteAllItems();
2339     FillList();
2340 
2341     return S_OK;
2342 }
2343 
2344 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2345 {
2346     return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT,
2347         (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd);
2348 }
2349 
2350 HRESULT WINAPI CDefView::DestroyViewWindow()
2351 {
2352     TRACE("(%p)\n", this);
2353 
2354     /* Make absolutely sure all our UI is cleaned up */
2355     UIActivate(SVUIA_DEACTIVATE);
2356 
2357     if (m_hAccel)
2358     {
2359         // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2360         m_hAccel = NULL;
2361     }
2362 
2363     if (m_hMenuArrangeModes)
2364     {
2365         DestroyMenu(m_hMenuArrangeModes);
2366         m_hMenuArrangeModes = NULL;
2367     }
2368 
2369     if (m_hMenuViewModes)
2370     {
2371         DestroyMenu(m_hMenuViewModes);
2372         m_hMenuViewModes = NULL;
2373     }
2374 
2375     if (m_hMenu)
2376     {
2377         DestroyMenu(m_hMenu);
2378         m_hMenu = NULL;
2379     }
2380 
2381     if (m_ListView)
2382     {
2383         m_ListView.DestroyWindow();
2384     }
2385 
2386     if (m_hWnd)
2387     {
2388         DestroyWindow();
2389     }
2390 
2391     m_pShellBrowser.Release();
2392     m_pCommDlgBrowser.Release();
2393 
2394     return S_OK;
2395 }
2396 
2397 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2398 {
2399     TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2400           m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2401 
2402     if (!lpfs)
2403         return E_INVALIDARG;
2404 
2405     *lpfs = m_FolderSettings;
2406     return S_OK;
2407 }
2408 
2409 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2410 {
2411     FIXME("(%p) stub\n", this);
2412 
2413     return E_NOTIMPL;
2414 }
2415 
2416 HRESULT WINAPI CDefView::SaveViewState()
2417 {
2418     FIXME("(%p) stub\n", this);
2419 
2420     return S_OK;
2421 }
2422 
2423 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2424 {
2425     int i;
2426 
2427     TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2428 
2429     i = LV_FindItemByPidl(pidl);
2430     if (i == -1)
2431         return S_OK;
2432 
2433     LVITEMW lvItem = {0};
2434     lvItem.mask = LVIF_STATE;
2435     lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2436 
2437     while (m_ListView.GetItem(&lvItem))
2438     {
2439         if (lvItem.iItem == i)
2440         {
2441             if (uFlags & SVSI_SELECT)
2442                 lvItem.state |= LVIS_SELECTED;
2443             else
2444                 lvItem.state &= ~LVIS_SELECTED;
2445 
2446             if (uFlags & SVSI_FOCUSED)
2447                 lvItem.state |= LVIS_FOCUSED;
2448             else
2449                 lvItem.state &= ~LVIS_FOCUSED;
2450         }
2451         else
2452         {
2453             if (uFlags & SVSI_DESELECTOTHERS)
2454             {
2455                 lvItem.state &= ~LVIS_SELECTED;
2456             }
2457             lvItem.state &= ~LVIS_FOCUSED;
2458         }
2459 
2460         m_ListView.SetItem(&lvItem);
2461         lvItem.iItem++;
2462     }
2463 
2464     if (uFlags & SVSI_ENSUREVISIBLE)
2465         m_ListView.EnsureVisible(i, FALSE);
2466 
2467     if((uFlags & SVSI_EDIT) == SVSI_EDIT)
2468         m_ListView.EditLabel(i);
2469 
2470     return S_OK;
2471 }
2472 
2473 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2474 {
2475     HRESULT hr = E_NOINTERFACE;
2476 
2477     TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2478 
2479     if (!ppvOut)
2480         return E_INVALIDARG;
2481 
2482     *ppvOut = NULL;
2483 
2484     switch (uItem)
2485     {
2486         case SVGIO_BACKGROUND:
2487             if (IsEqualIID(riid, IID_IContextMenu))
2488             {
2489                 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut);
2490                 if (FAILED_UNEXPECTEDLY(hr))
2491                     return hr;
2492 
2493                 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2494             }
2495             else if (IsEqualIID(riid, IID_IDispatch))
2496             {
2497                 if (m_pShellFolderViewDual == NULL)
2498                 {
2499                     hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
2500                     if (FAILED_UNEXPECTEDLY(hr))
2501                         return hr;
2502                 }
2503                 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
2504             }
2505             break;
2506 
2507         case SVGIO_SELECTION:
2508             GetSelections();
2509             hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2510             if (FAILED_UNEXPECTEDLY(hr))
2511                 return hr;
2512 
2513             if (IsEqualIID(riid, IID_IContextMenu))
2514                 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2515 
2516             break;
2517     }
2518 
2519     TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2520 
2521     return hr;
2522 }
2523 
2524 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2525 {
2526     TRACE("(%p)->(%p), stub\n", this, pViewMode);
2527 
2528     if (!pViewMode)
2529         return E_INVALIDARG;
2530 
2531     *pViewMode = m_FolderSettings.ViewMode;
2532     return S_OK;
2533 }
2534 
2535 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2536 {
2537     DWORD dwStyle;
2538     TRACE("(%p)->(%u), stub\n", this, ViewMode);
2539 
2540     /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2541     if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2542         return E_INVALIDARG;
2543 
2544     /* Windows before Vista uses LVM_SETVIEW and possibly
2545        LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2546        while later versions seem to accomplish this through other
2547        means. */
2548     switch (ViewMode)
2549     {
2550         case FVM_ICON:
2551             dwStyle = LVS_ICON;
2552             break;
2553         case FVM_DETAILS:
2554             dwStyle = LVS_REPORT;
2555             break;
2556         case FVM_SMALLICON:
2557             dwStyle = LVS_SMALLICON;
2558             break;
2559         case FVM_LIST:
2560             dwStyle = LVS_LIST;
2561             break;
2562         default:
2563         {
2564             FIXME("ViewMode %d not implemented\n", ViewMode);
2565             dwStyle = LVS_LIST;
2566             break;
2567         }
2568     }
2569 
2570     m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle);
2571 
2572     /* This will not necessarily be the actual mode set above.
2573        This mimics the behavior of Windows XP. */
2574     m_FolderSettings.ViewMode = ViewMode;
2575 
2576     return S_OK;
2577 }
2578 
2579 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2580 {
2581     if (m_pSFParent == NULL)
2582         return E_FAIL;
2583 
2584     return m_pSFParent->QueryInterface(riid, ppv);
2585 }
2586 
2587 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2588 {
2589     PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2590     if (pidl)
2591     {
2592         *ppidl = ILClone(pidl);
2593         return S_OK;
2594     }
2595 
2596     *ppidl = 0;
2597     return E_INVALIDARG;
2598 }
2599 
2600 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2601 {
2602     TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2603 
2604     if (uFlags != SVGIO_ALLVIEW)
2605         FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2606 
2607     *pcItems = m_ListView.GetItemCount();
2608 
2609     return S_OK;
2610 }
2611 
2612 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2613 {
2614     return E_NOTIMPL;
2615 }
2616 
2617 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2618 {
2619     TRACE("(%p)->(%p)\n", this, piItem);
2620 
2621     *piItem = m_ListView.GetSelectionMark();
2622 
2623     return S_OK;
2624 }
2625 
2626 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2627 {
2628     TRACE("(%p)->(%p)\n", this, piItem);
2629 
2630     *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2631 
2632     return S_OK;
2633 }
2634 
2635 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2636 {
2637     int lvIndex = LV_FindItemByPidl(pidl);
2638     if (lvIndex == -1 || ppt == NULL)
2639         return E_INVALIDARG;
2640 
2641     m_ListView.GetItemPosition(lvIndex, ppt);
2642     return S_OK;
2643 }
2644 
2645 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2646 {
2647     TRACE("(%p)->(%p)\n", this, ppt);
2648 
2649     if (!m_ListView)
2650         return S_FALSE;
2651 
2652     if (ppt)
2653     {
2654         SIZE spacing;
2655         m_ListView.GetItemSpacing(spacing);
2656 
2657         ppt->x = spacing.cx;
2658         ppt->y = spacing.cy;
2659     }
2660 
2661     return S_OK;
2662 }
2663 
2664 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2665 {
2666     return E_NOTIMPL;
2667 }
2668 
2669 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2670 {
2671     return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE);
2672 }
2673 
2674 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2675 {
2676     LVITEMW lvItem;
2677 
2678     TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2679 
2680     lvItem.state = 0;
2681     lvItem.stateMask = LVIS_SELECTED;
2682 
2683     if (dwFlags & SVSI_ENSUREVISIBLE)
2684         m_ListView.EnsureVisible(iItem, 0);
2685 
2686     /* all items */
2687     if (dwFlags & SVSI_DESELECTOTHERS)
2688         m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2689 
2690     /* this item */
2691     if (dwFlags & SVSI_SELECT)
2692         lvItem.state |= LVIS_SELECTED;
2693 
2694     if (dwFlags & SVSI_FOCUSED)
2695         lvItem.stateMask |= LVIS_FOCUSED;
2696 
2697     m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2698 
2699     if ((dwFlags & SVSI_EDIT) == SVSI_EDIT)
2700         m_ListView.EditLabel(iItem);
2701 
2702     return S_OK;
2703 }
2704 
2705 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2706 {
2707     /* Reset the selection */
2708     m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2709 
2710     int lvIndex;
2711     for (UINT i = 0 ; i < m_cidl; i++)
2712     {
2713         lvIndex = LV_FindItemByPidl(apidl[i]);
2714         if (lvIndex != -1)
2715         {
2716             SelectItem(lvIndex, dwFlags);
2717             m_ListView.SetItemPosition(lvIndex, &apt[i]);
2718         }
2719     }
2720 
2721     return S_OK;
2722 }
2723 
2724 /**********************************************************
2725  * IShellView2 implementation
2726  */
2727 
2728 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
2729 {
2730     FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
2731     return E_NOTIMPL;
2732 }
2733 
2734 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
2735 {
2736     return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev,
2737         SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags,
2738         (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView);
2739 }
2740 
2741 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd)
2742 {
2743     OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2744 
2745     *hwnd = NULL;
2746 
2747     TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags);
2748     if (prcView != NULL)
2749         TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2750 
2751     /* Validate the Shell Browser */
2752     if (psb == NULL || m_hWnd)
2753         return E_UNEXPECTED;
2754 
2755     if (view_flags != SV3CVW3_DEFAULT)
2756         FIXME("unsupported view flags 0x%08x\n", view_flags);
2757 
2758     /* Set up the member variables */
2759     m_pShellBrowser = psb;
2760     m_FolderSettings.ViewMode = mode;
2761     m_FolderSettings.fFlags = mask & flags;
2762 
2763     if (view_id)
2764     {
2765         if (IsEqualIID(*view_id, VID_LargeIcons))
2766             m_FolderSettings.ViewMode = FVM_ICON;
2767         else if (IsEqualIID(*view_id, VID_SmallIcons))
2768             m_FolderSettings.ViewMode = FVM_SMALLICON;
2769         else if (IsEqualIID(*view_id, VID_List))
2770             m_FolderSettings.ViewMode = FVM_LIST;
2771         else if (IsEqualIID(*view_id, VID_Details))
2772             m_FolderSettings.ViewMode = FVM_DETAILS;
2773         else if (IsEqualIID(*view_id, VID_Thumbnails))
2774             m_FolderSettings.ViewMode = FVM_THUMBNAIL;
2775         else if (IsEqualIID(*view_id, VID_Tile))
2776             m_FolderSettings.ViewMode = FVM_TILE;
2777         else if (IsEqualIID(*view_id, VID_ThumbStrip))
2778             m_FolderSettings.ViewMode = FVM_THUMBSTRIP;
2779         else
2780             FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
2781     }
2782 
2783     /* Get our parent window */
2784     m_pShellBrowser->GetWindow(&m_hWndParent);
2785 
2786     /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2787     m_pCommDlgBrowser = NULL;
2788     if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2789     {
2790         TRACE("-- CommDlgBrowser\n");
2791     }
2792 
2793     Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
2794     if (m_hWnd == NULL)
2795         return E_FAIL;
2796 
2797     *hwnd = m_hWnd;
2798 
2799     CheckToolbar();
2800 
2801     if (!*hwnd)
2802         return E_FAIL;
2803 
2804     _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, NULL);
2805 
2806     SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2807     UpdateWindow();
2808 
2809     if (!m_hMenu)
2810     {
2811         m_hMenu = CreateMenu();
2812         m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2813         TRACE("-- after fnInsertMenusSB\n");
2814     }
2815 
2816     _MergeToolbar();
2817 
2818     return S_OK;
2819 }
2820 
2821 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
2822 {
2823     FIXME("(%p)->(%p) stub\n", this, new_pidl);
2824     return E_NOTIMPL;
2825 }
2826 
2827 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
2828 {
2829     FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
2830     return E_NOTIMPL;
2831 }
2832 
2833 /**********************************************************
2834  * IShellFolderView implementation
2835  */
2836 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2837 {
2838     FIXME("(%p)->(%ld) stub\n", this, sort);
2839     return E_NOTIMPL;
2840 }
2841 
2842 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2843 {
2844     FIXME("(%p)->(%p) stub\n", this, sort);
2845     return E_NOTIMPL;
2846 }
2847 
2848 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2849 {
2850     FIXME("(%p) stub\n", this);
2851     return E_NOTIMPL;
2852 }
2853 
2854 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2855 {
2856     m_ListView.ModifyStyle(0, LVS_AUTOARRANGE);
2857     m_ListView.Arrange(LVA_DEFAULT);
2858     return S_OK;
2859 }
2860 
2861 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2862 {
2863     TRACE("(%p)->(%p %p)\n", this, pidl, item);
2864     *item = LV_AddItem(pidl);
2865     return (int)*item >= 0 ? S_OK : E_OUTOFMEMORY;
2866 }
2867 
2868 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2869 {
2870     TRACE("(%p)->(%p %d)\n", this, pidl, item);
2871     return Item(item, pidl);
2872 }
2873 
2874 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2875 {
2876 
2877     TRACE("(%p)->(%p %p)\n", this, pidl, item);
2878 
2879     if (pidl)
2880     {
2881         *item = LV_FindItemByPidl(ILFindLastID(pidl));
2882         m_ListView.DeleteItem(*item);
2883     }
2884     else
2885     {
2886         *item = 0;
2887         m_ListView.DeleteAllItems();
2888     }
2889 
2890     return S_OK;
2891 }
2892 
2893 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2894 {
2895     TRACE("(%p)->(%p)\n", this, count);
2896     *count = m_ListView.GetItemCount();
2897     return S_OK;
2898 }
2899 
2900 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2901 {
2902     FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2903     return E_NOTIMPL;
2904 }
2905 
2906 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2907 {
2908     FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2909     return E_NOTIMPL;
2910 }
2911 
2912 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2913 {
2914     FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2915     return E_NOTIMPL;
2916 }
2917 
2918 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2919 {
2920     TRACE("(%p)->(%d)\n", this, redraw);
2921     m_ListView.SetRedraw(redraw);
2922     return S_OK;
2923 }
2924 
2925 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2926 {
2927     FIXME("(%p)->(%p) stub\n", this, count);
2928     return E_NOTIMPL;
2929 }
2930 
2931 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2932 {
2933     TRACE("(%p)->(%p %p)\n", this, pidl, items);
2934 
2935     *items = GetSelections();
2936 
2937     if (*items)
2938     {
2939         *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2940         if (!*pidl)
2941         {
2942             return E_OUTOFMEMORY;
2943         }
2944 
2945         /* it's documented that caller shouldn't PIDLs, only array itself */
2946         memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2947     }
2948 
2949     return S_OK;
2950 }
2951 
2952 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2953 {
2954     if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) &&
2955         (m_pSourceDataObject.p))
2956     {
2957         return S_OK;
2958     }
2959 
2960     return S_FALSE;
2961 }
2962 
2963 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2964 {
2965     if (!pt)
2966         return E_INVALIDARG;
2967 
2968     *pt = m_ptFirstMousePos;
2969     return S_OK;
2970 }
2971 
2972 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2973 {
2974     FIXME("(%p)->(%p) stub\n", this, pt);
2975     return E_NOTIMPL;
2976 }
2977 
2978 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2979 {
2980     TRACE("(%p)->(%p)\n", this, obj);
2981     return E_NOTIMPL;
2982 }
2983 
2984 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2985 {
2986     FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2987     return E_NOTIMPL;
2988 }
2989 
2990 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2991 {
2992     FIXME("(%p)->(%p) stub\n", this, drop_target);
2993     return E_NOTIMPL;
2994 }
2995 
2996 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2997 {
2998     FIXME("(%p)->(%d) stub\n", this, move);
2999     return E_NOTIMPL;
3000 }
3001 
3002 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
3003 {
3004     FIXME("(%p)->(%p) stub\n", this, obj);
3005     return E_NOTIMPL;
3006 }
3007 
3008 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
3009 {
3010     FIXME("(%p)->(%p) stub\n", this, spacing);
3011     return E_NOTIMPL;
3012 }
3013 
3014 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB  *new_cb, IShellFolderViewCB **old_cb)
3015 {
3016     if (old_cb)
3017         *old_cb = m_pShellFolderViewCB.Detach();
3018 
3019     m_pShellFolderViewCB = new_cb;
3020     return S_OK;
3021 }
3022 
3023 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
3024 {
3025     FIXME("(%p)->(%d) stub\n", this, flags);
3026     return E_NOTIMPL;
3027 }
3028 
3029 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
3030 {
3031     TRACE("(%p)->(%p)\n", this, support);
3032     return S_OK;
3033 }
3034 
3035 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
3036 {
3037     FIXME("(%p)->(%p) stub\n", this, disp);
3038     return E_NOTIMPL;
3039 }
3040 
3041 /**********************************************************
3042  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
3043  */
3044 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
3045 {
3046     FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
3047           this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
3048 
3049     if (!prgCmds)
3050         return E_INVALIDARG;
3051 
3052     for (UINT i = 0; i < cCmds; i++)
3053     {
3054         FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
3055         prgCmds[i].cmdf = 0;
3056     }
3057 
3058     return OLECMDERR_E_UNKNOWNGROUP;
3059 }
3060 
3061 /**********************************************************
3062  * ISVOleCmdTarget_Exec (IOleCommandTarget)
3063  *
3064  * nCmdID is the OLECMDID_* enumeration
3065  */
3066 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
3067 {
3068     FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3069           this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
3070 
3071     if (!pguidCmdGroup)
3072         return OLECMDERR_E_UNKNOWNGROUP;
3073 
3074     if (IsEqualCLSID(*pguidCmdGroup, m_Category))
3075     {
3076         if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
3077         {
3078             if (V_VT(pvaIn) != VT_INT_PTR)
3079                 return OLECMDERR_E_NOTSUPPORTED;
3080 
3081             TPMPARAMS params;
3082             params.cbSize = sizeof(params);
3083             params.rcExclude = *(RECT*) V_INTREF(pvaIn);
3084 
3085             if (m_hMenuViewModes)
3086             {
3087                 /* Duplicate all but the last two items of the view modes menu */
3088                 HMENU hmenuViewPopup = CreatePopupMenu();
3089                 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0);
3090                 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3091                 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3092                 CheckViewMode(hmenuViewPopup);
3093                 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
3094                 ::DestroyMenu(hmenuViewPopup);
3095             }
3096 
3097             // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3098             V_VT(pvaOut) = VT_I4;
3099             V_I4(pvaOut) = 0x403;
3100         }
3101     }
3102 
3103     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
3104             (nCmdID == 0x29) &&
3105             (nCmdexecopt == 4) && pvaOut)
3106         return S_OK;
3107 
3108     if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
3109             (nCmdID == 9) &&
3110             (nCmdexecopt == 0))
3111         return 1;
3112 
3113     return OLECMDERR_E_UNKNOWNGROUP;
3114 }
3115 
3116 /**********************************************************
3117  * ISVDropTarget implementation
3118  */
3119 
3120 /******************************************************************************
3121  * drag_notify_subitem [Internal]
3122  *
3123  * Figure out the shellfolder object, which is currently under the mouse cursor
3124  * and notify it via the IDropTarget interface.
3125  */
3126 
3127 #define SCROLLAREAWIDTH 20
3128 
3129 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3130 {
3131     LONG lResult;
3132     HRESULT hr;
3133     RECT clientRect;
3134 
3135     /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3136        reflects the key state after the user released the button, so we need
3137        to remember the last key state when the button was pressed */
3138     m_grfKeyState = grfKeyState;
3139 
3140     /* Map from global to client coordinates and query the index of the listview-item, which is
3141      * currently under the mouse cursor. */
3142     LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM};
3143     ScreenToClient(&htinfo.pt);
3144     lResult = m_ListView.HitTest(&htinfo);
3145 
3146     /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3147     ::GetClientRect(m_ListView, &clientRect);
3148     if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
3149             (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
3150              htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
3151     {
3152         m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
3153         if (m_cScrollDelay == 0)
3154         {
3155             /* Mouse did hover another 250 ms over the scroll-area */
3156             if (htinfo.pt.x < SCROLLAREAWIDTH)
3157                 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
3158 
3159             if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
3160                 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
3161 
3162             if (htinfo.pt.y < SCROLLAREAWIDTH)
3163                 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
3164 
3165             if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
3166                 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
3167         }
3168     }
3169     else
3170     {
3171         m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
3172     }
3173 
3174     m_ptLastMousePos = htinfo.pt;
3175 
3176     /* We need to check if we drag the selection over itself */
3177     if (lResult != -1 && m_pSourceDataObject.p != NULL)
3178     {
3179         PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3180 
3181         for (UINT i = 0; i < m_cidl; i++)
3182         {
3183             if (pidl == m_apidl[i])
3184             {
3185                 /* The item that is being draged is hovering itself. */
3186                 lResult = -1;
3187                 break;
3188             }
3189         }
3190     }
3191 
3192     /* If we are still over the previous sub-item, notify it via DragOver and return. */
3193     if (m_pCurDropTarget && lResult == m_iDragOverItem)
3194         return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
3195 
3196     /* We've left the previous sub-item, notify it via DragLeave and Release it. */
3197     if (m_pCurDropTarget)
3198     {
3199         PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem);
3200         if (pidl)
3201             SelectItem(pidl, 0);
3202 
3203         m_pCurDropTarget->DragLeave();
3204         m_pCurDropTarget.Release();
3205     }
3206 
3207     m_iDragOverItem = lResult;
3208 
3209     if (lResult == -1)
3210     {
3211         /* We are not above one of the listview's subitems. Bind to the parent folder's
3212          * DropTarget interface. */
3213         hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
3214     }
3215     else
3216     {
3217         /* Query the relative PIDL of the shellfolder object represented by the currently
3218          * dragged over listview-item ... */
3219         PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3220 
3221         /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
3222         hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
3223     }
3224 
3225     IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this);
3226 
3227     /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
3228     if (FAILED(hr))
3229     {
3230         *pdwEffect = DROPEFFECT_NONE;
3231         return hr;
3232     }
3233 
3234     if (m_iDragOverItem != -1)
3235     {
3236         SelectItem(m_iDragOverItem, SVSI_SELECT);
3237     }
3238 
3239     /* Notify the item just entered via DragEnter. */
3240     return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
3241 }
3242 
3243 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3244 {
3245     if (*pdwEffect == DROPEFFECT_NONE)
3246         return S_OK;
3247 
3248     /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3249     m_pCurDataObject = pDataObject;
3250 
3251     HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect);
3252     if (SUCCEEDED(hr))
3253     {
3254         POINT ptClient = {pt.x, pt.y};
3255         ScreenToClient(&ptClient);
3256         ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y);
3257     }
3258 
3259     return hr;
3260 }
3261 
3262 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3263 {
3264     POINT ptClient = {pt.x, pt.y};
3265     ScreenToClient(&ptClient);
3266     ImageList_DragMove(ptClient.x, ptClient.y);
3267     return drag_notify_subitem(grfKeyState, pt, pdwEffect);
3268 }
3269 
3270 HRESULT WINAPI CDefView::DragLeave()
3271 {
3272     ImageList_DragLeave(m_hWnd);
3273 
3274     if (m_pCurDropTarget)
3275     {
3276         m_pCurDropTarget->DragLeave();
3277         m_pCurDropTarget.Release();
3278     }
3279 
3280     if (m_pCurDataObject != NULL)
3281     {
3282         m_pCurDataObject.Release();
3283     }
3284 
3285     m_iDragOverItem = 0;
3286 
3287     return S_OK;
3288 }
3289 
3290 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3291 {
3292     ImageList_DragLeave(m_hWnd);
3293     ImageList_EndDrag();
3294 
3295     if ((IsDropOnSource(NULL) == S_OK) &&
3296         (*pdwEffect & DROPEFFECT_MOVE) &&
3297         (m_grfKeyState & MK_LBUTTON))
3298     {
3299         if (m_pCurDropTarget)
3300         {
3301             m_pCurDropTarget->DragLeave();
3302             m_pCurDropTarget.Release();
3303         }
3304 
3305         /* Restore the selection */
3306         m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
3307         for (UINT i = 0 ; i < m_cidl; i++)
3308             SelectItem(m_apidl[i], SVSI_SELECT);
3309 
3310         /* Reposition the items */
3311         int lvIndex = -1;
3312         while ((lvIndex = m_ListView.GetNextItem(lvIndex,  LVNI_SELECTED)) > -1)
3313         {
3314             POINT ptItem;
3315             if (m_ListView.GetItemPosition(lvIndex, &ptItem))
3316             {
3317                 ptItem.x += pt.x - m_ptFirstMousePos.x;
3318                 ptItem.y += pt.y - m_ptFirstMousePos.y;
3319                 m_ListView.SetItemPosition(lvIndex, &ptItem);
3320             }
3321         }
3322     }
3323     else if (m_pCurDropTarget)
3324     {
3325         m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
3326         m_pCurDropTarget.Release();
3327     }
3328 
3329     m_pCurDataObject.Release();
3330     m_iDragOverItem = 0;
3331     return S_OK;
3332 }
3333 
3334 /**********************************************************
3335  * ISVDropSource implementation
3336  */
3337 
3338 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
3339 {
3340     TRACE("(%p)\n", this);
3341 
3342     if (fEscapePressed)
3343         return DRAGDROP_S_CANCEL;
3344     else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
3345         return DRAGDROP_S_DROP;
3346     else
3347         return S_OK;
3348 }
3349 
3350 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
3351 {
3352     TRACE("(%p)\n", this);
3353 
3354     return DRAGDROP_S_USEDEFAULTCURSORS;
3355 }
3356 
3357 /**********************************************************
3358  * ISVViewObject implementation
3359  */
3360 
3361 HRESULT WINAPI CDefView::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue)
3362 {
3363     FIXME("Stub: this=%p\n", this);
3364 
3365     return E_NOTIMPL;
3366 }
3367 
3368 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
3369 {
3370     FIXME("Stub: this=%p\n", this);
3371 
3372     return E_NOTIMPL;
3373 }
3374 
3375 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
3376 {
3377     FIXME("Stub: this=%p\n", this);
3378 
3379     return E_NOTIMPL;
3380 }
3381 
3382 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3383 {
3384     FIXME("Stub: this=%p\n", this);
3385 
3386     return E_NOTIMPL;
3387 }
3388 
3389 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3390 {
3391     FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink);
3392 
3393     /* FIXME: we set the AdviseSink, but never use it to send any advice */
3394     m_pAdvSink = pAdvSink;
3395     m_dwAspects = aspects;
3396     m_dwAdvf = advf;
3397 
3398     return S_OK;
3399 }
3400 
3401 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3402 {
3403     TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3404 
3405     if (ppAdvSink)
3406     {
3407         *ppAdvSink = m_pAdvSink;
3408         m_pAdvSink.p->AddRef();
3409     }
3410 
3411     if (pAspects)
3412         *pAspects = m_dwAspects;
3413 
3414     if (pAdvf)
3415         *pAdvf = m_dwAdvf;
3416 
3417     return S_OK;
3418 }
3419 
3420 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3421 {
3422     if (IsEqualIID(guidService, SID_IShellBrowser))
3423         return m_pShellBrowser->QueryInterface(riid, ppvObject);
3424     else if(IsEqualIID(guidService, SID_IFolderView))
3425         return QueryInterface(riid, ppvObject);
3426 
3427     return E_NOINTERFACE;
3428 }
3429 
3430 HRESULT CDefView::_MergeToolbar()
3431 {
3432     CComPtr<IExplorerToolbar> ptb;
3433     HRESULT hr = S_OK;
3434 
3435     hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3436     if (FAILED(hr))
3437         return hr;
3438 
3439     m_Category = CGID_DefViewFrame;
3440 
3441     hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3442     if (FAILED(hr))
3443         return hr;
3444 
3445     if (hr == S_FALSE)
3446         return S_OK;
3447 
3448 #if 0
3449     hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3450     if (FAILED(hr))
3451         return hr;
3452 #endif
3453 
3454     return S_OK;
3455 }
3456 
3457 // The default processing of IShellFolderView callbacks
3458 HRESULT CDefView::DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3459 {
3460     // TODO: SFVM_GET_CUSTOMVIEWINFO, SFVM_WINDOWCREATED
3461     TRACE("CDefView::DefMessageSFVCB uMsg=%u\n", uMsg);
3462     return E_NOTIMPL;
3463 }
3464 
3465 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3466 {
3467     HRESULT hr = E_NOTIMPL;
3468 
3469     if (m_pShellFolderViewCB)
3470     {
3471         hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam);
3472     }
3473 
3474     if (hr == E_NOTIMPL)
3475     {
3476         hr = DefMessageSFVCB(uMsg, wParam, lParam);
3477     }
3478 
3479     return hr;
3480 }
3481 
3482 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
3483 {
3484     return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
3485 }
3486 
3487 HRESULT WINAPI SHCreateShellFolderViewEx(
3488     LPCSFV psvcbi,    /* [in] shelltemplate struct */
3489     IShellView **ppsv) /* [out] IShellView pointer */
3490 {
3491     CComPtr<IShellView> psv;
3492     HRESULT hRes;
3493 
3494     TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3495       psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback,
3496       psvcbi->fvm, psvcbi->psvOuter);
3497 
3498     *ppsv = NULL;
3499     hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv));
3500     if (FAILED_UNEXPECTEDLY(hRes))
3501         return hRes;
3502 
3503     *ppsv = psv.Detach();
3504     return hRes;
3505 }
3506 
3507 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv,
3508                         IShellView **ppsv)
3509 {
3510     CComPtr<IShellView> psv;
3511     HRESULT hRes;
3512 
3513     if (!ppsv)
3514         return E_INVALIDARG;
3515 
3516     *ppsv = NULL;
3517 
3518     if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv))
3519         return E_INVALIDARG;
3520 
3521     TRACE("sf=%p outer=%p callback=%p\n",
3522       pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb);
3523 
3524     hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv));
3525     if (FAILED(hRes))
3526         return hRes;
3527 
3528     if (pcsfv->psfvcb)
3529     {
3530         CComPtr<IShellFolderView> sfv;
3531         if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv))))
3532         {
3533             sfv->SetCallback(pcsfv->psfvcb, NULL);
3534         }
3535     }
3536 
3537     *ppsv = psv.Detach();
3538     return hRes;
3539 }
3540