Shell Namespace : How to create a namespace like "My Computer"

Shell Namespace : How to create a namespace like "My Computer"

Post by Fran?ois Garci » Sat, 21 Nov 1998 04:00:00



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 :

Desktop
 + 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 :

    SHGetDesktopFolder(&pDesktopFolder)
    pDesktopFolder->ParseDisplayName(..., wsFolderPath, ... , ppidlFolder,
...)
    pDesktopFolder->BindToObject(*ppidlFolder, ... , IID_IShellFolder,
ppFolder)

With the explorer view, the namespace works fine on the left pane. But in
the
right pane, since a double click is done on one the folders, the explorer is
stopped without any exception.

I'm looking for someone how have already done such shell namespace ?

Thanks a lot

F.GARCIA

 
 
 

Shell Namespace : How to create a namespace like "My Computer"

Post by Gertjan Schuurman » Sun, 22 Nov 1998 04:00:00



>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 :

>Desktop
> + 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 :

>    SHGetDesktopFolder(&pDesktopFolder)
>    pDesktopFolder->ParseDisplayName(..., wsFolderPath, ... , ppidlFolder,
>...)
>    pDesktopFolder->BindToObject(*ppidlFolder, ... , IID_IShellFolder,
>ppFolder)

>With the explorer view, the namespace works fine on the left pane. But in
>the
>right pane, since a double click is done on one the folders, the explorer
is
>stopped without any exception.

>I'm looking for someone how have already done such shell namespace ?

>Thanks a lot

>F.GARCIA


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
object.
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
pidl routines.

5. When you double-click on a item in the Explorer's right pane, this is
what happens:
a. Explorer fires a GetUIObjectOf(IID_IContextMenu,...) on your
IShellFolder.
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
{
public:
    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;
else
        if (riid == IID_IPersistFolder) return
static_cast<IPersistFolder*>this; else
        {
            *ppv = 0;
            return E_NOINTERFACE;
        }
        AddRef();
        return S_OK;
    }
    STDMETHODIMP_(LONG) AddRef()
    {
        m_nRef++;
    }
    STDMETHODIMP_(LONG) Release()
    {
        m_nRef--;
        if (m_nRef == 0)
            delete this;
    }
    // IShellFolder methods
    //     All methods simply forward to the m_psfRealFolder interface
    STDMETHODIMP BindToObject(LPITEMIDLIST* ppidl, ..., REFIID riid, LPVOID*
ppv)
    {
        return m_psfRealFolder->BindToOBject(ppidl, .., riid, ppv)
    }
    STDMETHODIMP EnumIDList(IEnumIDList** ppenum)
    {
        return m_psfRealFolder->EnumIDList(...)
    }
    ....
    // IPersistFolder
    //     All methods simply forward to the m_ppfRealFolder interface
    STDMETHODIMP Init(...)
    {
        return m_ppfRealFolder->Init(...);
    }
    ...

    // CMyFolder constructor
    CMyFolder(LPCTSTR pszFolderName) :
        m_nRef(0),
        m_psfRealFolder(0),
        m_ppfRealFolder(0)
    {
        // Lock the DLL
        g_nModuleLock++;

        // Get desktop folder and the pidl for pszFolderName
        SHGetDesktopFolder(&psfDesktop);
        psfDesktop->ParseDisplayName(pszFolderName,...)

        // Get the *real* IShellFolder interface
        psfDesktop->BindToObject(&pidl, .., IID_IShellFolder,
m_psfRealFolder);

        // Get the *real* IPersistFolder interface
        m_psfRealFolder->QueryInterface(IID_IPersistFolder,
(void**)&m_ppfRealFolder);

        // Free temporary stuff, (although its handy to preserve the pidl)
        FreePIDL(pidl);
        psfDesktop->Release();

    }
    // CMyFolder destructor
    ~CMyFolder()
    {
        m_ppfRealFolder->Release();
        m_psfRealFolder->Release();

        // DLL lock count down
        g_nModuleLock--;
    }

Quote:};

Good luck!

Regards,

Gertjan Schuurmans
Amsterdam


 
 
 

Shell Namespace : How to create a namespace like "My Computer"

Post by Fran?ois Garci » Mon, 23 Nov 1998 04:00:00



Groupes de discussion : comp.os.ms-windows.programmer.ole,comp.os.ms-
windows.programmer.win32,microsoft.public.win32.programmer.ole,microsoft.pub
lic.win32.programmer.ui
Date : samedi 21 novembre 1998 13:22


>>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.  (..)

>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".

When my IShellFolder interface is instanciated, i just increment my
reference count in AddRef ;
and when BindToObject is call by the Explorer, i create a instance of a
"standard" IShellFolder.
At the end (after last "release" is called), i release the indirected
IShellFolder.

In fact i think my Explorer was "hanging" because it was opened in a root
mode, from my shell-extension.
If i open the Explorer in a standard mode (rooted to Desktop), and implement
my shell-extension in Desktop or in "My Computer", there is no hang :
-> When i select a folder under my extension "<Local Private Storage>" in
left pane, all works perfectly well (left and right panes are refreshed)
-> When i create, open or rename a file in right pane, no problem
-> But when i double-click on a folder in this right pane, the folder in
fact opens itself under his "real" path, for instance "<My
Computer><C:><Users><JohnDoe>", instead of "<My Computer><Local Private
Storage>".

(when Explorer was opened rooted from my extension <Local Private Storage>,
i suppose this was* because Explorer can't find <My Computer><C:> in
is TreeView ?)

Well, problem is that right pane seems to be entirely built and updated by
the IShellView instance, which
i queried from my indirected "standard" IShellFolder (in method
CreateViewObject).

Maybe there is actually a aggregation problem. I should try to create an
instance of IShellFolder using aggregation  and passing a reference to the
IUnknown interface of my object.

Quote:>2. You should not forward QueryInterface calls from your object to the
inner
>object.
>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.

At present, i implement IShellFolder and IPersistFolder ; all others
interface requests are querying to my indirect IShellFolder object... :
**IShellView**, **IEnumIDList**, IExtractIcon, IContextMenu....

Quote:>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
>pidl routines.

These two points are OK in my implementation.

Quote:>5. When you double-click on a item in the Explorer's right pane, this is
>what happens:
>a. Explorer fires a GetUIObjectOf(IID_IContextMenu,...) on your
>IShellFolder.
>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.

I saw none of this calls because IShellView seems to instanciate an
IShellFolder directly from the Explorer, bypassing my own IShellFolder

Quote:>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.

Thank you very much for your help, i will try to experiment what can be done
with aggregation. But i am not sure IShellFolder will support this !

F.GARCIA


 
 
 

1. "using namespace std" vs. "using std::ostream" (FAQ 19.05)

Anyone have any ideas what causes the following problem?  The second one
is from "C++ FAQs, second edition", yet it does not compile in
MSVC++6.0.

//This compiles fine
#include <iostream>
using std::ostream;
class MyString
{
public:
    friend ostream& operator<<(ostream& os,const MyString& s);
private:
    char* s_;
ostream& operator<<(ostream& os,const MyString& s)
{
    os << s.s_;
    return os;

//This generates error C2248: 's_' : cannot access private member
declared in class 'MyString'
#include <iostream>
using namespace std;
class MyString
{
public:
    friend ostream& operator<<(ostream& os,const MyString& s);
private:
    char* s_;
ostream& operator<<(ostream& os,const MyString& s)
{
    os << s.s_; //error C2248: 's_' : cannot access private member
declared in class 'MyString'
    return os;

2. PMCIA driver for AST Ascentia 900N?

3. Replacing Explorer's "Printers" shell namespace?

4. Indy Webforce- Adequate Power?

5. "Extending the Shell’s Namespace" (junction point) example needed

6. Canon BJ200e driver for AutoCAD12/13

7. "Extending the Shell’s Namespace" example needed

8. Linux breaches at an all-time high ... Windoze security better?

9. Removing "My Computer", "Recycle Bin" and "Network Neighborhood" from desktop

10. Making "My Computer" = "My Documents"

11. "own" vs "uses" vs "contains" vs "is a"

12. Root shell namespace and Nonroot namespace.