Jump to content

Get Root PIDL


musicstashall
 Share

Recommended Posts

Hello.
Faced the task - you need to read the paths from the registry, but the string is encoded:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers, SlideshowDirectoryPath1:

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

Here, there must be paths to the images used by the system for the slideshow. It is necessary to decode, and then to encode and write this parameter. There is an article where you can see a sample PowerShell code for such operations, but I did not get the desired result: https://social.technet.microsoft.com/Forums/office/en-US/2e0aa2b5-6256-4b05-9ef7-3d3904438fbb/where-are-photo-screensaver-settings-saved

cls


#That string is encoded in Base64, without headers. There is a Windows API that encrypt binary arrays (the PIDL) to Base64, CryptBinaryToString. The dwFlags parameter should be set to CRYPT_STRING_BASE64.
#Our problem is the inverse, given a Base64 string (the encoded PIDL), get the decoded PIDL. There's an API for that, too!, CryptStringToBinary. The dwFlags parameter should also be set to CRYPT_STRING_BASE64.
#I think it is not hard to write a small program that uses those API's (and some more to get a "readable" path from the PIDL); ask in the MSDN forums to get directions if you get stuck.

#http://www.ms-windows.info/Help/windows-photo-screensaver-settings-19334.aspx

#http://msdn.microsoft.com/en-us/library/aa379887(v=vs.85).aspx
#BOOL WINAPI CryptBinaryToString(
#  _In_       const BYTE *pbBinary,
#  _In_       DWORD cbBinary,
#  _In_       DWORD dwFlags,
#  _Out_opt_  LPTSTR pszString,
#  _Inout_    DWORD *pcchString
#);
#http://msdn.microsoft.com/en-us/library/aa380285(v=vs.85).aspx
#BOOL WINAPI CryptStringToBinary(
#  _In_     LPCTSTR pszString,
#  _In_     DWORD cchString,
#  _In_     DWORD dwFlags,
#  _In_     BYTE *pbBinary,
#  _Inout_  DWORD *pcbBinary,
#  _Out_    DWORD *pdwSkip,
#  _Out_    DWORD *pdwFlags
#);






add-type  @"

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

public static class PIDLUtils
{
        // funciones
        [DllImport("shell32.dll")]
        public static extern Int32 SHGetDesktopFolder(out IShellFolder ppshf);

        [DllImport("shell32.dll")]
        public static extern bool SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);

        [DllImport("crypt32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CryptBinaryToString(IntPtr pcbBinary, int cbBinary, uint dwFlags, StringBuilder pszString, ref int pcchString);

        [DllImport("crypt32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CryptStringToBinary(string pszString, int cchString, uint dwFlags, IntPtr pbBinary, ref int pcbBinary, ref int pdwSkip, ref int pdwFlags);

        // interfaces
        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("000214E6-0000-0000-C000-000000000046")]
        public interface IShellFolder
        {
            Int32 ParseDisplayName(IntPtr hwnd, IntPtr pbc, String pszDisplayName, UInt32 pchEaten, out IntPtr ppidl, UInt32 pdwAttributes);
            Int32 EnumObjects(IntPtr hwnd, ESHCONTF grfFlags, out IntPtr ppenumIDList);
            Int32 BindToObject(IntPtr pidl, IntPtr pbc, [In]ref Guid riid, out IntPtr ppv);
            Int32 BindToStorage(IntPtr pidl, IntPtr pbc, [In]ref Guid riid, out IntPtr ppv);
            Int32 CompareIDs(Int32 lParam, IntPtr pidl1, IntPtr pidl2);
            Int32 CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, out IntPtr ppv);
            Int32 GetAttributesOf(UInt32 cidl, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]IntPtr[] apidl, ref ESFGAO rgfInOut);
            Int32 GetUIObjectOf(IntPtr hwndOwner, UInt32 cidl, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] apidl, [In] ref Guid riid, UInt32 rgfReserved, out IntPtr ppv);
            Int32 GetDisplayNameOf(IntPtr pidl, ESHGDN uFlags, out ESTRRET pName);
            Int32 SetNameOf(IntPtr hwnd, IntPtr pidl, String pszName, ESHCONTF uFlags, out IntPtr ppidlOut);
        }

        // enumeraciones
        public enum ESHCONTF
        {
            SHCONTF_FOLDERS = 0x0020,
            SHCONTF_NONFOLDERS = 0x0040,
            SHCONTF_INCLUDEHIDDEN = 0x0080,
            SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
            SHCONTF_NETPRINTERSRCH = 0x0200,
            SHCONTF_SHAREABLE = 0x0400,
            SHCONTF_STORAGE = 0x0800
        }

        public enum ESFGAO : uint
        {
            SFGAO_CANCOPY = 0x00000001,
            SFGAO_CANMOVE = 0x00000002,
            SFGAO_CANLINK = 0x00000004,
            SFGAO_LINK = 0x00010000,
            SFGAO_SHARE = 0x00020000,
            SFGAO_READONLY = 0x00040000,
            SFGAO_HIDDEN = 0x00080000,
            SFGAO_FOLDER = 0x20000000,
            SFGAO_FILESYSTEM = 0x40000000,
            SFGAO_HASSUBFOLDER = 0x80000000,
        }

        public enum ESHGDN
        {
            SHGDN_NORMAL = 0x0000,
            SHGDN_INFOLDER = 0x0001,
            SHGDN_FOREDITING = 0x1000,
            SHGDN_FORADDRESSBAR = 0x4000,
            SHGDN_FORPARSING = 0x8000,
        }

        public enum ESTRRET : int
        {
            eeRRET_WSTR = 0x0000,
            STRRET_OFFSET = 0x0001,
            STRRET_CSTR = 0x0002
        }

        // constantes
        private const uint CRYPT_STRING_BASE64 = 1;
		
//*****************************************************************************************************************************
//*****************************************************************************************************************************

        // mis funciones

        public static string Encode(string myClearPath)
        {
            IShellFolder folder;
            IntPtr pidl;
            string Pathcodificado;
            Pathcodificado = "ERROR";
            string myPathTextoPlano = myClearPath;
            //string myPathTextoPlano = @"c:\flashtool"; // Regex.Escape(myClearPath);
            

            // este es el folder del escritorio (raíz del espacio de nombres del shell)
            if (SHGetDesktopFolder(out folder) == 0)
            {
                // pidl del archivo
                //folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, @"C:\walter\yo.png", 0, out pidl, 0);
                folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, myPathTextoPlano, 0, out pidl, 0);

                // parseo el pidl para obtener sus tamaño
                int k = 0;
                short cb = 0;
				
			  // ONLY WORKS WITH .NET FRAMEWORK 4	
              //  while ((k = Marshal.ReadInt16(pidl + cb)) > 0)
			  //		
              //  {
              //      cb += (short)k;
              //  }
			  
				IntPtr tempIntPtr = new IntPtr(pidl.ToInt64() + cb);
                while ((k = Marshal.ReadInt16(tempIntPtr)) > 0)
                {
                    cb += (short)k;
                    tempIntPtr = new IntPtr(pidl.ToInt64() + cb);
                }

                cb += 2;

                // encripto el pidl
                StringBuilder sb = new StringBuilder();
                int largo = 0;

                CryptBinaryToString(pidl, cb, CRYPT_STRING_BASE64, null, ref largo);
                sb.Capacity = largo;
                
                if (CryptBinaryToString(pidl, cb, CRYPT_STRING_BASE64, sb, ref largo))
                {
                    //Console.WriteLine(sb.ToString());
                    Pathcodificado = sb.ToString();
                }
                Marshal.FreeCoTaskMem(pidl);
            }
        
            return Pathcodificado;
        }
		
//************************************************************************************************************************************

        public static string Decode (string myEncryptedPath)
        {
            IShellFolder folder;
           // IntPtr pidl;
            string PathDescodificado;
            PathDescodificado = "ERROR";
            string mypathEncriptado = myEncryptedPath; // Regex.Escape(myEncryptedPath);

            // este es el folder del escritorio (raíz del espacio de nombres del shell)
            if (SHGetDesktopFolder(out folder) == 0)
            {
              
                // Desencripto 
                int a = 0;
                int b = 0;
                int largo = 0;


                CryptStringToBinary(mypathEncriptado, mypathEncriptado.Length, CRYPT_STRING_BASE64, IntPtr.Zero, ref largo, ref a, ref b);
                // recreo el objeto
                IntPtr pidl2 = Marshal.AllocCoTaskMem(largo);
                //if (CryptStringToBinary(sb.ToString(), sb.Length, CRYPT_STRING_BASE64, pidl2, ref largo, ref a, ref b))
                StringBuilder sb = new StringBuilder();
                if (CryptStringToBinary(mypathEncriptado, mypathEncriptado.Length, CRYPT_STRING_BASE64, pidl2, ref largo, ref a, ref b))
                {
                    // muestro el path proveyendo el pidl reconstruído
                    //sb.Clear(); Only works with .NET 4
					 sb.Length = 0;
                    sb.Capacity = 261;
                    SHGetPathFromIDList(pidl2, sb);
                    //Console.WriteLine(sb.ToString());
                    PathDescodificado = sb.ToString();
                }

                //
                //Marshal.FreeCoTaskMem(pidl);
                Marshal.FreeCoTaskMem(pidl2);
            }
            return PathDescodificado;

        }       
}

"@


try
{
	$MyPath = "c:\Windows"
	
	$Encrypted = [PIDLUtils]::Encode($MyPath)
	$Encrypted
		
	$notEncrypted = [PIDLUtils]::Decode($Encrypted) 
	$notEncrypted
	
}
catch
{
	$_
	break
}

I ask help

 

 

 

Link to comment
Share on other sites

Did you search the forum for Base64?
There are a few example implementations available :)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Quote

There are a few example implementations available

I tried all such examples, nothing happened. Read the topic yet, it turns out we need a completely different procedure, should get IShellItemArray. The quote:

Quote

The problem is,  IShellItemArray items = wallpaper.GetSlideshow(); where IDesktopWallpaper wallpaper = (IDesktopWallpaper)(new DesktopWallpaperClass()); gives me only the correct path, when slideshow is turned on. But for activating it (wallpaper.SetSlideshow(items)) , i need stored path from SlideshowDirectoryPath1.

So i think this value IShellItemArray is a IShellItemArray stored as string. But i have no idea, how to convert it from string to IShellItemArray .

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...