[SHELL32] Do not try to call a NULL m_pSF2Parent. CORE-11969 #comment Please retest!
[reactos.git] / reactos / dll / win32 / shell32 / CDefView.cpp
index 9780c11..0d639a4 100644 (file)
@@ -91,17 +91,18 @@ class CDefView :
         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;
 
@@ -245,7 +246,7 @@ 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);
@@ -271,7 +272,7 @@ 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_WINDOW + 1), NULL, SV_CLASS_NAME, NULL
                 },
@@ -287,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);
@@ -345,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);
 
@@ -509,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);
 
@@ -558,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;
@@ -580,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);
         }
     }
 }
@@ -612,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);
@@ -633,7 +641,7 @@ BOOL CDefView::InitList()
     }
     else
     {
-        FIXME("no SF2\n");
+        FIXME("no m_pSF2Parent\n");
     }
 
     Shell_GetImageLists(&big_icons, &small_icons);
@@ -709,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);
 
@@ -786,7 +794,7 @@ BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
 
     nItem = LV_FindItemByPidl(pidl);
 
-    if ( -1 != nItem )
+    if (-1 != nItem)
     {
         lvItem.mask = LVIF_IMAGE;
         lvItem.iItem = nItem;
@@ -807,7 +815,7 @@ BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
 * - 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);
@@ -883,7 +891,14 @@ HRESULT CDefView::FillList()
     DPA_DestroyCallback( hdpa, fill_list, this);
 
     /* sort the array */
-    m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL);
+    if (m_pSF2Parent)
+    {
+        m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL);
+    }
+    else
+    {
+        FIXME("no m_pSF2Parent\n");
+    }
     m_sortInfo.bIsAscending = TRUE;
     m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
     m_ListView.SortItems(ListViewCompareItems, this);
@@ -969,15 +984,15 @@ LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHa
 */
 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();
         }
@@ -1023,7 +1038,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);
@@ -1202,6 +1217,8 @@ HRESULT CDefView::OpenSelectedItems()
     if (FAILED(hResult))
         goto cleanup;
 
+    IUnknown_SetSite(m_pCM, (IShellView *)this);
+
     hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
     if (FAILED(hResult))
         goto cleanup;
@@ -1221,7 +1238,10 @@ cleanup:
         DestroyMenu(hMenu);
 
     if (m_pCM)
+    {
+        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
+    }
 
     return hResult;
 }
@@ -1231,11 +1251,10 @@ cleanup:
  */
 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    WORD                 x;
-    WORD                 y;
-    UINT                 uCommand;
-    HMENU                hMenu;
-    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)
@@ -1256,6 +1275,8 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
     if (FAILED( hResult))
         goto cleanup;
 
+    IUnknown_SetSite(m_pCM, (IShellView *)this);
+
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
@@ -1273,7 +1294,10 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
 
 cleanup:
     if (m_pCM)
+    {
+        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
+    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1294,6 +1318,8 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
     if (FAILED( hResult))
         goto cleanup;
 
+    IUnknown_SetSite(m_pCM, (IShellView *)this);
+
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
@@ -1302,7 +1328,10 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
 
 cleanup:
     if (m_pCM)
+    {
+        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
+    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1319,15 +1348,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);
@@ -1370,7 +1398,7 @@ void CDefView::DoActivate(UINT uState)
     }
     else
     {
-        if(m_hMenu)
+        if (m_hMenu)
         {
             if (!m_menusLoaded)
             {
@@ -1727,7 +1755,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
                 }
                 else
                 {
-                    FIXME("no SF2\n");
+                    FIXME("no m_pSF2Parent\n");
                 }
             }
             if(lpdi->item.mask & LVIF_IMAGE)    /* image requested */
@@ -1781,7 +1809,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;
@@ -2064,24 +2097,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)
     {
 
@@ -2113,7 +2144,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;
 
@@ -2128,21 +2159,21 @@ HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTI
     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;
 
@@ -2172,7 +2203,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)
@@ -2306,7 +2337,13 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
             else if (IsEqualIID(riid, IID_IDispatch))
             {
                 if (m_pShellFolderViewDual == NULL)
+                {
                     hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
+                    if (FAILED_UNEXPECTEDLY(hr))
+                    {
+                        return hr;
+                    }
+                }
                 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
             }
             break;
@@ -2934,7 +2971,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();
@@ -3043,8 +3096,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));