Skip to content

Commit

Permalink
[Registry Preview] Moving to a different API to call the File Picker (m…
Browse files Browse the repository at this point in the history
…icrosoft#25260)

* Moving from FileOpenPicker

Moving from FileOpenPicker to a Win32/PInvoke version, so it can be opened while running as Admin.

* Update Resources.resw

Replacing a lost string.

* Save file picker also crashed

Switched to Win32-based SafeFilePicker
Cleaned up some of the code which should now pass spell checking and removed pragmas
  • Loading branch information
randyrants authored Apr 11, 2023
1 parent d0a1e40 commit 1dc013f
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 30 deletions.
39 changes: 39 additions & 0 deletions src/modules/registrypreview/RegistryPreviewUI/FileName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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;

namespace RegistryPreview
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct FileName
{
public int StructSize;
public IntPtr HwndOwner;
public IntPtr Instance;
public string Filter;
public string CustomFilter;
public int MaxCustFilter;
public int FilterIndex;
public string File;
public int MaxFile;
public string FileTitle;
public int MaxFileTitle;
public string InitialDir;
public string Title;
public int Flags;
public short FileOffset;
public short FileExtension;
public string DefExt;
public IntPtr CustData;
public IntPtr Hook;
public string TemplateName;
public IntPtr PtrReserved;
public int Reserved;
public int FlagsEx;
}
}
52 changes: 24 additions & 28 deletions src/modules/registrypreview/RegistryPreviewUI/MainWindow.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@ private async void OpenButton_Click(object sender, RoutedEventArgs e)
}
}

// Pull in a new REG file
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.ViewMode = PickerViewMode.List;
fileOpenPicker.CommitButtonText = resourceLoader.GetString("OpenButtonText");
fileOpenPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
fileOpenPicker.FileTypeFilter.Add(".reg");
// Pull in a new REG file - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
string filename = OpenFilePicker.ShowDialog(
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("OpenDialogTitle"));

// Get the HWND so we an open the modal
IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
InitializeWithWindow.Initialize(fileOpenPicker, hWnd);
if (filename == string.Empty || File.Exists(filename) == false)
{
return;
}

StorageFile storageFile = await fileOpenPicker.PickSingleFileAsync();
StorageFile storageFile = await StorageFile.GetFileFromPathAsync(filename);

if (storageFile != null)
{
Expand Down Expand Up @@ -174,27 +174,23 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
/// <summary>
/// Uses a picker to save out a copy of the current reg file
/// </summary>
private async void SaveAsButton_Click(object sender, RoutedEventArgs e)
private void SaveAsButton_Click(object sender, RoutedEventArgs e)
{
// Save out a new REG file and then open it
FileSavePicker fileSavePicker = new FileSavePicker();
fileSavePicker.CommitButtonText = resourceLoader.GetString("SaveButtonText");
fileSavePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
fileSavePicker.FileTypeChoices.Add("Registry file", new List<string>() { ".reg" });
fileSavePicker.SuggestedFileName = resourceLoader.GetString("SuggestFileName");

// Get the HWND so we an save the modal
IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
InitializeWithWindow.Initialize(fileSavePicker, hWnd);

StorageFile storageFile = await fileSavePicker.PickSaveFileAsync();

if (storageFile != null)
// Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's
// called while running as admin
string filename = SaveFilePicker.ShowDialog(
resourceLoader.GetString("SuggestFileName"),
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
resourceLoader.GetString("SaveDialogTitle"));

if (filename == string.Empty)
{
App.AppFilename = storageFile.Path;
SaveFile();
UpdateToolBarAndUI(OpenRegistryFile(App.AppFilename));
return;
}

App.AppFilename = filename;
SaveFile();
UpdateToolBarAndUI(OpenRegistryFile(App.AppFilename));
}

/// <summary>
Expand Down
36 changes: 36 additions & 0 deletions src/modules/registrypreview/RegistryPreviewUI/OpenFileName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.Runtime.InteropServices;

namespace RegistryPreview
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504
public static partial class OpenFilePicker
{
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool GetOpenFileName(ref FileName openFileName);

public static string ShowDialog(string filter, string dialogTitle)
{
FileName openFileName = default(FileName);
openFileName.StructSize = Marshal.SizeOf(openFileName);

openFileName.Filter = filter;
openFileName.File = new string(new char[256]);
openFileName.MaxFile = openFileName.File.Length;
openFileName.FileTitle = new string(new char[64]);
openFileName.MaxFileTitle = openFileName.FileTitle.Length;
openFileName.Title = dialogTitle;

if (GetOpenFileName(ref openFileName))
{
return openFileName.File;
}

return string.Empty;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<AssemblyDescription>PowerToys RegistryPreview</AssemblyDescription>
<RootNamespace>RegistryPreview</RootNamespace>
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<!-- SelfContained=true requires RuntimeIdentifier to be set -->
Expand Down
38 changes: 38 additions & 0 deletions src/modules/registrypreview/RegistryPreviewUI/SaveFileName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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.Runtime.InteropServices;

namespace RegistryPreview
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504
public static partial class SaveFilePicker
{
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool GetSaveFileName(ref FileName saveFileName);

public static string ShowDialog(string suggestedFilename, string filter, string dialogTitle)
{
FileName saveFileName = default(FileName);
saveFileName.StructSize = Marshal.SizeOf(saveFileName);

saveFileName.Filter = filter;
saveFileName.File = new string(new char[256]);
saveFileName.MaxFile = saveFileName.File.Length;
saveFileName.File = string.Concat(suggestedFilename, saveFileName.File);
saveFileName.FileTitle = new string(new char[64]);
saveFileName.MaxFileTitle = saveFileName.FileTitle.Length;
saveFileName.Title = dialogTitle;
saveFileName.DefExt = "reg";

if (GetSaveFileName(ref saveFileName))
{
return saveFileName.File;
}

return string.Empty;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@
<data name="FileSaveError" xml:space="preserve">
<value>The REG file cannot be written to.</value>
</data>
<data name="FilterAllFiles" xml:space="preserve">
<value>All files (*.*)</value>
</data>
<data name="FilterRegistryName" xml:space="preserve">
<value>Registry files (*.reg)</value>
</data>
<data name="InvalidRegistryFile" xml:space="preserve">
<value> doesn't appear to be a valid registry file!</value>
</data>
Expand All @@ -153,8 +159,8 @@
<data name="OpenButton.Label" xml:space="preserve">
<value>Open file...</value>
</data>
<data name="OpenButtonText" xml:space="preserve">
<value>Open</value>
<data name="OpenDialogTitle" xml:space="preserve">
<value>Open Registry file...</value>
</data>
<data name="RefreshButton.Label" xml:space="preserve">
<value>Reload from file</value>
Expand Down

0 comments on commit 1dc013f

Please sign in to comment.