Code:
idlItemsTemp = *pidlItems
Unfortunately, this will not work to copy a pidl. An idl is essentially one or more SHITEMID structures that are packed together, one after the other, in memory.
Code:
typedef struct _ITEMIDLIST {
SHITEMID mkid;
} ITEMIDLIST;
typedef struct _SHITEMID {
USHORT cb; // Size of identifier, in bytes, including cb itself.
BYTE abID[1]; // Variable-length item identifier.
} SHITEMID;
As you can see the SHITEMID structure is a variable sized structure. Therefore,
Code:
idlItemsTemp = *pidlItems
is going to run into two problems. First, only the first SHITEMID will be copied. Secondly, only the first three bytes of the variable sized SHITEMID will be copied.
MS provides the ILClone() function to copy a pidl. Again, this is only officially available in Win2000+. Here is a home brew implementation of ILClone() that you can use:
Code:
// GetPidlSize is available in a previous thread.
LPITEMIDLIST ILCloneImp(LPITEMIDLIST pidl)
{
if (pidl)
{
LPITEMIDLIST pidlRet;
DWORD cbPidl = GetPidlSize(pidl);
if (!(pidlRet = (LPITEMIDLIST) CoTaskMemAlloc(cbPidl))) return NULL;
CopyMemory(pidlRet, pidl, cbPidl);
return pidlRet;
}
else
{
return NULL;
}
}
It should be noted that all pidls need to be freed using CoTaskMemFree() or IMalloc::Free().
EDIT: In this case you can just store the pidl and not free it, so you can use it later.
Code:
hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidlProgFiles);
hr = SHGetDesktopFolder(&psfDeskTop);
hr = psfDeskTop->BindToObject(pidlProgFiles, NULL, IID_IShellFolder, (LPVOID*) &psfProgFiles);
psfDeskTop->Release();
hr = psfProgFiles->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
char pathAbsol[MAX_PATH+1];
// enum and print all sub folders
while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
{
pidlAbsol = ILCombineImp(pidlProgFiles, pidlItems);
if(SHGetPathFromIDList(pidlAbsol, pathAbsol))
{
cout<< pathAbsol << endl;
}
// bind only the 1st sub folder
if(!psfFirstFolder)
{
uAttr = SFGAO_FOLDER;
psfProgFiles->GetAttributesOf(1, (LPCITEMIDLIST *) &pidlItems, &uAttr);
if(uAttr & SFGAO_FOLDER)
{
hr = psfProgFiles->BindToObject(pidlItems, NULL, IID_IShellFolder, (LPVOID *) &psfFirstFolder); // get IShellFolder IF for daughter folder
pidlItemsTemp = pidlItems; // store the PIDL of the 1st folder
}
}
else
{
// Free the pidl if we don't need it later
CoTaskMemFree(pidlItems);
}
CoTaskMemFree(pidlAbsol);
}
cout << "\n\n";
ppenum->Release();
if(psfFirstFolder)
{
hr = psfFirstFolder->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
// enum through items in the 1st sub folder
while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1) // ?
{
pidlAbsol = ILCombineImp(pidlItemsTemp, pidlItems);
if(SHGetPathFromIDList(pidlAbsol, pathAbsol))
{
cout<< pathAbsol << endl;
}
CoTaskMemFree(pidlAbsol);
CoTaskMemFree(pidlItems);
}
}
CoTaskMemFree(pidlItemsTemp);