[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / shlview.c
index 7292267..3355245 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Copyright 1998,1999     <juergen.schmied@debitel.net>
  *
- * This is the view visualizing the data provied by the shellfolder.
+ * This is the view visualizing the data provided by the shellfolder.
  * No direct access to data from pidls should be done from here.
  *
  * This library is free software; you can redistribute it and/or
@@ -21,9 +21,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * FIXME: The order by part of the background context menu should be
- * buily according to the columns shown.
+ * built according to the columns shown.
  *
- * FIXME: Load/Save the view state from/into the stream provied by
+ * FIXME: Load/Save the view state from/into the stream provided by
  * the ShellBrowser
  *
  * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
  * Release() ???
  */
 
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define COBJMACROS
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-
-#include "windef.h"
-#include "winerror.h"
-#include "winbase.h"
-#include "winnls.h"
-#include "objbase.h"
-#include "servprov.h"
-#include "shlguid.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "shlobj.h"
-#include "undocshell.h"
-#include "shresdef.h"
-#include "wine/debug.h"
-
-#include "docobj.h"
-#include "pidl.h"
-#include "shell32_main.h"
-#include "shellfolder.h"
+#include <precomp.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
@@ -110,7 +82,7 @@ typedef struct
         UINT            cScrollDelay;   /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
         POINT           ptLastMousePos; /* Mouse position at last DragOver call */
     IContextMenu2   *pCM;
-} IShellViewImpl;
+} IShellViewImpl, *LPIShellViewImpl;
 
 static const IShellViewVtbl svvt;
 static const IOleCommandTargetVtbl ctvt;
@@ -119,24 +91,24 @@ static const IDropSourceVtbl dsvt;
 static const IViewObjectVtbl vovt;
 
 
-static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
+static LPIShellViewImpl __inline impl_from_IOleCommandTarget( IOleCommandTarget *iface )
 {
-    return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
+    return (LPIShellViewImpl)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
 }
 
-static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
+static LPIShellViewImpl __inline impl_from_IDropTarget( IDropTarget *iface )
 {
-    return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
+    return (LPIShellViewImpl)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
 }
 
-static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
+static LPIShellViewImpl __inline impl_from_IDropSource( IDropSource *iface )
 {
-    return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
+    return (LPIShellViewImpl)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
 }
 
-static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
+static LPIShellViewImpl __inline impl_from_IViewObject( IViewObject *iface )
 {
-    return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
+    return (LPIShellViewImpl)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
 }
 
 /* ListView Header ID's */
@@ -295,8 +267,8 @@ static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
 
        TRACE("(%p)\n", This);
 
-       tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
-       SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
+       tmpstyle = GetWindowLongPtrW(This->hWndList, GWL_STYLE);
+       SetWindowLongPtrW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
 }
 
 /**********************************************************
@@ -390,7 +362,7 @@ static BOOL ShellView_InitList(IShellViewImpl * This)
        {
          for (i=0; 1; i++)
          {
-           if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
+            if (FAILED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
              break;
            lvColumn.fmt = sd.fmt;
            lvColumn.cx = sd.cxChar*8; /* chars->pixel */
@@ -456,8 +428,8 @@ static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam
     FILETIME fd1, fd2;
     char strName1[MAX_PATH], strName2[MAX_PATH];
     BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
-    LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
-    LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
+    LPITEMIDLIST pItemIdList1 = lParam1;
+    LPITEMIDLIST pItemIdList2 = lParam2;
     LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
 
 
@@ -566,7 +538,10 @@ static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
        lvItem.lParam = (LPARAM) ILClone(ILFindLastID(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*/
-       return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
+       if (SendMessageW(This->hWndList, LVM_INSERTITEMW, 0, (LPARAM)&lvItem) == -1)
+      return FALSE;
+       else
+         return TRUE;
 }
 
 /**********************************************************
@@ -774,8 +749,8 @@ static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
 
        if(hSubMenu)
        { /*insert This item at the beginning of the menu */
-         _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
-         _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
+         _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
+         _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"dummy45", MFS_ENABLED);
 
        }
        TRACE("--\n");
@@ -791,18 +766,18 @@ static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
 
        if(hSubMenu)
        { /*add a separator at the correct position in the menu*/
-         MENUITEMINFOA mii;
-         static char view[] = "View";
+         MENUITEMINFOW mii;
+         static WCHAR view[] = L"View";
 
-         _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
+         _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
 
          ZeroMemory(&mii, sizeof(mii));
          mii.cbSize = sizeof(mii);
          mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
          mii.fType = MFT_STRING;
          mii.dwTypeData = view;
-         mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
-         InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
+         mii.hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001");
+         InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
        }
 }
 
@@ -835,12 +810,14 @@ static UINT ShellView_GetSelections(IShellViewImpl * This)
          lvItem.iItem = 0;
          lvItem.iSubItem = 0;
 
-         while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
+         while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM)&lvItem) && (i < This->cidl))
          {
            if(lvItem.state & LVIS_SELECTED)
            {
              This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
              i++;
+                 if (i == This->cidl)
+               break;
              TRACE("-- selected Item found\n");
            }
            lvItem.iItem++;
@@ -858,6 +835,8 @@ static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
        static UINT CF_IDLIST = 0;
        HRESULT hr;
        IDataObject* selection;
+       IContextMenu * cm;
+       HMENU hmenu;
        FORMATETC fetc;
        STGMEDIUM stgm;
        LPIDA pIDList;
@@ -866,20 +845,76 @@ static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
        LPCWSTR parent_dir = NULL;
        SFGAOF attribs;
        int i;
+       CMINVOKECOMMANDINFOEX ici;
+       MENUITEMINFOW info;
 
        if (0 == ShellView_GetSelections(This))
        {
          return S_OK;
        }
+
+       hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
+                                       (LPCITEMIDLIST*)This->apidl, &IID_IContextMenu,
+                                       0, (LPVOID *)&cm);
+
+       if (SUCCEEDED(hr))
+       {
+               hmenu = CreatePopupMenu();
+               if (hmenu)
+               {
+                       if (SUCCEEDED(IContextMenu_QueryContextMenu( cm, hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY)))
+                       {
+                               INT def = -1, n = GetMenuItemCount(hmenu);
+
+                               for ( i = 0; i < n; i++ )
+                               {
+                                       memset( &info, 0, sizeof info );
+                                       info.cbSize = sizeof info;
+                                       info.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID;
+                                       if (GetMenuItemInfoW( hmenu, i, TRUE, &info))
+                                       {
+                                               if (info.fState & MFS_DEFAULT)
+                                               {
+                                                       def = info.wID;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (def != -1)
+                               {
+                                       memset( &ici, 0, sizeof ici );
+                                       ici.cbSize = sizeof ici;
+                                       ici.lpVerb = MAKEINTRESOURCEA( def );
+                                       ici.hwnd = This->hWnd;
+
+                                       if (IContextMenu_InvokeCommand(cm, (LPCMINVOKECOMMANDINFO) &ici ) == S_OK)
+                                       {
+                                               IContextMenu_Release(cm);
+                                               DestroyMenu( hmenu );
+                                               return S_OK;
+                                       }
+                               }
+                               
+                       }
+                       DestroyMenu( hmenu );
+               }
+               IContextMenu_Release(cm);
+       }
+
+
+
        hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
                                        (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
                                        0, (LPVOID *)&selection);
+
+
+
        if (FAILED(hr))
          return hr;
 
        if (0 == CF_IDLIST)
        {
-         CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
+         CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
        }
        fetc.cfFormat = CF_IDLIST;
        fetc.ptd = NULL;
@@ -1030,7 +1065,7 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
        {
          hMenu = CreatePopupMenu();
 
-         This->pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
+         CDefFolderMenu_Create2(NULL, NULL, This->cidl, (LPCITEMIDLIST*)This->apidl, This->pSFParent, NULL, 0, NULL, (IContextMenu**)&This->pCM);
          IContextMenu2_QueryContextMenu(This->pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
 
          uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
@@ -1308,7 +1343,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
             break;
 
           case NM_RETURN:
-            TRACE("-- NM_DBLCLK %p\n",This);
+            TRACE("-- NM_RETURN %p\n",This);
             if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
             break;
 
@@ -1415,8 +1450,8 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
 
                  if (pds)
                  {
-                   DWORD dwEffect;
-                   DoDragDrop(pda, pds, dwEffect, &dwEffect);
+                   DWORD dwEffect2;
+                   DoDragDrop(pda, pds, dwEffect, &dwEffect2);
                  }
                  IDataObject_Release(pda);
              }
@@ -1428,7 +1463,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
              DWORD dwAttr = SFGAO_CANRENAME;
              pidl = (LPITEMIDLIST)lpdi->item.lParam;
 
-             TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
+             TRACE("-- LVN_BEGINLABELEDITW %p\n",This);
 
              IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
              if (SFGAO_CANRENAME & dwAttr)
@@ -1440,7 +1475,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
 
          case LVN_ENDLABELEDITW:
            {
-             TRACE("-- LVN_ENDLABELEDITA %p\n",This);
+             TRACE("-- LVN_ENDLABELEDITW %p\n",This);
              if (lpdi->item.pszText)
              {
                HRESULT hr;
@@ -1476,6 +1511,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
              msg.pt = 0;*/
 
              LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
+          SHORT ctrl = GetKeyState(VK_CONTROL) & 0x8000;
 
               /* initiate a rename of the selected file or directory */
               if(plvKeyDown->wVKey == VK_F2)
@@ -1556,6 +1592,147 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
                 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
             }
         }
+        else if(plvKeyDown->wVKey == 'C' && ctrl)
+        {
+            if (ShellView_GetSelections(This))
+            {
+                IDataObject * pda;
+
+                if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
+                {
+                    HRESULT hr = OleSetClipboard(pda);
+                    if (FAILED(hr))
+                    {
+                        WARN("OleSetClipboard failed");
+                    }
+                    IDataObject_Release(pda);
+                }
+            }
+            break;
+        }
+        else if(plvKeyDown->wVKey == 'V' && ctrl)
+        {
+            IDataObject * pda;
+            STGMEDIUM medium;
+            FORMATETC formatetc;
+            LPITEMIDLIST * apidl;
+            LPITEMIDLIST pidl;
+            IShellFolder *psfFrom = NULL, *psfDesktop, *psfTarget = NULL;
+            LPIDA lpcida;
+            ISFHelper *psfhlpdst, *psfhlpsrc;
+            HRESULT hr;
+
+            hr = OleGetClipboard(&pda);
+            if (hr != S_OK)
+            {
+                ERR("Failed to get clipboard with %lx\n", hr);
+                return E_FAIL;
+            }
+
+            InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
+            hr = IDataObject_GetData(pda,&formatetc,&medium);
+
+            if (FAILED(hr))
+            {
+                ERR("Failed to get clipboard data with %lx\n", hr);
+                IDataObject_Release(pda);
+                return E_FAIL;
+            }
+
+            /* lock the handle */
+            lpcida = GlobalLock(medium.u.hGlobal);
+            if (!lpcida)
+            {
+                ERR("failed to lock pidl\n");
+                ReleaseStgMedium(&medium);
+                IDataObject_Release(pda);
+                return E_FAIL;
+            }
+
+            /* convert the data into pidl */
+            apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
+
+            if (!apidl)
+            {
+                ERR("failed to copy pidl\n");
+                return E_FAIL;
+            }
+
+            if (FAILED(SHGetDesktopFolder(&psfDesktop)))
+            {
+                ERR("failed to get desktop folder\n");
+                SHFree(pidl);
+                _ILFreeaPidl(apidl, lpcida->cidl);
+                ReleaseStgMedium(&medium);
+                IDataObject_Release(pda);
+                return E_FAIL;
+            }
+
+            if (_ILIsDesktop(pidl))
+            {
+                /* use desktop shellfolder */
+                psfFrom = psfDesktop;
+            }
+            else if (FAILED(IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom)))
+            {
+                ERR("no IShellFolder\n");
+
+                IShellFolder_Release(psfDesktop);
+                SHFree(pidl);
+                _ILFreeaPidl(apidl, lpcida->cidl);
+                ReleaseStgMedium(&medium);
+                IDataObject_Release(pda);
+
+                return E_FAIL;
+            }
+
+            psfTarget = This->pSFParent;
+
+
+            /* get source and destination shellfolder */
+            if (FAILED(IShellFolder_QueryInterface(psfTarget, &IID_ISFHelper, (LPVOID*)&psfhlpdst)))
+            {
+                ERR("no IID_ISFHelper for destination\n");
+
+                IShellFolder_Release(psfFrom);
+                IShellFolder_Release(psfTarget);
+                SHFree(pidl);
+                _ILFreeaPidl(apidl, lpcida->cidl);
+                ReleaseStgMedium(&medium);
+                IDataObject_Release(pda);
+
+                return E_FAIL;
+            }
+
+            if (FAILED(IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc)))
+            {
+                ERR("no IID_ISFHelper for source\n");
+
+                ISFHelper_Release(psfhlpdst);
+                IShellFolder_Release(psfFrom);
+                IShellFolder_Release(psfTarget);
+                SHFree(pidl);
+                _ILFreeaPidl(apidl, lpcida->cidl);
+                ReleaseStgMedium(&medium);
+                IDataObject_Release(pda);
+                return E_FAIL;
+            }
+
+            /* FIXXME
+            * do we want to perform a copy or move ???
+            */
+            hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
+
+            ISFHelper_Release(psfhlpdst);
+            ISFHelper_Release(psfhlpsrc);
+            IShellFolder_Release(psfFrom);
+            SHFree(pidl);
+            _ILFreeaPidl(apidl, lpcida->cidl);
+            ReleaseStgMedium(&medium);
+            IDataObject_Release(pda);
+            TRACE("paste end hr %x\n", hr);
+            break;
+        }
         else
             FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
         }
@@ -1669,7 +1846,7 @@ static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wPara
              return 1;
            break;
       case CWM_GETISHELLBROWSER:
-          return pThis->pShellBrowser;
+          return (LRESULT)pThis->pShellBrowser;
        }
        return DefWindowProcW(hWnd, uMessage, wParam, lParam);
 }
@@ -1895,7 +2072,14 @@ static HRESULT WINAPI IShellView_fnCreateViewWindow(
 
 
        TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
-       TRACE("-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
+       if (lpfs != NULL)
+               TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
+       if (prcView != NULL)
+               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)
+               return E_UNEXPECTED;
 
        /*set up the member variables*/
        This->pShellBrowser = psb;
@@ -1924,7 +2108,7 @@ static HRESULT WINAPI IShellView_fnCreateViewWindow(
          wc.hInstance          = shell32_hInstance;
          wc.hIcon              = 0;
          wc.hCursor            = LoadCursorW(0, (LPWSTR)IDC_ARROW);
-         wc.hbrBackground      = (HBRUSH) (COLOR_WINDOW + 1);
+         wc.hbrBackground      = (HBRUSH) (COLOR_BACKGROUND+1);
          wc.lpszMenuName       = NULL;
          wc.lpszClassName      = SV_CLASS_NAME;
 
@@ -2063,6 +2247,7 @@ static HRESULT WINAPI IShellView_fnSelectItem(
 
 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
 {
+       HRESULT hr = E_FAIL;
        IShellViewImpl *This = (IShellViewImpl *)iface;
 
        TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
@@ -2072,19 +2257,19 @@ static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem,
        switch(uItem)
        {
          case SVGIO_BACKGROUND:
-           *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
+           //*ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
+               CDefFolderMenu_Create2(NULL, NULL, This->cidl, (LPCITEMIDLIST*)This->apidl, This->pSFParent, NULL, 0, NULL, (IContextMenu**)ppvOut);
+        if (!ppvOut) hr = E_OUTOFMEMORY;
            break;
 
          case SVGIO_SELECTION:
            ShellView_GetSelections(This);
-           IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
+           hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
            break;
        }
        TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
 
-       if(!*ppvOut) return E_OUTOFMEMORY;
-
-       return S_OK;
+       return hr;
 }
 
 static const IShellViewVtbl svvt =
@@ -2356,8 +2541,13 @@ static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
         IDropTarget_Release(This->pCurDropTarget);
         This->pCurDropTarget = NULL;
     }
-    IDataObject_Release(This->pCurDataObject);
-    This->pCurDataObject = NULL;
+
+    if (This->pCurDataObject != NULL)
+    {
+        IDataObject_Release(This->pCurDataObject);
+        This->pCurDataObject = NULL;
+    }
+
     This->iDragOverItem = 0;
 
     return S_OK;
@@ -2375,8 +2565,12 @@ static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataO
         This->pCurDropTarget = NULL;
     }
 
-    IDataObject_Release(This->pCurDataObject);
-    This->pCurDataObject = NULL;
+    if (This->pCurDataObject != NULL)
+    {
+        IDataObject_Release(This->pCurDataObject);
+        This->pCurDataObject = NULL;
+    }
+
     This->iDragOverItem = 0;
 
     return S_OK;