[EXPLORER-NEW]
authorDavid Quintana <gigaherz@gmail.com>
Thu, 6 Nov 2014 03:05:33 +0000 (03:05 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Thu, 6 Nov 2014 03:05:33 +0000 (03:05 +0000)
* Use IContextMenu for the context menus, instead of a struct with function pointers.

svn path=/branches/shell-experiments/; revision=65279

base/shell/explorer-new/precomp.h
base/shell/explorer-new/startctxmnu.cpp
base/shell/explorer-new/traywnd.cpp

index 1c63685..8ade10e 100644 (file)
@@ -155,20 +155,6 @@ _CStartMenu_Constructor(REFIID riid, void **ppv);
 
 #define TWM_OPENSTARTMENU (WM_USER + 260)
 
 
 #define TWM_OPENSTARTMENU (WM_USER + 260)
 
-typedef HMENU(*PCREATECTXMENU)(IN HWND hWndOwner,
-                               IN PVOID *ppcmContext,
-                               IN PVOID Context  OPTIONAL);
-typedef VOID(*PCTXMENUCOMMAND)(IN HWND hWndOwner,
-                               IN UINT uiCmdId,
-                               IN PVOID pcmContext  OPTIONAL,
-                               IN PVOID Context  OPTIONAL);
-
-typedef struct _TRAYWINDOW_CTXMENU
-{
-    PCREATECTXMENU CreateCtxMenu;
-    PCTXMENUCOMMAND CtxMenuCommand;
-} TRAYWINDOW_CTXMENU, *PTRAYWINDOW_CTXMENU;
-
 extern const GUID IID_IShellDesktopTray;
 
 #define INTERFACE ITrayWindow
 extern const GUID IID_IShellDesktopTray;
 
 #define INTERFACE ITrayWindow
@@ -343,7 +329,7 @@ OUT HWND *phWndTaskSwitch);
  * startmnu.cpp
  */
 
  * startmnu.cpp
  */
 
-extern const TRAYWINDOW_CTXMENU StartMenuBtnCtxMenu;
+HRESULT StartMenuBtnCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
 
 #define INTERFACE IStartMenuSite
 DECLARE_INTERFACE_(IStartMenuSite, IUnknown)
 
 #define INTERFACE IStartMenuSite
 DECLARE_INTERFACE_(IStartMenuSite, IUnknown)
index 831a597..4e625f1 100644 (file)
  * Start menu button context menu
  */
 
  * Start menu button context menu
  */
 
-// TODO: Convert into an IContextMenu
-
-typedef struct _STARTMNU_CTMENU_CTX
-{
-    IContextMenu *pcm;
-    LPITEMIDLIST pidl;
-} STARTMNU_CTMENU_CTX, *PSTARTMNU_CTMENU_CTX;
-
-static HMENU
-CreateStartContextMenu(IN HWND hWndOwner,
-                       IN PVOID *ppcmContext,
-                       IN PVOID Context  OPTIONAL);
-
-static VOID
-OnStartContextMenuCommand(IN HWND hWndOwner,
-                          IN UINT uiCmdId,
-                          IN PVOID pcmContext  OPTIONAL,
-                          IN PVOID Context  OPTIONAL);
-
-const TRAYWINDOW_CTXMENU StartMenuBtnCtxMenu = {
-    CreateStartContextMenu,
-    OnStartContextMenuCommand
-};
-
-static HMENU
-CreateContextMenuFromShellFolderPidl(IN HWND hWndOwner,
-                                     IN OUT IShellFolder *psf,
-                                     IN OUT LPITEMIDLIST pidl,
-                                     OUT IContextMenu **ppcm)
+class CStartMenuBtnCtxMenu :
+    public CComCoClass<CStartMenuBtnCtxMenu>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IContextMenu
 {
 {
+    HWND hWndOwner;
+    CComPtr<ITrayWindow> TrayWnd;
     CComPtr<IContextMenu> pcm;
     CComPtr<IContextMenu> pcm;
-    HRESULT hRet;
-    HMENU hPopup;
+    CComPtr<IShellFolder> psf;
+    LPITEMIDLIST pidl;
 
 
-    hRet = psf->GetUIObjectOf(hWndOwner, 1, (LPCITEMIDLIST *) &pidl, IID_NULL_PPV_ARG(IContextMenu, &pcm));
-    if (SUCCEEDED(hRet))
+    HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup)
     {
     {
-        hPopup = CreatePopupMenu();
+        CComPtr<IContextMenu> pcm;
+        HRESULT hRet;
 
 
-        if (hPopup != NULL)
+        hRet = psf->GetUIObjectOf(hWndOwner, 1, (LPCITEMIDLIST *) &pidl, IID_NULL_PPV_ARG(IContextMenu, &pcm));
+        if (SUCCEEDED(hRet))
         {
         {
-            hRet = pcm->QueryContextMenu(
-                hPopup,
-                0,
-                ID_SHELL_CMD_FIRST,
-                ID_SHELL_CMD_LAST,
-                CMF_VERBSONLY);
-
-            if (SUCCEEDED(hRet))
+            if (hPopup != NULL)
             {
             {
-                *ppcm = pcm;
-                return hPopup;
-            }
-
-            DestroyMenu(hPopup);
-        }
-    }
-
-    return NULL;
-}
-
-static VOID
-OnStartContextMenuCommand(IN HWND hWndOwner,
-                          IN UINT uiCmdId,
-                          IN PVOID pcmContext  OPTIONAL,
-                          IN PVOID Context  OPTIONAL)
-{
-    PSTARTMNU_CTMENU_CTX psmcmc = (PSTARTMNU_CTMENU_CTX) pcmContext;
-
-    if (uiCmdId != 0)
-    {
-        if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId <= ID_SHELL_CMD_LAST))
-        {
-            CMINVOKECOMMANDINFO cmici = { 0 };
-            CHAR szDir[MAX_PATH];
+                hRet = pcm->QueryContextMenu(
+                    hPopup,
+                    0,
+                    ID_SHELL_CMD_FIRST,
+                    ID_SHELL_CMD_LAST,
+                    CMF_VERBSONLY);
 
 
-            /* Setup and invoke the shell command */
-            cmici.cbSize = sizeof(cmici);
-            cmici.hwnd = hWndOwner;
-            cmici.lpVerb = (LPCSTR) MAKEINTRESOURCE(uiCmdId - ID_SHELL_CMD_FIRST);
-            cmici.nShow = SW_NORMAL;
+                if (SUCCEEDED(hRet))
+                {
+                    return hRet;
+                }
 
 
-            /* FIXME: Support Unicode!!! */
-            if (SHGetPathFromIDListA(psmcmc->pidl,
-                szDir))
-            {
-                cmici.lpDirectory = szDir;
+                DestroyMenu(hPopup);
             }
             }
-
-            psmcmc->pcm->InvokeCommand(&cmici);
         }
         }
-        else
-        {
-            ITrayWindow * TrayWnd = (ITrayWindow *) Context;
-            TrayWnd->ExecContextMenuCmd(uiCmdId);
-        }
-    }
-
-    psmcmc->pcm->Release();
-
-    HeapFree(hProcessHeap, 0, psmcmc);
-}
-
-static VOID
-AddStartContextMenuItems(IN HWND hWndOwner, IN HMENU hPopup)
-{
-    WCHAR szBuf[MAX_PATH];
-    HRESULT hRet;
 
 
-    /* Add the "Open All Users" menu item */
-    if (LoadString(hExplorerInstance,
-        IDS_PROPERTIES,
-        szBuf,
-        sizeof(szBuf) / sizeof(szBuf[0])))
-    {
-        AppendMenu(hPopup,
-                   MF_STRING,
-                   ID_SHELL_CMD_PROPERTIES,
-                   szBuf);
+        return E_FAIL;
     }
 
     }
 
-    if (!SHRestricted(REST_NOCOMMONGROUPS))
+    VOID AddStartContextMenuItems(IN HMENU hPopup)
     {
     {
-        /* Check if we should add menu items for the common start menu */
-        hRet = SHGetFolderPath(hWndOwner,
-                               CSIDL_COMMON_STARTMENU,
-                               NULL,
-                               SHGFP_TYPE_CURRENT,
-                               szBuf);
-        if (SUCCEEDED(hRet) && hRet != S_FALSE)
+        WCHAR szBuf[MAX_PATH];
+        HRESULT hRet;
+
+        /* Add the "Open All Users" menu item */
+        if (LoadString(hExplorerInstance,
+            IDS_PROPERTIES,
+            szBuf,
+            sizeof(szBuf) / sizeof(szBuf[0])))
         {
         {
-            /* The directory exists, but only show the items if the
-               user can actually make any changes to the common start
-               menu. This is most likely only the case if the user
-               has administrative rights! */
-            if (IsUserAnAdmin())
-            {
-                AppendMenu(hPopup,
-                           MF_SEPARATOR,
-                           0,
-                           NULL);
+            AppendMenu(hPopup,
+                       MF_STRING,
+                       ID_SHELL_CMD_PROPERTIES,
+                       szBuf);
+        }
 
 
-                /* Add the "Open All Users" menu item */
-                if (LoadString(hExplorerInstance,
-                    IDS_OPEN_ALL_USERS,
-                    szBuf,
-                    sizeof(szBuf) / sizeof(szBuf[0])))
+        if (!SHRestricted(REST_NOCOMMONGROUPS))
+        {
+            /* Check if we should add menu items for the common start menu */
+            hRet = SHGetFolderPath(hWndOwner,
+                                   CSIDL_COMMON_STARTMENU,
+                                   NULL,
+                                   SHGFP_TYPE_CURRENT,
+                                   szBuf);
+            if (SUCCEEDED(hRet) && hRet != S_FALSE)
+            {
+                /* The directory exists, but only show the items if the
+                user can actually make any changes to the common start
+                menu. This is most likely only the case if the user
+                has administrative rights! */
+                if (IsUserAnAdmin())
                 {
                     AppendMenu(hPopup,
                 {
                     AppendMenu(hPopup,
-                               MF_STRING,
-                               ID_SHELL_CMD_OPEN_ALL_USERS,
-                               szBuf);
-                }
+                               MF_SEPARATOR,
+                               0,
+                               NULL);
+
+                    /* Add the "Open All Users" menu item */
+                    if (LoadString(hExplorerInstance,
+                        IDS_OPEN_ALL_USERS,
+                        szBuf,
+                        sizeof(szBuf) / sizeof(szBuf[0])))
+                    {
+                        AppendMenu(hPopup,
+                                   MF_STRING,
+                                   ID_SHELL_CMD_OPEN_ALL_USERS,
+                                   szBuf);
+                    }
 
 
-                /* Add the "Explore All Users" menu item */
-                if (LoadString(hExplorerInstance,
-                    IDS_EXPLORE_ALL_USERS,
-                    szBuf,
-                    sizeof(szBuf) / sizeof(szBuf[0])))
-                {
-                    AppendMenu(hPopup,
-                               MF_STRING,
-                               ID_SHELL_CMD_EXPLORE_ALL_USERS,
-                               szBuf);
+                    /* Add the "Explore All Users" menu item */
+                    if (LoadString(hExplorerInstance,
+                        IDS_EXPLORE_ALL_USERS,
+                        szBuf,
+                        sizeof(szBuf) / sizeof(szBuf[0])))
+                    {
+                        AppendMenu(hPopup,
+                                   MF_STRING,
+                                   ID_SHELL_CMD_EXPLORE_ALL_USERS,
+                                   szBuf);
+                    }
                 }
             }
         }
     }
                 }
             }
         }
     }
-}
 
 
-static HMENU
-CreateStartContextMenu(IN HWND hWndOwner,
-                       IN PVOID *ppcmContext,
-                       IN PVOID Context  OPTIONAL)
-{
-    LPITEMIDLIST pidlStart, pidlLast;
-    CComPtr<IShellFolder> psfStart;
-    CComPtr<IShellFolder> psfDesktop;
-    CComPtr<IContextMenu> pcm;
-    HRESULT hRet;
-    HMENU hPopup;
-
-    pidlStart = SHCloneSpecialIDList(hWndOwner,
-                                     CSIDL_STARTMENU,
-                                     TRUE);
+public:
+    HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
+    {
+        this->TrayWnd = pTrayWnd;
+        this->hWndOwner = hWndOwner;
+        return S_OK;
+    }
 
 
-    if (pidlStart != NULL)
+    virtual HRESULT STDMETHODCALLTYPE
+        QueryContextMenu(HMENU hPopup,
+                         UINT indexMenu,
+                         UINT idCmdFirst,
+                         UINT idCmdLast,
+                         UINT uFlags)
     {
     {
-        pidlLast = ILClone(ILFindLastID(pidlStart));
-        ILRemoveLastID(pidlStart);
+        LPITEMIDLIST pidlStart;
+        CComPtr<IShellFolder> psfDesktop;
+        HRESULT hRet;
 
 
-        if (pidlLast != NULL)
+        psfDesktop = NULL;
+        pcm = NULL;
+
+        pidlStart = SHCloneSpecialIDList(hWndOwner, CSIDL_STARTMENU, TRUE);
+
+        if (pidlStart != NULL)
         {
         {
-            hRet = SHGetDesktopFolder(&psfDesktop);
-            if (SUCCEEDED(hRet))
+            pidl = ILClone(ILFindLastID(pidlStart));
+            ILRemoveLastID(pidlStart);
+
+            if (pidl != NULL)
             {
             {
-                hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &psfStart));
+                hRet = SHGetDesktopFolder(&psfDesktop);
                 if (SUCCEEDED(hRet))
                 {
                 if (SUCCEEDED(hRet))
                 {
-                    hPopup = CreateContextMenuFromShellFolderPidl(hWndOwner,
-                                                                  psfStart,
-                                                                  pidlLast,
-                                                                  &pcm);
-
-                    if (hPopup != NULL)
+                    hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &psf));
+                    if (SUCCEEDED(hRet))
                     {
                     {
-                        PSTARTMNU_CTMENU_CTX psmcmc;
+                        CreateContextMenuFromShellFolderPidl(hPopup);
+                        AddStartContextMenuItems(hPopup);
+                    }
+                }
+            }
 
 
-                        psmcmc = (PSTARTMNU_CTMENU_CTX) HeapAlloc(hProcessHeap, 0, sizeof(*psmcmc));
-                        if (psmcmc != NULL)
-                        {
-                            psmcmc->pcm = pcm;
-                            psmcmc->pidl = pidlLast;
+            ILFree(pidlStart);
+        }
 
 
-                            AddStartContextMenuItems(hWndOwner,
-                                                     hPopup);
+        return NULL;
+    }
 
 
-                            *ppcmContext = psmcmc;
-                            return hPopup;
-                        }
-                        else
-                        {
-                            DestroyMenu(hPopup);
-                            hPopup = NULL;
-                        }
-                    }
+    virtual HRESULT STDMETHODCALLTYPE
+        InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
+    {
+        UINT uiCmdId = (UINT)lpici->lpVerb;
+        if (uiCmdId != 0)
+        {
+            if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId <= ID_SHELL_CMD_LAST))
+            {
+                CMINVOKECOMMANDINFO cmici = { 0 };
+                CHAR szDir[MAX_PATH];
+
+                /* Setup and invoke the shell command */
+                cmici.cbSize = sizeof(cmici);
+                cmici.hwnd = hWndOwner;
+                cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST);
+                cmici.nShow = SW_NORMAL;
+
+                /* FIXME: Support Unicode!!! */
+                if (SHGetPathFromIDListA(pidl, szDir))
+                {
+                    cmici.lpDirectory = szDir;
                 }
                 }
-            }
 
 
-            ILFree(pidlLast);
+                pcm->InvokeCommand(&cmici);
+            }
+            else
+            {
+                TrayWnd->ExecContextMenuCmd(uiCmdId);
+            }
         }
         }
+        return S_OK;
+    }
+
+    virtual HRESULT STDMETHODCALLTYPE 
+        GetCommandString(UINT_PTR idCmd,
+                         UINT uType,
+                         UINT *pwReserved,
+                         LPSTR pszName,
+                         UINT cchMax)
+    {
+        return E_NOTIMPL;
+    }
+
+    CStartMenuBtnCtxMenu()
+    {
+    }
 
 
-        ILFree(pidlStart);
+    virtual ~CStartMenuBtnCtxMenu()
+    {
+        if (pidl)
+            ILFree(pidl);
     }
 
     }
 
-    return NULL;
+    BEGIN_COM_MAP(CStartMenuBtnCtxMenu)
+        COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
+    END_COM_MAP()
+};
+HRESULT StartMenuBtnCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
+{
+    CStartMenuBtnCtxMenu * mnu = new CComObject<CStartMenuBtnCtxMenu>();
+    mnu->Initialize(TrayWnd, hWndOwner);
+    *ppCtxMenu = mnu;
+    return S_OK;
 }
 }
index 147abb8..1c143fb 100644 (file)
@@ -24,7 +24,7 @@
 extern HRESULT InitShellServices(HDPA * phdpa);
 extern HRESULT ShutdownShellServices(HDPA hdpa);
 
 extern HRESULT InitShellServices(HDPA * phdpa);
 extern HRESULT ShutdownShellServices(HDPA hdpa);
 
-extern const TRAYWINDOW_CTXMENU TrayWindowCtxMenu;
+HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
 
 #define WM_APP_TRAYDESTROY  (WM_APP + 0x100)
 
 
 #define WM_APP_TRAYDESTROY  (WM_APP + 0x100)
 
@@ -70,7 +70,6 @@ class CTrayWindow :
     HFONT hStartBtnFont;
     HFONT hCaptionFont;
 
     HFONT hStartBtnFont;
     HFONT hCaptionFont;
 
-    CComPtr<ITrayBandSite> TrayBandSite;
     HWND hwndRebar;
     HWND hwndTaskSwitch;
     HWND hwndTrayNotify;
     HWND hwndRebar;
     HWND hwndTaskSwitch;
     HWND hwndTrayNotify;
@@ -84,6 +83,25 @@ class CTrayWindow :
     RECT rcTrayWnd[4];
     RECT rcNewPosSize;
     SIZE TraySize;
     RECT rcTrayWnd[4];
     RECT rcNewPosSize;
     SIZE TraySize;
+
+    NONCLIENTMETRICS ncm;
+    HFONT hFont;
+
+    CComPtr<IMenuBand> StartMenuBand;
+    CComPtr<IMenuPopup> StartMenuPopup;
+    HBITMAP hbmStartMenu;
+
+    HWND hwndTrayPropertiesOwner;
+    HWND hwndRunFileDlgOwner;
+
+    UINT AutoHideState;
+    SIZE AutoHideOffset;
+    TRACKMOUSEEVENT MouseTrackingInfo;
+
+    HDPA hdpaShellServices;
+
+public:
+    CComPtr<ITrayBandSite> TrayBandSite;
     union
     {
         DWORD Flags;
     union
     {
         DWORD Flags;
@@ -102,22 +120,6 @@ class CTrayWindow :
         };
     };
 
         };
     };
 
-    NONCLIENTMETRICS ncm;
-    HFONT hFont;
-
-    CComPtr<IMenuBand> StartMenuBand;
-    CComPtr<IMenuPopup> StartMenuPopup;
-    HBITMAP hbmStartMenu;
-
-    HWND hwndTrayPropertiesOwner;
-    HWND hwndRunFileDlgOwner;
-
-    UINT AutoHideState;
-    SIZE AutoHideOffset;
-    TRACKMOUSEEVENT MouseTrackingInfo;
-
-    HDPA hdpaShellServices;
-
 public:
     CTrayWindow() :
         StartButton(this, 1),
 public:
     CTrayWindow() :
         StartButton(this, 1),
@@ -134,13 +136,13 @@ public:
         PreviousMonitor(NULL),
         DraggingPosition(0),
         DraggingMonitor(NULL),
         PreviousMonitor(NULL),
         DraggingPosition(0),
         DraggingMonitor(NULL),
-        Flags(0),
         hFont(NULL),
         hbmStartMenu(NULL),
         hwndTrayPropertiesOwner(NULL),
         hwndRunFileDlgOwner(NULL),
         AutoHideState(NULL),
         hFont(NULL),
         hbmStartMenu(NULL),
         hwndTrayPropertiesOwner(NULL),
         hwndRunFileDlgOwner(NULL),
         AutoHideState(NULL),
-        hdpaShellServices(NULL)
+        hdpaShellServices(NULL),
+        Flags(0)
     {
         ZeroMemory(&StartBtnSize, sizeof(StartBtnSize));
         ZeroMemory(&rcTrayWnd, sizeof(rcTrayWnd));
     {
         ZeroMemory(&StartBtnSize, sizeof(StartBtnSize));
         ZeroMemory(&rcTrayWnd, sizeof(rcTrayWnd));
@@ -1017,38 +1019,51 @@ ChangePos:
         return cmdId;
     }
 
         return cmdId;
     }
 
-    UINT TrackCtxMenu(
-        IN const TRAYWINDOW_CTXMENU *pMenu,
+    HRESULT TrackCtxMenu(
+        IN IContextMenu * contextMenu,
         IN POINT *ppt OPTIONAL,
         IN HWND hwndExclude OPTIONAL,
         IN BOOL TrackUp,
         IN PVOID Context OPTIONAL)
     {
         IN POINT *ppt OPTIONAL,
         IN HWND hwndExclude OPTIONAL,
         IN BOOL TrackUp,
         IN PVOID Context OPTIONAL)
     {
-        HMENU hPopup;
-        UINT cmdId = 0;
-        PVOID pcmContext = NULL;
+        INT x = ppt->x;
+        INT y = ppt->y;
+        HRESULT hr;
+        UINT uCommand;
+        HMENU popup = CreatePopupMenu();
 
 
-        hPopup = pMenu->CreateCtxMenu(m_hWnd,
-                                      &pcmContext,
-                                      Context);
-        if (hPopup != NULL)
-        {
-            cmdId = TrackMenu(
-                hPopup,
-                ppt,
-                hwndExclude,
-                TrackUp,
-                TRUE);
+        if (popup == NULL)
+            return E_FAIL;
 
 
-            pMenu->CtxMenuCommand(m_hWnd,
-                                  cmdId,
-                                  pcmContext,
-                                  Context);
+        TRACE("Before Query\n");
+        hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
+        if (FAILED_UNEXPECTEDLY(hr))
+        {
+            TRACE("Query failed\n");
+            DestroyMenu(popup);
+            return hr;
+        }
+        
+        TRACE("Before Tracking\n");
+        uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
 
 
-            DestroyMenu(hPopup);
+        if (uCommand != 0)
+        {
+            TRACE("Before InvokeCommand\n");
+            CMINVOKECOMMANDINFO cmi = { 0 };
+            cmi.cbSize = sizeof(cmi);
+            cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+            cmi.hwnd = m_hWnd;
+            hr = contextMenu->InvokeCommand(&cmi);
+        }
+        else
+        {
+            TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
+            hr = S_FALSE;
         }
 
         }
 
-        return cmdId;
+        DestroyMenu(popup);
+        return hr;
     }
 
 
     }
 
 
@@ -2480,12 +2495,9 @@ SetStartBtnImage:
             menu is currently being shown */
             if (!(StartButton.SendMessage(BM_GETSTATE, 0, 0) & BST_PUSHED))
             {
             menu is currently being shown */
             if (!(StartButton.SendMessage(BM_GETSTATE, 0, 0) & BST_PUSHED))
             {
-                TrackCtxMenu(
-                    &StartMenuBtnCtxMenu,
-                    ppt,
-                    hWndExclude,
-                    Position == ABE_BOTTOM,
-                    this);
+                CComPtr<IContextMenu> ctxMenu;
+                StartMenuBtnCtxMenuCreator(this, m_hWnd, &ctxMenu);
+                TrackCtxMenu(ctxMenu, ppt, hWndExclude, Position == ABE_BOTTOM, this);
             }
         }
         else
             }
         }
         else
@@ -2522,12 +2534,9 @@ SetStartBtnImage:
             {
 HandleTrayContextMenu:
                 /* Tray the default tray window context menu */
             {
 HandleTrayContextMenu:
                 /* Tray the default tray window context menu */
-                TrackCtxMenu(
-                    &TrayWindowCtxMenu,
-                    ppt,
-                    NULL,
-                    FALSE,
-                    this);
+                CComPtr<IContextMenu> ctxMenu;
+                TrayWindowCtxMenuCreator(this, m_hWnd, &ctxMenu);
+                TrackCtxMenu(ctxMenu, ppt, NULL, FALSE, this);
             }
         }
         return Ret;
             }
         }
         return Ret;
@@ -2816,89 +2825,6 @@ HandleTrayContextMenu:
     ALT_MSG_MAP(1)
     END_MSG_MAP()
 
     ALT_MSG_MAP(1)
     END_MSG_MAP()
 
-    /*
-     * Tray Window Context Menu
-     */
-
-    static HMENU CreateTrayWindowContextMenu(IN HWND hWndOwner,
-                                             IN PVOID *ppcmContext,
-                                             IN PVOID Context OPTIONAL)
-    {
-        CTrayWindow *This = (CTrayWindow *) Context;
-        IContextMenu *pcm = NULL;
-        HMENU hPopup;
-
-        hPopup = LoadPopupMenu(hExplorerInstance,
-                               MAKEINTRESOURCE(IDM_TRAYWND));
-
-        if (hPopup != NULL)
-        {
-            if (SHRestricted(REST_CLASSICSHELL) != 0)
-            {
-                DeleteMenu(hPopup,
-                           ID_LOCKTASKBAR,
-                           MF_BYCOMMAND);
-            }
-
-            CheckMenuItem(hPopup,
-                          ID_LOCKTASKBAR,
-                          MF_BYCOMMAND | (This->Locked ? MF_CHECKED : MF_UNCHECKED));
-
-            if (This->TrayBandSite != NULL)
-            {
-                if (SUCCEEDED(This->TrayBandSite->AddContextMenus(
-                    hPopup,
-                    0,
-                    ID_SHELL_CMD_FIRST,
-                    ID_SHELL_CMD_LAST,
-                    CMF_NORMAL,
-                    &pcm)))
-                {
-                    TRACE("ITrayBandSite::AddContextMenus succeeded!\n");
-                    *(IContextMenu **) ppcmContext = pcm;
-                }
-            }
-        }
-
-        return hPopup;
-    }
-
-    static VOID OnTrayWindowContextMenuCommand(IN HWND hWndOwner,
-                                               IN UINT uiCmdId,
-                                               IN PVOID pcmContext OPTIONAL,
-                                               IN PVOID Context OPTIONAL)
-    {
-        CTrayWindow *This = (CTrayWindow *) Context;
-        IContextMenu *pcm = (IContextMenu *) pcmContext;
-
-        if (uiCmdId != 0)
-        {
-            if (uiCmdId >= ID_SHELL_CMD_FIRST && uiCmdId <= ID_SHELL_CMD_LAST)
-            {
-                CMINVOKECOMMANDINFO cmici = { 0 };
-
-                if (pcm != NULL)
-                {
-                    /* Setup and invoke the shell command */
-                    cmici.cbSize = sizeof(cmici);
-                    cmici.hwnd = hWndOwner;
-                    cmici.lpVerb = (LPCSTR) MAKEINTRESOURCE(uiCmdId - ID_SHELL_CMD_FIRST);
-                    cmici.nShow = SW_NORMAL;
-
-                    pcm->InvokeCommand(
-                        &cmici);
-                }
-            }
-            else
-            {
-                This->ExecContextMenuCmd(uiCmdId);
-            }
-        }
-
-        if (pcm != NULL)
-            pcm->Release();
-    }
-
     /*****************************************************************************/
 
     VOID TrayProcessMessages()
     /*****************************************************************************/
 
     VOID TrayProcessMessages()
@@ -3017,11 +2943,148 @@ HandleTrayContextMenu:
     END_COM_MAP()
 };
 
     END_COM_MAP()
 };
 
-const TRAYWINDOW_CTXMENU TrayWindowCtxMenu = {
-    CTrayWindow::CreateTrayWindowContextMenu,
-    CTrayWindow::OnTrayWindowContextMenuCommand
+class CTrayWindowCtxMenu :
+    public CComCoClass<CTrayWindowCtxMenu>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IContextMenu
+{
+    HWND hWndOwner;
+    CComPtr<CTrayWindow> TrayWnd;
+    CComPtr<IContextMenu> pcm;
+
+public:
+    HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
+    {
+        this->TrayWnd = (CTrayWindow *) pTrayWnd;
+        this->hWndOwner = hWndOwner;
+        return S_OK;
+    }
+
+    virtual HRESULT STDMETHODCALLTYPE 
+        QueryContextMenu(HMENU hPopup,
+                         UINT indexMenu,
+                         UINT idCmdFirst,
+                         UINT idCmdLast,
+                         UINT uFlags)
+    {
+        HMENU menubase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCE(IDM_TRAYWND));
+
+        if (menubase)
+        {
+            int count = ::GetMenuItemCount(menubase);
+
+            for (int i = 0; i < count; i++)
+            {
+                WCHAR label[128];
+
+                MENUITEMINFOW mii = { 0 };
+                mii.cbSize = sizeof(mii);
+                mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS 
+                    | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
+                mii.dwTypeData = label;
+                mii.cch = _countof(label);
+                ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
+
+                TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
+
+                mii.fType |= MFT_RADIOCHECK;
+
+                ::InsertMenuItemW(hPopup, i + 1, TRUE, &mii);
+            }
+
+            ::DestroyMenu(menubase);
+
+            if (SHRestricted(REST_CLASSICSHELL) != 0)
+            {
+                DeleteMenu(hPopup,
+                           ID_LOCKTASKBAR,
+                           MF_BYCOMMAND);
+            }
+
+            CheckMenuItem(hPopup,
+                          ID_LOCKTASKBAR,
+                          MF_BYCOMMAND | (TrayWnd->Locked ? MF_CHECKED : MF_UNCHECKED));
+
+            if (TrayWnd->TrayBandSite != NULL)
+            {
+                if (SUCCEEDED(TrayWnd->TrayBandSite->AddContextMenus(
+                    hPopup,
+                    0,
+                    ID_SHELL_CMD_FIRST,
+                    ID_SHELL_CMD_LAST,
+                    CMF_NORMAL,
+                    &pcm)))
+                {
+                    return S_OK;
+                }
+            }
+
+        }
+
+        return E_FAIL;
+    }
+
+    virtual HRESULT STDMETHODCALLTYPE
+        InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
+    {
+        UINT uiCmdId = (UINT) lpici->lpVerb;
+        if (uiCmdId != 0)
+        {
+            if (uiCmdId >= ID_SHELL_CMD_FIRST && uiCmdId <= ID_SHELL_CMD_LAST)
+            {
+                CMINVOKECOMMANDINFO cmici = { 0 };
+
+                if (pcm != NULL)
+                {
+                    /* Setup and invoke the shell command */
+                    cmici.cbSize = sizeof(cmici);
+                    cmici.hwnd = hWndOwner;
+                    cmici.lpVerb = (LPCSTR) MAKEINTRESOURCE(uiCmdId - ID_SHELL_CMD_FIRST);
+                    cmici.nShow = SW_NORMAL;
+
+                    pcm->InvokeCommand(&cmici);
+                }
+            }
+            else
+            {
+                TrayWnd->ExecContextMenuCmd(uiCmdId);
+            }
+        }
+
+        return S_OK;
+    }
+
+    virtual HRESULT STDMETHODCALLTYPE
+        GetCommandString(UINT_PTR idCmd,
+        UINT uType,
+        UINT *pwReserved,
+        LPSTR pszName,
+        UINT cchMax)
+    {
+        return E_NOTIMPL;
+    }
+
+    CTrayWindowCtxMenu()
+    {
+    }
+
+    virtual ~CTrayWindowCtxMenu()
+    {
+    }
+
+    BEGIN_COM_MAP(CTrayWindowCtxMenu)
+        COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
+    END_COM_MAP()
 };
 
 };
 
+HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
+{
+    CTrayWindowCtxMenu * mnu = new CComObject<CTrayWindowCtxMenu>();
+    mnu->Initialize(TrayWnd, hWndOwner);
+    *ppCtxMenu = mnu;
+    return S_OK;
+}
+
 CTrayWindow * g_TrayWindow;
 
 HRESULT
 CTrayWindow * g_TrayWindow;
 
 HRESULT