[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Thu, 17 Nov 2016 14:35:19 +0000 (14:35 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Thu, 17 Nov 2016 14:35:19 +0000 (14:35 +0000)
- CDefaultContextMenu: Add rudimentary support for callbacks so as to let folders have item specific commands and remove all item specific code from this class.
- Implement context menu callbacks for CFSFolder, CRegFolder, CDrivesFolder in order to let them handle the properties item and let the CDrivesFolder add and handle the Format item itself.

svn path=/trunk/; revision=73243

13 files changed:
reactos/dll/win32/shell32/CDefaultContextMenu.cpp
reactos/dll/win32/shell32/dialogs/drive.cpp
reactos/dll/win32/shell32/dialogs/fprop.cpp
reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp
reactos/dll/win32/shell32/folders/CDrivesFolder.cpp
reactos/dll/win32/shell32/folders/CFSFolder.cpp
reactos/dll/win32/shell32/folders/CFSFolder.h
reactos/dll/win32/shell32/folders/CNetFolder.cpp
reactos/dll/win32/shell32/folders/CRecycleBin.cpp
reactos/dll/win32/shell32/folders/CRegFolder.cpp
reactos/dll/win32/shell32/shfldr.h
reactos/dll/win32/shell32/shlfolder.cpp
reactos/dll/win32/shell32/wine/shell32_main.h

index d6b8ba9..7f8efa0 100644 (file)
@@ -61,6 +61,8 @@ class CDefaultContextMenu :
     private:
         CComPtr<IUnknown> m_site;
         CComPtr<IShellFolder> m_psf;
+        CComPtr<IContextMenuCB> m_pmcb;
+        LPFNDFMCALLBACK m_pfnmcb;
         UINT m_cidl;
         PCUITEMID_CHILD_ARRAY m_apidl;
         CComPtr<IDataObject> m_pDataObj;
@@ -75,6 +77,7 @@ class CDefaultContextMenu :
         UINT m_iIdSCMFirst; /* first static used id */
         UINT m_iIdSCMLast; /* last static used id */
 
+        HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam);
         void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb);
         void AddStaticEntriesForKey(HKEY hKey);
         BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid);
@@ -93,7 +96,6 @@ class CDefaultContextMenu :
         HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy);
         HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi);
-        HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici);
         HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi);
@@ -106,7 +108,7 @@ class CDefaultContextMenu :
     public:
         CDefaultContextMenu();
         ~CDefaultContextMenu();
-        HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm);
+        HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn);
 
         // IContextMenu
         virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
@@ -133,6 +135,8 @@ class CDefaultContextMenu :
 
 CDefaultContextMenu::CDefaultContextMenu() :
     m_psf(NULL),
+    m_pmcb(NULL),
+    m_pfnmcb(NULL),
     m_cidl(0),
     m_apidl(NULL),
     m_pDataObj(NULL),
@@ -180,7 +184,7 @@ CDefaultContextMenu::~CDefaultContextMenu()
     _ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl);
 }
 
-HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
+HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn)
 {
     TRACE("cidl %u\n", pdcm->cidl);
 
@@ -189,6 +193,8 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
     if (m_cidl && !m_apidl)
         return E_OUTOFMEMORY;
     m_psf = pdcm->psf;
+    m_pmcb = pdcm->pcmcb;
+    m_pfnmcb = lpfn;
 
     m_cKeys = pdcm->cKeys;
     if (pdcm->cKeys)
@@ -219,6 +225,20 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
     return S_OK;
 }
 
+HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam)
+{
+    if (m_pmcb)
+    {
+        return m_pmcb->CallBack(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
+    }
+    else if(m_pfnmcb)
+    {
+        return m_pfnmcb(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
+    }
+
+    return S_OK;
+}
+
 void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb)
 {
     PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL;
@@ -712,23 +732,15 @@ CDefaultContextMenu::BuildShellItemContextMenu(
     IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast);
     TRACE("IndexMenu %d\n", IndexMenu);
 
-    if (_ILIsDrive(m_apidl[0]))
-    {
-        char szDrive[8] = {0};
-        DWORD dwFlags;
-
-        _ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive));
-        if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0))
-        {
-            /* Disable format if read only */
-            if (!(dwFlags & FILE_READ_ONLY_VOLUME))
-            {
-                _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
-                _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
-                bAddSep = TRUE;
-            }
-        }
-    }
+    /* Now let the callback add its own items */
+    QCMINFO qcminfo;
+    qcminfo.hmenu = hMenu;
+    qcminfo.indexMenu = IndexMenu;
+    qcminfo.idCmdFirst = iIdCmdFirst;
+    qcminfo.idCmdLast = iIdCmdLast;
+    qcminfo.pIdMap = NULL;
+    _DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo);
+    IndexMenu = GetMenuItemCount(hMenu);
 
     BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
     if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData)
@@ -971,105 +983,8 @@ HRESULT
 CDefaultContextMenu::DoProperties(
     LPCMINVOKECOMMANDINFO lpcmi)
 {
-    HRESULT hr = S_OK;
-    const ITEMIDLIST *pidlParent = m_pidlFolder, *pidlChild;
+    _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL);
 
-    if (!pidlParent)
-    {
-        CComPtr<IPersistFolder2> pf;
-
-        /* pidlFolder is optional */
-        if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
-        {
-            pf->GetCurFolder((_ITEMIDLIST**)&pidlParent);
-        }
-    }
-
-    if (m_cidl > 0)
-        pidlChild = m_apidl[0];
-    else
-    {
-        /* Set pidlChild to last pidl of current folder */
-        if (pidlParent == m_pidlFolder)
-            pidlParent = (ITEMIDLIST*)ILClone(pidlParent);
-
-        pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent));
-        ILRemoveLastID((ITEMIDLIST*)pidlParent);
-    }
-
-    if (_ILIsMyComputer(pidlChild))
-    {
-        if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
-            hr = E_FAIL;
-    }
-    else if (_ILIsDesktop(pidlChild))
-    {
-        if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
-            hr = E_FAIL;
-    }
-    else if (_ILIsDrive(pidlChild))
-    {
-        WCHAR wszBuf[MAX_PATH];
-        ILGetDisplayName(pidlChild, wszBuf);
-        if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild))
-            hr = E_FAIL;
-    }
-    else if (_ILIsNetHood(pidlChild))
-    {
-        // FIXME path!
-        if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
-                                      L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
-                                      NULL, SW_SHOWDEFAULT))
-            hr = E_FAIL;
-    }
-    else if (_ILIsBitBucket(pidlChild))
-    {
-        /* FIXME: detect the drive path of bitbucket if appropiate */
-        if (!SH_ShowRecycleBinProperties(L'C'))
-            hr = E_FAIL;
-    }
-    else
-    {
-        if (m_cidl > 1)
-            WARN("SHMultiFileProperties is not yet implemented\n");
-
-        STRRET strFile;
-        hr = m_psf->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strFile);
-        if (SUCCEEDED(hr))
-        {
-            WCHAR wszBuf[MAX_PATH];
-            hr = StrRetToBufW(&strFile, pidlChild, wszBuf, _countof(wszBuf));
-            if (SUCCEEDED(hr))
-                hr = SH_ShowPropertiesDialog(wszBuf, pidlParent, &pidlChild);
-            else
-                ERR("StrRetToBufW failed\n");
-        }
-        else
-            ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
-    }
-
-    /* Free allocated PIDLs */
-    if (pidlParent != m_pidlFolder)
-        ILFree((ITEMIDLIST*)pidlParent);
-    if (m_cidl < 1 || pidlChild != m_apidl[0])
-        ILFree((ITEMIDLIST*)pidlChild);
-
-    return hr;
-}
-
-HRESULT
-CDefaultContextMenu::DoFormat(
-    LPCMINVOKECOMMANDINFO lpcmi)
-{
-    char szDrive[8] = {0};
-
-    if (!_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)))
-    {
-        ERR("pidl is not a drive\n");
-        return E_FAIL;
-    }
-
-    SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
     return S_OK;
 }
 
@@ -1411,13 +1326,13 @@ CDefaultContextMenu::InvokeCommand(
     case FCIDM_SHVIEW_PROPERTIES:
         Result = DoProperties(&LocalInvokeInfo);
         break;
-    case 0x7ABC:
-        Result = DoFormat(&LocalInvokeInfo);
-        break;
     case FCIDM_SHVIEW_NEWFOLDER:
         Result = DoCreateNewFolder(&LocalInvokeInfo);
         break;
     default:
+
+        _DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL);
+
         Result = E_UNEXPECTED;
         break;
     }
@@ -1561,9 +1476,9 @@ CDefaultContextMenu::GetSite(REFIID riid, void **ppvSite)
 
 static
 HRESULT
-CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
+CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn, REFIID riid, void **ppv)
 {
-    return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, riid, ppv);
+    return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, lpfn, riid, ppv);
 }
 
 /*************************************************************************
@@ -1575,7 +1490,7 @@ HRESULT
 WINAPI
 SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
 {
-    HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, riid, ppv);
+    HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, NULL, riid, ppv);
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
@@ -1600,18 +1515,18 @@ CDefFolderMenu_Create2(
     const HKEY *ahkeyClsKeys,
     IContextMenu **ppcm)
 {
-    DEFCONTEXTMENU pdcm;
-    pdcm.hwnd = hwnd;
-    pdcm.pcmcb = NULL;
-    pdcm.pidlFolder = pidlFolder;
-    pdcm.psf = psf;
-    pdcm.cidl = cidl;
-    pdcm.apidl = apidl;
-    pdcm.punkAssociationInfo = NULL;
-    pdcm.cKeys = nKeys;
-    pdcm.aKeys = ahkeyClsKeys;
-
-    HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm));
+    DEFCONTEXTMENU dcm;
+    dcm.hwnd = hwnd;
+    dcm.pcmcb = NULL;
+    dcm.pidlFolder = pidlFolder;
+    dcm.psf = psf;
+    dcm.cidl = cidl;
+    dcm.apidl = apidl;
+    dcm.punkAssociationInfo = NULL;
+    dcm.cKeys = nKeys;
+    dcm.aKeys = ahkeyClsKeys;
+
+    HRESULT hr = CDefaultContextMenu_CreateInstance(&dcm, lpfn, IID_PPV_ARG(IContextMenu, ppcm));
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
 
index 692bea9..2f59094 100644 (file)
@@ -123,7 +123,7 @@ typedef struct _DRIVE_PROP_PAGE
 } DRIVE_PROP_PAGE;
 
 BOOL
-SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl)
+SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
 {
     HPSXA hpsx = NULL;
     HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
index a2b6ac2..ede236f 100644 (file)
@@ -95,7 +95,7 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPage
  */
 
 BOOL
-SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl)
+SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl)
 {
     HPSXA hpsxa[3] = {NULL, NULL, NULL};
     CComObject<CFileDefExt> *pFileDefExt = NULL;
index e9dba76..6a0a79d 100644 (file)
@@ -133,8 +133,8 @@ HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, R
 
     CComPtr<IDefaultExtractIconInit> initIcon;
     HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
-    if (FAILED(hr))
-        return NULL;
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
     initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0);
 
index d2008c6..9262f5f 100644 (file)
@@ -39,6 +39,69 @@ CDrivesFolderEnum is only responsible for returning the physical items.
 *   IShellFolder implementation
 */
 
+HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
+                                           HWND         hwnd,
+                                           IDataObject  *pdtobj,
+                                           UINT         uMsg,
+                                           WPARAM       wParam,
+                                           LPARAM       lParam)
+{
+    if (uMsg != DFM_MERGECONTEXTMENU && uMsg != DFM_INVOKECOMMAND)
+        return S_OK;
+
+    PIDLIST_ABSOLUTE pidlFolder;
+    PUITEMID_CHILD *apidl;
+    UINT cidl;
+    HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    char szDrive[8] = {0};
+    if (!_ILGetDrive(apidl[0], szDrive, sizeof(szDrive)))
+    {
+        ERR("pidl is not a drive\n");
+        SHFree(pidlFolder);
+        _ILFreeaPidl(apidl, cidl);
+        return E_FAIL;
+    }
+
+    if (uMsg == DFM_MERGECONTEXTMENU)
+    {
+        QCMINFO *pqcminfo = (QCMINFO *)lParam;
+        DWORD dwFlags;
+
+        if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0))
+        {
+            /* Disable format if read only */
+            if (!(dwFlags & FILE_READ_ONLY_VOLUME) && GetDriveTypeA(szDrive) != DRIVE_REMOTE)
+            {
+                _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+                _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
+            }
+        }
+    }
+    else if (uMsg == DFM_INVOKECOMMAND)
+    {
+        if(wParam == 0x7ABC)
+        {
+            SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
+        }
+        else if (wParam == DFM_CMD_PROPERTIES)
+        {
+            WCHAR wszBuf[4];
+            wcscpy(wszBuf, L"A:\\");
+            wszBuf[0] = (WCHAR)szDrive[0];
+            if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl))
+                hr = E_FAIL;
+        }
+    }
+
+    SHFree(pidlFolder);
+    _ILFreeaPidl(apidl, cidl);
+
+    return hr;
+}
+
 HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
                                           HWND hwnd,
                                           UINT cidl,
@@ -51,16 +114,15 @@ HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
     AddClassKeyToArray(L"Drive", hKeys, &cKeys);
     AddClassKeyToArray(L"Folder", hKeys, &cKeys);
 
-    /* TODO: also pass a callback here */
-    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
+    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, DrivesContextMenuCallback, cKeys, hKeys, ppcm);
 }
 
 HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
 {
     CComPtr<IDefaultExtractIconInit> initIcon;
     HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
-    if (FAILED(hr))
-        return NULL;
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
     CHAR* pszDrive = _ILGetDataPointer(pidl)->u.drive.szDriveName;
     WCHAR wTemp[MAX_PATH];
index 19a2d74..40c72b1 100644 (file)
@@ -489,12 +489,21 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
 
         if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
         {
-            IContextMenu  * pCm = NULL;
             HKEY hKeys[16];
             UINT cKeys = 0;
             AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
-            hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, cKeys, hKeys, &pCm);
-            pObj = pCm;
+
+            DEFCONTEXTMENU dcm;
+            dcm.hwnd = hwndOwner;
+            dcm.pcmcb = this;
+            dcm.pidlFolder = pidlRoot;
+            dcm.psf = this;
+            dcm.cidl = cidl;
+            dcm.apidl = apidl;
+            dcm.cKeys = cKeys;
+            dcm.aKeys = hKeys;
+            dcm.punkAssociationInfo = NULL;
+            hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj);
         }
         else if (IsEqualIID (riid, IID_IDataObject))
         {
@@ -1088,4 +1097,38 @@ HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandler(const CLSID *pclsid, LPC
         return hr;
     }
     return hr;
-}
\ No newline at end of file
+}
+
+HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
+        return S_OK;
+
+    PIDLIST_ABSOLUTE pidlFolder;
+    PUITEMID_CHILD *apidl;
+    UINT cidl;
+    HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    if (cidl > 1)
+        ERR("SHMultiFileProperties is not yet implemented\n");
+
+    STRRET strFile;
+    hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile);
+    if (SUCCEEDED(hr))
+    {
+        hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl);
+        if (FAILED(hr))
+            ERR("SH_ShowPropertiesDialog failed\n");
+    }
+    else
+    {
+        ERR("Failed to get display name\n");
+    }
+
+    SHFree(pidlFolder);
+    _ILFreeaPidl(apidl, cidl);
+
+    return hr;
+}
index f76c724..40d54d3 100644 (file)
@@ -27,7 +27,8 @@ class CFSFolder :
     public CComCoClass<CFSFolder, &CLSID_ShellFSFolder>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
     public IShellFolder2,
-    public IPersistFolder3
+    public IPersistFolder3,
+    public IContextMenuCB
 {
     private:
         CLSID *pclsid;
@@ -80,6 +81,9 @@ class CFSFolder :
         virtual HRESULT WINAPI InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti);
         virtual HRESULT WINAPI GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti);
 
+        // IContextMenuCB
+        virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
         DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER)
         DECLARE_NOT_AGGREGATABLE(CFSFolder)
 
index 0644eed..9284331 100644 (file)
@@ -53,8 +53,8 @@ HRESULT CNetFolderExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LP
 {
     CComPtr<IDefaultExtractIconInit> initIcon;
     HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
-    if (FAILED(hr))
-        return NULL;
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
     initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_NETWORK_FOLDER);
 
index 03b1e00..ba80e3b 100644 (file)
@@ -67,8 +67,8 @@ HRESULT CRecyclerExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPV
 {
     CComPtr<IDefaultExtractIconInit> initIcon;
     HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon));
-    if (FAILED(hr))
-        return NULL;
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
     /* FIXME: This is completely unimplemented */
     initIcon->SetNormalIcon(swShell32Name, 0);
index e595d37..55d4fa8 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL (shell);
 
+HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf,
+                                              HWND         hwnd,
+                                              IDataObject  *pdtobj,
+                                              UINT         uMsg,
+                                              WPARAM       wParam,
+                                              LPARAM       lParam)
+{
+    if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
+        return S_OK;
+
+    PIDLIST_ABSOLUTE pidlFolder;
+    PUITEMID_CHILD *apidl;
+    UINT cidl;
+    HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    if (_ILIsMyComputer(apidl[0]))
+    {
+        if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
+            hr = E_FAIL;
+    }
+    else if (_ILIsDesktop(apidl[0]))
+    {
+        if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
+            hr = E_FAIL;
+    }
+    else if (_ILIsNetHood(apidl[0]))
+    {
+        // FIXME path!
+        if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
+                                      L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
+                                      NULL, SW_SHOWDEFAULT))
+            hr = E_FAIL;
+    }
+    else if (_ILIsBitBucket(apidl[0]))
+    {
+        /* FIXME: detect the drive path of bitbucket if appropiate */
+        if (!SH_ShowRecycleBinProperties(L'C'))
+            hr = E_FAIL;
+    }
+
+    SHFree(pidlFolder);
+    _ILFreeaPidl(apidl, cidl);
+
+    return hr;
+}
+
 HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
                                             HWND hwnd,
                                             UINT cidl,
@@ -48,7 +96,7 @@ HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
     }
     AddClassKeyToArray(L"Folder", hKeys, &cKeys);
 
-    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
+    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm);
 }
 
 HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
@@ -398,6 +446,10 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
 
         hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
     }
+    else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
+    {
+        hr = IDataObject_Constructor (hwndOwner, m_pidlRoot, apidl, cidl, (IDataObject **)&pObj);
+    }
     else
     {
         hr = E_NOINTERFACE;
index bc373af..799e96b 100644 (file)
@@ -63,6 +63,8 @@ BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
 
 void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys);
 
+HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl);
+
 static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str)
 {
     return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
index 114504f..00538a2 100644 (file)
@@ -547,6 +547,49 @@ void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys)
     }
 }
 
+HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
+{
+    UINT cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
+    if (!cfShellIDList)
+        return E_FAIL;
+
+    FORMATETC fmt;
+    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
+
+    HRESULT hr = pDataObject->QueryGetData(&fmt);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    STGMEDIUM medium;
+    hr = pDataObject->GetData(&fmt, &medium);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    /* lock the handle */
+    LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
+    if (!lpcida)
+    {
+        ReleaseStgMedium(&medium);
+        return E_FAIL;
+    }
+
+    /* convert the data into pidl */
+    LPITEMIDLIST pidl;
+    LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
+    if (!apidl)
+    {
+        ReleaseStgMedium(&medium);
+        return E_OUTOFMEMORY;
+    }
+
+    *ppidlfolder = pidl;
+    *apidlItems = apidl;
+    *pcidl = lpcida->cidl;
+
+    ReleaseStgMedium(&medium);
+    return S_OK;
+}
+
 /***********************************************************************
  *  SHCreateLinks
  *
index 1a74cba..127a566 100644 (file)
@@ -189,10 +189,9 @@ BOOL SHELL_IsShortcut(LPCITEMIDLIST) DECLSPEC_HIDDEN;
 INT_PTR CALLBACK SH_FileGeneralDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK SH_FileVersionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 HPROPSHEETPAGE SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle);
-BOOL SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl);
+BOOL SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl);
 BOOL SH_ShowRecycleBinProperties(WCHAR sDrive);
-BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl);
-BOOL SH_ShowFolderProperties(LPWSTR pwszFolder, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl);
+BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl);
 LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf);
 
 HRESULT WINAPI DoRegisterServer(void);