mirror of
https://github.com/microsoft/PowerToys
synced 2025-09-01 15:05:12 +00:00
[New PowerToy] File Locksmith (#20930)
* Imported offline solution * Make solution compile * Add Windows sample, doesn't work? * Added new project to implement the dll * Remove unneeded header * Implemented IUnknown part of ExplorerCommand * Implemented IExplorerCommand methods * Implemented ClassFactory * Implemented DLL register/unregister * Implemented other DLL exports, not working? * Implemented IShellExtInit inferface * Implemented IContextMenu, it works! * Implement command data fetching * Make sample project compile on VS 2022 * Add plan * Implement Lib as separate project * Implemented IPC, not tested * Console UI project skeleton * Implemented basic console UI * Implemented piping, there are bugs * Prototype works * Remove old project * Added GUI project skeleton * Mitigate issue with WinUI3 * Added a control for displaying results * Add button * Implement core functions in lib project * Call new library function from console main * Implement showing results * Improve UI * Implemented subdirectory search * Remove useless code * Set window size * UI adjustments * Implement killing process * Rename variable * Add lib project to main solution * Add Ext and GUI projects to solution * Tweak packages for GUI project * Add a settings page * Add a few resource strings * Add one more resources string * VS keeps trying to correct this * Add references to File Locksmith in /,github * Implement some parts of FileLocksmithModule * Change output directory * Change target name and add to runner * Add logger * Started implementing settings backend * Fix log folder * Settings work * Add some basic tracing * Attempt at adding resources * Remove junk files * Added missing defines * Replaced some constants with resources Something's not working * Move resources to the Ext project * Remove experiment * Add binaries for signing * Improve tracing * Remove old Settings calls * Show something when there are no results * Change window title * Move computation to another thread, improve UX * Increase font size for default text * Remove entries for killed processes * Show user name * Remove nonrecursive implementation * Implement back end for getting file names * Show list of files, UI tweaks * Remove useless includes * Implement back end for getting full process path * Dark title bar on dark themes * Using Expander, other UI adjustments * Show "No results" after killing all processes * Show progress ring * Update configuration mapping * Revert "Update configuration mapping" This reverts commit d8e13206f3c7de3c6dbf880299bfff3bf9f27a37. * Fixed solution configuration, ARM64 should build * Backend for refreshing * Variable window size * Add refresh button * New WinUI3 C# project for FL * Started porting functionality * Add Interop project * Move IPC to Ext project * Ported native functions to Interop * Ported finding processes * Ported most of Main Window functionality * Display paths of files * Implement killing processes * Use resource string for "End Task" * Remove entries for terminated processes * Show User name * Set default window size * Make the new UI the default * Reading paths from stdin, completed port to C# * Fix small bug * Moving to MVVM * Adding Labs * Merge branch 'ivan/file-locksmith' of https://github.com/microsoft/PowerToys into ivan/file-locksmith Removing one parent commit for cleaner history Co-Authored-By: Niels Laute <niels.laute@live.nl> * Reintroducing features * Moving UI strings to resources file * Restored functionality * Add missing dlls * Add FIle Locksmith to publish.cmd * Rebase fixes * Try updating nuget.config * Fix copy-paste blunder * Add File Locksmith UI for publishing * Add .pubxml file in FileLocksmith * Change build output folder * Fix installer build issues Remove old projects from solution so MSBuild doesn't build them. Downgrade target framework to what most other projects are using. Fix publishing profile and project runtimes. Remove unused CsWinRT references. * [CI] Add clear to nuget packages * Fix module reference counting * Fix nuget for release CI * Fix version and signing * Fix path for resources * Fix incorrect results when running 2 instances * Fix default nuget source * Windows 10 icon and fallback for UI * Code clean-up and spaces instead of tabs * Add gif showcasing FL * Add screenshot of File Locksmith for Settings * Add new files to the installer * Add OOBE page * Showing selected paths in the header * Tweak path list * Added new, wider gif * Add GPO * Add some logs * [CI]Get CommunityToolkit.Labs from BigPark feed * [CI]Use azure package feed for Nuget in release * [CI]Another try for the labs source * Revert changes to feed * Use RestoreAdditionalProjectSources * Add tooltip to file list * Change tooltip to not trim the lines * Add Tips and tricks section mentioning elevated * Add some more logs messages. * Grammar fix * Add to bug report tool * Fix UI virtualization not working * Disable virtualization to avoid crashes * Get better virtualization * Add dialog instead of tooltip to show list of items * No results refresh icon is now a button too * Use managed methods for handling processes * Remove registry code from Ext. * Support drives too Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -52,6 +52,7 @@ body:
|
||||
- ColorPicker
|
||||
- FancyZones
|
||||
- FancyZones Editor
|
||||
- File Locksmith
|
||||
- File Explorer: Preview Pane
|
||||
- File Explorer: Thumbnail preview
|
||||
- Image Resizer
|
||||
|
1
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
1
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
@@ -26,6 +26,7 @@ body:
|
||||
- ColorPicker
|
||||
- FancyZones
|
||||
- FancyZones Editor
|
||||
- File Locksmith
|
||||
- File Explorer: Preview Pane
|
||||
- File Explorer: Thumbnail preview
|
||||
- Image Resizer
|
||||
|
@@ -71,6 +71,11 @@
|
||||
"modules\\Hosts\\PowerToys.Hosts.dll",
|
||||
"modules\\Hosts\\PowerToys.Hosts.exe",
|
||||
|
||||
"modules\\FileLocksmith\\PowerToys.FileLocksmithLib.Interop.dll",
|
||||
"modules\\FileLocksmith\\PowerToys.FileLocksmithExt.dll",
|
||||
"modules\\FileLocksmith\\PowerToys.FileLocksmithUI.exe",
|
||||
"modules\\FileLocksmith\\PowerToys.FileLocksmithUI.dll",
|
||||
|
||||
"modules\\ImageResizer\\PowerToys.ImageResizer.exe",
|
||||
"modules\\ImageResizer\\PowerToys.ImageResizer.dll",
|
||||
"modules\\ImageResizer\\PowerToys.ImageResizerExt.dll",
|
||||
@@ -207,6 +212,7 @@
|
||||
"vcomp140_app.dll",
|
||||
"vcruntime140_1_app.dll",
|
||||
"vcruntime140_app.dll",
|
||||
"modules\\FileLocksmith\\CommunityToolkit.Labs.WinUI.SettingsControls.dll",
|
||||
"modules\\PowerAccent\\Vanara.Core.dll",
|
||||
"modules\\PowerAccent\\Vanara.PInvoke.ComCtl32.dll",
|
||||
"modules\\PowerAccent\\Vanara.PInvoke.Cryptography.dll",
|
||||
|
@@ -295,6 +295,22 @@ jobs:
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Publish File Locksmith UI for Packaging
|
||||
inputs:
|
||||
solution: 'src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj'
|
||||
vsVersion: 17.0
|
||||
# The arguments should be the same as the ones for Settings; make sure they are.
|
||||
msbuildArgs: >-
|
||||
/target:Publish
|
||||
/p:Configuration=$(BuildConfiguration);Platform=$(BuildPlatform);AppxBundle=Never
|
||||
/p:VCRTForwarders-IncludeDebugCRT=false
|
||||
/p:PowerToysRoot=$(Build.SourcesDirectory)
|
||||
/p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Build PowerToysSetupCustomActions DLL # This dll needs to be build and signed before building the MSI.
|
||||
inputs:
|
||||
|
@@ -458,6 +458,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hosts.Tests", "src\modules\
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HostsModuleInterface", "src\modules\Hosts\HostsModuleInterface\HostsModuleInterface.vcxproj", "{B41B888C-7DB8-4747-B262-4062E05A230D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileLocksmith", "FileLocksmith", "{AB82E5DD-C32D-4F28-9746-2C780846188E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithExt", "src\modules\FileLocksmith\FileLocksmithExt\FileLocksmithExt.vcxproj", "{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileLocksmithUI", "src\modules\FileLocksmith\FileLocksmithUI\FileLocksmithUI.csproj", "{E69B044A-2F8A-45AA-AD0B-256C59421807}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLibInterop", "src\modules\FileLocksmith\FileLocksmithLibInterop\FileLocksmithLibInterop.vcxproj", "{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPOWrapper", "src\common\GPOWrapper\GPOWrapper.vcxproj", "{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPOWrapperProjection", "src\common\GPOWrapperProjection\GPOWrapperProjection.csproj", "{00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}"
|
||||
@@ -1547,8 +1555,8 @@ Global
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x64.ActiveCfg = Release|x64
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x64.Build.0 = Release|x64
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.ActiveCfg = Release|x64
|
||||
{04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x86.Build.0 = Release|x64
|
||||
{F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{F44934A8-36F3-49B0-9465-3831BE041CDE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -1853,6 +1861,36 @@ Global
|
||||
{B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x64.Build.0 = Release|x64
|
||||
{B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x86.ActiveCfg = Release|x64
|
||||
{B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x86.Build.0 = Release|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x64.Build.0 = Debug|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|x64.ActiveCfg = Release|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|x64.Build.0 = Release|x64
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|x86.ActiveCfg = Release|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|ARM64.ActiveCfg = Debug|arm64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|ARM64.Build.0 = Debug|arm64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|x64.Build.0 = Debug|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|ARM64.ActiveCfg = Release|arm64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|ARM64.Build.0 = Release|arm64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|x64.ActiveCfg = Release|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|x64.Build.0 = Release|x64
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|x86.ActiveCfg = Release|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|x64.Build.0 = Debug|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|x64.ActiveCfg = Release|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|x64.Build.0 = Release|x64
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|x86.ActiveCfg = Release|x64
|
||||
{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2033,6 +2071,10 @@ Global
|
||||
{F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
||||
{B41B888C-7DB8-4747-B262-4062E05A230D} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
||||
{AB82E5DD-C32D-4F28-9746-2C780846188E} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
|
||||
{E69B044A-2F8A-45AA-AD0B-256C59421807} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
|
||||
{C604B37E-9D0E-4484-8778-E8B31B0E1B3A} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
|
||||
{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{00EE9BA6-4E8F-43CA-960D-D4882F0FBB97} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
EndGlobalSection
|
||||
|
@@ -57,6 +57,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFileLocksmith" class="Both" displayName="$(string.ConfigureEnabledUtilityFileLocksmith)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFileLocksmith">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFileExplorerSVGPreview" class="Both" displayName="$(string.ConfigureEnabledUtilityFileExplorerSVGPreview)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFileExplorerSVGPreview">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
|
@@ -32,6 +32,7 @@ If you don't configure this setting, users are able to disable or enable the uti
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityColorPicker">Color Picker: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileLocksmith">File Locksmith: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerSVGPreview">SVG file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerMarkdownPreview">Markdown file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerMonacoPreview">Source code file preview: Configure enabled state</string>
|
||||
|
@@ -8,6 +8,7 @@
|
||||
<?define KeyboardManagerProjectName="KeyboardManager"?>
|
||||
<?define PowerAccentProjectName="PowerAccent"?>
|
||||
<?define PowerRenameProjectName="PowerRename"?>
|
||||
<?define FileLocksmithProjectName="FileLocksmith"?>
|
||||
<?define ColorPickerProjectName="ColorPicker"?>
|
||||
<?define PowerOCRProjectName="PowerOCR"?>
|
||||
<?define VideoConferenceProjectName="VideoConference"?>
|
||||
@@ -52,11 +53,11 @@
|
||||
|
||||
<?define SettingsV2Files=backup_restore_settings.json;Ijwhost.dll;ColorCode.Core.dll;ColorCode.WinUI.dll;CommunityToolkit.Common.dll;CommunityToolkit.WinUI.dll;CommunityToolkit.WinUI.UI.Controls.Core.dll;CommunityToolkit.WinUI.UI.Controls.DataGrid.dll;CommunityToolkit.WinUI.UI.Controls.Input.dll;CommunityToolkit.WinUI.UI.Controls.Layout.dll;CommunityToolkit.WinUI.UI.Controls.Markdown.dll;CommunityToolkit.WinUI.UI.Controls.Media.dll;CommunityToolkit.WinUI.UI.Controls.Primitives.dll;CommunityToolkit.WinUI.UI.dll;icon.ico;Microsoft.Graphics.Canvas.Interop.dll;Microsoft.InteractiveExperiences.Projection.dll;Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll;Microsoft.Windows.ApplicationModel.Resources.Projection.dll;Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll;Microsoft.Windows.AppLifecycle.Projection.dll;Microsoft.Windows.SDK.NET.dll;Microsoft.Windows.System.Power.Projection.dll;Microsoft.WindowsAppRuntime.Bootstrap.Net.dll;Microsoft.WinUI.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.Settings.deps.json;PowerToys.Settings.dll;PowerToys.Settings.exe;PowerToys.Settings.runtimeconfig.json;PowerToys.Settings.UI.Lib.dll;resources.pri;System.CodeDom.dll;System.IO.Abstractions.dll;System.Text.Json.dll;WinRT.Runtime.dll;Microsoft.Graphics.Canvas.dll;System.Management.dll;PowerToys.GPOWrapper.dll?>
|
||||
|
||||
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerAccent.png;PowerOCR.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ScreenRuler.png;ShortcutGuide.png;VideoConference.png?>
|
||||
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerAccent.png;PowerOCR.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ScreenRuler.png;ShortcutGuide.png;VideoConference.png?>
|
||||
|
||||
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;FancyZones.gif;FileExplorer.png;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;ScreenRuler.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
|
||||
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;FancyZones.gif;FileExplorer.png;FileLocksmith.gif;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;ScreenRuler.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
|
||||
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;Hosts.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;Hosts.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
|
||||
|
||||
<?define SettingsV2MicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
|
||||
|
||||
@@ -116,6 +117,8 @@
|
||||
|
||||
<?define PowerRenameFiles=PowerRenameUI.ico;PowerToys.PowerRename.exe;resources.pri;PowerToys.PowerRenameExt.dll;PowerRenameContextMenuPackage.msix;PowerToys.PowerRenameContextMenu.dll?>
|
||||
|
||||
<?define FileLocksmithFiles=icon.ico;Microsoft.Win32.SystemEvents.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;CommunityToolkit.WinUI.dll;CommunityToolkit.WinUI.UI.dll;CommunityToolkit.Common.dll;CommunityToolkit.Mvvm.dll;CommunityToolkit.Labs.WinUI.SettingsControls.dll;Ijwhost.dll;Microsoft.InteractiveExperiences.Projection.dll;Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll;Microsoft.Windows.ApplicationModel.Resources.Projection.dll;Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll;Microsoft.Windows.AppLifecycle.Projection.dll;Microsoft.Windows.SDK.NET.dll;Microsoft.Windows.System.Power.Projection.dll;Microsoft.WindowsAppRuntime.Bootstrap.Net.dll;Microsoft.WinUI.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.FileLocksmithExt.dll;PowerToys.FileLocksmithLib.Interop.dll;PowerToys.FileLocksmithUI.exe;PowerToys.FileLocksmithUI.dll;PowerToys.FileLocksmithUI.deps.json;PowerToys.FileLocksmithUI.runtimeconfig.json;System.CodeDom.dll;System.Drawing.Common.dll;System.Management.dll;WinRT.Runtime.dll;WinUIEx.dll;resources.pri;PowerToys.GPOWrapper.dll?>
|
||||
|
||||
<?define PowerRenameSparsePackageAssets=LargeTile.png;SmallTile.png;SplashScreen.png;Square150x150Logo.png;Square44x44Logo.png;storelogo.png;Wide310x150Logo.png?>
|
||||
|
||||
<?define ImageResizerSparsePackageAssets=LargeTile.png;SmallTile.png;SplashScreen.png;Square150x150Logo.png;Square44x44Logo.png;storelogo.png;Wide310x150Logo.png?>
|
||||
@@ -498,6 +501,8 @@
|
||||
</Directory>
|
||||
<Directory Id="PowerAccentInstallFolder" Name="$(var.PowerAccentProjectName)">
|
||||
</Directory>
|
||||
<Directory Id="FileLocksmithInstallFolder" Name="$(var.FileLocksmithProjectName)">
|
||||
</Directory>
|
||||
<Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)">
|
||||
<Directory Id="PowerRenameAssetsFolder" Name="Assets" />
|
||||
<Directory Id="PowerRenameMicrosoftUIXamlInstallFolder" Name="Microsoft.UI.Xaml">
|
||||
@@ -877,6 +882,30 @@
|
||||
<?endforeach?>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- FileLocksmith -->
|
||||
<DirectoryRef Id="FileLocksmithInstallFolder" FileSource="$(var.BinDir)modules\$(var.FileLocksmithProjectName)">
|
||||
<?foreach File in $(var.FileLocksmithFiles)?>
|
||||
<Component Id="FileLocksmith_$(var.File)" Win64="yes">
|
||||
<File Id="FileLocksmithFile_$(var.File)" Source="$(var.BinDir)modules\$(var.FileLocksmithProjectName)\$(var.File)" />
|
||||
</Component>
|
||||
<?endforeach?>
|
||||
<!-- !Warning! Make sure to change Component Guid if you update something here -->
|
||||
<Component Id="Module_FileLocksmith" Guid="108D3EC1-E6E0-4E81-88EF-25966133CB41" Win64="yes">
|
||||
<RegistryKey Root="HKLM" Key="Software\Classes\CLSID\{84D68575-E186-46AD-B0CB-BAEB45EE29C0}">
|
||||
<RegistryValue Type="string" Value="File Locksmith Shell Extension" />
|
||||
<RegistryValue Type="string" Name="ContextMenuOptIn" Value="" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Value="[FileLocksmithInstallFolder]PowerToys.FileLocksmithExt.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Apartment" />
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="HKLM" Key="Software\Classes\AllFileSystemObjects\ShellEx\ContextMenuHandlers\FileLocksmithExt">
|
||||
<RegistryValue Type="string" Value="{84D68575-E186-46AD-B0CB-BAEB45EE29C0}"/>
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="HKLM" Key="Software\Classes\Drive\ShellEx\ContextMenuHandlers\FileLocksmithExt">
|
||||
<RegistryValue Type="string" Value="{84D68575-E186-46AD-B0CB-BAEB45EE29C0}"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- PowerRename -->
|
||||
<DirectoryRef Id="PowerRenameInstallFolder" FileSource="$(var.BinDir)modules\$(var.PowerRenameProjectName)">
|
||||
<?foreach File in $(var.PowerRenameFiles)?>
|
||||
@@ -1241,6 +1270,10 @@
|
||||
<?endforeach?>
|
||||
<ComponentRef Id="DesktopShortcut" />
|
||||
<ComponentRef Id="Module_PowerRename" />
|
||||
<ComponentRef Id="Module_FileLocksmith" />
|
||||
<?foreach File in $(var.FileLocksmithFiles)?>
|
||||
<ComponentRef Id="FileLocksmith_$(var.File)" />
|
||||
<?endforeach?>
|
||||
<?foreach File in $(var.PowerAccentFiles)?>
|
||||
<ComponentRef Id="PowerAccent_$(var.File)" />
|
||||
<?endforeach?>
|
||||
@@ -1649,7 +1682,7 @@
|
||||
<!-- Localization languages shipped with WinAppSDK. We should ship these as well. -->
|
||||
<?define WinAppSDKLocLanguageList = af-ZA;ar-SA;az-Latn-AZ;bg-BG;bs-Latn-BA;ca-ES;cs-CZ;cy-GB;da-DK;de-DE;el-GR;en-GB;en-us;es-ES;es-MX;et-EE;eu-ES;fa-IR;fi-FI;fr-CA;fr-FR;gl-ES;he-IL;hi-IN;hr-HR;hu-HU;id-ID;is-IS;it-IT;ja-JP;ka-GE;kk-KZ;ko-KR;lt-LT;lv-LV;ms-MY;nb-NO;nl-NL;nn-NO;pl-PL;pt-BR;pt-PT;ro-RO;ru-RU;sk-SK;sl-SI;sq-AL;sr-Cyrl-RS;sr-Latn-RS;sv-SE;th-TH;tr-TR;uk-UA;vi-VN;zh-CN;zh-TW?>
|
||||
<Fragment>
|
||||
<?foreach ParentDirectory in SettingsV2InstallFolder;PowerRenameInstallFolder;MeasureToolInstallFolder;HostsInstallFolder?>
|
||||
<?foreach ParentDirectory in SettingsV2InstallFolder;PowerRenameInstallFolder;MeasureToolInstallFolder;HostsInstallFolder;FileLocksmithInstallFolder?>
|
||||
<DirectoryRef Id="$(var.ParentDirectory)">
|
||||
<?foreach Language in $(var.WinAppSDKLocLanguageList)?>
|
||||
<?if $(var.Language) = af-ZA?>
|
||||
@@ -1975,6 +2008,13 @@
|
||||
<File Id="Hosts_WinAppSDKLoc_$(var.IdSafeLanguage)_XamlMui_File" Source="$(var.BinDir)modules\$(var.HostsProjectName)\$(var.Language)\Microsoft.ui.xaml.dll.mui" />
|
||||
<File Id="Hosts_WinAppSDKLoc_$(var.IdSafeLanguage)_XamlPhoneMui_File" Source="$(var.BinDir)modules\$(var.HostsProjectName)\$(var.Language)\Microsoft.UI.Xaml.Phone.dll.mui" />
|
||||
</Component>
|
||||
<Component
|
||||
Id="FileLocksmith_WinAppSDKLoc_$(var.IdSafeLanguage)_Component"
|
||||
Directory="WinAppSDKLoc$(var.IdSafeLanguage)FileLocksmithInstallFolder"
|
||||
Guid="$(var.CompGUIDPrefix)05">
|
||||
<File Id="FileLocksmith_WinAppSDKLoc_$(var.IdSafeLanguage)_XamlMui_File" Source="$(var.BinDir)modules\$(var.FileLocksmithProjectName)\$(var.Language)\Microsoft.ui.xaml.dll.mui" />
|
||||
<File Id="FileLocksmith_WinAppSDKLoc_$(var.IdSafeLanguage)_XamlPhoneMui_File" Source="$(var.BinDir)modules\$(var.FileLocksmithProjectName)\$(var.Language)\Microsoft.UI.Xaml.Phone.dll.mui" />
|
||||
</Component>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?undef CompGUIDPrefix?>
|
||||
<?endforeach?>
|
||||
|
@@ -20,3 +20,5 @@ msbuild !PTRoot!\src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csp
|
||||
msbuild !PTRoot!\src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
|
||||
msbuild !PTRoot!\src\modules\MeasureTool\MeasureToolUI\MeasureToolUI.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
|
||||
msbuild !PTRoot!\src\modules\FileLocksmith\FileLocksmithUI\FileLocksmithUI.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
|
@@ -1045,11 +1045,20 @@ UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
const std::wstring WinAppSDKConsumers[] =
|
||||
{
|
||||
L"Settings",
|
||||
L"modules\\PowerRename",
|
||||
L"modules\\MeasureTool",
|
||||
L"modules\\FileLocksmith",
|
||||
L"modules\\Hosts",
|
||||
};
|
||||
|
||||
UINT __stdcall CreateWinAppSDKHardlinksCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder, winAppSDKFilesSrcDir, settingsDir, powerRenameDir, measureToolDir, hostsFileEditorDir;
|
||||
std::wstring installationFolder, winAppSDKFilesSrcDir;
|
||||
|
||||
hr = WcaInitialize(hInstall, "CreateWinAppSDKHardlinksCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
@@ -1058,18 +1067,13 @@ UINT __stdcall CreateWinAppSDKHardlinksCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Failed to get installation folder");
|
||||
|
||||
winAppSDKFilesSrcDir = installationFolder + L"dll\\WinAppSDK\\";
|
||||
hostsFileEditorDir = installationFolder + L"modules\\Hosts\\";
|
||||
settingsDir = installationFolder + L"Settings\\";
|
||||
powerRenameDir = installationFolder + L"modules\\PowerRename\\";
|
||||
measureToolDir = installationFolder + L"modules\\MeasureTool\\";
|
||||
|
||||
for (auto file : winAppSdkFiles)
|
||||
{
|
||||
for (auto consumer : WinAppSDKConsumers)
|
||||
{
|
||||
std::error_code ec;
|
||||
std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (hostsFileEditorDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (settingsDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (powerRenameDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (measureToolDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (installationFolder + consumer + L"\\" + file).c_str(), ec);
|
||||
|
||||
if (ec.value() != S_OK)
|
||||
{
|
||||
@@ -1079,18 +1083,33 @@ UINT __stdcall CreateWinAppSDKHardlinksCA(MSIHANDLE hInstall)
|
||||
Logger::error(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
const std::wstring PTInteropConsumers[] =
|
||||
{
|
||||
L"modules\\ColorPicker",
|
||||
L"modules\\PowerOCR",
|
||||
L"modules\\launcher",
|
||||
L"modules\\FancyZones",
|
||||
L"modules\\ImageResizer",
|
||||
L"Settings",
|
||||
L"modules\\Awake",
|
||||
L"modules\\MeasureTool",
|
||||
L"modules\\PowerAccent",
|
||||
L"modules\\FileLocksmith",
|
||||
L"modules\\Hosts",
|
||||
};
|
||||
|
||||
UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder, interopFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
|
||||
imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, hostsFileEditorDir;
|
||||
std::wstring installationFolder, interopFilesSrcDir;
|
||||
|
||||
hr = WcaInitialize(hInstall, "CreatePTInteropHardlinksCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
@@ -1099,30 +1118,13 @@ UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Failed to get installation folder");
|
||||
|
||||
interopFilesSrcDir = installationFolder + L"dll\\Interop\\";
|
||||
colorPickerDir = installationFolder + L"modules\\ColorPicker\\";
|
||||
powerOCRDir = installationFolder + L"modules\\PowerOCR\\";
|
||||
launcherDir = installationFolder + L"modules\\launcher\\";
|
||||
fancyZonesDir = installationFolder + L"modules\\FancyZones\\";
|
||||
hostsFileEditorDir = installationFolder + L"modules\\Hosts\\";
|
||||
imageResizerDir = installationFolder + L"modules\\ImageResizer\\";
|
||||
settingsDir = installationFolder + L"Settings\\";
|
||||
awakeDir = installationFolder + L"modules\\Awake\\";
|
||||
measureToolDir = installationFolder + L"modules\\MeasureTool\\";
|
||||
powerAccentDir = installationFolder + L"modules\\PowerAccent\\";
|
||||
|
||||
for (auto file : powerToysInteropFiles)
|
||||
{
|
||||
for (auto consumer : PTInteropConsumers)
|
||||
{
|
||||
std::error_code ec;
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (colorPickerDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (powerOCRDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (launcherDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (fancyZonesDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (hostsFileEditorDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (imageResizerDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (settingsDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (awakeDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (measureToolDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (powerAccentDir + file).c_str(), ec);
|
||||
std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (installationFolder + consumer + L"\\" + file).c_str(), ec);
|
||||
|
||||
if (ec.value() != S_OK)
|
||||
{
|
||||
@@ -1132,6 +1134,7 @@ UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
|
||||
Logger::error(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
@@ -1142,7 +1145,7 @@ UINT __stdcall DeleteWinAppSDKHardlinksCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder, settingsDir, powerRenameDir, measureToolDir, hostsFileEditorDir;
|
||||
std::wstring installationFolder;
|
||||
|
||||
hr = WcaInitialize(hInstall, "DeleteWinAppSDKHardlinksCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
@@ -1150,19 +1153,14 @@ UINT __stdcall DeleteWinAppSDKHardlinksCA(MSIHANDLE hInstall)
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installation folder");
|
||||
|
||||
hostsFileEditorDir = installationFolder + L"modules\\Hosts\\";
|
||||
settingsDir = installationFolder + L"Settings\\";
|
||||
powerRenameDir = installationFolder + L"modules\\PowerRename\\";
|
||||
measureToolDir = installationFolder + L"modules\\MeasureTool\\";
|
||||
|
||||
try
|
||||
{
|
||||
for (auto file : winAppSdkFiles)
|
||||
{
|
||||
DeleteFile((hostsFileEditorDir + file).c_str());
|
||||
DeleteFile((settingsDir + file).c_str());
|
||||
DeleteFile((powerRenameDir + file).c_str());
|
||||
DeleteFile((measureToolDir + file).c_str());
|
||||
for (auto consumer : WinAppSDKConsumers)
|
||||
{
|
||||
DeleteFile((installationFolder + consumer + L"\\" + file).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception e)
|
||||
@@ -1183,8 +1181,7 @@ UINT __stdcall DeletePTInteropHardlinksCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder, interopFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
|
||||
imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, hostsFileEditorDir;
|
||||
std::wstring installationFolder, interopFilesSrcDir;
|
||||
|
||||
hr = WcaInitialize(hInstall, "DeletePTInteropHardlinksCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
@@ -1192,31 +1189,14 @@ UINT __stdcall DeletePTInteropHardlinksCA(MSIHANDLE hInstall)
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installation folder");
|
||||
|
||||
colorPickerDir = installationFolder + L"modules\\ColorPicker\\";
|
||||
powerOCRDir = installationFolder + L"modules\\PowerOCR\\";
|
||||
launcherDir = installationFolder + L"modules\\launcher\\";
|
||||
fancyZonesDir = installationFolder + L"modules\\FancyZones\\";
|
||||
hostsFileEditorDir = installationFolder + L"modules\\Hosts\\";
|
||||
imageResizerDir = installationFolder + L"modules\\ImageResizer\\";
|
||||
settingsDir = installationFolder + L"Settings\\";
|
||||
awakeDir = installationFolder + L"modules\\Awake\\";
|
||||
measureToolDir = installationFolder + L"modules\\MeasureTool\\";
|
||||
powerAccentDir = installationFolder + L"modules\\PowerAccent\\";
|
||||
|
||||
try
|
||||
{
|
||||
for (auto file : powerToysInteropFiles)
|
||||
{
|
||||
DeleteFile((colorPickerDir + file).c_str());
|
||||
DeleteFile((powerOCRDir + file).c_str());
|
||||
DeleteFile((launcherDir + file).c_str());
|
||||
DeleteFile((fancyZonesDir + file).c_str());
|
||||
DeleteFile((hostsFileEditorDir + file).c_str());
|
||||
DeleteFile((imageResizerDir + file).c_str());
|
||||
DeleteFile((settingsDir + file).c_str());
|
||||
DeleteFile((awakeDir + file).c_str());
|
||||
DeleteFile((measureToolDir + file).c_str());
|
||||
DeleteFile((powerAccentDir + file).c_str());
|
||||
for (auto consumer : PTInteropConsumers)
|
||||
{
|
||||
DeleteFile((installationFolder + consumer + L"\\" + file).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception e)
|
||||
@@ -1256,6 +1236,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.Awake.exe",
|
||||
L"PowerToys.FancyZones.exe",
|
||||
L"PowerToys.FancyZonesEditor.exe",
|
||||
L"PowerToys.FileLocksmithUI.exe",
|
||||
L"PowerToys.ColorPickerUI.exe",
|
||||
L"PowerToys.AlwaysOnTop.exe",
|
||||
L"PowerToys.exe"
|
||||
|
@@ -1,5 +0,0 @@
|
||||
<configuration>
|
||||
<config>
|
||||
<clear />
|
||||
</config>
|
||||
</configuration>
|
@@ -20,6 +20,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return (GpoRuleConfigured)powertoys_gpo::getConfiguredFancyZonesEnabledValue();
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredFileLocksmithEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)powertoys_gpo::getConfiguredFileLocksmithEnabledValue();
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredSvgPreviewEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)powertoys_gpo::getConfiguredSvgPreviewEnabledValue();
|
||||
|
@@ -11,6 +11,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFileLocksmithEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredSvgPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMarkdownPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMonacoPreviewEnabledValue();
|
||||
|
@@ -15,6 +15,7 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFileLocksmithEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredSvgPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMarkdownPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMonacoPreviewEnabledValue();
|
||||
|
@@ -34,6 +34,7 @@ struct LogSettings
|
||||
inline const static std::string powerRenameLoggerName = "powerrename";
|
||||
inline const static std::string alwaysOnTopLoggerName = "always-on-top";
|
||||
inline const static std::string powerOcrLoggerName = "TextExtractor";
|
||||
inline const static std::string fileLocksmithLoggerName = "FileLocksmith";
|
||||
inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.txt";
|
||||
inline const static std::string hostsLoggerName = "hosts";
|
||||
inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.txt";
|
||||
|
@@ -23,6 +23,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_AWAKE = L"ConfigureEnabledUtilityAwake";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_COLOR_PICKER = L"ConfigureEnabledUtilityColorPicker";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_FANCYZONES = L"ConfigureEnabledUtilityFancyZones";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_FILE_LOCKSMITH = L"ConfigureEnabledUtilityFileLocksmith";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SVG_PREVIEW = L"ConfigureEnabledUtilityFileExplorerSVGPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MARKDOWN_PREVIEW = L"ConfigureEnabledUtilityFileExplorerMarkdownPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MONACO_PREVIEW = L"ConfigureEnabledUtilityFileExplorerMonacoPreview";
|
||||
@@ -119,6 +120,11 @@ namespace powertoys_gpo {
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_FANCYZONES);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredFileLocksmithEnabledValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_FILE_LOCKSMITH);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredSvgPreviewEnabledValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_SVG_PREVIEW);
|
||||
|
80
src/modules/FileLocksmith/FileLocksmithExt/ClassFactory.cpp
Normal file
80
src/modules/FileLocksmith/FileLocksmithExt/ClassFactory.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "ClassFactory.h"
|
||||
#include "ExplorerCommand.h"
|
||||
#include "dllmain.h"
|
||||
|
||||
// Class ctor/dtors
|
||||
|
||||
ClassFactory::ClassFactory(_In_ REFCLSID clsid) :
|
||||
m_ref_count(1),
|
||||
m_clsid(clsid)
|
||||
{
|
||||
++globals::ref_count;
|
||||
}
|
||||
|
||||
ClassFactory::~ClassFactory()
|
||||
{
|
||||
--globals::ref_count;
|
||||
}
|
||||
|
||||
// Implementations of inherited IUnknown methods
|
||||
|
||||
IFACEMETHODIMP ClassFactory::QueryInterface(REFIID riid, void** ppv)
|
||||
{
|
||||
static const QITAB qit[] = {
|
||||
QITABENT(ClassFactory, IClassFactory),
|
||||
{ 0, 0 },
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ClassFactory::AddRef()
|
||||
{
|
||||
return ++m_ref_count;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ClassFactory::Release()
|
||||
{
|
||||
auto result = --m_ref_count;
|
||||
if (result == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implementations of inherited IClassFactory methods
|
||||
|
||||
IFACEMETHODIMP ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
|
||||
{
|
||||
*ppvObject = NULL;
|
||||
HRESULT hr;
|
||||
if (pUnkOuter)
|
||||
{
|
||||
hr = CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
else if (m_clsid == __uuidof(ExplorerCommand))
|
||||
{
|
||||
hr = ExplorerCommand::s_CreateInstance(pUnkOuter, riid, ppvObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ClassFactory::LockServer(BOOL fLock)
|
||||
{
|
||||
if (fLock)
|
||||
{
|
||||
++globals::ref_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
--globals::ref_count;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
22
src/modules/FileLocksmith/FileLocksmithExt/ClassFactory.h
Normal file
22
src/modules/FileLocksmith/FileLocksmithExt/ClassFactory.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
class ClassFactory : public IClassFactory
|
||||
{
|
||||
public:
|
||||
ClassFactory(_In_ REFCLSID clsid);
|
||||
~ClassFactory();
|
||||
|
||||
// IUnknown
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
|
||||
IFACEMETHODIMP_(ULONG) AddRef() override;
|
||||
IFACEMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IClassFactory
|
||||
IFACEMETHODIMP CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject) override;
|
||||
IFACEMETHODIMP LockServer(BOOL fLock) override;
|
||||
private:
|
||||
std::atomic<ULONG> m_ref_count;
|
||||
IID m_clsid;
|
||||
};
|
33
src/modules/FileLocksmith/FileLocksmithExt/Constants.h
Normal file
33
src/modules/FileLocksmith/FileLocksmithExt/Constants.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// Non-localizable constants
|
||||
namespace constants::nonlocalizable
|
||||
{
|
||||
// Description of the registry key
|
||||
constexpr WCHAR RegistryKeyDescription[] = L"File Locksmith Shell Extension";
|
||||
|
||||
// File name of the UI executable
|
||||
constexpr WCHAR FileNameUIExe[] = L"PowerToys.FileLocksmithUI.exe";
|
||||
|
||||
// String key used by PowerToys
|
||||
constexpr WCHAR PowerToyKey[] = L"File Locksmith";
|
||||
|
||||
// Nonlocalized name of this PowerToy, for logs, etc
|
||||
constexpr WCHAR PowerToyName[] = L"File Locksmith";
|
||||
|
||||
// JSON key used to store whether the module is enabled
|
||||
constexpr WCHAR JsonKeyEnabled[] = L"Enabled";
|
||||
|
||||
// Path of the JSON file used to store settings
|
||||
constexpr WCHAR DataFilePath[] = L"\\file-locksmith-settings.json";
|
||||
|
||||
// Name of the file where the list of files to checked will be stored
|
||||
constexpr WCHAR LastRunPath[] = L"\\last-run.log";
|
||||
}
|
||||
|
||||
// Macros, non-localizable
|
||||
|
||||
// Description of the registry key
|
||||
#define REGISTRY_CONTEXT_MENU_KEY L"FileLocksmithExt"
|
296
src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
Normal file
296
src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "ExplorerCommand.h"
|
||||
#include "Constants.h"
|
||||
#include "Settings.h"
|
||||
#include "dllmain.h"
|
||||
#include "Trace.h"
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
// Implementations of inherited IUnknown methods
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::QueryInterface(REFIID riid, void** ppv)
|
||||
{
|
||||
static const QITAB qit[] = {
|
||||
QITABENT(ExplorerCommand, IExplorerCommand),
|
||||
QITABENT(ExplorerCommand, IShellExtInit),
|
||||
QITABENT(ExplorerCommand, IContextMenu),
|
||||
{ 0, 0 },
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ExplorerCommand::AddRef()
|
||||
{
|
||||
return ++m_ref_count;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ExplorerCommand::Release()
|
||||
{
|
||||
auto result = --m_ref_count;
|
||||
if (result == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implementations of inherited IExplorerCommand methods
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetTitle(IShellItemArray* psiItemArray, LPWSTR* ppszName)
|
||||
{
|
||||
WCHAR buffer[128];
|
||||
LoadStringW(globals::instance, IDS_FILELOCKSMITH_COMMANDTITLE, buffer, ARRAYSIZE(buffer));
|
||||
return SHStrDupW(buffer, ppszName);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon)
|
||||
{
|
||||
// Path to the icon should be computed relative to the path of this module
|
||||
ppszIcon = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetToolTip(IShellItemArray* psiItemArray, LPWSTR* ppszInfotip)
|
||||
{
|
||||
// No tooltip for now
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetCanonicalName(GUID* pguidCommandName)
|
||||
{
|
||||
*pguidCommandName = __uuidof(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState)
|
||||
{
|
||||
if (globals::enabled)
|
||||
{
|
||||
*pCmdState = ECS_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pCmdState = ECS_HIDDEN;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::Invoke(IShellItemArray* psiItemArray, IBindCtx* pbc)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetFlags(EXPCMDFLAGS* pFlags)
|
||||
{
|
||||
*pFlags = ECF_DEFAULT;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::EnumSubCommands(IEnumExplorerCommand** ppEnum)
|
||||
{
|
||||
*ppEnum = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// Implementations of inherited IShellExtInit methods
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID)
|
||||
{
|
||||
m_data_obj = pdtobj;
|
||||
m_data_obj->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Implementations of inherited IContextMenu methods
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
|
||||
{
|
||||
// Skip if disabled
|
||||
if (!FileLocksmithSettingsInstance().GetEnabled())
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = E_UNEXPECTED;
|
||||
if (m_data_obj && !(uFlags & (CMF_DEFAULTONLY | CMF_VERBSONLY | CMF_OPTIMIZEFORINVOKE)))
|
||||
{
|
||||
MENUITEMINFO mii;
|
||||
mii.cbSize = sizeof(MENUITEMINFO);
|
||||
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
|
||||
mii.wID = idCmdFirst++;
|
||||
mii.fType = MFT_STRING;
|
||||
|
||||
hr = GetTitle(NULL, &mii.dwTypeData);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
mii.fState = MFS_ENABLED;
|
||||
|
||||
// TODO icon from file
|
||||
|
||||
if (!InsertMenuItem(hmenu, indexMenu, TRUE, &mii))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
Trace::QueryContextMenuError(hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::InvokeCommand(CMINVOKECOMMANDINFO* pici)
|
||||
{
|
||||
Trace::Invoked();
|
||||
ipc::Writer writer;
|
||||
|
||||
if (HRESULT result = writer.start(); FAILED(result))
|
||||
{
|
||||
Trace::InvokedRet(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (HRESULT result = LaunchUI(pici, &writer); FAILED(result))
|
||||
{
|
||||
Trace::InvokedRet(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
IShellItemArray* shell_item_array;
|
||||
HRESULT result = SHCreateShellItemArrayFromDataObject(m_data_obj, __uuidof(IShellItemArray), reinterpret_cast<void**>(&shell_item_array));
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
DWORD num_items;
|
||||
shell_item_array->GetCount(&num_items);
|
||||
for (DWORD i = 0; i < num_items; i++)
|
||||
{
|
||||
IShellItem* item;
|
||||
result = shell_item_array->GetItemAt(i, &item);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
LPWSTR file_path;
|
||||
result = item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
// TODO Aggregate items and send to UI
|
||||
writer.add_path(file_path);
|
||||
CoTaskMemFree(file_path);
|
||||
}
|
||||
|
||||
item->Release();
|
||||
}
|
||||
}
|
||||
|
||||
shell_item_array->Release();
|
||||
}
|
||||
|
||||
Trace::InvokedRet(S_OK);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ExplorerCommand::s_CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
|
||||
{
|
||||
*ppvObject = NULL;
|
||||
HRESULT hr = E_OUTOFMEMORY;
|
||||
ExplorerCommand* pNew = new (std::nothrow) ExplorerCommand;
|
||||
if (pNew)
|
||||
{
|
||||
hr = pNew->QueryInterface(riid, ppvObject);
|
||||
pNew->Release();
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
ExplorerCommand::ExplorerCommand()
|
||||
{
|
||||
++globals::ref_count;
|
||||
}
|
||||
|
||||
ExplorerCommand::~ExplorerCommand()
|
||||
{
|
||||
if (m_data_obj)
|
||||
{
|
||||
m_data_obj->Release();
|
||||
}
|
||||
--globals::ref_count;
|
||||
}
|
||||
|
||||
// Implementation taken from src/common/utils
|
||||
// TODO reference that function
|
||||
inline std::wstring get_module_folderpath(HMODULE mod = nullptr, const bool removeFilename = true)
|
||||
{
|
||||
wchar_t buffer[MAX_PATH + 1];
|
||||
DWORD actual_length = GetModuleFileNameW(mod, buffer, MAX_PATH + 1);
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
const DWORD long_path_length = 0xFFFF; // should be always enough
|
||||
std::wstring long_filename(long_path_length, L'\0');
|
||||
actual_length = GetModuleFileNameW(mod, long_filename.data(), long_path_length);
|
||||
PathRemoveFileSpecW(long_filename.data());
|
||||
long_filename.resize(std::wcslen(long_filename.data()));
|
||||
long_filename.shrink_to_fit();
|
||||
return long_filename;
|
||||
}
|
||||
|
||||
if (removeFilename)
|
||||
{
|
||||
PathRemoveFileSpecW(buffer);
|
||||
}
|
||||
return { buffer, (UINT)lstrlenW(buffer) };
|
||||
}
|
||||
|
||||
HRESULT ExplorerCommand::LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer)
|
||||
{
|
||||
// Compute exe path
|
||||
std::wstring exe_path = get_module_folderpath(globals::instance);
|
||||
exe_path += L'\\';
|
||||
exe_path += constants::nonlocalizable::FileNameUIExe;
|
||||
|
||||
STARTUPINFO startupInfo;
|
||||
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
|
||||
startupInfo.cb = sizeof(STARTUPINFO);
|
||||
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
|
||||
|
||||
if (pici)
|
||||
{
|
||||
startupInfo.wShowWindow = pici->nShow;
|
||||
}
|
||||
else
|
||||
{
|
||||
startupInfo.wShowWindow = SW_SHOWNORMAL;
|
||||
}
|
||||
|
||||
PROCESS_INFORMATION processInformation;
|
||||
std::wstring command_line = L"\"";
|
||||
command_line += exe_path;
|
||||
command_line += L"\"\0";
|
||||
|
||||
CreateProcessW(
|
||||
NULL,
|
||||
command_line.data(),
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&startupInfo,
|
||||
&processInformation);
|
||||
|
||||
// Discard handles
|
||||
CloseHandle(processInformation.hProcess);
|
||||
CloseHandle(processInformation.hThread);
|
||||
|
||||
return S_OK;
|
||||
}
|
50
src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
Normal file
50
src/modules/FileLocksmith/FileLocksmithExt/ExplorerCommand.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "IPC.h"
|
||||
|
||||
#define EXPLORER_COMMAND_UUID_STR "84d68575-e186-46ad-b0cb-baeb45ee29c0"
|
||||
|
||||
class __declspec(uuid(EXPLORER_COMMAND_UUID_STR)) ExplorerCommand : public IExplorerCommand, public IShellExtInit, public IContextMenu
|
||||
{
|
||||
public:
|
||||
// IUnknown
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
|
||||
IFACEMETHODIMP_(ULONG) AddRef() override;
|
||||
IFACEMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
// IExplorerCommand
|
||||
IFACEMETHODIMP GetTitle(IShellItemArray* psiItemArray, LPWSTR* ppszName) override;
|
||||
IFACEMETHODIMP GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon) override;
|
||||
IFACEMETHODIMP GetToolTip(IShellItemArray* psiItemArray, LPWSTR* ppszInfotip) override;
|
||||
IFACEMETHODIMP GetCanonicalName(GUID* pguidCommandName) override;
|
||||
IFACEMETHODIMP GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState) override;
|
||||
IFACEMETHODIMP Invoke(IShellItemArray* psiItemArray, IBindCtx* pbc) override;
|
||||
IFACEMETHODIMP GetFlags(EXPCMDFLAGS* pFlags) override;
|
||||
IFACEMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum) override;
|
||||
|
||||
// IShellExtInit
|
||||
IFACEMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) override;
|
||||
|
||||
// IContextMenu
|
||||
IFACEMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override;
|
||||
IFACEMETHODIMP InvokeCommand(CMINVOKECOMMANDINFO* pici) override;
|
||||
IFACEMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, CHAR* pszName, UINT cchMax) override;
|
||||
|
||||
// Static member to create an instance
|
||||
static HRESULT s_CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject);
|
||||
|
||||
// Constructor
|
||||
ExplorerCommand();
|
||||
|
||||
// Destructor
|
||||
~ExplorerCommand();
|
||||
|
||||
private:
|
||||
// Helpers
|
||||
HRESULT LaunchUI(CMINVOKECOMMANDINFO* pici, ipc::Writer* writer);
|
||||
|
||||
std::atomic<ULONG> m_ref_count = 1;
|
||||
IDataObject* m_data_obj = NULL;
|
||||
};
|
@@ -0,0 +1,50 @@
|
||||
#include <windows.h>
|
||||
#include "Generated Files/resource.h"
|
||||
#include "../../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
@@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h FileLocksmithExt.base.rc FileLocksmithExt.rc" />
|
||||
</Target>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{57175ec7-92a5-4c1e-8244-e3fbca2a81de}</ProjectGuid>
|
||||
<RootNamespace>FileLocksmithExt</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;FILELOCKSMITHEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;FILELOCKSMITHEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;FILELOCKSMITHEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;FILELOCKSMITHEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;FILELOCKSMITHLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;FILELOCKSMITHLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../;../../../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ClassFactory.h" />
|
||||
<ClInclude Include="Constants.h" />
|
||||
<ClInclude Include="dllmain.h" />
|
||||
<ClInclude Include="ExplorerCommand.h" />
|
||||
<ClInclude Include="IPC.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Settings.h" />
|
||||
<ClInclude Include="Trace.h" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="resource.base.h" />
|
||||
<ClInclude Include="Generated Files/resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files/FileLocksmithExt.rc" />
|
||||
<None Include="FileLocksmithExt.base.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ClassFactory.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="ExplorerCommand.cpp" />
|
||||
<ClCompile Include="IPC.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerToysModule.cpp" />
|
||||
<ClCompile Include="Settings.cpp" />
|
||||
<ClCompile Include="Trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dll.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\version\version.vcxproj">
|
||||
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ExplorerCommand.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ClassFactory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dllmain.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files/resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IPC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ExplorerCommand.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ClassFactory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerToysModule.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IPC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dll.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="resource.base.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
<None Include="FileLocksmithExt.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files/FileLocksmithExt.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
62
src/modules/FileLocksmith/FileLocksmithExt/IPC.cpp
Normal file
62
src/modules/FileLocksmith/FileLocksmithExt/IPC.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "IPC.h"
|
||||
#include "Constants.h"
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
constexpr DWORD DefaultPipeBufferSize = 8192;
|
||||
constexpr DWORD DefaultPipeTimeoutMillis = 200;
|
||||
|
||||
namespace ipc
|
||||
{
|
||||
Writer::Writer()
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
Writer::~Writer()
|
||||
{
|
||||
finish();
|
||||
}
|
||||
|
||||
HRESULT Writer::start()
|
||||
{
|
||||
std::wstring path = PTSettingsHelper::get_module_save_folder_location(constants::nonlocalizable::PowerToyName);
|
||||
path += L"\\";
|
||||
path += constants::nonlocalizable::LastRunPath;
|
||||
|
||||
try
|
||||
{
|
||||
m_stream = std::ofstream(path);
|
||||
return S_OK;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Writer::add_path(LPCWSTR path)
|
||||
{
|
||||
int length = lstrlenW(path);
|
||||
if (!m_stream.write(reinterpret_cast<const char*>(path), length * sizeof(WCHAR)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
WCHAR line_break = L'\n';
|
||||
if (!m_stream.write(reinterpret_cast<const char*>(&line_break), sizeof(WCHAR)))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Writer::finish()
|
||||
{
|
||||
add_path(L"");
|
||||
m_stream.close();
|
||||
}
|
||||
}
|
20
src/modules/FileLocksmith/FileLocksmithExt/IPC.h
Normal file
20
src/modules/FileLocksmith/FileLocksmithExt/IPC.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace ipc
|
||||
{
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
Writer();
|
||||
~Writer();
|
||||
HRESULT start();
|
||||
HRESULT add_path(LPCWSTR path);
|
||||
void finish();
|
||||
HANDLE get_read_handle();
|
||||
|
||||
private:
|
||||
std::ofstream m_stream;
|
||||
};
|
||||
}
|
118
src/modules/FileLocksmith/FileLocksmithExt/PowerToysModule.cpp
Normal file
118
src/modules/FileLocksmith/FileLocksmithExt/PowerToysModule.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/logger/logger_settings.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <optional>
|
||||
|
||||
#include "Constants.h"
|
||||
#include "dllmain.h"
|
||||
#include "Settings.h"
|
||||
#include "Trace.h"
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
class FileLocksmithModule : public PowertoyModuleIface
|
||||
{
|
||||
public:
|
||||
FileLocksmithModule()
|
||||
{
|
||||
LoggerHelpers::init_logger(constants::nonlocalizable::PowerToyName, L"ModuleInterface", LogSettings::fileLocksmithLoggerName);
|
||||
init_settings();
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
static WCHAR buffer[128];
|
||||
LoadStringW(globals::instance, IDS_FILELOCKSMITH_POWERTOYNAME, buffer, ARRAYSIZE(buffer));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return constants::nonlocalizable::PowerToyKey;
|
||||
}
|
||||
|
||||
// Return the configured status for the gpo policy for the module
|
||||
virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
|
||||
{
|
||||
return powertoys_gpo::getConfiguredFileLocksmithEnabledValue();
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
// These are the settings shown on the settings page along with their current values.
|
||||
virtual bool get_config(_Out_ PWSTR buffer, _Out_ int* buffer_size) override
|
||||
{
|
||||
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
|
||||
// Create a Settings object.
|
||||
PowerToysSettings::Settings settings(hinstance, get_name());
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
// Passes JSON with the configuration settings for the powertoy.
|
||||
// This is called when the user hits Save on the settings page.
|
||||
virtual void set_config(PCWSTR config) override
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the input JSON string.
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
// Currently, there are no settings, so we don't do anything.
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Logger::error("Configuration parsing failed: {}", std::string{ e.what() });
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enable() override
|
||||
{
|
||||
Logger::info(L"File Locksmith enabled");
|
||||
m_enabled = true;
|
||||
save_settings();
|
||||
}
|
||||
|
||||
virtual void disable() override
|
||||
{
|
||||
Logger::info(L"File Locksmith disabled");
|
||||
m_enabled = false;
|
||||
save_settings();
|
||||
}
|
||||
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_enabled;
|
||||
|
||||
void init_settings()
|
||||
{
|
||||
m_enabled = FileLocksmithSettingsInstance().GetEnabled();
|
||||
Trace::EnableFileLocksmith(m_enabled);
|
||||
}
|
||||
|
||||
void save_settings()
|
||||
{
|
||||
auto& settings = FileLocksmithSettingsInstance();
|
||||
settings.SetEnabled(m_enabled);
|
||||
settings.Save();
|
||||
Trace::EnableFileLocksmith(m_enabled);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new FileLocksmithModule();
|
||||
}
|
128
src/modules/FileLocksmith/FileLocksmithExt/Resources.resx
Normal file
128
src/modules/FileLocksmith/FileLocksmithExt/Resources.resx
Normal file
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="FileLocksmith_CommandTitle" xml:space="preserve">
|
||||
<value>What's using this file?</value>
|
||||
<comment>This text will be shown when the user opens the context menu (right clicks) a file.</comment>
|
||||
</data>
|
||||
<data name="FileLocksmith_PowerToyName" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
<comment>Localized name of the PowerToy.</comment>
|
||||
</data>
|
||||
</root>
|
85
src/modules/FileLocksmith/FileLocksmithExt/Settings.cpp
Normal file
85
src/modules/FileLocksmith/FileLocksmithExt/Settings.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "pch.h"
|
||||
#include "Settings.h"
|
||||
#include "Constants.h"
|
||||
|
||||
#include <common/utils/json.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
static bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA attr{};
|
||||
if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr))
|
||||
{
|
||||
*lpFileTime = attr.ftLastWriteTime;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FileLocksmithSettings::FileLocksmithSettings()
|
||||
{
|
||||
std::wstring savePath = PTSettingsHelper::get_module_save_folder_location(constants::nonlocalizable::PowerToyKey);
|
||||
std::error_code ec;
|
||||
|
||||
jsonFilePath = savePath + constants::nonlocalizable::DataFilePath;
|
||||
Load();
|
||||
}
|
||||
|
||||
void FileLocksmithSettings::Save()
|
||||
{
|
||||
json::JsonObject jsonData;
|
||||
|
||||
jsonData.SetNamedValue(constants::nonlocalizable::JsonKeyEnabled, json::value(settings.enabled));
|
||||
|
||||
json::to_file(jsonFilePath, jsonData);
|
||||
GetSystemTimeAsFileTime(&lastLoadedTime);
|
||||
}
|
||||
|
||||
void FileLocksmithSettings::Load()
|
||||
{
|
||||
if (!std::filesystem::exists(jsonFilePath))
|
||||
{
|
||||
Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseJson();
|
||||
}
|
||||
}
|
||||
|
||||
void FileLocksmithSettings::Reload()
|
||||
{
|
||||
// Load json settings from data file if it is modified in the meantime.
|
||||
FILETIME lastModifiedTime{};
|
||||
if (LastModifiedTime(jsonFilePath, &lastModifiedTime) &&
|
||||
CompareFileTime(&lastModifiedTime, &lastLoadedTime) == 1)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
void FileLocksmithSettings::ParseJson()
|
||||
{
|
||||
auto json = json::from_file(jsonFilePath);
|
||||
if (json)
|
||||
{
|
||||
const json::JsonObject& jsonSettings = json.value();
|
||||
try
|
||||
{
|
||||
if (json::has(jsonSettings, constants::nonlocalizable::JsonKeyEnabled, json::JsonValueType::Boolean))
|
||||
{
|
||||
settings.enabled = jsonSettings.GetNamedBoolean(constants::nonlocalizable::JsonKeyEnabled);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
}
|
||||
}
|
||||
GetSystemTimeAsFileTime(&lastLoadedTime);
|
||||
}
|
||||
|
||||
FileLocksmithSettings& FileLocksmithSettingsInstance()
|
||||
{
|
||||
static FileLocksmithSettings instance;
|
||||
return instance;
|
||||
}
|
45
src/modules/FileLocksmith/FileLocksmithExt/Settings.h
Normal file
45
src/modules/FileLocksmith/FileLocksmithExt/Settings.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include <common/utils/gpo.h>
|
||||
|
||||
class FileLocksmithSettings
|
||||
{
|
||||
public:
|
||||
FileLocksmithSettings();
|
||||
|
||||
inline bool GetEnabled()
|
||||
{
|
||||
auto gpoSetting = powertoys_gpo::getConfiguredFileLocksmithEnabledValue();
|
||||
if (gpoSetting == powertoys_gpo::gpo_rule_configured_enabled)
|
||||
return true;
|
||||
if (gpoSetting == powertoys_gpo::gpo_rule_configured_disabled)
|
||||
return false;
|
||||
Reload();
|
||||
return settings.enabled;
|
||||
}
|
||||
|
||||
inline void SetEnabled(bool enabled)
|
||||
{
|
||||
settings.enabled = enabled;
|
||||
Save();
|
||||
}
|
||||
|
||||
void Save();
|
||||
void Load();
|
||||
|
||||
private:
|
||||
struct Settings
|
||||
{
|
||||
bool enabled{ true };
|
||||
};
|
||||
|
||||
void Reload();
|
||||
void ParseJson();
|
||||
|
||||
Settings settings;
|
||||
std::wstring jsonFilePath;
|
||||
FILETIME lastLoadedTime;
|
||||
};
|
||||
|
||||
FileLocksmithSettings& FileLocksmithSettingsInstance();
|
60
src/modules/FileLocksmith/FileLocksmithExt/Trace.cpp
Normal file
60
src/modules/FileLocksmith/FileLocksmithExt/Trace.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "Trace.h"
|
||||
#include "../common/Telemetry/ProjectTelemetry.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider() noexcept
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider() noexcept
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::EnableFileLocksmith(_In_ bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FileLocksmith_EnableFileLocksmith",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
||||
|
||||
void Trace::Invoked() noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FileLocksmith_Invoked",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::InvokedRet(_In_ HRESULT hr) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FileLocksmith_InvokedRet",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingHResult(hr),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::QueryContextMenuError(_In_ HRESULT hr) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FileLocksmith_QueryContextMenuError",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingHResult(hr),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
14
src/modules/FileLocksmith/FileLocksmithExt/Trace.h
Normal file
14
src/modules/FileLocksmith/FileLocksmithExt/Trace.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider() noexcept;
|
||||
static void UnregisterProvider() noexcept;
|
||||
static void EnableFileLocksmith(_In_ bool enabled) noexcept;
|
||||
static void Invoked() noexcept;
|
||||
static void InvokedRet(_In_ HRESULT hr) noexcept;
|
||||
static void QueryContextMenuError(_In_ HRESULT hr) noexcept;
|
||||
};
|
5
src/modules/FileLocksmith/FileLocksmithExt/dll.def
Normal file
5
src/modules/FileLocksmith/FileLocksmithExt/dll.def
Normal file
@@ -0,0 +1,5 @@
|
||||
EXPORTS
|
||||
DllRegisterServer PRIVATE
|
||||
DllUnregisterServer PRIVATE
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
62
src/modules/FileLocksmith/FileLocksmithExt/dllmain.cpp
Normal file
62
src/modules/FileLocksmith/FileLocksmithExt/dllmain.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
// Additional libraries to link
|
||||
#pragma comment(lib, "shlwapi")
|
||||
|
||||
#include "ClassFactory.h"
|
||||
#include "Trace.h"
|
||||
|
||||
namespace globals
|
||||
{
|
||||
HMODULE instance;
|
||||
std::atomic<ULONG> ref_count;
|
||||
std::atomic<bool> enabled;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
globals::instance = hModule;
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI DllRegisterServer()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI DllUnregisterServer()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv)
|
||||
{
|
||||
HRESULT result = E_FAIL;
|
||||
*ppv = NULL;
|
||||
ClassFactory* class_factory = new (std::nothrow) ClassFactory(clsid);
|
||||
if (class_factory)
|
||||
{
|
||||
result = class_factory->QueryInterface(riid, ppv);
|
||||
class_factory->Release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
STDAPI DllCanUnloadNow(void)
|
||||
{
|
||||
return globals::ref_count == 0 ? S_OK : S_FALSE;
|
||||
}
|
10
src/modules/FileLocksmith/FileLocksmithExt/dllmain.h
Normal file
10
src/modules/FileLocksmith/FileLocksmithExt/dllmain.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
namespace globals
|
||||
{
|
||||
extern HMODULE instance;
|
||||
extern std::atomic<ULONG> ref_count;
|
||||
extern std::atomic<bool> enabled;
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.220929.3" targetFramework="native" />
|
||||
</packages>
|
5
src/modules/FileLocksmith/FileLocksmithExt/pch.cpp
Normal file
5
src/modules/FileLocksmith/FileLocksmithExt/pch.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
16
src/modules/FileLocksmith/FileLocksmithExt/pch.h
Normal file
16
src/modules/FileLocksmith/FileLocksmithExt/pch.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <Windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <ShlObj_core.h>
|
||||
#include <atlbase.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
// C++ Standard library
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
13
src/modules/FileLocksmith/FileLocksmithExt/resource.base.h
Normal file
13
src/modules/FileLocksmith/FileLocksmithExt/resource.base.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by FileLocksmithLib.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys File Locksmith Static Library"
|
||||
#define INTERNAL_NAME "PowerToys.FileLocksmithLib.lib"
|
||||
#define ORIGINAL_FILENAME "PowerToys.FileLocksmithLib.lib"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
@@ -0,0 +1,172 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "FileLocksmith.h"
|
||||
#include "NtdllExtensions.h"
|
||||
|
||||
static bool is_directory(const std::wstring path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(path.c_str());
|
||||
return attributes != INVALID_FILE_ATTRIBUTES && attributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
// C++20 method
|
||||
static bool starts_with(std::wstring_view whole, std::wstring_view part)
|
||||
{
|
||||
return whole.size() >= part.size() && whole.substr(0, part.size()) == part;
|
||||
}
|
||||
|
||||
std::vector<ProcessResult> find_processes_recursive(const std::vector<std::wstring>& paths)
|
||||
{
|
||||
NtdllExtensions nt_ext;
|
||||
|
||||
// TODO use a trie!
|
||||
|
||||
// This maps kernel names of files within `paths` to their normal paths.
|
||||
std::map<std::wstring, std::wstring> kernel_names_files;
|
||||
|
||||
// This maps kernel names of directories within `paths` to their normal paths.
|
||||
std::map<std::wstring, std::wstring> kernel_names_dirs;
|
||||
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
auto kernel_path = nt_ext.path_to_kernel_name(path.c_str());
|
||||
if (!kernel_path.empty())
|
||||
{
|
||||
(is_directory(path) ? kernel_names_dirs : kernel_names_files)[kernel_path] = path;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<DWORD, std::set<std::wstring>> pid_files;
|
||||
|
||||
// Returns a normal path of the file specified by kernel_name, if it matches
|
||||
// the search criteria. Otherwise, return an empty string.
|
||||
auto kernel_paths_contain = [&](const std::wstring& kernel_name) -> std::wstring
|
||||
{
|
||||
// Normal equivalence
|
||||
if (auto it = kernel_names_files.find(kernel_name); it != kernel_names_files.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (auto it = kernel_names_dirs.find(kernel_name); it != kernel_names_dirs.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
for (const auto& [dir_kernel_name, dir_path] : kernel_names_dirs)
|
||||
{
|
||||
if (starts_with(kernel_name, dir_kernel_name + (dir_kernel_name.length()>0&&dir_kernel_name[dir_kernel_name.length()-1]!=L'\\' ? L"\\" : L"")))
|
||||
{
|
||||
return dir_path + kernel_name.substr(dir_kernel_name.size());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
for (const auto& handle_info : nt_ext.handles())
|
||||
{
|
||||
if (handle_info.type_name == L"File")
|
||||
{
|
||||
auto path = kernel_paths_contain(handle_info.kernel_file_name);
|
||||
if (!path.empty())
|
||||
{
|
||||
pid_files[handle_info.pid].insert(std::move(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check all modules used by processes
|
||||
auto processes = nt_ext.processes();
|
||||
|
||||
for (const auto& process : processes)
|
||||
{
|
||||
for (const auto& path : process.modules)
|
||||
{
|
||||
auto kernel_name = nt_ext.path_to_kernel_name(path.c_str());
|
||||
|
||||
auto found_path = kernel_paths_contain(kernel_name);
|
||||
if (!found_path.empty())
|
||||
{
|
||||
pid_files[process.pid].insert(std::move(found_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ProcessResult> result;
|
||||
|
||||
for (const auto& process_info : processes)
|
||||
{
|
||||
if (auto it = pid_files.find(process_info.pid); it != pid_files.end())
|
||||
{
|
||||
result.push_back(ProcessResult
|
||||
{
|
||||
process_info.name,
|
||||
process_info.pid,
|
||||
std::vector(it->second.begin(), it->second.end())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring pid_to_user(DWORD pid)
|
||||
{
|
||||
HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
|
||||
if (process == NULL)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring user = L"";
|
||||
std::wstring domain = L"";
|
||||
|
||||
HANDLE token = NULL;
|
||||
|
||||
if (OpenProcessToken(process, TOKEN_QUERY, &token))
|
||||
{
|
||||
DWORD token_size = 0;
|
||||
GetTokenInformation(token, TokenUser, NULL, 0, &token_size);
|
||||
|
||||
if (token_size > 0)
|
||||
{
|
||||
std::vector<BYTE> token_buffer(token_size);
|
||||
GetTokenInformation(token, TokenUser, token_buffer.data(), token_size, &token_size);
|
||||
TOKEN_USER* user_ptr = (TOKEN_USER*)token_buffer.data();
|
||||
PSID psid = user_ptr->User.Sid;
|
||||
DWORD user_size = 0;
|
||||
DWORD domain_size = 0;
|
||||
SID_NAME_USE sid_name;
|
||||
LookupAccountSidW(NULL, psid, NULL, &user_size, NULL, &domain_size, &sid_name);
|
||||
user.resize(user_size + 1);
|
||||
domain.resize(domain_size + 1);
|
||||
LookupAccountSidW(NULL, psid, user.data(), &user_size, domain.data(), &domain_size, &sid_name);
|
||||
user[user_size] = L'\0';
|
||||
domain[domain_size] = L'\0';
|
||||
}
|
||||
|
||||
CloseHandle(token);
|
||||
}
|
||||
|
||||
CloseHandle(process);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
constexpr size_t LongMaxPathSize = 65536;
|
||||
|
||||
std::wstring pid_to_full_path(DWORD pid)
|
||||
{
|
||||
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
|
||||
|
||||
std::wstring result(LongMaxPathSize, L'\0');
|
||||
|
||||
// Returns zero on failure, so it's okay to resize to zero.
|
||||
auto length = GetModuleFileNameExW(process, NULL, result.data(), (DWORD)result.size());
|
||||
result.resize(length);
|
||||
|
||||
CloseHandle(process);
|
||||
return result;
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
struct ProcessResult
|
||||
{
|
||||
std::wstring name;
|
||||
DWORD pid;
|
||||
std::vector<std::wstring> files;
|
||||
};
|
||||
|
||||
// Second version, checks handles towards files and all subfiles and folders of given dirs, if any.
|
||||
std::vector<ProcessResult> find_processes_recursive(const std::vector<std::wstring>& paths);
|
||||
|
||||
// Gives the user name of the account running this process
|
||||
std::wstring pid_to_user(DWORD pid);
|
||||
|
||||
// Gives the full path of the executable, given the process id
|
||||
std::wstring pid_to_full_path(DWORD pid);
|
@@ -0,0 +1,40 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
@@ -0,0 +1,290 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{c604b37e-9d0e-4484-8778-e8b31b0e1b3a}</ProjectGuid>
|
||||
<RootNamespace>FileLocksmithLibInterop</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>NetCore</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\FileLocksmith\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;FILELOCKSMITHLIBINTEROP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsManaged>NetCore</CompileAsManaged>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/Zc:twoPhase-</AdditionalOptions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="FileLocksmith.cpp" />
|
||||
<ClCompile Include="Interop.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NtdllBase.cpp" />
|
||||
<ClCompile Include="NtdllExtensions.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="FileLocksmith.h" />
|
||||
<ClInclude Include="NtdllBase.h" />
|
||||
<ClInclude Include="NtdllExtensions.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj">
|
||||
<Project>{f055103b-f80b-4d0c-bf48-057c55620033}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="FileLocksmithLibInterop.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Interop.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileLocksmith.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NtdllBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NtdllExtensions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileLocksmith.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NtdllBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NtdllExtensions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="FileLocksmithLibInterop.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -0,0 +1,61 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "NtdllBase.h"
|
||||
|
||||
Ntdll::Ntdll()
|
||||
{
|
||||
m_module = GetModuleHandleW(L"ntdll.dll");
|
||||
if (m_module == 0)
|
||||
{
|
||||
throw std::runtime_error{ "GetModuleHandleW returned null" };
|
||||
}
|
||||
|
||||
m_NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(m_module, "NtQuerySystemInformation");
|
||||
if (m_NtQuerySystemInformation == 0)
|
||||
{
|
||||
throw std::runtime_error{ "GetProcAddress returned null for NtQuerySystemInformation" };
|
||||
}
|
||||
|
||||
m_NtDuplicateObject = (NtDuplicateObject_t)GetProcAddress(m_module, "NtDuplicateObject");
|
||||
if (m_NtDuplicateObject == 0)
|
||||
{
|
||||
throw std::runtime_error{ "GetProcAddress returned null for NtDuplicateObject" };
|
||||
}
|
||||
|
||||
m_NtQueryObject = (NtQueryObject_t)GetProcAddress(m_module, "NtQueryObject");
|
||||
if (m_NtQueryObject == 0)
|
||||
{
|
||||
throw std::runtime_error{ "GetProcAddress returned null for NtQueryObject" };
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS Ntdll::NtQuerySystemInformation(
|
||||
ULONG SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength)
|
||||
{
|
||||
return m_NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
|
||||
}
|
||||
|
||||
NTSTATUS Ntdll::NtDuplicateObject(
|
||||
HANDLE SourceProcessHandle,
|
||||
HANDLE SourceHandle,
|
||||
HANDLE TargetProcessHandle,
|
||||
PHANDLE TargetHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG Attributes,
|
||||
ULONG Options)
|
||||
{
|
||||
return m_NtDuplicateObject(SourceProcessHandle, SourceHandle, TargetProcessHandle, TargetHandle, DesiredAccess, Attributes, Options);
|
||||
}
|
||||
|
||||
NTSTATUS Ntdll::NtQueryObject(
|
||||
HANDLE ObjectHandle,
|
||||
ULONG ObjectInformationClass,
|
||||
PVOID ObjectInformation,
|
||||
ULONG ObjectInformationLength,
|
||||
PULONG ReturnLength)
|
||||
{
|
||||
return m_NtQueryObject(ObjectHandle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#define DECLARE_NTDLL_FUNCTION(name, ...) \
|
||||
private: \
|
||||
typedef NTSTATUS(NTAPI* name ## _t)( \
|
||||
__VA_ARGS__ \
|
||||
); \
|
||||
name ## _t m_ ## name; \
|
||||
public: \
|
||||
NTSTATUS name(__VA_ARGS__);
|
||||
|
||||
class Ntdll
|
||||
{
|
||||
private:
|
||||
HMODULE m_module;
|
||||
public:
|
||||
struct SYSTEM_HANDLE
|
||||
{
|
||||
ULONG ProcessId;
|
||||
BYTE ObjectTypeNumber;
|
||||
BYTE Flags;
|
||||
USHORT Handle;
|
||||
PVOID Object;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
};
|
||||
|
||||
struct SYSTEM_HANDLE_INFORMATION
|
||||
{
|
||||
ULONG HandleCount;
|
||||
SYSTEM_HANDLE Handles[1];
|
||||
};
|
||||
|
||||
enum POOL_TYPE
|
||||
{
|
||||
NonPagedPool,
|
||||
PagedPool,
|
||||
NonPagedPoolMustSucceed,
|
||||
DontUseThisType,
|
||||
NonPagedPoolCacheAligned,
|
||||
PagedPoolCacheAligned,
|
||||
NonPagedPoolCacheAlignedMustS
|
||||
};
|
||||
|
||||
struct OBJECT_TYPE_INFORMATION
|
||||
{
|
||||
UNICODE_STRING Name;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG TotalPagedPoolUsage;
|
||||
ULONG TotalNonPagedPoolUsage;
|
||||
ULONG TotalNamePoolUsage;
|
||||
ULONG TotalHandleTableUsage;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
ULONG HighWaterPagedPoolUsage;
|
||||
ULONG HighWaterNonPagedPoolUsage;
|
||||
ULONG HighWaterNamePoolUsage;
|
||||
ULONG HighWaterHandleTableUsage;
|
||||
ULONG InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
ULONG ValidAccess;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
USHORT MaintainTypeList;
|
||||
POOL_TYPE PoolType;
|
||||
ULONG PagedPoolUsage;
|
||||
ULONG NonPagedPoolUsage;
|
||||
};
|
||||
|
||||
Ntdll();
|
||||
|
||||
DECLARE_NTDLL_FUNCTION(NtQuerySystemInformation,
|
||||
ULONG SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
)
|
||||
|
||||
DECLARE_NTDLL_FUNCTION(NtDuplicateObject,
|
||||
HANDLE SourceProcessHandle,
|
||||
HANDLE SourceHandle,
|
||||
HANDLE TargetProcessHandle,
|
||||
PHANDLE TargetHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
ULONG Attributes,
|
||||
ULONG Options
|
||||
)
|
||||
|
||||
DECLARE_NTDLL_FUNCTION(NtQueryObject,
|
||||
HANDLE ObjectHandle,
|
||||
ULONG ObjectInformationClass,
|
||||
PVOID ObjectInformation,
|
||||
ULONG ObjectInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
};
|
@@ -0,0 +1,266 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "NtdllExtensions.h"
|
||||
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((LONG)0xC0000004)
|
||||
|
||||
// Calls NtQuerySystemInformation and returns a buffer containing the result.
|
||||
|
||||
namespace
|
||||
{
|
||||
std::wstring_view unicode_to_view(UNICODE_STRING unicode_str)
|
||||
{
|
||||
return std::wstring_view(unicode_str.Buffer, unicode_str.Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
std::wstring unicode_to_str(UNICODE_STRING unicode_str)
|
||||
{
|
||||
return std::wstring(unicode_str.Buffer, unicode_str.Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
// Implementation adapted from src/common/utils
|
||||
inline std::wstring get_module_name(HANDLE process, HMODULE mod)
|
||||
{
|
||||
wchar_t buffer[MAX_PATH + 1];
|
||||
DWORD actual_length = GetModuleFileNameExW(process, mod, buffer, MAX_PATH + 1);
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
const DWORD long_path_length = 0xFFFF; // should be always enough
|
||||
std::wstring long_filename(long_path_length, L'\0');
|
||||
actual_length = GetModuleFileNameW(mod, long_filename.data(), long_path_length);
|
||||
long_filename.resize(std::wcslen(long_filename.data()));
|
||||
long_filename.shrink_to_fit();
|
||||
return long_filename;
|
||||
}
|
||||
|
||||
return { buffer, (UINT)lstrlenW(buffer) };
|
||||
}
|
||||
|
||||
constexpr size_t DefaultModulesResultSize = 512;
|
||||
|
||||
std::vector<std::wstring> process_modules(DWORD pid)
|
||||
{
|
||||
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
|
||||
if (!process)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::wstring> result;
|
||||
|
||||
bool completed = false;
|
||||
std::vector<HMODULE> modules(DefaultModulesResultSize);
|
||||
while (!completed)
|
||||
{
|
||||
DWORD needed;
|
||||
auto status = EnumProcessModules(process, modules.data(), static_cast<DWORD>(modules.size() * sizeof(HMODULE)), &needed);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
// Give up
|
||||
return {};
|
||||
}
|
||||
|
||||
if (needed > modules.size() * sizeof(HMODULE))
|
||||
{
|
||||
// Array is too small
|
||||
modules.resize(needed / sizeof(HMODULE));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Okay
|
||||
modules.resize(needed / sizeof(HMODULE));
|
||||
|
||||
for (auto mod : modules)
|
||||
{
|
||||
result.push_back(get_module_name(process, mod));
|
||||
}
|
||||
|
||||
completed = true;
|
||||
}
|
||||
|
||||
CloseHandle(process);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
NtdllExtensions::MemoryLoopResult NtdllExtensions::NtQuerySystemInformationMemoryLoop(ULONG SystemInformationClass)
|
||||
{
|
||||
MemoryLoopResult result;
|
||||
result.memory.resize(DefaultResultBufferSize);
|
||||
|
||||
while (result.memory.size() <= MaxResultBufferSize)
|
||||
{
|
||||
ULONG result_len;
|
||||
result.status = NtQuerySystemInformation(SystemInformationClass, result.memory.data(), (ULONG)result.memory.size(), &result_len);
|
||||
|
||||
if (result.status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
result.memory.resize(result.memory.size() * 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NT_ERROR(result.status))
|
||||
{
|
||||
result.memory.clear();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result.status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
result.memory.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring NtdllExtensions::file_handle_to_kernel_name(HANDLE file_handle, std::vector<BYTE>& buffer)
|
||||
{
|
||||
if (GetFileType(file_handle) != FILE_TYPE_DISK)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
ULONG return_length;
|
||||
auto status = NtQueryObject(file_handle, ObjectNameInformation, buffer.data(), (ULONG)buffer.size(), &return_length);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
auto object_name_info = (UNICODE_STRING*)buffer.data();
|
||||
return unicode_to_str(*object_name_info);
|
||||
}
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring NtdllExtensions::file_handle_to_kernel_name(HANDLE file_handle)
|
||||
{
|
||||
std::vector<BYTE> buffer(DefaultResultBufferSize);
|
||||
return file_handle_to_kernel_name(file_handle, buffer);
|
||||
}
|
||||
|
||||
std::wstring NtdllExtensions::path_to_kernel_name(LPCWSTR path)
|
||||
{
|
||||
HANDLE file_handle = CreateFileW(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto kernel_name = file_handle_to_kernel_name(file_handle);
|
||||
CloseHandle(file_handle);
|
||||
return kernel_name;
|
||||
}
|
||||
|
||||
std::vector<NtdllExtensions::HandleInfo> NtdllExtensions::handles() noexcept
|
||||
{
|
||||
auto get_info_result = NtQuerySystemInformationMemoryLoop(SystemHandleInformation);
|
||||
if (NT_ERROR(get_info_result.status))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto info_ptr = (SYSTEM_HANDLE_INFORMATION*)get_info_result.memory.data();
|
||||
|
||||
std::map<DWORD, HANDLE> pid_to_handle;
|
||||
std::vector<HandleInfo> result;
|
||||
|
||||
std::vector<BYTE> object_info_buffer(DefaultResultBufferSize);
|
||||
|
||||
for (ULONG i = 0; i < info_ptr->HandleCount; i++)
|
||||
{
|
||||
auto handle_info = info_ptr->Handles + i;
|
||||
DWORD pid = handle_info->ProcessId;
|
||||
|
||||
HANDLE process_handle = NULL;
|
||||
auto iter = pid_to_handle.find(pid);
|
||||
if (iter != pid_to_handle.end())
|
||||
{
|
||||
process_handle = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
process_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
|
||||
if (!process_handle)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pid_to_handle[pid] = process_handle;
|
||||
}
|
||||
|
||||
// According to this:
|
||||
// https://stackoverflow.com/questions/46384048/enumerate-handles
|
||||
// NtQueryObject could hang
|
||||
|
||||
// TODO uncomment and investigate
|
||||
// if (handle_info->GrantedAccess == 0x0012019f) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
HANDLE handle_copy;
|
||||
|
||||
auto dh_result = DuplicateHandle(process_handle, (HANDLE)handle_info->Handle, GetCurrentProcess(), &handle_copy, 0, 0, DUPLICATE_SAME_ACCESS);
|
||||
if (dh_result == 0)
|
||||
{
|
||||
// Ignore this handle.
|
||||
continue;
|
||||
}
|
||||
|
||||
ULONG return_length;
|
||||
auto status = NtQueryObject(handle_copy, ObjectTypeInformation, object_info_buffer.data(), (ULONG)object_info_buffer.size(), &return_length);
|
||||
if (NT_ERROR(status))
|
||||
{
|
||||
// Ignore this handle.
|
||||
CloseHandle(handle_copy);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto object_type_info = (OBJECT_TYPE_INFORMATION*)object_info_buffer.data();
|
||||
auto type_name = unicode_to_str(object_type_info->Name);
|
||||
|
||||
std::wstring file_name = file_handle_to_kernel_name(handle_copy, object_info_buffer);
|
||||
|
||||
if (type_name == L"File")
|
||||
{
|
||||
file_name = file_handle_to_kernel_name(handle_copy, object_info_buffer);
|
||||
}
|
||||
|
||||
result.push_back(HandleInfo{ pid, handle_info->Handle, type_name, file_name });
|
||||
CloseHandle(handle_copy);
|
||||
}
|
||||
|
||||
for (auto [pid, handle] : pid_to_handle)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the list of all processes.
|
||||
// On failure, returns an empty vector.
|
||||
|
||||
std::vector<NtdllExtensions::ProcessInfo> NtdllExtensions::processes() noexcept
|
||||
{
|
||||
auto get_info_result = NtQuerySystemInformationMemoryLoop(SystemProcessInformation);
|
||||
|
||||
if (NT_ERROR(get_info_result.status))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<ProcessInfo> result;
|
||||
auto info_ptr = (PSYSTEM_PROCESS_INFORMATION)get_info_result.memory.data();
|
||||
|
||||
while (info_ptr->NextEntryOffset)
|
||||
{
|
||||
info_ptr = decltype(info_ptr)((LPBYTE)info_ptr + info_ptr->NextEntryOffset);
|
||||
|
||||
ProcessInfo item;
|
||||
item.name = unicode_to_str(info_ptr->ImageName);
|
||||
item.pid = (DWORD)(uintptr_t)info_ptr->UniqueProcessId;
|
||||
item.modules = process_modules(item.pid);
|
||||
|
||||
result.push_back(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "NtdllBase.h"
|
||||
|
||||
class NtdllExtensions : protected Ntdll
|
||||
{
|
||||
private:
|
||||
constexpr static size_t DefaultResultBufferSize = 64 * 1024;
|
||||
constexpr static size_t MaxResultBufferSize = 1024 * 1024 * 1024;
|
||||
|
||||
constexpr static int ObjectNameInformation = 1;
|
||||
constexpr static int SystemHandleInformation = 16;
|
||||
|
||||
struct MemoryLoopResult
|
||||
{
|
||||
NTSTATUS status = 0;
|
||||
std::vector<BYTE> memory;
|
||||
};
|
||||
|
||||
// Calls NtQuerySystemInformation and returns a buffer containing the result.
|
||||
MemoryLoopResult NtQuerySystemInformationMemoryLoop(ULONG SystemInformationClass);
|
||||
|
||||
std::wstring file_handle_to_kernel_name(HANDLE file_handle, std::vector<BYTE>& buffer);
|
||||
|
||||
public:
|
||||
struct ProcessInfo
|
||||
{
|
||||
DWORD pid;
|
||||
std::wstring name;
|
||||
std::vector<std::wstring> modules;
|
||||
};
|
||||
|
||||
struct HandleInfo
|
||||
{
|
||||
DWORD pid;
|
||||
USHORT handle;
|
||||
std::wstring type_name;
|
||||
std::wstring kernel_file_name;
|
||||
};
|
||||
|
||||
std::wstring file_handle_to_kernel_name(HANDLE file_handle);
|
||||
|
||||
std::wstring path_to_kernel_name(LPCWSTR path);
|
||||
|
||||
std::vector<HandleInfo> handles() noexcept;
|
||||
|
||||
// Returns the list of all processes.
|
||||
// On failure, returns an empty vector.
|
||||
std::vector<ProcessInfo> processes() noexcept;
|
||||
};
|
186
src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp
Normal file
186
src/modules/FileLocksmith/FileLocksmithLibInterop/interop.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "FileLocksmith.h"
|
||||
|
||||
#include "../FileLocksmithExt/Constants.h"
|
||||
|
||||
namespace FileLocksmith::Interop
|
||||
{
|
||||
public ref struct ProcessResult
|
||||
{
|
||||
System::String^ name;
|
||||
System::UInt32 pid;
|
||||
array<System::String^>^ files;
|
||||
System::Boolean isExpanded; // For helping in the UI
|
||||
};
|
||||
|
||||
System::String^ from_wstring_view(std::wstring_view str)
|
||||
{
|
||||
return gcnew System::String(str.data(), 0, static_cast<int>(str.size()));
|
||||
}
|
||||
|
||||
std::wstring from_system_string(System::String^ str)
|
||||
{
|
||||
// TODO use some built-in method
|
||||
auto chars = str->ToCharArray();
|
||||
|
||||
std::wstring result(chars->Length, 0);
|
||||
for (int i = 0; i < chars->Length; i++)
|
||||
{
|
||||
result[i] = chars[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring paths_file()
|
||||
{
|
||||
std::wstring path = from_system_string(interop::Constants::AppDataPath());
|
||||
path += L"\\";
|
||||
path += constants::nonlocalizable::PowerToyName;
|
||||
path += L"\\";
|
||||
path += constants::nonlocalizable::LastRunPath;
|
||||
return path;
|
||||
}
|
||||
|
||||
std::wstring executable_path()
|
||||
{
|
||||
return pid_to_full_path(GetCurrentProcessId());
|
||||
}
|
||||
|
||||
public ref struct NativeMethods
|
||||
{
|
||||
static array<ProcessResult ^> ^ FindProcessesRecursive(array<System::String^>^ paths)
|
||||
{
|
||||
const int n = paths->Length;
|
||||
|
||||
std::vector<std::wstring> paths_cpp(n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
paths_cpp[i] = from_system_string(paths[i]);
|
||||
}
|
||||
|
||||
auto result_cpp = find_processes_recursive(paths_cpp);
|
||||
const auto result_size = static_cast<int>(result_cpp.size());
|
||||
|
||||
auto result = gcnew array<ProcessResult ^>(result_size);
|
||||
for (int i = 0; i < result_size; i++)
|
||||
{
|
||||
auto item = gcnew ProcessResult;
|
||||
|
||||
item->name = from_wstring_view(result_cpp[i].name);
|
||||
item->pid = result_cpp[i].pid;
|
||||
|
||||
const int n_files = static_cast<int>(result_cpp[i].files.size());
|
||||
item->files = gcnew array<System::String ^>(n_files);
|
||||
for (int j = 0; j < n_files; j++)
|
||||
{
|
||||
item->files[j] = from_wstring_view(result_cpp[i].files[j]);
|
||||
}
|
||||
item->isExpanded = false;
|
||||
|
||||
result[i] = item;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static System::String^ PidToUser(System::UInt32 pid)
|
||||
{
|
||||
auto user_cpp = pid_to_user(pid);
|
||||
return from_wstring_view(user_cpp);
|
||||
}
|
||||
|
||||
static System::String^ PidToFullPath(System::UInt32 pid)
|
||||
{
|
||||
auto path_cpp = pid_to_full_path(pid);
|
||||
return from_wstring_view(path_cpp);
|
||||
}
|
||||
|
||||
static array<System::String^>^ ReadPathsFromFile()
|
||||
{
|
||||
std::ifstream stream(paths_file());
|
||||
|
||||
std::vector<std::wstring> result_cpp;
|
||||
std::wstring line;
|
||||
|
||||
bool finished = false;
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
WCHAR ch;
|
||||
// We have to read data like this
|
||||
if (!stream.read(reinterpret_cast<char*>(&ch), 2))
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else if (ch == L'\n')
|
||||
{
|
||||
if (line.empty())
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_cpp.push_back(line);
|
||||
line = {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line += ch;
|
||||
}
|
||||
}
|
||||
|
||||
auto result = gcnew array<System::String ^>(static_cast<int>(result_cpp.size()));
|
||||
for (int i = 0; i < result->Length; i++)
|
||||
{
|
||||
result[i] = from_wstring_view(result_cpp[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static System::Boolean StartAsElevated(array<System::String ^> ^ paths)
|
||||
{
|
||||
std::ofstream stream(paths_file());
|
||||
const WCHAR newline = L'\n';
|
||||
for (int i = 0; i < paths->Length; i++)
|
||||
{
|
||||
auto path_cpp = from_system_string(paths[i]);
|
||||
stream.write(reinterpret_cast<const char*>(path_cpp.c_str()), path_cpp.size() * sizeof(WCHAR));
|
||||
stream.write(reinterpret_cast<const char*>(&newline), sizeof(WCHAR));
|
||||
}
|
||||
|
||||
stream.write(reinterpret_cast<const char*>(&newline), sizeof(WCHAR));
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
stream.close();
|
||||
|
||||
auto exec_path = executable_path();
|
||||
|
||||
SHELLEXECUTEINFOW exec_info;
|
||||
exec_info.cbSize = sizeof(exec_info);
|
||||
exec_info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
exec_info.hwnd = NULL;
|
||||
exec_info.lpVerb = L"runas";
|
||||
exec_info.lpFile = exec_path.c_str();
|
||||
exec_info.lpParameters = L"--elevated";
|
||||
exec_info.lpDirectory = NULL;
|
||||
exec_info.nShow = SW_SHOW;
|
||||
exec_info.hInstApp = NULL;
|
||||
|
||||
if (ShellExecuteExW(&exec_info))
|
||||
{
|
||||
CloseHandle(exec_info.hProcess);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
19
src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h
Normal file
19
src/modules/FileLocksmith/FileLocksmithLibInterop/pch.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
// System headers
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <Psapi.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
// C++ standard library headers
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
13
src/modules/FileLocksmith/FileLocksmithLibInterop/resource.h
Normal file
13
src/modules/FileLocksmith/FileLocksmithLibInterop/resource.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by FileLocksmithLibInterop.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys FileLocksmithLib Interop"
|
||||
#define INTERNAL_NAME "PowerToys.FileLocksmithLib.Interop"
|
||||
#define ORIGINAL_FILENAME "PowerToys.FileLocksmithLib.Interop.dll"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
118
src/modules/FileLocksmith/FileLocksmithUI/App.xaml
Normal file
118
src/modules/FileLocksmith/FileLocksmithUI/App.xaml
Normal file
@@ -0,0 +1,118 @@
|
||||
<Application
|
||||
x:Class="FileLocksmithUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FileLocksmithUI">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
|
||||
|
||||
|
||||
<Style x:Key="SubtleButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Width" Value="36" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Height" Value="36" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="FocusVisualMargin" Value="-3" />
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AnimatedIcon.State="Normal"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ContentPresenter.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</ContentPresenter.BackgroundTransition>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</ContentPresenter>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
49
src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs
Normal file
49
src/modules/FileLocksmith/FileLocksmithUI/App.xaml.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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.Linq;
|
||||
using FileLocksmithUI.Helpers;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace FileLocksmithUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="App"/> class.
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||
/// will be used such as when the application is launched to open a specific file.
|
||||
/// </summary>
|
||||
/// <param name="args">Details about the launch request and process.</param>
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredFileLocksmithEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
Environment.Exit(0); // Current.Exit won't work until there's a window opened.
|
||||
return;
|
||||
}
|
||||
|
||||
_window = new MainWindow(Environment.GetCommandLineArgs().Contains("--elevated"));
|
||||
_window.Activate();
|
||||
}
|
||||
|
||||
private Window _window;
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.Converters
|
||||
{
|
||||
using System;
|
||||
using FileLocksmith.Interop;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
public sealed class FileCountConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
#pragma warning disable CA1305 // Specify IFormatProvider
|
||||
return ((string[])value).Length.ToString();
|
||||
#pragma warning restore CA1305 // Specify IFormatProvider
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.Converters
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using FileLocksmith.Interop;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
public sealed class FileListToDescriptionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var paths = (string[])value;
|
||||
if (paths.Length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string firstPath = paths[0];
|
||||
firstPath = Path.GetFileName(paths[0]);
|
||||
if (string.IsNullOrEmpty(firstPath))
|
||||
{
|
||||
firstPath = Path.GetDirectoryName(paths[0]);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(firstPath))
|
||||
{
|
||||
firstPath = Path.GetPathRoot(paths[0]);
|
||||
}
|
||||
|
||||
if (paths.Length == 1)
|
||||
{
|
||||
return firstPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return firstPath + "; +" + (paths.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.Converters
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Windows.Storage;
|
||||
|
||||
public sealed class PidToIconConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var y = FileLocksmith.Interop.NativeMethods.PidToFullPath((uint)value);
|
||||
Icon icon = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(y))
|
||||
{
|
||||
icon = Icon.ExtractAssociatedIcon(y);
|
||||
}
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
Bitmap bitmap = icon.ToBitmap();
|
||||
BitmapImage bitmapImage = new BitmapImage();
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
|
||||
stream.Position = 0;
|
||||
bitmapImage.SetSource(stream.AsRandomAccessStream());
|
||||
}
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BitmapImage();
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.Converters
|
||||
{
|
||||
using System;
|
||||
using FileLocksmith.Interop;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
public sealed class PidToUserConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return NativeMethods.PidToUser((uint)value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>PowerToys.FileLocksmith</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys File Locksmith</AssemblyDescription>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\modules\FileLocksmith</OutputPath>
|
||||
<RootNamespace>PowerToys.FileLocksmithUI</RootNamespace>
|
||||
<AssemblyName>PowerToys.FileLocksmithUI</AssemblyName>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>0436</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Views\MainPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Needed for CommunityToolkit.Labs.WinUI.SettingsControls. -->
|
||||
<PropertyGroup>
|
||||
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.SettingsControls" Version="0.0.2" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.5" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22000.194" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
|
||||
<PackageReference Include="WinUIEx" Version="1.8.0" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||
package has not yet been restored -->
|
||||
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnablePreviewMsixTooling)'=='true'">
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\FileLocksmithLibInterop\FileLocksmithLibInterop.vcxproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
76
src/modules/FileLocksmith/FileLocksmithUI/Helpers/Logger.cs
Normal file
76
src/modules/FileLocksmith/FileLocksmithUI/Helpers/Logger.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace FileLocksmithUI.Helpers
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly string ApplicationLogPath = Path.Combine(interop.Constants.AppDataPath(), "File Locksmith\\FileLocksmithUI\\Logs");
|
||||
|
||||
static Logger()
|
||||
{
|
||||
if (!Directory.Exists(ApplicationLogPath))
|
||||
{
|
||||
Directory.CreateDirectory(ApplicationLogPath);
|
||||
}
|
||||
|
||||
// Using InvariantCulture since this is used for a log file name
|
||||
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
|
||||
Trace.AutoFlush = true;
|
||||
}
|
||||
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log(message, "ERROR");
|
||||
}
|
||||
|
||||
public static void LogError(string message, Exception ex)
|
||||
{
|
||||
Log(
|
||||
message + Environment.NewLine +
|
||||
ex?.Message + Environment.NewLine +
|
||||
"Inner exception: " + Environment.NewLine +
|
||||
ex?.InnerException?.Message + Environment.NewLine +
|
||||
"Stack trace: " + Environment.NewLine +
|
||||
ex?.StackTrace,
|
||||
"ERROR");
|
||||
}
|
||||
|
||||
public static void LogWarning(string message)
|
||||
{
|
||||
Log(message, "WARNING");
|
||||
}
|
||||
|
||||
public static void LogInfo(string message)
|
||||
{
|
||||
Log(message, "INFO");
|
||||
}
|
||||
|
||||
private static void Log(string message, string type)
|
||||
{
|
||||
Trace.WriteLine(type + ": " + DateTime.Now.TimeOfDay);
|
||||
Trace.Indent();
|
||||
Trace.WriteLine(GetCallerInfo());
|
||||
Trace.WriteLine(message);
|
||||
Trace.Unindent();
|
||||
}
|
||||
|
||||
private static string GetCallerInfo()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace();
|
||||
|
||||
var methodName = stackTrace.GetFrame(3)?.GetMethod();
|
||||
var className = methodName?.DeclaringType.Name;
|
||||
return "[Method]: " + methodName?.Name + " [Class]: " + className;
|
||||
}
|
||||
}
|
||||
}
|
44
src/modules/FileLocksmith/FileLocksmithUI/MainWindow.xaml
Normal file
44
src/modules/FileLocksmith/FileLocksmithUI/MainWindow.xaml
Normal file
@@ -0,0 +1,44 @@
|
||||
<winuiex:WindowEx
|
||||
x:Class="FileLocksmithUI.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
xmlns:converters1="using:PowerToys.FileLocksmithUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interop="using:FileLocksmith.Interop"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="using:PowerToys.FileLocksmithUI.Views"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
x:Uid="AppTitle"
|
||||
Width="680"
|
||||
MinWidth="480"
|
||||
MinHeight="320"
|
||||
IsShownInSwitchers="True"
|
||||
IsTitleBarVisible="True"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.Backdrop>
|
||||
<winuiex:MicaSystemBackdrop />
|
||||
</winuiex:WindowEx.Backdrop>
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="titleBar">
|
||||
<StackPanel
|
||||
Margin="16,8,8,8"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock FontFamily="{ThemeResource SymbolThemeFontFamily}" Text="" />
|
||||
<TextBlock
|
||||
x:Uid="AppTitleText"
|
||||
Margin="12,0,0,0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<views:MainPage x:Name="mainPage" Grid.Row="1" />
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
49
src/modules/FileLocksmith/FileLocksmithUI/MainWindow.xaml.cs
Normal file
49
src/modules/FileLocksmith/FileLocksmithUI/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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 ManagedCommon;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using WinUIEx;
|
||||
|
||||
namespace FileLocksmithUI
|
||||
{
|
||||
public sealed partial class MainWindow : WindowEx, IDisposable
|
||||
{
|
||||
public MainWindow(bool isElevated)
|
||||
{
|
||||
InitializeComponent();
|
||||
mainPage.ViewModel.IsElevated = isElevated;
|
||||
SetTitleBar();
|
||||
}
|
||||
|
||||
private void SetTitleBar()
|
||||
{
|
||||
if (AppWindowTitleBar.IsCustomizationSupported())
|
||||
{
|
||||
AppWindow window = this.GetAppWindow();
|
||||
window.TitleBar.ExtendsContentIntoTitleBar = true;
|
||||
window.TitleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
SetTitleBar(titleBar);
|
||||
}
|
||||
else
|
||||
{
|
||||
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
ThemeHelpers.SetImmersiveDarkMode(hWnd, ThemeHelpers.GetAppTheme() == AppTheme.Dark);
|
||||
titleBar.Visibility = Visibility.Collapsed;
|
||||
|
||||
// Set window icon
|
||||
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
|
||||
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
|
||||
appWindow.SetIcon("icon.ico");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||
<PublishDir>$(PowerToysRoot)\$(Platform)\$(Configuration)\modules\FileLocksmith</PublishDir>
|
||||
<RuntimeIdentifier>win10-$(Platform)</RuntimeIdentifier>
|
||||
<SelfContained>false</SelfContained>
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
<PublishReadyToRun>False</PublishReadyToRun>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AppTitle.Title" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
</data>
|
||||
<data name="AppTitleText.Text" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
</data>
|
||||
<data name="EmptyListDescription.Text" xml:space="preserve">
|
||||
<value>No results</value>
|
||||
</data>
|
||||
<data name="EndTask.Text" xml:space="preserve">
|
||||
<value>End task</value>
|
||||
</data>
|
||||
<data name="Files.Text" xml:space="preserve">
|
||||
<value>Files</value>
|
||||
</data>
|
||||
<data name="PathsTooltipDescription.Text" xml:space="preserve">
|
||||
<value>Click to see the entire list of paths.</value>
|
||||
<comment>Paths as in file paths that were selected for the utility to check.</comment>
|
||||
</data>
|
||||
<data name="SelectedFilesListDialog.Title" xml:space="preserve">
|
||||
<value>Selected file paths</value>
|
||||
<comment>Paths as in file paths that were selected for the utility to check.</comment>
|
||||
</data>
|
||||
<data name="SelectedFilesListDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
<comment>As in, close a dialog prompt.</comment>
|
||||
</data>
|
||||
<data name="NoFilesSelected.Text" xml:space="preserve">
|
||||
<value>No files selected</value>
|
||||
</data>
|
||||
<data name="ProcessID.Header" xml:space="preserve">
|
||||
<value>Process ID</value>
|
||||
</data>
|
||||
<data name="Reload.Text" xml:space="preserve">
|
||||
<value>Reload</value>
|
||||
</data>
|
||||
<data name="RestartAsAdmin.Text" xml:space="preserve">
|
||||
<value>Restart as administrator</value>
|
||||
</data>
|
||||
<data name="User.Header" xml:space="preserve">
|
||||
<value>User</value>
|
||||
</data>
|
||||
</root>
|
@@ -0,0 +1,184 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.ViewModels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FileLocksmith.Interop;
|
||||
using global::FileLocksmithUI;
|
||||
using global::FileLocksmithUI.Helpers;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
#pragma warning disable CA1708 // Identifiers should differ by more than case
|
||||
public partial class MainViewModel : ObservableObject, IDisposable
|
||||
#pragma warning restore CA1708 // Identifiers should differ by more than case
|
||||
{
|
||||
public IAsyncRelayCommand LoadProcessesCommand { get; }
|
||||
|
||||
private bool _isLoading;
|
||||
private bool _isElevated;
|
||||
private string[] paths;
|
||||
private bool _disposed;
|
||||
private CancellationTokenSource _cancelProcessWatching;
|
||||
|
||||
public ObservableCollection<ProcessResult> Processes { get; } = new ();
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isLoading;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_isLoading = value;
|
||||
OnPropertyChanged(nameof(IsLoading));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsElevated
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isElevated;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_isElevated = value;
|
||||
OnPropertyChanged(nameof(IsElevated));
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Paths
|
||||
{
|
||||
get => paths;
|
||||
set
|
||||
{
|
||||
paths = value;
|
||||
OnPropertyChanged(nameof(Paths));
|
||||
}
|
||||
}
|
||||
|
||||
public string PathsToString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Join("\n", paths);
|
||||
}
|
||||
}
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
paths = NativeMethods.ReadPathsFromFile();
|
||||
Logger.LogInfo($"Starting FileLocksmith with {paths.Length} files selected.");
|
||||
LoadProcessesCommand = new AsyncRelayCommand(LoadProcessesAsync);
|
||||
}
|
||||
|
||||
private async Task LoadProcessesAsync()
|
||||
{
|
||||
IsLoading = true;
|
||||
Processes.Clear();
|
||||
|
||||
if (_cancelProcessWatching is not null)
|
||||
{
|
||||
_cancelProcessWatching.Cancel();
|
||||
}
|
||||
|
||||
_cancelProcessWatching = new CancellationTokenSource();
|
||||
|
||||
foreach (ProcessResult p in await FindProcesses(paths))
|
||||
{
|
||||
Processes.Add(p);
|
||||
WatchProcess(p, _cancelProcessWatching.Token);
|
||||
}
|
||||
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
private async Task<List<ProcessResult>> FindProcesses(string[] paths)
|
||||
{
|
||||
var results = new List<ProcessResult>();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
results = NativeMethods.FindProcessesRecursive(paths).ToList();
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
private async void WatchProcess(ProcessResult process, CancellationToken token)
|
||||
{
|
||||
Process handle = Process.GetProcessById((int)process.pid);
|
||||
try
|
||||
{
|
||||
await handle.WaitForExitAsync(token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// Nothing to do, normal operation
|
||||
}
|
||||
|
||||
if (handle.HasExited)
|
||||
{
|
||||
Processes.Remove(process);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void EndTask(ProcessResult selectedProcess)
|
||||
{
|
||||
Process handle = Process.GetProcessById((int)selectedProcess.pid);
|
||||
try
|
||||
{
|
||||
handle.Kill();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogError($"Couldn't kill process {selectedProcess.name} with PID {selectedProcess.pid}.");
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void RestartElevated()
|
||||
{
|
||||
if (NativeMethods.StartAsElevated(paths))
|
||||
{
|
||||
// TODO gentler exit
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO report error?
|
||||
Logger.LogError($"Couldn't restart as elevated.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
206
src/modules/FileLocksmith/FileLocksmithUI/Views/MainPage.xaml
Normal file
206
src/modules/FileLocksmith/FileLocksmithUI/Views/MainPage.xaml
Normal file
@@ -0,0 +1,206 @@
|
||||
<Page
|
||||
x:Class="PowerToys.FileLocksmithUI.Views.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:PowerToys.FileLocksmithUI.Converters"
|
||||
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:interop="using:FileLocksmith.Interop"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:local="using:PowerToys.FileLocksmithUI.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkitConverters="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<toolkitConverters:BoolToVisibilityConverter
|
||||
x:Key="boolToVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
TrueValue="Collapsed" />
|
||||
|
||||
<toolkitConverters:DoubleToVisibilityConverter
|
||||
x:Key="doubleToVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
GreaterThan="0"
|
||||
TrueValue="Collapsed" />
|
||||
<converters:FileCountConverter x:Key="fileCountConverter" />
|
||||
<converters:PidToIconConverter x:Key="pidToIconConverter" />
|
||||
<converters:PidToUserConverter x:Key="pidToUserConverter" />
|
||||
<converters:FileListToDescriptionConverter x:Key="fileListToDescriptionConverter" />
|
||||
</Page.Resources>
|
||||
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<core:EventTriggerBehavior EventName="Loaded">
|
||||
<core:InvokeCommandAction Command="{x:Bind ViewModel.LoadProcessesCommand}" />
|
||||
</core:EventTriggerBehavior>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="48" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Padding="18,0,18,4" VerticalAlignment="Bottom">
|
||||
<!--<TextBlock Margin="0,2,0,0" Text="Current proccesses:" Style="{ThemeResource BodyStrongTextBlockStyle}"/>-->
|
||||
<Button Content="{x:Bind ViewModel.Paths, Converter={StaticResource fileListToDescriptionConverter}}" Click="ShowSelectedPathsButton_Click">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<TextBlock Margin="0,8,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{TemplateBinding Content}" >
|
||||
</TextBlock>
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="PathsTooltipDescription" TextWrapping="WrapWholeWords"/>
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Orientation="Horizontal"
|
||||
Spacing="6">
|
||||
<Button
|
||||
Padding="0"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding LoadProcessesCommand}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<FontIcon
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Glyph="" />
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="Reload" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="RestartAsAdminBtn"
|
||||
Padding="0"
|
||||
Command="{Binding RestartElevatedCommand}"
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
Visibility="{x:Bind ViewModel.IsElevated, Converter={StaticResource boolToVisibilityConverter}}">
|
||||
<FontIcon
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Glyph="" />
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="RestartAsAdmin" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource boolToVisibilityConverter}, Mode=OneWay}">
|
||||
<ListView
|
||||
x:Name="ProcessesListView"
|
||||
Grid.Row="1"
|
||||
ItemsSource="{x:Bind ViewModel.Processes}"
|
||||
IncrementalLoadingThreshold="10"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="interop:ProcessResult">
|
||||
<labs:SettingsExpander IsExpanded="{Binding isExpanded}" Margin="0,3,0,0">
|
||||
<labs:SettingsExpander.Header>
|
||||
<!-- We can't use the HeaderIcon because it only support a BitmapIcon, which only supports UriSource - not a direct BitmapImage -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="2,0,24,0"
|
||||
Source="{x:Bind pid, Converter={StaticResource pidToIconConverter}}" />
|
||||
<TextBlock IsTextSelectionEnabled="True" Text="{x:Bind name}" />
|
||||
</StackPanel>
|
||||
</labs:SettingsExpander.Header>
|
||||
<labs:SettingsExpander.Content>
|
||||
<Button Command="{Binding Path=DataContext.EndTaskCommand, ElementName=ProcessesListView}" CommandParameter="{Binding}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<FontIcon
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="14"
|
||||
Glyph="" />
|
||||
<TextBlock x:Uid="EndTask" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</labs:SettingsExpander.Content>
|
||||
<labs:SettingsExpander.Items>
|
||||
<labs:SettingsCard x:Uid="ProcessID">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind pid}" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard x:Uid="User">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind pid, Converter={StaticResource pidToUserConverter}}" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard ContentAlignment="Vertical">
|
||||
<labs:SettingsCard.Header>
|
||||
<TextBlock>
|
||||
<Run x:Uid="Files" />
|
||||
<Run Text="(" /><Run Text="{x:Bind files, Converter={StaticResource fileCountConverter}}" /><Run Text=")" />
|
||||
</TextBlock>
|
||||
</labs:SettingsCard.Header>
|
||||
<ListView
|
||||
Margin="-16,0,0,0"
|
||||
ItemsSource="{x:Bind files}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="x:String">
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap"
|
||||
ToolTipService.ToolTip="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</labs:SettingsCard>
|
||||
</labs:SettingsExpander.Items>
|
||||
</labs:SettingsExpander>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Vertical"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind ViewModel.Processes.Count, Mode=OneWay, Converter={StaticResource doubleToVisibilityConverter}}">
|
||||
<Button HorizontalAlignment="Center" Command="{Binding LoadProcessesCommand}" >
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<FontIcon FontSize="32" Glyph="" />
|
||||
</ControlTemplate>
|
||||
</Button.Template>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="Reload" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<TextBlock x:Uid="EmptyListDescription" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<ProgressRing
|
||||
Width="48"
|
||||
Height="48"
|
||||
IsActive="{x:Bind ViewModel.IsLoading, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<ContentDialog
|
||||
x:Name="SelectedFilesListDialog"
|
||||
x:Uid="SelectedFilesListDialog"
|
||||
>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" HorizontalScrollMode="Auto" VerticalScrollBarVisibility="Auto" VerticalScrollMode="Auto">
|
||||
<TextBlock Text="{x:Bind ViewModel.PathsToString, Mode=OneWay}"/>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
@@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
namespace PowerToys.FileLocksmithUI.Views
|
||||
{
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using PowerToys.FileLocksmithUI.ViewModels;
|
||||
|
||||
public sealed partial class MainPage : Page
|
||||
{
|
||||
public MainViewModel ViewModel { get; private set; }
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = new MainViewModel();
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private async void ShowSelectedPathsButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
await SelectedFilesListDialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/modules/FileLocksmith/FileLocksmithUI/icon.ico
Normal file
BIN
src/modules/FileLocksmith/FileLocksmithUI/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@@ -155,6 +155,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
L"modules/MouseUtils/PowerToys.MousePointerCrosshairs.dll",
|
||||
L"modules/PowerAccent/PowerToys.PowerAccentModuleInterface.dll",
|
||||
L"modules/PowerOCR/PowerToys.PowerOCRModuleInterface.dll",
|
||||
L"modules/FileLocksmith/PowerToys.FileLocksmithExt.dll",
|
||||
L"modules/MeasureTool/PowerToys.MeasureToolModuleInterface.dll",
|
||||
L"modules/Hosts/PowerToys.HostsModuleInterface.dll",
|
||||
};
|
||||
|
@@ -303,6 +303,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
}
|
||||
}
|
||||
|
||||
private bool fileLocksmith = true;
|
||||
|
||||
[JsonPropertyName("File Locksmith")]
|
||||
public bool FileLocksmith
|
||||
{
|
||||
get => fileLocksmith;
|
||||
set
|
||||
{
|
||||
if (fileLocksmith != value)
|
||||
{
|
||||
LogTelemetryEvent(value);
|
||||
fileLocksmith = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
|
@@ -118,6 +118,7 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "Awake": StartupPage = typeof(Views.AwakePage); break;
|
||||
case "ColorPicker": StartupPage = typeof(Views.ColorPickerPage); break;
|
||||
case "FancyZones": StartupPage = typeof(Views.FancyZonesPage); break;
|
||||
case "FileLocksmith": StartupPage = typeof(Views.FileLocksmithPage); break;
|
||||
case "Run": StartupPage = typeof(Views.PowerLauncherPage); break;
|
||||
case "ImageResizer": StartupPage = typeof(Views.ImageResizerPage); break;
|
||||
case "KBM": StartupPage = typeof(Views.KeyboardManagerPage); break;
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
src/settings-ui/Settings.UI/Assets/Modules/FileLocksmith.png
Normal file
BIN
src/settings-ui/Settings.UI/Assets/Modules/FileLocksmith.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 419 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
@@ -11,6 +11,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
|
||||
Awake,
|
||||
ColorPicker,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
FileExplorer,
|
||||
ImageResizer,
|
||||
KBM,
|
||||
|
@@ -0,0 +1,37 @@
|
||||
<Page x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeFileLocksmith"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
mc:Ignorable="d">
|
||||
<controls:OOBEPageControl x:Uid="Oobe_FileLocksmith"
|
||||
HeroImage="ms-appx:///Assets/Modules/OOBE/FileLocksmith.gif">
|
||||
|
||||
<controls:OOBEPageControl.PageContent>
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<TextBlock x:Uid="Oobe_HowToUse"
|
||||
Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
|
||||
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_FileLocksmith_HowToUse" />
|
||||
|
||||
<TextBlock x:Uid="Oobe_TipsAndTricks"
|
||||
Style="{ThemeResource OobeSubtitleStyle}"/>
|
||||
|
||||
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_FileLocksmith_TipsAndTricks" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
|
||||
<Button x:Uid="OOBE_Settings"
|
||||
Click="SettingsLaunchButton_Click"/>
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_FileLocksmith" Style="{StaticResource TextButtonStyle}">
|
||||
<TextBlock x:Uid="LearnMore_FileLocksmith"
|
||||
TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:OOBEPageControl.PageContent>
|
||||
</controls:OOBEPageControl>
|
||||
</Page>
|
@@ -0,0 +1,47 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.OOBE.Enums;
|
||||
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class OobeFileLocksmith : Page
|
||||
{
|
||||
public OobePowerToysModule ViewModel { get; set; }
|
||||
|
||||
public OobeFileLocksmith()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.FileLocksmith]);
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (OobeShellPage.OpenMainWindowCallback != null)
|
||||
{
|
||||
OobeShellPage.OpenMainWindowCallback(typeof(FileLocksmithPage));
|
||||
}
|
||||
|
||||
ViewModel.LogOpeningSettingsEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogOpeningModuleEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogClosingModuleEvent();
|
||||
}
|
||||
}
|
||||
}
|
@@ -48,6 +48,11 @@
|
||||
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem x:Uid="Shell_FileLocksmith" Tag="FileLocksmith">
|
||||
<NavigationViewItem.Icon>
|
||||
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFileLocksmith.png" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem x:Uid="Shell_PowerPreview" Tag="FileExplorer">
|
||||
<NavigationViewItem.Icon>
|
||||
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFileExplorerPreview.png" />
|
||||
|
@@ -64,7 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
Modules.Insert((int)PowerToysModules.AlwaysOnTop, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "AlwaysOnTop",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.Awake, new OobePowerToysModule()
|
||||
{
|
||||
@@ -81,6 +81,11 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
ModuleName = "FancyZones",
|
||||
IsNew = false,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.FileLocksmith, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "FileLocksmith",
|
||||
IsNew = true,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.FileExplorer, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "FileExplorer",
|
||||
@@ -99,7 +104,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
Modules.Insert((int)PowerToysModules.MouseUtils, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "MouseUtils",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.PowerRename, new OobePowerToysModule()
|
||||
{
|
||||
@@ -114,7 +119,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
Modules.Insert((int)PowerToysModules.QuickAccent, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "QuickAccent",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
Modules.Insert((int)PowerToysModules.ShortcutGuide, new OobePowerToysModule()
|
||||
{
|
||||
@@ -124,19 +129,19 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
Modules.Insert((int)PowerToysModules.TextExtractor, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "TextExtractor",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.VideoConference, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "VideoConference",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.MeasureTool, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "MeasureTool",
|
||||
IsNew = true,
|
||||
IsNew = false,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.Hosts, new OobePowerToysModule()
|
||||
@@ -187,6 +192,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
|
||||
case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
|
||||
case "FancyZones": NavigationFrame.Navigate(typeof(OobeFancyZones)); break;
|
||||
case "FileLocksmith": NavigationFrame.Navigate(typeof(OobeFileLocksmith)); break;
|
||||
case "Run": NavigationFrame.Navigate(typeof(OobeRun)); break;
|
||||
case "ImageResizer": NavigationFrame.Navigate(typeof(OobeImageResizer)); break;
|
||||
case "KBM": NavigationFrame.Navigate(typeof(OobeKBM)); break;
|
||||
|
@@ -1469,6 +1469,9 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<data name="Oobe_FancyZones.Description" xml:space="preserve">
|
||||
<value>FancyZones is a window manager that makes it easy to create complex window layouts and quickly position windows into those layouts.</value>
|
||||
</data>
|
||||
<data name="Oobe_FileLocksmith.Description" xml:space="preserve">
|
||||
<value>File Locksmith lists which processes are using the selected files or directories and allows closing those processes.</value>
|
||||
</data>
|
||||
<data name="Oobe_FileExplorer.Description" xml:space="preserve">
|
||||
<value>PowerToys introduces add-ons to the Windows File Explorer that will enable files like Markdown (.md), PDF (.pdf), SVG (.svg), STL (.stl), G-code (.gcode) and developer files to be viewed in the preview pane. It introduces File Explorer thumbnail support for a number of these file types as well.</value>
|
||||
</data>
|
||||
@@ -1523,6 +1526,12 @@ Take a moment to preview the various utilities listed or view our comprehensive
|
||||
<data name="Oobe_FancyZones_TipsAndTricks.Text" xml:space="preserve">
|
||||
<value>Snap a window to multiple zones by holding the **Ctrl** key (while also holding **Shift**) when dragging a window.</value>
|
||||
</data>
|
||||
<data name="Oobe_FileLocksmith_HowToUse.Text" xml:space="preserve">
|
||||
<value>In File Explorer, **right-clicking one or more selected files** and **clicking on "What's using this file?"** from the context menu.</value>
|
||||
</data>
|
||||
<data name="Oobe_FileLocksmith_TipsAndTricks.Text" xml:space="preserve">
|
||||
<value>Press the Restart Elevated button from the File Locksmith UI to also get information on elevated processes that might be using the files.</value>
|
||||
</data>
|
||||
<data name="Oobe_FileExplorer_HowToEnable.Text" xml:space="preserve">
|
||||
<value>Open File Explorer, **select the View tab** in the File Explorer ribbon, then **select Preview Pane**.
|
||||
From there, simply click on one of the supported files in the File Explorer and observe the content on the preview pane!</value>
|
||||
@@ -1596,6 +1605,9 @@ From there, simply click on one of the supported files in the File Explorer and
|
||||
<value>FancyZones</value>
|
||||
<comment>Do not localize this string</comment>
|
||||
</data>
|
||||
<data name="Oobe_FileLocksmith.Title" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
</data>
|
||||
<data name="Oobe_ImageResizer.Title" xml:space="preserve">
|
||||
<value>Image Resizer</value>
|
||||
<comment>Do not localize this string</comment>
|
||||
@@ -1807,6 +1819,9 @@ From there, simply click on one of the supported files in the File Explorer and
|
||||
<value>Learn more about FancyZones</value>
|
||||
<comment>FancyZones is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="LearnMore_FileLocksmith.Text" xml:space="preserve">
|
||||
<value>Learn more about File Locksmith</value>
|
||||
</data>
|
||||
<data name="LearnMore_ImageResizer.Text" xml:space="preserve">
|
||||
<value>Learn more about Image Resizer</value>
|
||||
<comment>Image Resizer is a product name, do not loc</comment>
|
||||
@@ -2646,6 +2661,20 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="Hosts_Toggle_LaunchAdministrator.Header" xml:space="preserve">
|
||||
<value>Launch as administrator</value>
|
||||
</data>
|
||||
<data name="FileLocksmith.ModuleDescription" xml:space="preserve">
|
||||
<value>A Windows shell extension to find out which processes are using the selected files and directories.</value>
|
||||
</data>
|
||||
<data name="FileLocksmith.ModuleTitle" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
</data>
|
||||
<data name="Shell_FileLocksmith.Content" xml:space="preserve">
|
||||
<value>File Locksmith</value>
|
||||
<comment>Product name: Navigation view item name for FileLocksmith</comment>
|
||||
</data>
|
||||
<data name="FileLocksmith_Enable_FileLocksmith.Header" xml:space="preserve">
|
||||
<value>Enable File Locksmith</value>
|
||||
<comment>File Locksmith is the name of the utility</comment>
|
||||
</data>
|
||||
<data name="GPO_IsSettingForced.Title" xml:space="preserve">
|
||||
<value>The systems administrator is forcing this setting.</value>
|
||||
</data>
|
||||
|
@@ -0,0 +1,81 @@
|
||||
// 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 global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class FileLocksmithViewModel : Observable
|
||||
{
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
public FileLocksmithViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
||||
{
|
||||
// To obtain the general settings configurations of PowerToys Settings.
|
||||
if (settingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settingsRepository));
|
||||
}
|
||||
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFileLocksmithEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
_isFileLocksmithEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isFileLocksmithEnabled = GeneralSettingsConfig.Enabled.FileLocksmith;
|
||||
}
|
||||
|
||||
// set the callback functions value to hangle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
}
|
||||
|
||||
public bool IsFileLocksmithEnabled
|
||||
{
|
||||
get => _isFileLocksmithEnabled;
|
||||
set
|
||||
{
|
||||
if (_enabledStateIsGPOConfigured)
|
||||
{
|
||||
// If it's GPO configured, shouldn't be able to change this state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isFileLocksmithEnabled != value)
|
||||
{
|
||||
_isFileLocksmithEnabled = value;
|
||||
|
||||
GeneralSettingsConfig.Enabled.FileLocksmith = value;
|
||||
OnPropertyChanged(nameof(IsFileLocksmithEnabled));
|
||||
|
||||
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
SendConfigMSG(outgoing.ToString());
|
||||
|
||||
// TODO: Implement when this module has properties.
|
||||
// NotifyPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
private bool _isFileLocksmithEnabled;
|
||||
}
|
||||
}
|
42
src/settings-ui/Settings.UI/Views/FileLocksmithPage.xaml
Normal file
42
src/settings-ui/Settings.UI/Views/FileLocksmithPage.xaml
Normal file
@@ -0,0 +1,42 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Views.FileLocksmithPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
AutomationProperties.LandmarkType="Main">
|
||||
|
||||
<Page.Resources>
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
||||
</Page.Resources>
|
||||
|
||||
<controls:SettingsPageControl x:Uid="FileLocksmith"
|
||||
ModuleImageSource="ms-appx:///Assets/Modules/FileLocksmith.png">
|
||||
<controls:SettingsPageControl.ModuleContent>
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<controls:Setting x:Uid="FileLocksmith_Enable_FileLocksmith" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
|
||||
<controls:Setting.Icon>
|
||||
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerToys.png" ShowAsMonochrome="False" />
|
||||
</controls:Setting.Icon>
|
||||
<controls:Setting.ActionContent>
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFileLocksmithEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
<InfoBar x:Uid="GPO_IsSettingForced"
|
||||
Severity="Informational"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}" />
|
||||
|
||||
</StackPanel>
|
||||
</controls:SettingsPageControl.ModuleContent>
|
||||
<controls:SettingsPageControl.PrimaryLinks>
|
||||
<controls:PageLink x:Uid="LearnMore_FileLocksmith" Link="https://aka.ms/PowerToysOverview_FileLocksmith"/>
|
||||
</controls:SettingsPageControl.PrimaryLinks>
|
||||
</controls:SettingsPageControl>
|
||||
</Page>
|
23
src/settings-ui/Settings.UI/Views/FileLocksmithPage.xaml.cs
Normal file
23
src/settings-ui/Settings.UI/Views/FileLocksmithPage.xaml.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
public sealed partial class FileLocksmithPage : Page
|
||||
{
|
||||
private FileLocksmithViewModel ViewModel { get; set; }
|
||||
|
||||
public FileLocksmithPage()
|
||||
{
|
||||
var settingsUtils = new SettingsUtils();
|
||||
ViewModel = new FileLocksmithViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@@ -70,6 +70,12 @@
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
|
||||
<NavigationViewItem x:Uid="Shell_FileLocksmith" helpers:NavHelper.NavigateTo="views:FileLocksmithPage">
|
||||
<NavigationViewItem.Icon>
|
||||
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFileLocksmith.png" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
|
||||
<NavigationViewItem x:Uid="Shell_PowerPreview" helpers:NavHelper.NavigateTo="views:PowerPreviewPage">
|
||||
<NavigationViewItem.Icon>
|
||||
<BitmapIcon ShowAsMonochrome="False" UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFileExplorerPreview.png" />
|
||||
|
@@ -9,6 +9,7 @@ std::vector<std::wstring> processes =
|
||||
L"PowerToys.Awake.exe",
|
||||
L"PowerToys.FancyZonesEditor.exe",
|
||||
L"PowerToys.FancyZones.exe",
|
||||
L"PowerToys.FileLocksmithUI.exe",
|
||||
L"PowerToys.KeyboardManagerEngine.exe",
|
||||
L"PowerToys.KeyboardManagerEditor.exe",
|
||||
L"PowerToys.PowerAccent.exe",
|
||||
|
@@ -32,6 +32,7 @@ void ReportGPOValues(const std::filesystem::path& tmpDir)
|
||||
report << "getConfiguredAwakeEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredAwakeEnabledValue()) << std::endl;
|
||||
report << "getConfiguredColorPickerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredColorPickerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFancyZonesEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFancyZonesEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFileLocksmithEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFileLocksmithEnabledValue()) << std::endl;
|
||||
report << "getConfiguredSvgPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredSvgPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMarkdownPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMarkdownPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMonacoPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMonacoPreviewEnabledValue()) << std::endl;
|
||||
|
Reference in New Issue
Block a user