I've implemented a directory walking algorithm for the Windows Shell using IShellItem
, IShellFolder
, IStorage
, IStream
, etc. All is well and good. I can even walk inside shell namespace extensions (e.g. .zip
) files.
However, I have problems extracting (regular) file sizes when files are being used by some other program with exclusive access.
AFAIK, there is nothing but the STATSTG
structure that gives more information than the file's name. There are essentially 3 ways to get a hold of a STATSTG
for a IShellItem
:
IEnumSTATSTG
instead of IEnumIDList
. Instead of invoking IShellFolder::EnumObjects()
, get the IStorage
for the folder and invoke IStorage::EnumElements()
. You now get STATSTG
structures directly.IStorage
for the IShellItem
and invoke IStorage::Stat()
.IStream
for the IShellItem
and invoke IStream::Stat()
.I would really like to use #1 because it would give me all the information I need. However, I cannot get it to enumerate folder contents. I successfully extract the IStorage
for the folder: it's own Stat()
gives me the proper folder name. I successfully extract the IEnumSTATSTG
, but the first call to Next(1, &item, NULL)
returns S_FALSE
and terminates the enumeration.
I would fallback to use #2 as it is still not so bad, but extracting the IStorage
for regular disk files produces an error using both of IShellItem::BindToHandler(0, BHID_Storage, ...)
and IShellFolder::BindToStorage(child, ...)
.
I finally tried #3 although it just plains seems wrong and it succeeds as long as files are not being used with exclusive access by another program.
I've googled around a bit and found several code snippets that use approach #3.
Question: Can anyone explain how I'm supposed to get the file's STATSTG
without using approach #3?
Should approach #1 work, or does the IStorage
implementation for regular folders simply not produce listings? Should approach #2 work or is the IStorage
implementation simply not implemented for regular files?
Environment: Windows Vista Ultimate 32-bit, Visual Studio 2008 Express. Using C++, no ATL, all custom COM wrappers (in-house, may be suitably modified assuming somwthing is wrong there).
Have you tried getting hold of the IShellItem2 interface, and then querying for the value of the PKEY_Size property?