Discussion:
Decoding PIDLs
(too old to reply)
Nollie :)
2005-10-13 12:35:45 UTC
Permalink
The first byte of a pidl determines what type of file system object
the item is. For example,

ITEMIDLIST *pidl;

...GetThePIDL...

switch ( pidl->mkid.abID[0] )
{
case 0x25: // cd-rom drive
case 0x29 // floppy drive
case 0x23: // fixed drive?
case 0x2f: // fixed drive?
break;
}

On my XP machine, all of the fixed drives show up as 0x2f. On my Win98
box, all of the fixed drives show up as 0x23.

There's at least one circumstance where this causes a major problem
for me on Win98:

My shell viewer (treeview control) stores all its items with their
respective simple pidls. All the fixed drives' pidls start with 0x23.
After registering SHChangeNotifyRegister(), my program receives the
SHCNE_NETSHARE message along with a pidl of the affected item. If the
item is on a fixed drive, the drive component of the pidl is 0x2f,
which makes it very difficult to locate in my treeview because all the
fixed drives begin with 0x23!

1. Why does the drive's pidl differ from one point to another in
Win98?

2. Sure, I can simply change the pidl upon receipt from 0x2f to 0x23,
but I'm afraid this is a small symptom of a much larger problem. Is
it?

3. Is this a bug in the Windows 98 shell?

Any help or advice will be greatly appreciated. TIA.

-Nollie
Nollie :)
2005-10-13 18:08:00 UTC
Permalink
Ok, I still don't know why the same item's pidl changes, but I did
find a nice solution for anyone who's interested.

(Crickets chirping...)

In navigating the namespace I use each item's simple pidl. These pidls
are compared with each other using ILIsEqual(). ILIsEqual() is the
problem! The solution is to get an IShellFolder pointer to the item's
parent, and then use IShellFolder::CompareIDs() to compare the pidls.

IShellFolder::CompareIDs() will equate two pidls that represent the
same item, but have different binary values. ILIsEqual() only compares
the pidls' binary values.

Any comments?

-Nollie
Jim Barry
2005-10-13 20:53:45 UTC
Permalink
Post by Nollie :)
Any comments?
Yes - item identifiers are supposed to be opaque. This is explained in the topic "The Shell Namespace". You shouldn't attempt to ascribe any meaning to the data stored in the item ID.

http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/namespace.asp
--
Jim Barry, MVP for Windows SDK
Nollie :)
2005-10-14 06:02:46 UTC
Permalink
Post by Jim Barry
You shouldn't attempt to ascribe any meaning to the data stored in the item ID.
Thanks for your help. I didn't mean to give the impression that my
program relies on binary pidl data. I just want to compare any two
shell items and determine if they are the same item or not.

-Nollie
Matt Ellis
2005-10-13 21:31:36 UTC
Permalink
So, assuming you get these PIDLs by enumerating the My Computer folder
- how do you handle my custom namespace extension that's I've got
registered in My Computer? It's my PIDL, I can put anything I like in
there. Let's say I put in 0x23. How does that break this code? What if
I put in 0x2f?

Don't look at the contents of a PIDL - they're not yours, not
documented, and therefore not trustworkthy.

Cheers
Matt
Post by Nollie :)
The first byte of a pidl determines what type of file system object
the item is. For example,
ITEMIDLIST *pidl;
...GetThePIDL...
switch ( pidl->mkid.abID[0] )
{
case 0x25: // cd-rom drive
case 0x29 // floppy drive
case 0x23: // fixed drive?
case 0x2f: // fixed drive?
break;
}
On my XP machine, all of the fixed drives show up as 0x2f. On my Win98
box, all of the fixed drives show up as 0x23.
There's at least one circumstance where this causes a major problem
My shell viewer (treeview control) stores all its items with their
respective simple pidls. All the fixed drives' pidls start with 0x23.
After registering SHChangeNotifyRegister(), my program receives the
SHCNE_NETSHARE message along with a pidl of the affected item. If the
item is on a fixed drive, the drive component of the pidl is 0x2f,
which makes it very difficult to locate in my treeview because all the
fixed drives begin with 0x23!
1. Why does the drive's pidl differ from one point to another in
Win98?
2. Sure, I can simply change the pidl upon receipt from 0x2f to 0x23,
but I'm afraid this is a small symptom of a much larger problem. Is
it?
3. Is this a bug in the Windows 98 shell?
Any help or advice will be greatly appreciated. TIA.
-Nollie
Nollie :)
2005-10-14 05:56:21 UTC
Permalink
Post by Matt Ellis
Don't look at the contents of a PIDL - they're not yours, not
documented, and therefore not trustworkthy.
Except for debugging purposes, my program doesn't look at the contents
of pidls, not at all. However, Microsoft's function ILIsEqual()
does...poorly. Talk about not documented, the entire shell api has the
most vague documentation I've seen of all Win32. Here's MSDN's
description of the ILIsEqual() function:

Tests whether two ITEMIDLIST structures are equal.

Equal how? Take your custom namespace extension for example. The same
NSE can have 2 different pidls at different points of execution, and
ILIsEqual() will have no idea.

IShellFolder::CompareIDs() is the answer. A very simple, undocumented
answer. I wish someone here could have told me this sooner.
Jim Barry
2005-10-14 10:49:35 UTC
Permalink
Post by Nollie :)
Except for debugging purposes, my program doesn't look at the contents
of pidls, not at all. However, Microsoft's function ILIsEqual()
does...poorly.
ILIsEqual just does a binary comparison of the data structure - the containing folder object is not consulted.
Post by Nollie :)
Talk about not documented, the entire shell api has the
most vague documentation I've seen of all Win32.
Some parts of the shell have become quite well documented over the years. Some parts less so. ILIsEqual is one of the "Settlement Program Interfaces", documented only as a result of the DoJ vs Microsoft antitrust case. Microsoft claims that the settlement interfaces have been documented to the same standard as the rest of Win32, but this is blatantly untrue.
Post by Nollie :)
IShellFolder::CompareIDs() is the answer. A very simple, undocumented
answer. I wish someone here could have told me this sooner.
I'll see if I can get something added to the ILIsEqual documentation.
--
Jim Barry, MVP for Windows SDK
Loading...