ShellGetFolder.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Runtime.InteropServices; 7 using System.Text; 8 9 namespace Microsoft.PowerToys.Settings.UI.Helpers 10 { 11 public class ShellGetFolder 12 { 13 public delegate int BrowseCallbackProc(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp); 14 15 [StructLayout(LayoutKind.Sequential)] 16 public struct BrowseInformation 17 { 18 public IntPtr HwndOwner; 19 public IntPtr PidlRoot; 20 public string PszDisplayName; 21 public string LpszTitle; 22 public uint UlFlags; 23 public BrowseCallbackProc Lpfn; 24 public IntPtr LParam; 25 public int IImage; 26 } 27 28 public static string GetFolderDialog(IntPtr hwndOwner) 29 { 30 return GetFolderDialogWithFlags(hwndOwner, 0); 31 } 32 33 public static string GetFolderDialogWithFlags(IntPtr hwndOwner, uint ulFlags) 34 { 35 // windows MAX_PATH with long path enable can be approximated 32k char long 36 // allocating more than double (unicode) to hold the path 37 StringBuilder sb = new StringBuilder(65000); 38 IntPtr bufferAddress = Marshal.AllocHGlobal(65000); 39 IntPtr pidl = IntPtr.Zero; 40 BrowseInformation browseInfo; 41 browseInfo.HwndOwner = hwndOwner; 42 browseInfo.PidlRoot = IntPtr.Zero; 43 browseInfo.PszDisplayName = null; 44 browseInfo.LpszTitle = null; 45 browseInfo.UlFlags = ulFlags; 46 browseInfo.Lpfn = null; 47 browseInfo.LParam = IntPtr.Zero; 48 browseInfo.IImage = 0; 49 50 try 51 { 52 pidl = NativeMethods.SHBrowseForFolderW(ref browseInfo); 53 if (NativeMethods.SHGetPathFromIDListW(pidl, bufferAddress) == 0) 54 { 55 return null; 56 } 57 58 sb.Append(Marshal.PtrToStringUni(bufferAddress)); 59 Marshal.FreeHGlobal(bufferAddress); 60 } 61 finally 62 { 63 // Need to free pidl 64 Marshal.FreeCoTaskMem(pidl); 65 } 66 67 return sb.ToString(); 68 } 69 70 public struct FolderDialogFlags 71 { 72 public const uint _BIF_NEWDIALOGSTYLE = 0x00000040; 73 } 74 } 75 }