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