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