diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c4efe2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,261 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fa3c8e1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# Registry Editor
+
+Registry Editor is a small utility that will help you finding specific registries with a specific search criteria.
+All the results will be showen in one place and you can then delete the selected registries or right click on one of the results will open
+the official Windows regedit in the location of the selected registry. NOTE: When deleting registries, a backup will automatically be
+created on your desktop.
+
+
+## Motivation
+
+If you're here, I guess you already aware that the official build in registry editor(regedit) in Windows allows you to only `Find Next`
+and searching for `Keys`, `Values` and `Data`.
+That sometimes can be very time consuming when you look for specific registry, therefore writing a quick gui application to add all
+these results in one place wouldn't take much time so I can just let it scan through with more advanced filters and do with the results
+whatever comes in mind, i.e deleting found results, saving, jumping directly to the official registry location etc...
+I also have to give credit to my brother that asked for a simple script to scan through the registry on a specific criteria, which brought
+me to the idea of writing a gui application that will be much easier to maintain and extend if needed.
+
+Another useful situation is when you install a new software and you want to look for any registers that the software installed on your
+machine, which can be easily tracked down by scanning the whole registry and finding their existing locations.
+
+## Pictures
+
+![alt text][img_main]
+
+![alt text][img_edit]
+
+![alt text][img_network]
+
+[img_main]: pictures/mainwindow.png
+[img_edit]: pictures/findwindow.png
+[img_network]: pictures/networkwindow.png
\ No newline at end of file
diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000..9d4e0a4
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,21 @@
+@echo off
+
+
+set BUILD_TYPE=%1
+
+if not "%BUILD_TYPE%" == "Debug" (
+ echo Building in Release mode.
+ set BUILD_TYPE=Release
+) else (
+ echo Building in Debug mode.
+)
+
+WHERE msbuild
+if %ERRORLEVEL% NEQ 0 (
+ echo ### ERROR: Run Developer Command Prompt for VS and try again. ###
+) else (
+ cd /d %~dp0
+ cd src
+ msbuild /t:Rebuild /m /p:Configuration=%BUILD_TYPE% /p:BuildInParallel=true /p:Platform="Any CPU"
+ cd ..
+)
\ No newline at end of file
diff --git a/pictures/findwindow.png b/pictures/findwindow.png
new file mode 100644
index 0000000..be0ba38
Binary files /dev/null and b/pictures/findwindow.png differ
diff --git a/pictures/mainwindow.png b/pictures/mainwindow.png
new file mode 100644
index 0000000..a53edd0
Binary files /dev/null and b/pictures/mainwindow.png differ
diff --git a/pictures/networkwindow.png b/pictures/networkwindow.png
new file mode 100644
index 0000000..e385838
Binary files /dev/null and b/pictures/networkwindow.png differ
diff --git a/src/Windows.RegistryEditor.sln b/src/Windows.RegistryEditor.sln
new file mode 100644
index 0000000..4fe0cbd
--- /dev/null
+++ b/src/Windows.RegistryEditor.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2047
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryEditor", "Windows.RegistryEditor\RegistryEditor.csproj", "{E76E123C-04A1-488F-AA28-A5FF6FE236E5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E76E123C-04A1-488F-AA28-A5FF6FE236E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E76E123C-04A1-488F-AA28-A5FF6FE236E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E76E123C-04A1-488F-AA28-A5FF6FE236E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E76E123C-04A1-488F-AA28-A5FF6FE236E5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F377F101-355E-4E65-B5F2-8A0F71D97308}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Windows.RegistryEditor/App.config b/src/Windows.RegistryEditor/App.config
new file mode 100644
index 0000000..016d28f
--- /dev/null
+++ b/src/Windows.RegistryEditor/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/FindResultsArgs.cs b/src/Windows.RegistryEditor/Events/FindResultsArgs.cs
new file mode 100644
index 0000000..ba5b301
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/FindResultsArgs.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace Windows.RegistryEditor.Events
+{
+ public class FindResultsArgs : EventArgs
+ {
+ public List Matches { get; set; }
+
+ public FindResultsArgs(List matches)
+ {
+ Matches = matches;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/FindSingleResultArgs.cs b/src/Windows.RegistryEditor/Events/FindSingleResultArgs.cs
new file mode 100644
index 0000000..a065079
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/FindSingleResultArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Windows.RegistryEditor.Events
+{
+ public class FindSingleResultArgs : EventArgs
+ {
+ public string Match { get; set; }
+
+ public FindSingleResultArgs(string match)
+ {
+ Match = match;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/ProgressArgs.cs b/src/Windows.RegistryEditor/Events/ProgressArgs.cs
new file mode 100644
index 0000000..ca65603
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/ProgressArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Windows.RegistryEditor.Events
+{
+ public class ProgressArgs : EventArgs
+ {
+ public string Message { get; set; }
+
+ public ProgressArgs(string message)
+ {
+ Message = message;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/ProgressChangedArgs.cs b/src/Windows.RegistryEditor/Events/ProgressChangedArgs.cs
new file mode 100644
index 0000000..b06e56a
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/ProgressChangedArgs.cs
@@ -0,0 +1,12 @@
+namespace Windows.RegistryEditor.Events
+{
+ public class ProgressChangedArgs : ProgressArgs
+ {
+ public string Hive { get; set; }
+ public ProgressChangedArgs(string message, string hive)
+ : base(message)
+ {
+ Hive = hive;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/ProgressFinishedArgs.cs b/src/Windows.RegistryEditor/Events/ProgressFinishedArgs.cs
new file mode 100644
index 0000000..3ffebef
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/ProgressFinishedArgs.cs
@@ -0,0 +1,9 @@
+namespace Windows.RegistryEditor.Events
+{
+ public class ProgressFinishedArgs : ProgressArgs
+ {
+ public ProgressFinishedArgs(string message)
+ : base(message)
+ { }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Events/ProgressStartedArgs.cs b/src/Windows.RegistryEditor/Events/ProgressStartedArgs.cs
new file mode 100644
index 0000000..c6c8198
--- /dev/null
+++ b/src/Windows.RegistryEditor/Events/ProgressStartedArgs.cs
@@ -0,0 +1,12 @@
+namespace Windows.RegistryEditor.Events
+{
+ public class ProgressStartedArgs : ProgressArgs
+ {
+ public string Hive { get; set; }
+ public ProgressStartedArgs(string message, string hive)
+ : base(message)
+ {
+ Hive = hive;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Program.cs b/src/Windows.RegistryEditor/Program.cs
new file mode 100644
index 0000000..226cea4
--- /dev/null
+++ b/src/Windows.RegistryEditor/Program.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Windows.Forms;
+using Windows.RegistryEditor.Views;
+
+namespace Windows.RegistryEditor
+{
+ static class Program
+ {
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainWindow());
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Properties/AssemblyInfo.cs b/src/Windows.RegistryEditor/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8fa65ea
--- /dev/null
+++ b/src/Windows.RegistryEditor/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Registry Editor")]
+[assembly: AssemblyDescription("Windows utility to help scanning and removing unwanted registries.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Registry Editor")]
+[assembly: AssemblyCopyright("Copyright © 2018 Reich")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e76e123c-04a1-488f-aa28-a5ff6fe236e5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.1")]
+[assembly: AssemblyFileVersion("1.0.1")]
diff --git a/src/Windows.RegistryEditor/Properties/Resources.Designer.cs b/src/Windows.RegistryEditor/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..8d07252
--- /dev/null
+++ b/src/Windows.RegistryEditor/Properties/Resources.Designer.cs
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Windows.RegistryEditor.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Windows.RegistryEditor.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+ ///
+ internal static System.Drawing.Icon app {
+ get {
+ object obj = ResourceManager.GetObject("app", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap loader_clock {
+ get {
+ object obj = ResourceManager.GetObject("loader_clock", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Properties/Resources.resx b/src/Windows.RegistryEditor/Properties/Resources.resx
new file mode 100644
index 0000000..e7f7c3b
--- /dev/null
+++ b/src/Windows.RegistryEditor/Properties/Resources.resx
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\loader_clock.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Properties/Settings.Designer.cs b/src/Windows.RegistryEditor/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..1a848bd
--- /dev/null
+++ b/src/Windows.RegistryEditor/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Windows.RegistryEditor.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Properties/Settings.settings b/src/Windows.RegistryEditor/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/src/Windows.RegistryEditor/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/Windows.RegistryEditor/RegistryEditor.csproj b/src/Windows.RegistryEditor/RegistryEditor.csproj
new file mode 100644
index 0000000..9e97f2f
--- /dev/null
+++ b/src/Windows.RegistryEditor/RegistryEditor.csproj
@@ -0,0 +1,132 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E76E123C-04A1-488F-AA28-A5FF6FE236E5}
+ WinExe
+ Windows.RegistryEditor
+ RegistryEditor-v1.0.1
+ v4.7
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ app.manifest
+
+
+ Resources/app.ico
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ NetworkWindow.cs
+
+
+ UserControl
+
+
+ CheckBoxes.cs
+
+
+ Component
+
+
+ UserControl
+
+
+ Loader.cs
+
+
+
+ Form
+
+
+ FindWindow.cs
+
+
+ Form
+
+
+ MainWindow.cs
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Windows.RegistryEditor/Resources/app.ico b/src/Windows.RegistryEditor/Resources/app.ico
new file mode 100644
index 0000000..869c96d
Binary files /dev/null and b/src/Windows.RegistryEditor/Resources/app.ico differ
diff --git a/src/Windows.RegistryEditor/Resources/loader_clock.gif b/src/Windows.RegistryEditor/Resources/loader_clock.gif
new file mode 100644
index 0000000..031c908
Binary files /dev/null and b/src/Windows.RegistryEditor/Resources/loader_clock.gif differ
diff --git a/src/Windows.RegistryEditor/Utils/Native/NativeListViewItem.cs b/src/Windows.RegistryEditor/Utils/Native/NativeListViewItem.cs
new file mode 100644
index 0000000..4816079
--- /dev/null
+++ b/src/Windows.RegistryEditor/Utils/Native/NativeListViewItem.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Windows.RegistryEditor.Utils.Native
+{
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ internal struct NativeListViewItem
+ {
+ public int mask;
+ public int iItem;
+ public int iSubItem;
+ public int state;
+ public int stateMask;
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pszText;
+ public int cchTextMax;
+ public int iImage;
+ public IntPtr lParam;
+ public int iIndent;
+ public int iGroupId;
+ public int cColumns;
+ public IntPtr puColumns;
+ }
+}
diff --git a/src/Windows.RegistryEditor/Utils/Native/NativeMethods.cs b/src/Windows.RegistryEditor/Utils/Native/NativeMethods.cs
new file mode 100644
index 0000000..2428f73
--- /dev/null
+++ b/src/Windows.RegistryEditor/Utils/Native/NativeMethods.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Windows.Forms;
+
+namespace Windows.RegistryEditor.Utils.Native
+{
+ [ComVisible(false), SuppressUnmanagedCodeSecurity]
+ internal sealed class NativeMethods
+ {
+
+ #region --- ListView WinForms Control Stuff ---
+
+ private const int LVM_FIRST = 0x1000;
+ private const int LVM_SETITEMSTATE = LVM_FIRST + 43;
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref NativeListViewItem lvi);
+
+ internal static void SetItemState(ListView listView, int itemIndex, int mask, int value)
+ {
+ NativeListViewItem lvItem = new NativeListViewItem {stateMask = mask, state = value};
+ SendMessage(listView.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem);
+ }
+
+ #endregion #region --- ListView Functions ---
+ }
+}
diff --git a/src/Windows.RegistryEditor/Utils/RegistryUtils.cs b/src/Windows.RegistryEditor/Utils/RegistryUtils.cs
new file mode 100644
index 0000000..0dd471a
--- /dev/null
+++ b/src/Windows.RegistryEditor/Utils/RegistryUtils.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+namespace Windows.RegistryEditor.Utils
+{
+ public static class RegistryUtils
+ {
+ public const string HKCR = "HKEY_CLASSES_ROOT";
+ public const string HKCU = "HKEY_CURRENT_USER";
+ public const string HKLM = "HKEY_LOCAL_MACHINE";
+ public const string HKU = "HKEY_USERS";
+ public const string HKCC = "HKEY_CURRENT_CONFIG";
+
+ public const string SHKCR = "HKCR";
+ public const string SHKCU = "HKCU";
+ public const string SHKLM = "HKLM";
+ public const string SHKU = "HKU";
+ public const string SHKCC = "HKCC";
+
+ public const string REG_SZ = "REG_SZ";
+ public const string REG_EXPAND_SZ = "REG_EXPAND_SZ";
+ public const string REG_MULTI_SZ = "REG_MULTI_SZ";
+ public const string REG_DWORD = "REG_DWORD";
+ public const string REG_QWORD = "REG_QWORD";
+ public const string REG_DWORD_LITTLE_ENDIAN = "REG_DWORD_LITTLE_ENDIAN";
+ public const string REG_QWORD_LITTLE_ENDIAN = "REG_QWORD_LITTLE_ENDIAN";
+ public const string REG_DWORD_BIG_ENDIAN = "REG_DWORD_BIG_ENDIAN";
+ public const string REG_BINARY = "REG_BINARY";
+ public const string REG_NONE = "REG_NONE";
+ public const string REG_LINK = "REG_LINK";
+ public const string REG_RESOURCE_LIST = "REG_RESOURCE_LIST";
+
+ private const string HKEY_REGEDIT = @"HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit";
+
+ public static void OpenRegistryLocation(string path)
+ {
+ string args = $"{HKEY_REGEDIT} /v LastKey /t REG_SZ /d \"{path}\" /f";
+ ProcessStartInfo procInfo = new ProcessStartInfo
+ {
+ FileName = "REG",
+ Arguments = $"ADD {args}",
+ CreateNoWindow = true,
+ UseShellExecute = false
+ };
+
+ Process.Start(procInfo);
+
+ Utility.KillProcess("regedit");
+ Process.Start("regedit.exe");
+ }
+
+ public static void ExportHive(string hivePath, string dstDir)
+ {
+ if (!Directory.Exists(dstDir))
+ Directory.CreateDirectory(dstDir);
+
+ string fileName = Utility.ValidateDirOrFileName(hivePath.Split('\\').Last());
+ string dstFile = Path.Combine(dstDir, fileName + ".reg");
+ ProcessStartInfo procInfo = new ProcessStartInfo()
+ {
+ FileName = "REG",
+ Arguments = $"EXPORT \"{hivePath}\" \"{dstFile}\" /y",
+ CreateNoWindow = true,
+ UseShellExecute = false
+ };
+
+ Process.Start(procInfo);
+ }
+
+ public static void DeleteHive(string hivePath)
+ {
+ ProcessStartInfo procInfo = new ProcessStartInfo()
+ {
+ FileName = "REG",
+ Arguments = $"DELETE \"{hivePath}\" /f",
+ CreateNoWindow = true,
+ UseShellExecute = false
+ };
+
+ Process.Start(procInfo);
+ }
+
+ public static string GetHiveShortcut(string hive)
+ {
+ switch (hive)
+ {
+ case HKCR: return SHKCR;
+ case HKCU: return SHKCU;
+ case HKLM: return SHKLM;
+ case HKU: return SHKU;
+ case HKCC: return SHKCC;
+
+ default:
+ throw new ArgumentException($"[GetHiveShortcut] - Invalid HKEY input -> {hive}");
+ }
+ }
+
+ public static string GetHiveFullName(string hive)
+ {
+ switch (hive)
+ {
+ case SHKCR: return HKCR;
+ case SHKCU: return HKCU;
+ case SHKLM: return HKLM;
+ case SHKU: return HKU;
+ case SHKCC: return HKCC;
+
+ default:
+ throw new ArgumentException($"[GetHiveFullName] - Invalid HKEY input -> {hive}");
+ }
+ }
+
+ public static string GetRemoteShortcut(string hive)
+ {
+ return GetHiveShortcut(hive.Split('\\').Last());
+ }
+
+ public static string GetRemoteHiveFullName(string hive)
+ {
+ return GetHiveFullName(hive.Split('\\').Last());
+ }
+
+ }
+}
diff --git a/src/Windows.RegistryEditor/Utils/Stopwatch.cs b/src/Windows.RegistryEditor/Utils/Stopwatch.cs
new file mode 100644
index 0000000..7a3badc
--- /dev/null
+++ b/src/Windows.RegistryEditor/Utils/Stopwatch.cs
@@ -0,0 +1,48 @@
+using System;
+
+using SW = System.Diagnostics.Stopwatch;
+
+namespace Windows.RegistryEditor.Utils
+{
+ public class Stopwatch
+ {
+ public event Action Started;
+ public event Action Stopped;
+
+ protected virtual void OnStarted() => Started?.Invoke();
+ protected virtual void OnStopped(TimeSpan e) => Stopped?.Invoke(e);
+
+
+ private SW watch;
+
+ public Stopwatch()
+ {
+ watch = new SW();
+ }
+
+ public TimeSpan Elapsed => watch.Elapsed;
+
+ public bool IsRunning => watch.IsRunning;
+
+ public Stopwatch Start(bool reset = false)
+ {
+ if (reset) watch.Reset();
+
+ watch.Start();
+ OnStarted();
+
+ return this;
+ }
+
+ public TimeSpan Stop()
+ {
+ if (!watch.IsRunning)
+ throw new InvalidOperationException("Stopwatch isn't running");
+
+ watch.Stop();
+ OnStopped(Elapsed);
+
+ return Elapsed;
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Utils/Utility.cs b/src/Windows.RegistryEditor/Utils/Utility.cs
new file mode 100644
index 0000000..c9484b8
--- /dev/null
+++ b/src/Windows.RegistryEditor/Utils/Utility.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using Windows.RegistryEditor.Utils.Native;
+
+namespace Windows.RegistryEditor.Utils
+{
+ public static class Utility
+ {
+
+ public static void InvokeSafe(this ISynchronizeInvoke caller, Action method)
+ {
+ if (caller.InvokeRequired)
+ caller.Invoke(method, null);
+ else
+ method.Invoke();
+ }
+
+ public static T InvokeSafe(this ISynchronizeInvoke caller, Func method)
+ {
+ if (caller.InvokeRequired)
+ return (T)caller.Invoke(method, null);
+
+ return method.Invoke();
+ }
+
+ public static void BeginInvokeSafe(this ISynchronizeInvoke caller, Action method)
+ {
+ if (caller.InvokeRequired)
+ caller.BeginInvoke(method, null);
+ else
+ method.Invoke();
+ }
+
+ public static bool KillProcess(string proc)
+ {
+ foreach (Process process in Process.GetProcesses())
+ {
+ if (process.ProcessName.ToLower() != proc) continue;
+
+ process.Kill();
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Characters that are not allowed on windows:
+ /// < > : " / \ | ?
+ ///
+ public static string ValidateDirOrFileName(string name)
+ {
+ return Regex.Replace(name, "<|>|:|\"|/|\\\\|\\||\\?|\\*", " ");
+ }
+
+ public static void SelectAllItems(this ListView listView)
+ {
+ NativeMethods.SetItemState(listView, -1, 2, 2);
+ }
+
+ public static void DeselectAllItems(this ListView listView)
+ {
+ NativeMethods.SetItemState(listView, -1, 2, 0);
+ }
+
+ public static void OpenFolderInExplorer(string path)
+ {
+ Process.Start("explorer.exe", path);
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.Designer.cs b/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.Designer.cs
new file mode 100644
index 0000000..bf4b7dc
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.Designer.cs
@@ -0,0 +1,95 @@
+namespace Windows.RegistryEditor.Views.Controls
+{
+ partial class CheckBoxes
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.lbxAll = new System.Windows.Forms.CheckedListBox();
+ this.cbxAll = new System.Windows.Forms.CheckBox();
+ this.panelMain = new System.Windows.Forms.TableLayoutPanel();
+ this.panelMain.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // lbxAll
+ //
+ this.lbxAll.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lbxAll.FormattingEnabled = true;
+ this.lbxAll.Location = new System.Drawing.Point(0, 30);
+ this.lbxAll.Margin = new System.Windows.Forms.Padding(0);
+ this.lbxAll.Name = "lbxAll";
+ this.lbxAll.Size = new System.Drawing.Size(148, 90);
+ this.lbxAll.TabIndex = 0;
+ this.lbxAll.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.LbxAll_ItemCheck);
+ //
+ // cbxAll
+ //
+ this.cbxAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.cbxAll.AutoSize = true;
+ this.cbxAll.Location = new System.Drawing.Point(3, 10);
+ this.cbxAll.Name = "cbxAll";
+ this.cbxAll.Size = new System.Drawing.Size(70, 17);
+ this.cbxAll.TabIndex = 1;
+ this.cbxAll.Text = "Select All";
+ this.cbxAll.UseVisualStyleBackColor = true;
+ this.cbxAll.CheckedChanged += new System.EventHandler(this.CbxAll_CheckedChanged);
+ //
+ // panelMain
+ //
+ this.panelMain.ColumnCount = 1;
+ this.panelMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.panelMain.Controls.Add(this.cbxAll, 0, 0);
+ this.panelMain.Controls.Add(this.lbxAll, 0, 1);
+ this.panelMain.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panelMain.Location = new System.Drawing.Point(0, 0);
+ this.panelMain.Name = "panelMain";
+ this.panelMain.RowCount = 2;
+ this.panelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F));
+ this.panelMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.panelMain.Size = new System.Drawing.Size(148, 120);
+ this.panelMain.TabIndex = 2;
+ //
+ // CheckBoxes
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.panelMain);
+ this.Name = "CheckBoxes";
+ this.Size = new System.Drawing.Size(148, 120);
+ this.Load += new System.EventHandler(this.CheckBoxes_Load);
+ this.panelMain.ResumeLayout(false);
+ this.panelMain.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.CheckedListBox lbxAll;
+ private System.Windows.Forms.CheckBox cbxAll;
+ private System.Windows.Forms.TableLayoutPanel panelMain;
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.cs b/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.cs
new file mode 100644
index 0000000..d81cc93
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/Controls/CheckBoxes.cs
@@ -0,0 +1,221 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Design;
+using System.Management.Instrumentation;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace Windows.RegistryEditor.Views.Controls
+{
+ public partial class CheckBoxes : UserControl
+ {
+
+ public event ItemCheckEventHandler ItemCheck;
+ public event EventHandler SelectAllCheckedChanged;
+
+ protected virtual void OnItemCheck(ItemCheckEventArgs e) => ItemCheck?.Invoke(this, e);
+ protected virtual void OnSelectAllCheckedChanged() => SelectAllCheckedChanged?.Invoke(this, EventArgs.Empty);
+
+ public CheckBoxes()
+ {
+ InitializeComponent();
+ CheckOnClick = true;
+ lbxAll.Dock = DockStyle.Fill;
+
+ foreach (Control control in panelMain.Controls)
+ typeof(Control).InvokeMember("DoubleBuffered",
+ BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
+ null, control, new object[] { true });
+ }
+
+ private void CheckBoxes_Load(object sender, EventArgs e)
+ {
+
+ }
+
+ private void CbxAll_CheckedChanged(object sender, EventArgs e)
+ {
+ for (int i = 0; i < lbxAll.Items.Count; i++)
+ {
+ lbxAll.SetItemChecked(i, cbxAll.Checked);
+ }
+
+ OnSelectAllCheckedChanged();
+ }
+
+ private void LbxAll_ItemCheck(object sender, ItemCheckEventArgs e)
+ {
+ if (e.NewValue == CheckState.Unchecked)
+ {
+ cbxAll.CheckedChanged -= CbxAll_CheckedChanged;
+ cbxAll.Checked = false;
+ cbxAll.CheckedChanged += CbxAll_CheckedChanged;
+ }
+ else if (lbxAll.Items.Count == lbxAll.CheckedItems.Count + 1
+ && e.NewValue == CheckState.Checked)
+ {
+ cbxAll.CheckedChanged -= CbxAll_CheckedChanged;
+ cbxAll.Checked = true;
+ cbxAll.CheckedChanged += CbxAll_CheckedChanged;
+ }
+
+ OnItemCheck(e);
+ }
+
+ [Browsable(false)]
+ protected override CreateParams CreateParams
+ {
+ get
+ {
+ CreateParams cp = base.CreateParams;
+ cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
+ return cp;
+ }
+ }
+
+ [MergableProperty(false)]
+ [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [Localizable(true)]
+ [Category("Data")]
+ [Description("Gets the collection of items in this CheckedListBox.")]
+ public CheckedListBox.ObjectCollection Items
+ {
+ get
+ {
+ CbxAll_CheckedChanged(null, null); // When new items are added through the designer, check the state of the cbxAll.
+ return lbxAll.Items;
+ }
+ }
+
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Description("CheckedListBox DataSource.")]
+ public object DataSource
+ {
+ get => lbxAll.DataSource;
+ set => lbxAll.DataSource = value;
+ }
+
+ [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Deprecated", false)]
+ public new Image BackgroundImage { get; set; }
+
+ [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
+ public new ImageLayout BackgroundImageLayout { get; set; }
+
+ public new Color BackColor
+ {
+ get => lbxAll.BackColor;
+ set => UpdateControl(() => lbxAll.BackColor = value);
+ }
+
+ public new BorderStyle BorderStyle
+ {
+ get => lbxAll.BorderStyle;
+ set => UpdateControl(() => lbxAll.BorderStyle = value);
+ }
+
+ public new Color ForeColor
+ {
+ get => lbxAll.ForeColor;
+ set => UpdateControl(() => lbxAll.ForeColor = value);
+ }
+
+ [Category("Appearance")]
+ [Description("Indicates if the CheckBoxes should show up as flat or 3D in appearance.")]
+ public bool ThreeDCheckBoxes
+ {
+ get => lbxAll.ThreeDCheckBoxes;
+ set => UpdateControl(() => lbxAll.ThreeDCheckBoxes = value);
+ }
+
+ [Category("Behavior")]
+ [Description("Indicates if the check box should be toggled with the first click on an item.")]
+ public bool CheckOnClick
+ {
+ get => lbxAll.CheckOnClick;
+ set => lbxAll.CheckOnClick = value;
+ }
+
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Description("Collection of checked items in this CheckedListBox.")]
+ public CheckedListBox.CheckedItemCollection CheckedItems => lbxAll.CheckedItems;
+
+ [Browsable(true)]
+ [Description("Indicates if all check boxes are checked in the CheckedListBox.")]
+ [Category("Appearance")]
+ public bool SelectAllChecked
+ {
+ get => cbxAll.Checked;
+ set => UpdateControl(() => cbxAll.Checked = value);
+ }
+
+ public void UpdateControl(Action action)
+ {
+ action.Invoke();
+ if (DesignMode) Invalidate();
+ }
+
+ ///
+ /// Sets the checked value of the given item. This value should be a boolean.
+ ///
+ public void SetItemChecked(int index, bool value)
+ {
+ lbxAll.SetItemChecked(index, value);
+ }
+
+ ///
+ /// Sets the checked value of the given item. This value should be from
+ /// the System.Windows.Forms.CheckState enumeration.
+ ///
+ public void SetItemCheckState(int index, CheckState value)
+ {
+ lbxAll.SetItemCheckState(index, value);
+ }
+
+ ///
+ /// Indicates if the given item is, in any way, shape, or form, checked.
+ /// This will return true if the item is fully or indeterminately checked.
+ ///
+ public bool GetItemChecked(int index)
+ {
+ return lbxAll.GetItemChecked(index);
+ }
+
+ ///
+ /// Gets the check value of the current item. This value will be from the
+ /// System.Windows.Forms.CheckState enumeration.
+ ///
+ public CheckState GetItemCheckState(int index)
+ {
+ return lbxAll.GetItemCheckState(index);
+ }
+
+ public void SetItemCheckedByName(string value, bool flag)
+ {
+ for (int i = 0; i < lbxAll.Items.Count; i++)
+ {
+ if (lbxAll.Items[i].ToString().Equals(value))
+ lbxAll.SetItemChecked(i, flag);
+ }
+
+ throw new InstanceNotFoundException($"[SetItemCheckedByName] - Couldn't find the specified value -> {value}.");
+ }
+
+ public bool GetItemCheckedByName(string value)
+ {
+ for (int i = 0; i < lbxAll.Items.Count; i++)
+ {
+ if (lbxAll.Items[i].ToString().Equals(value))
+ return lbxAll.GetItemChecked(i);
+ }
+
+ throw new InstanceNotFoundException($"[GetItemCheckedByName] - Couldn't find the specified value -> {value}.");
+ }
+
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/Controls/ListViewEx.cs b/src/Windows.RegistryEditor/Views/Controls/ListViewEx.cs
new file mode 100644
index 0000000..a1fbc31
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/Controls/ListViewEx.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using Windows.RegistryEditor.Utils;
+
+namespace Windows.RegistryEditor.Views.Controls
+{
+ public class ListViewEx : ListView
+ {
+
+ public ListViewEx()
+ {
+ CheckBoxes = true;
+ FullRowSelect = true;
+ GridLines = true;
+ }
+
+ public void SelectAllItems() => Utility.SelectAllItems(this);
+
+ public void DeselectAllItems() => Utility.DeselectAllItems(this);
+
+ public void CheckAllItems(bool value)
+ {
+ foreach (ListViewItem item in Items)
+ item.Checked = value;
+ }
+
+ public string GetAllSelectedSubItemsText(int index)
+ {
+ string data = String.Empty;
+ foreach (ListViewItem item in SelectedItems)
+ data += item.SubItems[index].Text + Environment.NewLine;
+
+ data = data.TrimEnd();
+
+ return data;
+ }
+
+ public List GetAllSelectedSubItemsTextList(int index)
+ {
+ List newList = new List();
+ foreach (ListViewItem item in SelectedItems)
+ newList.Add(item.SubItems[index].Text);
+
+ return newList;
+ }
+
+ public List GetAllCheckedSubItemsTextList(int index)
+ {
+ List newList = new List();
+ foreach (ListViewItem item in CheckedItems)
+ newList.Add(item.SubItems[index].Text);
+
+ return newList;
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/Controls/Loader.Designer.cs b/src/Windows.RegistryEditor/Views/Controls/Loader.Designer.cs
new file mode 100644
index 0000000..81194d1
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/Controls/Loader.Designer.cs
@@ -0,0 +1,64 @@
+namespace Windows.RegistryEditor.Views.Controls
+{
+ partial class Loader
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.pbxGif = new System.Windows.Forms.PictureBox();
+ ((System.ComponentModel.ISupportInitialize)(this.pbxGif)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pbxGif
+ //
+ this.pbxGif.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.pbxGif.Image = global::Windows.RegistryEditor.Properties.Resources.loader_clock;
+ this.pbxGif.Location = new System.Drawing.Point(0, 0);
+ this.pbxGif.Name = "pbxGif";
+ this.pbxGif.Size = new System.Drawing.Size(100, 100);
+ this.pbxGif.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pbxGif.TabIndex = 0;
+ this.pbxGif.TabStop = false;
+ //
+ // Loader
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Transparent;
+ this.Controls.Add(this.pbxGif);
+ this.Name = "Loader";
+ this.Size = new System.Drawing.Size(100, 100);
+ this.Load += new System.EventHandler(this.Spinner_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.pbxGif)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pbxGif;
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/Controls/Loader.cs b/src/Windows.RegistryEditor/Views/Controls/Loader.cs
new file mode 100644
index 0000000..ad3369f
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/Controls/Loader.cs
@@ -0,0 +1,208 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Runtime.CompilerServices;
+using System.Windows.Forms;
+using Windows.RegistryEditor.Properties;
+
+namespace Windows.RegistryEditor.Views.Controls
+{
+ public enum LoaderKind
+ {
+ Clock,
+ Arrows,
+ CircleBall,
+ Loading,
+ Snake,
+ WheelThrobber
+ }
+
+ public partial class Loader : UserControl
+ {
+ #region --- Fields ---
+
+ private LoaderKind loaderKind;
+
+ #endregion --- Fields ---
+
+
+
+ #region --- Properties ---
+
+ [Description("Whether to disable all controls on form when loader is displayed.")]
+ [Category("Behavior")]
+ public bool DisableControlsOnWork { get; set; }
+
+ [Description("The size of the control when it's spinning. The purpose of this property is " +
+ "to allow you hidding your loader as a very small size in the corner, while " +
+ "being able to specifying the expected size.")]
+ [Category("Layout")]
+ public Size SizeLoading { get; set; }
+
+ [Description("Gets or sets the loader appearance to be displayed.")]
+ [Category("Appearance")]
+ public LoaderKind LoaderKind
+ {
+ get => loaderKind;
+ set
+ {
+ if (value == loaderKind) return;
+
+ loaderKind = value;
+ pbxGif.Image = CreateLoaderImage(value);
+ if (DesignMode) Invalidate();
+ }
+ }
+
+ protected override CreateParams CreateParams
+ {
+ get
+ {
+ CreateParams cp = base.CreateParams;
+ cp.ExStyle |= 0x02000000; // Turns on WS_EX_COMPOSITED
+ return cp;
+ }
+ }
+
+ #endregion --- Properties ---
+
+
+ public Loader()
+ {
+ SetStyle(ControlStyles.SupportsTransparentBackColor |
+ ControlStyles.UserPaint |
+ ControlStyles.ResizeRedraw |
+ ControlStyles.Selectable, true);
+
+ InitializeComponent();
+
+ DoubleBuffered = true;
+ Visible = false;
+ DisableControlsOnWork = true;
+ SizeLoading = new Size(100, 100);
+ LoaderKind = LoaderKind.Clock;
+ }
+
+ private void Spinner_Load(object sender, EventArgs e)
+ {
+ if (IsParentNull()) return;
+
+ ParentForm.SizeChanged += delegate { PositionToParent(); };
+ }
+
+ private void PositionToParent()
+ {
+ if (IsParentNull()) return;
+
+ this.Invoke(new Action(() => Left = (ParentForm.ClientSize.Width - Width) / 2));
+ this.Invoke(new Action(() => Top = (ParentForm.ClientSize.Height - Height) / 2));
+ }
+
+ public new void Show()
+ {
+ if (IsParentNull() || Visible) return;
+
+ this.Invoke(new Action(() => Size = SizeLoading));
+
+ if (DisableControlsOnWork)
+ EnableParentControls(false);
+
+ PositionToParent();
+
+ this.Invoke(new Action(() => base.Show()));
+ this.Invoke(new Action(() => BringToFront()));
+ }
+
+ public new void Hide()
+ {
+ if (IsParentNull() || !Visible) return;
+
+ if (DisableControlsOnWork)
+ EnableParentControls(true);
+
+ this.Invoke(new Action(() => base.Hide()));
+ this.Invoke(new Action(() => SendToBack()));
+ }
+
+
+ private bool IsParentNull([CallerMemberName] string callerMethod = "")
+ {
+ bool isNull = ParentForm == null;
+
+ if (isNull)
+ Debug.WriteLine($"[{callerMethod}] - Parent cannot be null.");
+
+ return isNull;
+ }
+ private void EnableParentControls(bool enabled)
+ {
+ if (IsParentNull()) return;
+
+ foreach (Control control in ParentForm.Controls)
+ {
+ if (control.GetType() == typeof(Loader)) continue;
+
+ control.Invoke(new Action(() => control.Enabled = enabled));
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ Transparent(this, e.Graphics);
+ base.OnPaint(e);
+ }
+
+ public static void Transparent(Control control, Graphics graphics)
+ {
+ Control owner = control.Parent;
+ if (owner == null) return;
+
+ Rectangle controlBounds = control.Bounds;
+ ControlCollection ownerControls = owner.Controls;
+ int controlIndex = ownerControls.IndexOf(control);
+ Bitmap bitmapBehind = null;
+ for (int i = controlIndex + 1; i < ownerControls.Count; i++)
+ {
+ Control targetControl = ownerControls[i];
+ if (!targetControl.Bounds.IntersectsWith(controlBounds)) continue;
+
+ if (bitmapBehind == null)
+ bitmapBehind = new Bitmap(control.Parent.ClientSize.Width, control.Parent.ClientSize.Height);
+ targetControl.DrawToBitmap(bitmapBehind, targetControl.Bounds);
+ }
+
+ if (bitmapBehind == null) return;
+
+ graphics.DrawImage(bitmapBehind, control.ClientRectangle, controlBounds, GraphicsUnit.Pixel);
+ bitmapBehind.Dispose();
+ }
+
+ private Image CreateLoaderImage(LoaderKind value)
+ {
+ switch (value)
+ {
+ case LoaderKind.Clock:
+ return Resources.loader_clock;
+
+ //case LoaderKind.Arrows:
+ // return Resources.loader_arrows;
+
+ //case LoaderKind.CircleBall:
+ // return Resources.loader_circleball;
+
+ //case LoaderKind.Loading:
+ // return Resources.loader_loading;
+
+ //case LoaderKind.Snake:
+ // return Resources.loader_snake;
+
+ //case LoaderKind.WheelThrobber:
+ // return Resources.loader_wheelthrobber;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, null);
+ }
+ }
+ }
+}
diff --git a/src/Windows.RegistryEditor/Views/FindWindow.Designer.cs b/src/Windows.RegistryEditor/Views/FindWindow.Designer.cs
new file mode 100644
index 0000000..bf52dda
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/FindWindow.Designer.cs
@@ -0,0 +1,405 @@
+namespace Windows.RegistryEditor.Views
+{
+ partial class FindWindow
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.tbxSearch = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.gbxLookAt = new System.Windows.Forms.GroupBox();
+ this.cbxData = new System.Windows.Forms.CheckBox();
+ this.cbxValues = new System.Windows.Forms.CheckBox();
+ this.cbxKeys = new System.Windows.Forms.CheckBox();
+ this.cbxMatchString = new System.Windows.Forms.CheckBox();
+ this.btnFindNext = new System.Windows.Forms.Button();
+ this.btnFindAll = new System.Windows.Forms.Button();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.cbxCaseSensitive = new System.Windows.Forms.CheckBox();
+ this.cbxRegularEx = new System.Windows.Forms.CheckBox();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.gbxOptions = new System.Windows.Forms.GroupBox();
+ this.gbxHkeys = new System.Windows.Forms.GroupBox();
+ this.cbxsHkeys = new Windows.RegistryEditor.Views.Controls.CheckBoxes();
+ this.gbxDataTypes = new System.Windows.Forms.GroupBox();
+ this.cbxsDataTypes = new Windows.RegistryEditor.Views.Controls.CheckBoxes();
+ this.tbxRemoteComputer = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.cbxRemoteSearch = new System.Windows.Forms.CheckBox();
+ this.btnFindAvailableMachines = new System.Windows.Forms.Button();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ this.loader = new Windows.RegistryEditor.Views.Controls.Loader();
+ this.gbxLookAt.SuspendLayout();
+ this.gbxOptions.SuspendLayout();
+ this.gbxHkeys.SuspendLayout();
+ this.gbxDataTypes.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tbxSearch
+ //
+ this.tbxSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tbxSearch.Location = new System.Drawing.Point(110, 57);
+ this.tbxSearch.Name = "tbxSearch";
+ this.tbxSearch.Size = new System.Drawing.Size(454, 20);
+ this.tbxSearch.TabIndex = 0;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(44, 60);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(60, 13);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Find String:";
+ //
+ // gbxLookAt
+ //
+ this.gbxLookAt.Controls.Add(this.cbxData);
+ this.gbxLookAt.Controls.Add(this.cbxValues);
+ this.gbxLookAt.Controls.Add(this.cbxKeys);
+ this.gbxLookAt.Location = new System.Drawing.Point(18, 83);
+ this.gbxLookAt.Name = "gbxLookAt";
+ this.gbxLookAt.Size = new System.Drawing.Size(86, 120);
+ this.gbxLookAt.TabIndex = 4;
+ this.gbxLookAt.TabStop = false;
+ this.gbxLookAt.Text = "Look at";
+ //
+ // cbxData
+ //
+ this.cbxData.AutoSize = true;
+ this.cbxData.Checked = true;
+ this.cbxData.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.cbxData.Location = new System.Drawing.Point(7, 66);
+ this.cbxData.Name = "cbxData";
+ this.cbxData.Size = new System.Drawing.Size(49, 17);
+ this.cbxData.TabIndex = 2;
+ this.cbxData.Text = "Data";
+ this.cbxData.UseVisualStyleBackColor = true;
+ //
+ // cbxValues
+ //
+ this.cbxValues.AutoSize = true;
+ this.cbxValues.Checked = true;
+ this.cbxValues.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.cbxValues.Location = new System.Drawing.Point(7, 43);
+ this.cbxValues.Name = "cbxValues";
+ this.cbxValues.Size = new System.Drawing.Size(58, 17);
+ this.cbxValues.TabIndex = 1;
+ this.cbxValues.Text = "Values";
+ this.cbxValues.UseVisualStyleBackColor = true;
+ //
+ // cbxKeys
+ //
+ this.cbxKeys.AutoSize = true;
+ this.cbxKeys.Checked = true;
+ this.cbxKeys.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.cbxKeys.Location = new System.Drawing.Point(7, 20);
+ this.cbxKeys.Name = "cbxKeys";
+ this.cbxKeys.Size = new System.Drawing.Size(49, 17);
+ this.cbxKeys.TabIndex = 0;
+ this.cbxKeys.Text = "Keys";
+ this.cbxKeys.UseVisualStyleBackColor = true;
+ //
+ // cbxMatchString
+ //
+ this.cbxMatchString.AutoSize = true;
+ this.cbxMatchString.Location = new System.Drawing.Point(6, 43);
+ this.cbxMatchString.Name = "cbxMatchString";
+ this.cbxMatchString.Size = new System.Drawing.Size(113, 17);
+ this.cbxMatchString.TabIndex = 1;
+ this.cbxMatchString.Text = "Match whole word";
+ this.cbxMatchString.UseVisualStyleBackColor = true;
+ //
+ // btnFindNext
+ //
+ this.btnFindNext.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnFindNext.Enabled = false;
+ this.btnFindNext.Location = new System.Drawing.Point(519, 272);
+ this.btnFindNext.Name = "btnFindNext";
+ this.btnFindNext.Size = new System.Drawing.Size(75, 23);
+ this.btnFindNext.TabIndex = 1;
+ this.btnFindNext.Text = "Find Next";
+ this.btnFindNext.UseVisualStyleBackColor = true;
+ this.btnFindNext.Click += new System.EventHandler(this.BtnFindSingle_Click);
+ //
+ // btnFindAll
+ //
+ this.btnFindAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnFindAll.Location = new System.Drawing.Point(519, 301);
+ this.btnFindAll.Name = "btnFindAll";
+ this.btnFindAll.Size = new System.Drawing.Size(75, 23);
+ this.btnFindAll.TabIndex = 2;
+ this.btnFindAll.Text = "Find All";
+ this.btnFindAll.UseVisualStyleBackColor = true;
+ this.btnFindAll.Click += new System.EventHandler(this.BtnFindAll_Click);
+ //
+ // btnCancel
+ //
+ this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnCancel.Enabled = false;
+ this.btnCancel.Location = new System.Drawing.Point(519, 330);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(75, 23);
+ this.btnCancel.TabIndex = 3;
+ this.btnCancel.Text = "Cancel";
+ this.btnCancel.UseVisualStyleBackColor = true;
+ this.btnCancel.Click += new System.EventHandler(this.BtnCancel_Click);
+ //
+ // cbxCaseSensitive
+ //
+ this.cbxCaseSensitive.AutoSize = true;
+ this.cbxCaseSensitive.Location = new System.Drawing.Point(6, 20);
+ this.cbxCaseSensitive.Name = "cbxCaseSensitive";
+ this.cbxCaseSensitive.Size = new System.Drawing.Size(96, 17);
+ this.cbxCaseSensitive.TabIndex = 0;
+ this.cbxCaseSensitive.Text = "Case Sensitive";
+ this.cbxCaseSensitive.UseVisualStyleBackColor = true;
+ //
+ // cbxRegularEx
+ //
+ this.cbxRegularEx.AutoSize = true;
+ this.cbxRegularEx.Enabled = false;
+ this.cbxRegularEx.Location = new System.Drawing.Point(6, 66);
+ this.cbxRegularEx.Name = "cbxRegularEx";
+ this.cbxRegularEx.Size = new System.Drawing.Size(117, 17);
+ this.cbxRegularEx.TabIndex = 2;
+ this.cbxRegularEx.Text = "Regular Expression";
+ this.cbxRegularEx.UseVisualStyleBackColor = true;
+ //
+ // textBox1
+ //
+ this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBox1.Enabled = false;
+ this.textBox1.Location = new System.Drawing.Point(6, 90);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Size = new System.Drawing.Size(478, 20);
+ this.textBox1.TabIndex = 3;
+ //
+ // gbxOptions
+ //
+ this.gbxOptions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.gbxOptions.Controls.Add(this.cbxMatchString);
+ this.gbxOptions.Controls.Add(this.textBox1);
+ this.gbxOptions.Controls.Add(this.cbxRegularEx);
+ this.gbxOptions.Controls.Add(this.cbxCaseSensitive);
+ this.gbxOptions.Location = new System.Drawing.Point(110, 83);
+ this.gbxOptions.Name = "gbxOptions";
+ this.gbxOptions.Size = new System.Drawing.Size(490, 120);
+ this.gbxOptions.TabIndex = 5;
+ this.gbxOptions.TabStop = false;
+ this.gbxOptions.Text = "Search Options";
+ //
+ // gbxHkeys
+ //
+ this.gbxHkeys.Controls.Add(this.cbxsHkeys);
+ this.gbxHkeys.Location = new System.Drawing.Point(18, 210);
+ this.gbxHkeys.Name = "gbxHkeys";
+ this.gbxHkeys.Size = new System.Drawing.Size(194, 147);
+ this.gbxHkeys.TabIndex = 6;
+ this.gbxHkeys.TabStop = false;
+ this.gbxHkeys.Text = "HKEYS";
+ //
+ // cbxsHkeys
+ //
+ this.cbxsHkeys.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+ this.cbxsHkeys.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+ this.cbxsHkeys.CheckOnClick = true;
+ this.cbxsHkeys.DataSource = null;
+ this.cbxsHkeys.Items.AddRange(new object[] {
+ "HKEY_CLASSES_ROOT",
+ "HKEY_CURRENT_USER",
+ "HKEY_LOCAL_MACHINE",
+ "HKEY_USERS",
+ "HKEY_CURRENT_CONFIG"});
+ this.cbxsHkeys.Location = new System.Drawing.Point(6, 16);
+ this.cbxsHkeys.Name = "cbxsHkeys";
+ this.cbxsHkeys.SelectAllChecked = false;
+ this.cbxsHkeys.Size = new System.Drawing.Size(182, 125);
+ this.cbxsHkeys.TabIndex = 0;
+ this.cbxsHkeys.ThreeDCheckBoxes = false;
+ //
+ // gbxDataTypes
+ //
+ this.gbxDataTypes.Controls.Add(this.cbxsDataTypes);
+ this.gbxDataTypes.Location = new System.Drawing.Point(218, 210);
+ this.gbxDataTypes.Name = "gbxDataTypes";
+ this.gbxDataTypes.Size = new System.Drawing.Size(269, 147);
+ this.gbxDataTypes.TabIndex = 7;
+ this.gbxDataTypes.TabStop = false;
+ this.gbxDataTypes.Text = "Data Types";
+ //
+ // cbxsDataTypes
+ //
+ this.cbxsDataTypes.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+ this.cbxsDataTypes.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+ this.cbxsDataTypes.CheckOnClick = true;
+ this.cbxsDataTypes.DataSource = null;
+ this.cbxsDataTypes.Items.AddRange(new object[] {
+ "REG_SZ",
+ "REG_EXPAND_SZ",
+ "REG_MULTI_SZ",
+ "REG_DWORD",
+ "REG_QWORD",
+ "REG_DWORD_LITTLE_ENDIAN",
+ "REG_QWORD_LITTLE_ENDIAN",
+ "REG_DWORD_BIG_ENDIAN",
+ "REG_BINARY",
+ "REG_NONE",
+ "REG_LINK",
+ "REG_RESOURCE_LIST"});
+ this.cbxsDataTypes.Location = new System.Drawing.Point(6, 16);
+ this.cbxsDataTypes.Name = "cbxsDataTypes";
+ this.cbxsDataTypes.SelectAllChecked = true;
+ this.cbxsDataTypes.Size = new System.Drawing.Size(257, 125);
+ this.cbxsDataTypes.TabIndex = 0;
+ this.cbxsDataTypes.ThreeDCheckBoxes = false;
+ //
+ // tbxRemoteComputer
+ //
+ this.tbxRemoteComputer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tbxRemoteComputer.Enabled = false;
+ this.tbxRemoteComputer.Location = new System.Drawing.Point(110, 31);
+ this.tbxRemoteComputer.Name = "tbxRemoteComputer";
+ this.tbxRemoteComputer.Size = new System.Drawing.Size(454, 20);
+ this.tbxRemoteComputer.TabIndex = 0;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(18, 34);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(86, 13);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "Computer Name:";
+ //
+ // cbxRemoteSearch
+ //
+ this.cbxRemoteSearch.AutoSize = true;
+ this.cbxRemoteSearch.Location = new System.Drawing.Point(18, 8);
+ this.cbxRemoteSearch.Name = "cbxRemoteSearch";
+ this.cbxRemoteSearch.Size = new System.Drawing.Size(227, 17);
+ this.cbxRemoteSearch.TabIndex = 4;
+ this.cbxRemoteSearch.Text = "Search in remote computer on the network";
+ this.cbxRemoteSearch.UseVisualStyleBackColor = true;
+ this.cbxRemoteSearch.CheckedChanged += new System.EventHandler(this.CbxSearchInRemote_CheckedChanged);
+ //
+ // btnFindAvailableMachines
+ //
+ this.btnFindAvailableMachines.Enabled = false;
+ this.btnFindAvailableMachines.Location = new System.Drawing.Point(570, 30);
+ this.btnFindAvailableMachines.Name = "btnFindAvailableMachines";
+ this.btnFindAvailableMachines.Size = new System.Drawing.Size(24, 21);
+ this.btnFindAvailableMachines.TabIndex = 9;
+ this.btnFindAvailableMachines.Text = "...";
+ this.toolTip.SetToolTip(this.btnFindAvailableMachines, "Find available machines on the network.");
+ this.btnFindAvailableMachines.UseVisualStyleBackColor = true;
+ this.btnFindAvailableMachines.Click += new System.EventHandler(this.BtnFindAvailableMachines_Click);
+ //
+ // loader
+ //
+ this.loader.BackColor = System.Drawing.Color.Transparent;
+ this.loader.DisableControlsOnWork = false;
+ this.loader.LoaderKind = Windows.RegistryEditor.Views.Controls.LoaderKind.Clock;
+ this.loader.Location = new System.Drawing.Point(554, 226);
+ this.loader.Name = "loader";
+ this.loader.Size = new System.Drawing.Size(40, 40);
+ this.loader.SizeLoading = new System.Drawing.Size(100, 100);
+ this.loader.TabIndex = 8;
+ this.loader.Visible = false;
+ //
+ // FindWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(606, 365);
+ this.Controls.Add(this.btnFindAvailableMachines);
+ this.Controls.Add(this.cbxRemoteSearch);
+ this.Controls.Add(this.loader);
+ this.Controls.Add(this.gbxDataTypes);
+ this.Controls.Add(this.gbxHkeys);
+ this.Controls.Add(this.gbxOptions);
+ this.Controls.Add(this.btnCancel);
+ this.Controls.Add(this.btnFindAll);
+ this.Controls.Add(this.btnFindNext);
+ this.Controls.Add(this.gbxLookAt);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.tbxRemoteComputer);
+ this.Controls.Add(this.tbxSearch);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+ this.KeyPreview = true;
+ this.Name = "FindWindow";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Find";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FindWindow_FormClosing);
+ this.Load += new System.EventHandler(this.FindWindow_Load);
+ this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.FindWindow_KeyPress);
+ this.gbxLookAt.ResumeLayout(false);
+ this.gbxLookAt.PerformLayout();
+ this.gbxOptions.ResumeLayout(false);
+ this.gbxOptions.PerformLayout();
+ this.gbxHkeys.ResumeLayout(false);
+ this.gbxDataTypes.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.TextBox tbxSearch;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.GroupBox gbxLookAt;
+ private System.Windows.Forms.CheckBox cbxData;
+ private System.Windows.Forms.CheckBox cbxValues;
+ private System.Windows.Forms.CheckBox cbxKeys;
+ private System.Windows.Forms.CheckBox cbxMatchString;
+ private System.Windows.Forms.Button btnFindNext;
+ private System.Windows.Forms.Button btnFindAll;
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.CheckBox cbxCaseSensitive;
+ private System.Windows.Forms.CheckBox cbxRegularEx;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.GroupBox gbxOptions;
+ private System.Windows.Forms.GroupBox gbxHkeys;
+ private System.Windows.Forms.GroupBox gbxDataTypes;
+ private Windows.RegistryEditor.Views.Controls.CheckBoxes cbxsDataTypes;
+ private Windows.RegistryEditor.Views.Controls.CheckBoxes cbxsHkeys;
+ private Windows.RegistryEditor.Views.Controls.Loader loader;
+ private System.Windows.Forms.TextBox tbxRemoteComputer;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.CheckBox cbxRemoteSearch;
+ private System.Windows.Forms.Button btnFindAvailableMachines;
+ private System.Windows.Forms.ToolTip toolTip;
+ }
+}
+
diff --git a/src/Windows.RegistryEditor/Views/FindWindow.cs b/src/Windows.RegistryEditor/Views/FindWindow.cs
new file mode 100644
index 0000000..f9fbe6b
--- /dev/null
+++ b/src/Windows.RegistryEditor/Views/FindWindow.cs
@@ -0,0 +1,443 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Principal;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Windows.RegistryEditor.Events;
+using Windows.RegistryEditor.Utils;
+using Stopwatch = Windows.RegistryEditor.Utils.Stopwatch;
+
+namespace Windows.RegistryEditor.Views
+{
+ ///
+ /// https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/reg-query
+ ///
+ public partial class FindWindow : Form
+ {
+ private NetworkWindow refNetworkWindow;
+ public NetworkWindow NetworkInstance
+ {
+ get
+ {
+ if (refNetworkWindow != null && !refNetworkWindow.IsDisposed)
+ {
+ refNetworkWindow.Activate();
+ return refNetworkWindow;
+ }
+ refNetworkWindow = new NetworkWindow();
+ refNetworkWindow.MachineSelected += (e) => tbxRemoteComputer.Text = e;
+ refNetworkWindow.FormClosing += delegate { tbxSearch.Focus(); };
+ return refNetworkWindow;
+ }
+ }
+
+
+ private List procsList;
+ private int procsExecuted;
+ private bool searchInProgress;
+
+ private AutoResetEvent procToken;
+ private CancellationTokenSource cancelSrc;
+ private CancellationToken cancelToken;
+
+ public FindWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void FindWindow_Load(object sender, EventArgs e)
+ {
+ cbxsHkeys.SetItemChecked(1, true);
+ }
+
+ private void BtnFindAvailableMachines_Click(object sender, EventArgs e)
+ {
+ NetworkInstance.ShowDialog(this);
+ }
+
+ private void BtnFindSingle_Click(object sender, EventArgs e) { }
+
+ private async void BtnFindAll_Click(object sender, EventArgs e)
+ {
+ if (String.IsNullOrEmpty(tbxSearch.Text)) return;
+
+ if (cbxRemoteSearch.Checked)
+ {
+ DialogResult answer = MessageBox.Show(
+ "Scanning registries through the network may take a while depending on the" +
+ "chosen filter. Are you sure you want to continue?", "INFO",
+ MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
+
+ if (answer != DialogResult.Yes) return;
+ }
+
+ Started();
+ List hives = GetHkeysFilters();
+ procsList = GenerateRegQueryProcs(hives);
+
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.Start();
+ OnProgressStarted(this, new ProgressStartedArgs("Starting to search for registries...", hives.First()));
+
+ searchInProgress = true;
+ await ExecuteProcs(procsList);
+ searchInProgress = false;
+ procToken.Set();
+
+ stopwatch.Stop();
+ OnProgressFinished(this, new ProgressFinishedArgs("Finished searching for registries."));
+ Stopped();
+
+ Activate();
+ MessageBox.Show("Finished searching. Time Taken:\n" + stopwatch.Elapsed.ToString("g"),
+ "INFO", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+
+ private void Started()
+ {
+ btnFindAll.Enabled = false;
+ btnCancel.Enabled = true;
+ loader.Show();
+
+ procsExecuted = 0;
+ procToken = new AutoResetEvent(false);
+ cancelSrc = new CancellationTokenSource();
+ cancelToken = cancelSrc.Token;
+ }
+
+ private void Stopped()
+ {
+ Text = "Find";
+ btnFindAll.Enabled = true;
+ btnCancel.Enabled = false;
+ loader.Hide();
+ }
+
+ ///
+ /// BIG NOTE: When we search through the registry remotely, we can't really access HKCR, HKCU, HKCC but at the same time
+ /// we don't really need to, as they can be found under HKLM and HKU. In other words, they're just symbolic links. i.e:
+ /// ### HKEY_CLASSES_ROOT links to: ###
+ /// HKEY_CURRENT_USER\Software\Classes
+ /// HKEY_LOCAL_MACHINE\SOFTWARE\Classes
+ /// HKEY_USERS\{UserSID}\Software\Classes
+ /// HKEY_USERS\{UserSID}_Classes
+ ///
+ /// ### HKEY_CURRENT_USER links to: ###
+ /// HKEY_USERS\{UserSID}
+ ///
+ /// ### HKEY_CURRENT_CONFIG links to: ###
+ /// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Hardware Profiles\0001
+ /// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Hardware Profiles\Current
+ /// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\0001
+ /// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current
+ ///
+ /// Getting user SID:
+ /// WindowsIdentity.GetCurrent().User
+ /// whoami /user
+ ///
+ private List GetHkeysFilters()
+ {
+ List hives = new List();
+ if (cbxRemoteSearch.Checked)
+ {
+ hives.Add(RegistryUtils.HKLM);
+ hives.Add(RegistryUtils.HKU);
+ #region experimental
+ //string userSID = WindowsIdentity.GetCurrent().User?.Value;
+ //Debug.Assert(userSID != null, "userSID != null");
+ //foreach (string hive in cbxsHkeys.CheckedItems)
+ //{
+ // if (hive.Equals(RegistryUtils.HKCR))
+ // hives.Add($@"HKU\{userSID}\Software\Classes");
+ // else if (hive.Equals(RegistryUtils.HKCU))
+ // hives.Add($@"HKU\{userSID}");
+ // else if (hive.Equals(RegistryUtils.HKLM))
+ // hives.Add($@"HKLM");
+ // else if (hive.Equals(RegistryUtils.HKU))
+ // hives.Add($@"HKU");
+ // else if (hive.Equals(RegistryUtils.HKCC))
+ // hives.Add($@"HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\Current");
+ //}
+ #endregion experimental
+ }
+ else
+ {
+ foreach (string hive in cbxsHkeys.CheckedItems)
+ hives.Add(hive);
+ }
+
+ return hives;
+ }
+
+ private List GenerateRegQueryProcs(List hives)
+ {
+ List procs = new List();
+ foreach (string hive in hives)
+ {
+ string searchQuery = BuildSearchQuery(RegistryUtils.GetHiveShortcut(hive));
+ Process proc = CreateRegQueryProc(searchQuery);
+ procs.Add(proc);
+ Console.WriteLine($"{proc.StartInfo.FileName} {proc.StartInfo.Arguments}");
+ }
+
+ return procs;
+ }
+
+ private string BuildSearchQuery(string hive)
+ {
+ string query = String.Empty;
+
+ if (cbxRemoteSearch.Checked)
+ query = $"\"\\\\{tbxRemoteComputer.Text}\\{hive}\" /f \"{tbxSearch.Text}\" /s";
+ else
+ query = $"\"{hive}\" /f \"{tbxSearch.Text}\" /s";
+
+ if (cbxKeys.Checked) query += " /k";
+ if (cbxValues.Checked) query += " /v";
+ if (cbxData.Checked) query += " /d";
+ if (cbxCaseSensitive.Checked) query += " /c";
+ if (cbxMatchString.Checked) query += " /e";
+ if (cbxsDataTypes.GetItemCheckedByName("REG_MULTI_SZ")) query += " /se +";
+
+ if (cbxsDataTypes.CheckedItems.Count <= 0 || cbxsDataTypes.SelectAllChecked)
+ return query;
+
+ // ------------------------ Adding Data types filters ------------------------
+ query += " /t \"";
+ foreach (string checkedItem in cbxsDataTypes.CheckedItems)
+ query += checkedItem + ",";
+
+ query = query.TrimEnd(',');
+ query += "\"";
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb773476(v=vs.85).aspx
+ // Unfortunately these are not supported by reg query when filtering...
+ query = Regex.Replace(query, ",?REG_QWORD_LITTLE_ENDIAN", String.Empty);
+ query = Regex.Replace(query, ",?REG_LINK", String.Empty);
+ query = Regex.Replace(query, ",?REG_RESOURCE_LIST", String.Empty);
+
+ return query;
+ }
+
+ private Process CreateRegQueryProc(string searchQuery)
+ {
+ ProcessStartInfo procInfo = new ProcessStartInfo
+ {
+ FileName = "REG",
+ Arguments = $"QUERY {searchQuery}",
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ RedirectStandardOutput = true,
+ CreateNoWindow = true,
+ UseShellExecute = false
+ };
+
+ Process proc = new Process
+ {
+ StartInfo = procInfo,
+ EnableRaisingEvents = true
+ };
+
+ proc.ErrorDataReceived += OnErrorDataReceived;
+ proc.OutputDataReceived += OnOutputDataReceived;
+ proc.Exited += OnFindEnd;
+
+ return proc;
+ }
+
+ private async Task ExecuteProcs(IEnumerable procs)
+ {
+ foreach (Process proc in procs)
+ {
+ procsExecuted++;
+
+ string hiveShort = proc.StartInfo.Arguments.Split('"')[1];
+ string hive = cbxRemoteSearch.Checked
+ ? RegistryUtils.GetRemoteHiveFullName(hiveShort)
+ : RegistryUtils.GetHiveFullName(hiveShort);
+ string message = $"Searching in {hive}...Patient :)";
+ Text = $"Find | {message}";
+
+ OnProgressChanged(this, new ProgressChangedArgs(message, hive));
+ await Task.Run(() => ExecuteProc(proc));
+
+ if (cancelToken.IsCancellationRequested)
+ break;
+ }
+ }
+
+ private void ExecuteProc(Process proc)
+ {
+ proc.Start();
+ proc.BeginErrorReadLine();
+ proc.BeginOutputReadLine();
+
+ Console.WriteLine("[Process::ExecuteProc] - Waiting for exit...");
+ proc.WaitForExit();
+ Console.WriteLine("[Process::ExecuteProc] - Executed Finished.");
+ }
+
+ private void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ if (e?.Data == null) return;
+
+ string hive = e.Data.TrimStart().StartsWith("HKEY_") ? e.Data : String.Empty;
+ if (String.IsNullOrEmpty(hive)) return;
+
+ if (cbxRemoteSearch.Checked)
+ hive = $"{tbxRemoteComputer.Text}\\{hive}";
+
+ OnFoundSingleResult(this, new FindSingleResultArgs(hive));
+ }
+
+ private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ if (e?.Data == null) return;
+ if (!e.Data.StartsWith("ERROR")) return;
+
+ if (e.Data.Trim().StartsWith("ERROR: The network path was not found."))
+ {
+ MessageBox.Show($"{e.Data}\n" +
+ "Make sure that the target machine has \"Remote Registry\" service running.",
+ "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
+
+ cancelSrc.Cancel();
+ }
+ else
+ {
+ MessageBox.Show("Error occured. Please contact author of this app with this message.\n" +
+ $"{e.Data}",
+ "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+
+ private async void OnFindEnd(object sender, EventArgs e)
+ {
+ if (procsList.Count != procsExecuted || procsExecuted == 0) return;
+
+ await Task.Run(() => Thread.Sleep(1000));
+ Console.WriteLine("[Process::OnFindEnd] - Waiting for other thread to finished.");
+ procToken.WaitOne();
+ Console.WriteLine("[Process::OnFindEnd] - Clearing up.");
+ for (int i = 0; i < procsList.Count; i++)
+ {
+ procsList[i].Dispose();
+ procsList[i] = null;
+ }
+
+ searchInProgress = false;
+ loader.Hide();
+ }
+
+ private void BtnCancel_Click(object sender, EventArgs e)
+ {
+ if (!searchInProgress) return;
+
+ cancelSrc.Cancel();
+ for (int i = 0; i < procsExecuted; i++)
+ {
+ procsList[i].CancelErrorRead();
+ procsList[i].CancelOutputRead();
+ if (!procsList[i].HasExited)
+ procsList[i].Kill();
+ }
+
+ procToken.Set();
+ }
+
+ private void CbxSearchInRemote_CheckedChanged(object sender, EventArgs e)
+ {
+ tbxRemoteComputer.Enabled = cbxRemoteSearch.Checked;
+ btnFindAvailableMachines.Enabled = cbxRemoteSearch.Checked;
+ gbxHkeys.Enabled = !cbxRemoteSearch.Checked;
+ if (cbxRemoteSearch.Checked)
+ tbxRemoteComputer.Focus();
+ else
+ tbxSearch.Focus();
+ }
+
+ private void FindWindow_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ Keys key = (Keys) e.KeyChar;
+ switch (key)
+ {
+ case Keys.Escape:
+ Close();
+ break;
+
+ case Keys.Return:
+ btnFindAll.PerformClick();
+ break;
+ }
+ }
+
+ private async void FindWindow_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (searchInProgress)
+ {
+ e.Cancel = true;
+ btnCancel.PerformClick();
+ await Task.Run(() => Thread.Sleep(500));
+ Close();
+ }
+ }
+
+
+ #region --- Events ---
+
+ public event Action