xref: /reactos/dll/win32/shell32/CDefView.cpp (revision 1ac9e484)
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         BOOLEAN 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 BOOLEAN 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     if (m_ListView.InsertItem(&lvItem) == -1)
809         return FALSE;
810     else
811         return TRUE;
812 }
813 
814 /**********************************************************
815 * LV_DeleteItem()
816 */
817 BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl)
818 {
819     int nIndex;
820 
821     TRACE("(%p)(pidl=%p)\n", this, pidl);
822 
823     nIndex = LV_FindItemByPidl(pidl);
824 
825     return (-1 == m_ListView.DeleteItem(nIndex)) ? FALSE : TRUE;
826 }
827 
828 /**********************************************************
829 * LV_RenameItem()
830 */
831 BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew)
832 {
833     int nItem;
834     LVITEMW lvItem;
835 
836     TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew);
837 
838     nItem = LV_FindItemByPidl(pidlOld);
839 
840     if ( -1 != nItem )
841     {
842         lvItem.mask = LVIF_PARAM;        /* only the pidl */
843         lvItem.iItem = nItem;
844         lvItem.iSubItem = 0;
845         m_ListView.GetItem(&lvItem);
846 
847         SHFree(reinterpret_cast<LPVOID>(lvItem.lParam));
848         lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
849         lvItem.iItem = nItem;
850         lvItem.iSubItem = 0;
851         lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew));    /* set the item's data */
852         lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
853         m_ListView.SetItem(&lvItem);
854         m_ListView.Update(nItem);
855         return TRUE;                    /* FIXME: better handling */
856     }
857 
858     return FALSE;
859 }
860 
861 /**********************************************************
862 * LV_ProdItem()
863 */
864 BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
865 {
866     int nItem;
867     LVITEMW lvItem;
868 
869     TRACE("(%p)(pidl=%p)\n", this, pidl);
870 
871     nItem = LV_FindItemByPidl(pidl);
872 
873     if (-1 != nItem)
874     {
875         lvItem.mask = LVIF_IMAGE;
876         lvItem.iItem = nItem;
877         lvItem.iSubItem = 0;
878         lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
879         m_ListView.SetItem(&lvItem);
880         m_ListView.Update(nItem);
881         return TRUE;
882     }
883 
884     return FALSE;
885 }
886 
887 /**********************************************************
888 * ShellView_FillList()
889 *
890 * - gets the objectlist from the shellfolder
891 * - sorts the list
892 * - fills the list into the view
893 */
894 INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg)
895 {
896     PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr);
897     CDefView *pThis = static_cast<CDefView *>(arg);
898 
899     /* in a commdlg This works as a filemask*/
900     if (pThis->IncludeObject(pidl) == S_OK)
901         pThis->LV_AddItem(pidl);
902 
903     SHFree(pidl);
904     return TRUE;
905 }
906 
907 HRESULT CDefView::FillList()
908 {
909     CComPtr<IEnumIDList> pEnumIDList;
910     PITEMID_CHILD pidl;
911     DWORD         dwFetched;
912     HRESULT       hRes;
913     HDPA          hdpa;
914     HKEY          hKey;
915     DWORD         dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS;
916 
917     TRACE("%p\n", this);
918 
919     /* determine if there is a setting to show all the hidden files/folders */
920     if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
921     {
922         DWORD dataLength, flagVal;
923 
924         dataLength = sizeof(flagVal);
925         if (RegQueryValueExW(hKey, L"Hidden", NULL, NULL, (LPBYTE)&flagVal, &dataLength) == ERROR_SUCCESS)
926         {
927             /* if the value is 1, then show all hidden files/folders */
928             if (flagVal == 1)
929             {
930                 dFlags |= SHCONTF_INCLUDEHIDDEN;
931                 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
932             }
933         }
934 
935         /* close the key */
936         RegCloseKey(hKey);
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     /* Store the context menu in m_pCM and keep it in order to invoke the selected command later on */
1211     HRESULT hr = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1212     if (FAILED_UNEXPECTEDLY(hr))
1213         return hr;
1214 
1215     HMENU hmenu = CreatePopupMenu();
1216 
1217     hr = m_pCM->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1218     if (FAILED_UNEXPECTEDLY(hr))
1219         return hr;
1220 
1221     // TODO: filter or something
1222 
1223     Shell_MergeMenus(hFileMenu, hmenu, 0, 0, 0xFFFF, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
1224 
1225     ::DestroyMenu(hmenu);
1226 
1227     return S_OK;
1228 }
1229 
1230 HRESULT CDefView::FillEditMenu()
1231 {
1232     HMENU hEditMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_EDIT);
1233     if (!hEditMenu)
1234         return E_FAIL;
1235 
1236     HMENU hmenuContents = ::LoadMenuW(shell32_hInstance, L"MENU_003");
1237     if (!hmenuContents)
1238         return E_FAIL;
1239 
1240     Shell_MergeMenus(hEditMenu, hmenuContents, 0, 0, 0xFFFF, 0);
1241 
1242     ::DestroyMenu(hmenuContents);
1243 
1244     return S_OK;
1245 }
1246 
1247 HRESULT CDefView::FillViewMenu()
1248 {
1249     HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
1250     if (!hViewMenu)
1251         return E_FAIL;
1252 
1253     m_hMenuViewModes = ::LoadMenuW(shell32_hInstance, L"MENU_001");
1254     if (!m_hMenuViewModes)
1255         return E_FAIL;
1256 
1257     UINT i = SHMenuIndexFromID(hViewMenu, FCIDM_MENU_VIEW_SEP_OPTIONS);
1258     Shell_MergeMenus(hViewMenu, m_hMenuViewModes, i, 0, 0xFFFF, MM_ADDSEPARATOR | MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
1259 
1260     return S_OK;
1261 }
1262 
1263 HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange)
1264 {
1265     /* We only need to fill this once */
1266     if (GetMenuItemID(hmenuArrange, 0) == FCIDM_SHVIEW_AUTOARRANGE)
1267     {
1268         Shell_MergeMenus(hmenuArrange, m_hMenuArrangeModes, 0, 0, 0xFFFF,0);
1269     }
1270 
1271     /* Also check the menu item according to which we sort */
1272     CheckMenuRadioItem(hmenuArrange,
1273                        0x30,
1274                        0x100,
1275                        m_sortInfo.nHeaderID + 0x30,
1276                        MF_BYCOMMAND);
1277 
1278     if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST)
1279     {
1280         EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED);
1281     }
1282     else
1283     {
1284         EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND);
1285 
1286         if (GetAutoArrange() == S_OK)
1287             CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED);
1288     }
1289 
1290 
1291     return S_OK;
1292 }
1293 
1294 HRESULT CDefView::CheckViewMode(HMENU hmenuView)
1295 {
1296     if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST)
1297     {
1298         UINT iItemFirst = FCIDM_SHVIEW_BIGICON;
1299         UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST;
1300         UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST;
1301         CheckMenuRadioItem(hmenuView, iItemFirst, iItemLast, iItem, MF_BYCOMMAND);
1302     }
1303 
1304     return S_OK;
1305 }
1306 
1307 /**********************************************************
1308 *   ShellView_GetSelections()
1309 *
1310 * - fills the m_apidl list with the selected objects
1311 *
1312 * RETURNS
1313 *  number of selected items
1314 */
1315 UINT CDefView::GetSelections()
1316 {
1317     SHFree(m_apidl);
1318 
1319     m_cidl = m_ListView.GetSelectedCount();
1320     m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
1321     if (!m_apidl)
1322     {
1323         m_cidl = 0;
1324         return 0;
1325     }
1326 
1327     TRACE("-- Items selected =%u\n", m_cidl);
1328 
1329     UINT i = 0;
1330     int lvIndex = -1;
1331     while ((lvIndex = m_ListView.GetNextItem(lvIndex,  LVNI_SELECTED)) > -1)
1332     {
1333         m_apidl[i] = _PidlByItem(lvIndex);
1334         i++;
1335         if (i == m_cidl)
1336              break;
1337         TRACE("-- selected Item found\n");
1338     }
1339 
1340     return m_cidl;
1341 }
1342 
1343 HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
1344 {
1345     CMINVOKECOMMANDINFO cmi;
1346 
1347     ZeroMemory(&cmi, sizeof(cmi));
1348     cmi.cbSize = sizeof(cmi);
1349     cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1350     cmi.hwnd = m_hWnd;
1351 
1352     if (GetKeyState(VK_SHIFT) & 0x8000)
1353         cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
1354 
1355     if (GetKeyState(VK_CONTROL) & 0x8000)
1356         cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
1357 
1358     HRESULT hr = m_pCM->InvokeCommand(&cmi);
1359     if (FAILED_UNEXPECTEDLY(hr))
1360         return hr;
1361 
1362     return S_OK;
1363 }
1364 
1365 /**********************************************************
1366  *    ShellView_OpenSelectedItems()
1367  */
1368 HRESULT CDefView::OpenSelectedItems()
1369 {
1370     HMENU hMenu;
1371     UINT uCommand;
1372     HRESULT hResult;
1373 
1374     m_cidl = m_ListView.GetSelectedCount();
1375     if (m_cidl == 0)
1376         return S_OK;
1377 
1378     hResult = OnDefaultCommand();
1379     if (hResult == S_OK)
1380         return hResult;
1381 
1382     hMenu = CreatePopupMenu();
1383     if (!hMenu)
1384         return E_FAIL;
1385 
1386     hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1387     if (FAILED_UNEXPECTEDLY(hResult))
1388         goto cleanup;
1389 
1390     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY);
1391     if (FAILED_UNEXPECTEDLY(hResult))
1392         goto cleanup;
1393 
1394     uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1395     if (uCommand == (UINT)-1)
1396     {
1397         hResult = E_FAIL;
1398         goto cleanup;
1399     }
1400 
1401     InvokeContextMenuCommand(uCommand);
1402 
1403 cleanup:
1404 
1405     if (hMenu)
1406         DestroyMenu(hMenu);
1407 
1408     if (m_pCM)
1409     {
1410         IUnknown_SetSite(m_pCM, NULL);
1411         m_pCM.Release();
1412     }
1413 
1414     return hResult;
1415 }
1416 
1417 /**********************************************************
1418  *    ShellView_DoContextMenu()
1419  */
1420 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1421 {
1422     int     x, y;
1423     UINT    uCommand;
1424     HRESULT hResult;
1425 
1426     TRACE("(%p)\n", this);
1427 
1428     m_hContextMenu = CreatePopupMenu();
1429     if (!m_hContextMenu)
1430         return E_FAIL;
1431 
1432     m_cidl = m_ListView.GetSelectedCount();
1433 
1434     hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1435     if (FAILED_UNEXPECTEDLY(hResult))
1436         goto cleanup;
1437 
1438     /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */
1439     hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL);
1440     if (FAILED_UNEXPECTEDLY(hResult))
1441         goto cleanup;
1442 
1443     /* There is no position requested, so try to find one */
1444     if (lParam == ~0)
1445     {
1446         int lvIndex;
1447         POINT pt;
1448 
1449         /* Do we have a focused item, */
1450         if ((lvIndex = m_ListView.GetNextItem(-1, LVIS_FOCUSED)) < 0)
1451         {
1452             /* or a selected item? */
1453             lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED);
1454         }
1455         /* We got something */
1456         if (lvIndex > -1)
1457         {
1458             /* Let's find the center of the icon */
1459             RECT rc = { LVIR_ICON };
1460             m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc);
1461             pt.x = (rc.right + rc.left) / 2;
1462             pt.y = (rc.bottom + rc.top) / 2;
1463         }
1464         else
1465         {
1466             /* We have to drop it somewhere.. */
1467             pt.x = pt.y = 0;
1468         }
1469 
1470         m_ListView.ClientToScreen(&pt);
1471         x = pt.x;
1472         y = pt.y;
1473     }
1474     else
1475     {
1476         x = GET_X_LPARAM(lParam);
1477         y = GET_Y_LPARAM(lParam);
1478     }
1479 
1480     uCommand = TrackPopupMenu(m_hContextMenu,
1481                               TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1482                               x, y, 0, m_hWnd, NULL);
1483     if (uCommand == 0)
1484         goto cleanup;
1485 
1486     if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1487         goto cleanup;
1488 
1489     InvokeContextMenuCommand(uCommand - CONTEXT_MENU_BASE_ID);
1490 
1491 cleanup:
1492     if (m_pCM)
1493     {
1494         IUnknown_SetSite(m_pCM, NULL);
1495         m_pCM.Release();
1496     }
1497 
1498     if (m_hContextMenu)
1499     {
1500         DestroyMenu(m_hContextMenu);
1501         m_hContextMenu = NULL;
1502     }
1503 
1504     return 0;
1505 }
1506 
1507 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1508 {
1509     HRESULT hResult;
1510     HMENU hMenu;
1511 
1512     hMenu = CreatePopupMenu();
1513     if (!hMenu)
1514         return 0;
1515 
1516     hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1517     if (FAILED_UNEXPECTEDLY( hResult))
1518         goto cleanup;
1519 
1520     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1521     if (FAILED_UNEXPECTEDLY( hResult))
1522         goto cleanup;
1523 
1524     InvokeContextMenuCommand(uCommand);
1525 
1526 cleanup:
1527     if (m_pCM)
1528     {
1529         IUnknown_SetSite(m_pCM, NULL);
1530         m_pCM.Release();
1531     }
1532 
1533     if (hMenu)
1534         DestroyMenu(hMenu);
1535 
1536     return 0;
1537 }
1538 
1539 /**********************************************************
1540  *    ##### message handling #####
1541  */
1542 
1543 /**********************************************************
1544 *  ShellView_OnSize()
1545 */
1546 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1547 {
1548     WORD wWidth, wHeight;
1549 
1550     wWidth  = LOWORD(lParam);
1551     wHeight = HIWORD(lParam);
1552 
1553     TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1554 
1555     /* Resize the ListView to fit our window */
1556     if (m_ListView)
1557     {
1558         ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1559     }
1560 
1561     _DoFolderViewCB(SFVM_SIZE, 0, 0);
1562 
1563     return 0;
1564 }
1565 
1566 /**********************************************************
1567 * ShellView_OnDeactivate()
1568 *
1569 * NOTES
1570 *  internal
1571 */
1572 void CDefView::OnDeactivate()
1573 {
1574     TRACE("%p\n", this);
1575 
1576     if (m_uState != SVUIA_DEACTIVATE)
1577     {
1578         // TODO: cleanup menu after deactivation
1579 
1580         m_uState = SVUIA_DEACTIVATE;
1581     }
1582 }
1583 
1584 void CDefView::DoActivate(UINT uState)
1585 {
1586     TRACE("%p uState=%x\n", this, uState);
1587 
1588     /*don't do anything if the state isn't really changing */
1589     if (m_uState == uState)
1590     {
1591         return;
1592     }
1593 
1594     if (uState == SVUIA_DEACTIVATE)
1595     {
1596         OnDeactivate();
1597     }
1598     else
1599     {
1600         if(m_hMenu && !m_bmenuBarInitialized)
1601         {
1602             FillEditMenu();
1603             FillViewMenu();
1604             m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1605             m_bmenuBarInitialized = TRUE;
1606         }
1607 
1608         if (SVUIA_ACTIVATE_FOCUS == uState)
1609         {
1610             m_ListView.SetFocus();
1611         }
1612     }
1613 
1614     m_uState = uState;
1615     TRACE("--\n");
1616 }
1617 
1618 /**********************************************************
1619 * ShellView_OnActivate()
1620 */
1621 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1622 {
1623     DoActivate(SVUIA_ACTIVATE_FOCUS);
1624     return 0;
1625 }
1626 
1627 /**********************************************************
1628 *  ShellView_OnSetFocus()
1629 *
1630 */
1631 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1632 {
1633     TRACE("%p\n", this);
1634 
1635     /* Tell the browser one of our windows has received the focus. This
1636     should always be done before merging menus (OnActivate merges the
1637     menus) if one of our windows has the focus.*/
1638 
1639     m_pShellBrowser->OnViewWindowActive(this);
1640     DoActivate(SVUIA_ACTIVATE_FOCUS);
1641 
1642     /* Set the focus to the listview */
1643     m_ListView.SetFocus();
1644 
1645     /* Notify the ICommDlgBrowser interface */
1646     OnStateChange(CDBOSC_SETFOCUS);
1647 
1648     return 0;
1649 }
1650 
1651 /**********************************************************
1652 * ShellView_OnKillFocus()
1653 */
1654 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1655 {
1656     TRACE("(%p) stub\n", this);
1657 
1658     DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1659     /* Notify the ICommDlgBrowser */
1660     OnStateChange(CDBOSC_KILLFOCUS);
1661 
1662     return 0;
1663 }
1664 
1665 /**********************************************************
1666 * ShellView_OnCommand()
1667 *
1668 * NOTES
1669 *    the CmdID's are the ones from the context menu
1670 */
1671 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1672 {
1673     DWORD dwCmdID;
1674     DWORD dwCmd;
1675     HWND  hwndCmd;
1676     int   nCount;
1677 
1678     dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1679     dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1680     hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1681 
1682     TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1683 
1684     switch (dwCmdID)
1685     {
1686         case FCIDM_SHVIEW_SMALLICON:
1687             m_FolderSettings.ViewMode = FVM_SMALLICON;
1688             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
1689             CheckToolbar();
1690             break;
1691 
1692         case FCIDM_SHVIEW_BIGICON:
1693             m_FolderSettings.ViewMode = FVM_ICON;
1694             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
1695             CheckToolbar();
1696             break;
1697 
1698         case FCIDM_SHVIEW_LISTVIEW:
1699             m_FolderSettings.ViewMode = FVM_LIST;
1700             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
1701             CheckToolbar();
1702             break;
1703 
1704         case FCIDM_SHVIEW_REPORTVIEW:
1705             m_FolderSettings.ViewMode = FVM_DETAILS;
1706             m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
1707             CheckToolbar();
1708             break;
1709 
1710         /* the menu-ID's for sorting are 0x30... see shrec.rc */
1711         case 0x30:
1712         case 0x31:
1713         case 0x32:
1714         case 0x33:
1715             m_sortInfo.nHeaderID = dwCmdID - 0x30;
1716             m_sortInfo.bIsAscending = TRUE;
1717             _Sort();
1718             break;
1719 
1720         case FCIDM_SHVIEW_SNAPTOGRID:
1721             //FIXME
1722             break;
1723         case FCIDM_SHVIEW_AUTOARRANGE:
1724             if (GetAutoArrange() == S_OK)
1725                 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0);
1726             else
1727                 AutoArrange();
1728             break;
1729         case FCIDM_SHVIEW_SELECTALL:
1730             m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
1731             break;
1732 
1733         case FCIDM_SHVIEW_INVERTSELECTION:
1734             nCount = m_ListView.GetItemCount();
1735             for (int i=0; i < nCount; i++)
1736                 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
1737             break;
1738 
1739         case FCIDM_SHVIEW_REFRESH:
1740             Refresh();
1741             break;
1742 
1743         case FCIDM_SHVIEW_DELETE:
1744         case FCIDM_SHVIEW_CUT:
1745         case FCIDM_SHVIEW_COPY:
1746         case FCIDM_SHVIEW_RENAME:
1747         case FCIDM_SHVIEW_PROPERTIES:
1748             return OnExplorerCommand(dwCmdID, TRUE);
1749 
1750         case FCIDM_SHVIEW_INSERT:
1751         case FCIDM_SHVIEW_UNDO:
1752         case FCIDM_SHVIEW_INSERTLINK:
1753         case FCIDM_SHVIEW_NEWFOLDER:
1754             return OnExplorerCommand(dwCmdID, FALSE);
1755         default:
1756             /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1757             if (m_pCM && dwCmd == 0)
1758             {
1759                 InvokeContextMenuCommand(dwCmdID);
1760             }
1761     }
1762 
1763     return 0;
1764 }
1765 
1766 /**********************************************************
1767 * ShellView_OnNotify()
1768 */
1769 
1770 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1771 {
1772     UINT                                CtlID;
1773     LPNMHDR                                lpnmh;
1774     LPNMLISTVIEW                        lpnmlv;
1775     NMLVDISPINFOW                        *lpdi;
1776     PCUITEMID_CHILD                     pidl;
1777     BOOL                                unused;
1778 
1779     CtlID = wParam;
1780     lpnmh = (LPNMHDR)lParam;
1781     lpnmlv = (LPNMLISTVIEW)lpnmh;
1782     lpdi = (NMLVDISPINFOW *)lpnmh;
1783 
1784     TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1785 
1786     switch (lpnmh->code)
1787     {
1788         case NM_SETFOCUS:
1789             TRACE("-- NM_SETFOCUS %p\n", this);
1790             OnSetFocus(0, 0, 0, unused);
1791             break;
1792 
1793         case NM_KILLFOCUS:
1794             TRACE("-- NM_KILLFOCUS %p\n", this);
1795             OnDeactivate();
1796             /* Notify the ICommDlgBrowser interface */
1797             OnStateChange(CDBOSC_KILLFOCUS);
1798             break;
1799 
1800         case NM_CUSTOMDRAW:
1801             TRACE("-- NM_CUSTOMDRAW %p\n", this);
1802             return CDRF_DODEFAULT;
1803 
1804         case NM_RELEASEDCAPTURE:
1805             TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1806             break;
1807 
1808         case NM_CLICK:
1809             TRACE("-- NM_CLICK %p\n", this);
1810             break;
1811 
1812         case NM_RCLICK:
1813             TRACE("-- NM_RCLICK %p\n", this);
1814             break;
1815 
1816         case NM_DBLCLK:
1817             TRACE("-- NM_DBLCLK %p\n", this);
1818             OpenSelectedItems();
1819             break;
1820 
1821         case NM_RETURN:
1822             TRACE("-- NM_RETURN %p\n", this);
1823             OpenSelectedItems();
1824             break;
1825 
1826         case HDN_ENDTRACKW:
1827             TRACE("-- HDN_ENDTRACKW %p\n", this);
1828             /*nColumn1 = m_ListView.GetColumnWidth(0);
1829             nColumn2 = m_ListView.GetColumnWidth(1);*/
1830             break;
1831 
1832         case LVN_DELETEITEM:
1833             TRACE("-- LVN_DELETEITEM %p\n", this);
1834 
1835             /*delete the pidl because we made a copy of it*/
1836             SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1837 
1838             break;
1839 
1840         case LVN_DELETEALLITEMS:
1841             TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1842             return FALSE;
1843 
1844         case LVN_INSERTITEM:
1845             TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1846             break;
1847 
1848         case LVN_ITEMACTIVATE:
1849             TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1850             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1851             break;
1852 
1853         case LVN_COLUMNCLICK:
1854             m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1855             if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1856                 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1857             else
1858                 m_sortInfo.bIsAscending = TRUE;
1859             _Sort();
1860             break;
1861 
1862         case LVN_GETDISPINFOA:
1863         case LVN_GETDISPINFOW:
1864             TRACE("-- LVN_GETDISPINFO %p\n", this);
1865             pidl = _PidlByItem(lpdi->item);
1866 
1867             if (lpdi->item.mask & LVIF_TEXT)    /* text requested */
1868             {
1869                 if (m_pSF2Parent)
1870                 {
1871                     SHELLDETAILS sd;
1872                     if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1873                         break;
1874 
1875                     if (lpnmh->code == LVN_GETDISPINFOA)
1876                     {
1877                         /* shouldn't happen */
1878                         NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1879                         StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1880                         TRACE("-- text=%s\n", lpdiA->item.pszText);
1881                     }
1882                     else /* LVN_GETDISPINFOW */
1883                     {
1884                         StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1885                         TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1886                     }
1887                 }
1888                 else
1889                 {
1890                     FIXME("no m_pSF2Parent\n");
1891                 }
1892             }
1893             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
1894             {
1895                 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1896             }
1897             if(lpdi->item.mask & LVIF_STATE)
1898             {
1899                 ULONG attributes = SFGAO_HIDDEN;
1900                 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
1901                 {
1902                     if (attributes & SFGAO_HIDDEN)
1903                     {
1904                         lpdi->item.state |= LVIS_CUT;
1905                     }
1906                 }
1907             }
1908             lpdi->item.mask |= LVIF_DI_SETITEM;
1909             break;
1910 
1911         case LVN_ITEMCHANGED:
1912             TRACE("-- LVN_ITEMCHANGED %p\n", this);
1913             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
1914             UpdateStatusbar();
1915             _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */);
1916             break;
1917 
1918         case LVN_BEGINDRAG:
1919         case LVN_BEGINRDRAG:
1920             TRACE("-- LVN_BEGINDRAG\n");
1921 
1922             if (GetSelections())
1923             {
1924                 CComPtr<IDataObject> pda;
1925                 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK;
1926                 DWORD dwEffect = DROPEFFECT_MOVE;
1927 
1928                 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1929                 {
1930                     LPNMLISTVIEW params = (LPNMLISTVIEW)lParam;
1931 
1932                     if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1933                     {
1934                         dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK);
1935                     }
1936 
1937                     CComPtr<IAsyncOperation> piaso;
1938                     if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1939                     {
1940                         piaso->SetAsyncMode(TRUE);
1941                     }
1942 
1943                     DWORD dwEffect2;
1944 
1945                     m_pSourceDataObject = pda;
1946                     m_ptFirstMousePos = params->ptAction;
1947                     ClientToScreen(&m_ptFirstMousePos);
1948 
1949                     HIMAGELIST big_icons, small_icons;
1950                     Shell_GetImageLists(&big_icons, &small_icons);
1951                     PCUITEMID_CHILD pidl = _PidlByItem(params->iItem);
1952                     int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1953                     POINT ptItem;
1954                     m_ListView.GetItemPosition(params->iItem, &ptItem);
1955 
1956                     ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y);
1957 
1958                     DoDragDrop(pda, this, dwEffect, &dwEffect2);
1959 
1960                     m_pSourceDataObject.Release();
1961                 }
1962             }
1963             break;
1964 
1965         case LVN_BEGINLABELEDITW:
1966         {
1967             DWORD dwAttr = SFGAO_CANRENAME;
1968             pidl = _PidlByItem(lpdi->item);
1969 
1970             TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1971 
1972             m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
1973             if (SFGAO_CANRENAME & dwAttr)
1974             {
1975                 m_isEditing = TRUE;
1976                 return FALSE;
1977             }
1978             return TRUE;
1979         }
1980 
1981         case LVN_ENDLABELEDITW:
1982         {
1983             TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1984 
1985             m_isEditing = FALSE;
1986 
1987             if (lpdi->item.pszText)
1988             {
1989                 HRESULT hr;
1990                 LVITEMW lvItem;
1991 
1992                 pidl = _PidlByItem(lpdi->item);
1993                 PITEMID_CHILD pidlNew = NULL;
1994                 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
1995 
1996                 if (SUCCEEDED(hr) && pidlNew)
1997                 {
1998                     lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
1999                     lvItem.iItem = lpdi->item.iItem;
2000                     lvItem.iSubItem = 0;
2001                     lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
2002                     lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
2003                     m_ListView.SetItem(&lvItem);
2004                     m_ListView.Update(lpdi->item.iItem);
2005                     return TRUE;
2006                 }
2007             }
2008 
2009             return FALSE;
2010         }
2011 
2012         default:
2013             TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
2014             break;
2015     }
2016 
2017     return 0;
2018 }
2019 
2020 /*
2021  * This is just a quick hack to make the desktop work correctly.
2022  * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
2023  * a folder should know if it should update upon a change notification.
2024  * It is exported by merged folders at a minimum.
2025  */
2026 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
2027 {
2028     if (!pidl1 || !pidl2)
2029         return FALSE;
2030     if (ILIsParent(pidl1, pidl2, TRUE))
2031         return TRUE;
2032 
2033     if (_ILIsDesktop(pidl1))
2034     {
2035         PIDLIST_ABSOLUTE deskpidl;
2036         SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2037         if (ILIsParent(deskpidl, pidl2, TRUE))
2038         {
2039             ILFree(deskpidl);
2040             return TRUE;
2041         }
2042         ILFree(deskpidl);
2043         SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2044         if (ILIsParent(deskpidl, pidl2, TRUE))
2045         {
2046             ILFree(deskpidl);
2047             return TRUE;
2048         }
2049         ILFree(deskpidl);
2050     }
2051     return FALSE;
2052 }
2053 
2054 /**********************************************************
2055 * ShellView_OnChange()
2056 */
2057 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2058 {
2059     PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
2060     BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
2061     BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
2062 
2063     TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
2064 
2065     switch (lParam &~ SHCNE_INTERRUPT)
2066     {
2067         case SHCNE_MKDIR:
2068         case SHCNE_CREATE:
2069             if (bParent0)
2070             {
2071                 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
2072                 {
2073                     LV_AddItem(ILFindLastID(Pidls[0]));
2074                 }
2075                 else
2076                 {
2077                     LV_ProdItem(ILFindLastID(Pidls[0]));
2078                 }
2079             }
2080             break;
2081 
2082         case SHCNE_RMDIR:
2083         case SHCNE_DELETE:
2084             if (bParent0)
2085                 LV_DeleteItem(ILFindLastID(Pidls[0]));
2086             break;
2087 
2088         case SHCNE_RENAMEFOLDER:
2089         case SHCNE_RENAMEITEM:
2090             if (bParent0 && bParent1)
2091                 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
2092             else if (bParent0)
2093                 LV_DeleteItem(ILFindLastID(Pidls[0]));
2094             else if (bParent1)
2095                 LV_AddItem(ILFindLastID(Pidls[1]));
2096             break;
2097 
2098         case SHCNE_UPDATEITEM:
2099             if (bParent0)
2100                 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
2101             break;
2102 
2103         case SHCNE_UPDATEDIR:
2104             Refresh();
2105             break;
2106     }
2107     return TRUE;
2108 }
2109 
2110 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId);
2111 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId);
2112 
2113 /**********************************************************
2114 *  CDefView::OnCustomItem
2115 */
2116 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2117 {
2118     if (!m_pCM.p)
2119     {
2120         /* no menu */
2121         ERR("no menu!!!\n");
2122         return FALSE;
2123     }
2124 
2125     /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to
2126        be changed to a menu identifier offset */
2127     UINT CmdID;
2128     HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID);
2129     if (SUCCEEDED(hres))
2130         SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID);
2131 
2132     /* Forward the message to the IContextMenu2 */
2133     LRESULT result;
2134     hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
2135 
2136     return (SUCCEEDED(hres));
2137 }
2138 
2139 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2140 {
2141     /* Wallpaper setting affects drop shadows effect */
2142     if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
2143         UpdateListColors();
2144 
2145     return S_OK;
2146 }
2147 
2148 /**********************************************************
2149 *  CDefView::OnInitMenuPopup
2150 */
2151 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2152 {
2153     HMENU hmenu = (HMENU) wParam;
2154     int nPos = LOWORD(lParam);
2155     UINT  menuItemId;
2156 
2157     OnCustomItem(uMsg, wParam, lParam, bHandled);
2158 
2159     HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
2160 
2161     /* Lets try to find out what the hell wParam is */
2162     if (hmenu == GetSubMenu(m_hMenu, nPos))
2163         menuItemId = ReallyGetMenuItemID(m_hMenu, nPos);
2164     else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos))
2165         menuItemId = ReallyGetMenuItemID(hViewMenu, nPos);
2166     else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos))
2167         menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos);
2168     else
2169         return FALSE;
2170 
2171     switch (menuItemId)
2172     {
2173     case FCIDM_MENU_FILE:
2174         FillFileMenu();
2175         break;
2176     case FCIDM_MENU_VIEW:
2177     case FCIDM_SHVIEW_VIEW:
2178         CheckViewMode(hmenu);
2179         break;
2180     case FCIDM_SHVIEW_ARRANGE:
2181         FillArrangeAsMenu(hmenu);
2182         break;
2183     }
2184 
2185     return FALSE;
2186 }
2187 
2188 /**********************************************************
2189 *
2190 *
2191 *  The INTERFACE of the IShellView object
2192 *
2193 *
2194 **********************************************************
2195 */
2196 
2197 /**********************************************************
2198 *  ShellView_GetWindow
2199 */
2200 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2201 {
2202     TRACE("(%p)\n", this);
2203 
2204     *phWnd = m_hWnd;
2205 
2206     return S_OK;
2207 }
2208 
2209 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2210 {
2211     FIXME("(%p) stub\n", this);
2212 
2213     return E_NOTIMPL;
2214 }
2215 
2216 /**********************************************************
2217 * IShellView_TranslateAccelerator
2218 *
2219 * FIXME:
2220 *  use the accel functions
2221 */
2222 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2223 {
2224     if (m_isEditing)
2225         return S_FALSE;
2226 
2227     if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2228     {
2229         if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2230             return S_OK;
2231 
2232         TRACE("-- key=0x%04lx\n", lpmsg->wParam) ;
2233     }
2234 
2235     return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2236 }
2237 
2238 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2239 {
2240     FIXME("(%p) stub\n", this);
2241 
2242     return E_NOTIMPL;
2243 }
2244 
2245 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2246 {
2247     // CHAR szName[MAX_PATH];
2248     LRESULT lResult;
2249     int nPartArray[1] = { -1};
2250 
2251     TRACE("(%p)->(state=%x) stub\n", this, uState);
2252 
2253     /* don't do anything if the state isn't really changing */
2254     if (m_uState == uState)
2255     {
2256         return S_OK;
2257     }
2258 
2259     /* OnActivate handles the menu merging and internal state */
2260     DoActivate(uState);
2261 
2262     /* only do This if we are active */
2263     if (uState != SVUIA_DEACTIVATE)
2264     {
2265 
2266         /*
2267             GetFolderPath is not a method of IShellFolder
2268             IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2269         */
2270         /* set the number of parts */
2271         m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2272 
2273         /* set the text for the parts */
2274         /*
2275             m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2276         */
2277     }
2278 
2279     return S_OK;
2280 }
2281 
2282 HRESULT WINAPI CDefView::Refresh()
2283 {
2284     TRACE("(%p)\n", this);
2285 
2286     m_ListView.DeleteAllItems();
2287     FillList();
2288 
2289     return S_OK;
2290 }
2291 
2292 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2293 {
2294     return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT,
2295         (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd);
2296 }
2297 
2298 HRESULT WINAPI CDefView::DestroyViewWindow()
2299 {
2300     TRACE("(%p)\n", this);
2301 
2302     /* Make absolutely sure all our UI is cleaned up */
2303     UIActivate(SVUIA_DEACTIVATE);
2304 
2305     if (m_hAccel)
2306     {
2307         // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2308         m_hAccel = NULL;
2309     }
2310 
2311     if (m_hMenuArrangeModes)
2312     {
2313         DestroyMenu(m_hMenuArrangeModes);
2314         m_hMenuArrangeModes = NULL;
2315     }
2316 
2317     if (m_hMenuViewModes)
2318     {
2319         DestroyMenu(m_hMenuViewModes);
2320         m_hMenuViewModes = NULL;
2321     }
2322 
2323     if (m_hMenu)
2324     {
2325         DestroyMenu(m_hMenu);
2326         m_hMenu = NULL;
2327     }
2328 
2329     if (m_ListView)
2330     {
2331         m_ListView.DestroyWindow();
2332     }
2333 
2334     if (m_hWnd)
2335     {
2336         DestroyWindow();
2337     }
2338 
2339     m_pShellBrowser.Release();
2340     m_pCommDlgBrowser.Release();
2341 
2342     return S_OK;
2343 }
2344 
2345 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2346 {
2347     TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2348           m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2349 
2350     if (!lpfs)
2351         return E_INVALIDARG;
2352 
2353     *lpfs = m_FolderSettings;
2354     return S_OK;
2355 }
2356 
2357 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2358 {
2359     FIXME("(%p) stub\n", this);
2360 
2361     return E_NOTIMPL;
2362 }
2363 
2364 HRESULT WINAPI CDefView::SaveViewState()
2365 {
2366     FIXME("(%p) stub\n", this);
2367 
2368     return S_OK;
2369 }
2370 
2371 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2372 {
2373     int i;
2374 
2375     TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2376 
2377     i = LV_FindItemByPidl(pidl);
2378     if (i == -1)
2379         return S_OK;
2380 
2381     if(uFlags & SVSI_ENSUREVISIBLE)
2382         m_ListView.EnsureVisible(i, FALSE);
2383 
2384     LVITEMW lvItem = {0};
2385     lvItem.mask = LVIF_STATE;
2386     lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2387 
2388     while (m_ListView.GetItem(&lvItem))
2389     {
2390         if (lvItem.iItem == i)
2391         {
2392             if (uFlags & SVSI_SELECT)
2393                 lvItem.state |= LVIS_SELECTED;
2394             else
2395                 lvItem.state &= ~LVIS_SELECTED;
2396 
2397             if (uFlags & SVSI_FOCUSED)
2398                 lvItem.state &= ~LVIS_FOCUSED;
2399         }
2400         else
2401         {
2402             if (uFlags & SVSI_DESELECTOTHERS)
2403                 lvItem.state &= ~LVIS_SELECTED;
2404         }
2405 
2406         m_ListView.SetItem(&lvItem);
2407         lvItem.iItem++;
2408     }
2409 
2410     if((uFlags & SVSI_EDIT) == SVSI_EDIT)
2411         m_ListView.EditLabel(i);
2412 
2413     return S_OK;
2414 }
2415 
2416 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2417 {
2418     HRESULT hr = E_NOINTERFACE;
2419 
2420     TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2421 
2422     *ppvOut = NULL;
2423 
2424     switch (uItem)
2425     {
2426         case SVGIO_BACKGROUND:
2427             if (IsEqualIID(riid, IID_IContextMenu))
2428             {
2429                 if (!ppvOut)
2430                     hr = E_OUTOFMEMORY;
2431 
2432                 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut);
2433                 if (FAILED_UNEXPECTEDLY(hr))
2434                     return hr;
2435 
2436                 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2437             }
2438             else if (IsEqualIID(riid, IID_IDispatch))
2439             {
2440                 if (m_pShellFolderViewDual == NULL)
2441                 {
2442                     hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
2443                     if (FAILED_UNEXPECTEDLY(hr))
2444                         return hr;
2445                 }
2446                 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
2447             }
2448             break;
2449 
2450         case SVGIO_SELECTION:
2451             GetSelections();
2452             hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2453             if (FAILED_UNEXPECTEDLY(hr))
2454                 return hr;
2455 
2456             if (IsEqualIID(riid, IID_IContextMenu))
2457                 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2458 
2459             break;
2460     }
2461 
2462     TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2463 
2464     return hr;
2465 }
2466 
2467 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2468 {
2469     TRACE("(%p)->(%p), stub\n", this, pViewMode);
2470 
2471     if (!pViewMode)
2472         return E_INVALIDARG;
2473 
2474     *pViewMode = m_FolderSettings.ViewMode;
2475     return S_OK;
2476 }
2477 
2478 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2479 {
2480     DWORD dwStyle;
2481     TRACE("(%p)->(%u), stub\n", this, ViewMode);
2482 
2483     /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2484     if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2485         return E_INVALIDARG;
2486 
2487     /* Windows before Vista uses LVM_SETVIEW and possibly
2488        LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2489        while later versions seem to accomplish this through other
2490        means. */
2491     switch (ViewMode)
2492     {
2493         case FVM_ICON:
2494             dwStyle = LVS_ICON;
2495             break;
2496         case FVM_DETAILS:
2497             dwStyle = LVS_REPORT;
2498             break;
2499         case FVM_SMALLICON:
2500             dwStyle = LVS_SMALLICON;
2501             break;
2502         case FVM_LIST:
2503             dwStyle = LVS_LIST;
2504             break;
2505         default:
2506         {
2507             FIXME("ViewMode %d not implemented\n", ViewMode);
2508             dwStyle = LVS_LIST;
2509             break;
2510         }
2511     }
2512 
2513     m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle);
2514 
2515     /* This will not necessarily be the actual mode set above.
2516        This mimics the behavior of Windows XP. */
2517     m_FolderSettings.ViewMode = ViewMode;
2518 
2519     return S_OK;
2520 }
2521 
2522 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2523 {
2524     if (m_pSFParent == NULL)
2525         return E_FAIL;
2526 
2527     return m_pSFParent->QueryInterface(riid, ppv);
2528 }
2529 
2530 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2531 {
2532     PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2533     if (pidl)
2534     {
2535         *ppidl = ILClone(pidl);
2536         return S_OK;
2537     }
2538 
2539     *ppidl = 0;
2540     return E_INVALIDARG;
2541 }
2542 
2543 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2544 {
2545     TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2546 
2547     if (uFlags != SVGIO_ALLVIEW)
2548         FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2549 
2550     *pcItems = m_ListView.GetItemCount();
2551 
2552     return S_OK;
2553 }
2554 
2555 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2556 {
2557     return E_NOTIMPL;
2558 }
2559 
2560 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2561 {
2562     TRACE("(%p)->(%p)\n", this, piItem);
2563 
2564     *piItem = m_ListView.GetSelectionMark();
2565 
2566     return S_OK;
2567 }
2568 
2569 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2570 {
2571     TRACE("(%p)->(%p)\n", this, piItem);
2572 
2573     *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2574 
2575     return S_OK;
2576 }
2577 
2578 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2579 {
2580     int lvIndex = LV_FindItemByPidl(pidl);
2581     if (lvIndex == -1 || ppt == NULL)
2582         return E_INVALIDARG;
2583 
2584     m_ListView.GetItemPosition(lvIndex, ppt);
2585     return S_OK;
2586 }
2587 
2588 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2589 {
2590     TRACE("(%p)->(%p)\n", this, ppt);
2591 
2592     if (!m_ListView)
2593         return S_FALSE;
2594 
2595     if (ppt)
2596     {
2597         SIZE spacing;
2598         m_ListView.GetItemSpacing(spacing);
2599 
2600         ppt->x = spacing.cx;
2601         ppt->y = spacing.cy;
2602     }
2603 
2604     return S_OK;
2605 }
2606 
2607 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2608 {
2609     return E_NOTIMPL;
2610 }
2611 
2612 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2613 {
2614     return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE);
2615 }
2616 
2617 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2618 {
2619     LVITEMW lvItem;
2620 
2621     TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2622 
2623     lvItem.state = 0;
2624     lvItem.stateMask = LVIS_SELECTED;
2625 
2626     if (dwFlags & SVSI_ENSUREVISIBLE)
2627         m_ListView.EnsureVisible(iItem, 0);
2628 
2629     /* all items */
2630     if (dwFlags & SVSI_DESELECTOTHERS)
2631         m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2632 
2633     /* this item */
2634     if (dwFlags & SVSI_SELECT)
2635         lvItem.state |= LVIS_SELECTED;
2636 
2637     if (dwFlags & SVSI_FOCUSED)
2638         lvItem.stateMask |= LVIS_FOCUSED;
2639 
2640     m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2641 
2642     if ((dwFlags & SVSI_EDIT) == SVSI_EDIT)
2643         m_ListView.EditLabel(iItem);
2644 
2645     return S_OK;
2646 }
2647 
2648 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2649 {
2650     /* Reset the selection */
2651     m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2652 
2653     int lvIndex;
2654     for (UINT i = 0 ; i < m_cidl; i++)
2655     {
2656         lvIndex = LV_FindItemByPidl(apidl[i]);
2657         if (lvIndex != -1)
2658         {
2659             SelectItem(lvIndex, dwFlags);
2660             m_ListView.SetItemPosition(lvIndex, &apt[i]);
2661         }
2662     }
2663 
2664     return S_OK;
2665 }
2666 
2667 /**********************************************************
2668  * IShellView2 implementation
2669  */
2670 
2671 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
2672 {
2673     FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
2674     return E_NOTIMPL;
2675 }
2676 
2677 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
2678 {
2679     return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev,
2680         SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags,
2681         (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView);
2682 }
2683 
2684 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)
2685 {
2686     OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2687 
2688     *hwnd = NULL;
2689 
2690     TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags);
2691     if (prcView != NULL)
2692         TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2693 
2694     /* Validate the Shell Browser */
2695     if (psb == NULL || m_hWnd)
2696         return E_UNEXPECTED;
2697 
2698     if (view_flags != SV3CVW3_DEFAULT)
2699         FIXME("unsupported view flags 0x%08x\n", view_flags);
2700 
2701     /* Set up the member variables */
2702     m_pShellBrowser = psb;
2703     m_FolderSettings.ViewMode = mode;
2704     m_FolderSettings.fFlags = mask & flags;
2705 
2706     if (view_id)
2707     {
2708         if (IsEqualIID(*view_id, VID_LargeIcons))
2709             m_FolderSettings.ViewMode = FVM_ICON;
2710         else if (IsEqualIID(*view_id, VID_SmallIcons))
2711             m_FolderSettings.ViewMode = FVM_SMALLICON;
2712         else if (IsEqualIID(*view_id, VID_List))
2713             m_FolderSettings.ViewMode = FVM_LIST;
2714         else if (IsEqualIID(*view_id, VID_Details))
2715             m_FolderSettings.ViewMode = FVM_DETAILS;
2716         else if (IsEqualIID(*view_id, VID_Thumbnails))
2717             m_FolderSettings.ViewMode = FVM_THUMBNAIL;
2718         else if (IsEqualIID(*view_id, VID_Tile))
2719             m_FolderSettings.ViewMode = FVM_TILE;
2720         else if (IsEqualIID(*view_id, VID_ThumbStrip))
2721             m_FolderSettings.ViewMode = FVM_THUMBSTRIP;
2722         else
2723             FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
2724     }
2725 
2726     /* Get our parent window */
2727     m_pShellBrowser->GetWindow(&m_hWndParent);
2728 
2729     /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2730     m_pCommDlgBrowser = NULL;
2731     if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2732     {
2733         TRACE("-- CommDlgBrowser\n");
2734     }
2735 
2736     Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
2737     if (m_hWnd == NULL)
2738         return E_FAIL;
2739 
2740     *hwnd = m_hWnd;
2741 
2742     CheckToolbar();
2743 
2744     if (!*hwnd)
2745         return E_FAIL;
2746 
2747     _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, NULL);
2748 
2749     SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2750     UpdateWindow();
2751 
2752     if (!m_hMenu)
2753     {
2754         m_hMenu = CreateMenu();
2755         m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2756         TRACE("-- after fnInsertMenusSB\n");
2757     }
2758 
2759     _MergeToolbar();
2760 
2761     return S_OK;
2762 }
2763 
2764 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
2765 {
2766     FIXME("(%p)->(%p) stub\n", this, new_pidl);
2767     return E_NOTIMPL;
2768 }
2769 
2770 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
2771 {
2772     FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
2773     return E_NOTIMPL;
2774 }
2775 
2776 /**********************************************************
2777  * IShellFolderView implementation
2778  */
2779 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2780 {
2781     FIXME("(%p)->(%ld) stub\n", this, sort);
2782     return E_NOTIMPL;
2783 }
2784 
2785 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2786 {
2787     FIXME("(%p)->(%p) stub\n", this, sort);
2788     return E_NOTIMPL;
2789 }
2790 
2791 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2792 {
2793     FIXME("(%p) stub\n", this);
2794     return E_NOTIMPL;
2795 }
2796 
2797 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2798 {
2799     m_ListView.ModifyStyle(0, LVS_AUTOARRANGE);
2800     m_ListView.Arrange(LVA_DEFAULT);
2801     return S_OK;
2802 }
2803 
2804 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2805 {
2806     FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2807     return E_NOTIMPL;
2808 }
2809 
2810 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2811 {
2812     TRACE("(%p)->(%p %d)\n", this, pidl, item);
2813     return Item(item, pidl);
2814 }
2815 
2816 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2817 {
2818 
2819     TRACE("(%p)->(%p %p)\n", this, pidl, item);
2820 
2821     if (pidl)
2822     {
2823         *item = LV_FindItemByPidl(ILFindLastID(pidl));
2824         m_ListView.DeleteItem(*item);
2825     }
2826     else
2827     {
2828         *item = 0;
2829         m_ListView.DeleteAllItems();
2830     }
2831 
2832     return S_OK;
2833 }
2834 
2835 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2836 {
2837     TRACE("(%p)->(%p)\n", this, count);
2838     *count = m_ListView.GetItemCount();
2839     return S_OK;
2840 }
2841 
2842 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2843 {
2844     FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2845     return E_NOTIMPL;
2846 }
2847 
2848 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2849 {
2850     FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2851     return E_NOTIMPL;
2852 }
2853 
2854 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2855 {
2856     FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2857     return E_NOTIMPL;
2858 }
2859 
2860 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2861 {
2862     TRACE("(%p)->(%d)\n", this, redraw);
2863     m_ListView.SetRedraw(redraw);
2864     return S_OK;
2865 }
2866 
2867 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2868 {
2869     FIXME("(%p)->(%p) stub\n", this, count);
2870     return E_NOTIMPL;
2871 }
2872 
2873 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2874 {
2875     TRACE("(%p)->(%p %p)\n", this, pidl, items);
2876 
2877     *items = GetSelections();
2878 
2879     if (*items)
2880     {
2881         *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2882         if (!*pidl)
2883         {
2884             return E_OUTOFMEMORY;
2885         }
2886 
2887         /* it's documented that caller shouldn't PIDLs, only array itself */
2888         memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2889     }
2890 
2891     return S_OK;
2892 }
2893 
2894 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2895 {
2896     if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) &&
2897         (m_pSourceDataObject.p))
2898     {
2899         return S_OK;
2900     }
2901 
2902     return S_FALSE;
2903 }
2904 
2905 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2906 {
2907     if (!pt)
2908         return E_INVALIDARG;
2909 
2910     *pt = m_ptFirstMousePos;
2911     return S_OK;
2912 }
2913 
2914 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2915 {
2916     FIXME("(%p)->(%p) stub\n", this, pt);
2917     return E_NOTIMPL;
2918 }
2919 
2920 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2921 {
2922     TRACE("(%p)->(%p)\n", this, obj);
2923     return E_NOTIMPL;
2924 }
2925 
2926 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2927 {
2928     FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2929     return E_NOTIMPL;
2930 }
2931 
2932 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2933 {
2934     FIXME("(%p)->(%p) stub\n", this, drop_target);
2935     return E_NOTIMPL;
2936 }
2937 
2938 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2939 {
2940     FIXME("(%p)->(%d) stub\n", this, move);
2941     return E_NOTIMPL;
2942 }
2943 
2944 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2945 {
2946     FIXME("(%p)->(%p) stub\n", this, obj);
2947     return E_NOTIMPL;
2948 }
2949 
2950 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2951 {
2952     FIXME("(%p)->(%p) stub\n", this, spacing);
2953     return E_NOTIMPL;
2954 }
2955 
2956 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB  *new_cb, IShellFolderViewCB **old_cb)
2957 {
2958     if (old_cb)
2959         *old_cb = m_pShellFolderViewCB.Detach();
2960 
2961     m_pShellFolderViewCB = new_cb;
2962     return S_OK;
2963 }
2964 
2965 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2966 {
2967     FIXME("(%p)->(%d) stub\n", this, flags);
2968     return E_NOTIMPL;
2969 }
2970 
2971 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2972 {
2973     TRACE("(%p)->(%p)\n", this, support);
2974     return S_OK;
2975 }
2976 
2977 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2978 {
2979     FIXME("(%p)->(%p) stub\n", this, disp);
2980     return E_NOTIMPL;
2981 }
2982 
2983 /**********************************************************
2984  * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2985  */
2986 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2987 {
2988     FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2989           this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2990 
2991     if (!prgCmds)
2992         return E_INVALIDARG;
2993 
2994     for (UINT i = 0; i < cCmds; i++)
2995     {
2996         FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2997         prgCmds[i].cmdf = 0;
2998     }
2999 
3000     return OLECMDERR_E_UNKNOWNGROUP;
3001 }
3002 
3003 /**********************************************************
3004  * ISVOleCmdTarget_Exec (IOleCommandTarget)
3005  *
3006  * nCmdID is the OLECMDID_* enumeration
3007  */
3008 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
3009 {
3010     FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3011           this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
3012 
3013     if (!pguidCmdGroup)
3014         return OLECMDERR_E_UNKNOWNGROUP;
3015 
3016     if (IsEqualCLSID(*pguidCmdGroup, m_Category))
3017     {
3018         if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
3019         {
3020             if (V_VT(pvaIn) != VT_INT_PTR)
3021                 return OLECMDERR_E_NOTSUPPORTED;
3022 
3023             TPMPARAMS params;
3024             params.cbSize = sizeof(params);
3025             params.rcExclude = *(RECT*) V_INTREF(pvaIn);
3026 
3027             if (m_hMenuViewModes)
3028             {
3029                 /* Duplicate all but the last two items of the view modes menu */
3030                 HMENU hmenuViewPopup = CreatePopupMenu();
3031                 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0);
3032                 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3033                 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3034                 CheckViewMode(hmenuViewPopup);
3035                 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
3036                 ::DestroyMenu(hmenuViewPopup);
3037             }
3038 
3039             // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3040             V_VT(pvaOut) = VT_I4;
3041             V_I4(pvaOut) = 0x403;
3042         }
3043     }
3044 
3045     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
3046             (nCmdID == 0x29) &&
3047             (nCmdexecopt == 4) && pvaOut)
3048         return S_OK;
3049 
3050     if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
3051             (nCmdID == 9) &&
3052             (nCmdexecopt == 0))
3053         return 1;
3054 
3055     return OLECMDERR_E_UNKNOWNGROUP;
3056 }
3057 
3058 /**********************************************************
3059  * ISVDropTarget implementation
3060  */
3061 
3062 /******************************************************************************
3063  * drag_notify_subitem [Internal]
3064  *
3065  * Figure out the shellfolder object, which is currently under the mouse cursor
3066  * and notify it via the IDropTarget interface.
3067  */
3068 
3069 #define SCROLLAREAWIDTH 20
3070 
3071 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3072 {
3073     LONG lResult;
3074     HRESULT hr;
3075     RECT clientRect;
3076 
3077     /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3078        reflects the key state after the user released the button, so we need
3079        to remember the last key state when the button was pressed */
3080     m_grfKeyState = grfKeyState;
3081 
3082     /* Map from global to client coordinates and query the index of the listview-item, which is
3083      * currently under the mouse cursor. */
3084     LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM};
3085     ScreenToClient(&htinfo.pt);
3086     lResult = m_ListView.HitTest(&htinfo);
3087 
3088     /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3089     ::GetClientRect(m_ListView, &clientRect);
3090     if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
3091             (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
3092              htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
3093     {
3094         m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
3095         if (m_cScrollDelay == 0)
3096         {
3097             /* Mouse did hover another 250 ms over the scroll-area */
3098             if (htinfo.pt.x < SCROLLAREAWIDTH)
3099                 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
3100 
3101             if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
3102                 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
3103 
3104             if (htinfo.pt.y < SCROLLAREAWIDTH)
3105                 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
3106 
3107             if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
3108                 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
3109         }
3110     }
3111     else
3112     {
3113         m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
3114     }
3115 
3116     m_ptLastMousePos = htinfo.pt;
3117 
3118     /* We need to check if we drag the selection over itself */
3119     if (lResult != -1 && m_pSourceDataObject.p != NULL)
3120     {
3121         PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3122 
3123         for (UINT i = 0; i < m_cidl; i++)
3124         {
3125             if (pidl == m_apidl[i])
3126             {
3127                 /* The item that is being draged is hovering itself. */
3128                 lResult = -1;
3129                 break;
3130             }
3131         }
3132     }
3133 
3134     /* If we are still over the previous sub-item, notify it via DragOver and return. */
3135     if (m_pCurDropTarget && lResult == m_iDragOverItem)
3136         return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
3137 
3138     /* We've left the previous sub-item, notify it via DragLeave and Release it. */
3139     if (m_pCurDropTarget)
3140     {
3141         PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem);
3142         if (pidl)
3143             SelectItem(pidl, 0);
3144 
3145         m_pCurDropTarget->DragLeave();
3146         m_pCurDropTarget.Release();
3147     }
3148 
3149     m_iDragOverItem = lResult;
3150 
3151     if (lResult == -1)
3152     {
3153         /* We are not above one of the listview's subitems. Bind to the parent folder's
3154          * DropTarget interface. */
3155         hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
3156     }
3157     else
3158     {
3159         /* Query the relative PIDL of the shellfolder object represented by the currently
3160          * dragged over listview-item ... */
3161         PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3162 
3163         /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
3164         hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
3165     }
3166 
3167     IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this);
3168 
3169     /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
3170     if (FAILED(hr))
3171     {
3172         *pdwEffect = DROPEFFECT_NONE;
3173         return hr;
3174     }
3175 
3176     if (m_iDragOverItem != -1)
3177     {
3178         SelectItem(m_iDragOverItem, SVSI_SELECT);
3179     }
3180 
3181     /* Notify the item just entered via DragEnter. */
3182     return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
3183 }
3184 
3185 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3186 {
3187     /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3188     m_pCurDataObject = pDataObject;
3189 
3190     HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect);
3191     if (SUCCEEDED(hr))
3192     {
3193         POINT ptClient = {pt.x, pt.y};
3194         ScreenToClient(&ptClient);
3195         ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y);
3196     }
3197 
3198     return hr;
3199 }
3200 
3201 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3202 {
3203     POINT ptClient = {pt.x, pt.y};
3204     ScreenToClient(&ptClient);
3205     ImageList_DragMove(ptClient.x, ptClient.y);
3206     return drag_notify_subitem(grfKeyState, pt, pdwEffect);
3207 }
3208 
3209 HRESULT WINAPI CDefView::DragLeave()
3210 {
3211     ImageList_DragLeave(m_hWnd);
3212 
3213     if (m_pCurDropTarget)
3214     {
3215         m_pCurDropTarget->DragLeave();
3216         m_pCurDropTarget.Release();
3217     }
3218 
3219     if (m_pCurDataObject != NULL)
3220     {
3221         m_pCurDataObject.Release();
3222     }
3223 
3224     m_iDragOverItem = 0;
3225 
3226     return S_OK;
3227 }
3228 
3229 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3230 {
3231     ImageList_DragLeave(m_hWnd);
3232     ImageList_EndDrag();
3233 
3234     if ((IsDropOnSource(NULL) == S_OK) &&
3235         (*pdwEffect & DROPEFFECT_MOVE) &&
3236         (m_grfKeyState & MK_LBUTTON))
3237     {
3238         if (m_pCurDropTarget)
3239         {
3240             m_pCurDropTarget->DragLeave();
3241             m_pCurDropTarget.Release();
3242         }
3243 
3244         /* Restore the selection */
3245         m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
3246         for (UINT i = 0 ; i < m_cidl; i++)
3247             SelectItem(m_apidl[i], SVSI_SELECT);
3248 
3249         /* Reposition the items */
3250         int lvIndex = -1;
3251         while ((lvIndex = m_ListView.GetNextItem(lvIndex,  LVNI_SELECTED)) > -1)
3252         {
3253             POINT ptItem;
3254             if (m_ListView.GetItemPosition(lvIndex, &ptItem))
3255             {
3256                 ptItem.x += pt.x - m_ptFirstMousePos.x;
3257                 ptItem.y += pt.y - m_ptFirstMousePos.y;
3258                 m_ListView.SetItemPosition(lvIndex, &ptItem);
3259             }
3260         }
3261     }
3262     else if (m_pCurDropTarget)
3263     {
3264         m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
3265         m_pCurDropTarget.Release();
3266     }
3267 
3268     m_pCurDataObject.Release();
3269     m_iDragOverItem = 0;
3270     return S_OK;
3271 }
3272 
3273 /**********************************************************
3274  * ISVDropSource implementation
3275  */
3276 
3277 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
3278 {
3279     TRACE("(%p)\n", this);
3280 
3281     if (fEscapePressed)
3282         return DRAGDROP_S_CANCEL;
3283     else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
3284         return DRAGDROP_S_DROP;
3285     else
3286         return S_OK;
3287 }
3288 
3289 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
3290 {
3291     TRACE("(%p)\n", this);
3292 
3293     return DRAGDROP_S_USEDEFAULTCURSORS;
3294 }
3295 
3296 /**********************************************************
3297  * ISVViewObject implementation
3298  */
3299 
3300 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)
3301 {
3302     FIXME("Stub: this=%p\n", this);
3303 
3304     return E_NOTIMPL;
3305 }
3306 
3307 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
3308 {
3309     FIXME("Stub: this=%p\n", this);
3310 
3311     return E_NOTIMPL;
3312 }
3313 
3314 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
3315 {
3316     FIXME("Stub: this=%p\n", this);
3317 
3318     return E_NOTIMPL;
3319 }
3320 
3321 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3322 {
3323     FIXME("Stub: this=%p\n", this);
3324 
3325     return E_NOTIMPL;
3326 }
3327 
3328 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3329 {
3330     FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink);
3331 
3332     /* FIXME: we set the AdviseSink, but never use it to send any advice */
3333     m_pAdvSink = pAdvSink;
3334     m_dwAspects = aspects;
3335     m_dwAdvf = advf;
3336 
3337     return S_OK;
3338 }
3339 
3340 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3341 {
3342     TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3343 
3344     if (ppAdvSink)
3345     {
3346         *ppAdvSink = m_pAdvSink;
3347         m_pAdvSink.p->AddRef();
3348     }
3349 
3350     if (pAspects)
3351         *pAspects = m_dwAspects;
3352 
3353     if (pAdvf)
3354         *pAdvf = m_dwAdvf;
3355 
3356     return S_OK;
3357 }
3358 
3359 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3360 {
3361     if (IsEqualIID(guidService, SID_IShellBrowser))
3362         return m_pShellBrowser->QueryInterface(riid, ppvObject);
3363     else if(IsEqualIID(guidService, SID_IFolderView))
3364         return QueryInterface(riid, ppvObject);
3365 
3366     return E_NOINTERFACE;
3367 }
3368 
3369 HRESULT CDefView::_MergeToolbar()
3370 {
3371     CComPtr<IExplorerToolbar> ptb;
3372     HRESULT hr = S_OK;
3373 
3374     hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3375     if (FAILED(hr))
3376         return hr;
3377 
3378     m_Category = CGID_DefViewFrame;
3379 
3380     hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3381     if (FAILED(hr))
3382         return hr;
3383 
3384     if (hr == S_FALSE)
3385         return S_OK;
3386 
3387 #if 0
3388     hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3389     if (FAILED(hr))
3390         return hr;
3391 #endif
3392 
3393     return S_OK;
3394 }
3395 
3396 // The default processing of IShellFolderView callbacks
3397 HRESULT CDefView::DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3398 {
3399     // TODO: SFVM_GET_CUSTOMVIEWINFO, SFVM_WINDOWCREATED
3400     TRACE("CDefView::DefMessageSFVCB uMsg=%u\n", uMsg);
3401     return E_NOTIMPL;
3402 }
3403 
3404 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3405 {
3406     HRESULT hr = E_NOTIMPL;
3407 
3408     if (m_pShellFolderViewCB)
3409     {
3410         hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam);
3411     }
3412 
3413     if (hr == E_NOTIMPL)
3414     {
3415         hr = DefMessageSFVCB(uMsg, wParam, lParam);
3416     }
3417 
3418     return hr;
3419 }
3420 
3421 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
3422 {
3423     return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
3424 }
3425 
3426 HRESULT WINAPI SHCreateShellFolderViewEx(
3427     LPCSFV psvcbi,    /* [in] shelltemplate struct */
3428     IShellView **ppsv) /* [out] IShellView pointer */
3429 {
3430     CComPtr<IShellView> psv;
3431     HRESULT hRes;
3432 
3433     TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3434       psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback,
3435       psvcbi->fvm, psvcbi->psvOuter);
3436 
3437     *ppsv = NULL;
3438     hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv));
3439     if (FAILED_UNEXPECTEDLY(hRes))
3440         return hRes;
3441 
3442     *ppsv = psv.Detach();
3443     return hRes;
3444 }
3445 
3446 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv,
3447                         IShellView **ppsv)
3448 {
3449     CComPtr<IShellView> psv;
3450     HRESULT hRes;
3451 
3452     *ppsv = NULL;
3453     if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv))
3454         return E_INVALIDARG;
3455 
3456     TRACE("sf=%p outer=%p callback=%p\n",
3457       pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb);
3458 
3459     hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv));
3460     if (FAILED(hRes))
3461         return hRes;
3462 
3463     if (pcsfv->psfvcb)
3464     {
3465         CComPtr<IShellFolderView> sfv;
3466         if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv))))
3467         {
3468             sfv->SetCallback(pcsfv->psfvcb, NULL);
3469         }
3470     }
3471 
3472     *ppsv = psv.Detach();
3473     return hRes;
3474 }
3475