locked
How to get PIDL from OpenSavePidlMRU

    Question

  • Hi All, 

          I am trying to read binary data stored in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\*, after reading i am trying to convert that binary data to PIDL by constructing PIDL. Following is the sample code for the same. Can anybody point out what i am doing wrong?

    typedef struct _PIDLDATA
    {
    	USHORT cb;
        LPBYTE lpData;
    }PIDLDATA, *LPPIDLDATA;
    
    #define OPENSAVE_MRU_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU\\"
    
    void OpenMRUFiles(CString strExt, CString& strFiles)
    {
    	HKEY hKey;
    	CString strKey (OPENSAVE_MRU_KEY);
    	strKey += strExt;
    	if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_QUERY_VALUE, &hKey))
    	{
    		//DWORD dwType = REG_BINARY;
    		DWORD dwBufSize = 0;
    		if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, 0, &dwBufSize))
    		{
    			LPBYTE lpData = new BYTE[dwBufSize + 1];
    			if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, lpData, &dwBufSize))
    			{
    				LPPIDLDATA	pidlOut = NULL;
    
    				CComPtr<IMalloc> spMalloc;
    				HRESULT hr = SHGetMalloc(&spMalloc);
    
    				pidlOut = (LPPIDLDATA)spMalloc->Alloc(dwBufSize + sizeof(USHORT));
    
    				pidlOut->cb = dwBufSize;
    				pidlOut->lpData = new BYTE[dwBufSize];
    				memcpy(pidlOut->lpData, lpData, dwBufSize);
    
    				pidlOut = (LPPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);
    
    				pidlOut->cb = 0;
    
    				wchar_t szPath[MAX_PATH] = {0};
    				SHGetPathFromIDListW((LPCITEMIDLIST)pidlOut, szPath); //here i always get DesktopFolder not the value stored @ 0
    				int ia = 0;
    			}
    			else
    			{
    				DWORD dwError = GetLastError();
    			}
    		}
    		RegCloseKey(hKey);
    	}
    }
    
    void main()
    {
            CString strMRUPrtFiles;
    	OpenMRUFiles(L"*", strMRUPrtFiles);
    }

    Monday, March 19, 2012 11:22 AM

Answers

  • Ok I think i have found the solution and thought should share it if somebody requires it.

    Just modified OpenMRUFiles function.

    void OpenMRUFiles(CString strExt, CString& strFiles)
    {
    	HKEY hKey;
    	CString strKey (OPENSAVE_MRU_KEY);
    	strKey += strExt;
    	if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_QUERY_VALUE, &hKey))
    	{
    		//DWORD dwType = REG_BINARY;
    		DWORD dwBufSize = 0;
    		if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, 0, &dwBufSize))
    		{
    			LPBYTE lpData = new BYTE[dwBufSize+ 1];
    			if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, lpData, &dwBufSize))
    			{
    				CComPtr<IMalloc> spMalloc;
    				HRESULT hr = SHGetMalloc(&spMalloc);
    
    				// Also allocate memory for the final null SHITEMID.
    				LPITEMIDLIST pidlNew = (LPITEMIDLIST) spMalloc->Alloc(sizeof(BYTE) + dwBufSize);
    
    				if ( pidlNew )
    				{
    					memcpy(pidlNew, lpData, dwBufSize);
    					wchar_t szPath[MAX_PATH] = {0};
    					if(SHGetPathFromIDListW(pidlNew, szPath))
    					{
    						AfxMessageBox(szPath);
    					}
    					spMalloc->Free(pidlNew);
    				}				
    				if(lpData)
    					delete lpData;
    			}
    			else
    			{
    				DWORD dwError = GetLastError();
    			}
    		}
    		RegCloseKey(hKey);
    	}
    }

    • Marked as answer by CoolSanil Tuesday, March 27, 2012 2:50 PM
    Tuesday, March 27, 2012 2:50 PM

All replies

  • Hello,

    What's the return value of this function?

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, March 21, 2012 10:08 AM
    Moderator
  • Hi Jesse,

                 Thanks for your reply. Return value of this function is path to desktop folder always. 

    Thanks,

    CoolSanil

    Friday, March 23, 2012 6:27 PM
  • Ok I think i have found the solution and thought should share it if somebody requires it.

    Just modified OpenMRUFiles function.

    void OpenMRUFiles(CString strExt, CString& strFiles)
    {
    	HKEY hKey;
    	CString strKey (OPENSAVE_MRU_KEY);
    	strKey += strExt;
    	if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_QUERY_VALUE, &hKey))
    	{
    		//DWORD dwType = REG_BINARY;
    		DWORD dwBufSize = 0;
    		if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, 0, &dwBufSize))
    		{
    			LPBYTE lpData = new BYTE[dwBufSize+ 1];
    			if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"0", 0, NULL, lpData, &dwBufSize))
    			{
    				CComPtr<IMalloc> spMalloc;
    				HRESULT hr = SHGetMalloc(&spMalloc);
    
    				// Also allocate memory for the final null SHITEMID.
    				LPITEMIDLIST pidlNew = (LPITEMIDLIST) spMalloc->Alloc(sizeof(BYTE) + dwBufSize);
    
    				if ( pidlNew )
    				{
    					memcpy(pidlNew, lpData, dwBufSize);
    					wchar_t szPath[MAX_PATH] = {0};
    					if(SHGetPathFromIDListW(pidlNew, szPath))
    					{
    						AfxMessageBox(szPath);
    					}
    					spMalloc->Free(pidlNew);
    				}				
    				if(lpData)
    					delete lpData;
    			}
    			else
    			{
    				DWORD dwError = GetLastError();
    			}
    		}
    		RegCloseKey(hKey);
    	}
    }

    • Marked as answer by CoolSanil Tuesday, March 27, 2012 2:50 PM
    Tuesday, March 27, 2012 2:50 PM
  • Somebody can convert this code to VB.NET ?
    Tuesday, May 01, 2012 5:00 PM
  • Hi

    I dont know about VB.NET but I can help you with C#. Hope you can convert this code to VB.NET

    using Microsoft.Win32;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication2
    {
        class Program
        {
           [DllImport("shell32.dll")]
            private static extern Int32 SHGetPathFromIDListW(UIntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] 							 StringBuilder pszPath);
    
            static void Main(string[] args)
            {
                String mru = @"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU";
                RegistryKey rk = Registry.CurrentUser.OpenSubKey(mru);
                foreach (string skName in rk.GetSubKeyNames())
                {
                    RegistryKey sk = rk.OpenSubKey(skName);
                    object value = sk.GetValue("0");
                    if (value == null)
                        throw new NullReferenceException();
                    
                    byte[] data = (byte[])(value);
    
                    IntPtr p = Marshal.AllocHGlobal(data.Length);
                    Marshal.Copy(data, 0, p, data.Length);
    
                    // get number of data;
                    UInt32 cidl = (UInt32)Marshal.ReadInt16(p);
    
                    // get parent folder
                    UIntPtr parentpidl = (UIntPtr)((UInt32)p);
    
                    StringBuilder path = new StringBuilder(256);
    
                    SHGetPathFromIDListW(parentpidl, path);
    
                    Marshal.Release(p);
    
                    string fileName = path.ToString();
                }
            }        
        }
    }

    Thanks,

    CoolSanil :)

    Wednesday, May 02, 2012 4:13 AM
  • thank you very much +++

    I can convert to vb.net

    Saturday, May 05, 2012 5:35 PM