Thread: SHELL – Path problem 2

  1. #1
    Android geek@02's Avatar
    Join Date
    Mar 2004
    Location
    Kurunegala Colony, Sri Lanka, Sri Lanka
    Posts
    470

    SHELL – Path problem 2

    Greetings.
    Below program 1st finds the program files folder and prints all the sub folders paths. Then, it goes into the 1st sub-folder and tries to print the contents paths in it, but fails. The problem is ‘idlItemsTemp’. I’ve tried to store the 1st sub folder’s PIDL in idlItemsTemp, then used it to combine with the PIDLs of the sub-folder's items to get the absolute path.
    But I get these as the absolute paths :
    C:\Documents and Settings\geekAt02\Desktop\§\iδτw►☻►☻►☻é♥\Entertain ment
    C:\Documents and Settings\geekAt02\Desktop\§\iδτw►☻►☻►☻é♥\Accessibi lity
    C:\Documents and Settings\geekAt02\Desktop\§\iδτw►☻►☻►☻é♥\Synchroni ze.lnk
    C:\Documents and Settings\geekAt02\Desktop\§\iδτw►☻►☻►☻é♥\Tour Windows XP.lnk
    C:\Documents and Settings\geekAt02\Desktop\§\iδτw►☻►☻►☻é♥\Program Compatibility
    Wizard.lnk
    Please some body show me how to fix this.
    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
    				idlItemsTemp = *pidlItems; // ? store the PIDL of the 1st folder
                }
            }
            pMalloc->Free(pidlItems); 
    		
    	}
    	
    	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(&idlItemsTemp, pidlItems);	
    			if(SHGetPathFromIDList(pidlAbsol, pathAbsol)) {
    				cout<< pathAbsol << endl;
    			}
    		}
    	}
    	................
    	................
    	................
    Thanks for reading.

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    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);
    Last edited by anonytmouse; 04-30-2004 at 03:37 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. a file path problem
    By fighter92 in forum C++ Programming
    Replies: 1
    Last Post: 06-21-2008, 05:50 AM
  2. Simulating a shell problem
    By Galileo in forum Linux Programming
    Replies: 1
    Last Post: 06-06-2008, 04:41 AM
  3. cross platform semaphore problem
    By jet-plane in forum C Programming
    Replies: 0
    Last Post: 05-24-2008, 01:59 PM
  4. Path Problem
    By AndyBomstad in forum C++ Programming
    Replies: 6
    Last Post: 05-05-2005, 02:17 PM
  5. System.ini Shell Problems
    By (TNT) in forum Windows Programming
    Replies: 2
    Last Post: 08-26-2001, 01:05 PM