[SHELL32] Add CDefView::DefMessageSFVCB (Retrial of #1145) (#1151)
[reactos.git] / dll / win32 / shell32 / CDefView.cpp
index 1492724..b382dcd 100644 (file)
@@ -72,6 +72,7 @@ class CDefView :
     private:
         CComPtr<IShellFolder>     m_pSFParent;
         CComPtr<IShellFolder2>    m_pSF2Parent;
+        CComPtr<IShellFolderViewCB> m_pShellFolderViewCB;
         CComPtr<IShellBrowser>    m_pShellBrowser;
         CComPtr<ICommDlgBrowser>  m_pCommDlgBrowser;
         CComPtr<IShellFolderViewDual> m_pShellFolderViewDual;
@@ -101,6 +102,7 @@ class CDefView :
         UINT                      m_cScrollDelay;       /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
         POINT                     m_ptLastMousePos;     /* Mouse position at last DragOver call */
         POINT                     m_ptFirstMousePos;    /* Mouse position when the drag operation started */
+        DWORD                     m_grfKeyState;
         //
         CComPtr<IContextMenu>     m_pCM;
 
@@ -112,6 +114,7 @@ class CDefView :
     private:
         HRESULT _MergeToolbar();
         BOOL _Sort();
+        HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
 
     public:
         CDefView();
@@ -122,10 +125,10 @@ class CDefView :
         HRESULT OnStateChange(UINT uFlags);
         void UpdateStatusbar();
         void CheckToolbar();
-        void SetStyle(DWORD dwAdd, DWORD dwRemove);
         BOOL CreateList();
         void UpdateListColors();
         BOOL InitList();
+        HRESULT DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
         static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
 
         PCUITEMID_CHILD _PidlByItem(int i);
@@ -415,7 +418,7 @@ HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl)
     {
         TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
         ret = m_pCommDlgBrowser->IncludeObject(this, pidl);
-        TRACE("--0x%08x\n", ret);
+        TRACE("-- returns 0x%08x\n", ret);
     }
 
     return ret;
@@ -429,7 +432,7 @@ HRESULT CDefView::OnDefaultCommand()
     {
         TRACE("ICommDlgBrowser::OnDefaultCommand\n");
         ret = m_pCommDlgBrowser->OnDefaultCommand(this);
-        TRACE("-- returns %08x\n", ret);
+        TRACE("-- returns 0x%08x\n", ret);
     }
 
     return ret;
@@ -497,18 +500,6 @@ void CDefView::UpdateStatusbar()
  *
  * ##### helperfunctions for initializing the view #####
  */
-/**********************************************************
- *    change the style of the listview control
- */
-void CDefView::SetStyle(DWORD dwAdd, DWORD dwRemove)
-{
-    DWORD tmpstyle;
-
-    TRACE("(%p)\n", this);
-
-    tmpstyle = ::GetWindowLongPtrW(m_ListView, GWL_STYLE);
-    ::SetWindowLongPtrW(m_ListView, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
-}
 
 /**********************************************************
 * ShellView_CreateList()
@@ -517,7 +508,9 @@ void CDefView::SetStyle(DWORD dwAdd, DWORD dwRemove)
 */
 BOOL CDefView::CreateList()
 {
+    HRESULT hr;
     DWORD dwStyle, dwExStyle;
+    UINT ViewMode;
 
     TRACE("%p\n", this);
 
@@ -530,6 +523,16 @@ BOOL CDefView::CreateList()
     else
         dwStyle |= LVS_ALIGNTOP | LVS_SHOWSELALWAYS;
 
+    ViewMode = m_FolderSettings.ViewMode;
+    hr = _DoFolderViewCB(SFVM_DEFVIEWMODE, NULL, (LPARAM)&ViewMode);
+    if (SUCCEEDED(hr))
+    {
+        if (ViewMode >= FVM_FIRST && ViewMode <= FVM_LAST)
+            m_FolderSettings.ViewMode = ViewMode;
+        else
+            ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode, m_FolderSettings.ViewMode);
+    }
+
     switch (m_FolderSettings.ViewMode)
     {
         case FVM_ICON:
@@ -950,6 +953,8 @@ HRESULT CDefView::FillList()
     /*turn the listview's redrawing back on and force it to draw*/
     m_ListView.SetRedraw(TRUE);
 
+    _DoFolderViewCB(SFVM_LISTREFRESHED, NULL, NULL);
+
     return S_OK;
 }
 
@@ -1058,6 +1063,8 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
         m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
     }
 
+    /* _DoFolderViewCB(SFVM_GETNOTIFY, ??  ??) */
+
     m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
 
     UpdateStatusbar();
@@ -1110,8 +1117,6 @@ HRESULT CDefView::FillFileMenu()
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
-    IUnknown_SetSite(m_pCM, (IShellView *)this);
-
     HMENU hmenu = CreatePopupMenu();
 
     hr = m_pCM->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
@@ -1175,6 +1180,19 @@ HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange)
                        m_sortInfo.nHeaderID + 0x30, 
                        MF_BYCOMMAND);
 
+    if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST)
+    {
+        EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED);
+    }
+    else
+    {
+        EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND); 
+
+        if (GetAutoArrange() == S_OK)
+            CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED);
+    }
+
+
     return S_OK;
 }
 
@@ -1274,8 +1292,6 @@ HRESULT CDefView::OpenSelectedItems()
     if (FAILED_UNEXPECTEDLY(hResult))
         goto cleanup;
 
-    IUnknown_SetSite(m_pCM, (IShellView *)this);
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY);
     if (FAILED_UNEXPECTEDLY(hResult))
         goto cleanup;
@@ -1327,8 +1343,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
     if (FAILED_UNEXPECTEDLY(hResult))
         goto cleanup;
 
-    IUnknown_SetSite(m_pCM, (IShellView *)this);
-
     /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */
     hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED_UNEXPECTEDLY(hResult))
@@ -1374,8 +1388,6 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
     if (FAILED_UNEXPECTEDLY( hResult))
         goto cleanup;
 
-    IUnknown_SetSite(m_pCM, (IShellView *)this);
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED_UNEXPECTEDLY( hResult))
         goto cleanup;
@@ -1417,6 +1429,8 @@ LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled
         ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
     }
 
+    _DoFolderViewCB(SFVM_SIZE, 0, 0);
+
     return 0;
 }
 
@@ -1542,25 +1556,25 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
     {
         case FCIDM_SHVIEW_SMALLICON:
             m_FolderSettings.ViewMode = FVM_SMALLICON;
-            SetStyle (LVS_SMALLICON, LVS_TYPEMASK);
+            m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
             CheckToolbar();
             break;
 
         case FCIDM_SHVIEW_BIGICON:
             m_FolderSettings.ViewMode = FVM_ICON;
-            SetStyle (LVS_ICON, LVS_TYPEMASK);
+            m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
             CheckToolbar();
             break;
 
         case FCIDM_SHVIEW_LISTVIEW:
             m_FolderSettings.ViewMode = FVM_LIST;
-            SetStyle (LVS_LIST, LVS_TYPEMASK);
+            m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
             CheckToolbar();
             break;
 
         case FCIDM_SHVIEW_REPORTVIEW:
             m_FolderSettings.ViewMode = FVM_DETAILS;
-            SetStyle (LVS_REPORT, LVS_TYPEMASK);
+            m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
             CheckToolbar();
             break;
 
@@ -1575,9 +1589,14 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
             break;
 
         case FCIDM_SHVIEW_SNAPTOGRID:
-        case FCIDM_SHVIEW_AUTOARRANGE:
             //FIXME
             break;
+        case FCIDM_SHVIEW_AUTOARRANGE:
+            if (GetAutoArrange() == S_OK)
+                m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0);
+            else
+                AutoArrange();
+            break;
         case FCIDM_SHVIEW_SELECTALL:
             m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
             break;
@@ -1596,6 +1615,7 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
         case FCIDM_SHVIEW_CUT:
         case FCIDM_SHVIEW_COPY:
         case FCIDM_SHVIEW_RENAME:
+        case FCIDM_SHVIEW_PROPERTIES:
             return OnExplorerCommand(dwCmdID, TRUE);
 
         case FCIDM_SHVIEW_INSERT:
@@ -1763,6 +1783,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
             TRACE("-- LVN_ITEMCHANGED %p\n", this);
             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
             UpdateStatusbar();
+            _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */);
             break;
 
         case LVN_BEGINDRAG:
@@ -1772,8 +1793,8 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
             if (GetSelections())
             {
                 CComPtr<IDataObject> pda;
-                DWORD dwAttributes = SFGAO_CANLINK;
-                DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
+                DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK;
+                DWORD dwEffect = DROPEFFECT_MOVE;
 
                 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
                 {
@@ -1781,10 +1802,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
 
                     if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
                     {
-                        if (dwAttributes & SFGAO_CANLINK)
-                        {
-                            dwEffect |= DROPEFFECT_LINK;
-                        }
+                        dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK);
                     }
                     
                     CComPtr<IAsyncOperation> piaso;
@@ -1843,7 +1861,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
                 LVITEMW lvItem;
 
                 pidl = _PidlByItem(lpdi->item);
-                PITEMID_CHILD pidlNew;
+                PITEMID_CHILD pidlNew = NULL;
                 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
 
                 if (SUCCEEDED(hr) && pidlNew)
@@ -2082,7 +2100,7 @@ HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
         if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
             return S_OK;
 
-        TRACE("-- key=0x04%lx\n", lpmsg->wParam) ;
+        TRACE("-- key=0x%04lx\n", lpmsg->wParam) ;
     }
 
     return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
@@ -2286,6 +2304,7 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
                 if (FAILED_UNEXPECTEDLY(hr))
                     return hr;
 
+                IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
             }
             else if (IsEqualIID(riid, IID_IDispatch))
             {
@@ -2304,6 +2323,10 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
             hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
             if (FAILED_UNEXPECTEDLY(hr))
                 return hr;
+
+            if (IsEqualIID(riid, IID_IContextMenu))
+                IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
+
             break;
     }
 
@@ -2358,7 +2381,7 @@ HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
         }
     }
 
-    SetStyle(dwStyle, LVS_TYPEMASK);
+    m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle);
 
     /* This will not necessarily be the actual mode set above.
        This mimics the behavior of Windows XP. */
@@ -2425,7 +2448,12 @@ HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
 
 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
 {
-    return E_NOTIMPL;
+    int lvIndex = LV_FindItemByPidl(pidl);
+    if (lvIndex == -1 || ppt == NULL)
+        return E_INVALIDARG;
+
+    m_ListView.GetItemPosition(lvIndex, ppt);
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
@@ -2454,7 +2482,7 @@ HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
 
 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
 {
-    return E_NOTIMPL;
+    return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE);
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
@@ -2490,7 +2518,21 @@ HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
 
 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
 {
-    return E_NOTIMPL;
+    /* Reset the selection */
+    m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
+
+    int lvIndex;
+    for (UINT i = 0 ; i < m_cidl; i++)
+    {
+        lvIndex = LV_FindItemByPidl(apidl[i]);
+        if (lvIndex != -1)
+        {
+            SelectItem(lvIndex, dwFlags);
+            m_ListView.SetItemPosition(lvIndex, &apt[i]);
+        }
+    }
+
+    return S_OK;
 }
 
 /**********************************************************
@@ -2573,6 +2615,8 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShell
     if (!*hwnd)
         return E_FAIL;
 
+    _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, NULL);
+
     SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
     UpdateWindow();
 
@@ -2623,8 +2667,9 @@ HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
 
 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
 {
-    FIXME("(%p) stub\n", this);
-    return E_NOTIMPL;
+    m_ListView.ModifyStyle(0, LVS_AUTOARRANGE);
+    m_ListView.Arrange(LVA_DEFAULT);
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
@@ -2719,14 +2764,22 @@ HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, U
 
 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
 {
-    FIXME("(%p)->(%p) stub\n", this, drop_target);
-    return E_NOTIMPL;
+    if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) && 
+        (m_pSourceDataObject.p))
+    {
+        return S_OK;
+    }
+
+    return S_FALSE;
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
 {
-    FIXME("(%p)->(%p) stub\n", this, pt);
-    return E_NOTIMPL;
+    if (!pt)
+        return E_INVALIDARG;
+
+    *pt = m_ptFirstMousePos;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
@@ -2773,8 +2826,11 @@ HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
 
 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB  *new_cb, IShellFolderViewCB **old_cb)
 {
-    FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
-    return E_NOTIMPL;
+    if (old_cb)
+        *old_cb = m_pShellFolderViewCB.Detach();
+
+    m_pShellFolderViewCB = new_cb;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
@@ -2889,6 +2945,11 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf
     HRESULT hr;
     RECT clientRect;
 
+    /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
+       reflects the key state after the user released the button, so we need
+       to remember the last key state when the button was pressed */
+    m_grfKeyState = grfKeyState;
+
     /* Map from global to client coordinates and query the index of the listview-item, which is
      * currently under the mouse cursor. */
     LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM};
@@ -2974,6 +3035,8 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf
         hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
     }
 
+    IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this);
+
     /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
     if (FAILED(hr))
     {
@@ -3036,16 +3099,12 @@ HRESULT WINAPI CDefView::DragLeave()
 
 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-    ERR("GetKeyState(VK_LBUTTON): %d\n", GetKeyState(VK_LBUTTON));
-
     ImageList_DragLeave(m_hWnd);
     ImageList_EndDrag();
 
-    if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) && 
+    if ((IsDropOnSource(NULL) == S_OK) && 
         (*pdwEffect & DROPEFFECT_MOVE) && 
-        /*(GetKeyState(VK_LBUTTON) != 0) &&*/
-        (m_pSourceDataObject.p) && 
-        (SHIsSameObject(pDataObject, m_pSourceDataObject)))
+        (m_grfKeyState & MK_LBUTTON))
     {
         if (m_pCurDropTarget)
         {
@@ -3139,7 +3198,7 @@ HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
 
 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
 {
-    FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
+    FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink);
 
     /* FIXME: we set the AdviseSink, but never use it to send any advice */
     m_pAdvSink = pAdvSink;
@@ -3205,6 +3264,31 @@ HRESULT CDefView::_MergeToolbar()
     return S_OK;
 }
 
+// The default processing of IShellFolderView callbacks
+HRESULT CDefView::DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    // TODO: SFVM_GET_CUSTOMVIEWINFO, SFVM_WINDOWCREATED
+    TRACE("CDefView::DefMessageSFVCB uMsg=%u\n", uMsg);
+    return E_NOTIMPL;
+}
+
+HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    HRESULT hr = E_NOTIMPL;
+
+    if (m_pShellFolderViewCB)
+    {
+        hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam);
+    }
+
+    if (hr == E_NOTIMPL)
+    {
+        hr = DefMessageSFVCB(uMsg, wParam, lParam);
+    }
+
+    return hr;
+}
+
 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
 {
     return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
@@ -3247,6 +3331,15 @@ HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv,
     if (FAILED(hRes))
         return hRes;
 
+    if (pcsfv->psfvcb)
+    {
+        CComPtr<IShellFolderView> sfv;
+        if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv))))
+        {
+            sfv->SetCallback(pcsfv->psfvcb, NULL);
+        }
+    }
+
     *ppsv = psv.Detach();
     return hRes;
 }