in my shell namespace extension context menu differs from the default one("new" and "properties" items are missed)

149 views Asked by At

I have my custom shell namespace extension. Just want to have a virtual folder mapped to some folder on disk C:/ with the same functionality.

    using namespace ATL;
    
    class ATL_NO_VTABLE CMyShellFolder :
        public CComObjectRootEx<CComMultiThreadModel>,
        public CComCoClass<CMyShellFolder, &CLSID_CMyShellFolder>,
        public IPersistFolder2,
        public IShellFolder2,
        public IExplorerPaneVisibility
    {
        CComHeapPtr<ITEMIDLIST_ABSOLUTE> m_pidl;
    
        CComPtr<IShellFolder2> m_folder;
    
        CComPtr<IThumbnailHandlerFactory> m_thFactory;
        CComPtr<IUnknown> m_site;
    
    public:
        CMyShellFolder()
        {
        }
    
        static HRESULT WINAPI UpdateRegistry(BOOL reg) throw();
    
        BEGIN_COM_MAP(CMyShellFolder)
            COM_INTERFACE_ENTRY(IShellFolder)
            COM_INTERFACE_ENTRY(IShellFolder2)
            COM_INTERFACE_ENTRY2(IPersist, IPersistFolder)
            COM_INTERFACE_ENTRY(IPersistFolder)
            COM_INTERFACE_ENTRY(IPersistFolder2)
            COM_INTERFACE_ENTRY(IExplorerPaneVisibility)
        END_COM_MAP()
    
        DECLARE_PROTECT_FINAL_CONSTRUCT()

---------------------------------

    HRESULT CMyShellFolder::BindToObject(PCUIDLIST_RELATIVE pidl, IBindCtx* pbc, REFIID riid, LPVOID* ppv)

{
    if (riid == __uuidof(IShellFolder3))
        return E_NOINTERFACE;


    HR;
    CComObject<CMyShellFolder>* folder = nullptr;
    CHECKARG(pidl);
    hr = E_NOINTERFACE;

    if (riid == IID_IShellFolder ||
        riid == IID_IShellFolder2)
    {
        // check it's a folder
        SFGAOF atts = SFGAO_FOLDER;
        auto hr2 = GetAttributesOf(1, (PCUITEMID_CHILD_ARRAY)&pidl, &atts);
        if (FAILED(hr2) || !(atts & SFGAO_FOLDER))
            goto cleanup; // nope, get out

        CHECKHR(CreateInstanceAddRef(&folder));
        CHECKHR(folder->_Initialize(this, pidl));
        CHECKHR(folder->QueryInterface(riid, ppv));

    }

    RELEASE(folder);
    HRONFAIL(L"CMyShellFolder::BindToObject");
}


    HRESULT CMyShellFolder::CreateViewObject(HWND hwnd, REFIID riid, LPVOID* ppv)
    {
    HR;
    SFV_CREATE sfvc = { 0 };
    DEFCONTEXTMENU dcm = { 0 };
    CHECKITEM;
    CHECKARG(ppv);
    hr = E_NOINTERFACE;

    if (riid == IID_IShellView)
    {
        sfvc.cbSize = sizeof(SFV_CREATE);
        CHECKHR(QueryInterface(IID_PPV_ARGS(&sfvc.pshf)));
        QueryInterface(IID_PPV_ARGS(&sfvc.psfvcb));
        CHECKHR(SHCreateShellFolderView(&sfvc, (IShellView**)ppv));
        goto cleanup;
    }

    if (riid == IID_IContextMenu)
    {
        dcm.hwnd = hwnd;
        //dcm.pidlFolder = (PCIDLIST_ABSOLUTE)m_pidl.m_pData;
        QueryInterface(IID_PPV_ARGS(&dcm.pcmcb));
        CHECKHR(QueryInterface(IID_PPV_ARGS(&dcm.psf)));
        CHECKHR(SHCreateDefaultContextMenu(&dcm, riid, ppv));
        goto cleanup;
    }

    if (riid == IID_ITransferSource || // for delete & file operations
        riid == IID_IDropTarget) // for copy paste & dd
    {
        CHECKHR(m_folder->CreateViewObject(hwnd, riid, ppv));
        goto cleanup;
    }
    CHECKHR(m_folder->CreateViewObject(hwnd, riid, ppv));

cleanup:
    RELEASE(dcm.pcmcb);
    RELEASE(dcm.psf);
    RELEASE(sfvc.psfvcb);
    RELEASE(sfvc.pshf);
    HRONFAIL(L"CMyShellFolder::CreateViewObject");
}

From the first site everything works fine, but then I noticed a few unclear moments:

  1. Context menu is not the same. "New" and "Properties" are missed. Pure context menu

  2. Can't rename folder. New name is not applied.

I tried to create CM in different way:

  {
    HKEY result;
    LSTATUS st = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"Directory\\Background", NULL, KEY_QUERY_VALUE, &result); // just check if it exists

    if (st == ERROR_SUCCESS)
    {
      aKeys[cKeys] = result;
      cKeys++;
    }
  }

  DEFCONTEXTMENU dcm =
  {
    hwndOwner,
    NULL,
    NULL, // _spidl,
    static_cast<IShellFolder2 *>(this),
    cidl,
    rgpidl,
    NULL,
    cKeys,
    aKeys
  };

  hr = SHCreateDefaultContextMenu(&dcm, riid, ppv);

And "New" item appeared(still no "Properties") but didn't work and leaded explorer to crash.

0

There are 0 answers