├── .gitattributes
├── .gitignore
├── .gitmodules
├── .vscode
└── launch.json
├── Installer
└── Installer.vdproj
├── KRegExp
├── KRegExp.cpp
├── KRegExp.h
├── KRegExp.vcxproj
├── KRegExp.vcxproj.filters
└── KRegExpCommon.h
├── LICENSE
├── README.md
├── RegExp
├── AboutDlg.cpp
├── AboutDlg.h
├── AppCommandBase.cpp
├── AppCommandBase.h
├── AppSettings.h
├── BinaryValueDlg.cpp
├── BinaryValueDlg.h
├── ChangeValueCommand.cpp
├── ChangeValueCommand.h
├── CommandManager.cpp
├── CommandManager.h
├── ConnectRegistryDlg.cpp
├── ConnectRegistryDlg.h
├── CopyKeyCommand.cpp
├── CopyKeyCommand.h
├── CopyValueCommand.cpp
├── CopyValueCommand.h
├── CreateKeyCommand.cpp
├── CreateKeyCommand.h
├── CreateValueCommand.cpp
├── CreateValueCommand.h
├── DeleteKeyCommand.cpp
├── DeleteKeyCommand.h
├── DeleteValueCommand.cpp
├── DeleteValueCommand.h
├── DriverHelper.cpp
├── DriverHelper.h
├── EnumStrings.cpp
├── EnumStrings.h
├── ExportDlg.cpp
├── ExportDlg.h
├── FindAllDlg.cpp
├── FindAllDlg.h
├── FindDlg.cpp
├── FindDlg.h
├── FindOptions.h
├── GotoKeyDlg.cpp
├── GotoKeyDlg.h
├── Helpers.cpp
├── Helpers.h
├── HexControl.cpp
├── HexControl.h
├── IMainFrame.h
├── Icons
│ ├── Delete.ico
│ ├── Options.ico
│ ├── Properties.ico
│ ├── Query.ico
│ ├── Refresh.ico
│ ├── Registry.ico
│ ├── RegistrySearch.ico
│ ├── back.ico
│ ├── binary.ico
│ ├── bookmark_add.ico
│ ├── bookmark_delete.ico
│ ├── bookmarks.ico
│ ├── check.ico
│ ├── copy.ico
│ ├── cut.ico
│ ├── digit.ico
│ ├── export.ico
│ ├── find.ico
│ ├── find_next.ico
│ ├── find_previous.ico
│ ├── folder.ico
│ ├── folder_accessdenied.ico
│ ├── folder_closed.ico
│ ├── folder_into.ico
│ ├── folder_new.ico
│ ├── folder_view.ico
│ ├── folderup.ico
│ ├── font.ico
│ ├── forward.ico
│ ├── goto.ico
│ ├── hive-accessdenied.ico
│ ├── hive.ico
│ ├── import.ico
│ ├── laptop.ico
│ ├── link.ico
│ ├── lock.ico
│ ├── number-1.ico
│ ├── number-2.ico
│ ├── number-4.ico
│ ├── number-8-2.ico
│ ├── number-8.ico
│ ├── paste.ico
│ ├── quickfind.ico
│ ├── redo.ico
│ ├── regexp.ico
│ ├── regremote.ico
│ ├── rename.ico
│ ├── replace.ico
│ ├── save_as.ico
│ ├── shield.ico
│ ├── text.ico
│ └── undo.ico
├── ImageIconCache.cpp
├── ImageIconCache.h
├── KeysHandlesDlg.cpp
├── KeysHandlesDlg.h
├── LoadHiveDlg.cpp
├── LoadHiveDlg.h
├── LocationManager.cpp
├── LocationManager.h
├── MainFrame.cpp
├── MainFrame.h
├── ManageLocationsDlg.cpp
├── ManageLocationsDlg.h
├── MemoryBuffer.cpp
├── MemoryBuffer.h
├── MultiStringValueDlg.cpp
├── MultiStringValueDlg.h
├── NavigationManager.h
├── NtDll.h
├── NumberValueDlg.cpp
├── NumberValueDlg.h
├── QuickFilterBar.cpp
├── QuickFilterBar.h
├── RegExp.cpp
├── RegExp.h
├── RegExp.rc
├── RegExp.vcxproj
├── RegExp.vcxproj.filters
├── RegExportImport.cpp
├── RegExportImport.h
├── Registry.cpp
├── Registry.h
├── RegistryKey.cpp
├── RegistryKey.h
├── RegistrySearcher.cpp
├── RegistrySearcher.h
├── RenameKeyCommand.cpp
├── RenameKeyCommand.h
├── RenameValueCommand.cpp
├── RenameValueCommand.h
├── SecurityHelper.cpp
├── SecurityHelper.h
├── SecurityInformation.cpp
├── SecurityInformation.h
├── StringValueDlg.cpp
├── StringValueDlg.h
├── TreeHelper.cpp
├── TreeHelper.h
├── cpp.hint
├── framework.h
├── manifest.xml
├── pch.cpp
├── pch.h
├── resource.h
└── targetver.h
├── TotalRegistry.sln
├── regexp1.png
├── regexp2.png
└── regexp3.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "WTLHelper"]
2 | path = WTLHelper
3 | url = https://github.com/zodiacon/WTLHelper
4 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "(Windows) Launch",
9 | "type": "cppvsdbg",
10 | "request": "launch",
11 | "program": "${workspaceFolder}/x64/Debug/RegExp.exe",
12 | "args": [],
13 | "stopAtEntry": false,
14 | "cwd": "${fileDirname}",
15 | "environment": [],
16 | "console": "externalTerminal"
17 | }
18 | ]
19 | }
--------------------------------------------------------------------------------
/KRegExp/KRegExp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define DRIVER_PREFIX "KRegExp: "
4 |
--------------------------------------------------------------------------------
/KRegExp/KRegExp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {8E41214B-6785-4CFE-B992-037D68949A14}
18 | inf;inv;inx;mof;mc;
19 |
20 |
21 |
22 |
23 | Source Files
24 |
25 |
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 |
--------------------------------------------------------------------------------
/KRegExp/KRegExpCommon.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define DRIVER_CURRENT_VERSION 0x0100
4 |
5 | #define IOCTL_KREGEXP_OPEN_KEY CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
6 | #define IOCTL_KREGEXP_DUP_HANDLE CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
7 |
8 | struct KeyData {
9 | ULONG Length;
10 | ULONG Access;
11 | WCHAR Name[1];
12 | };
13 |
14 | struct DupHandleData {
15 | HANDLE Handle;
16 | ULONG SourcePid;
17 | ULONG AccessMask;
18 | ULONG Flags;
19 | };
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Pavel Yosifovich
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Total Registry
2 |
3 | Replacement for the Windows built-in *Regedit.exe* tool. Improvements over that tool include:
4 |
5 | * Show real Registry (not just the standard one)
6 | * Sort list view by any column
7 | * Key icons for hives, inaccessible keys, and links
8 | * Key details: last write time and number of keys/values
9 | * Displays MUI and REG_EXPAND_SZ expanded values
10 | * Full search (Find All / Ctrl+Shift+F)
11 | * Enhanced hex editor for binary values
12 | * Undo/redo
13 | * Copy/paste of keys/values
14 | * Optionally replace RegEdit
15 | * Connect to remote Registry
16 | * View open key handles
17 |
18 | ## Build instructions
19 |
20 | Build the solution file with Visual Studio 2022 preview. Can be built with Visual Studio 2019 as well (change toolset to v142 and C++ compiler version to C++ latest or C++20).
21 |
22 | 
23 |
24 | 
25 |
26 | 
27 |
--------------------------------------------------------------------------------
/RegExp/AboutDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "resource.h"
3 | #include "AboutDlg.h"
4 | #include "VersionResourceHelper.h"
5 |
6 | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
7 | CenterWindow(GetParent());
8 | SetDialogIcon(IDR_MAINFRAME);
9 |
10 | WCHAR path[MAX_PATH];
11 | ::GetModuleFileName(nullptr, path, _countof(path));
12 | VersionResourceHelper vr(path);
13 | auto version = vr.GetValue(L"ProductVersion");
14 | auto copyright = vr.GetValue(L"LegalCopyright");
15 | SetDlgItemText(IDC_VERSION, L"Total Registry v" + version);
16 | SetDlgItemText(IDC_COPYRIGHT, copyright);
17 |
18 | return TRUE;
19 | }
20 |
21 | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
22 | EndDialog(wID);
23 | return 0;
24 | }
25 |
26 | LRESULT CAboutDlg::OnClickSyslink(int, LPNMHDR hdr, BOOL&) const {
27 | CString text;
28 | GetDlgItem(IDC_LINK).GetWindowText(text);
29 | text.Replace(L"", L"");
30 | text.Replace(L"", L"");
31 | ::ShellExecute(nullptr, L"open", text, nullptr, nullptr, SW_SHOWDEFAULT);
32 | return 0;
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/RegExp/AboutDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class CAboutDlg :
6 | public CDialogImpl,
7 | public CDialogHelper {
8 | public:
9 | enum { IDD = IDD_ABOUTBOX };
10 |
11 | BEGIN_MSG_MAP(CAboutDlg)
12 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
13 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
14 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
15 | NOTIFY_CODE_HANDLER(NM_CLICK, OnClickSyslink)
16 | NOTIFY_CODE_HANDLER(NM_RETURN, OnClickSyslink)
17 | REFLECT_NOTIFICATIONS_EX()
18 | END_MSG_MAP()
19 |
20 | // Handler prototypes (uncomment arguments if needed):
21 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
22 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
23 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
24 |
25 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
26 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
27 | LRESULT OnClickSyslink(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) const;
28 | };
29 |
--------------------------------------------------------------------------------
/RegExp/AppCommandBase.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "AppCommandBase.h"
3 |
4 | void AppCommandList::AddCommand(std::shared_ptr command) {
5 | _commands.push_back(command);
6 | }
7 |
8 | std::shared_ptr AppCommandList::GetCommand(size_t i) const {
9 | return i < _commands.size() ? _commands[i] : nullptr;
10 | }
11 |
12 | int AppCommandList::GetCount() const {
13 | return static_cast(_commands.size());
14 | }
15 |
16 | bool AppCommandList::Execute() {
17 | for (auto& cmd : _commands)
18 | if (!cmd->Execute())
19 | return false;
20 | return InvokeCallback(true);
21 | }
22 |
23 | bool AppCommandList::Undo() {
24 | for (int i = (int)_commands.size() - 1; i >= 0; --i)
25 | if (!_commands[i]->Undo())
26 | return false;
27 |
28 | return InvokeCallback(false);
29 | }
30 |
--------------------------------------------------------------------------------
/RegExp/AppCommandBase.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | const CString DeletedPathBackup(L"SOFTWARE\\ScorpioSoftware\\RegExp\\__Deleted__\\");
4 |
5 | struct AppCommand abstract {
6 | explicit AppCommand(const CString& name) : _cmdname(name) {}
7 |
8 | virtual CString GetCommandName() const {
9 | return _cmdname;
10 | }
11 |
12 | void SetCommandName(PCWSTR name) {
13 | _cmdname = name;
14 | }
15 |
16 | virtual ~AppCommand() = default;
17 | virtual bool Execute() = 0;
18 | virtual bool Undo() = 0;
19 |
20 | private:
21 | CString _cmdname;
22 | };
23 |
24 | template
25 | using AppCommandCallback = std::function;
26 |
27 | template
28 | struct AppCommandBase abstract : AppCommand {
29 | explicit AppCommandBase(const CString& name, AppCommandCallback cb = nullptr) : AppCommand(name), _cb(cb) {}
30 |
31 | void SetCallback(AppCommandCallback cb) {
32 | _cb = cb;
33 | }
34 |
35 | protected:
36 | virtual bool InvokeCallback(bool execute) {
37 | if (_cb)
38 | return _cb(static_cast(*this), execute);
39 | return true;
40 | }
41 |
42 | private:
43 | AppCommandCallback _cb;
44 | };
45 |
46 | template
47 | struct RegAppCommandBase : AppCommandBase {
48 | RegAppCommandBase(const CString& cmdname, PCWSTR path, PCWSTR name, AppCommandCallback cb = nullptr)
49 | : AppCommandBase(cmdname, cb), _path(path), _name(name) {}
50 |
51 | const CString& GetPath() const {
52 | return _path;
53 | }
54 | const CString& GetName() const {
55 | return _name;
56 | }
57 |
58 | protected:
59 | CString _path, _name;
60 | };
61 |
62 | struct AppCommandList final : AppCommandBase {
63 | AppCommandList(PCWSTR name = nullptr, AppCommandCallback cb = nullptr) : AppCommandBase(name, cb) {}
64 |
65 | void AddCommand(std::shared_ptr command);
66 |
67 | std::shared_ptr GetCommand(size_t i) const;
68 | int GetCount() const;
69 |
70 | bool Execute() override;
71 | bool Undo() override;
72 |
73 | private:
74 | std::vector> _commands;
75 | };
76 |
--------------------------------------------------------------------------------
/RegExp/AppSettings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "FindOptions.h"
5 |
6 | struct AppSettings : Settings {
7 | BEGIN_SETTINGS(AppSettings)
8 | SETTING(MainWindowPlacement, WINDOWPLACEMENT{}, SettingType::Binary);
9 | SETTING(Font, LOGFONT{}, SettingType::Binary);
10 | SETTING(ShowExtraHives, 0, SettingType::Bool);
11 | SETTING(ShowKeysInList, 0, SettingType::Bool);
12 | SETTING_STRING(LastKey, L"");
13 | SETTING(AlwaysOnTop, 0, SettingType::Bool);
14 | SETTING(ViewAddressBar, 1, SettingType::Bool);
15 | SETTING(ViewToolBar, 1, SettingType::Bool);
16 | SETTING(ViewStatusBar, 1, SettingType::Bool);
17 | SETTING(ReadOnly, 0, SettingType::Bool);
18 | SETTING(ReplaceRegEdit, 0, SettingType::Bool);
19 | SETTING(DarkMode, 0, SettingType::Bool);
20 | SETTING(SingleInstance, 0, SettingType::Bool);
21 | SETTING(Find, FindOptions::SearchKeys | FindOptions::SearchValues | FindOptions::SearchStdRegistry | FindOptions::SearchSelected, SettingType::Int32);
22 | END_SETTINGS
23 |
24 | DEF_SETTING(ShowExtraHives, int)
25 | DEF_SETTING(AlwaysOnTop, int)
26 | DEF_SETTING(ShowKeysInList, int)
27 | DEF_SETTING(ReadOnly, int)
28 | DEF_SETTING(MainWindowPlacement, WINDOWPLACEMENT)
29 | DEF_SETTING(Font, LOGFONT)
30 | DEF_SETTING(Find, FindOptions)
31 | DEF_SETTING(ReplaceRegEdit, int)
32 | DEF_SETTING(DarkMode, int)
33 | DEF_SETTING(SingleInstance, int)
34 | DEF_SETTING(ViewAddressBar, int)
35 | DEF_SETTING(ViewToolBar, int)
36 | DEF_SETTING(ViewStatusBar, int)
37 | DEF_SETTING_MULTI(Bookmarks)
38 | DEF_SETTING_STRING(LastKey)
39 | };
40 |
--------------------------------------------------------------------------------
/RegExp/BinaryValueDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "resource.h"
3 | #include "BinaryValueDlg.h"
4 | #include "Helpers.h"
5 | #include "ThemeHelper.h"
6 | #include "Theme.h"
7 |
8 | CBinaryValueDlg::CBinaryValueDlg(RegistryKey& key, PCWSTR name, bool readOnly, IMainFrame* frame)
9 | : m_Key(key), m_Name(name), m_ReadOnly(readOnly), m_pFrame(frame) {
10 | }
11 |
12 | const std::vector& CBinaryValueDlg::GetValue() const {
13 | return m_Value;
14 | }
15 |
16 | bool CBinaryValueDlg::IsModified() const {
17 | return m_Modified;
18 | }
19 |
20 | void CBinaryValueDlg::BuildToolBar(CRect& rc) {
21 | CToolBarCtrl tb;
22 | tb.Create(m_hWnd, &rc, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR);
23 | tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
24 |
25 | CImageList tbImages;
26 | tbImages.Create(16, 16, ILC_COLOR32, 8, 4);
27 | tb.SetImageList(tbImages);
28 |
29 | const struct {
30 | UINT id;
31 | int image;
32 | BYTE style = BTNS_BUTTON;
33 | BYTE state = TBSTATE_ENABLED;
34 | PCWSTR text = nullptr;
35 | } buttons[] = {
36 | { ID_DATA_BYTE, IDI_NUM1, BTNS_BUTTON | BTNS_CHECKGROUP, TBSTATE_ENABLED | TBSTATE_CHECKED },
37 | { ID_DATA_BYTE + 1, IDI_NUM2, BTNS_BUTTON | BTNS_CHECKGROUP },
38 | { ID_DATA_BYTE + 2, IDI_NUM4, BTNS_BUTTON | BTNS_CHECKGROUP },
39 | { ID_DATA_BYTE + 3, IDI_NUM8_2, BTNS_BUTTON | BTNS_CHECKGROUP },
40 | { 0 },
41 | { ID_LINE, IDI_OPTIONS, BTNS_BUTTON | BTNS_DROPDOWN, TBSTATE_ENABLED, L"Bytes / Line" },
42 | };
43 | for (auto& b : buttons) {
44 | if (b.id == 0)
45 | tb.AddSeparator(0);
46 | else {
47 | HICON hIcon = nullptr;
48 | int image = -1;
49 | if (b.image) {
50 | hIcon = AtlLoadIconImage(b.image, 0, 16, 16);
51 | ATLASSERT(hIcon);
52 | image = tbImages.AddIcon(hIcon);
53 | }
54 | tb.AddButton(b.id, b.style | (b.text ? BTNS_SHOWTEXT : 0), b.state, image, b.text, 0);
55 | }
56 | }
57 | }
58 |
59 | void CBinaryValueDlg::UpdateBufferSize() {
60 | CString text;
61 | auto bytes = (ULONG)m_Buffer.GetSize();
62 | text.Format(L"Size: %u bytes", bytes);
63 | SetDlgItemText(IDC_BUFFERSIZE, text);
64 | }
65 |
66 | LRESULT CBinaryValueDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
67 | InitDynamicLayout();
68 | SetDialogIcon(IDI_BINARY);
69 |
70 | CRect rc;
71 | GetDlgItem(IDC_BUTTON1).GetWindowRect(&rc);
72 | ScreenToClient(&rc);
73 | GetDlgItem(IDC_BUTTON1).ShowWindow(SW_HIDE);
74 |
75 | m_Hex.Create(m_hWnd, &rc, nullptr,
76 | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_CLIENTEDGE, IDC_HEX);
77 | rc.OffsetRect(0, -30);
78 | if (!ThemeHelper::IsDefault()) {
79 | auto theme = ThemeHelper::GetCurrentTheme();
80 | auto& colors = m_Hex.GetColors();
81 | colors.Offset = theme->TextColor;
82 | colors.Ascii = theme->TextColor;
83 | }
84 |
85 | BuildToolBar(rc);
86 |
87 | Helpers::RestoreWindowPosition(m_hWnd, L"BinaryValueDialog");
88 | PostMessage(WM_SIZE);
89 |
90 | ULONG bytes = 0;
91 | m_Key.QueryBinaryValue(m_Name, nullptr, &bytes);
92 | m_Value.resize(bytes);
93 | if (ERROR_SUCCESS != m_Key.QueryBinaryValue(m_Name, m_Value.data(), &bytes)) {
94 | EndDialog(IDRETRY);
95 | return 0;
96 | }
97 |
98 | m_Buffer.Init(m_Value.data(), (uint32_t)m_Value.size());
99 |
100 | UpdateBufferSize();
101 |
102 | m_Hex.SetReadOnly(m_ReadOnly);
103 | m_Hex.SetBufferManager(&m_Buffer);
104 | m_Hex.SetBytesPerLine(8);
105 | m_Hex.SetBiasOffset(0);
106 | m_Hex.SetFocus();
107 |
108 | SetDlgItemText(IDC_NAME, m_Name.IsEmpty() ? Helpers::DefaultValueName : m_Name);
109 |
110 | return 0;
111 | }
112 |
113 | LRESULT CBinaryValueDlg::OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) {
114 | Helpers::SaveWindowPosition(m_hWnd, L"BinaryValueDialog");
115 | handled = FALSE;
116 | return 0;
117 | }
118 |
119 | LRESULT CBinaryValueDlg::OnSize(UINT, WPARAM, LPARAM, BOOL& handled) {
120 | if (m_Hex) {
121 | CRect rc;
122 | GetDlgItem(IDC_BUTTON1).GetWindowRect(&rc);
123 | ScreenToClient(&rc);
124 | m_Hex.MoveWindow(&rc);
125 | }
126 | handled = FALSE;
127 | return 0;
128 | }
129 |
130 | LRESULT CBinaryValueDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
131 | if (IDOK == wID && !m_ReadOnly) {
132 | if (m_Buffer.GetSize() != m_Value.size())
133 | m_Modified = true;
134 | else {
135 | m_Modified = 0 != ::memcmp(m_Value.data(), m_Buffer.GetRawData(0), m_Value.size());
136 | }
137 | if (m_Modified) {
138 | m_Value.resize(m_Buffer.GetSize());
139 | m_Buffer.GetData(0, m_Value.data(), (DWORD)m_Buffer.GetSize());
140 | }
141 | }
142 | EndDialog(wID);
143 | return 0;
144 | }
145 |
146 | LRESULT CBinaryValueDlg::OnHexBufferSizeChanged(int, LPNMHDR, BOOL&) {
147 | UpdateBufferSize();
148 | return 0;
149 | }
150 |
151 | LRESULT CBinaryValueDlg::OnDataSize(WORD, WORD id, HWND, BOOL&) {
152 | m_Hex.SetDataSize(1 << (id - ID_DATA_BYTE));
153 |
154 | return 0;
155 | }
156 |
157 | LRESULT CBinaryValueDlg::OnToolBarDropdown(int, LPNMHDR hdr, BOOL&) {
158 | auto tb = (NMTOOLBAR*)hdr;
159 | CMenu menu;
160 | menu.LoadMenu(IDR_CONTEXT);
161 | CWindow win(hdr->hwndFrom);
162 | CRect rc(tb->rcButton);
163 | rc.OffsetRect(0, rc.Height());
164 | win.ClientToScreen(&rc);
165 | auto id = (UINT)m_pFrame->TrackPopupMenu(menu.GetSubMenu(4), TPM_RETURNCMD, rc.left, rc.top);
166 | if (id) {
167 | LRESULT result = 0;
168 | ProcessWindowMessage(m_hWnd, WM_COMMAND, id, 0, result);
169 | }
170 | return 0;
171 | }
172 |
173 | LRESULT CBinaryValueDlg::OnBytesPerLine(WORD, WORD id, HWND, BOOL&) {
174 | m_Hex.SetBytesPerLine(8 * (id - ID_HEX_8BYTES + 1));
175 |
176 | return 0;
177 | }
178 |
--------------------------------------------------------------------------------
/RegExp/BinaryValueDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DialogHelper.h"
4 | #include "HexControl.h"
5 | #include "MemoryBuffer.h"
6 | #include "IMainFrame.h"
7 | #include "RegistryKey.h"
8 |
9 | class CBinaryValueDlg :
10 | public CDialogImpl,
11 | public CDialogHelper,
12 | public CDynamicDialogLayout {
13 | public:
14 | enum { IDD = IDD_BINVALUE };
15 | enum { ID_DATA_BYTE = 30000, ID_LINE = 30020 };
16 |
17 | CBinaryValueDlg(RegistryKey& key, PCWSTR name, bool readOnly, IMainFrame* frame);
18 |
19 | const std::vector& GetValue() const;
20 | bool IsModified() const;
21 |
22 | BEGIN_MSG_MAP(CBinaryValueDlg)
23 | MESSAGE_HANDLER(WM_SIZE, OnSize)
24 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
25 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
26 | COMMAND_RANGE_HANDLER(ID_DATA_BYTE, ID_DATA_BYTE + 3, OnDataSize)
27 | COMMAND_RANGE_HANDLER(ID_HEX_8BYTES, ID_HEX_32BYTES, OnBytesPerLine)
28 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
29 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
30 | NOTIFY_CODE_HANDLER(HCN_SIZECHANGED, OnHexBufferSizeChanged)
31 | NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnToolBarDropdown)
32 | CHAIN_MSG_MAP(CDynamicDialogLayout)
33 | //REFLECT_NOTIFICATIONS()
34 | END_MSG_MAP()
35 |
36 | // Handler prototypes (uncomment arguments if needed):
37 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
38 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
39 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
40 |
41 | private:
42 | void BuildToolBar(CRect& rc);
43 | void UpdateBufferSize();
44 |
45 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
46 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
47 | LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
48 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
49 | LRESULT OnHexBufferSizeChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
50 | LRESULT OnDataSize(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
51 | LRESULT OnToolBarDropdown(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/);
52 | LRESULT OnBytesPerLine(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
53 |
54 | RegistryKey& m_Key;
55 | CString m_Name;
56 | CHexControl m_Hex;
57 | MemoryBuffer m_Buffer;
58 | std::vector m_Value;
59 | DWORD m_Type{ 0 };
60 | IMainFrame* m_pFrame;
61 | bool m_ReadOnly;
62 | bool m_Modified{ false };
63 | };
64 |
--------------------------------------------------------------------------------
/RegExp/ChangeValueCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ChangeValueCommand.h"
3 | #include "Registry.h"
4 |
5 | ChangeValueCommand::ChangeValueCommand(PCWSTR path, PCWSTR name, DWORD type, const PVOID data, LONG size, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Change Value " + CString(name), path, name, cb), _type(type), _size(size) {
7 | _data = std::make_unique(size);
8 | memcpy(_data.get(), data, size);
9 | }
10 |
11 | bool ChangeValueCommand::Execute() {
12 | auto key = Registry::OpenKey(GetPath(), KEY_SET_VALUE | KEY_QUERY_VALUE);
13 | if (!key)
14 | return false;
15 |
16 | //
17 | // read old value
18 | //
19 | ULONG size = 0;
20 | DWORD type;
21 | key.QueryValue(GetName(), &type, nullptr, &size);
22 | auto buffer = std::make_unique(size);
23 | auto error = key.QueryValue(GetName(), &type, buffer.get(), &size);
24 | if (ERROR_SUCCESS != error) {
25 | ::SetLastError(error);
26 | return false;
27 | }
28 |
29 | //
30 | // make the change
31 | //
32 | error = key.SetValue(GetName(), _type, _data.get(), _size);
33 | if (ERROR_SUCCESS != error) {
34 | ::SetLastError(error);
35 | return false;
36 | }
37 |
38 | _size = size;
39 | _type = type;
40 | _data = std::move(buffer);
41 |
42 | return InvokeCallback(false);
43 | }
44 |
--------------------------------------------------------------------------------
/RegExp/ChangeValueCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct ChangeValueCommand : RegAppCommandBase {
6 | public:
7 | ChangeValueCommand(PCWSTR path, PCWSTR name, DWORD type, const PVOID data, LONG size, AppCommandCallback cb = nullptr);
8 |
9 | bool Execute() override;
10 | bool Undo() override {
11 | return Execute();
12 | }
13 |
14 | private:
15 | LONG _size;
16 | std::unique_ptr _data;
17 | DWORD _type;
18 | };
19 |
--------------------------------------------------------------------------------
/RegExp/CommandManager.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CommandManager.h"
3 | #include "AppCommandBase.h"
4 |
5 | void CommandManager::Enable(bool enable) {
6 | _enabled = enable;
7 | }
8 |
9 | bool CommandManager::IsEnabled() const {
10 | return _enabled;
11 | }
12 |
13 | bool CommandManager::CanUndo() const {
14 | return !_undoList.empty();
15 | }
16 |
17 | bool CommandManager::CanRedo() const {
18 | return !_redoList.empty();
19 | }
20 |
21 | bool CommandManager::AddCommand(std::shared_ptr command, bool execute) {
22 | if (execute)
23 | if (!command->Execute())
24 | return false;
25 |
26 | if (!_enabled)
27 | return true;
28 |
29 | _undoList.push_back(command);
30 | _redoList.clear();
31 | return true;
32 | }
33 |
34 | bool CommandManager::Undo() {
35 | if (!CanUndo())
36 | return false;
37 |
38 | auto cmd = _undoList.back();
39 | auto success = cmd->Undo();
40 | if (success) {
41 | _redoList.push_back(cmd);
42 | _undoList.pop_back();
43 | }
44 | return success;
45 | }
46 |
47 | bool CommandManager::Redo() {
48 | if (!CanRedo())
49 | return false;
50 |
51 | auto command = _redoList.back();
52 | auto success = command->Execute();
53 | if (success) {
54 | _redoList.pop_back();
55 | _undoList.push_back(command);
56 | }
57 | return success;
58 | }
59 |
60 | void CommandManager::Clear() {
61 | _undoList.clear();
62 | _redoList.clear();
63 | }
64 |
65 | AppCommand* CommandManager::GetUndoCommand() const {
66 | return _undoList.empty() ? nullptr : _undoList.back().get();
67 | }
68 |
69 | AppCommand* CommandManager::GetRedoCommand() const {
70 | return _redoList.empty() ? nullptr : _redoList.back().get();
71 | }
72 |
--------------------------------------------------------------------------------
/RegExp/CommandManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct AppCommand;
4 |
5 | class CommandManager {
6 | public:
7 | void Enable(bool enable);
8 | bool IsEnabled() const;
9 |
10 | bool CanUndo() const;
11 | bool CanRedo() const;
12 |
13 | bool AddCommand(std::shared_ptr command, bool execute = true);
14 | bool Undo();
15 | bool Redo();
16 | void Clear();
17 |
18 | AppCommand* GetUndoCommand() const;
19 | AppCommand* GetRedoCommand() const;
20 |
21 | private:
22 | std::vector> _undoList;
23 | std::vector> _redoList;
24 | bool _enabled{ true };
25 | };
26 |
27 |
--------------------------------------------------------------------------------
/RegExp/ConnectRegistryDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include
3 | #include "resource.h"
4 | #include "ConnectRegistryDlg.h"
5 |
6 | const CString& CConnectRegistryDlg::GetComputerName() const {
7 | return m_Name;
8 | }
9 |
10 | LRESULT CConnectRegistryDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
11 | CenterWindow(GetParent());
12 | SetDialogIcon(IDI_REGREMOTE);
13 |
14 | return 0;
15 | }
16 |
17 | LRESULT CConnectRegistryDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
18 | if (wID == IDOK)
19 | GetDlgItemText(IDC_NAME, m_Name);
20 |
21 | EndDialog(wID);
22 | return 0;
23 | }
24 |
25 | LRESULT CConnectRegistryDlg::OnTextChanged(WORD, WORD wID, HWND, BOOL&) {
26 | GetDlgItem(IDOK).EnableWindow(GetDlgItem(IDC_NAME).GetWindowTextLength() > 0);
27 |
28 | return 0;
29 | }
30 |
31 | LRESULT CConnectRegistryDlg::OnBrowse(WORD, WORD wID, HWND, BOOL&) {
32 | IDsObjectPicker* pPicker;
33 | auto hr = ::CoCreateInstance(CLSID_DsObjectPicker, nullptr, CLSCTX_ALL, IID_IDsObjectPicker, reinterpret_cast(&pPicker));
34 | if (FAILED(hr)) {
35 | m_pFrame->DisplayError(L"Failed launch computer selection dialog", m_hWnd, hr & 0xffff);
36 | return 0;
37 | }
38 |
39 | DSOP_INIT_INFO info = { sizeof(info) };
40 | info.cDsScopeInfos = 1;
41 | DSOP_SCOPE_INIT_INFO scope = { sizeof(scope) };
42 | scope.flType = DSOP_SCOPE_TYPE_WORKGROUP | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
43 | scope.flScope = DSOP_SCOPE_FLAG_DEFAULT_FILTER_COMPUTERS;
44 | scope.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
45 | info.aDsScopeInfos = &scope;
46 | hr = pPicker->Initialize(&info);
47 | CComPtr spData;
48 | hr = pPicker->InvokeDialog(m_hWnd, &spData);
49 | pPicker->Release();
50 | if (spData == nullptr || FAILED(hr))
51 | return 0;
52 |
53 | FORMATETC fmt{};
54 | fmt.cfFormat = ::RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
55 | fmt.dwAspect = DVASPECT_CONTENT;
56 | fmt.tymed = TYMED_HGLOBAL;
57 | fmt.lindex = -1;
58 | STGMEDIUM med;
59 | hr = spData->GetData(&fmt, &med);
60 | if (FAILED(hr)) {
61 | m_pFrame->DisplayError(L"Failed to retrieve computer name", m_hWnd, hr & 0xffff);
62 | return 0;
63 | }
64 |
65 | auto data = static_cast(::GlobalLock(med.hGlobal));
66 | ATLASSERT(data);
67 | ATLASSERT(data->cItems >= 1);
68 | SetDlgItemText(IDC_NAME, data->aDsSelection[0].pwzName);
69 | ::GlobalUnfix(med.hGlobal);
70 | ::ReleaseStgMedium(&med);
71 |
72 | return 0;
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/RegExp/ConnectRegistryDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DialogHelper.h"
4 | #include "IMainFrame.h"
5 |
6 | class CConnectRegistryDlg :
7 | public CDialogImpl,
8 | public CDialogHelper {
9 | public:
10 | enum { IDD = IDD_CONNECTREG };
11 |
12 | CConnectRegistryDlg(IMainFrame* frame) : m_pFrame(frame) {}
13 |
14 | const CString& GetComputerName() const;
15 |
16 | BEGIN_MSG_MAP(CConnectRegistryDlg)
17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
18 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
19 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
20 | COMMAND_CODE_HANDLER(EN_CHANGE, OnTextChanged)
21 | COMMAND_ID_HANDLER(IDC_BROWSE, OnBrowse)
22 | REFLECT_NOTIFICATIONS_EX()
23 | END_MSG_MAP()
24 |
25 | // Handler prototypes (uncomment arguments if needed):
26 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
27 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
28 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
29 |
30 | private:
31 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
32 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
33 | LRESULT OnTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
34 | LRESULT OnBrowse(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
35 |
36 | CString m_Name;
37 | IMainFrame* m_pFrame;
38 | };
39 |
--------------------------------------------------------------------------------
/RegExp/CopyKeyCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CopyKeyCommand.h"
3 | #include "Registry.h"
4 |
5 | CopyKeyCommand::CopyKeyCommand(PCWSTR path, PCWSTR name, PCWSTR targetPath, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Paste Key " + CString(name), path, name, cb), _targetPath(targetPath) {
7 | }
8 |
9 | const CString& CopyKeyCommand::GetTargetPath() const {
10 | return _targetPath;
11 | }
12 |
13 | bool CopyKeyCommand::Execute() {
14 | auto key = Registry::OpenKey(_path + L"\\" + _name, KEY_READ);
15 | if (!key)
16 | return false;
17 |
18 | auto targetKey = Registry::CreateKey(_targetPath + L"\\" + _name, KEY_ALL_ACCESS);
19 | if (!targetKey)
20 | return false;
21 |
22 | if (!Registry::CopyKey(key.Get(), nullptr, targetKey))
23 | return false;
24 |
25 | return InvokeCallback(true);
26 | }
27 |
28 | bool CopyKeyCommand::Undo() {
29 | auto key = Registry::OpenKey(_path, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | DELETE);
30 | if (!key)
31 | return false;
32 |
33 | LSTATUS error;
34 | if (ERROR_SUCCESS != (error = ::RegDeleteTree(key.Get(), _name))) {
35 | ::SetLastError(error);
36 | return false;
37 | }
38 | return InvokeCallback(false);
39 | }
40 |
--------------------------------------------------------------------------------
/RegExp/CopyKeyCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct CopyKeyCommand : public RegAppCommandBase {
6 | CopyKeyCommand(PCWSTR path, PCWSTR name, PCWSTR targetPath, AppCommandCallback cb = nullptr);
7 |
8 | const CString& GetTargetPath() const;
9 |
10 | bool Execute() override;
11 | bool Undo() override;
12 |
13 | private:
14 | CString _targetPath;
15 | };
16 |
--------------------------------------------------------------------------------
/RegExp/CopyValueCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CopyValueCommand.h"
3 | #include "Registry.h"
4 |
5 | CopyValueCommand::CopyValueCommand(PCWSTR path, PCWSTR name, PCWSTR targetPath, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Paste value " + CString(name), path, name, cb), _targetPath(targetPath) {
7 | }
8 |
9 | bool CopyValueCommand::Execute() {
10 | auto key = Registry::OpenKey(GetPath(), KEY_QUERY_VALUE);
11 | if (!key)
12 | return false;
13 |
14 | auto target = Registry::OpenKey(_targetPath, KEY_WRITE | KEY_READ);
15 | if (!target)
16 | return false;
17 |
18 | DWORD size = 0;
19 | int i = 1;
20 | auto tname = GetName();
21 | LSTATUS error;
22 | while (ERROR_SUCCESS == (error = target.QueryValue(tname, nullptr, nullptr, &size))) {
23 | // value already exists
24 | if (i++ == 1)
25 | tname = "Copy Of" + _name;
26 | else
27 | tname.Format(L"Copy(%d) Of %s", i, _name);
28 | }
29 | if (error != ERROR_FILE_NOT_FOUND) {
30 | ::SetLastError(error);
31 | return false;
32 | }
33 | _targetName = tname;
34 |
35 | if (!Registry::CopyValue(key.Get(), target.Get(), GetName(), _targetName))
36 | return false;
37 |
38 | return InvokeCallback(true);
39 | }
40 |
41 | bool CopyValueCommand::Undo() {
42 | auto target = Registry::OpenKey(_targetPath, KEY_WRITE);
43 | if (!target)
44 | return false;
45 |
46 | auto error = target.DeleteValue(_targetName);
47 | ::SetLastError(error);
48 | if (ERROR_SUCCESS != error)
49 | return false;
50 |
51 | return InvokeCallback(false);
52 | }
53 |
--------------------------------------------------------------------------------
/RegExp/CopyValueCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct CopyValueCommand : RegAppCommandBase {
6 | CopyValueCommand(PCWSTR path, PCWSTR name, PCWSTR targetPath, AppCommandCallback cb = nullptr);
7 |
8 | bool Execute() override;
9 | bool Undo() override;
10 |
11 | private:
12 | CString _targetPath;
13 | CString _targetName;
14 | };
15 |
--------------------------------------------------------------------------------
/RegExp/CreateKeyCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CreateKeyCommand.h"
3 | #include "Registry.h"
4 |
5 | CreateKeyCommand::CreateKeyCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Create Key " + CString(name), path, name, cb) {
7 | }
8 |
9 | bool CreateKeyCommand::Execute() {
10 | auto key = Registry::OpenKey(_path, KEY_CREATE_SUB_KEY);
11 | if (!key)
12 | return false;
13 |
14 | CRegKey newKey;
15 | DWORD disp;
16 | auto error = newKey.Create(key.Get(), _name, nullptr, 0, KEY_READ | KEY_WRITE, nullptr, &disp);
17 | if (error == ERROR_SUCCESS) {
18 | if (disp == REG_OPENED_EXISTING_KEY) {
19 | ::SetLastError(ERROR_OBJECT_ALREADY_EXISTS);
20 | return false;
21 | }
22 | return InvokeCallback(true);
23 | }
24 | return false;
25 | }
26 |
27 | bool CreateKeyCommand::Undo() {
28 | auto key = Registry::OpenKey(_path, KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE);
29 | if(!key)
30 | return false;
31 |
32 | auto error = ::RegDeleteTree(key.Get(), _name);
33 | ::SetLastError(error);
34 | return ERROR_SUCCESS == error ? InvokeCallback(false) : false;
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/RegExp/CreateKeyCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct CreateKeyCommand : RegAppCommandBase {
6 | CreateKeyCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb = nullptr);
7 |
8 | bool Execute() override;
9 | bool Undo() override;
10 | };
11 |
12 |
--------------------------------------------------------------------------------
/RegExp/CreateValueCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CreateValueCommand.h"
3 | #include "Registry.h"
4 |
5 | CreateValueCommand::CreateValueCommand(PCWSTR path, PCWSTR name, DWORD type, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Create Value " + CString(name), path, name, cb), _type(type) {
7 | }
8 |
9 | bool CreateValueCommand::Execute() {
10 | auto key = Registry::OpenKey(GetPath(), KEY_SET_VALUE);
11 | if (!key)
12 | return false;
13 |
14 | DWORD size = 0;
15 | switch (GetType()) {
16 | case REG_DWORD: size = 4; break;
17 | case REG_QWORD: size = 8; break;
18 | case REG_SZ:
19 | case REG_EXPAND_SZ:
20 | size = 2;
21 | break;
22 |
23 | case REG_MULTI_SZ:
24 | size = 4;
25 | break;
26 | }
27 | BYTE dummy[8] = { 0 };
28 | auto error = key.SetValue(GetName(), GetType(), dummy, _size = size);
29 | ::SetLastError(error);
30 | if (ERROR_SUCCESS != error)
31 | return false;
32 |
33 | return InvokeCallback(true);
34 | }
35 |
36 | bool CreateValueCommand::Undo() {
37 | auto key = Registry::OpenKey(GetPath(), KEY_WRITE);
38 | if (!key)
39 | return false;
40 |
41 | auto error = key.DeleteValue(GetName());
42 | ::SetLastError(error);
43 | if (ERROR_SUCCESS != error)
44 | return false;
45 |
46 | return InvokeCallback(false);
47 | }
48 |
49 | DWORD CreateValueCommand::GetType() const {
50 | return _type;
51 | }
52 |
53 | DWORD CreateValueCommand::GetSize() const {
54 | return _size;
55 | }
56 |
--------------------------------------------------------------------------------
/RegExp/CreateValueCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct CreateValueCommand : RegAppCommandBase {
6 | CreateValueCommand(PCWSTR path, PCWSTR name, DWORD type, AppCommandCallback cb = nullptr);
7 |
8 | bool Execute() override;
9 | bool Undo() override;
10 |
11 | DWORD GetType() const;
12 | DWORD GetSize() const;
13 |
14 | private:
15 | DWORD _type;
16 | DWORD _size{ 0 };
17 | };
18 |
--------------------------------------------------------------------------------
/RegExp/DeleteKeyCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "DeleteKeyCommand.h"
3 | #include "Registry.h"
4 | #include "Helpers.h"
5 |
6 | DeleteKeyCommand::DeleteKeyCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb)
7 | : RegAppCommandBase(L"Delete Key " + CString(name), path, name, cb) {
8 | }
9 |
10 | bool DeleteKeyCommand::Execute() {
11 | auto key = Registry::OpenKey(_path, MAXIMUM_ALLOWED);
12 | if (!key)
13 | return false;
14 |
15 | if (_savePath.IsEmpty()) {
16 | LARGE_INTEGER li;
17 | ::QueryPerformanceCounter(&li);
18 | _savePath.Format(L"%llX", li.QuadPart);
19 | }
20 | CRegKey keyBackup;
21 | auto error = keyBackup.Create(HKEY_CURRENT_USER, DeletedPathBackup + _savePath, nullptr, 0, MAXIMUM_ALLOWED);
22 | ::SetLastError(error);
23 | if (!keyBackup)
24 | return false;
25 | // BUG: RegCopyTree fails if key is one of the predefined keys
26 | ::SetLastError(error = ::RegCopyTree(key.Get(), _name, keyBackup));
27 | if (ERROR_SUCCESS != error)
28 | return false;
29 |
30 | ::SetLastError(error = ::RegDeleteTree(key.Get(), _name));
31 | if (ERROR_SUCCESS != error) {
32 | return false;
33 | }
34 | return InvokeCallback(true);
35 | }
36 |
37 | bool DeleteKeyCommand::Undo() {
38 | auto key = Registry::OpenKey(_path, KEY_CREATE_SUB_KEY);
39 | if (!key)
40 | return false;
41 |
42 | DWORD error;
43 | CRegKey keyBackup;
44 | ::SetLastError(error = keyBackup.Open(HKEY_CURRENT_USER, DeletedPathBackup + _savePath, KEY_READ));
45 | if (!keyBackup)
46 | return false;
47 |
48 | CRegKey newKey;
49 | DWORD disp;
50 | error = newKey.Create(key.Get(), _name, nullptr, 0, KEY_ALL_ACCESS, nullptr, &disp);
51 | ::SetLastError(error);
52 | if (error != ERROR_SUCCESS)
53 | return false;
54 |
55 | ::SetLastError(error = ::RegCopyTree(keyBackup, nullptr, newKey));
56 | if (error != ERROR_SUCCESS)
57 | return false;
58 |
59 | return InvokeCallback(false);
60 | }
61 |
--------------------------------------------------------------------------------
/RegExp/DeleteKeyCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct DeleteKeyCommand : RegAppCommandBase {
6 | DeleteKeyCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb = nullptr);
7 |
8 | bool Execute() override;
9 | bool Undo() override;
10 |
11 | private:
12 | CString _savePath;
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/RegExp/DeleteValueCommand.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "DeleteValueCommand.h"
3 | #include "Registry.h"
4 |
5 | DeleteValueCommand::DeleteValueCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb)
6 | : RegAppCommandBase(L"Delete Value " + CString(name), path, name, cb) {
7 | }
8 |
9 | bool DeleteValueCommand::Execute() {
10 | auto key = Registry::OpenKey(GetPath(), KEY_WRITE | KEY_READ);
11 | if (!key)
12 | return false;
13 |
14 | _size = 0;
15 | auto error = key.QueryValue(GetName(), &_type, nullptr, &_size);
16 | ::SetLastError(error);
17 | if (error != ERROR_SUCCESS)
18 | return false;
19 |
20 | if (_size) {
21 | _data = std::make_unique(_size);
22 | if (!_data) {
23 | ::SetLastError(ERROR_OUTOFMEMORY);
24 | return false;
25 | }
26 | error = key.QueryValue(GetName(), &_type, _data.get(), &_size);
27 | ::SetLastError(error);
28 | if (ERROR_SUCCESS != error)
29 | return false;
30 | }
31 |
32 | error = key.DeleteValue(GetName());
33 | ::SetLastError(error);
34 | if (ERROR_SUCCESS != error)
35 | return false;
36 |
37 | return InvokeCallback(true);
38 | }
39 |
40 | bool DeleteValueCommand::Undo() {
41 | auto key = Registry::OpenKey(GetPath(), KEY_WRITE);
42 | if (!key)
43 | return false;
44 |
45 | auto error = key.SetValue(GetName(), _type, _data.get(), _size);
46 | ::SetLastError(error);
47 | if (ERROR_SUCCESS != error)
48 | return false;
49 |
50 | return InvokeCallback(false);
51 | }
52 |
--------------------------------------------------------------------------------
/RegExp/DeleteValueCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "AppCommandBase.h"
4 |
5 | struct DeleteValueCommand : RegAppCommandBase {
6 | DeleteValueCommand(PCWSTR path, PCWSTR name, AppCommandCallback cb = nullptr);
7 |
8 | bool Execute() override;
9 | bool Undo() override;
10 |
11 | private:
12 | DWORD _type;
13 | std::unique_ptr _data;
14 | DWORD _size;
15 | };
16 |
--------------------------------------------------------------------------------
/RegExp/DriverHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "DriverHelper.h"
3 | #include "SecurityHelper.h"
4 | #include "resource.h"
5 | #include
6 | #include
7 | #include "..\KRegExp\KRegExpCommon.h"
8 |
9 | wil::unique_hfile _hDevice;
10 |
11 | bool DriverHelper::LoadDriver() {
12 | if (!SecurityHelper::IsRunningElevated())
13 | return false;
14 |
15 | wil::unique_schandle hScm(::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
16 | if (!hScm)
17 | return false;
18 |
19 | wil::unique_schandle hService(::OpenService(hScm.get(), L"KRegExp", SERVICE_START));
20 | if (!hService && !InstallDriver())
21 | return false;
22 |
23 | hService.reset(::OpenService(hScm.get(), L"KRegExp", SERVICE_START));
24 | if (!hService)
25 | return false;
26 |
27 | return ::StartService(hService.get(), 0, nullptr);
28 | }
29 |
30 | bool DriverHelper::InstallDriver() {
31 | if (!SecurityHelper::IsRunningElevated())
32 | return false;
33 |
34 | auto hRes = ::FindResource(nullptr, MAKEINTRESOURCE(IDR_DRIVER), L"BIN");
35 | if (!hRes)
36 | return false;
37 |
38 | auto hGlobal = ::LoadResource(nullptr, hRes);
39 | if (!hGlobal)
40 | return false;
41 |
42 | auto size = ::SizeofResource(nullptr, hRes);
43 | void* pBuffer = ::LockResource(hGlobal);
44 |
45 | WCHAR path[MAX_PATH];
46 | ::GetSystemDirectory(path, MAX_PATH);
47 | ::wcscat_s(path, L"\\Drivers\\KRegExp.sys");
48 | wil::unique_hfile hFile(::CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM, nullptr));
49 | if (!hFile)
50 | return false;
51 |
52 | DWORD bytes = 0;
53 | ::WriteFile(hFile.get(), pBuffer, size, &bytes, nullptr);
54 | if (bytes != size)
55 | return false;
56 |
57 | wil::unique_schandle hScm(::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
58 | if (!hScm)
59 | return false;
60 |
61 | wil::unique_schandle hService(::CreateService(hScm.get(), L"KRegExp", nullptr, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,
62 | SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path, nullptr, nullptr, nullptr, nullptr, nullptr));
63 |
64 | return hService != nullptr;
65 | }
66 |
67 | HANDLE DriverHelper::OpenKey(PCWSTR name, ACCESS_MASK access) {
68 | if (!OpenDevice())
69 | return nullptr;
70 |
71 | auto len = (ULONG)::wcslen(name);
72 | DWORD size = len * sizeof(WCHAR) + sizeof(KeyData);
73 | auto buffer = std::make_unique(size);
74 | if (!buffer)
75 | return nullptr;
76 | auto data = reinterpret_cast(buffer.get());
77 | data->Access = access;
78 | data->Length = len;
79 | ::wcscpy_s(data->Name, len + 1, name);
80 |
81 | DWORD bytes;
82 | HANDLE hObject = nullptr;
83 | ::DeviceIoControl(_hDevice.get(), IOCTL_KREGEXP_OPEN_KEY, data, size,
84 | &hObject, sizeof(hObject), &bytes, nullptr);
85 |
86 | return hObject;
87 | }
88 |
89 | HANDLE DriverHelper::DupHandle(HANDLE hObject, ULONG pid, ACCESS_MASK access, DWORD flags) {
90 | HANDLE hTarget = nullptr;
91 | if (OpenDevice()) {
92 | DupHandleData data;
93 | data.AccessMask = access;
94 | data.Handle = hObject;
95 | data.SourcePid = pid;
96 | data.Flags = flags;
97 |
98 | DWORD bytes;
99 | ::DeviceIoControl(_hDevice.get(), IOCTL_KREGEXP_DUP_HANDLE, &data, sizeof(data),
100 | &hTarget, sizeof(hTarget), &bytes, nullptr);
101 | }
102 | return hTarget;
103 | }
104 |
105 | bool DriverHelper::IsDriverLoaded() {
106 | wil::unique_schandle hScm(::OpenSCManager(nullptr, nullptr, SC_MANAGER_ENUMERATE_SERVICE));
107 | if (!hScm)
108 | return false;
109 |
110 | wil::unique_schandle hService(::OpenService(hScm.get(), L"KRegExp", SERVICE_QUERY_STATUS));
111 | if (!hService)
112 | return false;
113 |
114 | SERVICE_STATUS status;
115 | if (!::QueryServiceStatus(hService.get(), &status))
116 | return false;
117 |
118 | return status.dwCurrentState == SERVICE_RUNNING;
119 | }
120 |
121 | bool DriverHelper::OpenDevice() {
122 | if (SecurityHelper::IsRunningElevated() && !_hDevice) {
123 | _hDevice.reset(::CreateFile(L"\\\\.\\KRegExp", GENERIC_WRITE | GENERIC_READ,
124 | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
125 | OPEN_EXISTING, 0, nullptr));
126 | }
127 | return (bool)_hDevice;
128 | }
129 |
--------------------------------------------------------------------------------
/RegExp/DriverHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct DriverHelper abstract final {
4 | static bool LoadDriver();
5 | static bool InstallDriver();
6 | static bool IsDriverLoaded();
7 | static bool OpenDevice();
8 | static HANDLE DupHandle(HANDLE hObject, ULONG pid, ACCESS_MASK access, DWORD flags);
9 | static HANDLE OpenKey(PCWSTR name, ACCESS_MASK access);
10 | };
11 |
--------------------------------------------------------------------------------
/RegExp/EnumStrings.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "EnumStrings.h"
3 | #include "Registry.h"
4 |
5 | void CEnumStrings::SetRegistryPath(const CString& path) {
6 | _path = path;
7 | }
8 |
9 | bool CEnumStrings::GenerateStrings(const CString& path) {
10 | _strings.clear();
11 | _current = 0;
12 | if (path.IsEmpty()) {
13 | for (auto& key : Registry::Keys) {
14 | _strings.push_back(key.text);
15 | }
16 | return true;
17 | }
18 | if (path == L"\\") {
19 | _strings.push_back(L"\\REGISTRY");
20 | return true;
21 | }
22 | auto key = Registry::OpenKey(path, KEY_READ);
23 | if (!key)
24 | return false;
25 | Registry::EnumSubKeys(key.Get(), [&](auto name, const auto&) {
26 | _strings.push_back(path + name);
27 | return TRUE;
28 | });
29 |
30 | return true;
31 | }
32 |
33 | HRESULT __stdcall CEnumStrings::Next(ULONG celt, LPOLESTR* rgelt, ULONG* pceltFetched) {
34 | if (_strings.empty()) {
35 | if(pceltFetched)
36 | *pceltFetched = 0;
37 |
38 | // generate strings
39 | if (!GenerateStrings(_path))
40 | return E_FAIL;
41 | }
42 | if (celt == 0)
43 | return S_OK;
44 |
45 | ULONG i = 0;
46 | for (; i < celt; i++) {
47 | auto index = _current + i;
48 | if (index >= _strings.size())
49 | break;
50 | CString& str(_strings[index]);
51 | rgelt[i] = (PWSTR)::CoTaskMemAlloc((str.GetLength() + 1) * sizeof(WCHAR));
52 | wcscpy_s(rgelt[i], str.GetLength() + 1, str);
53 | ATLTRACE(L"Added string: %s\n", rgelt[i]);
54 | }
55 | if (pceltFetched)
56 | *pceltFetched = i;
57 | _current += i;
58 | return i < celt ? S_FALSE : S_OK;
59 | }
60 |
61 | HRESULT __stdcall CEnumStrings::Skip(ULONG celt) {
62 | _current += celt;
63 | return S_OK;
64 | }
65 |
66 | HRESULT __stdcall CEnumStrings::Reset(void) {
67 | _current = 0;
68 | return S_OK;
69 | }
70 |
71 | HRESULT __stdcall CEnumStrings::Clone(IEnumString** ppenum) {
72 | CComObject* p;
73 | auto hr = p->CreateInstance(&p);
74 | if (FAILED(hr))
75 | return hr;
76 |
77 | p->SetRegistryPath(_path);
78 | p->_current = _current;
79 | p->_strings = _strings;
80 |
81 | return p->QueryInterface(ppenum);
82 | }
83 |
84 | HRESULT __stdcall CEnumStrings::Expand(PCWSTR pszExpand) {
85 | _path = pszExpand;
86 | _strings.clear();
87 | return S_OK;
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/RegExp/EnumStrings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class CEnumStrings :
4 | public CComObjectRoot,
5 | public IEnumString,
6 | public IACList {
7 | public:
8 | BEGIN_COM_MAP(CEnumStrings)
9 | COM_INTERFACE_ENTRY(IEnumString)
10 | COM_INTERFACE_ENTRY(IACList)
11 | END_COM_MAP()
12 |
13 | void SetRegistryPath(const CString& path);
14 |
15 | private:
16 | bool GenerateStrings(const CString& path);
17 |
18 | // Inherited via IEnumString
19 | HRESULT __stdcall Next(ULONG celt, LPOLESTR* rgelt, ULONG* pceltFetched) override;
20 | HRESULT __stdcall Skip(ULONG celt) override;
21 | HRESULT __stdcall Reset(void) override;
22 | HRESULT __stdcall Clone(IEnumString** ppenum) override;
23 |
24 | // Inherited via IACList
25 | HRESULT __stdcall Expand(PCWSTR pszExpand) override;
26 |
27 | CString _path;
28 | std::vector _strings;
29 | size_t _current{ 0 };
30 |
31 | };
32 |
--------------------------------------------------------------------------------
/RegExp/ExportDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "resource.h"
3 | #include "ExportDlg.h"
4 | #include "ThemeHelper.h"
5 |
6 | void CExportDlg::SetKeyPath(PCWSTR path) {
7 | m_Key = path;
8 | }
9 |
10 | const CString& CExportDlg::GetSelectedKey() const {
11 | return m_Key;
12 | }
13 |
14 | const CString& CExportDlg::GetFileName() const {
15 | return m_FileName;
16 | }
17 |
18 | LRESULT CExportDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
19 | SetDialogIcon(IDI_EXPORT);
20 | SetDlgItemText(IDC_KEY, m_Key);
21 | CheckDlgButton(IDC_EXPORTKEY, BST_CHECKED);
22 | ::SHAutoComplete(GetDlgItem(IDC_PATH), SHACF_FILESYS_ONLY);
23 |
24 | return 0;
25 | }
26 |
27 | LRESULT CExportDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
28 | if (wID == IDOK) {
29 | if (IsDlgButtonChecked(IDC_EXPORT_REAL))
30 | m_Key.Empty();
31 | else
32 | GetDlgItemText(IDC_KEY, m_Key);
33 | GetDlgItemText(IDC_PATH, m_FileName);
34 | }
35 | EndDialog(wID);
36 | return 0;
37 | }
38 |
39 | LRESULT CExportDlg::OnBrowse(WORD, WORD wID, HWND, BOOL&) {
40 | ThemeHelper::Suspend();
41 | CSimpleFileDialog dlg(FALSE, L"Reg", nullptr,
42 | OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY,
43 | L"REG format (*reg)\0*.reg\0Native Format\0*.*\0", m_hWnd);
44 | if (dlg.DoModal() == IDOK) {
45 | SetDlgItemText(IDC_PATH, dlg.m_szFileName);
46 | }
47 | ThemeHelper::Resume();
48 | return 0;
49 | }
50 |
51 | LRESULT CExportDlg::OnPathTextChanged(WORD, WORD wID, HWND, BOOL&) {
52 | GetDlgItem(IDOK).EnableWindow(GetDlgItem(IDC_PATH).GetWindowTextLength() > 0
53 | && (IsDlgButtonChecked(IDC_EXPORT_REAL) == BST_CHECKED || GetDlgItem(IDC_KEY).GetWindowTextLength() > 0));
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/RegExp/ExportDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DialogHelper.h"
4 |
5 | class CExportDlg :
6 | public CDialogHelper,
7 | public CDialogImpl {
8 | public:
9 | enum { IDD = IDD_EXPORT };
10 |
11 | void SetKeyPath(PCWSTR path);
12 |
13 | const CString& GetSelectedKey() const;
14 | const CString& GetFileName() const;
15 |
16 | BEGIN_MSG_MAP(CExportDlg)
17 | COMMAND_HANDLER(IDC_PATH, EN_CHANGE, OnPathTextChanged)
18 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
19 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
20 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
21 | COMMAND_ID_HANDLER(IDC_BROWSE, OnBrowse)
22 | REFLECT_NOTIFICATIONS_EX()
23 | END_MSG_MAP()
24 |
25 | private:
26 | // Handler prototypes (uncomment arguments if needed):
27 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
28 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
29 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
30 |
31 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
32 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
33 | LRESULT OnBrowse(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
34 | LRESULT OnPathTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
35 |
36 | CString m_Key;
37 | CString m_FileName;
38 | };
39 |
--------------------------------------------------------------------------------
/RegExp/FindAllDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "FindOptions.h"
4 | #include "AppSettings.h"
5 | #include "DialogHelper.h"
6 | #include "RegistrySearcher.h"
7 | #include "IMainFrame.h"
8 | #include "VirtualListView.h"
9 |
10 | class CFindAllDlg :
11 | public CDialogImpl,
12 | public CDynamicDialogLayout,
13 | public CVirtualListView,
14 | public CDialogHelper {
15 | public:
16 | enum { IDD = IDD_FINDALL };
17 |
18 | const UINT WM_SEARCH_COMPLETE = WM_APP + 1;
19 |
20 | explicit CFindAllDlg(IMainFrame* frame);
21 |
22 | void UpdateUI();
23 | void Cancel();
24 | void OnFinalMessage(HWND) override;
25 |
26 | CString GetColumnText(HWND, int row, int col) const;
27 | int GetRowImage(HWND, int row, int) const;
28 | void DoSort(const SortInfo* si);
29 |
30 | bool OnDoubleClickList(HWND, int row, int, const POINT&);
31 |
32 | BEGIN_MSG_MAP(CFindAllDlg)
33 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
34 | MESSAGE_HANDLER(WM_SEARCH_COMPLETE, OnSearchComplete)
35 | COMMAND_ID_HANDLER(IDC_FIND, OnFind)
36 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
37 | COMMAND_ID_HANDLER(IDC_CANCEL, OnCancel)
38 | COMMAND_ID_HANDLER(IDC_SAVE, OnSaveResults)
39 | COMMAND_ID_HANDLER(IDC_LOAD, OnLoadResults)
40 | COMMAND_ID_HANDLER(IDC_DELETE, OnDelete)
41 | COMMAND_ID_HANDLER(IDC_COPY, OnCopy)
42 | COMMAND_CODE_HANDLER(EN_CHANGE, OnTextChanged)
43 | COMMAND_CODE_HANDLER(BN_CLICKED, OnClick)
44 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
45 | CHAIN_MSG_MAP(CVirtualListView)
46 | CHAIN_MSG_MAP(CDynamicDialogLayout)
47 | REFLECT_NOTIFICATIONS_EX()
48 | END_MSG_MAP()
49 |
50 | // Handler prototypes (uncomment arguments if needed):
51 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
52 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
53 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
54 |
55 | private:
56 | struct ListItem {
57 | CString Path;
58 | CString Name;
59 | CString Data;
60 | };
61 |
62 | bool CheckButton(UINT id, FindOptions options, FindOptions value);
63 | FindOptions UpdateOptions();
64 |
65 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
66 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
67 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
68 | LRESULT OnFind(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
69 | LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
70 | LRESULT OnTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
71 | LRESULT OnClick(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
72 | LRESULT OnSearchComplete(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
73 | LRESULT OnSaveResults(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
74 | LRESULT OnLoadResults(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
75 | LRESULT OnCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
76 | LRESULT OnDelete(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
77 |
78 | IMainFrame* m_pFrame;
79 | RegistrySearcher m_Searcher;
80 | CListViewCtrl m_List;
81 | CProgressBarCtrl m_Progress;
82 | std::vector m_Items;
83 | };
84 |
--------------------------------------------------------------------------------
/RegExp/FindDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "resource.h"
3 | #include "FindDlg.h"
4 |
5 | CFindDlg::CFindDlg(IMainFrame* frame) : m_pFrame(frame) {
6 | }
7 |
8 | void CFindDlg::UpdateUI() {
9 | auto options = AppSettings::Get().Find();
10 | CheckButton(IDC_SEARCH_KEYS, options, FindOptions::SearchKeys);
11 | CheckButton(IDC_SEARCH_VALUES, options, FindOptions::SearchValues);
12 | CheckButton(IDC_SEARCH_DATA, options, FindOptions::SearchData);
13 | if (!CheckButton(IDC_SEARCH_SELECTED, options, FindOptions::SearchSelected))
14 | CheckDlgButton(IDC_SEARCH_ALL, BST_CHECKED);
15 | CheckButton(IDC_SEARCH_MATCHWHOLE, options, FindOptions::MatchWholeWords);
16 | CheckButton(IDC_SEARCH_CASE, options, FindOptions::MatchCase);
17 | CheckButton(IDC_SEARCH_STD, options, FindOptions::SearchStdRegistry);
18 | CheckButton(IDC_SEARCH_REAL, options, FindOptions::SearchRealRegistry);
19 | GetDlgItem(IDC_CANCEL).EnableWindow(m_Searcher.IsRunning());
20 |
21 | }
22 |
23 | void CFindDlg::Cancel() {
24 | m_Searcher.Cancel();
25 | }
26 |
27 | void CFindDlg::Continue() {
28 | m_Searcher.Continue();
29 | }
30 |
31 | bool CFindDlg::IsFindNextAvailable() const {
32 | return IsWindow() && GetDlgItem(IDC_TEXT).GetWindowTextLength() > 0;
33 | }
34 |
35 | bool CFindDlg::CheckButton(UINT id, FindOptions options, FindOptions value) {
36 | bool check = (options & value) == value;
37 | CheckDlgButton(id, check ? BST_CHECKED : BST_UNCHECKED);
38 | return check;
39 | }
40 |
41 | FindOptions CFindDlg::UpdateOptions() {
42 | //
43 | // save options
44 | //
45 | auto options = FindOptions::None;
46 | if (IsDlgButtonChecked(IDC_SEARCH_KEYS))
47 | options |= FindOptions::SearchKeys;
48 | if (IsDlgButtonChecked(IDC_SEARCH_VALUES))
49 | options |= FindOptions::SearchValues;
50 | if (IsDlgButtonChecked(IDC_SEARCH_DATA))
51 | options |= FindOptions::SearchData;
52 | if (IsDlgButtonChecked(IDC_SEARCH_SELECTED))
53 | options |= FindOptions::SearchSelected;
54 | if (IsDlgButtonChecked(IDC_SEARCH_STD))
55 | options |= FindOptions::SearchStdRegistry;
56 | if (IsDlgButtonChecked(IDC_SEARCH_REAL))
57 | options |= FindOptions::SearchRealRegistry;
58 | if (IsDlgButtonChecked(IDC_SEARCH_MATCHWHOLE))
59 | options |= FindOptions::MatchWholeWords;
60 | if (IsDlgButtonChecked(IDC_SEARCH_CASE))
61 | options |= FindOptions::MatchCase;
62 |
63 | AppSettings::Get().Find(options);
64 | return options;
65 | }
66 |
67 | LRESULT CFindDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
68 | CenterWindow(m_pFrame->GetHwnd());
69 | SetDialogIcon(IDI_FIND);
70 | AddIconToButton(IDC_CANCEL, IDI_DELETE);
71 | AddIconToButton(IDC_FIND, IDI_FIND_NEXT);
72 | AddIconToButton(IDC_NEW, IDI_FIND);
73 |
74 | m_Progress.Attach(GetDlgItem(IDC_PROGRESS));
75 | ::SetWindowTheme(m_Progress, L"Explorer", L"");
76 | m_Progress.SetMarquee(TRUE);
77 | UpdateUI();
78 |
79 | return 0;
80 | }
81 |
82 | LRESULT CFindDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
83 | m_Searcher.Cancel();
84 | UpdateOptions();
85 | ShowWindow(SW_HIDE);
86 | return 0;
87 | }
88 |
89 | LRESULT CFindDlg::OnFind(WORD, WORD wID, HWND, BOOL&) {
90 | auto options = UpdateOptions();
91 | GetDlgItem(IDC_FIND).EnableWindow(FALSE);
92 | GetDlgItem(IDC_NEW).EnableWindow(FALSE);
93 | GetDlgItem(IDC_CANCEL).EnableWindow();
94 | m_Progress.ShowWindow(SW_SHOW);
95 |
96 | CString text;
97 | GetDlgItemText(IDC_TEXT, text);
98 | m_Searcher.SetText(text);
99 | m_Searcher.SetOptions(options);
100 | SetDlgItemText(IDC_STATUS, L"Searching...");
101 | if (m_Searcher.IsRunning()) {
102 | m_Searcher.Continue();
103 | return 0;
104 | }
105 |
106 | m_Searcher.SetStartKey(m_pFrame->GetCurrentKeyPath());
107 | m_Searcher.Find([&](auto path, auto name, auto data) {
108 | ResetUI();
109 | if (path == nullptr) {
110 | // search done
111 | m_pFrame->OnFindEnd(m_Searcher.IsCancelled());
112 | }
113 | else {
114 | m_pFrame->OnFindNext(path, name, data);
115 | }
116 | });
117 |
118 | return 0;
119 | }
120 |
121 | LRESULT CFindDlg::OnCancel(WORD, WORD wID, HWND, BOOL&) {
122 | if(m_Searcher.IsRunning())
123 | m_Searcher.Cancel();
124 |
125 | return 0;
126 | }
127 |
128 | LRESULT CFindDlg::OnNewSearch(WORD, WORD wID, HWND, BOOL&) {
129 | m_Searcher.Cancel();
130 | return 0;
131 | }
132 |
133 | LRESULT CFindDlg::OnTextChanged(WORD, WORD wID, HWND, BOOL&) {
134 | GetDlgItem(IDC_FIND).EnableWindow(GetDlgItem(IDC_TEXT).GetWindowTextLength() > 0);
135 | return 0;
136 | }
137 |
138 | LRESULT CFindDlg::OnClick(WORD, WORD wID, HWND, BOOL&) {
139 | if (GetDlgItem(IDC_FIND).IsWindowEnabled()) {
140 | if (IsDlgButtonChecked(IDC_SEARCH_STD) == BST_UNCHECKED && IsDlgButtonChecked(IDC_SEARCH_REAL) == BST_UNCHECKED)
141 | GetDlgItem(IDC_FIND).EnableWindow(FALSE);
142 | }
143 | return 0;
144 | }
145 |
146 | void CFindDlg::ResetUI() {
147 | GetDlgItem(IDC_FIND).EnableWindow(TRUE);
148 | GetDlgItem(IDC_CANCEL).EnableWindow(FALSE);
149 | GetDlgItem(IDC_NEW).EnableWindow();
150 | m_Progress.ShowWindow(SW_HIDE);
151 | SetDlgItemText(IDC_STATUS, L"");
152 | }
153 |
--------------------------------------------------------------------------------
/RegExp/FindDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "FindOptions.h"
4 | #include "AppSettings.h"
5 | #include "DialogHelper.h"
6 | #include "RegistrySearcher.h"
7 | #include "IMainFrame.h"
8 |
9 | class CFindDlg :
10 | public CDialogImpl,
11 | public CDialogHelper {
12 | public:
13 | enum { IDD = IDD_FIND };
14 |
15 | CFindDlg(IMainFrame* frame);
16 |
17 | void UpdateUI();
18 | void Cancel();
19 | void Continue();
20 | bool IsFindNextAvailable() const;
21 |
22 | BEGIN_MSG_MAP(CFindDlg)
23 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
24 | COMMAND_ID_HANDLER(IDC_FIND, OnFind)
25 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
26 | COMMAND_ID_HANDLER(IDC_CANCEL, OnCancel)
27 | COMMAND_ID_HANDLER(IDC_NEW, OnNewSearch)
28 | COMMAND_CODE_HANDLER(EN_CHANGE, OnTextChanged)
29 | COMMAND_CODE_HANDLER(BN_CLICKED, OnClick)
30 | REFLECT_NOTIFICATIONS_EX()
31 | END_MSG_MAP()
32 |
33 | // Handler prototypes (uncomment arguments if needed):
34 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
35 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
36 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
37 |
38 | private:
39 | bool CheckButton(UINT id, FindOptions options, FindOptions value);
40 | FindOptions UpdateOptions();
41 | void ResetUI();
42 |
43 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
44 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
45 | LRESULT OnFind(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
46 | LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
47 | LRESULT OnNewSearch(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
48 | LRESULT OnTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
49 | LRESULT OnClick(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
50 |
51 | IMainFrame* m_pFrame;
52 | RegistrySearcher m_Searcher;
53 | CProgressBarCtrl m_Progress;
54 | };
55 |
--------------------------------------------------------------------------------
/RegExp/FindOptions.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum class FindOptions {
4 | None = 0,
5 | SearchKeys = 1,
6 | SearchValues = 2,
7 | SearchData = 4,
8 | SearchRealRegistry = 8,
9 | SearchStdRegistry = 16,
10 | MatchCase = 0x20,
11 | MatchWholeWords = 0x40,
12 | SearchSelected = 0x80,
13 | };
14 | DEFINE_ENUM_FLAG_OPERATORS(FindOptions);
15 |
--------------------------------------------------------------------------------
/RegExp/GotoKeyDlg.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Resource.h"
3 | #include "GotoKeyDlg.h"
4 | #include "EnumStrings.h"
5 |
6 | const CString& CGotoKeyDlg::GetKey() const {
7 | return m_Key;
8 | }
9 |
10 | void CGotoKeyDlg::SetKey(const CString& key) {
11 | m_Key = key;
12 | }
13 |
14 | LRESULT CGotoKeyDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
15 | CenterWindow(GetParent());
16 | SetDialogIcon(IDI_GOTO);
17 |
18 | SetDlgItemText(IDC_PATH, m_Key);
19 | GetDlgItem(IDOK).EnableWindow(!m_Key.IsEmpty());
20 |
21 | CComObject* pEnum;
22 | pEnum->CreateInstance(&pEnum);
23 | CComPtr spAC;
24 | auto hr = spAC.CoCreateInstance(CLSID_AutoComplete);
25 | if(spAC) {
26 | spAC->Init(GetDlgItem(IDC_PATH), pEnum->GetUnknown(), nullptr, nullptr);
27 | spAC->SetOptions(ACO_AUTOSUGGEST | ACO_USETAB | ACO_AUTOAPPEND);
28 | }
29 |
30 | return 0;
31 | }
32 |
33 | LRESULT CGotoKeyDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
34 | if (wID == IDOK) {
35 | GetDlgItemText(IDC_PATH, m_Key);
36 | }
37 | EndDialog(wID);
38 | return 0;
39 | }
40 |
41 | LRESULT CGotoKeyDlg::OnChangeText(WORD, WORD wID, HWND, BOOL&) {
42 | GetDlgItem(IDOK).EnableWindow(GetDlgItem(IDC_PATH).GetWindowTextLength() > 1);
43 | return 0;
44 | }
45 |
--------------------------------------------------------------------------------
/RegExp/GotoKeyDlg.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DialogHelper.h"
4 |
5 | class CGotoKeyDlg :
6 | public CDialogImpl,
7 | public CDialogHelper {
8 | public:
9 | enum { IDD = IDD_GOTOKEY };
10 |
11 | const CString& GetKey() const;
12 | void SetKey(const CString& key);
13 |
14 | BEGIN_MSG_MAP(CGotoKeyDlg)
15 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
16 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
17 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
18 | COMMAND_HANDLER(IDC_PATH, EN_CHANGE, OnChangeText)
19 | REFLECT_NOTIFICATIONS_EX()
20 | END_MSG_MAP()
21 |
22 | // Handler prototypes (uncomment arguments if needed):
23 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
24 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
25 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
26 |
27 | private:
28 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
29 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
30 | LRESULT OnChangeText(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
31 |
32 | CString m_Key;
33 | };
34 |
--------------------------------------------------------------------------------
/RegExp/Helpers.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Helpers.h"
3 | #include "AppSettings.h"
4 | #include "NtDll.h"
5 | #include "SecurityHelper.h"
6 | #include
7 | #include
8 |
9 | bool Helpers::SaveWindowPosition(HWND hWnd, PCWSTR name) {
10 | CRect rc;
11 | ::GetWindowRect(hWnd, &rc);
12 | AppSettings::Get().Set(name, rc);
13 | return true;
14 | }
15 |
16 | bool Helpers::RestoreWindowPosition(HWND hWnd, PCWSTR name) {
17 | auto rc = AppSettings::Get().GetBinary(name);
18 | if (rc) {
19 | ::SetWindowPos(hWnd, nullptr, rc->left, rc->top, rc->Width(), rc->Height(), SWP_NOREPOSITION);
20 | return true;
21 | }
22 | return false;
23 | }
24 |
25 | CString Helpers::ToBinary(ULONGLONG value) {
26 | CString svalue;
27 |
28 | while (value) {
29 | svalue = ((value & 1) ? L"1" : L"0") + svalue;
30 | value >>= 1;
31 | }
32 | if (svalue.IsEmpty())
33 | svalue = L"0";
34 | return svalue;
35 | }
36 |
37 | PCWSTR Helpers::GetSystemDirectory() {
38 | static WCHAR dir[MAX_PATH];
39 | if (dir[0] == 0)
40 | ::GetSystemDirectory(dir, _countof(dir));
41 |
42 | return dir;
43 | }
44 |
45 | PCWSTR Helpers::GetWindowsDirectory() {
46 | static WCHAR dir[MAX_PATH];
47 | if (dir[0] == 0)
48 | ::GetWindowsDirectory(dir, _countof(dir));
49 |
50 | return dir;
51 | }
52 |
53 | COLORREF Helpers::ParseColor(const CString& text) {
54 | int index = 0;
55 | CString token;
56 | COLORREF color = 0;
57 | int shift = 0;
58 | while (!(token = text.Tokenize(L" ", index)).IsEmpty()) {
59 | if (shift > 24)
60 | return CLR_INVALID;
61 | int n = _wtoi(token);
62 | if (n < 0 || n > 255)
63 | return CLR_INVALID;
64 | color |= (n << shift);
65 | shift += 8;
66 | }
67 | return color;
68 | }
69 |
70 | CString Helpers::GetObjectName(HANDLE hObject, DWORD pid) {
71 | auto h = SecurityHelper::DupHandle(hObject, pid, KEY_QUERY_VALUE);
72 | if (h) {
73 | BYTE buffer[2048];
74 | auto status = NtQueryObject(h, ObjectNameInformation, buffer, sizeof(buffer), nullptr);
75 | ::CloseHandle(h);
76 | if (STATUS_SUCCESS == status) {
77 | auto str = reinterpret_cast(buffer);
78 | return CString(str->Buffer, str->Length / sizeof(WCHAR));
79 | }
80 | }
81 | return L"";
82 | }
83 |
84 | USHORT Helpers::GetKeyObjectTypeIndex() {
85 | static USHORT keyIndex = 0;
86 | if (keyIndex == 0) {
87 | const ULONG len = 1 << 14;
88 | auto buffer = std::make_unique(len);
89 | if (!NT_SUCCESS(NtQueryObject(nullptr, ObjectTypesInformation, buffer.get(), len, nullptr)))
90 | return 0;
91 |
92 | auto p = reinterpret_cast(buffer.get());
93 | auto raw = &p->TypeInformation[0];
94 | for (ULONG i = 0; i < p->NumberOfTypes; i++) {
95 | if (_wcsicmp(raw->TypeName.Buffer, L"Key") == 0) {
96 | keyIndex = raw->TypeIndex;
97 | break;
98 | }
99 | auto temp = (BYTE*)raw + sizeof(OBJECT_TYPE_INFORMATION) + raw->TypeName.MaximumLength;
100 | temp += sizeof(PVOID) - 1;
101 | raw = reinterpret_cast((ULONG_PTR)temp / sizeof(PVOID) * sizeof(PVOID));
102 | }
103 | }
104 | return keyIndex;
105 | }
106 |
107 | CString Helpers::GetErrorText(DWORD error) {
108 | ATLASSERT(error);
109 | PWSTR buffer;
110 | CString msg;
111 | if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
112 | nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buffer, 0, nullptr)) {
113 | msg = buffer;
114 | ::LocalFree(buffer);
115 | msg.Trim(L"\n\r");
116 | }
117 | return msg;
118 | }
119 |
120 | CString Helpers::GetProcessNameById(DWORD pid) {
121 | static std::unordered_map processes;
122 | if (processes.empty()) {
123 | auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
124 | ATLASSERT(hSnapshot != INVALID_HANDLE_VALUE);
125 | if (hSnapshot == INVALID_HANDLE_VALUE)
126 | return L"";
127 |
128 | PROCESSENTRY32 pe;
129 | pe.dwSize = sizeof(pe);
130 | ::Process32First(hSnapshot, &pe);
131 |
132 | while (::Process32Next(hSnapshot, &pe)) {
133 | processes.insert({ pe.th32ProcessID, pe.szExeFile });
134 | }
135 | ::CloseHandle(hSnapshot);
136 | }
137 |
138 | if (auto it = processes.find(pid); it != processes.end()) {
139 | wil::unique_handle hProcess(::OpenProcess(SYNCHRONIZE, FALSE, pid));
140 | if (hProcess && ::WaitForSingleObject(hProcess.get(), 0) == WAIT_OBJECT_0) {
141 | // process is dead
142 | processes.erase(pid);
143 | }
144 | else {
145 | return it->second;
146 | }
147 | }
148 | wil::unique_handle hProcess(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
149 | if (!hProcess)
150 | return L"";
151 |
152 | WCHAR path[MAX_PATH * 2];
153 | DWORD size = _countof(path);
154 | CString name;
155 | if (::QueryFullProcessImageName(hProcess.get(), 0, path, &size)) {
156 | name = wcsrchr(path, L'\\') + 1;
157 | processes.insert({ pid, name });
158 | }
159 |
160 | return name;
161 | }
162 |
163 | bool Helpers::CloseHandle(HANDLE hObject, DWORD pid) {
164 | wil::unique_handle hProcess(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid));
165 | if (!hProcess)
166 | return false;
167 | return ::DuplicateHandle(hProcess.get(), hObject, nullptr, nullptr, 0, FALSE, DUPLICATE_CLOSE_SOURCE);
168 | }
169 |
170 | CString Helpers::GetWin32PathFromNTPath(PCWSTR ntpath) {
171 | if (ntpath[0] != L'\\')
172 | return ntpath;
173 |
174 | static std::vector> drives;
175 | if (drives.empty()) {
176 | auto ldrives = ::GetLogicalDrives();
177 | int d = 0;
178 | WCHAR drive[] = L"X:";
179 | WCHAR target[256];
180 | while (ldrives) {
181 | if (ldrives & 1) {
182 | drive[0] = WCHAR(d + 'A');
183 | if (::QueryDosDevice(drive, target, _countof(target))) {
184 | drives.push_back({ target, drive });
185 | }
186 | }
187 | d++;
188 | ldrives >>= 1;
189 | }
190 | }
191 | auto bs = wcschr(ntpath + 8, L'\\');
192 | if (bs == nullptr)
193 | return L"";
194 |
195 | CString native(ntpath, (int)(bs - ntpath));
196 | for (auto& [nt, win32] : drives)
197 | if (nt.CompareNoCase(native) == 0)
198 | return win32 + bs;
199 |
200 | return L"";
201 | }
202 |
203 | bool Helpers::WriteToFile(PCWSTR path, CString const& text) {
204 | return WriteToFile(path, text, text.GetLength() * sizeof(TCHAR));
205 | }
206 |
207 | bool Helpers::WriteToFile(PCWSTR path, void const* data, DWORD size) {
208 | HANDLE hFile = ::CreateFile(path, GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, 0, nullptr);
209 | if (hFile == INVALID_HANDLE_VALUE)
210 | return false;
211 |
212 | DWORD bytes;
213 | auto ok = ::WriteFile(hFile, data, size, &bytes, nullptr);
214 | ::CloseHandle(hFile);
215 | return ok;
216 | }
217 |
218 | bool Helpers::ReadFileText(PCWSTR path, CString& text) {
219 | HANDLE hFile = ::CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
220 | if (hFile == INVALID_HANDLE_VALUE)
221 | return false;
222 |
223 | DWORD bytes;
224 | auto size = ::GetFileSize(hFile, nullptr);
225 | auto buffer = text.GetBufferSetLength(size / sizeof(WCHAR));
226 | auto ok = ::ReadFile(hFile, buffer, size, &bytes, nullptr);
227 | ::CloseHandle(hFile);
228 | return ok;
229 | }
230 |
231 | CString Helpers::NormalizePath(CString const& path) {
232 | CString spath(path);
233 | spath.MakeUpper();
234 | static const CString regEditPrefix = L"COMPUTER\\";
235 | if (spath.Left(regEditPrefix.GetLength()) == regEditPrefix)
236 | spath = spath.Mid(regEditPrefix.GetLength());
237 |
238 | if (spath != L'\\') {
239 | if (spath.Find(L'\\') < 0)
240 | spath += L"\\";
241 | int n = spath.Replace(L"HKLM:\\", L"HKEY_LOCAL_MACHINE\\");
242 | if (n == 0)
243 | n = spath.Replace(L"HKLM\\", L"HKEY_LOCAL_MACHINE\\");
244 | if (n == 0)
245 | n = spath.Replace(L"HKCU:\\", L"HKEY_CURRENT_USER\\");
246 | if (n == 0)
247 | n = spath.Replace(L"HKCU\\", L"HKEY_CURRENT_USER\\");
248 | if (n == 0)
249 | n = spath.Replace(L"HKCR:\\", L"HKEY_CLASSES_ROOT\\");
250 | if (n == 0)
251 | n = spath.Replace(L"HKCR\\", L"HKEY_CLASSES_ROOT\\");
252 | if (n == 0)
253 | n = spath.Replace(L"HKU:\\", L"HKEY_USERS\\");
254 | if (n == 0)
255 | n = spath.Replace(L"HKU\\", L"HKEY_USERS\\");
256 | if (n == 0)
257 | n = spath.Replace(L"HKCC:\\", L"HKEY_CURRENT_CONFIG");
258 | if (n == 0)
259 | spath.Replace(L"HKCC\\", L"HKEY_CURRENT_CONFIG");
260 | }
261 | return spath;
262 | }
263 |
264 | CString Helpers::GuidToString(GUID const& guid) {
265 | WCHAR text[64];
266 | return 0 == ::StringFromGUID2(guid, text, _countof(text)) ? L"" : text;
267 | }
268 |
--------------------------------------------------------------------------------
/RegExp/Helpers.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct Helpers abstract final {
4 | static bool SaveWindowPosition(HWND hWnd, PCWSTR name);
5 | static bool RestoreWindowPosition(HWND hWnd, PCWSTR name);
6 | static CString ToBinary(ULONGLONG value);
7 | static PCWSTR GetSystemDirectory();
8 | static PCWSTR GetWindowsDirectory();
9 | static COLORREF ParseColor(const CString& text);
10 | static inline const CString DefaultValueName{ L"(Default)" };
11 | static CString GetObjectName(HANDLE hObject, DWORD pid);
12 | static USHORT GetKeyObjectTypeIndex();
13 | static CString GetErrorText(DWORD error = ::GetLastError());
14 | static CString GetProcessNameById(DWORD pid);
15 | static bool CloseHandle(HANDLE hObject, DWORD pid);
16 | static CString GetWin32PathFromNTPath(PCWSTR ntpath);
17 | static bool WriteToFile(PCWSTR path, CString const& text);
18 | static bool WriteToFile(PCWSTR path, void const* data, DWORD size);
19 | static bool ReadFileText(PCWSTR path, CString& text);
20 | static CString NormalizePath(CString const& path);
21 | static CString GuidToString(GUID const& guid);
22 | };
23 |
24 |
--------------------------------------------------------------------------------
/RegExp/HexControl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include