>Hello From Paris
>For a very high secured project, I need to create a Shell Namespace like
>"My Computer". The main idea is to not allow the user to reach any devices
>(A to Z), but, the user will access to some other folders where the path
>is unknown for them. For example, the left pane of the explorer should
>look like :
> + My Computer
> + Local Private Storage
> + Remote Private Storage
> + Remote Public Storage
> + Floppy Disk
> + CD-ROM
> + Recycler Bin
> + (Other namespaces)
>So when the user click on "Local Private Storage", the file showed in the
>right pane are located on "C:\Users\JohnDoe", and when the user click on
>"Remote Private Storage", the file showed in the right pane are located
>on "Z:\Users\JohnDoe", and so on.
>A solution have been tested : A namespace with the IShellFolder interface.
>All methods (BindToObject, GetUIOfObject, ...) are forwarded to an
>IShellFolder interface created with the following code :
> pDesktopFolder->ParseDisplayName(..., wsFolderPath, ... , ppidlFolder,
> pDesktopFolder->BindToObject(*ppidlFolder, ... , IID_IShellFolder,
>With the explorer view, the namespace works fine on the left pane. But in
>right pane, since a double click is done on one the folders, the explorer
>stopped without any exception.
>I'm looking for someone how have already done such shell namespace ?
>Thanks a lot
Some thoughts crossed my mind:
1. I understand you've created your own IShellFolder object which
encapsulates a "standard" IShellFolder. So the "outer" object holds a
pointer to the inner and both are included in an AddRef/Release lifecycle.
This can cause all kinds of problems. Check all information (in the MSDN for
example) on "aggregation".
2. You should not forward QueryInterface calls from your object to the inner
For example: Explorer holds an IShellFolder interface pointer to your object
and queries IPersistFolder; you forward this QueryInterface call to the
inner IShellFolder, which returns its IPersistFolder interface. So far, so
good. But when explorer queries an IShellFolder from this IPersistFolder it
does NOT get your IShellFolder, and your object is completely left out.
Solution: implement all necessary interfaces on your object and let
QueryInterface return pointers to these interfaces.
3. Be sure your to lock the DLL when any of your object is in use. (See
DllCanUnloadNow and other Inproc server DLL issues).
4. Use the ole-allocator for allocating PIDL's (ShGetMalloc) and check all
5. When you double-click on a item in the Explorer's right pane, this is
a. Explorer fires a GetUIObjectOf(IID_IContextMenu,...) on your
b. IContextMenu::QueryContextMenu is called, and explorer looks for the
default menu item (typically "open")
c. IContextMenu::Invoke() is called.
Carefully examine what happens to your object during these operations.
6. Look at the REGVIEW example in the MSDN (this implements a hierarchical
namespace extension, and is written well) Do not look at the CABVIEW
example; it's a disaster.
Here is some sample code:
class CMyFolder: public IShellFolder, public IPersistFolder
STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv)
// CMyFolder exposes the interfaces.
*ppResult = 0;
if (riid == IID_IUnknown) *ppv = this; else
if (riid == IID_IShellFolder) return static_cast<IShellFolder*>this;
if (riid == IID_IPersistFolder) return
*ppv = 0;
if (m_nRef == 0)
// IShellFolder methods
// All methods simply forward to the m_psfRealFolder interface
STDMETHODIMP BindToObject(LPITEMIDLIST* ppidl, ..., REFIID riid, LPVOID*
return m_psfRealFolder->BindToOBject(ppidl, .., riid, ppv)
STDMETHODIMP EnumIDList(IEnumIDList** ppenum)
// All methods simply forward to the m_ppfRealFolder interface
// CMyFolder constructor
CMyFolder(LPCTSTR pszFolderName) :
// Lock the DLL
// Get desktop folder and the pidl for pszFolderName
// Get the *real* IShellFolder interface
psfDesktop->BindToObject(&pidl, .., IID_IShellFolder,
// Get the *real* IPersistFolder interface
// Free temporary stuff, (although its handy to preserve the pidl)
// CMyFolder destructor
// DLL lock count down