Modernizing our simple program that retrieves information about the items in the Recycle Bin

Last time,
we wrote a simple program to print various properties of the items
in the Recycle Bin,
and we did so in the classical style,
using item ID lists and IShell­Folders.
One thing you may have noticed is that a lot of functions take
the combination of an IShell­Folder and a
PCUITEMID_CHILD.
In the shell namespace, operations on items usually happen
by means of the pair (folder, child),
and one of the common mistakes made by beginners is
failing to keep track of the pairing and passing child pidls
to the wrong parent folder.

Even if you're not a beginner and are good at keeping track of
which child pidls correspond to which parent folders,
it's still extra work you have to do,
and it means that a lot of functions take two parameters in order to
describe one thing.

Enter IShell­Item.

The IShell­Item encapsulates the pair (folder, child).
This solves two problems:

You only have to pass one thing around (the IShell­Item)
instead of two (the IShell­Folder and the
PCUITEMID_CHILD).

By keeping track of the two items as a single unit,
it reduces the risk that you'll accidentally use a child pidl
with the wrong parent folder.

Another complexity of the classic shell interface is that there
are a bunch of ways of obtaining COM objects from a shell folder:

IShell­Folder::Bind­To­Object

IShell­Folder::Bind­To­Storage

IShell­Folder::Create­View­Object

IShell­Folder::Get­UI­Object­Of

IUnknown::Query­Interface
(thanks to the desktop special case we saw last time).

The IShell­Item::Bind­To­Handler
interface hides these
special-cases by dealing with them under the covers so you don't have to.
You just call IShell­Item::Bind­To­Handler
and it figures
out where to get the object and what weird special cases apply.
(It also takes care of the weird S_FALSE return value
from IShell­Folder::Enum­Objects.)

And then there's the annoyance of
IShell­Folder::Get­Display­Name­Of
using
the kooky STRRET structure.
The IShell­Item::Get­Display­Name
function encapsulates that
away for you by doing the work to convert that STRRET
into a boring string pointer.

First up in modernizing our sample program
is to change Bind­To­Csidl to return a shell item
instead of a shell folder.

And then we convert Print­Detail to use
IShell­Item.
Oh wait, now we've hit a snag:
The IShell­Item interface doesn't have a helper method
that wraps IShell­Folder2::Get­Details­Ex.
Fortunately, there is a way to ask IShell­Item to
regurgitate the IShell­Folder
and PITEMID_CHILD
that it is wrapping:
You use the
IParent­And­Item::Get­Parent­And­Item
method.