mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-22 08:53:08 +08:00
[Settings]Fix backup and restore select folder when running as admin (#24164)
* Settings bkp and restore Open foolder when elevated using shell32 api. * increase the size of the alocated buffer for the path based on https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
This commit is contained in:
parent
eeca3014e7
commit
28144b6375
72
src/settings-ui/Settings.UI/Helpers/ShellGetFolder.cs
Normal file
72
src/settings-ui/Settings.UI/Helpers/ShellGetFolder.cs
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static Microsoft.PowerToys.Settings.UI.Helpers.ShellGetFolder;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
{
|
||||
public class ShellGetFolder
|
||||
{
|
||||
[DllImport("shell32.dll")]
|
||||
private static extern IntPtr SHBrowseForFolderW(ref BrowseInformation browseInfo);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
private static extern int SHGetPathFromIDListW(IntPtr pidl, IntPtr pszPath);
|
||||
|
||||
public delegate int BrowseCallbackProc(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct BrowseInformation
|
||||
{
|
||||
public IntPtr HwndOwner;
|
||||
public IntPtr PidlRoot;
|
||||
public string PszDisplayName;
|
||||
public string LpszTitle;
|
||||
public uint UlFlags;
|
||||
public BrowseCallbackProc Lpfn;
|
||||
public IntPtr LParam;
|
||||
public int IImage;
|
||||
}
|
||||
|
||||
public static string GetFolderDialog(IntPtr hwndOwner)
|
||||
{
|
||||
// windows MAX_PATH with long path enable can be approximated 32k char long
|
||||
// allocating more than double (unicode) to hold the path
|
||||
StringBuilder sb = new StringBuilder(65000);
|
||||
IntPtr bufferAddress = Marshal.AllocHGlobal(65000);
|
||||
IntPtr pidl = IntPtr.Zero;
|
||||
BrowseInformation browseInfo;
|
||||
browseInfo.HwndOwner = hwndOwner;
|
||||
browseInfo.PidlRoot = IntPtr.Zero;
|
||||
browseInfo.PszDisplayName = null;
|
||||
browseInfo.LpszTitle = null;
|
||||
browseInfo.UlFlags = 0;
|
||||
browseInfo.Lpfn = null;
|
||||
browseInfo.LParam = IntPtr.Zero;
|
||||
browseInfo.IImage = 0;
|
||||
|
||||
try
|
||||
{
|
||||
pidl = SHBrowseForFolderW(ref browseInfo);
|
||||
if (SHGetPathFromIDListW(pidl, bufferAddress) == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
sb.Append(Marshal.PtrToStringUni(bufferAddress));
|
||||
Marshal.FreeHGlobal(bufferAddress);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Need to free pidl
|
||||
Marshal.FreeCoTaskMem(pidl);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||
@ -142,12 +143,12 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
|
||||
private async Task<string> PickSingleFolderDialog()
|
||||
{
|
||||
var openPicker = new FolderPicker();
|
||||
// This function was changed to use the shell32 API to open folder dialog
|
||||
// as the old one (PickSingleFolderAsync) can't work when the process is elevated
|
||||
// TODO: go back PickSingleFolderAsync when it's fixed
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
|
||||
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hwnd);
|
||||
openPicker.FileTypeFilter.Add("*");
|
||||
var folder = await openPicker.PickSingleFolderAsync();
|
||||
return folder?.Path;
|
||||
string r = await Task.FromResult<string>(ShellGetFolder.GetFolderDialog(hwnd));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user