[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / CDefView.cpp
index 1b63d1c..6e4c47c 100644 (file)
  * built according to the columns shown.
  *
  * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
- *
- * FIXME: ShellView_FillList: consider sort orders
  */
 
 /*
 TODO:
-1. Load/Save the view state from/into the stream provided by the ShellBrowser.
-2. Let the shell folder sort items.
-3. Code to merge menus in the shellbrowser is incorrect.
-4. Move the background context menu creation into shell view. It should store the
-    shell view HWND to send commands.
-5. Send init, measure, and draw messages to context menu during tracking.
-6. Shell view should do SetCommandTarget on internet toolbar.
-7. When editing starts on item, set edit text to for editing value.
-8. When shell view is called back for item info, let listview save the value.
-9. Shell view should update status bar.
-10. Fix shell view to handle view mode popup exec.
-11. The background context menu should have a pidl just like foreground menus. This
-    causes crashes when dynamic handlers try to use the NULL pidl.
-12. The SHELLDLL_DefView should not be filled with blue unconditionally. This causes
-    annoying flashing of blue even on XP, and is not correct.
-13. Reorder of columns doesn't work - might be bug in comctl32
+- Load/Save the view state from/into the stream provided by the ShellBrowser.
+- Code to merge menus in the shellbrowser is incorrect.
+- Move the background context menu creation into shell view. It should store the
+   shell view HWND to send commands.
+- Shell view should do SetCommandTarget on internet toolbar.
+- When editing starts on item, set edit text to for editing value.
+- When shell view is called back for item info, let listview save the value.
+- Fix shell view to handle view mode popup exec.
+- The background context menu should have a pidl just like foreground menus. This
+   causes crashes when dynamic handlers try to use the NULL pidl.
+- The SHELLDLL_DefView should not be filled with blue unconditionally. This causes
+   annoying flashing of blue even on XP, and is not correct.
+- Reorder of columns doesn't work - might be bug in comctl32
 */
 
 #include "precomp.h"
@@ -71,7 +66,7 @@ typedef struct
 class CDefView :
     public CWindowImpl<CDefView, CWindow, CControlWinTraits>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public IShellView,
+    public IShellView2,
     public IFolderView,
     public IShellFolderView,
     public IOleCommandTarget,
@@ -85,6 +80,7 @@ class CDefView :
         CComPtr<IShellFolder2>    m_pSF2Parent;
         CComPtr<IShellBrowser>    m_pShellBrowser;
         CComPtr<ICommDlgBrowser>  m_pCommDlgBrowser;
+        CComPtr<IShellFolderViewDual> m_pShellFolderViewDual;
         CListView                 m_ListView;
         HWND                      m_hWndParent;
         FOLDERSETTINGS            m_FolderSettings;
@@ -92,19 +88,21 @@ class CDefView :
         BOOL                      m_menusLoaded;
         UINT                      m_uState;
         UINT                      m_cidl;
-        PCUITEMID_CHILD_ARRAY     m_apidl;
+        PCUITEMID_CHILD          *m_apidl;
+        PIDLIST_ABSOLUTE          m_pidlParent;
         LISTVIEW_SORT_INFO        m_sortInfo;
-        ULONG                     m_hNotify;            /* change notification handle */
+        ULONG                     m_hNotify;            /* Change notification handle */
         HACCEL                    m_hAccel;
         DWORD                     m_dwAspects;
         DWORD                     m_dwAdvf;
         CComPtr<IAdviseSink>      m_pAdvSink;
         // for drag and drop
-        CComPtr<IDropTarget>      m_pCurDropTarget;        /* The sub-item, which is currently dragged over */
-        CComPtr<IDataObject>      m_pCurDataObject;        /* The dragged data-object */
-        LONG                      m_iDragOverItem;        /* Dragged over item's index, iff m_pCurDropTarget != NULL */
-        UINT                      m_cScrollDelay;        /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
-        POINT                     m_ptLastMousePos;        /* Mouse position at last DragOver call */
+        CComPtr<IDataObject>      m_pSourceDataObject;
+        CComPtr<IDropTarget>      m_pCurDropTarget;     /* The sub-item, which is currently dragged over */
+        CComPtr<IDataObject>      m_pCurDataObject;     /* The dragged data-object */
+        LONG                      m_iDragOverItem;      /* Dragged over item's index, iff m_pCurDropTarget != NULL */
+        UINT                      m_cScrollDelay;       /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
+        POINT                     m_ptLastMousePos;     /* Mouse position at last DragOver call */
         //
         CComPtr<IContextMenu>     m_pCM;
 
@@ -112,6 +110,7 @@ class CDefView :
 
         CLSID m_Category;
         HMENU m_hView;
+        BOOL m_Destroyed;
     private:
 
         HRESULT _MergeToolbar();
@@ -123,12 +122,12 @@ class CDefView :
         HRESULT IncludeObject(PCUITEMID_CHILD pidl);
         HRESULT OnDefaultCommand();
         HRESULT OnStateChange(UINT uFlags);
+        void UpdateStatusbar();
         void CheckToolbar();
         void SetStyle(DWORD dwAdd, DWORD dwRemove);
         BOOL CreateList();
         void UpdateListColors();
         BOOL InitList();
-        static INT CALLBACK CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData);
         static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
 
         PCUITEMID_CHILD _PidlByItem(int i);
@@ -137,6 +136,7 @@ class CDefView :
         BOOLEAN LV_AddItem(PCUITEMID_CHILD pidl);
         BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl);
         BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew);
+        BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl);
         static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg);
         HRESULT FillList();
         HMENU BuildFileMenu();
@@ -147,6 +147,7 @@ class CDefView :
         void OnDeactivate();
         void DoActivate(UINT uState);
         HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
+        HRESULT InvokeContextMenuCommand(UINT uCommand);
         LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
 
         // *** IOleWindow methods ***
@@ -166,6 +167,12 @@ class CDefView :
         virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags);
         virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv);
 
+        // *** IShellView2 methods ***
+        virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type);
+        virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params);
+        virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl);
+        virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point);
+
         // *** IFolderView methods ***
         virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode);
         virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode);
@@ -239,13 +246,15 @@ class CDefView :
         // *** IServiceProvider methods ***
         virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
 
-        // message handlers
+        // Message handlers
         LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+        LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+        LRESULT OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
@@ -263,9 +272,9 @@ class CDefView :
         {
             static ATL::CWndClassInfo wc =
             {
-                {   sizeof(WNDCLASSEX), 0, StartWindowProc,
+                {   sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc,
                     0, 0, NULL, NULL,
-                    LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BACKGROUND + 1), NULL, SV_CLASS_NAME, NULL
+                    LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, SV_CLASS_NAME, NULL
                 },
                 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
             };
@@ -279,10 +288,10 @@ class CDefView :
 
         static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         {
-            CDefView                        *pThis;
-            LRESULT                            result;
+            CDefView *pThis;
+            LRESULT  result;
 
-            // must hold a reference during message handling
+            // Must hold a reference during message handling
             pThis = reinterpret_cast<CDefView *>(hWnd);
             pThis->AddRef();
             result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam);
@@ -294,6 +303,8 @@ class CDefView :
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
         MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
+        MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate)
+        MESSAGE_HANDLER(WM_NCDESTROY, OnNCDestroy)
         MESSAGE_HANDLER(WM_CREATE, OnCreate)
         MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
         MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
@@ -313,8 +324,10 @@ class CDefView :
         END_MSG_MAP()
 
         BEGIN_COM_MAP(CDefView)
-        COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
+        // Windows returns E_NOINTERFACE for IOleWindow
+        // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
         COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView)
+        COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2)
         COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView)
         COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView)
         COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
@@ -325,13 +338,6 @@ class CDefView :
         END_COM_MAP()
 };
 
-/* ListView Header ID's */
-#define LISTVIEW_COLUMN_NAME 0
-#define LISTVIEW_COLUMN_SIZE 1
-#define LISTVIEW_COLUMN_TYPE 2
-#define LISTVIEW_COLUMN_TIME 3
-#define LISTVIEW_COLUMN_ATTRIB 4
-
 /*menu items */
 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
@@ -340,9 +346,9 @@ class CDefView :
 #define ID_LISTVIEW     1
 
 /*windowsx.h */
-#define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
-#define GET_WM_COMMAND_HWND(wp, lp)             (HWND)(lp)
-#define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
+#define GET_WM_COMMAND_ID(wp, lp)       LOWORD(wp)
+#define GET_WM_COMMAND_HWND(wp, lp)     (HWND)(lp)
+#define GET_WM_COMMAND_CMD(wp, lp)      HIWORD(wp)
 
 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
 
@@ -354,6 +360,7 @@ CDefView::CDefView() :
     m_uState(0),
     m_cidl(0),
     m_apidl(NULL),
+    m_pidlParent(NULL),
     m_hNotify(0),
     m_hAccel(NULL),
     m_dwAspects(0),
@@ -361,7 +368,8 @@ CDefView::CDefView() :
     m_iDragOverItem(0),
     m_cScrollDelay(0),
     m_isEditing(FALSE),
-    m_hView(NULL)
+    m_hView(NULL),
+    m_Destroyed(FALSE)
 {
     ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
     ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
@@ -459,6 +467,26 @@ void CDefView::CheckToolbar()
     }
 }
 
+void CDefView::UpdateStatusbar()
+{
+    WCHAR szFormat[MAX_PATH] = {0};
+    WCHAR szObjects[MAX_PATH] = {0};
+    UINT cSelectedItems;
+
+    cSelectedItems = m_ListView.GetSelectedCount();
+    if (cSelectedItems)
+    {
+        LoadStringW(shell32_hInstance, IDS_OBJECTS_SELECTED, szFormat, _countof(szFormat));
+        StringCchPrintfW(szObjects, MAX_PATH, szFormat, cSelectedItems);
+    }
+    else
+    {
+        LoadStringW(shell32_hInstance, IDS_OBJECTS, szFormat, _countof(szFormat));
+        StringCchPrintfW(szObjects, MAX_PATH, szFormat, m_ListView.GetItemCount());
+    }
+    m_pShellBrowser->SetStatusTextSB(szObjects);
+}
+
 /**********************************************************
  *
  * ##### helperfunctions for initializing the view #####
@@ -482,7 +510,8 @@ void CDefView::SetStyle(DWORD dwAdd, DWORD dwRemove)
 * - creates the list view window
 */
 BOOL CDefView::CreateList()
-{   DWORD dwStyle, dwExStyle;
+{
+    DWORD dwStyle, dwExStyle;
 
     TRACE("%p\n", this);
 
@@ -531,7 +560,7 @@ BOOL CDefView::CreateList()
         dwExStyle &= ~WS_EX_CLIENTEDGE;
 
     RECT rcListView = {0,0,0,0};
-    m_ListView.Create(m_hWnd, rcListView, NULL,dwStyle, dwExStyle, ID_LISTVIEW);
+    m_ListView.Create(m_hWnd, rcListView, L"FolderView", dwStyle, dwExStyle, ID_LISTVIEW);
 
     if (!m_ListView)
         return FALSE;
@@ -553,27 +582,33 @@ void CDefView::UpdateListColors()
         /* Check if drop shadows option is enabled */
         BOOL bDropShadow = FALSE;
         DWORD cbDropShadow = sizeof(bDropShadow);
-        WCHAR wszBuf[16] = L"";
+
+        /*
+         * The desktop ListView always take the default desktop colours, by
+         * remaining transparent and letting user32/win32k paint itself the
+         * desktop background color, if any.
+         */
+        m_ListView.SetBkColor(CLR_NONE);
 
         RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
                      L"ListviewShadow", RRF_RT_DWORD, NULL, &bDropShadow, &cbDropShadow);
-        if (bDropShadow && SystemParametersInfoW(SPI_GETDESKWALLPAPER, _countof(wszBuf), wszBuf, 0) && wszBuf[0])
+        if (bDropShadow)
         {
+            /* Set the icon background transparent */
             m_ListView.SetTextBkColor(CLR_NONE);
-            m_ListView.SetBkColor(CLR_NONE);
             m_ListView.SetTextColor(RGB(255, 255, 255));
             m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT, LVS_EX_TRANSPARENTSHADOWTEXT);
         }
         else
         {
+            /* Set the icon background as the same colour as the desktop */
             COLORREF crDesktop = GetSysColor(COLOR_DESKTOP);
             m_ListView.SetTextBkColor(crDesktop);
-            m_ListView.SetBkColor(crDesktop);
             if (GetRValue(crDesktop) + GetGValue(crDesktop) + GetBValue(crDesktop) > 128 * 3)
                 m_ListView.SetTextColor(RGB(0, 0, 0));
             else
                 m_ListView.SetTextColor(RGB(255, 255, 255));
-            m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT);
+            m_ListView.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT);
         }
     }
 }
@@ -585,8 +620,8 @@ void CDefView::UpdateListColors()
 */
 BOOL CDefView::InitList()
 {
-    SHELLDETAILS    sd;
-    WCHAR    szTemp[50];
+    SHELLDETAILS sd;
+    WCHAR szTemp[50];
     HIMAGELIST big_icons, small_icons;
 
     TRACE("%p\n", this);
@@ -616,30 +651,6 @@ BOOL CDefView::InitList()
     return TRUE;
 }
 
-/**********************************************************
-* ShellView_CompareItems()
-*
-* NOTES
-*  internal, CALLBACK for DSA_Sort
-*/
-INT CALLBACK CDefView::CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
-{
-    int ret;
-    TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
-
-    if (!lpData)
-        return 0;
-
-    IShellFolder* psf = reinterpret_cast<IShellFolder*>(lpData);
-    PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
-    PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
-
-    ret = (SHORT)SCODE_CODE(psf->CompareIDs(0, pidl1, pidl2));
-    TRACE("ret=%i\n", ret);
-
-    return ret;
-}
-
 /*************************************************************************
  * ShellView_ListViewCompareItems
  *
@@ -654,89 +665,20 @@ INT CALLBACK CDefView::CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpDat
  *     A negative value if the first item should precede the second,
  *     a positive value if the first item should follow the second,
  *     or zero if the two items are equivalent
- *
- * NOTES
- *    FIXME: function does what ShellView_CompareItems is supposed to do.
- *    unify it and figure out how to use the undocumented first parameter
- *    of IShellFolder_CompareIDs to do the job this function does and
- *    move this code to IShellFolder.
- *    make LISTVIEW_SORT_INFO obsolete
- *    the way this function works is only usable if we had only
- *    filesystemfolders  (25/10/99 jsch)
  */
 INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
 {
-    INT nDiff = 0;
-    FILETIME fd1, fd2;
-    char strName1[MAX_PATH], strName2[MAX_PATH];
-    BOOL bIsFolder1, bIsFolder2, bIsBothFolder;
     PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
     PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
-    LISTVIEW_SORT_INFO *pSortInfo = reinterpret_cast<LPLISTVIEW_SORT_INFO>(lpData);
-
-
-    bIsFolder1 = _ILIsFolder(pidl1);
-    bIsFolder2 = _ILIsFolder(pidl2);
-    bIsBothFolder = bIsFolder1 && bIsFolder2;
-
-    /* When sorting between a File and a Folder, the Folder gets sorted first */
-    if ( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
-    {
-        nDiff = bIsFolder1 ? -1 : 1;
-    }
-    else
-    {
-        /* Sort by Time: Folders or Files can be sorted */
+    CDefView *pThis = reinterpret_cast<CDefView*>(lpData);
 
-        if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
-        {
-            _ILGetFileDateTime(pidl1, &fd1);
-            _ILGetFileDateTime(pidl2, &fd2);
-            nDiff = CompareFileTime(&fd2, &fd1);
-        }
-        /* Sort by Attribute: Folder or Files can be sorted */
-        else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
-        {
-            _ILGetFileAttributes(pidl1, strName1, MAX_PATH);
-            _ILGetFileAttributes(pidl2, strName2, MAX_PATH);
-            nDiff = lstrcmpiA(strName1, strName2);
-        }
-        /* Sort by FileName: Folder or Files can be sorted */
-        else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
-        {
-            /* Sort by Text */
-            _ILSimpleGetText(pidl1, strName1, MAX_PATH);
-            _ILSimpleGetText(pidl2, strName2, MAX_PATH);
-            nDiff = lstrcmpiA(strName1, strName2);
-        }
-        /* Sort by File Size, Only valid for Files */
-        else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
-        {
-            nDiff = (INT)(_ILGetFileSize(pidl1, NULL, 0) - _ILGetFileSize(pidl2, NULL, 0));
-        }
-        /* Sort by File Type, Only valid for Files */
-        else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
-        {
-            /* Sort by Type */
-            _ILGetFileType(pidl1, strName1, MAX_PATH);
-            _ILGetFileType(pidl2, strName2, MAX_PATH);
-            nDiff = lstrcmpiA(strName1, strName2);
-        }
-    }
-    /*  If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
-
-    if (nDiff == 0)
-    {
-        _ILSimpleGetText(pidl1, strName1, MAX_PATH);
-        _ILSimpleGetText(pidl2, strName2, MAX_PATH);
-        nDiff = lstrcmpiA(strName1, strName2);
-    }
+    HRESULT hres = pThis->m_pSFParent->CompareIDs(pThis->m_sortInfo.nHeaderID, pidl1, pidl2);
+    if (FAILED_UNEXPECTEDLY(hres))
+        return 0;
 
-    if (!pSortInfo->bIsAscending)
-    {
+    SHORT nDiff = HRESULT_CODE(hres);
+    if (!pThis->m_sortInfo.bIsAscending)
         nDiff = -nDiff;
-    }
-
     return nDiff;
 }
 
@@ -775,7 +717,7 @@ int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
 */
 BOOLEAN CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
 {
-    LVITEMW    lvItem;
+    LVITEMW lvItem;
 
     TRACE("(%p)(pidl=%p)\n", this, pidl);
 
@@ -785,6 +727,7 @@ BOOLEAN CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
     lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/
     lvItem.pszText = LPSTR_TEXTCALLBACKW;                 /*get text on a callback basis*/
     lvItem.iImage = I_IMAGECALLBACK;                      /*get the image on a callback basis*/
+    lvItem.stateMask = LVIS_CUT;
 
     if (m_ListView.InsertItem(&lvItem) == -1)
         return FALSE;
@@ -822,11 +765,13 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew
     {
         lvItem.mask = LVIF_PARAM;        /* only the pidl */
         lvItem.iItem = nItem;
+        lvItem.iSubItem = 0;
         m_ListView.GetItem(&lvItem);
 
         SHFree(reinterpret_cast<LPVOID>(lvItem.lParam));
         lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
         lvItem.iItem = nItem;
+        lvItem.iSubItem = 0;
         lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew));    /* set the item's data */
         lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
         m_ListView.SetItem(&lvItem);
@@ -837,6 +782,32 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew
     return FALSE;
 }
 
+/**********************************************************
+* LV_ProdItem()
+*/
+BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
+{
+    int nItem;
+    LVITEMW lvItem;
+
+    TRACE("(%p)(pidl=%p)\n", this, pidl);
+
+    nItem = LV_FindItemByPidl(pidl);
+
+    if (-1 != nItem)
+    {
+        lvItem.mask = LVIF_IMAGE;
+        lvItem.iItem = nItem;
+        lvItem.iSubItem = 0;
+        lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
+        m_ListView.SetItem(&lvItem);
+        m_ListView.Update(nItem);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 /**********************************************************
 * ShellView_FillList()
 *
@@ -844,7 +815,7 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew
 * - sorts the list
 * - fills the list into the view
 */
-INT CALLBACK CDefView::fill_list( LPVOID ptr, LPVOID arg )
+INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg)
 {
     PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr);
     CDefView *pThis = static_cast<CDefView *>(arg);
@@ -879,7 +850,10 @@ HRESULT CDefView::FillList()
         {
             /* if the value is 1, then show all hidden files/folders */
             if (flagVal == 1)
+            {
                 dFlags |= SHCONTF_INCLUDEHIDDEN;
+                m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
+            }
         }
 
         /* close the key */
@@ -911,14 +885,17 @@ HRESULT CDefView::FillList()
         }
     }
 
-    /* sort the array */
-    DPA_Sort(hdpa, CompareItems, reinterpret_cast<LPARAM>(m_pSFParent.p));
-
     /*turn the listview's redrawing off*/
     m_ListView.SetRedraw(FALSE);
 
     DPA_DestroyCallback( hdpa, fill_list, this);
 
+    /* sort the array */
+    m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL);
+    m_sortInfo.bIsAscending = TRUE;
+    m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
+    m_ListView.SortItems(ListViewCompareItems, this);
+
     /*turn the listview's redrawing back on and force it to draw*/
     m_ListView.SetRedraw(TRUE);
 
@@ -939,10 +916,20 @@ LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bH
 
 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    if (m_hMenu)
-        DestroyMenu(m_hMenu);
-    RevokeDragDrop(m_hWnd);
-    SHChangeNotifyDeregister(m_hNotify);
+    if (!m_Destroyed)
+    {
+        m_Destroyed = TRUE;
+        if (m_hMenu)
+        {
+            DestroyMenu(m_hMenu);
+            m_hMenu = NULL;
+        }
+        RevokeDragDrop(m_hWnd);
+        SHChangeNotifyDeregister(m_hNotify);
+        m_hNotify = NULL;
+        SHFree(m_pidlParent);
+        m_pidlParent = NULL;
+    }
     bHandled = FALSE;
     return 0;
 }
@@ -971,20 +958,34 @@ LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
     return reinterpret_cast<LRESULT>(m_pShellBrowser.p);
 }
 
+LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    this->AddRef();
+    bHandled = FALSE;
+    return 0;
+}
+
+LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    this->Release();
+    bHandled = FALSE;
+    return 0;
+}
+
 /**********************************************************
 *  ShellView_OnCreate()
 */
 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    CComPtr<IDropTarget>                pdt;
-    SHChangeNotifyEntry ntreg;
-    CComPtr<IPersistFolder2>            ppf2;
+    CComPtr<IDropTarget>     pdt;
+    SHChangeNotifyEntry      ntreg;
+    CComPtr<IPersistFolder2> ppf2;
 
     TRACE("%p\n", this);
 
-    if(CreateList())
+    if (CreateList())
     {
-        if(InitList())
+        if (InitList())
         {
             FillList();
         }
@@ -1000,16 +1001,16 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
     m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
     if (ppf2)
     {
-        PIDLIST_ABSOLUTE pidlParent;
-        ppf2->GetCurFolder(&pidlParent);
+        ppf2->GetCurFolder(&m_pidlParent);
         ntreg.fRecursive = TRUE;
-        ntreg.pidl = pidlParent;
-        m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
-        SHFree(pidlParent);
+        ntreg.pidl = m_pidlParent;
+        m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
     }
 
     m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
 
+    UpdateStatusbar();
+
     return S_OK;
 }
 
@@ -1030,7 +1031,7 @@ HMENU CDefView::BuildFileMenu()
 
     HMENU hmenu = CreatePopupMenu();
 
-    //FIXME: get proper numbers ?
+    // FIXME: get proper numbers ?
     const UINT first = 0x7800;
     const UINT last  = 0x7A00;
     hr = cm->QueryContextMenu(hmenu, 0, first, last, 0);
@@ -1143,7 +1144,7 @@ UINT CDefView::GetSelections()
     SHFree(m_apidl);
 
     m_cidl = m_ListView.GetSelectedCount();
-    m_apidl = reinterpret_cast<PCUITEMID_CHILD_ARRAY>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
+    m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
     if (!m_apidl)
     {
         m_cidl = 0;
@@ -1166,13 +1167,30 @@ UINT CDefView::GetSelections()
     return m_cidl;
 }
 
+HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
+{
+    CMINVOKECOMMANDINFO cmi;
+
+    ZeroMemory(&cmi, sizeof(cmi));
+    cmi.cbSize = sizeof(cmi);
+    cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+    cmi.hwnd = m_hWnd;
+
+    if (GetKeyState(VK_SHIFT) & 0x8000)
+        cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
+
+    if (GetKeyState(VK_CONTROL) & 0x8000)
+        cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
+
+    return m_pCM->InvokeCommand(&cmi);
+}
+
 /**********************************************************
  *    ShellView_OpenSelectedItems()
  */
 HRESULT CDefView::OpenSelectedItems()
 {
     HMENU hMenu;
-    CMINVOKECOMMANDINFO cmi;
     UINT uCommand;
     HRESULT hResult;
 
@@ -1192,10 +1210,6 @@ HRESULT CDefView::OpenSelectedItems()
     if (FAILED(hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
     if (FAILED(hResult))
         goto cleanup;
@@ -1207,12 +1221,7 @@ HRESULT CDefView::OpenSelectedItems()
         goto cleanup;
     }
 
-    ZeroMemory(&cmi, sizeof(cmi));
-    cmi.cbSize = sizeof(cmi);
-    cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
-    cmi.hwnd = m_hWnd;
-
-    hResult = m_pCM->InvokeCommand(&cmi);
+    InvokeContextMenuCommand(uCommand);
 
 cleanup:
     
@@ -1220,10 +1229,7 @@ cleanup:
         DestroyMenu(hMenu);
 
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     return hResult;
 }
@@ -1233,12 +1239,10 @@ cleanup:
  */
 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    WORD                 x;
-    WORD                 y;
-    UINT                 uCommand;
-    HMENU                hMenu;
-    CMINVOKECOMMANDINFO  cmi;
-    HRESULT              hResult;
+    WORD    x, y;
+    UINT    uCommand;
+    HMENU   hMenu;
+    HRESULT hResult;
 
     // for some reason I haven't figured out, we sometimes recurse into this method
     if (m_pCM != NULL)
@@ -1259,17 +1263,10 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
     if (FAILED( hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
 
-    if (m_FolderSettings.fFlags & FWF_DESKTOP)
-        SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
-
     uCommand = TrackPopupMenu(hMenu,
                               TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
                               x, y, 0, m_hWnd, NULL);
@@ -1279,19 +1276,11 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
     if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
         goto cleanup;
 
-    ZeroMemory(&cmi, sizeof(cmi));
-    cmi.cbSize = sizeof(cmi);
-    cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
-    cmi.hwnd = m_hWnd;
-    m_pCM->InvokeCommand(&cmi);
+    InvokeContextMenuCommand(uCommand);
 
 cleanup:
-    
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1302,7 +1291,6 @@ cleanup:
 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
 {
     HRESULT hResult;
-    CMINVOKECOMMANDINFO cmi;
     HMENU hMenu;
 
     hMenu = CreatePopupMenu();
@@ -1313,27 +1301,15 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
     if (FAILED( hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
 
-    ZeroMemory(&cmi, sizeof(cmi));
-    cmi.cbSize = sizeof(cmi);
-    cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
-    cmi.hwnd = m_hWnd;
-    m_pCM->InvokeCommand(&cmi);
+    InvokeContextMenuCommand(uCommand);
 
 cleanup:
-
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1350,15 +1326,14 @@ cleanup:
 */
 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    WORD                                wWidth;
-    WORD                                wHeight;
+    WORD wWidth, wHeight;
 
-    wWidth = LOWORD(lParam);
+    wWidth  = LOWORD(lParam);
     wHeight = HIWORD(lParam);
 
     TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
 
-    /*resize the ListView to fit our window*/
+    /* Resize the ListView to fit our window */
     if (m_ListView)
     {
         ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
@@ -1401,7 +1376,7 @@ void CDefView::DoActivate(UINT uState)
     }
     else
     {
-        if(m_hMenu)
+        if (m_hMenu)
         {
             if (!m_menusLoaded)
             {
@@ -1549,9 +1524,10 @@ LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHa
 */
 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    DWORD                                dwCmdID;
-    DWORD                                dwCmd;
-    HWND                                hwndCmd;
+    DWORD dwCmdID;
+    DWORD dwCmd;
+    HWND  hwndCmd;
+    int   nCount; 
 
     dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
     dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
@@ -1593,7 +1569,17 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
             m_sortInfo.nHeaderID = dwCmdID - 0x30;
             m_sortInfo.bIsAscending = TRUE;
             m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
-            m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
+            m_ListView.SortItems(ListViewCompareItems, this);
+            break;
+
+        case FCIDM_SHVIEW_SELECTALL:
+            m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
+            break;
+
+        case FCIDM_SHVIEW_INVERTSELECTION:
+            nCount = m_ListView.GetItemCount();
+            for (int i=0; i < nCount; i++)
+                m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
             break;
 
         case FCIDM_SHVIEW_REFRESH:
@@ -1713,7 +1699,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
                 m_sortInfo.bIsAscending = TRUE;
             m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
 
-            m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
+            m_ListView.SortItems(ListViewCompareItems, this);
             break;
 
         case LVN_GETDISPINFOA:
@@ -1754,12 +1740,24 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
             {
                 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
             }
+            if(lpdi->item.mask & LVIF_STATE)
+            {
+                ULONG attributes = SFGAO_HIDDEN;
+                if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
+                {
+                    if (attributes & SFGAO_HIDDEN)
+                    {
+                        lpdi->item.state |= LVIS_CUT;
+                    }
+                }
+            }
             lpdi->item.mask |= LVIF_DI_SETITEM;
             break;
 
         case LVN_ITEMCHANGED:
             TRACE("-- LVN_ITEMCHANGED %p\n", this);
             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
+            UpdateStatusbar();
             break;
 
         case LVN_BEGINDRAG:
@@ -1789,7 +1787,12 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
                     }
 
                     DWORD dwEffect2;
+
+                    m_pSourceDataObject = pda;
+
                     DoDragDrop(pda, this, dwEffect, &dwEffect2);
+
+                    m_pSourceDataObject.Release();
                 }
             }
             break;
@@ -1829,6 +1832,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
                 {
                     lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
                     lvItem.iItem = lpdi->item.iItem;
+                    lvItem.iSubItem = 0;
                     lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
                     lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
                     m_ListView.SetItem(&lvItem);
@@ -1848,34 +1852,87 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
     return 0;
 }
 
+/*
+ * This is just a quick hack to make the desktop work correctly.
+ * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
+ * a folder should know if it should update upon a change notification.
+ * It is exported by merged folders at a minimum.
+ */
+static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
+{
+    if (!pidl1 || !pidl2)
+        return FALSE;
+    if (ILIsParent(pidl1, pidl2, TRUE))
+        return TRUE;
+
+    if (_ILIsDesktop(pidl1))
+    {
+        PIDLIST_ABSOLUTE deskpidl;
+        SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
+        if (ILIsParent(deskpidl, pidl2, TRUE))
+        {
+            ILFree(deskpidl);
+            return TRUE;
+        }
+        ILFree(deskpidl);
+        SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
+        if (ILIsParent(deskpidl, pidl2, TRUE))
+        {
+            ILFree(deskpidl);
+            return TRUE;
+        }
+        ILFree(deskpidl);
+    }
+    return FALSE;
+}
+
 /**********************************************************
 * ShellView_OnChange()
 */
 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
+    BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
+    BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
 
     TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
 
-    switch (lParam)
+    switch (lParam &~ SHCNE_INTERRUPT)
     {
         case SHCNE_MKDIR:
         case SHCNE_CREATE:
-            LV_AddItem(ILFindLastID(Pidls[0]));
+            if (bParent0)
+            {
+                if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
+                {
+                    LV_AddItem(ILFindLastID(Pidls[0]));
+                }
+                else
+                {
+                    LV_ProdItem(ILFindLastID(Pidls[0]));
+                }
+            }
             break;
 
         case SHCNE_RMDIR:
         case SHCNE_DELETE:
-            LV_DeleteItem(ILFindLastID(Pidls[0]));
+            if (bParent0)
+                LV_DeleteItem(ILFindLastID(Pidls[0]));
             break;
 
         case SHCNE_RENAMEFOLDER:
         case SHCNE_RENAMEITEM:
-            LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
+            if (bParent0 && bParent1)
+                LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
+            else if (bParent0)
+                LV_DeleteItem(ILFindLastID(Pidls[0]));
+            else if (bParent1)
+                LV_AddItem(ILFindLastID(Pidls[1]));
             break;
 
         case SHCNE_UPDATEITEM:
-            LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
+            if (bParent0)
+                LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
             break;
 
         case SHCNE_UPDATEDIR:
@@ -1897,12 +1954,9 @@ LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bH
         return FALSE;
     }
 
-    CComPtr<IContextMenu2> pCM2;
-    HRESULT hres = m_pCM.p->QueryInterface(IID_PPV_ARG(IContextMenu2, &pCM2));
-    if(FAILED(hres))
-        return FALSE;
-
-    if (pCM2.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK)
+    LRESULT result;
+    HRESULT hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
+    if (SUCCEEDED(hres))
         return TRUE;
     else
         return FALSE;
@@ -2021,24 +2075,22 @@ HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
 
 HRESULT WINAPI CDefView::UIActivate(UINT uState)
 {
-    /*
-        CHAR    szName[MAX_PATH];
-    */
-    LRESULT    lResult;
-    int    nPartArray[1] = { -1};
+    // CHAR szName[MAX_PATH];
+    LRESULT lResult;
+    int nPartArray[1] = { -1};
 
     TRACE("(%p)->(state=%x) stub\n", this, uState);
 
-    /*don't do anything if the state isn't really changing*/
+    /* don't do anything if the state isn't really changing */
     if (m_uState == uState)
     {
         return S_OK;
     }
 
-    /*OnActivate handles the menu merging and internal state*/
+    /* OnActivate handles the menu merging and internal state */
     DoActivate(uState);
 
-    /*only do This if we are active*/
+    /* only do This if we are active */
     if (uState != SVUIA_DEACTIVATE)
     {
 
@@ -2070,7 +2122,7 @@ HRESULT WINAPI CDefView::Refresh()
 
 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
 {
-    OLEMENUGROUPWIDTHS                    omw = { { 0, 0, 0, 0, 0, 0 } };
+    OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
 
     *phWnd = 0;
 
@@ -2082,24 +2134,24 @@ HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTI
         TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
 
     /* Validate the Shell Browser */
-    if (psb == NULL)
+    if (psb == NULL || m_hWnd)
         return E_UNEXPECTED;
 
-    /*set up the member variables*/
+    /* Set up the member variables */
     m_pShellBrowser = psb;
     m_FolderSettings = *lpfs;
 
-    /*get our parent window*/
+    /* Get our parent window */
     m_pShellBrowser->GetWindow(&m_hWndParent);
 
-    /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
+    /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
     m_pCommDlgBrowser = NULL;
     if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
     {
         TRACE("-- CommDlgBrowser\n");
     }
 
-    Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U);
+    Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
     if (m_hWnd == NULL)
         return E_FAIL;
 
@@ -2129,7 +2181,7 @@ HRESULT WINAPI CDefView::DestroyViewWindow()
 {
     TRACE("(%p)\n", this);
 
-    /*Make absolutely sure all our UI is cleaned up.*/
+    /* Make absolutely sure all our UI is cleaned up */
     UIActivate(SVUIA_DEACTIVATE);
 
     if (m_hAccel)
@@ -2147,7 +2199,7 @@ HRESULT WINAPI CDefView::DestroyViewWindow()
     if (m_hMenu)
     {
         DestroyMenu(m_hMenu);
-        m_hView = NULL;
+        m_hMenu = NULL;
     }
 
     if (m_ListView)
@@ -2260,6 +2312,12 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
                     return hr;
                 *ppvOut = pcm;
             }
+            else if (IsEqualIID(riid, IID_IDispatch))
+            {
+                if (m_pShellFolderViewDual == NULL)
+                    hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
+                hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
+            }
             break;
 
         case SVGIO_SELECTION:
@@ -2454,6 +2512,34 @@ HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_
     return E_NOTIMPL;
 }
 
+/**********************************************************
+ * IShellView2 implementation
+ */
+
+HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
+{
+    FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
+{
+    FIXME("(%p)->(%p) stub\n", this, view_params);
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
+{
+    FIXME("(%p)->(%p) stub\n", this, new_pidl);
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
+{
+    FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
+    return E_NOTIMPL;
+}
+
 /**********************************************************
  * IShellFolderView implementation
  */
@@ -2803,7 +2889,7 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf
     {
         /* We are not above one of the listview's subitems. Bind to the parent folder's
          * DropTarget interface. */
-        hr = m_pSFParent->QueryInterface(IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
+        hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
     }
     else
     {
@@ -2857,7 +2943,23 @@ HRESULT WINAPI CDefView::DragLeave()
 
 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-    if (m_pCurDropTarget)
+    ERR("GetKeyState(VK_LBUTTON): %d\n", GetKeyState(VK_LBUTTON));
+
+    if ((m_iDragOverItem == -1) && 
+        (*pdwEffect & DROPEFFECT_MOVE) && 
+        (GetKeyState(VK_LBUTTON) != 0) &&
+        (m_pSourceDataObject.p) && 
+        (SHIsSameObject(pDataObject, m_pSourceDataObject)))
+    {
+        ERR("Should implement moving items here!\n");
+
+        if (m_pCurDropTarget)
+        {
+            m_pCurDropTarget->DragLeave();
+            m_pCurDropTarget.Release();
+        }
+    }
+    else if (m_pCurDropTarget)
     {
         m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
         m_pCurDropTarget.Release();
@@ -2966,8 +3068,7 @@ HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID rii
 
 HRESULT CDefView::_MergeToolbar()
 {
-    CComPtr<IExplorerToolbar> ptb; // [sp+8h] [bp-4h]@1
-
+    CComPtr<IExplorerToolbar> ptb;
     HRESULT hr = S_OK;
 
     hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
@@ -2998,3 +3099,8 @@ HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newVie
 {
     return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
 }
+
+HRESULT WINAPI CDefView_Constructor(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
+{
+    return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
+}