https://git.reactos.org/?p=reactos.git;a=commitdiff;h=37e6151b40178a2cbea3fc17999eaa35d328666c

commit 37e6151b40178a2cbea3fc17999eaa35d328666c
Author: Giannis Adamopoulos <[email protected]>
AuthorDate: Fri Oct 20 16:17:10 2017 +0300

    [BROWSEUI] CBandSiteMenu: Implement the Desktop, Quick Launch and New 
Toolbar menu items
---
 dll/win32/browseui/shellbars/CBandSiteMenu.cpp | 354 +++++++++++++++++++++----
 dll/win32/browseui/shellbars/CBandSiteMenu.h   |  14 +-
 2 files changed, 321 insertions(+), 47 deletions(-)

diff --git a/dll/win32/browseui/shellbars/CBandSiteMenu.cpp 
b/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
index 01a31e9f54..300a2ccb40 100644
--- a/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
+++ b/dll/win32/browseui/shellbars/CBandSiteMenu.cpp
@@ -22,9 +22,20 @@
 #include "shellbars.h"
 #include <strsafe.h>
 
+/* The menu consists of 3 parts. The first is loaded from the resources,
+   the second is populated with the classes of the CATID_DeskBand comcat
+   and the third part consists of the entries for each CISFBand in the band 
side.
+   The first 5 ids are reserved for the resource menu, the following ids will 
be 
+   for the CATID_DeskBand classes and the rest for the CISFBands.
+   The ids for the CISFBand menu items are not continuous, in this range
+   each menu id is calculated by adding the band id to the last id for the 
CATID_DeskBand range */
+#define FIRST_COMCAT_MENU_ID 0x5
+
 CBandSiteMenu::CBandSiteMenu():
-    m_menuDsa(NULL),
-    m_hmenu(NULL)
+    m_comcatDsa(NULL),
+    m_hmenu(NULL),
+    m_DesktopPidl(NULL),
+    m_QLaunchPidl(NULL)
 {
 }
 
@@ -33,14 +44,37 @@ CBandSiteMenu::~CBandSiteMenu()
     if (m_hmenu)
         DestroyMenu(m_hmenu);
 
-    if (m_menuDsa)
-        DSA_Destroy(m_menuDsa);
+    if (m_comcatDsa)
+        DSA_Destroy(m_comcatDsa);
+
+    if (m_DesktopPidl)
+        ILFree(m_DesktopPidl);
+
+    if (m_QLaunchPidl)
+        ILFree(m_QLaunchPidl);
 
     m_BandSite = NULL;
 }
 
+HRESULT WINAPI CBandSiteMenu::FinalConstruct()
+{
+    HRESULT hr = SHGetFolderLocation(0, CSIDL_DESKTOP, NULL, 0, 
&m_DesktopPidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    WCHAR buffer[MAX_PATH];
+    hr = SHGetFolderPathAndSubDirW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 
0, L"Microsoft\\Internet Explorer\\Quick Launch", buffer);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-HRESULT CBandSiteMenu::CreateMenuPart()
+    m_QLaunchPidl = ILCreateFromPathW(buffer);
+    if (m_QLaunchPidl == NULL)
+        return E_FAIL;
+
+    return S_OK;
+}
+
+HRESULT CBandSiteMenu::_CreateMenuPart()
 {
     WCHAR wszBandName[MAX_PATH];
     WCHAR wszBandGUID[MAX_PATH];
@@ -56,16 +90,16 @@ HRESULT CBandSiteMenu::CreateMenuPart()
     if (m_hmenu)
         DestroyMenu(m_hmenu);
 
-    if (m_menuDsa)
-        DSA_Destroy(m_menuDsa);
+    if (m_comcatDsa)
+        DSA_Destroy(m_comcatDsa);
 
     /* Load the template we will fill in */
     m_hmenu = LoadMenuW(GetModuleHandleW(L"browseui.dll"), 
MAKEINTRESOURCEW(IDM_TASKBAR_TOOLBARS));
     if (!m_hmenu)
         return HRESULT_FROM_WIN32(GetLastError());
 
-    m_menuDsa = DSA_Create(sizeof(GUID), 5);
-    if (!m_menuDsa)
+    m_comcatDsa = DSA_Create(sizeof(GUID), 5);
+    if (!m_comcatDsa)
         return E_OUTOFMEMORY;
 
     /* Get the handle of the submenu where the available items will be shown */
@@ -94,8 +128,8 @@ HRESULT CBandSiteMenu::CreateMenuPart()
         SHGetValue(HKEY_CLASSES_ROOT, wRegKey, NULL, NULL, wszBandName, 
&dwDataSize);
 
         /* Insert it */
-        InsertMenu(hmenuToolbars, cBands, MF_BYPOSITION, 
DSA_GetItemCount(m_menuDsa), wszBandName);
-        DSA_AppendItem(m_menuDsa, &iter);
+        InsertMenu(hmenuToolbars, cBands, MF_BYPOSITION, 
DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID, wszBandName);
+        DSA_AppendItem(m_comcatDsa, &iter);
         cBands++;
     }
     while (dwRead > 0);
@@ -103,12 +137,197 @@ HRESULT CBandSiteMenu::CreateMenuPart()
     return S_OK;
 }
 
+HRESULT CBandSiteMenu::_CreateNewISFBand(HWND hwnd, REFIID riid, void** ppv)
+{
+    WCHAR path[MAX_PATH];
+    WCHAR message[256];
+    BROWSEINFOW bi = { hwnd, NULL, path };
+
+    if (LoadStringW(GetModuleHandleW(L"browseui.dll"), IDS_BROWSEFORNEWTOOLAR, 
message, _countof(message)))
+        bi.lpszTitle = message;
+    else
+        bi.lpszTitle = L"Choose a folder";
+
+    LPITEMIDLIST pidlSelected = SHBrowseForFolderW(&bi);
+    if (pidlSelected == NULL)
+        return S_FALSE;
+
+    CComPtr<IShellFolderBand> pISFB;
+    HRESULT hr = CISFBand_CreateInstance(IID_IShellFolderBand, (PVOID*)&pISFB);
+    if (FAILED_UNEXPECTEDLY(hr))
+        goto done;
+
+    hr = pISFB->InitializeSFB(NULL, pidlSelected);
+    if (FAILED_UNEXPECTEDLY(hr))
+        goto done;
+
+    hr = pISFB->QueryInterface(riid, ppv);
+
+done:
+    ILFree(pidlSelected);
+    return hr;
+}
+
+HRESULT CBandSiteMenu::_CreateBuiltInISFBand(UINT uID, REFIID riid, void** ppv)
+{
+    LPITEMIDLIST pidl;
+    HRESULT hr;
+
+    pidl = (uID == IDM_TASKBAR_TOOLBARS_DESKTOP) ? m_DesktopPidl : 
m_QLaunchPidl;
+
+    CComPtr<IShellFolderBand> pISFB;
+    hr = CISFBand_CreateInstance(IID_IShellFolderBand, (PVOID*)&pISFB);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pISFB->InitializeSFB(NULL, pidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    return pISFB->QueryInterface(riid, ppv);
+}
+
+HRESULT CBandSiteMenu::_AddISFBandToMenu(HMENU hmenu, UINT indexMenu, UINT 
idCmdFirst, UINT idCmdLast, IUnknown* pBand, DWORD dwBandID, UINT *newMenuId)
+{
+    CComPtr<IShellFolderBand> psfb;
+    HRESULT hr = pBand->QueryInterface(IID_PPV_ARG(IShellFolderBand, &psfb));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    BANDINFOSFB bi = {ISFB_MASK_IDLIST};
+    hr = psfb->GetBandInfoSFB(&bi);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    if (!bi.pidl)
+        return E_OUTOFMEMORY;
+
+    WCHAR buffer[MAX_PATH];
+    hr = ILGetDisplayNameEx(NULL, bi.pidl, buffer, ILGDN_INFOLDER) ? S_OK : 
E_FAIL;
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    UINT id = idCmdFirst + DSA_GetItemCount(m_comcatDsa) + 
FIRST_COMCAT_MENU_ID + dwBandID;
+    if (id >= idCmdLast)
+        return E_FAIL;
+
+    *newMenuId = id;
+    InsertMenu(hmenu, indexMenu, MF_BYPOSITION, id, buffer);
+    return S_OK;
+}
+
+UINT CBandSiteMenu::_GetMenuIdFromISFBand(IUnknown *pBand)
+{
+    UINT ret = UINT_MAX;
+
+    CComPtr<IShellFolderBand> psfb;
+    HRESULT hr = pBand->QueryInterface(IID_PPV_ARG(IShellFolderBand, &psfb));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return ret;
+
+    BANDINFOSFB bi = {ISFB_MASK_IDLIST};
+    hr = psfb->GetBandInfoSFB(&bi);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return ret;
+
+    CComPtr<IShellFolder> psfDesktop;
+    LPITEMIDLIST pidl = bi.pidl;
+    if (!pidl)
+        return ret;
+
+    if (pidl->mkid.cb == 0)
+    {
+        ret = IDM_TASKBAR_TOOLBARS_DESKTOP;
+        goto done;
+    }
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    if (FAILED_UNEXPECTEDLY(hr))
+        goto done;
+
+    hr = psfDesktop->CompareIDs(0, pidl, m_QLaunchPidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        goto done;
+
+    if (HRESULT_CODE(hr) == 0)
+        ret = IDM_TASKBAR_TOOLBARS_QUICKLAUNCH;
+
+done:
+    if (pidl)
+        ILFree(pidl);
+
+    return ret;
+}
+
+UINT CBandSiteMenu::_GetMenuIdFromBand(CLSID *BandCLSID)
+{
+    /* Try to find the clsid of the band in the dsa */
+    UINT count = DSA_GetItemCount(m_comcatDsa);
+    for (UINT i = 0; i < count; i++)
+    {
+        GUID* pdsaGUID = (GUID*)DSA_GetItemPtr(m_comcatDsa, i);
+        if (IsEqualGUID(*pdsaGUID, *BandCLSID))
+        {
+            /* The index in the dsa is also the index in the menu */
+            return i + FIRST_COMCAT_MENU_ID;
+        }
+    }
+
+    return UINT_MAX;
+}
+
+UINT CBandSiteMenu::_GetBandIdFromClsid(CLSID* pclsid)
+{
+    CComPtr<IPersist> pBand;
+    CLSID BandCLSID;
+    DWORD dwBandID;
+
+    for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)); 
uBand++)
+    {
+        if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, 
&pBand))))
+            continue;
+
+        if (FAILED(pBand->GetClassID(&BandCLSID)))
+            continue;
+
+        if (IsEqualGUID(*pclsid, BandCLSID))
+            return dwBandID;
+    }
+
+    return UINT_MAX;
+}
+
+UINT CBandSiteMenu::_GetBandIdForBuiltinISFBand(UINT uID)
+{
+    CComPtr<IPersist> pBand;
+    CLSID BandCLSID;
+    DWORD dwBandID;
+
+    for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)); 
uBand++)
+    {
+        if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, 
&pBand))))
+            continue;
+
+        if (FAILED(pBand->GetClassID(&BandCLSID)))
+            continue;
+
+        if (!IsEqualGUID(BandCLSID, CLSID_ISFBand))
+            continue;
+
+        UINT menuID = _GetMenuIdFromISFBand(pBand);
+        if (menuID == uID)
+            return dwBandID;
+    }
+
+    return UINT_MAX;
+}
+
 HRESULT STDMETHODCALLTYPE CBandSiteMenu::SetOwner(IUnknown *pOwner)
 {
     TRACE("CBandSiteMenu::SetOwner(%p, %p)\n", this, pOwner);
     
     /* Cache the menu that will be merged every time QueryContextMenu is 
called */
-    CreateMenuPart();
+    _CreateMenuPart();
 
     return pOwner->QueryInterface(IID_PPV_ARG(IBandSite, &m_BandSite));
 }
@@ -119,11 +338,12 @@ HRESULT STDMETHODCALLTYPE CBandSiteMenu::QueryContextMenu(
     CComPtr<IPersist> pBand;
     CLSID BandCLSID;
     DWORD dwBandID;
+    UINT idMax;
 
     TRACE("CBandSiteMenu::QueryContextMenu(%p, %p, %u, %u, %u, 0x%x)\n", this, 
hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 
     /* First Merge the menu with the available bands */
-    Shell_MergeMenus(hmenu, m_hmenu, indexMenu, idCmdFirst, idCmdLast, 
MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
+    idMax = Shell_MergeMenus(hmenu, m_hmenu, indexMenu, idCmdFirst, idCmdLast, 
MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
 
     HMENU hmenuToolbars = GetSubMenu(hmenu, indexMenu);
 
@@ -136,63 +356,107 @@ HRESULT STDMETHODCALLTYPE 
CBandSiteMenu::QueryContextMenu(
         if (FAILED(pBand->GetClassID(&BandCLSID)))
             continue;
 
-        /* Try to find the clsid of the band in the dsa */
-        UINT count = DSA_GetItemCount(m_menuDsa);
-        for (UINT i = 0; i < count; i++)
+        UINT menuID;
+        if (IsEqualGUID(BandCLSID, CLSID_ISFBand))
         {
-            GUID* pdsaGUID = (GUID*)DSA_GetItemPtr(m_menuDsa, i);
-            if (memcmp(pdsaGUID, &BandCLSID, sizeof(GUID)) == 0)
+            menuID = _GetMenuIdFromISFBand(pBand);
+            if (menuID == UINT_MAX)
             {
-                /* The index in the dsa is also the index in the menu */
-                CheckMenuItem(hmenuToolbars, i, MF_CHECKED | MF_BYPOSITION);
+                HRESULT hr;
+                hr = _AddISFBandToMenu(hmenuToolbars, 0, idCmdFirst, 
idCmdLast, pBand, dwBandID, &menuID);
+                if (SUCCEEDED(hr) && menuID > idMax)
+                    idMax = menuID;
+                menuID -= idCmdFirst;
             }
         }
+        else
+        {
+            menuID = _GetMenuIdFromBand(&BandCLSID);
+        }
+
+        if (menuID != UINT_MAX)
+            CheckMenuItem(hmenuToolbars, menuID + idCmdFirst, MF_CHECKED);
     }
 
-    return S_OK;
+    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idMax - idCmdFirst +1)); 
 }
 
 HRESULT STDMETHODCALLTYPE CBandSiteMenu::InvokeCommand(LPCMINVOKECOMMANDINFO 
lpici)
 {
+    HRESULT hRet;
+    DWORD dwBandID;
+
     /* FIXME: do we need to handle this and how? */
     if (HIWORD(lpici->lpVerb) != NULL)
         return E_FAIL;
 
-    /* Get the GUID of the item that was clicked */
     UINT uID = LOWORD(lpici->lpVerb);
-    GUID *pguidToolbar = (GUID *)DSA_GetItemPtr(m_menuDsa, uID);
-    if (!pguidToolbar)
-        return E_FAIL;
+    if (uID == IDM_TASKBAR_TOOLBARS_NEW)
+    {
+        CComPtr<IDeskBand> pDeskBand;
+        hRet = _CreateNewISFBand(lpici->hwnd, IID_PPV_ARG(IDeskBand, 
&pDeskBand));
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return hRet;
 
-    /* Try to find if a band with a guid is present. If it is remove it and 
return */
-    CComPtr<IPersist> pBand;
-    CLSID BandCLSID;
-    DWORD dwBandID;
-    for (UINT uBand = 0; SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)); 
uBand++)
+        hRet = m_BandSite->AddBand(pDeskBand);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return hRet;
+
+        return S_OK;
+    }
+    else if (uID > (UINT)DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID )
     {
-        if (FAILED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, 
&pBand))))
-            continue;
+        dwBandID = uID - (DSA_GetItemCount(m_comcatDsa) + FIRST_COMCAT_MENU_ID 
);
 
-        if (FAILED(pBand->GetClassID(&BandCLSID)))
-            continue;
+        m_BandSite->RemoveBand(dwBandID);
 
-        if (memcmp(pguidToolbar, &BandCLSID, sizeof(GUID)) == 0)
+        return S_OK;
+    }
+    else if (uID == IDM_TASKBAR_TOOLBARS_DESKTOP || uID == 
IDM_TASKBAR_TOOLBARS_QUICKLAUNCH)
+    {
+        dwBandID = _GetBandIdForBuiltinISFBand(uID);
+        if (dwBandID != UINT_MAX)
         {
-            /* We found it, remove it */
             m_BandSite->RemoveBand(dwBandID);
-            return S_OK;
         }
+        else
+        {
+            CComPtr<IDeskBand> pDeskBand;
+            hRet = _CreateBuiltInISFBand(uID, IID_PPV_ARG(IDeskBand, 
&pDeskBand));
+            if (FAILED_UNEXPECTEDLY(hRet))
+                return hRet;
+
+            hRet = m_BandSite->AddBand(pDeskBand);
+            if (FAILED_UNEXPECTEDLY(hRet))
+                return hRet;
+        }
+        return S_OK;
     }
 
-    /* It is not present. Add it. */
-    CComPtr<IDeskBand> pDeskBand;
-    HRESULT hRet = CoCreateInstance(*pguidToolbar, NULL, CLSCTX_INPROC_SERVER, 
IID_PPV_ARG(IDeskBand, &pDeskBand));
-    if (FAILED(hRet))
-        return hRet;
+    /* Get the GUID of the item that was clicked */
+    GUID *pguidToolbar = (GUID *)DSA_GetItemPtr(m_comcatDsa, uID - 
FIRST_COMCAT_MENU_ID);
+    if (!pguidToolbar)
+        return E_FAIL;
 
-    hRet = m_BandSite->AddBand(pDeskBand);
-    if (FAILED_UNEXPECTEDLY(hRet))
-        return hRet;
+    /* Try to find if a band with a guid is present. If it is, remove it and 
return */
+    dwBandID = _GetBandIdFromClsid(pguidToolbar);
+    if (dwBandID != UINT_MAX)
+    {
+        /* We found it, remove it */
+        m_BandSite->RemoveBand(dwBandID);
+    }
+    else
+    {
+        /* It is not present. Add it. */
+        CComPtr<IDeskBand> pDeskBand;
+        hRet = CoCreateInstance(*pguidToolbar, NULL, CLSCTX_INPROC_SERVER, 
IID_PPV_ARG(IDeskBand, &pDeskBand));
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return hRet;
+
+        hRet = m_BandSite->AddBand(pDeskBand);
+        if (FAILED_UNEXPECTEDLY(hRet))
+            return hRet;
+    }
 
     return S_OK;
 }
diff --git a/dll/win32/browseui/shellbars/CBandSiteMenu.h 
b/dll/win32/browseui/shellbars/CBandSiteMenu.h
index d4d27acdc7..f05107b529 100644
--- a/dll/win32/browseui/shellbars/CBandSiteMenu.h
+++ b/dll/win32/browseui/shellbars/CBandSiteMenu.h
@@ -29,14 +29,24 @@ class CBandSiteMenu :
     public IShellService
 {
     CComPtr<IBandSite> m_BandSite;
-    HDSA m_menuDsa;
+    HDSA m_comcatDsa;
     HMENU m_hmenu;
+    LPITEMIDLIST m_DesktopPidl;
+    LPITEMIDLIST m_QLaunchPidl;
 
-    HRESULT CreateMenuPart();
+    HRESULT _CreateMenuPart();
+    HRESULT _CreateNewISFBand(HWND hwnd, REFIID riid, void** ppv);
+    HRESULT _CreateBuiltInISFBand(UINT uID, REFIID riid, void** ppv);
+    HRESULT _AddISFBandToMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, 
UINT idCmdLast, IUnknown* pBand, DWORD dwBandID, UINT *newMenuId);
+    UINT _GetMenuIdFromISFBand(IUnknown *pBand);
+    UINT _GetMenuIdFromBand(CLSID *BandCLSID);
+    UINT _GetBandIdFromClsid(CLSID* pclsid);
+    UINT _GetBandIdForBuiltinISFBand(UINT uID);
 
 public:
     CBandSiteMenu();
     ~CBandSiteMenu();
+    HRESULT WINAPI FinalConstruct();
 
     // *** IShellService methods ***
     virtual HRESULT STDMETHODCALLTYPE SetOwner(IUnknown *);

Reply via email to