Skip to content

Commit 83ed139

Browse files
committed
Merge remote-tracking branch 'origin/master' into exception_handling
2 parents e2f6805 + 68b6a2e commit 83ed139

File tree

14 files changed

+134
-45
lines changed

14 files changed

+134
-45
lines changed

Files.Launcher/Program.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ private static async Task parseArguments(AppServiceRequestReceivedEventArgs args
286286
}
287287
break;
288288

289+
case "SetVolumeLabel":
290+
var driveName = (string)args.Request.Message["drivename"];
291+
var newLabel = (string)args.Request.Message["newlabel"];
292+
Win32API.SetVolumeLabel(driveName, newLabel);
293+
break;
294+
289295
case "FileOperation":
290296
await parseFileOperation(args);
291297
break;
@@ -330,7 +336,19 @@ private static object HandleMenuMessage(ValueSet message, Win32API.DisposableDic
330336

331337
case "ExecAndCloseContextMenu":
332338
var cMenuExec = table.GetValue<Win32API.ContextMenu>("MENU");
333-
cMenuExec?.InvokeItem(message.Get("ItemID", -1));
339+
if (message.TryGetValue("ItemID", out var menuId))
340+
{
341+
switch (message.Get("CommandString", (string)null))
342+
{
343+
case "format":
344+
var drivePath = cMenuExec.ItemsPath.First();
345+
Win32API.OpenFormatDriveDialog(drivePath);
346+
break;
347+
default:
348+
cMenuExec?.InvokeItem((int)menuId);
349+
break;
350+
}
351+
}
334352
// The following line is needed to cleanup resources when menu is closed.
335353
// Unfortunately if you uncomment it some menu items will randomly stop working.
336354
// Resource cleanup is currently done on app closing,
@@ -348,7 +366,7 @@ private static Func<string, bool> FilterMenuItems(bool showOpenMenu)
348366
var knownItems = new List<string>() {
349367
"opennew", "openas", "opencontaining", "opennewprocess",
350368
"runas", "runasuser", "pintohome", "PinToStartScreen",
351-
"cut", "copy", "paste", "delete", "properties", "link", "format",
369+
"cut", "copy", "paste", "delete", "properties", "link",
352370
"Windows.ModernShare", "Windows.Share", "setdesktopwallpaper",
353371
Win32API.ExtractStringFromDLL("shell32.dll", 30312), // SendTo menu
354372
Win32API.ExtractStringFromDLL("shell32.dll", 34593), // Add to collection

Files.Launcher/Win32API.cs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,26 +93,6 @@ public static string[] CommandLineToArgs(string commandLine)
9393
}
9494
}
9595

96-
public static void UnlockBitlockerDrive(string drive, string password)
97-
{
98-
try
99-
{
100-
Process process = new Process();
101-
process.StartInfo.UseShellExecute = true;
102-
process.StartInfo.Verb = "runas";
103-
process.StartInfo.FileName = "powershell.exe";
104-
process.StartInfo.CreateNoWindow = true;
105-
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
106-
process.StartInfo.Arguments = $"-command \"$SecureString = ConvertTo-SecureString '{password}' -AsPlainText -Force; Unlock-BitLocker -MountPoint '{drive}' -Password $SecureString\"";
107-
process.Start();
108-
process.WaitForExit(30 * 1000);
109-
}
110-
catch (Win32Exception)
111-
{
112-
// If user cancels UAC
113-
}
114-
}
115-
11696
public static (string icon, bool isCustom) GetFileOverlayIcon(string path)
11797
{
11898
var shfi = new Shell32.SHFILEINFO();
@@ -134,6 +114,47 @@ public static (string icon, bool isCustom) GetFileOverlayIcon(string path)
134114
return (Convert.ToBase64String(bitmapData, 0, bitmapData.Length), isCustom);
135115
}
136116

117+
private static void RunPowershellCommand(string command, bool runAsAdmin)
118+
{
119+
try
120+
{
121+
Process process = new Process();
122+
if (runAsAdmin)
123+
{
124+
process.StartInfo.UseShellExecute = true;
125+
process.StartInfo.Verb = "runas";
126+
}
127+
process.StartInfo.FileName = "powershell.exe";
128+
process.StartInfo.CreateNoWindow = true;
129+
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
130+
process.StartInfo.Arguments = command;
131+
process.Start();
132+
process.WaitForExit(30 * 1000);
133+
}
134+
catch (Win32Exception)
135+
{
136+
// If user cancels UAC
137+
}
138+
}
139+
140+
public static void UnlockBitlockerDrive(string drive, string password)
141+
{
142+
RunPowershellCommand($"-command \"$SecureString = ConvertTo-SecureString '{password}' -AsPlainText -Force; Unlock-BitLocker -MountPoint '{drive}' -Password $SecureString\"", true);
143+
}
144+
145+
public static void OpenFormatDriveDialog(string drive)
146+
{
147+
// format requires elevation
148+
int driveIndex = drive.ToUpperInvariant()[0] - 'A';
149+
RunPowershellCommand($"-command \"$Signature = '[DllImport(\\\"shell32.dll\\\", SetLastError = false)]public static extern uint SHFormatDrive(IntPtr hwnd, uint drive, uint fmtID, uint options);'; $SHFormatDrive = Add-Type -MemberDefinition $Signature -Name \"Win32SHFormatDrive\" -Namespace Win32Functions -PassThru; $SHFormatDrive::SHFormatDrive(0, {driveIndex}, 0xFFFF, 0x0001)\"", true);
150+
}
151+
152+
public static void SetVolumeLabel(string driveName, string newLabel)
153+
{
154+
// rename requires elevation
155+
RunPowershellCommand($"-command \"$Signature = '[DllImport(\\\"kernel32.dll\\\", SetLastError = false)]public static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);'; $SetVolumeLabel = Add-Type -MemberDefinition $Signature -Name \"Win32SetVolumeLabel\" -Namespace Win32Functions -PassThru; $SetVolumeLabel::SetVolumeLabel('{driveName}', '{newLabel}')\"", true);
156+
}
157+
137158
// There is usually no need to define Win32 COM interfaces/P-Invoke methods here.
138159
// The Vanara library contains the definitions for all members of Shell32.dll, User32.dll and more
139160
// The ones below are due to bugs in the current version of the library and can be removed once fixed

Files.Launcher/Win32API_ContextMenu.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,13 @@ public class ContextMenu : Win32ContextMenu, IDisposable
130130
{
131131
private Shell32.IContextMenu cMenu;
132132
private User32.SafeHMENU hMenu;
133+
public List<string> ItemsPath { get; }
133134

134-
public ContextMenu(Shell32.IContextMenu cMenu, User32.SafeHMENU hMenu)
135+
public ContextMenu(Shell32.IContextMenu cMenu, User32.SafeHMENU hMenu, IEnumerable<string> itemsPath)
135136
{
136137
this.cMenu = cMenu;
137138
this.hMenu = hMenu;
139+
this.ItemsPath = itemsPath.ToList();
138140
this.Items = new List<Win32ContextMenuItem>();
139141
}
140142

@@ -199,15 +201,15 @@ public static ContextMenu GetContextMenuForFiles(string[] filePathList, Shell32.
199201
}
200202
}
201203

202-
public static ContextMenu GetContextMenuForFiles(ShellItem[] shellItems, Shell32.CMF flags, Func<string, bool> itemFilter = null)
204+
private static ContextMenu GetContextMenuForFiles(ShellItem[] shellItems, Shell32.CMF flags, Func<string, bool> itemFilter = null)
203205
{
204206
if (shellItems == null || !shellItems.Any())
205207
return null;
206208
using var sf = shellItems.First().Parent; // HP: the items are all in the same folder
207209
Shell32.IContextMenu menu = sf.GetChildrenUIObjects<Shell32.IContextMenu>(null, shellItems);
208210
var hMenu = User32.CreatePopupMenu();
209211
menu.QueryContextMenu(hMenu, 0, 1, 0x7FFF, flags);
210-
var contextMenu = new ContextMenu(menu, hMenu);
212+
var contextMenu = new ContextMenu(menu, hMenu, shellItems.Select(x => x.ParsingName));
211213
ContextMenu.EnumMenuItems(menu, hMenu, contextMenu.Items, itemFilter);
212214
return contextMenu;
213215
}

Files/BaseLayout.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,8 @@ private async void MenuLayoutItem_Click(object sender, RoutedEventArgs e)
385385
await Connection.SendMessageAsync(new ValueSet() {
386386
{ "Arguments", "ExecAndCloseContextMenu" },
387387
{ "Handle", menuHandle },
388-
{ "ItemID", menuItem.ID } });
388+
{ "ItemID", menuItem.ID },
389+
{ "CommandString", menuItem.CommandString }});
389390
}
390391
}
391392
}

Files/DataModels/SidebarPinnedModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public int IndexOfItem(INavigationControlItem locationItem, List<INavigationCont
181181
/// <returns>Task</returns>
182182
public async Task AddItemToSidebar(string path)
183183
{
184-
var item = await DrivesManager.GetRootFromPath(path);
184+
var item = await DrivesManager.GetRootFromPath(path).Wrap();
185185
var res = await StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item).Wrap();
186186
if (res)
187187
{

Files/Filesystem/DriveItem.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ namespace Files.Filesystem
1717
public class DriveItem : ObservableObject, INavigationControlItem
1818
{
1919
public string Glyph { get; set; }
20-
public string Text { get; set; }
2120
public string Path { get; set; }
2221
public StorageFolder Root { get; set; }
2322
public NavigationControlItemType ItemType { get; set; } = NavigationControlItemType.Drive;
@@ -38,6 +37,13 @@ public DriveType Type
3837
}
3938
}
4039

40+
private string _text;
41+
public string Text
42+
{
43+
get => _text;
44+
set => SetProperty(ref _text, value);
45+
}
46+
4147
private string _spaceText;
4248
public string SpaceText
4349
{
@@ -60,7 +66,21 @@ public DriveItem(StorageFolder root, DriveType type)
6066
CoreApplication.MainView.ExecuteOnUIThreadAsync(() => GetDriveItemProperties());
6167
}
6268

63-
private async Task GetDriveItemProperties()
69+
public async Task Update()
70+
{
71+
try
72+
{
73+
// Delay is needed to apply the new name
74+
var properties = await Root.Properties.RetrievePropertiesAsync(new[] { "System.ItemNameDisplay" })
75+
.AsTask().WithTimeout(TimeSpan.FromSeconds(5));
76+
Text = (string)properties["System.ItemNameDisplay"];
77+
}
78+
catch (NullReferenceException)
79+
{
80+
}
81+
}
82+
83+
private async void GetDriveItemProperties()
6484
{
6585
try
6686
{

Files/Filesystem/Drives.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public static async Task<StorageFolderWithPath> GetRootFromPath(string devicePat
349349
return null;
350350
}
351351
var rootPath = Path.GetPathRoot(devicePath);
352-
if (devicePath.StartsWith("\\\\?\\"))
352+
if (devicePath.StartsWith("\\\\?\\")) // USB device
353353
{
354354
// Check among already discovered drives
355355
StorageFolder matchingDrive = App.AppSettings.DrivesManager.Drives.FirstOrDefault(x =>
@@ -380,11 +380,12 @@ public static async Task<StorageFolderWithPath> GetRootFromPath(string devicePat
380380
return new StorageFolderWithPath(matchingDrive, rootPath);
381381
}
382382
}
383+
else if (devicePath.StartsWith("\\\\")) // Network share
384+
{
385+
rootPath = rootPath.LastIndexOf("\\") > 1 ? rootPath.Substring(0, rootPath.LastIndexOf("\\")) : rootPath; // Remove share name
386+
return new StorageFolderWithPath(await StorageFolder.GetFolderFromPathAsync(rootPath), rootPath);
387+
}
383388
// It's ok to return null here, on normal drives StorageFolder.GetFolderFromPathAsync works
384-
//else
385-
//{
386-
// return new StorageFolderWithPath(await StorageFolder.GetFolderFromPathAsync(rootPath), rootPath);
387-
//}
388389
return null;
389390
}
390391

Files/UserControls/SidebarControl.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
Padding="0"
7171
AllowDrop="True"
7272
BorderThickness="0.8"
73-
Content="{x:Bind Text}"
73+
Content="{x:Bind Text, Mode=OneWay}"
7474
DataContext="{x:Bind}"
7575
DragEnter="NavigationViewItem_DragEnter"
7676
DragLeave="NavigationViewItem_DragLeave"

Files/UserControls/SidebarControl.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ private async void NavigationViewDriveItem_DragOver(object sender, DragEventArgs
392392
var storageItems = await e.DataView.GetStorageItemsAsync();
393393

394394
if (storageItems.Count == 0 ||
395-
"Unknown".Equals(driveItem.SpaceText, StringComparison.OrdinalIgnoreCase) ||
395+
"DriveCapacityUnknown".GetLocalized().Equals(driveItem.SpaceText, StringComparison.OrdinalIgnoreCase) ||
396396
storageItems.AreItemsAlreadyInFolder(driveItem.Path))
397397
{
398398
e.AcceptedOperation = DataPackageOperation.None;

Files/UserControls/Widgets/DrivesWidget.xaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@
6767
VerticalAlignment="Stretch"
6868
HorizontalContentAlignment="Stretch"
6969
VerticalContentAlignment="Stretch"
70-
AutomationProperties.Name="{x:Bind Text}"
70+
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
7171
Background="{ThemeResource YourHomeCardBackgroundColor}"
7272
BorderThickness="1"
7373
Click="Button_Click"
7474
CornerRadius="4"
7575
Style="{StaticResource ButtonRevealStyle}"
7676
Tag="{x:Bind Path}"
77-
ToolTipService.ToolTip="{x:Bind Text}">
77+
ToolTipService.ToolTip="{x:Bind Text, Mode=OneWay}">
7878
<Grid
7979
Margin="12"
8080
HorizontalAlignment="Stretch"
@@ -98,7 +98,7 @@
9898
x:Name="ItemLocationName"
9999
FontSize="14"
100100
FontWeight="Medium"
101-
Text="{x:Bind Text}"
101+
Text="{x:Bind Text, Mode=OneWay}"
102102
TextWrapping="NoWrap" />
103103
<muxc:ProgressBar Maximum="{x:Bind MaxSpace.GigaBytes, Mode=OneWay}" Value="{x:Bind SpaceUsed.GigaBytes, Mode=OneWay}" />
104104
<TextBlock Text="{x:Bind SpaceText, Mode=OneWay}" ToolTipService.ToolTip="{x:Bind SpaceText, Mode=OneWay}" />

0 commit comments

Comments
 (0)