images not working properly if I open it from my shell namespace extension folder

113 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"); }

But opening images from my custom folders don't work. image image2 Actually it displays an image for about a second and then error message appears. Nevertheless it could be opened normally via Paint

1

There are 1 answers

0
bho3538 On

Your nse need handle IID_Istream to open file with UWP program

// Pseudo code
STDMETHODIMP NSEShellFolder::BindToObject (LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, void** ppvOut)
{
    HRESULT hr = E NOTIMPL;
    //.....//
    if (riid == IID IStream) {
        DWORD grfMode = 0;
        if (pbcReserved) { //IBindCtx
            BIND OPTS opts;
            ZeroMemory (&opts, sizeof (BIND OPTS));
            opts.cbStruct = sizeof (opts);
            pbc->GetBindOptions (&opts);
            grfMode = opts.grfMode;
        }
        //If your nse Has FileSystemPath, Win32 API ¹SHCreateStreamOnFile Ex' is useful.
        //or you can implement own IStream interface.
        LPWSTR pPath = CNSEData::GetPath (m_pidl);
        BOOL bCreate = grfMode & STGM CREATE? TRUE : FALSE;
        hr = SHCreateStreamOnFileEx (pPath,grfMode, FILE_ATTRIBUTE_NORMAL,bCreate,NULL, (IStream**)ppvOut);
    }
    //.....//
    return hr;
}

Before After