How can I tell that I have a shell folder that represents My Computer?


You have in your hands an IShell­Folder, and you want to know whether this is an IShell­Folder that represents My Computer. There are a few ideas that may occur to you.

One is to ask the folder for its current location and compare it to CSIDL_DRIVES.

#define STRICT_TYPED_ITEMIDS
#include <shlobj.h>

PIDLIST_ABSOLUTE GetIDListViaPersistFolder(IUnknown *punk)
{
  PIDLIST_ABSOLUTE pidl = NULL;
  IPersistFolder2 *ppf;
  if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARGS(&ppf)))) {
    ppf->GetCurFolder(&pidl);
    ppf->Release();
  }
  return pidl;
}

HRESULT CompareAbsoluteIDLists(
    LPARAM lParam,
    PCUIDLIST_ABSOLUTE pidl1,
    PCUIDLIST_ABSOLUTE pidl2,
    int *piResult)
{
  *piResult = 0;
  IShellFolder *psfDesktop;
  HRESULT hr = SHGetDesktopFolder(&psfDesktop);
  if (SUCCEEDED(hr)) {
    hr = psfDesktop->CompareIDs(lParam,
    reinterpret_cast<PCUIDLIST_RELATIVE>(pidl1),
    reinterpret_cast<PCUIDLIST_RELATIVE>(pidl2));
    if (SUCCEEDED(hr)) {
     *piResult = ShortFromResult(hr);
    }
    psfDesktop->Release();
  }
  return hr;
}

BOOL IsMyComputerFolder(IUnknown *punk)
{
  BOOL fIsMyComputer = FALSE;
  PIDLIST_ABSOLUTE pidl = GetIDListViaPersistFolder(punk);
  if (pidl) {
    PIDLIST_ABSOLUTE pidlMyComputer;
    if (SUCCEEDED(SHGetSpecialFolderLocation(NULL,
                                 CSIDL_DRIVES, &pidlMyComputer)))
    {
      int iCompare;
      fIsMyComputer = SUCCEEDED(CompareAbsoluteIDLists(
                               SHCIDS_CANONICALONLY,
                               pidl, pidlMyComputer, &iCompare) &&
                      iCompare == 0;
      CoTaskMemFree(pidlMyComputer);
    }
    CoTaskMemFree(pidl);
  }
  return fIsMyComputer;
}

Okay, we have a lot of moving parts here. Let's look at them one at a time.

The Get­IDList­Via­Persist­Folder function takes an object and asks IPersist­Folder2::Get­Cur­Folder what folder it represents. Since we don't actually use any methods on the object beyond what is provided by IUnknown, we weaken the parameter requirement to simply IUnknown.

The Compare­Absolute­IDLists function compares two absolute ID lists according to the criteria specified by the lParam.

The Is­My­Computer­Folder combines these two function: It takes the object you pass in and gets the ID list it represents. It then gets the ID list for the My Computer folder. And then it compares the two via SHCIDS_CANONICAL­ONLY, which means "I just want to see if they represent the same object. Don't worry about getting the sort order absolutely right." And again, since we don't use any methods on the object other than IUnknown::Query­Interface, we weaken the parameter requirements to simply IUnknown.

Now, this code could be simplified or at least tweaked to take advantage of IShell­Item. For example, we could use SHGet­Known­Folder­Item to get the FOLDERID_Computer­Folder and then use IShell­Item::Compare.

But I'm not going to bother, because there is an underlying algorithmic problem with this technique: It is checking whether you have a folder to My Computer specifically at its default location. If somebody creates a My Computer folder at a custom location, say via a folder shortcut, or a folder with a magic name, then this code will not recognize it as My Computer because these alternate locations for My Computer will not match the standard location.

If you want to identify My Computer no matter where it winds up, then instead of checking the path, you can check its class.

HRESULT GetObjectCLSID(IUnknown *punk, CLSID *pclsid)
{
  *pclsid = CLSID_NULL;
  IPersist *pp;
  HRESULT hr = punk->QueryInterface(IID_PPV_ARGS(&pp));
  if (SUCCEEDED(hr)) {
    hr = pp->GetClassID(pclsid);
    pp->Release();
  }
  return hr;
}

BOOL IsMyComputerFolder(IUnknown *punk)
{
  CLSID clsid;
  GetObjectCLSID(psf, &clsid);
  return clsid == CLSID_MyComputer;
}

We ask the object directly, "Hey, what's your CLSID?" and if it replies, "I am CLSID_My­Computer," then we say, "Pleased to meet you, My Computer."

Comments (6)
  1. skSdnW says:

    This is almost the same as blogs.msdn.com/…/8956382.aspx but I'm guessing the shell helper function used there might know other ways than just GetCurFolder to get the clsid. I love this shell stuff but sometimes there are too many ways to do the same thing.

    What do you guys on the shell team call the "folder.{guid}" folders? [Shell]Folder junctions?

    [SHDESCRIPTIONID is GetClassId + other stuff. The other article tried too hard and asked for more information than it needed. -Raymond]
  2. I think a parenthesis is missing at the end of the call to CompareAbsoluteIDLists(). It reads:

       SUCCEEDED(CompareAbsoluteIDLists(

       SHCIDS_CANONICALONLY,

       pidl, pidlMyComputer, &iCompare) &&

    but I guess it should read:

       SUCCEEDED(CompareAbsoluteIDLists(

       SHCIDS_CANONICALONLY,

       pidl, pidlMyComputer, &iCompare)) &&

  3. Adam Rosenfield says:

    5 years ago, the Recycle Bin.  Today, My Computer.  In 5 more years, I expect the next article in the series "How can I tell that I have a shell folder that represents <SOME INTERESTING FOLDER>?".  Will it be the Control Panel?  The Games Explorer?  Some new folder that doesn't yet exist in current versions of Windows?  Find out in September 2018!

  4. @Adam Rosenfield: Five years from now, nobody will even remember there was something called Games Explorer or Control Panel. Games Explorer is already deprecated. Control Panel is being rivaled with PC Settings. (Windows 8.1)

  5. morlamweb says:

    @Fleet Commander: I must be ahead of the curve when it comes to Games Explorer.  I hadn't heard of it before reading these two comments : )  And as long as Microsoft retains the Desktop, then there will be a need to programatically check for special folders, like [My ]Computer.  I hope that they do preserve the Desktop for many years to come.  The windowing model of the desktop provides for one way of working with/using a PC; the Metro model provides another way.  I see value in both models, though I give the edge to the old Desktop model.  Full-screen-only apps just seems like a giant step backward in time to old full-screen DOS apps.

  6. Random832 says:

    If you have a "magic name" My Computer, and navigate from it to its own location, can you build an arbitrarily long IDL? (e.g. C:Computer.{CLSID}C:Computer.{CLSID}C:)? Explorer seems to canonicalize these once you navigate to a drive.

Comments are closed.

Skip to main content