├── .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 | ![](https://github.com/zodiacon/RegExp/blob/master/regexp1.png) 23 | 24 | ![](https://github.com/zodiacon/RegExp/blob/master/regexp2.png) 25 | 26 | ![](https://github.com/zodiacon/RegExp/blob/master/regexp3.png) 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 4 | #include 5 | 6 | struct IBufferManager { 7 | virtual uint32_t GetData(int64_t offset, uint8_t* buffer, uint32_t count) = 0; 8 | virtual bool Insert(int64_t offset, const uint8_t* data, uint32_t count) = 0; 9 | virtual bool Delete(int64_t offset, size_t count) = 0; 10 | virtual bool SetData(int64_t offset, const uint8_t* data, uint32_t count) = 0; 11 | virtual int64_t GetSize() const = 0; 12 | virtual uint8_t* GetRawData(int64_t offset) = 0; 13 | virtual bool IsReadOnly() const = 0; 14 | virtual bool Increase(uint32_t size) { 15 | return false; 16 | } 17 | virtual ~IBufferManager() = default; 18 | }; 19 | 20 | struct HexControlColors { 21 | COLORREF Text{ ::GetSysColor(COLOR_WINDOWTEXT) }; 22 | COLORREF Background{ ::GetSysColor(COLOR_WINDOW) }; 23 | COLORREF Ascii{ RGB(128, 0, 0) }; 24 | COLORREF Offset{ RGB(0, 0, 128) }; 25 | COLORREF SelectionText{ ::GetSysColor(COLOR_HIGHLIGHTTEXT) }; 26 | COLORREF SelectionBackground{ ::GetSysColor(COLOR_HIGHLIGHT) }; 27 | }; 28 | 29 | enum class SelectionType { 30 | Simple, 31 | Box 32 | }; 33 | 34 | class Selection { 35 | public: 36 | void SetSimple(int64_t offset, int64_t len); 37 | void SetBox(int64_t offset, int bytesPerLine, int width, int height); 38 | void SetAnchor(int64_t offset); 39 | 40 | int64_t GetOffset() const; 41 | int64_t GetAnchor() const; 42 | bool IsSelected(int64_t offset) const; 43 | bool IsEmpty() const; 44 | SelectionType GetSelectionType() const; 45 | int64_t GetLength() const { 46 | return _length; 47 | } 48 | 49 | void Clear(); 50 | 51 | private: 52 | SelectionType _type{ SelectionType::Simple }; 53 | int64_t _offset{ -1 }, _anchor{ -1 }; 54 | int64_t _length{ 0 }; 55 | int _width, _height, _bytesPerLine; 56 | }; 57 | 58 | const UINT HCN_SIZECHANGED = NM_FIRST - 3000; 59 | const UINT HCN_RCLICK = NM_FIRST - 3001; 60 | 61 | struct HCNOTIFY { 62 | NMHDR hdr; 63 | }; 64 | 65 | class CHexControl : 66 | public CBufferedPaintWindowImpl { 67 | public: 68 | DECLARE_WND_CLASS_EX(L"WTLHexControl", CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, NULL) 69 | 70 | HWND GetHwnd() const; 71 | void SetBufferManager(IBufferManager* mgr); 72 | IBufferManager* GetBufferManager() const; 73 | void SetReadOnly(bool readonly); 74 | bool IsReadOnly() const; 75 | void SetAllowExtension(bool allow); 76 | bool IsAllowExtension() const; 77 | void SetSize(int64_t size); 78 | bool SetDataSize(int32_t size); 79 | int32_t GetDataSize() const; 80 | bool SetBytesPerLine(int32_t bytesPerLine); 81 | int32_t GetBytesPerLine() const; 82 | bool Copy(int64_t offset = -1, int64_t size = 0); 83 | bool Paste(int64_t offset = -1); 84 | bool CanCopy() const; 85 | bool CanPaste() const; 86 | bool Cut(int64_t offset = -1, int64_t size = 0); 87 | bool Delete(int64_t offset = -1, int64_t size = 0); 88 | bool CanCut() const; 89 | bool CanDelete() const; 90 | int64_t SetBiasOffset(int64_t offset); 91 | int64_t GetBiasOffset() const; 92 | HexControlColors& GetColors(); 93 | std::wstring GetText(int64_t offset, int64_t size); 94 | void Refresh(); 95 | 96 | BEGIN_MSG_MAP(CHexControl) 97 | MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLeftButtonDown) 98 | MESSAGE_HANDLER(WM_SIZE, OnSize) 99 | MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) 100 | MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) 101 | MESSAGE_HANDLER(WM_LBUTTONUP, OnLeftButtonUp) 102 | MESSAGE_HANDLER(WM_CHAR, OnChar) 103 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 104 | MESSAGE_HANDLER(WM_VSCROLL, OnVScroll) 105 | MESSAGE_HANDLER(WM_HSCROLL, OnHScroll) 106 | MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel) 107 | MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) 108 | MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) 109 | MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDialogCode) 110 | MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) 111 | CHAIN_MSG_MAP(CBufferedPaintWindowImpl) 112 | END_MSG_MAP() 113 | 114 | void DoPaint(CDCHandle dc, RECT& rect); 115 | 116 | private: 117 | LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 118 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 119 | LRESULT OnHScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 120 | LRESULT OnVScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 121 | LRESULT OnMouseWheel(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 122 | LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 123 | LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 124 | LRESULT OnLeftButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 125 | LRESULT OnGetDialogCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 126 | LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 127 | LRESULT OnChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 128 | LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 129 | LRESULT OnLeftButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 130 | LRESULT OnContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 131 | 132 | private: 133 | void RecalcLayout(); 134 | void InitFontMetrics(); 135 | CPoint GetPointFromOffset(int64_t offset) const; 136 | int64_t GetOffsetFromPoint(const POINT& pt) const; 137 | void DrawNumber(CDCHandle dc, int64_t offset, uint64_t value, int editDigits); 138 | PCWSTR FormatNumber(ULONGLONG number) const; 139 | LRESULT SendNotify(HCNOTIFY* notify); 140 | 141 | void UpdateCaret(); 142 | void RedrawWindow(RECT* = nullptr); 143 | void ClearSelection(); 144 | void CommitValue(int64_t offset, uint64_t value); 145 | void ResetInput(); 146 | int64_t NormalizeOffset(int64_t offset) const; 147 | void RedrawCaretLine(); 148 | 149 | private: 150 | HexControlColors m_Colors; 151 | CFont m_Font; 152 | int m_FontPointSize{ 100 }; 153 | int m_Lines{ 1 }; 154 | int m_CharWidth, m_CharHeight; 155 | IBufferManager* m_Buffer{ nullptr }; 156 | std::vector m_Text; 157 | int64_t m_StartOffset{ 0 }, m_EndOffset; 158 | int32_t m_DataSize{ 1 }, m_BytesPerLine{ 32 }; 159 | int64_t m_CaretOffset{ 0 }; 160 | int m_AddressDigits{ 4 }; 161 | int m_EditDigits{ 0 }, m_LastDigits{ 0 }; 162 | Selection m_Selection; 163 | HCNOTIFY m_NotifyData; 164 | uint64_t m_CurrentInput{ 0 }, m_OldValue; 165 | bool m_InsertMode{ false }; 166 | bool m_ReadOnly{ false }; 167 | }; 168 | 169 | -------------------------------------------------------------------------------- /RegExp/IMainFrame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct AppSettings; 4 | 5 | struct IMainFrame abstract { 6 | virtual void OnFindStart() = 0; 7 | virtual void OnFindNext(PCWSTR path, PCWSTR name, PCWSTR data) = 0; 8 | virtual void OnFindEnd(bool cancelled) = 0; 9 | virtual bool GoToItem(PCWSTR path, PCWSTR name, PCWSTR data) = 0; 10 | virtual CString GetCurrentKeyPath() = 0; 11 | virtual BOOL TrackPopupMenu(HMENU hMenu, DWORD flags, int x, int y, HWND hWnd = nullptr) = 0; 12 | virtual HWND GetHwnd() const = 0; 13 | virtual void DisplayError(PCWSTR text, HWND hWnd = nullptr, DWORD err = ::GetLastError()) const = 0; 14 | virtual HTREEITEM GotoKey(CString const&, bool knownToExist) = 0; 15 | virtual void QuickFilter(PCWSTR text) = 0; 16 | }; 17 | -------------------------------------------------------------------------------- /RegExp/Icons/Delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Delete.ico -------------------------------------------------------------------------------- /RegExp/Icons/Options.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Options.ico -------------------------------------------------------------------------------- /RegExp/Icons/Properties.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Properties.ico -------------------------------------------------------------------------------- /RegExp/Icons/Query.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Query.ico -------------------------------------------------------------------------------- /RegExp/Icons/Refresh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Refresh.ico -------------------------------------------------------------------------------- /RegExp/Icons/Registry.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/Registry.ico -------------------------------------------------------------------------------- /RegExp/Icons/RegistrySearch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/RegistrySearch.ico -------------------------------------------------------------------------------- /RegExp/Icons/back.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/back.ico -------------------------------------------------------------------------------- /RegExp/Icons/binary.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/binary.ico -------------------------------------------------------------------------------- /RegExp/Icons/bookmark_add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/bookmark_add.ico -------------------------------------------------------------------------------- /RegExp/Icons/bookmark_delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/bookmark_delete.ico -------------------------------------------------------------------------------- /RegExp/Icons/bookmarks.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/bookmarks.ico -------------------------------------------------------------------------------- /RegExp/Icons/check.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/check.ico -------------------------------------------------------------------------------- /RegExp/Icons/copy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/copy.ico -------------------------------------------------------------------------------- /RegExp/Icons/cut.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/cut.ico -------------------------------------------------------------------------------- /RegExp/Icons/digit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/digit.ico -------------------------------------------------------------------------------- /RegExp/Icons/export.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/export.ico -------------------------------------------------------------------------------- /RegExp/Icons/find.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/find.ico -------------------------------------------------------------------------------- /RegExp/Icons/find_next.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/find_next.ico -------------------------------------------------------------------------------- /RegExp/Icons/find_previous.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/find_previous.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder_accessdenied.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder_accessdenied.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder_closed.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder_closed.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder_into.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder_into.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder_new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder_new.ico -------------------------------------------------------------------------------- /RegExp/Icons/folder_view.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folder_view.ico -------------------------------------------------------------------------------- /RegExp/Icons/folderup.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/folderup.ico -------------------------------------------------------------------------------- /RegExp/Icons/font.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/font.ico -------------------------------------------------------------------------------- /RegExp/Icons/forward.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/forward.ico -------------------------------------------------------------------------------- /RegExp/Icons/goto.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/goto.ico -------------------------------------------------------------------------------- /RegExp/Icons/hive-accessdenied.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/hive-accessdenied.ico -------------------------------------------------------------------------------- /RegExp/Icons/hive.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/hive.ico -------------------------------------------------------------------------------- /RegExp/Icons/import.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/import.ico -------------------------------------------------------------------------------- /RegExp/Icons/laptop.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/laptop.ico -------------------------------------------------------------------------------- /RegExp/Icons/link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/link.ico -------------------------------------------------------------------------------- /RegExp/Icons/lock.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/lock.ico -------------------------------------------------------------------------------- /RegExp/Icons/number-1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/number-1.ico -------------------------------------------------------------------------------- /RegExp/Icons/number-2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/number-2.ico -------------------------------------------------------------------------------- /RegExp/Icons/number-4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/number-4.ico -------------------------------------------------------------------------------- /RegExp/Icons/number-8-2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/number-8-2.ico -------------------------------------------------------------------------------- /RegExp/Icons/number-8.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/number-8.ico -------------------------------------------------------------------------------- /RegExp/Icons/paste.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/paste.ico -------------------------------------------------------------------------------- /RegExp/Icons/quickfind.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/quickfind.ico -------------------------------------------------------------------------------- /RegExp/Icons/redo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/redo.ico -------------------------------------------------------------------------------- /RegExp/Icons/regexp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/regexp.ico -------------------------------------------------------------------------------- /RegExp/Icons/regremote.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/regremote.ico -------------------------------------------------------------------------------- /RegExp/Icons/rename.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/rename.ico -------------------------------------------------------------------------------- /RegExp/Icons/replace.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/replace.ico -------------------------------------------------------------------------------- /RegExp/Icons/save_as.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/save_as.ico -------------------------------------------------------------------------------- /RegExp/Icons/shield.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/shield.ico -------------------------------------------------------------------------------- /RegExp/Icons/text.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/text.ico -------------------------------------------------------------------------------- /RegExp/Icons/undo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/Icons/undo.ico -------------------------------------------------------------------------------- /RegExp/ImageIconCache.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ImageIconCache.h" 3 | 4 | int ImageIconCache::GetIconIndex(CString const& path) const { 5 | if (auto it = _icons.find(path); it != _icons.end()) 6 | return it->second; 7 | 8 | auto hIcon = ::ExtractIcon(ModuleHelper::GetModuleInstance(), path, 0); 9 | if (hIcon) { 10 | int index; 11 | _icons.insert({ path, index = _images.AddIcon(hIcon) }); 12 | return index; 13 | } 14 | _icons.insert({ path, 0 }); 15 | return 0; 16 | } 17 | 18 | int ImageIconCache::GetIconIndex(DWORD pid) const { 19 | auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); 20 | if(!hProcess) 21 | return 0; 22 | 23 | WCHAR path[MAX_PATH * 2]; 24 | DWORD size = _countof(path); 25 | auto count = ::QueryFullProcessImageName(hProcess, 0, path, &size); 26 | ::CloseHandle(hProcess); 27 | return count > 0 ? GetIconIndex(path) : 0; 28 | } 29 | 30 | HIMAGELIST ImageIconCache::GetImageList() const { 31 | return _images.m_hImageList; 32 | } 33 | 34 | ImageIconCache& ImageIconCache::Get() { 35 | static ImageIconCache cache; 36 | return cache; 37 | } 38 | 39 | void ImageIconCache::Destroy() { 40 | _images.Destroy(); 41 | } 42 | 43 | ImageIconCache::ImageIconCache() { 44 | _images.Create(16, 16, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 50, 10); 45 | _images.AddIcon(AtlLoadSysIcon(IDI_APPLICATION)); 46 | } 47 | -------------------------------------------------------------------------------- /RegExp/ImageIconCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct ImageIconCache { 4 | int GetIconIndex(CString const& path) const; 5 | int GetIconIndex(DWORD pid) const; 6 | HIMAGELIST GetImageList() const; 7 | static ImageIconCache& Get(); 8 | void Destroy(); 9 | 10 | private: 11 | ImageIconCache(); 12 | mutable CImageListManaged _images; 13 | mutable std::map _icons; 14 | }; 15 | -------------------------------------------------------------------------------- /RegExp/KeysHandlesDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "KeysHandlesDlg.h" 4 | #include "Helpers.h" 5 | #include "ImageIconCache.h" 6 | #include "SortHelper.h" 7 | #include "SecurityInformation.h" 8 | #include "SecurityHelper.h" 9 | #include "ListViewhelper.h" 10 | #include "ClipboardHelper.h" 11 | #include "ThemeHelper.h" 12 | 13 | CString CKeysHandlesDlg::GetColumnText(HWND hWnd, int row, int col) const { 14 | auto const& item = m_Handles[row]; 15 | switch (GetColumnManager(hWnd)->GetColumnTag(col)) { 16 | case ColumnType::PID: return std::format(L"{}", item.ProcessId).c_str(); 17 | case ColumnType::Access: return std::format(L"0x{:08X}", item.Access).c_str(); 18 | case ColumnType::Handle: return std::format(L"0x{:X}", item.Handle).c_str(); 19 | case ColumnType::Attributes: return std::format(L"0x{:X}", item.Attributes).c_str(); 20 | case ColumnType::KeyName: return item.Name; 21 | case ColumnType::ProcessName: return item.ProcessName; 22 | case ColumnType::Address: return std::format(L"0x{:p}", item.Object).c_str(); 23 | } 24 | return L""; 25 | } 26 | 27 | bool CKeysHandlesDlg::OnRightClickList(HWND, int row, int col, POINT const& pt) { 28 | if (m_List.GetSelectedCount() > 0) { 29 | CMenu menu; 30 | menu.LoadMenu(IDR_CONTEXT); 31 | auto subMenu = menu.GetSubMenu(6); 32 | auto cmd = (UINT)ShowContextMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y); 33 | if (cmd) 34 | PostMessage(WM_COMMAND, cmd); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | bool CKeysHandlesDlg::OnDoubleClickList(HWND, int row, int col, POINT const& pt) { 41 | auto& item = m_Handles[row]; 42 | if(item.Name[0] != L'<') 43 | m_pFrame->GotoKey(item.Name, true); 44 | return true; 45 | } 46 | 47 | int CKeysHandlesDlg::GetRowImage(HWND, int row, int) const { 48 | return ImageIconCache::Get().GetIconIndex(m_Handles[row].ProcessId); 49 | } 50 | 51 | void CKeysHandlesDlg::DoSort(const SortInfo* si) { 52 | if (si == nullptr) 53 | return; 54 | 55 | auto col = GetColumnManager(m_List)->GetColumnTag(si->SortColumn); 56 | 57 | auto compare = [&](const auto& h1, const auto& h2) { 58 | switch (col) { 59 | case ColumnType::ProcessName: return SortHelper::Sort(h1.ProcessName, h2.ProcessName, si->SortAscending); 60 | case ColumnType::KeyName: return SortHelper::Sort(h1.Name, h2.Name, si->SortAscending); 61 | case ColumnType::PID: return SortHelper::Sort(h1.ProcessId, h2.ProcessId, si->SortAscending); 62 | case ColumnType::Handle: return SortHelper::Sort(h1.Handle, h2.Handle, si->SortAscending); 63 | case ColumnType::Access: return SortHelper::Sort(h1.Access, h2.Access, si->SortAscending); 64 | case ColumnType::Attributes: return SortHelper::Sort(h1.Attributes, h2.Attributes, si->SortAscending); 65 | case ColumnType::Address: return SortHelper::Sort(h1.Object, h2.Object, si->SortAscending); 66 | } 67 | return false; 68 | }; 69 | std::ranges::sort(m_Handles, compare); 70 | } 71 | 72 | void CKeysHandlesDlg::Refresh() { 73 | m_Handles = Registry::EnumKeyHandles(m_HideInaccesible); 74 | DoSort(GetSortInfo(m_List)); 75 | m_List.SetItemCountEx(static_cast(m_Handles.size()), LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL); 76 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage()); 77 | SetDlgItemText(IDC_HANDLECOUNT, std::format(L"Handles: {}", m_Handles.size()).c_str()); 78 | } 79 | 80 | BOOL CKeysHandlesDlg::OnIdle() { 81 | UIUpdateToolBar(); 82 | return FALSE; 83 | } 84 | 85 | BOOL CKeysHandlesDlg::PreTranslateMessage(MSG* pMsg) { 86 | return ::GetActiveWindow() == m_hWnd && ::TranslateAccelerator(m_hWnd, m_hAccel.get(), pMsg) != 0; 87 | } 88 | 89 | void CKeysHandlesDlg::UpdateUI() { 90 | auto count = m_List.GetSelectedCount(); 91 | UIEnable(ID_KEY_PERMISSIONS2, count == 1); 92 | UIEnable(ID_HANDLES_CLOSEHANDLES, count > 0); 93 | UIEnable(ID_EDIT_COPY2, count > 0); 94 | } 95 | 96 | void CKeysHandlesDlg::BuildToolBar() { 97 | CToolBarCtrl tb; 98 | CRect rc(8, 4, 350, 40); 99 | tb.Create(m_hWnd, &rc, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR); 100 | tb.GetToolTips().ModifyStyle(0, TTS_ALWAYSTIP); 101 | tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS); 102 | 103 | CImageList tbImages; 104 | tbImages.Create(24, 24, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 8, 4); 105 | tb.SetImageList(tbImages); 106 | 107 | const struct { 108 | UINT id; 109 | int image; 110 | BYTE style = BTNS_BUTTON; 111 | BYTE state = TBSTATE_ENABLED; 112 | PCWSTR text = nullptr; 113 | } buttons[] = { 114 | { ID_EDIT_COPY2, IDI_COPY }, 115 | { ID_VIEW_REFRESH, IDI_REFRESH }, 116 | { 0 }, 117 | { ID_HIDE_EMPTY, IDI_FOLDER_ACCESSDENIED, BTNS_BUTTON | BTNS_CHECK, TBSTATE_ENABLED }, 118 | { 0 }, 119 | { ID_KEY_PERMISSIONS2, IDI_PERM }, 120 | { ID_HANDLES_CLOSEHANDLES, IDI_DELETE }, 121 | }; 122 | for (auto& b : buttons) { 123 | if (b.id == 0) 124 | tb.AddSeparator(0); 125 | else { 126 | HICON hIcon = nullptr; 127 | int image = -1; 128 | if (b.image) { 129 | hIcon = AtlLoadIconImage(b.image, 0, 24, 24); 130 | ATLASSERT(hIcon); 131 | image = tbImages.AddIcon(hIcon); 132 | } 133 | tb.AddButton(b.id, b.style | (b.text ? BTNS_SHOWTEXT : 0), b.state, image, b.text, 0); 134 | if(hIcon) 135 | m_Menu.AddCommand(b.id, hIcon); 136 | 137 | } 138 | } 139 | UIAddToolBar(tb); 140 | } 141 | 142 | LRESULT CKeysHandlesDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 143 | InitDynamicLayout(); 144 | SetDialogIcon(IDI_REAL_REG); 145 | BuildToolBar(); 146 | 147 | m_List.Attach(GetDlgItem(IDC_LIST)); 148 | m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP); 149 | m_List.SetImageList(ImageIconCache::Get().GetImageList(), LVSIL_SMALL); 150 | 151 | auto cm = GetColumnManager(m_List); 152 | cm->AddColumn(L"Process Name", 0, 140, ColumnType::ProcessName); 153 | cm->AddColumn(L"PID", LVCFMT_RIGHT, 70, ColumnType::PID); 154 | cm->AddColumn(L"Handle", LVCFMT_RIGHT, 80, ColumnType::Handle); 155 | cm->AddColumn(L"Key", 0, 420, ColumnType::KeyName); 156 | cm->AddColumn(L"Object Address", LVCFMT_RIGHT, 140, ColumnType::Address); 157 | cm->AddColumn(L"Access", LVCFMT_RIGHT, 80, ColumnType::Access); 158 | cm->AddColumn(L"Decoded Access", 0, 160, ColumnType::DecodedAccess); 159 | cm->AddColumn(L"Attributes", LVCFMT_RIGHT, 90, ColumnType::Attributes); 160 | cm->UpdateColumns(); 161 | 162 | m_hAccel.reset(LoadAccelerators(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDR_MAINFRAME))); 163 | 164 | _Module.GetMessageLoop()->AddIdleHandler(this); 165 | _Module.GetMessageLoop()->AddMessageFilter(this); 166 | 167 | ThemeHelper::UpdateMenuColors(m_Menu, !ThemeHelper::IsDefault()); 168 | UIAddMenu(IDR_CONTEXT); 169 | UpdateUI(); 170 | 171 | return 0; 172 | } 173 | 174 | LRESULT CKeysHandlesDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 175 | ShowWindow(SW_HIDE); 176 | return 0; 177 | } 178 | 179 | LRESULT CKeysHandlesDlg::OnRefresh(WORD, WORD wID, HWND, BOOL&) { 180 | CWaitCursor wait; 181 | Refresh(); 182 | return 0; 183 | } 184 | 185 | LRESULT CKeysHandlesDlg::OnHideInaccessible(WORD, WORD wID, HWND, BOOL&) { 186 | m_HideInaccesible = !m_HideInaccesible; 187 | UISetCheck(wID, m_HideInaccesible); 188 | Refresh(); 189 | return 0; 190 | } 191 | 192 | LRESULT CKeysHandlesDlg::OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { 193 | handled = FALSE; 194 | _Module.GetMessageLoop()->RemoveIdleHandler(this); 195 | _Module.GetMessageLoop()->RemoveMessageFilter(this); 196 | return 0; 197 | } 198 | 199 | LRESULT CKeysHandlesDlg::OnCloseHandle(WORD, WORD wID, HWND, BOOL&) { 200 | auto count = m_List.GetSelectedCount(); 201 | ATLASSERT(count > 0); 202 | 203 | auto result = AtlMessageBox(m_hWnd, std::format(L"Close {} {}? This could lead to process instability.", count, count == 1 ? L"handle" : L"handles").c_str(), 204 | IDS_APP_TITLE, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); 205 | if (result == IDCANCEL) 206 | return 0; 207 | 208 | int closed = 0; 209 | for (int index = -1; (index = m_List.GetNextItem(index, LVIS_SELECTED)) >= 0;) { 210 | if (Helpers::CloseHandle(UlongToHandle(m_Handles[index].Handle), m_Handles[index].ProcessId)) 211 | closed++; 212 | } 213 | if(closed > 0) 214 | Refresh(); 215 | AtlMessageBox(m_hWnd, std::format(L"Successfully closed {} handle(s)", closed).c_str(), IDS_APP_TITLE, MB_ICONINFORMATION); 216 | 217 | return 0; 218 | } 219 | 220 | LRESULT CKeysHandlesDlg::OnEditCopy(WORD, WORD wID, HWND, BOOL&) { 221 | CString text; 222 | for (int index = -1; (index = m_List.GetNextItem(index, LVIS_SELECTED)) >= 0;) { 223 | text += ListViewHelper::GetRowAsString(m_List, index) + L"\n"; 224 | } 225 | ClipboardHelper::CopyText(m_hWnd, text.Left(text.GetLength() - 1)); 226 | return 0; 227 | } 228 | 229 | LRESULT CKeysHandlesDlg::OnPermissions(WORD, WORD wID, HWND, BOOL&) { 230 | auto index = m_List.GetSelectionMark(); 231 | ATLASSERT(index >= 0); 232 | auto& item = m_Handles[index]; 233 | auto hDup = SecurityHelper::DupHandle(ULongToHandle(item.Handle), item.ProcessId, READ_CONTROL | KEY_WRITE); 234 | if(!hDup) 235 | hDup = SecurityHelper::DupHandle(ULongToHandle(item.Handle), item.ProcessId, READ_CONTROL); 236 | if (hDup) { 237 | CSecurityInformation si(hDup, item.Name, false); 238 | ThemeHelper::Suspend(); 239 | ::EditSecurity(m_hWnd, &si); 240 | ThemeHelper::Resume(); 241 | ::CloseHandle(hDup); 242 | } 243 | else { 244 | m_pFrame->DisplayError(L"Failed to show key permissions", m_hWnd); 245 | } 246 | return 0; 247 | } 248 | 249 | LRESULT CKeysHandlesDlg::OnToolTipGetDisplay(int, LPNMHDR hdr, BOOL&) { 250 | auto tt = (NMTTDISPINFO*)hdr; 251 | CString text; 252 | text.LoadString((UINT)hdr->idFrom); 253 | text.Remove(L'\n'); 254 | wcscpy_s(tt->szText, text); 255 | tt->uFlags = TTF_DI_SETITEM; 256 | 257 | return 0; 258 | } 259 | 260 | LRESULT CKeysHandlesDlg::OnListSelectionChanged(int, LPNMHDR, BOOL&) { 261 | UpdateUI(); 262 | 263 | return 0; 264 | } 265 | -------------------------------------------------------------------------------- /RegExp/KeysHandlesDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "VirtualListView.h" 5 | #include "Registry.h" 6 | #include 7 | #include "IMainFrame.h" 8 | #include "OwnerDrawnMenu.h" 9 | 10 | class CKeysHandlesDlg : 11 | public CDialogImpl, 12 | public CDynamicDialogLayout, 13 | public CAutoUpdateUI, 14 | public CVirtualListView, 15 | public COwnerDrawnMenu, 16 | public CIdleHandler, 17 | public CMessageFilter, 18 | public CDialogHelper { 19 | public: 20 | enum { IDD = IDD_HANDLES }; 21 | 22 | CKeysHandlesDlg(IMainFrame* frame) : m_pFrame(frame) {} 23 | 24 | void Refresh(); 25 | BOOL OnIdle() override; 26 | BOOL PreTranslateMessage(MSG* pMsg) override; 27 | 28 | CString GetColumnText(HWND, int row, int col) const; 29 | bool OnRightClickList(HWND, int row, int col, POINT const& pt); 30 | bool OnDoubleClickList(HWND, int row, int col, POINT const& pt); 31 | 32 | int GetRowImage(HWND, int row, int) const; 33 | void DoSort(const SortInfo* si); 34 | 35 | BEGIN_MSG_MAP(CKeysHandlesDlg) 36 | NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnListSelectionChanged) 37 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 38 | NOTIFY_CODE_HANDLER(TTN_GETDISPINFO, OnToolTipGetDisplay) 39 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 40 | COMMAND_ID_HANDLER(ID_VIEW_REFRESH, OnRefresh) 41 | COMMAND_ID_HANDLER(ID_HIDE_EMPTY, OnHideInaccessible) 42 | COMMAND_ID_HANDLER(ID_HANDLES_CLOSEHANDLES, OnCloseHandle) 43 | COMMAND_ID_HANDLER(ID_KEY_PERMISSIONS2, OnPermissions) 44 | COMMAND_ID_HANDLER(ID_EDIT_COPY2, OnEditCopy) 45 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 46 | CHAIN_MSG_MAP(CVirtualListView) 47 | CHAIN_MSG_MAP(COwnerDrawnMenu) 48 | CHAIN_MSG_MAP(CDynamicDialogLayout) 49 | CHAIN_MSG_MAP(CAutoUpdateUI) 50 | END_MSG_MAP() 51 | 52 | // Handler prototypes (uncomment arguments if needed): 53 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 54 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 55 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 56 | 57 | private: 58 | void UpdateUI(); 59 | void BuildToolBar(); 60 | 61 | enum class ColumnType { 62 | ProcessName, PID, Handle, KeyName, Attributes, Access, DecodedAccess, Address 63 | }; 64 | 65 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 66 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 67 | LRESULT OnRefresh(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 68 | LRESULT OnHideInaccessible(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 69 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 70 | LRESULT OnCloseHandle (WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 71 | LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 72 | LRESULT OnPermissions(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 73 | LRESULT OnToolTipGetDisplay(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 74 | LRESULT OnListSelectionChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 75 | 76 | CListViewCtrl m_List; 77 | std::vector m_Handles; 78 | bool m_HideInaccesible{ false }; 79 | wil::unique_haccel m_hAccel; 80 | IMainFrame* m_pFrame; 81 | COwnerDrawnMenu m_Menu; 82 | }; 83 | -------------------------------------------------------------------------------- /RegExp/LoadHiveDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Resource.h" 3 | #include "LoadHiveDlg.h" 4 | #include "ThemeHelper.h" 5 | 6 | HKEY CLoadHiveDlg::GetSelectedKey() const { 7 | return m_hKey; 8 | } 9 | 10 | const CString& CLoadHiveDlg::GetFileName() const { 11 | return m_FileName; 12 | } 13 | 14 | const CString& CLoadHiveDlg::GetName() const { 15 | return m_Name; 16 | } 17 | 18 | LRESULT CLoadHiveDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 19 | SetDialogIcon(IDI_FOLDER_LOAD); 20 | CheckDlgButton(IDC_MACHINE, BST_CHECKED); 21 | ::SHAutoComplete(GetDlgItem(IDC_PATH), SHACF_FILESYS_ONLY); 22 | 23 | return 0; 24 | } 25 | 26 | LRESULT CLoadHiveDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 27 | if (wID == IDOK) { 28 | m_hKey = IsDlgButtonChecked(IDC_MACHINE) == BST_CHECKED ? HKEY_LOCAL_MACHINE : HKEY_USERS; 29 | GetDlgItemText(IDC_NAME, m_Name); 30 | GetDlgItemText(IDC_PATH, m_FileName); 31 | } 32 | EndDialog(wID); 33 | return 0; 34 | } 35 | 36 | LRESULT CLoadHiveDlg::OnBrowse(WORD, WORD wID, HWND, BOOL&) { 37 | ThemeHelper::Suspend(); 38 | CSimpleFileDialog dlg(TRUE, L"dat", nullptr, OFN_EXPLORER | OFN_ENABLESIZING | OFN_FILEMUSTEXIST, 39 | L"All Files\0*.*\0", m_hWnd); 40 | if (dlg.DoModal() == IDOK) { 41 | SetDlgItemText(IDC_PATH, dlg.m_szFileName); 42 | } 43 | ThemeHelper::Resume(); 44 | return 0; 45 | } 46 | 47 | LRESULT CLoadHiveDlg::OnTextChanged(WORD, WORD wID, HWND, BOOL&) { 48 | GetDlgItem(IDOK).EnableWindow(GetDlgItem(IDC_PATH).GetWindowTextLength() > 0 && GetDlgItem(IDC_NAME).GetWindowTextLength() > 0); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /RegExp/LoadHiveDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | 5 | class CLoadHiveDlg : 6 | public CDialogHelper, 7 | public CDialogImpl { 8 | public: 9 | enum { IDD = IDD_LOADHIVE }; 10 | 11 | HKEY GetSelectedKey() const; 12 | const CString& GetFileName() const; 13 | const CString& GetName() const; 14 | 15 | BEGIN_MSG_MAP(CLoadHiveDlg) 16 | COMMAND_CODE_HANDLER(EN_CHANGE, OnTextChanged) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 19 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 20 | COMMAND_ID_HANDLER(IDC_BROWSE, OnBrowse) 21 | REFLECT_NOTIFICATIONS_EX() 22 | END_MSG_MAP() 23 | 24 | private: 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 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 31 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 32 | LRESULT OnBrowse(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 33 | LRESULT OnTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 34 | 35 | CString m_FileName, m_Name; 36 | HKEY m_hKey; 37 | }; 38 | -------------------------------------------------------------------------------- /RegExp/LocationManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "LocationManager.h" 3 | #include "IniFile.h" 4 | #include "RegistryKey.h" 5 | 6 | bool LocationManager::LoadFromRegistry(PCWSTR path) { 7 | path = GetPath(path); 8 | if (!path) 9 | return false; 10 | 11 | CRegKey key; 12 | key.Open(HKEY_CURRENT_USER, path, KEY_QUERY_VALUE); 13 | if (!key) 14 | return false; 15 | 16 | ULONG chars = 0; 17 | key.QueryStringValue(L"Locations", nullptr, &chars); 18 | if (chars == 0) 19 | return false; 20 | 21 | auto data = std::make_unique(chars); 22 | if (ERROR_SUCCESS != key.QueryStringValue(L"Locations", data.get(), &chars)) 23 | return false; 24 | 25 | m_Items.clear(); 26 | for (auto p = data.get(); *p; ) { 27 | auto semi = wcschr(p, L';'); 28 | if (semi == nullptr) 29 | return false; 30 | 31 | auto count = semi - p; 32 | CString name((PCWSTR)p, (int)count); 33 | auto cr = wcschr(semi + 1, L'\n'); 34 | CString path(semi + 1, (int)(cr - semi - 1)); 35 | if (name.IsEmpty()) 36 | name = path; 37 | //if (name.Left(4) != L"HKEY") 38 | // name = name.Mid(name.Find(L"/") + 1); 39 | 40 | m_Items.insert({ name, path }); 41 | p = cr + 1; 42 | } 43 | 44 | return true; 45 | } 46 | 47 | bool LocationManager::SaveToRegistry(PCWSTR path) const { 48 | if (m_Items.empty()) 49 | return true; 50 | 51 | path = GetPath(path); 52 | if (!path) 53 | return false; 54 | 55 | RegistryKey key; 56 | key.Create(HKEY_CURRENT_USER, path); 57 | if (!key) 58 | return false; 59 | 60 | CString text; 61 | for (const auto& [name, value] : m_Items) { 62 | text += name + L";" + value + L"\n"; 63 | } 64 | return ERROR_SUCCESS == key.SetStringValue(L"Locations", text); 65 | } 66 | 67 | bool LocationManager::LoadFromFile(PCWSTR path) { 68 | path = GetPath(path); 69 | if (!path) 70 | return false; 71 | 72 | IniFile file(path); 73 | if (!file.IsValid()) 74 | return false; 75 | 76 | auto data = file.ReadSection(L"Locations"); 77 | for (auto& text : data) { 78 | int n = text.Find(L'='); 79 | m_Items.insert({ n < 0 ? text : text.Left(n), n < 0 ? text : text.Mid(n + 1) }); 80 | } 81 | 82 | return true; 83 | } 84 | 85 | bool LocationManager::SaveToFile(PCWSTR path) const { 86 | path = GetPath(path); 87 | if (!path) 88 | return false; 89 | 90 | IniFile file(path); 91 | for (auto& [name, target] : m_Items) { 92 | file.WriteString(L"Locations", name, target); 93 | } 94 | return true; 95 | } 96 | 97 | bool LocationManager::Load(PCWSTR path) { 98 | WCHAR fullpath[MAX_PATH]; 99 | ::GetModuleFileName(nullptr, fullpath, _countof(fullpath)); 100 | auto dot = wcsrchr(fullpath, L'.'); 101 | ATLASSERT(dot); 102 | if (!dot) 103 | return false; 104 | 105 | *dot = 0; 106 | wcscat_s(fullpath, L".ini"); 107 | if (::GetFileAttributes(fullpath) == INVALID_FILE_ATTRIBUTES) { 108 | // 109 | // INIT file does not exist, load from Registry 110 | // 111 | return LoadFromRegistry(path); 112 | } 113 | // 114 | // load from file 115 | // 116 | return LoadFromFile(fullpath); 117 | } 118 | 119 | bool LocationManager::Save() const { 120 | if (m_Path.IsEmpty()) 121 | return false; 122 | 123 | return m_Path[1] == L':' ? SaveToFile() : SaveToRegistry(); 124 | } 125 | 126 | int LocationManager::GetCount() const { 127 | return (int)m_Items.size(); 128 | } 129 | 130 | bool LocationManager::Replace(CString const& name, CString const& newName) { 131 | auto it = m_Items.find(name); 132 | if (it == m_Items.end()) 133 | return false; 134 | 135 | auto path = it->second; 136 | m_Items.erase(it); 137 | m_Items.insert({ newName, path }); 138 | return true; 139 | } 140 | 141 | void LocationManager::Add(CString const& name, CString const& path) { 142 | m_Items.insert({ name, path }); 143 | } 144 | 145 | void LocationManager::Clear() { 146 | m_Items.clear(); 147 | } 148 | 149 | CString LocationManager::GetPathByName(CString const& name) const { 150 | if (auto it = m_Items.find(name); it != m_Items.end()) 151 | return it->second; 152 | 153 | for (auto& [n, path] : m_Items) { 154 | if (auto index = n.Find(L"/"); index >= 0) 155 | if (n.Mid(index + 1) == name) 156 | return path; 157 | } 158 | return L""; 159 | } 160 | 161 | PCWSTR LocationManager::GetPath(PCWSTR path) const { 162 | if (path == nullptr || *path == 0) 163 | path = m_Path; 164 | 165 | m_Path = path; 166 | if (path == nullptr || *path == 0) 167 | return nullptr; 168 | 169 | return path; 170 | } 171 | -------------------------------------------------------------------------------- /RegExp/LocationManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class LocationManager { 4 | public: 5 | bool LoadFromRegistry(PCWSTR path = nullptr); 6 | bool SaveToRegistry(PCWSTR path = nullptr) const; 7 | bool LoadFromFile(PCWSTR path = nullptr); 8 | bool SaveToFile(PCWSTR path = nullptr) const; 9 | bool Load(PCWSTR path); 10 | bool Save() const; 11 | 12 | int GetCount() const; 13 | 14 | auto begin() { 15 | return m_Items.begin(); 16 | } 17 | 18 | auto end() { 19 | return m_Items.end(); 20 | } 21 | 22 | bool Replace(CString const& name, CString const& newName); 23 | 24 | void Add(CString const& name, CString const& path); 25 | void Clear(); 26 | CString GetPathByName(CString const& name) const; 27 | 28 | private: 29 | PCWSTR GetPath(PCWSTR path) const; 30 | struct LessNoCase { 31 | bool operator()(CString const& s1, CString const& s2) const { 32 | return s1.CompareNoCase(s2) < 0; 33 | } 34 | }; 35 | std::map m_Items; 36 | mutable CString m_Path; 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /RegExp/ManageLocationsDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ManageLocationsDlg.h" 3 | #include "ListViewhelper.h" 4 | #include "Helpers.h" 5 | #include "RegistryKey.h" 6 | #include "Registry.h" 7 | #include 8 | #include "EnumStrings.h" 9 | 10 | CManageLocationsDlg::CManageLocationsDlg(IMainFrame* frame, LocationManager& lm) : m_pFrame(frame), m_lm(lm) { 11 | } 12 | 13 | CString CManageLocationsDlg::GetColumnText(HWND, int row, int col) const { 14 | auto& item = m_Items[row]; 15 | switch (col) { 16 | case 0: return item.Name; 17 | case 1: return item.Path; 18 | } 19 | ATLASSERT(false); 20 | return L""; 21 | } 22 | 23 | void CManageLocationsDlg::DoSort(const SortInfo* si) { 24 | } 25 | 26 | void CManageLocationsDlg::OnStateChanged(HWND, int from, int to, UINT oldState, UINT newState) { 27 | UpdateUI(); 28 | } 29 | 30 | void CManageLocationsDlg::UpdateUI() { 31 | auto selected = m_List.GetSelectedCount(); 32 | GetDlgItem(IDC_SET).EnableWindow(selected == 1); 33 | if (selected == 1) { 34 | auto index = m_List.GetNextItem(-1, LVIS_SELECTED); 35 | ATLASSERT(index >= 0); 36 | SetDlgItemText(IDC_NAME, m_Items[index].Name); 37 | SetDlgItemText(IDC_PATH, m_Items[index].Path); 38 | } 39 | else { 40 | SetDlgItemText(IDC_NAME, L""); 41 | SetDlgItemText(IDC_PATH, L""); 42 | } 43 | GetDlgItem(IDC_DELETE).EnableWindow(selected > 0); 44 | GetDlgItem(IDC_COPY).EnableWindow(selected > 0); 45 | } 46 | 47 | LRESULT CManageLocationsDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 48 | InitDynamicLayout(); 49 | Helpers::RestoreWindowPosition(m_hWnd, L"ManageLocationsDlg"); 50 | 51 | SetDialogIcon(IDR_MAINFRAME); 52 | AddIconToButton(IDC_DELETE, IDI_DELETE); 53 | AddIconToButton(IDC_COPY, IDI_COPY); 54 | AddIconToButton(IDC_NEW, IDI_BOOKMARK_ADD); 55 | 56 | m_List.Attach(GetDlgItem(IDC_LIST)); 57 | m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT); 58 | 59 | auto cm = GetColumnManager(m_List); 60 | cm->AddColumn(L"Name", 0, 300); 61 | cm->AddColumn(L"Key Path", 0, 500); 62 | cm->UpdateColumns(); 63 | 64 | for (auto& [name, path] : m_lm) 65 | m_Items.push_back({ name, path }); 66 | 67 | m_List.SetItemCount((int)m_Items.size()); 68 | UpdateUI(); 69 | 70 | CComObject* pEnum; 71 | pEnum->CreateInstance(&pEnum); 72 | CComPtr spAC; 73 | auto hr = spAC.CoCreateInstance(CLSID_AutoComplete); 74 | if (spAC) { 75 | spAC->Init(GetDlgItem(IDC_PATH), pEnum->GetUnknown(), nullptr, nullptr); 76 | spAC->SetOptions(ACO_AUTOSUGGEST | ACO_USETAB | ACO_AUTOAPPEND); 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | LRESULT CManageLocationsDlg::OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { 83 | Helpers::SaveWindowPosition(m_hWnd, L"ManageLocationsDlg"); 84 | handled = FALSE; 85 | 86 | return 0; 87 | } 88 | 89 | LRESULT CManageLocationsDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) { 90 | if (id == IDOK) { 91 | m_lm.Clear(); 92 | for (auto& item : m_Items) 93 | m_lm.Add(item.Name, item.Path); 94 | } 95 | EndDialog(id); 96 | return 0; 97 | } 98 | 99 | LRESULT CManageLocationsDlg::OnCopy(WORD, WORD wID, HWND, BOOL&) { 100 | ClipboardHelper::CopyText(m_hWnd, ListViewHelper::GetSelectedRowsAsString(m_List)); 101 | 102 | return 0; 103 | } 104 | 105 | LRESULT CManageLocationsDlg::OnDelete(WORD, WORD wID, HWND, BOOL&) { 106 | int n = m_List.GetNextItem(-1, LVIS_SELECTED); 107 | int offset = 0; 108 | for (; n != -1; n = m_List.GetNextItem(n, LVIS_SELECTED)) { 109 | m_Items.erase(m_Items.begin() + n + offset); 110 | offset--; 111 | } 112 | m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL); 113 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage()); 114 | 115 | return 0; 116 | } 117 | 118 | LRESULT CManageLocationsDlg::OnNewLocation(WORD, WORD wID, HWND, BOOL&) { 119 | Location newLoc{ L"New Name", L"HKEY_LOCAL_MACHINE" }; 120 | m_Items.push_back(newLoc); 121 | m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL); 122 | m_List.SelectItem(m_List.GetItemCount() - 1); 123 | GetDlgItem(IDC_NAME).SetFocus(); 124 | 125 | return 0; 126 | } 127 | 128 | LRESULT CManageLocationsDlg::OnSet(WORD, WORD wID, HWND, BOOL&) { 129 | CString path, name; 130 | GetDlgItemText(IDC_PATH, path); 131 | auto key = Registry::OpenKey(path, KEY_QUERY_VALUE); 132 | if (!key && AtlMessageBox(m_hWnd, L"Key cannot be opened successfully. Continue?", 133 | IDS_APP_TITLE, MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2) == IDCANCEL) 134 | return 0; 135 | 136 | GetDlgItemText(IDC_NAME, name); 137 | if (name.IsEmpty()) { 138 | AtlMessageBox(m_hWnd, L"Name cannot be empty.", IDS_APP_TITLE, MB_ICONWARNING); 139 | return 0; 140 | } 141 | 142 | if (auto it = std::ranges::find_if(m_Items, [&](auto& item) { return item.Name.CompareNoCase(name) == 0; }); it != m_Items.end()) { 143 | AtlMessageBox(m_hWnd, L"Name already exists.", IDS_APP_TITLE, MB_ICONWARNING); 144 | return 0; 145 | } 146 | 147 | int index = m_List.GetNextItem(-1, LVIS_SELECTED); 148 | ATLASSERT(index >= 0); 149 | auto& item = m_Items[index]; 150 | item.Name = name; 151 | item.Path = path; 152 | m_List.RedrawItems(index, index); 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /RegExp/ManageLocationsDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "VirtualListView.h" 5 | #include "IMainFrame.h" 6 | #include "LocationManager.h" 7 | #include "resource.h" 8 | 9 | class CManageLocationsDlg : 10 | public CDialogImpl, 11 | public CDynamicDialogLayout, 12 | public CVirtualListView, 13 | public CDialogHelper { 14 | public: 15 | enum { IDD = IDD_LOCATIONS }; 16 | 17 | CManageLocationsDlg(IMainFrame* frame, LocationManager& lm); 18 | 19 | CString GetColumnText(HWND, int row, int col) const; 20 | void DoSort(const SortInfo* si); 21 | void OnStateChanged(HWND, int from, int to, UINT oldState, UINT newState); 22 | 23 | BEGIN_MSG_MAP(CManageLocationsDlg) 24 | COMMAND_ID_HANDLER(IDC_NEW, OnNewLocation) 25 | COMMAND_ID_HANDLER(IDC_SET, OnSet) 26 | COMMAND_ID_HANDLER(IDC_COPY, OnCopy) 27 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 28 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 29 | COMMAND_ID_HANDLER(IDC_DELETE, OnDelete) 30 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 31 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 32 | CHAIN_MSG_MAP(CDynamicDialogLayout) 33 | CHAIN_MSG_MAP(CVirtualListView) 34 | REFLECT_NOTIFICATIONS_EX() 35 | END_MSG_MAP() 36 | 37 | // Handler prototypes (uncomment arguments if needed): 38 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 39 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 40 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 41 | 42 | private: 43 | void UpdateUI(); 44 | 45 | struct Location { 46 | CString Name; 47 | CString Path; 48 | }; 49 | 50 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 51 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 52 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 53 | LRESULT OnCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 54 | LRESULT OnDelete(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 55 | LRESULT OnNewLocation(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 56 | LRESULT OnSet(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 57 | 58 | IMainFrame* m_pFrame; 59 | CListViewCtrl m_List; 60 | LocationManager& m_lm; 61 | std::vector m_Items; 62 | }; 63 | -------------------------------------------------------------------------------- /RegExp/MemoryBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MemoryBuffer.h" 3 | 4 | MemoryBuffer::MemoryBuffer(uint32_t initialSize) : _buffer(initialSize) { 5 | 6 | } 7 | 8 | MemoryBuffer::MemoryBuffer(const uint8_t* data, uint32_t size) { 9 | Init(data, size); 10 | } 11 | 12 | void MemoryBuffer::Init(const uint8_t* data, uint32_t size) { 13 | _buffer.resize(size); 14 | ::memcpy(_buffer.data(), data, size); 15 | } 16 | 17 | uint32_t MemoryBuffer::GetData(int64_t offset, uint8_t* buffer, uint32_t count) { 18 | if (offset >= GetSize()) 19 | return 0; 20 | if (count + offset > GetSize()) 21 | count = uint32_t(GetSize() - offset); 22 | ::memcpy(buffer, _buffer.data() + offset, count); 23 | return count; 24 | } 25 | 26 | bool MemoryBuffer::Insert(int64_t offset, const uint8_t* data, uint32_t count) { 27 | _buffer.insert(_buffer.begin() + offset, data, data + count); 28 | return true; 29 | } 30 | 31 | bool MemoryBuffer::Delete(int64_t offset, size_t count) { 32 | _buffer.erase(_buffer.begin() + offset, _buffer.begin() + offset + count); 33 | return true; 34 | } 35 | 36 | bool MemoryBuffer::SetData(int64_t offset, const uint8_t* data, uint32_t count) { 37 | ::memcpy(_buffer.data() + offset, data, count); 38 | return true; 39 | } 40 | 41 | int64_t MemoryBuffer::GetSize() const { 42 | return _buffer.size(); 43 | } 44 | 45 | uint8_t* MemoryBuffer::GetRawData(int64_t offset) { 46 | return _buffer.data() + offset; 47 | } 48 | 49 | bool MemoryBuffer::IsReadOnly() const { 50 | return false; 51 | } 52 | 53 | bool MemoryBuffer::Increase(uint32_t size) { 54 | _buffer.resize(_buffer.size() + size); 55 | return true; 56 | } 57 | -------------------------------------------------------------------------------- /RegExp/MemoryBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma once 4 | 5 | #include "HexControl.h" 6 | 7 | class MemoryBuffer : public IBufferManager { 8 | public: 9 | MemoryBuffer(uint32_t initialSize = 0); 10 | MemoryBuffer(const uint8_t* data, uint32_t size); 11 | 12 | void Init(const uint8_t* data, uint32_t size); 13 | 14 | // Inherited via IBufferManager 15 | uint32_t GetData(int64_t offset, uint8_t* buffer, uint32_t count) override; 16 | bool Insert(int64_t offset, const uint8_t* data, uint32_t count) override; 17 | bool Delete(int64_t offset, size_t count) override; 18 | bool SetData(int64_t offset, const uint8_t* data, uint32_t count) override; 19 | int64_t GetSize() const override; 20 | uint8_t* GetRawData(int64_t offset) override; 21 | bool IsReadOnly() const override; 22 | bool Increase(uint32_t size) override; 23 | 24 | private: 25 | std::vector _buffer; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /RegExp/MultiStringValueDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "MultiStringValueDlg.h" 4 | #include "Helpers.h" 5 | 6 | CMultiStringValueDlg::CMultiStringValueDlg(RegistryKey& key, PCWSTR name, bool readOnly) : m_Key(key), m_Name(name), m_ReadOnly(readOnly) { 7 | } 8 | 9 | const CString& CMultiStringValueDlg::GetValue() const { 10 | return m_Value; 11 | } 12 | 13 | bool CMultiStringValueDlg::IsModified() const { 14 | return m_Modified; 15 | } 16 | 17 | LRESULT CMultiStringValueDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 18 | InitDynamicLayout(); 19 | SetDialogIcon(IDI_TEXT); 20 | 21 | ULONG chars = 0; 22 | m_Key.QueryMultiStringValue(m_Name, nullptr, &chars); 23 | if (chars) { 24 | chars++; 25 | auto buffer = std::make_unique(chars); 26 | ZeroMemory(buffer.get(), chars * sizeof(WCHAR)); 27 | DWORD type; 28 | auto len = chars * 2; 29 | if (ERROR_SUCCESS != ::RegQueryValueEx(m_Key.Get(), m_Name, nullptr, &type, (PBYTE)buffer.get(), &len)) { 30 | EndDialog(IDRETRY); 31 | return 0; 32 | } 33 | std::for_each(buffer.get(), buffer.get() + chars - 1, [](auto& ch) { 34 | if (ch == 0) ch = L'\n'; 35 | }); 36 | 37 | m_Value = buffer.get(); 38 | m_Value.Replace(L"\n", L"\r\n"); 39 | SetDlgItemText(IDC_VALUE, m_Value); 40 | } 41 | if (m_ReadOnly) { 42 | ((CEdit)GetDlgItem(IDC_VALUE)).SetReadOnly(TRUE); 43 | } 44 | SetDlgItemText(IDC_NAME, m_Name.IsEmpty() ? Helpers::DefaultValueName : m_Name); 45 | 46 | return 0; 47 | } 48 | 49 | LRESULT CMultiStringValueDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) { 50 | if (id == IDOK) { 51 | CString text; 52 | GetDlgItemText(IDC_VALUE, text); 53 | m_Modified = text != m_Value; 54 | if (m_Modified) 55 | m_Value = text; 56 | } 57 | EndDialog(id); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /RegExp/MultiStringValueDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "RegistryKey.h" 5 | 6 | class CMultiStringValueDlg : 7 | public CDialogImpl, 8 | public CDialogHelper, 9 | public CDynamicDialogLayout { 10 | public: 11 | enum { IDD = IDD_MULTISTRVALUE }; 12 | 13 | CMultiStringValueDlg(RegistryKey& key, PCWSTR name, bool readOnly); 14 | 15 | const CString& GetValue() const; 16 | bool IsModified() const; 17 | 18 | BEGIN_MSG_MAP(CMultiStringValueDlg) 19 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 20 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 21 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 22 | CHAIN_MSG_MAP(CDynamicDialogLayout) 23 | REFLECT_NOTIFICATIONS_EX() 24 | END_MSG_MAP() 25 | 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 | private: 32 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 33 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 34 | 35 | RegistryKey& m_Key; 36 | CString m_Name; 37 | CString m_Value; 38 | bool m_ReadOnly; 39 | bool m_Modified{ false }; 40 | }; 41 | -------------------------------------------------------------------------------- /RegExp/NavigationManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct NavigationManager { 5 | bool CanGoBack() const { 6 | return _current > 0; 7 | } 8 | 9 | T const& GoBack() { 10 | ATLASSERT(CanGoBack()); 11 | return _items[--_current]; 12 | } 13 | 14 | bool CanGoForward() const { 15 | return _current < _items.size() - 1; 16 | } 17 | 18 | T const& GoForward() { 19 | ATLASSERT(CanGoForward()); 20 | return _items[++_current]; 21 | } 22 | 23 | void Add(T const& address) { 24 | _current++; 25 | _items.resize(_current); 26 | _items.push_back(address); 27 | } 28 | 29 | private: 30 | std::vector _items; 31 | int _current{ -1 }; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /RegExp/NtDll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef _Return_type_success_(return >= 0) LONG NTSTATUS; 4 | 5 | #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) 6 | 7 | #ifndef NT_SUCCESS 8 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 9 | #endif 10 | 11 | #ifndef STATUS_SUCCESS 12 | constexpr NTSTATUS STATUS_SUCCESS = 0; 13 | #endif 14 | 15 | _When_(Status < 0, _Out_range_(> , 0)) 16 | _When_(Status >= 0, _Out_range_(== , 0)) 17 | extern "C" ULONG NTAPI RtlNtStatusToDosError(NTSTATUS Status); 18 | 19 | typedef struct _UNICODE_STRING { 20 | USHORT Length; 21 | USHORT MaximumLength; 22 | PWSTR Buffer; 23 | } UNICODE_STRING; 24 | typedef UNICODE_STRING* PUNICODE_STRING; 25 | typedef const UNICODE_STRING* PCUNICODE_STRING; 26 | 27 | #define OBJ_CASE_INSENSITIVE 0x00000040 28 | 29 | extern "C" VOID NTAPI RtlInitUnicodeString( 30 | PUNICODE_STRING DestinationString, 31 | PCWSTR SourceString); 32 | 33 | #ifndef InitializeObjectAttributes 34 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 35 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 36 | (p)->RootDirectory = r; \ 37 | (p)->Attributes = a; \ 38 | (p)->ObjectName = n; \ 39 | (p)->SecurityDescriptor = s; \ 40 | (p)->SecurityQualityOfService = NULL; \ 41 | } 42 | #endif 43 | 44 | typedef struct _OBJECT_TYPE_INFORMATION { 45 | UNICODE_STRING TypeName; 46 | ULONG TotalNumberOfObjects; 47 | ULONG TotalNumberOfHandles; 48 | ULONG TotalPagedPoolUsage; 49 | ULONG TotalNonPagedPoolUsage; 50 | ULONG TotalNamePoolUsage; 51 | ULONG TotalHandleTableUsage; 52 | ULONG HighWaterNumberOfObjects; 53 | ULONG HighWaterNumberOfHandles; 54 | ULONG HighWaterPagedPoolUsage; 55 | ULONG HighWaterNonPagedPoolUsage; 56 | ULONG HighWaterNamePoolUsage; 57 | ULONG HighWaterHandleTableUsage; 58 | ULONG InvalidAttributes; 59 | GENERIC_MAPPING GenericMapping; 60 | ULONG ValidAccessMask; 61 | BOOLEAN SecurityRequired; 62 | BOOLEAN MaintainHandleCount; 63 | UCHAR TypeIndex; // since WINBLUE 64 | CHAR ReservedByte; 65 | ULONG PoolType; 66 | ULONG DefaultPagedPoolCharge; 67 | ULONG DefaultNonPagedPoolCharge; 68 | } OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION; 69 | 70 | typedef struct _OBJECT_TYPES_INFORMATION { 71 | ULONG NumberOfTypes; 72 | OBJECT_TYPE_INFORMATION TypeInformation[1]; 73 | } OBJECT_TYPES_INFORMATION, * POBJECT_TYPES_INFORMATION; 74 | 75 | typedef struct _OBJECT_ATTRIBUTES { 76 | ULONG Length; 77 | HANDLE RootDirectory; 78 | PUNICODE_STRING ObjectName; 79 | ULONG Attributes; 80 | PVOID SecurityDescriptor; 81 | PVOID SecurityQualityOfService; 82 | } OBJECT_ATTRIBUTES; 83 | typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES; 84 | 85 | typedef enum _OBJECT_INFORMATION_CLASS { 86 | ObjectBasicInformation, // OBJECT_BASIC_INFORMATION 87 | ObjectNameInformation, // OBJECT_NAME_INFORMATION 88 | ObjectTypeInformation, // OBJECT_TYPE_INFORMATION 89 | ObjectTypesInformation, // OBJECT_TYPES_INFORMATION 90 | ObjectHandleFlagInformation, // OBJECT_HANDLE_FLAG_INFORMATION 91 | ObjectSessionInformation, 92 | ObjectSessionObjectInformation, 93 | MaxObjectInfoClass 94 | } OBJECT_INFORMATION_CLASS; 95 | 96 | extern "C" NTSTATUS NTAPI NtQueryObject( 97 | _In_opt_ HANDLE Handle, 98 | _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, 99 | _Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation, 100 | _In_ ULONG ObjectInformationLength, 101 | _Out_opt_ PULONG ReturnLength); 102 | 103 | extern "C" NTSTATUS NTAPI NtOpenKey( 104 | _Out_ PHANDLE KeyHandle, 105 | _In_ ACCESS_MASK DesiredAccess, 106 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 107 | ); 108 | 109 | extern "C" NTSTATUS NTAPI NtCreateKey( 110 | _Out_ PHANDLE KeyHandle, 111 | _In_ ACCESS_MASK DesiredAccess, 112 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 113 | _Reserved_ ULONG TitleIndex, 114 | _In_opt_ PUNICODE_STRING Class, 115 | _In_ ULONG CreateOptions, 116 | _Out_opt_ PULONG Disposition 117 | ); 118 | 119 | enum class SystemInformationClass { 120 | ExtendedHandleInformation = 64, 121 | }; 122 | 123 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { 124 | PVOID Object; 125 | ULONG_PTR UniqueProcessId; 126 | ULONG_PTR HandleValue; 127 | ULONG GrantedAccess; 128 | USHORT CreatorBackTraceIndex; 129 | USHORT ObjectTypeIndex; 130 | ULONG HandleAttributes; 131 | ULONG Reserved; 132 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; 133 | 134 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX { 135 | ULONG_PTR NumberOfHandles; 136 | ULONG_PTR Reserved; 137 | SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; 138 | } SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX; 139 | 140 | extern "C" NTSTATUS NTAPI NtQuerySystemInformation( 141 | _In_ SystemInformationClass SystemInformationClass, 142 | _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, 143 | _In_ ULONG SystemInformationLength, 144 | _Out_opt_ PULONG ReturnLength); 145 | -------------------------------------------------------------------------------- /RegExp/NumberValueDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Resource.h" 3 | #include "NumberValueDlg.h" 4 | #include "Helpers.h" 5 | 6 | CNumberValueDlg::CNumberValueDlg(RegistryKey& key, PCWSTR name, DWORD type, bool readOnly) 7 | : m_Key(key), m_Name(name), m_Type(type), m_ReadOnly(readOnly) { 8 | } 9 | 10 | DWORD64 CNumberValueDlg::GetValue() const { 11 | return m_Value; 12 | } 13 | 14 | DWORD CNumberValueDlg::GetType() const { 15 | return m_Type; 16 | } 17 | 18 | bool CNumberValueDlg::IsModified() const { 19 | return m_Modified; 20 | } 21 | 22 | void CNumberValueDlg::DisplayValue(DWORD64 value, bool checkRadio) { 23 | CString text; 24 | switch (m_Format) { 25 | case ValueFormat::Decimal: 26 | text.Format(m_Type == REG_DWORD ? L"%u" : L"%llu", value); 27 | if(checkRadio) 28 | CheckDlgButton(IDC_DECIMAL, TRUE); 29 | break; 30 | 31 | case ValueFormat::Hex: 32 | text.Format(m_Type == REG_DWORD ? L"%X" : L"%llX", value); 33 | if (checkRadio) 34 | CheckDlgButton(IDC_HEX, TRUE); 35 | break; 36 | 37 | case ValueFormat::Binary: 38 | text = Helpers::ToBinary(value); 39 | if (checkRadio) 40 | CheckDlgButton(IDC_BINARY, TRUE); 41 | break; 42 | } 43 | SetDlgItemText(IDC_VALUE, text); 44 | } 45 | 46 | DWORD64 CNumberValueDlg::ParseValue(const CString& text, bool& error) { 47 | error = false; 48 | return _wcstoui64(text, nullptr, (int)m_Format); 49 | } 50 | 51 | LRESULT CNumberValueDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 52 | ATLASSERT(m_Type == REG_DWORD || m_Type == REG_QWORD); 53 | m_Value = 0; 54 | ULONG bytes = m_Type == REG_DWORD ? 4 : 8; 55 | DWORD type; 56 | if (ERROR_SUCCESS != m_Key.QueryValue(m_Name, &type, &m_Value, &bytes)) { 57 | EndDialog(IDRETRY); 58 | return 0; 59 | } 60 | ATLASSERT(m_Type == type); 61 | SetDialogIcon(m_Type == REG_DWORD ? IDI_NUM4 : IDI_NUM8); 62 | SetWindowText(m_Type == REG_DWORD ? L"DWORD Value" : L"QWORD Value"); 63 | SetDlgItemText(IDC_NAME, m_Name.IsEmpty() ? Helpers::DefaultValueName : m_Name); 64 | DisplayValue(m_Value); 65 | 66 | if (m_ReadOnly) 67 | ((CEdit)GetDlgItem(IDC_VALUE)).SetReadOnly(TRUE); 68 | 69 | if (m_Type == REG_QWORD) { 70 | GetDlgItem(IDC_COLOR).ShowWindow(SW_HIDE); 71 | int extra = 120; 72 | CRect rc; 73 | GetWindowRect(&rc); 74 | SetWindowPos(nullptr, 0, 0, rc.Width() + extra, rc.Height(), SWP_NOMOVE | SWP_NOREPOSITION); 75 | GetDlgItem(IDC_VALUE).GetClientRect(&rc); 76 | GetDlgItem(IDC_VALUE).SetWindowPos(nullptr, 0, 0, rc.right + extra, rc.bottom, SWP_NOMOVE | SWP_NOREPOSITION); 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | LRESULT CNumberValueDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 83 | if (IDOK == wID) { 84 | CString text; 85 | GetDlgItemText(IDC_VALUE, text); 86 | bool error; 87 | auto value = ParseValue(text, error); 88 | if (error) { 89 | AtlMessageBox(m_hWnd, L"Error parsing value", IDS_APP_TITLE, MB_ICONERROR); 90 | return 0; 91 | } 92 | if (m_Value != value) { 93 | m_Value = value; 94 | m_Modified = true; 95 | } 96 | } 97 | EndDialog(wID); 98 | return 0; 99 | } 100 | 101 | LRESULT CNumberValueDlg::OnClickBase(WORD, WORD id, HWND, BOOL&) { 102 | CString text; 103 | GetDlgItemText(IDC_VALUE, text); 104 | bool error; 105 | auto value = ParseValue(text, error); 106 | 107 | switch (id) { 108 | case IDC_HEX: m_Format = ValueFormat::Hex; break; 109 | case IDC_DECIMAL: m_Format = ValueFormat::Decimal; break; 110 | case IDC_BINARY: m_Format = ValueFormat::Binary; break; 111 | } 112 | DisplayValue(value, false); 113 | return 0; 114 | } 115 | 116 | LRESULT CNumberValueDlg::OnClickColor(WORD, WORD id, HWND, BOOL&) { 117 | CString text; 118 | GetDlgItemText(IDC_VALUE, text); 119 | bool error; 120 | auto value = ParseValue(text, error); 121 | CColorDialog dlg((COLORREF)value, CC_RGBINIT); 122 | if (dlg.DoModal() == IDOK && !m_ReadOnly) { 123 | DisplayValue(dlg.GetColor(), false); 124 | } 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /RegExp/NumberValueDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "RegistryKey.h" 5 | 6 | class CNumberValueDlg : 7 | public CDialogImpl, 8 | public CDialogHelper { 9 | public: 10 | enum { IDD = IDD_NUMBERVALUE }; 11 | 12 | CNumberValueDlg(RegistryKey& key, PCWSTR name, DWORD type, bool readOnly); 13 | 14 | DWORD64 GetValue() const; 15 | DWORD GetType() const; 16 | bool IsModified() const; 17 | 18 | BEGIN_MSG_MAP(CNumberValueDlg) 19 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 20 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 21 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 22 | COMMAND_ID_HANDLER(IDC_DECIMAL, OnClickBase) 23 | COMMAND_ID_HANDLER(IDC_HEX, OnClickBase) 24 | COMMAND_ID_HANDLER(IDC_BINARY, OnClickBase) 25 | COMMAND_ID_HANDLER(IDC_COLOR, OnClickColor) 26 | REFLECT_NOTIFICATIONS_EX() 27 | END_MSG_MAP() 28 | 29 | // Handler prototypes (uncomment arguments if needed): 30 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 31 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 32 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 33 | 34 | private: 35 | enum class ValueFormat { 36 | Decimal = 10, Hex = 16, Binary = 2, Octal = 8 37 | }; 38 | void DisplayValue(DWORD64 value, bool checkRadio = true); 39 | DWORD64 ParseValue(const CString& text, bool& error); 40 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 41 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 42 | LRESULT OnClickBase(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 43 | LRESULT OnClickColor(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 44 | 45 | RegistryKey& m_Key; 46 | CString m_Name; 47 | DWORD64 m_Value; 48 | DWORD m_Type; 49 | bool m_ReadOnly; 50 | bool m_Modified{ false }; 51 | inline static ValueFormat m_Format{ ValueFormat::Decimal }; 52 | }; 53 | -------------------------------------------------------------------------------- /RegExp/QuickFilterBar.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "QuickFilterBar.h" 4 | 5 | LRESULT CQuickFilterBar::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 6 | ((CButton)GetDlgItem(IDC_CLEAR)).SetIcon(AtlLoadIconImage(IDI_DELETE, 0, 16, 16)); 7 | m_Edit.SubclassWindow(GetDlgItem(IDC_FILTER)); 8 | 9 | return 0; 10 | } 11 | 12 | LRESULT CQuickFilterBar::OnDialogColor(UINT, WPARAM, LPARAM, BOOL&) { 13 | return (LRESULT)::GetSysColorBrush(COLOR_WINDOW); 14 | } 15 | 16 | LRESULT CQuickFilterBar::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) { 17 | if (id == 1) { 18 | KillTimer(id); 19 | CString text; 20 | GetDlgItemText(IDC_FILTER, text); 21 | m_pFrame->QuickFilter(text); 22 | } 23 | return 0; 24 | } 25 | 26 | LRESULT CQuickFilterBar::OnSetFocus(UINT, WPARAM, LPARAM, BOOL&) { 27 | m_Edit.SetSelAll(); 28 | m_Edit.SetFocus(); 29 | return 0; 30 | } 31 | 32 | LRESULT CQuickFilterBar::OnClearText(WORD, WORD, HWND, BOOL&) { 33 | m_Edit.SetWindowText(L""); 34 | m_pFrame->QuickFilter(L""); 35 | ::SetFocus(m_pFrame->GetHwnd()); 36 | 37 | return 0; 38 | } 39 | 40 | LRESULT CQuickFilterBar::OnEditKeyUp(UINT, WPARAM wp, LPARAM, BOOL& handled) { 41 | if (wp == VK_TAB) { 42 | ::SetFocus(m_pFrame->GetHwnd()); 43 | return 0; 44 | } 45 | if (wp == VK_ESCAPE) { 46 | SetDlgItemText(IDC_FILTER, L""); 47 | m_pFrame->QuickFilter(L""); 48 | return 0; 49 | } 50 | 51 | SetTimer(1, 300); 52 | return TRUE; 53 | } 54 | 55 | LRESULT CQuickFilterBar::OnEditChar(UINT, WPARAM wp, LPARAM, BOOL& handled) { 56 | if (wp == VK_ESCAPE || wp == VK_TAB) 57 | return 0; 58 | 59 | handled = FALSE; 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /RegExp/QuickFilterBar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "IMainFrame.h" 5 | 6 | struct CQuickFilterBar : 7 | public CDialogHelper, 8 | public CDialogImpl { 9 | 10 | enum { IDD = IDD_QUICKFILTER }; 11 | 12 | CQuickFilterBar(IMainFrame* frame) : m_pFrame(frame), m_Edit(this, 1) {} 13 | 14 | protected: 15 | BEGIN_MSG_MAP(CQuickFilterBar) 16 | MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | MESSAGE_HANDLER(WM_CTLCOLORDLG, OnDialogColor) 19 | MESSAGE_HANDLER(WM_TIMER, OnTimer) 20 | COMMAND_ID_HANDLER(IDC_CLEAR, OnClearText) 21 | ALT_MSG_MAP(1) 22 | MESSAGE_HANDLER(WM_KEYUP, OnEditKeyUp) 23 | MESSAGE_HANDLER(WM_CHAR, OnEditChar) 24 | END_MSG_MAP() 25 | 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 | private: 32 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 33 | LRESULT OnDialogColor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 34 | LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 35 | LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 36 | LRESULT OnClearText(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 37 | 38 | LRESULT OnEditKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 39 | LRESULT OnEditChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 40 | 41 | CContainedWindowT m_Edit; 42 | IMainFrame* m_pFrame; 43 | }; 44 | -------------------------------------------------------------------------------- /RegExp/RegExp.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "pch.h" 3 | #include "RegExp.h" 4 | #include "MainFrame.h" 5 | #include "ThemeHelper.h" 6 | #include "DriverHelper.h" 7 | #include "SecurityHelper.h" 8 | #include "AppSettings.h" 9 | 10 | CAppModule _Module; 11 | AppSettings _Settings; 12 | 13 | int Run(LPTSTR lpstrCmdLine = nullptr, int nCmdShow = SW_SHOWDEFAULT) { 14 | CMessageLoop theLoop; 15 | _Module.AddMessageLoop(&theLoop); 16 | 17 | CMainFrame wndMain; 18 | 19 | CString cmdline(lpstrCmdLine); 20 | cmdline.Trim(L" \""); 21 | if (!cmdline.IsEmpty() && cmdline.Right(11).CompareNoCase(L"regedit.exe") != 0) 22 | wndMain.SetStartKey(cmdline); 23 | 24 | if (wndMain.CreateEx() == nullptr) { 25 | ATLTRACE(_T("Main window creation failed!\n")); 26 | return 0; 27 | } 28 | 29 | wndMain.ShowWindow(nCmdShow); 30 | 31 | int nRet = theLoop.Run(); 32 | 33 | _Module.RemoveMessageLoop(); 34 | return nRet; 35 | } 36 | 37 | int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { 38 | HRESULT hRes = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 39 | ATLASSERT(SUCCEEDED(hRes)); 40 | 41 | AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES); 42 | 43 | hRes = _Module.Init(nullptr, hInstance); 44 | ATLASSERT(SUCCEEDED(hRes)); 45 | 46 | ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 47 | ThemeHelper::Init(); 48 | 49 | if (!DriverHelper::IsDriverLoaded() && SecurityHelper::IsRunningElevated()) { 50 | //auto loaded = DriverHelper::LoadDriver(); 51 | //if (!loaded) 52 | // AtlMessageBox(nullptr, L"Failed to load kernel driver. Some keys will be inaccesible", IDS_APP_TITLE, MB_ICONWARNING); 53 | } 54 | 55 | int nRet = Run(lpCmdLine, nCmdShow); 56 | 57 | _Module.Term(); 58 | ::CoUninitialize(); 59 | 60 | return 0; 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /RegExp/RegExp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | -------------------------------------------------------------------------------- /RegExp/RegExp.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/RegExp/RegExp.rc -------------------------------------------------------------------------------- /RegExp/RegExportImport.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "RegExportImport.h" 3 | #include "Registry.h" 4 | 5 | bool RegExportImport::Export(PCWSTR keyPath, PCWSTR path) const { 6 | auto hFile = ::CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr); 7 | if (hFile == INVALID_HANDLE_VALUE) 8 | return false; 9 | 10 | WriteString(hFile, L"Windows Registry Editor Version 5.00\n\n"); 11 | 12 | auto key = Registry::OpenKey(keyPath, KEY_READ); 13 | if (!key) 14 | return false; 15 | 16 | bool success = ExportKeys(key, hFile, keyPath); 17 | ::CloseHandle(hFile); 18 | return success; 19 | } 20 | 21 | bool RegExportImport::ExportKeys(HKEY hKey, HANDLE hFile, PCWSTR section) const { 22 | ExportKey(hKey, hFile, section); 23 | Registry::EnumSubKeys(hKey, [&](auto name, const auto&) { 24 | RegistryKey subKey; 25 | subKey.Open(hKey, name, KEY_READ); 26 | if(subKey) 27 | ExportKeys(subKey, hFile, section + CString(L"\\") + name); 28 | return true; 29 | }); 30 | return true; 31 | } 32 | 33 | bool RegExportImport::ExportKey(HKEY hKey, HANDLE hFile, PCWSTR section) const { 34 | WriteString(hFile, CString(L"[") + section + L"]\n"); 35 | 36 | RegistryKey key(hKey, false); 37 | Registry::EnumKeyValues(hKey, [&](auto type, auto name, auto size) { 38 | CString sname(name); 39 | if (sname.IsEmpty()) 40 | sname = L"@"; 41 | else 42 | sname = L"\"" + sname + L"\""; 43 | 44 | auto data = std::make_unique(size + 3); 45 | auto count{ size }; 46 | if (ERROR_SUCCESS != key.QueryValue(name, nullptr, data.get(), &count)) 47 | return true; 48 | 49 | switch (type) { 50 | case REG_DWORD: 51 | WriteString(hFile, sname + (L"=dword:" + std::format(L"{:08x}\n", *(DWORD*)data.get())).c_str()); 52 | break; 53 | 54 | case REG_SZ: { 55 | CString text((PCWSTR)data.get()); 56 | text.Replace(L"\"", L"\\\""); 57 | WriteString(hFile, sname + L"=\"" + text + L"\"\n"); 58 | break; 59 | } 60 | 61 | case REG_BINARY: 62 | WriteString(hFile, sname + L"=hex:" + BytesToString(data.get(), count) + L"\n"); 63 | break; 64 | 65 | default: 66 | WriteString(hFile, sname + std::format(L"=hex({:x}):", type).c_str() 67 | + BytesToString(data.get(), count) + L"\n"); 68 | break; 69 | } 70 | 71 | return true; 72 | }); 73 | WriteString(hFile, L"\n"); 74 | return true; 75 | } 76 | 77 | CString RegExportImport::BytesToString(BYTE const* data, DWORD count) { 78 | CString text, chars; 79 | for (DWORD i = 0; i < count; i++) { 80 | chars.Format(L"%02X,", data[i]); 81 | if (i % 32 == 31 && i < count - 1) 82 | text += L"\\\n"; 83 | text += chars; 84 | } 85 | return text.Left(text.GetLength() - 1); 86 | } 87 | 88 | bool RegExportImport::WriteString(HANDLE hFile, CString const& text) { 89 | DWORD bytes; 90 | return ::WriteFile(hFile, text.GetString(), text.GetLength() * sizeof(WCHAR), &bytes, nullptr); 91 | } 92 | -------------------------------------------------------------------------------- /RegExp/RegExportImport.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct RegExportImport { 4 | bool Export(PCWSTR key, PCWSTR path) const; 5 | bool Import(PCWSTR path, HKEY hKey); 6 | 7 | private: 8 | bool ExportKeys(HKEY hKey, HANDLE hFile, PCWSTR section) const; 9 | bool ExportKey(HKEY hKey, HANDLE hFile, PCWSTR section) const; 10 | static CString BytesToString(BYTE const* data, DWORD count); 11 | static bool WriteString(HANDLE hFile, CString const& text); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /RegExp/Registry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RegistryKey.h" 4 | 5 | struct Hive { 6 | std::wstring Key; 7 | std::wstring Path; 8 | }; 9 | 10 | struct RegistryItem { 11 | CString Name; 12 | mutable CString Value; 13 | mutable DWORD Type; 14 | mutable DWORD Size{ 0 }; 15 | FILETIME TimeStamp{}; 16 | bool Key : 1 { false }; 17 | }; 18 | 19 | struct RemoteRegistry { 20 | HKEY hLocal, hUsers; 21 | CString ComputerName; 22 | }; 23 | 24 | const DWORD REG_KEY = 0x1111; 25 | const DWORD REG_KEY_UP = 0x1112; 26 | 27 | struct HandleInfo { 28 | ULONG Handle; 29 | PVOID Object; 30 | DWORD Access; 31 | DWORD ProcessId; 32 | ULONG Attributes; 33 | CString Name; 34 | CString ProcessName; 35 | }; 36 | 37 | struct Registry abstract final { 38 | static DWORD EnumSubKeys(HKEY key, std::function handler); 39 | static DWORD EnumKeyValues(HKEY key, const std::function& handler); 40 | static CString QueryStringValue(RegistryKey& key, PCWSTR name); 41 | static CString StdRegPathToRealPath(const CString& path); 42 | static CString GetRegTypeAsString(DWORD type); 43 | static CString GetDataAsString(RegistryKey& key, const RegistryItem& item); 44 | static HKEY OpenRealRegistryKey(PCWSTR path = nullptr, DWORD access = KEY_READ); 45 | static HKEY CreateRealRegistryKey(PCWSTR path, DWORD access = KEY_READ); 46 | static bool RenameKey(HKEY hKey, PCWSTR name, PCWSTR newName); 47 | static bool RenameValue(HKEY hKey, PCWSTR path, PCWSTR oldName, PCWSTR newName); 48 | static bool CopyKey(HKEY hKey, PCWSTR path, HKEY htarget); 49 | static bool CopyValue(HKEY hSource, HKEY hTarget, PCWSTR sourceName, PCWSTR targetName); 50 | static DWORD GetSubKeyCount(HKEY hKey, DWORD* values = 0, FILETIME* ft = nullptr); 51 | 52 | static RegistryKey OpenKey(const CString& path, DWORD access, bool* root = nullptr); 53 | static CRegKey CreateKey(const CString& path, DWORD access); 54 | static bool IsKeyLink(HKEY hKey, PCWSTR path, CString& linkPath); 55 | static CString ExpandStrings(const CString& text); 56 | 57 | static bool ConnectRegistry(PCWSTR computerName); 58 | static bool Disconnect(PCWSTR computerName); 59 | 60 | static const std::vector& GetHiveList(bool refresh = false); 61 | static bool IsHiveKey(const CString& path); 62 | static bool IsKeyValid(HKEY h); 63 | static std::vector EnumKeyHandles(bool hideInaccessible); 64 | 65 | static inline const struct { 66 | PCWSTR text; 67 | PCWSTR stext; 68 | HKEY hKey; 69 | } Keys[] { 70 | { L"HKEY_CLASSES_ROOT", L"HKCR", HKEY_CLASSES_ROOT }, 71 | { L"HKEY_CURRENT_USER", L"HKCU", HKEY_CURRENT_USER }, 72 | { L"HKEY_LOCAL_MACHINE", L"HKLM", HKEY_LOCAL_MACHINE }, 73 | { L"HKEY_USERS", L"HKU", HKEY_USERS }, 74 | { L"HKEY_CURRENT_CONFIG", L"HKCC", HKEY_CURRENT_CONFIG }, 75 | { L"HKEY_PERFORMANCE_DATA", L"", HKEY_PERFORMANCE_DATA }, 76 | { L"HKEY_PERFORMANCE_TEXT", L"", HKEY_PERFORMANCE_TEXT }, 77 | { L"HKEY_PERFORMANCE_NLSTEXT", L"", HKEY_PERFORMANCE_NLSTEXT }, 78 | { L"HKEY_CURRENT_USER_LOCAL_SETTINGS", L"", HKEY_CURRENT_USER_LOCAL_SETTINGS }, 79 | }; 80 | 81 | private: 82 | inline static std::map _remotes; 83 | inline static std::vector _hives; 84 | }; 85 | -------------------------------------------------------------------------------- /RegExp/RegistryKey.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "RegistryKey.h" 3 | #include "Registry.h" 4 | 5 | RegistryKey::RegistryKey(HKEY hKey, bool own) noexcept : _hKey(hKey), _own(own) { 6 | ATLASSERT(IsValid()); 7 | CheckPredefinedKey(); 8 | } 9 | 10 | RegistryKey::RegistryKey(RegistryKey&& other) noexcept { 11 | _hKey = other._hKey; 12 | _own = other._own; 13 | CheckPredefinedKey(); 14 | ATLASSERT(IsValid()); 15 | other._hKey = nullptr; 16 | } 17 | 18 | RegistryKey& RegistryKey::operator=(RegistryKey&& other) noexcept { 19 | Close(); 20 | _hKey = other._hKey; 21 | _own = other._own; 22 | CheckPredefinedKey(); 23 | ATLASSERT(IsValid()); 24 | other._hKey = nullptr; 25 | return *this; 26 | } 27 | 28 | void RegistryKey::Close() { 29 | if (_own && _hKey) { 30 | ::RegCloseKey(_hKey); 31 | } 32 | _hKey = nullptr; 33 | } 34 | 35 | HKEY RegistryKey::Detach() { 36 | auto h = _hKey; 37 | _hKey = nullptr; 38 | return h; 39 | } 40 | 41 | void RegistryKey::Attach(HKEY hKey, bool own) { 42 | Close(); 43 | _hKey = hKey; 44 | _own = own; 45 | ATLASSERT(IsValid()); 46 | CheckPredefinedKey(); 47 | } 48 | 49 | bool RegistryKey::IsValid() const { 50 | return Registry::IsKeyValid(_hKey); 51 | } 52 | 53 | LSTATUS RegistryKey::Open(HKEY parent, PCWSTR path, DWORD access) { 54 | ATLASSERT(_hKey == nullptr); 55 | auto error = ::RegOpenKeyEx(parent, path, 0, access, &_hKey); 56 | CheckPredefinedKey(); 57 | return error; 58 | } 59 | 60 | LSTATUS RegistryKey::Create(HKEY parent, PCWSTR path, DWORD access) { 61 | ATLASSERT(_hKey == nullptr); 62 | auto error = ::RegCreateKeyEx(parent, path, 0, nullptr, 0, access, nullptr, &_hKey, nullptr); 63 | CheckPredefinedKey(); 64 | return error; 65 | } 66 | 67 | _Use_decl_annotations_ 68 | LSTATUS RegistryKey::SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType) noexcept { 69 | ATLASSUME(_hKey); 70 | ATLENSURE_RETURN_VAL(pszValue != NULL, ERROR_INVALID_DATA); 71 | ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ)); 72 | 73 | return ::RegSetValueEx(_hKey, pszValueName, 0, dwType, reinterpret_cast(pszValue), (static_cast(_tcslen(pszValue)) + 1) * sizeof(TCHAR)); 74 | } 75 | 76 | _Use_decl_annotations_ 77 | LSTATUS RegistryKey::SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) noexcept { 78 | LPCTSTR pszTemp; 79 | ULONG nBytes; 80 | ULONG nLength; 81 | 82 | ATLASSUME(_hKey); 83 | 84 | nBytes = 0; 85 | pszTemp = pszValue; 86 | do { 87 | nLength = static_cast(_tcslen(pszTemp)) + 1; 88 | pszTemp += nLength; 89 | nBytes += nLength * sizeof(TCHAR); 90 | } while (nLength != 1); 91 | 92 | return ::RegSetValueEx(_hKey, pszValueName, 0, REG_MULTI_SZ, reinterpret_cast(pszValue), nBytes); 93 | } 94 | 95 | LSTATUS RegistryKey::SetValue(_In_opt_z_ LPCTSTR pszValueName, _In_ DWORD dwType, _In_opt_ const void* pValue, _In_ ULONG nBytes) noexcept { 96 | ATLASSUME(_hKey); 97 | return ::RegSetValueEx(_hKey, pszValueName, 0, dwType, static_cast(pValue), nBytes); 98 | } 99 | 100 | LSTATUS RegistryKey::SetBinaryValue(_In_opt_z_ LPCTSTR pszValueName, _In_opt_ const void* pData, _In_ ULONG nBytes) noexcept { 101 | ATLASSUME(_hKey); 102 | return ::RegSetValueEx(_hKey, pszValueName, 0, REG_BINARY, reinterpret_cast(pData), nBytes); 103 | } 104 | 105 | LSTATUS RegistryKey::SetDWORDValue(_In_opt_z_ LPCTSTR pszValueName, _In_ DWORD dwValue) noexcept { 106 | ATLASSUME(_hKey); 107 | return ::RegSetValueEx(_hKey, pszValueName, 0, REG_DWORD, reinterpret_cast(&dwValue), sizeof(DWORD)); 108 | } 109 | 110 | LSTATUS RegistryKey::SetQWORDValue(_In_opt_z_ LPCTSTR pszValueName, _In_ ULONGLONG qwValue) noexcept { 111 | ATLASSUME(_hKey); 112 | return ::RegSetValueEx(_hKey, pszValueName, 0, REG_QWORD, reinterpret_cast(&qwValue), sizeof(ULONGLONG)); 113 | } 114 | 115 | LSTATUS RegistryKey::SetValue(_In_ DWORD dwValue, _In_opt_z_ LPCTSTR pszValueName) noexcept { 116 | ATLASSUME(_hKey); 117 | return SetDWORDValue(pszValueName, dwValue); 118 | } 119 | 120 | _Use_decl_annotations_ 121 | LSTATUS RegistryKey::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) noexcept { 122 | LONG lRes; 123 | DWORD dwType; 124 | ULONG nBytes; 125 | 126 | ATLASSUME(_hKey != NULL); 127 | ATLASSERT(pnChars != NULL); 128 | 129 | nBytes = (*pnChars) * sizeof(TCHAR); 130 | *pnChars = 0; 131 | lRes = ::RegQueryValueEx(_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), &nBytes); 132 | 133 | if (lRes != ERROR_SUCCESS) { 134 | return lRes; 135 | } 136 | 137 | if (dwType != REG_SZ && dwType != REG_EXPAND_SZ) { 138 | return ERROR_INVALID_DATA; 139 | } 140 | 141 | if (pszValue != NULL) { 142 | if (nBytes != 0) { 143 | if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) - 1] != 0)) { 144 | return ERROR_INVALID_DATA; 145 | } 146 | } 147 | else { 148 | pszValue[0] = _T('\0'); 149 | } 150 | } 151 | 152 | *pnChars = nBytes / sizeof(WCHAR); 153 | return ERROR_SUCCESS; 154 | } 155 | 156 | _Use_decl_annotations_ 157 | LSTATUS RegistryKey::QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) noexcept { 158 | LONG lRes; 159 | DWORD dwType; 160 | ULONG nBytes; 161 | 162 | ATLASSUME(_hKey); 163 | ATLASSERT(pnChars); 164 | 165 | if (pszValue != nullptr && *pnChars < 2) 166 | return ERROR_INSUFFICIENT_BUFFER; 167 | 168 | nBytes = (*pnChars) * sizeof(WCHAR); 169 | *pnChars = 0; 170 | 171 | lRes = ::RegQueryValueEx(_hKey, pszValueName, nullptr, &dwType, reinterpret_cast(pszValue), &nBytes); 172 | if (lRes != ERROR_SUCCESS) 173 | return lRes; 174 | if (dwType != REG_MULTI_SZ) 175 | return ERROR_INVALID_DATA; 176 | if (pszValue != nullptr && (nBytes % sizeof(WCHAR) != 0 || 177 | nBytes / sizeof(WCHAR) < 1 || pszValue[nBytes / sizeof(WCHAR) - 1] != 0 || 178 | ((nBytes / sizeof(WCHAR)) > 1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0))) 179 | return ERROR_INVALID_DATA; 180 | 181 | *pnChars = nBytes / sizeof(WCHAR); 182 | 183 | return ERROR_SUCCESS; 184 | } 185 | 186 | _Use_decl_annotations_ 187 | LONG RegistryKey::QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) noexcept { 188 | LONG lRes; 189 | DWORD dwType; 190 | 191 | ATLASSERT(pnBytes); 192 | ATLASSUME(_hKey); 193 | 194 | lRes = ::RegQueryValueEx(_hKey, pszValueName, nullptr, &dwType, static_cast(pValue), pnBytes); 195 | if (lRes != ERROR_SUCCESS) 196 | return lRes; 197 | if (dwType != REG_BINARY && dwType != REG_RESOURCE_LIST && dwType != REG_RESOURCE_REQUIREMENTS_LIST && dwType != REG_FULL_RESOURCE_DESCRIPTOR) 198 | return ERROR_INVALID_DATA; 199 | 200 | return ERROR_SUCCESS; 201 | } 202 | 203 | _Use_decl_annotations_ 204 | LSTATUS RegistryKey::QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) noexcept { 205 | ATLASSUME(_hKey != NULL); 206 | 207 | return(::RegQueryValueEx(_hKey, pszValueName, NULL, pdwType, static_cast(pData), pnBytes)); 208 | } 209 | 210 | _Use_decl_annotations_ 211 | LSTATUS RegistryKey::QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) noexcept { 212 | LONG lRes; 213 | ULONG nBytes; 214 | DWORD dwType; 215 | 216 | ATLASSUME(_hKey != NULL); 217 | 218 | nBytes = sizeof(DWORD); 219 | lRes = ::RegQueryValueEx(_hKey, pszValueName, nullptr, &dwType, reinterpret_cast(&dwValue), 220 | &nBytes); 221 | if (lRes != ERROR_SUCCESS) 222 | return lRes; 223 | if (dwType != REG_DWORD) 224 | return ERROR_INVALID_DATA; 225 | 226 | return ERROR_SUCCESS; 227 | } 228 | 229 | _Use_decl_annotations_ 230 | LSTATUS RegistryKey::QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) noexcept { 231 | LONG lRes; 232 | ULONG nBytes; 233 | DWORD dwType; 234 | 235 | ATLASSUME(_hKey); 236 | 237 | nBytes = sizeof(ULONGLONG); 238 | lRes = ::RegQueryValueEx(_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&qwValue), &nBytes); 239 | if (lRes != ERROR_SUCCESS) 240 | return lRes; 241 | if (dwType != REG_QWORD) 242 | return ERROR_INVALID_DATA; 243 | 244 | return ERROR_SUCCESS; 245 | } 246 | 247 | _Use_decl_annotations_ 248 | LSTATUS RegistryKey::DeleteValue(LPCTSTR lpszValue) noexcept { 249 | ATLASSUME(_hKey); 250 | return ::RegDeleteValue(_hKey, (LPTSTR)lpszValue); 251 | } 252 | 253 | void RegistryKey::CheckPredefinedKey() { 254 | if ((DWORD_PTR)_hKey & 0xf000000000000000) // predefined key 255 | _own = false; 256 | } 257 | 258 | -------------------------------------------------------------------------------- /RegExp/RegistryKey.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct RegistryKey { 4 | explicit RegistryKey(HKEY hKey = nullptr, bool own = true) noexcept; 5 | RegistryKey(const RegistryKey&) = delete; 6 | RegistryKey& operator=(const RegistryKey&) = delete; 7 | RegistryKey(RegistryKey&&) noexcept; 8 | RegistryKey& operator=(RegistryKey&&) noexcept; 9 | 10 | ~RegistryKey() { 11 | Close(); 12 | } 13 | 14 | void Close(); 15 | HKEY Detach(); 16 | void Attach(HKEY hKey, bool own = true); 17 | 18 | bool IsValid() const; 19 | 20 | operator bool() const { 21 | return _hKey != nullptr; 22 | } 23 | 24 | HKEY* AddressOf() { 25 | return &_hKey; 26 | } 27 | 28 | operator HKEY() const { 29 | return _hKey; 30 | } 31 | 32 | HKEY Get() const { 33 | return _hKey; 34 | } 35 | 36 | LSTATUS Open(HKEY parent, PCWSTR path, DWORD access = KEY_READ | KEY_WRITE); 37 | LSTATUS Create(HKEY parent, PCWSTR path, DWORD access = KEY_WRITE); 38 | LSTATUS SetValue(_In_opt_z_ LPCTSTR pszValueName, _In_ DWORD dwType, _In_opt_ const void* pValue, _In_ ULONG nBytes) noexcept; 39 | LSTATUS SetBinaryValue(_In_opt_z_ LPCTSTR pszValueName, _In_opt_ const void* pValue, _In_ ULONG nBytes) noexcept; 40 | LSTATUS SetDWORDValue(_In_opt_z_ LPCTSTR pszValueName, _In_ DWORD dwValue) noexcept; 41 | LSTATUS SetQWORDValue(_In_opt_z_ LPCTSTR pszValueName, _In_ ULONGLONG qwValue) noexcept; 42 | LSTATUS SetStringValue(_In_opt_z_ LPCTSTR pszValueName, _In_opt_z_ LPCTSTR pszValue, _In_ DWORD dwType = REG_SZ) noexcept; 43 | LSTATUS SetMultiStringValue(_In_opt_z_ LPCTSTR pszValueName, _In_z_ LPCTSTR pszValue) noexcept; 44 | LSTATUS SetValue(_In_ DWORD dwValue, _In_opt_z_ LPCTSTR pszValueName) noexcept; 45 | LSTATUS QueryValue(_Out_writes_to_opt_(*pdwCount, *pdwCount) LPTSTR szValue, _In_opt_z_ LPCTSTR lpszValueName, _Inout_ DWORD* pdwCount); 46 | LSTATUS QueryValue(_In_opt_z_ LPCTSTR pszValueName, _Out_opt_ DWORD* pdwType, _Out_opt_ void* pData, _Inout_ ULONG* pnBytes) noexcept; 47 | LSTATUS QueryBinaryValue(_In_opt_z_ LPCTSTR pszValueName, _Out_opt_ void* pValue, _Inout_opt_ ULONG* pnBytes) noexcept; 48 | LSTATUS QueryDWORDValue(_In_opt_z_ LPCTSTR pszValueName, _Out_ DWORD& dwValue) noexcept; 49 | LSTATUS QueryQWORDValue(_In_opt_z_ LPCTSTR pszValueName, _Out_ ULONGLONG& qwValue) noexcept; 50 | LSTATUS QueryStringValue(_In_opt_z_ LPCTSTR pszValueName, _Out_writes_to_opt_(*pnChars, *pnChars) LPTSTR pszValue, _Inout_ ULONG* pnChars) noexcept; 51 | LSTATUS QueryMultiStringValue(_In_opt_z_ LPCTSTR pszValueName, _Out_writes_to_opt_(*pnChars, *pnChars) LPTSTR pszValue, _Inout_ ULONG* pnChars) noexcept; 52 | LSTATUS DeleteSubKey(_In_z_ LPCTSTR lpszSubKey) noexcept; 53 | LSTATUS DeleteValue(_In_z_ LPCTSTR lpszValue) noexcept; 54 | 55 | private: 56 | void CheckPredefinedKey(); 57 | 58 | HKEY _hKey; 59 | bool _own; 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /RegExp/RegistrySearcher.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "RegistrySearcher.h" 3 | #include "Registry.h" 4 | 5 | void RegistrySearcher::SetStartKey(PCWSTR startKey) { 6 | std::lock_guard locker(_lock); 7 | _startKey = startKey; 8 | } 9 | 10 | void RegistrySearcher::SetOptions(FindOptions options) { 11 | std::lock_guard locker(_lock); 12 | _options = options; 13 | } 14 | 15 | void RegistrySearcher::SetText(PCWSTR text) { 16 | std::lock_guard locker(_lock); 17 | _searchText = text; 18 | } 19 | 20 | bool RegistrySearcher::Find(RegistrySearcherCallback callback) { 21 | ATLASSERT(callback); 22 | _cb = callback; 23 | _inProgress = true; 24 | _cancel = false; 25 | _hCancelEvent.reset(::CreateEvent(nullptr, TRUE, FALSE, nullptr)); 26 | _hContinueEvent.reset(::CreateEvent(nullptr, FALSE, FALSE, nullptr)); 27 | _hDoneEvent.reset(::CreateEvent(nullptr, TRUE, FALSE, nullptr)); 28 | 29 | _hThread.reset(::CreateThread(nullptr, 0, [](auto p) { 30 | return ((RegistrySearcher*)p)->DoSearch(); 31 | }, this, 0, nullptr)); 32 | ::SetThreadPriority(_hThread.get(), THREAD_PRIORITY_LOWEST); 33 | 34 | return true; 35 | } 36 | 37 | bool RegistrySearcher::Cancel() { 38 | if (IsRunning()) { 39 | ::SetEvent(_hCancelEvent.get()); 40 | _inProgress = false; 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | bool RegistrySearcher::Continue() { 47 | if (IsRunning()) { 48 | ::SetEvent(_hContinueEvent.get()); 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | bool RegistrySearcher::IsRunning() const { 55 | return _inProgress.load(); 56 | } 57 | 58 | bool RegistrySearcher::IsCancelled() const { 59 | return _cancel.load(); 60 | } 61 | 62 | bool RegistrySearcher::WaitForCompletion(DWORD timeout) { 63 | return WAIT_OBJECT_0 == ::WaitForSingleObject(_hDoneEvent.get(), timeout); 64 | } 65 | 66 | bool RegistrySearcher::FindNextWorker(HKEY hKey, const CString& path) { 67 | if (WAIT_OBJECT_0 == ::WaitForSingleObject(_hCancelEvent.get(), 0)) { 68 | _cancel = true; 69 | return false; 70 | } 71 | 72 | bool searchValues = (_options & FindOptions::SearchValues) == FindOptions::SearchValues; 73 | bool searchKeys = (_options & FindOptions::SearchKeys) == FindOptions::SearchKeys; 74 | bool searchData = (_options & FindOptions::SearchData) == FindOptions::SearchData; 75 | bool caseSensitive = (_options & FindOptions::MatchCase) == FindOptions::MatchCase; 76 | bool wholeWords = (_options & FindOptions::MatchWholeWords) == FindOptions::MatchWholeWords; 77 | { 78 | std::lock_guard locker(_lock); 79 | if (!caseSensitive) 80 | _searchText.MakeUpper(); 81 | } 82 | 83 | auto compare = [&](auto& text, auto& search) { 84 | int n = text.Find(search); 85 | if (n >= 0) { 86 | return !wholeWords || ((n == 0 || isspace(text[n - 1]) && (n + _searchText.GetLength() == text.GetLength() || isspace(text[n + _searchText.GetLength()])))); 87 | }; 88 | return false; 89 | }; 90 | 91 | if (searchValues || searchData) { 92 | Registry::EnumKeyValues(hKey, [&](auto type, auto name, auto size) { 93 | if (WAIT_OBJECT_0 == ::WaitForSingleObject(_hCancelEvent.get(), 0)) { 94 | _cancel = true; 95 | return false; 96 | } 97 | 98 | if (searchValues) { 99 | CString text(name); 100 | if (!caseSensitive) 101 | text.MakeUpper(); 102 | 103 | if (compare(text, _searchText)) { 104 | if (Notify(path, name, nullptr)) 105 | return false; 106 | } 107 | } 108 | if (searchData) { 109 | if (type == REG_SZ || type == REG_EXPAND_SZ) { 110 | size += 4 + (size % 2); // just in case the value is not stored properly in the Registry 111 | ATLASSERT(size % 2 == 0); 112 | auto buffer = std::make_unique(size / sizeof(WCHAR)); 113 | if (buffer) { 114 | ::ZeroMemory(buffer.get(), size); 115 | DWORD bytes = size; 116 | if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, name, nullptr, nullptr, (BYTE*)buffer.get(), &bytes)) { 117 | CString text(buffer.get()); 118 | if (!caseSensitive) 119 | text.MakeUpper(); 120 | if (compare(text, _searchText)) { 121 | if (Notify(path, name, buffer.get())) 122 | return false; 123 | } 124 | } 125 | } 126 | } 127 | else if (type == REG_MULTI_SZ) { 128 | size += 4 + (size % 2); // just in case the value is not stored properly in the Registry 129 | ATLASSERT(size % 2 == 0); 130 | auto buffer = std::make_unique(size / sizeof(WCHAR)); 131 | if (buffer) { 132 | ::ZeroMemory(buffer.get(), size); 133 | DWORD bytes = size; 134 | if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, name, nullptr, nullptr, (BYTE*)buffer.get(), &bytes)) { 135 | for (auto p = buffer.get(); *p; p += wcslen(p) + 1) { 136 | CString text(p); 137 | if (!caseSensitive) 138 | text.MakeUpper(); 139 | if (compare(text, _searchText)) { 140 | if (Notify(path, name, buffer.get())) 141 | return false; 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | return true; 149 | }); 150 | } 151 | if (_cancel) 152 | return false; 153 | 154 | Registry::EnumSubKeys(hKey, [&](auto name, const auto&) { 155 | if (WAIT_OBJECT_0 == ::WaitForSingleObject(_hCancelEvent.get(), 0)) { 156 | _cancel = true; 157 | return false; 158 | } 159 | if (searchKeys) { 160 | CString text(name); 161 | if (!caseSensitive) 162 | text.MakeUpper(); 163 | if (text.Find(_searchText) >= 0) { 164 | if (Notify(path + (path.IsEmpty() ? L"" : L"\\") + name, nullptr, nullptr)) 165 | return false; 166 | } 167 | } 168 | RegistryKey subKey; 169 | subKey.Open(hKey, name, KEY_READ); 170 | if (subKey) 171 | FindNextWorker(subKey.Get(), path + (path.IsEmpty() ? L"" : L"\\") + name); 172 | if (_cancel) 173 | return false; 174 | return true; 175 | }); 176 | 177 | if (_cancel) 178 | return false; 179 | 180 | return true; 181 | } 182 | 183 | bool RegistrySearcher::Notify(PCWSTR path, PCWSTR name, PCWSTR data) { 184 | if (!_cancel) 185 | _cb(path, name, data); 186 | HANDLE h[]{ _hCancelEvent.get(), _hContinueEvent.get() }; 187 | if (WAIT_OBJECT_0 == ::WaitForMultipleObjects(_countof(h), h, FALSE, INFINITE)) { 188 | _cancel = true; 189 | return true; 190 | } 191 | if ((_options & FindOptions::MatchCase) == FindOptions::None) 192 | _searchText.MakeUpper(); 193 | 194 | return false; 195 | } 196 | 197 | DWORD RegistrySearcher::DoSearch() { 198 | if ((_options & (FindOptions::SearchStdRegistry | FindOptions::SearchSelected)) == FindOptions::SearchStdRegistry) { 199 | for (auto key : Registry::Keys) { 200 | FindNextWorker(key.hKey, key.text); 201 | if (_cancel) 202 | break; 203 | } 204 | } 205 | if (!_cancel && (_options & (FindOptions::SearchRealRegistry | FindOptions::SearchSelected)) == FindOptions::SearchRealRegistry) { 206 | FindNextWorker(Registry::OpenRealRegistryKey(), L"\\REGISTRY"); 207 | } 208 | if (!_cancel && (_options & FindOptions::SearchSelected) == FindOptions::SearchSelected) { 209 | FindNextWorker(Registry::OpenKey(_startKey, KEY_READ).Get(), _startKey); 210 | } 211 | 212 | _cb(nullptr, nullptr, nullptr); 213 | ::SetEvent(_hDoneEvent.get()); 214 | _inProgress = false; 215 | 216 | return 0; 217 | } 218 | -------------------------------------------------------------------------------- /RegExp/RegistrySearcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FindOptions.h" 4 | #include 5 | #include 6 | 7 | using RegistrySearcherCallback = std::function; 8 | 9 | struct RegistrySearcher { 10 | void SetStartKey(PCWSTR startKey); 11 | void SetOptions(FindOptions options); 12 | void SetText(PCWSTR text); 13 | bool Find(RegistrySearcherCallback callback); 14 | 15 | bool Cancel(); 16 | bool Continue(); 17 | 18 | bool IsRunning() const; 19 | bool IsCancelled() const; 20 | bool WaitForCompletion(DWORD timeout = INFINITE); 21 | 22 | protected: 23 | bool FindNextWorker(HKEY hKey, const CString& path); 24 | bool Notify(PCWSTR path, PCWSTR value, PCWSTR data); 25 | 26 | private: 27 | DWORD DoSearch(); 28 | wil::unique_handle _hThread; 29 | FindOptions _options{ FindOptions::None }; 30 | RegistrySearcherCallback _cb; 31 | CString _searchText; 32 | std::mutex _lock; 33 | CString _startKey; 34 | wil::unique_handle _hCancelEvent, _hContinueEvent, _hDoneEvent; 35 | std::atomic _inProgress{ false }; 36 | std::atomic _cancel{ false }; 37 | }; 38 | -------------------------------------------------------------------------------- /RegExp/RenameKeyCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "RenameKeyCommand.h" 3 | #include "Registry.h" 4 | 5 | RenameKeyCommand::RenameKeyCommand(PCWSTR path, PCWSTR name, PCWSTR newName, AppCommandCallback cb) 6 | : RegAppCommandBase(L"Rename Key", path, name, cb), _newName(newName) { 7 | } 8 | 9 | bool RenameKeyCommand::Execute() { 10 | auto key = Registry::OpenKey(_path, KEY_ALL_ACCESS); 11 | if (!key) 12 | return false; 13 | 14 | if (Registry::RenameKey(key.Get(), _name, _newName)) { 15 | if (!InvokeCallback(true)) 16 | return false; 17 | std::swap(_name, _newName); 18 | return true; 19 | } 20 | 21 | return false; 22 | } 23 | 24 | bool RenameKeyCommand::Undo() { 25 | return Execute(); 26 | } 27 | 28 | const CString& RenameKeyCommand::GetNewName() const { 29 | return _newName; 30 | } 31 | 32 | CString RenameKeyCommand::GetCommandName() const { 33 | return L"Rename Key " + GetName(); 34 | } 35 | -------------------------------------------------------------------------------- /RegExp/RenameKeyCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "AppCommandBase.h" 4 | 5 | struct RenameKeyCommand : RegAppCommandBase { 6 | RenameKeyCommand(PCWSTR path, PCWSTR name, PCWSTR newName, AppCommandCallback cb = nullptr); 7 | 8 | bool Execute() override; 9 | bool Undo() override; 10 | 11 | const CString& GetNewName() const; 12 | 13 | CString GetCommandName() const override; 14 | 15 | private: 16 | CString _newName; 17 | }; 18 | -------------------------------------------------------------------------------- /RegExp/RenameValueCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "RenameValueCommand.h" 3 | #include "Registry.h" 4 | 5 | RenameValueCommand::RenameValueCommand(PCWSTR path, PCWSTR name, PCWSTR newName, AppCommandCallback cb) 6 | : RegAppCommandBase(L"Rename Value", path, name, cb), _newName(newName) { 7 | } 8 | 9 | bool RenameValueCommand::Execute() { 10 | auto key = Registry::OpenKey(_path, KEY_ALL_ACCESS); 11 | if (!key) 12 | return false; 13 | 14 | if (Registry::RenameValue(key.Get(), nullptr, _name, _newName)) { 15 | if (!InvokeCallback(true)) 16 | return false; 17 | std::swap(_name, _newName); 18 | return true; 19 | } 20 | 21 | return false; 22 | } 23 | 24 | bool RenameValueCommand::Undo() { 25 | return Execute(); 26 | } 27 | 28 | const CString& RenameValueCommand::GetNewName() const { 29 | return _newName; 30 | } 31 | 32 | CString RenameValueCommand::GetCommandName() const { 33 | return L"Rename Value " + GetName(); 34 | } 35 | -------------------------------------------------------------------------------- /RegExp/RenameValueCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma once 4 | 5 | #include "AppCommandBase.h" 6 | 7 | struct RenameValueCommand : RegAppCommandBase { 8 | RenameValueCommand(PCWSTR path, PCWSTR name, PCWSTR newName, AppCommandCallback cb = nullptr); 9 | 10 | bool Execute() override; 11 | bool Undo() override; 12 | 13 | const CString& GetNewName() const; 14 | 15 | CString GetCommandName() const override; 16 | 17 | private: 18 | CString _newName; 19 | }; 20 | -------------------------------------------------------------------------------- /RegExp/SecurityHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SecurityHelper.h" 3 | #include 4 | #include "DriverHelper.h" 5 | 6 | bool SecurityHelper::IsRunningElevated() { 7 | static bool runningElevated = false; 8 | static bool runningElevatedCheck = false; 9 | if (runningElevatedCheck) 10 | return runningElevated; 11 | 12 | runningElevatedCheck = true; 13 | wil::unique_handle hToken; 14 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, hToken.addressof())) 15 | return false; 16 | 17 | TOKEN_ELEVATION te; 18 | DWORD len; 19 | if (::GetTokenInformation(hToken.get(), TokenElevation, &te, sizeof(te), &len)) { 20 | runningElevated = te.TokenIsElevated ? true : false; 21 | } 22 | return runningElevated; 23 | } 24 | 25 | bool SecurityHelper::RunElevated() { 26 | WCHAR path[MAX_PATH]; 27 | ::GetModuleFileName(nullptr, path, _countof(path)); 28 | return (INT_PTR)::ShellExecute(nullptr, L"runas", path, nullptr, nullptr, SW_SHOWDEFAULT) > 31; 29 | } 30 | 31 | bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) { 32 | wil::unique_handle hToken; 33 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken.addressof())) 34 | return false; 35 | 36 | bool result = false; 37 | TOKEN_PRIVILEGES tp; 38 | tp.PrivilegeCount = 1; 39 | tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; 40 | if (::LookupPrivilegeValue(nullptr, privName, 41 | &tp.Privileges[0].Luid)) { 42 | if (::AdjustTokenPrivileges(hToken.get(), FALSE, &tp, sizeof(tp), 43 | nullptr, nullptr)) 44 | result = ::GetLastError() == ERROR_SUCCESS; 45 | } 46 | return result; 47 | } 48 | 49 | HANDLE SecurityHelper::DupHandle(HANDLE hSource, DWORD sourcePid, DWORD access) { 50 | auto h = DriverHelper::DupHandle(hSource, sourcePid, access, access == 0 ? DUPLICATE_SAME_ACCESS : 0); 51 | if (!h) { 52 | wil::unique_handle hProcess(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, sourcePid)); 53 | if (!hProcess) 54 | return nullptr; 55 | 56 | ::DuplicateHandle(hProcess.get(), hSource, ::GetCurrentProcess(), &h, access, FALSE, access == 0 ? DUPLICATE_SAME_ACCESS : 0); 57 | } 58 | return h; 59 | } 60 | -------------------------------------------------------------------------------- /RegExp/SecurityHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct SecurityHelper abstract final { 4 | static bool IsRunningElevated(); 5 | static bool RunElevated(); 6 | static bool EnablePrivilege(PCWSTR privName, bool enable); 7 | static HANDLE DupHandle(HANDLE hSource, DWORD sourcePid, DWORD access = 0); 8 | }; 9 | -------------------------------------------------------------------------------- /RegExp/SecurityInformation.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SecurityInformation.h" 3 | 4 | #pragma comment(lib, "Aclui.lib") 5 | 6 | CSecurityInformation::~CSecurityInformation() { 7 | } 8 | 9 | STDMETHODIMP CSecurityInformation::QueryInterface(REFIID riid, void** ppvObj) { 10 | if (riid == IID_IUnknown || riid == IID_ISecurityInformation) 11 | return *ppvObj = this, S_OK; 12 | return E_NOINTERFACE; 13 | } 14 | 15 | STDMETHODIMP CSecurityInformation::GetObjectInformation(PSI_OBJECT_INFO pInfo) { 16 | pInfo->dwFlags = SI_ADVANCED | SI_EDIT_OWNER | SI_CONTAINER | (m_ReadOnly ? (SI_READONLY | SI_OWNER_READONLY) : 0); 17 | pInfo->hInstance = nullptr; 18 | pInfo->pszPageTitle = nullptr; 19 | pInfo->pszObjectName = (LPWSTR)(LPCWSTR)m_Name; 20 | 21 | return S_OK; 22 | } 23 | 24 | STDMETHODIMP CSecurityInformation::GetAccessRights(const GUID* pguidObjectType, 25 | DWORD dwFlags, PSI_ACCESS* ppAccess, ULONG* pcAccesses, ULONG* piDefaultAccess) { 26 | static SI_ACCESS access[] = { 27 | { &GUID_NULL, KEY_CREATE_SUB_KEY, L"Create", SI_ACCESS_SPECIFIC }, 28 | { &GUID_NULL, KEY_ENUMERATE_SUB_KEYS, L"Enumerate", SI_ACCESS_SPECIFIC }, 29 | { &GUID_NULL, KEY_SET_VALUE, L"Set Value", SI_ACCESS_SPECIFIC }, 30 | { &GUID_NULL, KEY_QUERY_VALUE, L"Query Value", SI_ACCESS_SPECIFIC }, 31 | { &GUID_NULL, KEY_WRITE, L"Write", SI_ACCESS_GENERAL }, 32 | { &GUID_NULL, KEY_READ, L"Read", SI_ACCESS_GENERAL }, 33 | }; 34 | 35 | *ppAccess = access; 36 | *pcAccesses = _countof(access); 37 | *piDefaultAccess = 0; 38 | 39 | return S_OK; 40 | } 41 | 42 | STDMETHODIMP CSecurityInformation::GetInheritTypes(PSI_INHERIT_TYPE* ppInheritTypes, ULONG* pcInheritTypes) { 43 | return S_OK; 44 | } 45 | 46 | STDMETHODIMP CSecurityInformation::SetSecurity(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { 47 | return ::SetKernelObjectSecurity(m_hObject, SecurityInformation, pSecurityDescriptor) ? S_OK : HRESULT_FROM_WIN32(::GetLastError()); 48 | } 49 | 50 | STDMETHODIMP CSecurityInformation::MapGeneric(const GUID* pguidObjectType, UCHAR* pAceFlags, ACCESS_MASK* pMask) { 51 | return S_OK; 52 | } 53 | 54 | STDMETHODIMP CSecurityInformation::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage) { 55 | return S_OK; 56 | } 57 | 58 | STDMETHODIMP CSecurityInformation::GetSecurity(SECURITY_INFORMATION RequestedInformation, 59 | PSECURITY_DESCRIPTOR* ppSecurityDescriptor, BOOL fDefault) { 60 | auto code = ::GetSecurityInfo(m_hObject, SE_REGISTRY_KEY, RequestedInformation, 61 | nullptr, nullptr, nullptr, nullptr, ppSecurityDescriptor); 62 | 63 | return HRESULT_FROM_WIN32(code); 64 | } 65 | -------------------------------------------------------------------------------- /RegExp/SecurityInformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CSecurityInformation : public ISecurityInformation { 4 | public: 5 | CSecurityInformation(HANDLE hObject, const CString& name, bool readonly) : m_hObject(hObject), m_Name(name), m_ReadOnly(readonly) {} 6 | ~CSecurityInformation(); 7 | 8 | STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj); 9 | 10 | // use as static or stack based object 11 | 12 | STDMETHOD_(ULONG, AddRef)() { 13 | return 2; 14 | } 15 | STDMETHOD_(ULONG, Release)() { 16 | return 1; 17 | } 18 | 19 | // ISecurityInformation methods 20 | STDMETHOD(GetObjectInformation) (PSI_OBJECT_INFO pObjectInfo); 21 | STDMETHOD(GetSecurity) (SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR* ppSecurityDescriptor, BOOL fDefault); 22 | STDMETHOD(SetSecurity) (SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor); 23 | STDMETHOD(GetAccessRights) (const GUID* pguidObjectType, 24 | DWORD dwFlags, // SI_EDIT_AUDITS, SI_EDIT_PROPERTIES 25 | PSI_ACCESS* ppAccess, ULONG* pcAccesses, ULONG* piDefaultAccess); 26 | STDMETHOD(MapGeneric) (const GUID* pguidObjectType, UCHAR* pAceFlags, ACCESS_MASK* pMask); 27 | STDMETHOD(GetInheritTypes) (PSI_INHERIT_TYPE* ppInheritTypes, ULONG* pcInheritTypes); 28 | STDMETHOD(PropertySheetPageCallback)(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage); 29 | 30 | private: 31 | HANDLE m_hObject; 32 | CString m_Name; 33 | bool m_ReadOnly; 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /RegExp/StringValueDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "StringValueDlg.h" 4 | #include "Helpers.h" 5 | 6 | CStringValueDlg::CStringValueDlg(RegistryKey& key, PCWSTR name, bool readOnly) : m_Key(key), m_Name(name), m_ReadOnly(readOnly) { 7 | } 8 | 9 | const CString& CStringValueDlg::GetValue() const { 10 | return m_Value; 11 | } 12 | 13 | DWORD CStringValueDlg::GetType() const { 14 | return m_Type; 15 | } 16 | 17 | bool CStringValueDlg::IsModified() const { 18 | return m_Modified; 19 | } 20 | 21 | LRESULT CStringValueDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 22 | InitDynamicLayout(); 23 | SetDialogIcon(IDI_TEXT); 24 | 25 | ULONG chars = 0; 26 | m_Key.QueryStringValue(m_Name, nullptr, &chars); 27 | if (chars) { 28 | auto buffer = std::make_unique(chars); 29 | if (ERROR_SUCCESS != m_Key.QueryStringValue(m_Name, buffer.get(), &chars)) { 30 | EndDialog(IDRETRY); 31 | return 0; 32 | } 33 | SetDlgItemText(IDC_VALUE, m_Value = buffer.get()); 34 | } 35 | m_Key.QueryValue(m_Name, &m_Type, nullptr, nullptr); 36 | ATLASSERT(m_Type == REG_SZ || m_Type == REG_EXPAND_SZ); 37 | CheckDlgButton(m_Type == REG_SZ ? IDC_STRING : IDC_EXPANDSTRING, BST_CHECKED); 38 | 39 | if (m_ReadOnly) { 40 | ((CEdit)GetDlgItem(IDC_VALUE)).SetReadOnly(TRUE); 41 | GetDlgItem(IDC_STRING).EnableWindow(FALSE); 42 | GetDlgItem(IDC_EXPANDSTRING).EnableWindow(FALSE); 43 | GetDlgItem(IDC_FILE).EnableWindow(FALSE); 44 | GetDlgItem(IDC_FOLDER).EnableWindow(FALSE); 45 | } 46 | else { 47 | ::SHAutoComplete(GetDlgItem(IDC_VALUE), SHACF_FILESYS_DIRS); 48 | } 49 | SetDlgItemText(IDC_NAME, m_Name.IsEmpty() ? Helpers::DefaultValueName : m_Name); 50 | 51 | return 0; 52 | } 53 | 54 | LRESULT CStringValueDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 55 | if (wID == IDOK) { 56 | CString value; 57 | GetDlgItemText(IDC_VALUE, value); 58 | auto type = IsDlgButtonChecked(IDC_STRING) == BST_CHECKED ? REG_SZ : REG_EXPAND_SZ; 59 | if (type != m_Type || value != m_Value) { 60 | m_Value = value; 61 | m_Type = type; 62 | // 63 | // something changed 64 | // 65 | m_Modified = true; 66 | } 67 | } 68 | EndDialog(wID); 69 | return 0; 70 | } 71 | 72 | LRESULT CStringValueDlg::OnBrowseFile(WORD, WORD wID, HWND, BOOL&) { 73 | CFileDialog dlg(TRUE, nullptr, nullptr, OFN_EXPLORER | OFN_ENABLESIZING, 74 | L"All Files\0*.*\0", m_hWnd); 75 | if (dlg.DoModal() == IDOK) { 76 | SetDlgItemText(IDC_VALUE, dlg.m_szFileName); 77 | } 78 | return 0; 79 | } 80 | 81 | LRESULT CStringValueDlg::OnBrowseFolder(WORD, WORD wID, HWND, BOOL&) { 82 | CComPtr spFileDlg; 83 | auto hr = spFileDlg.CoCreateInstance(CLSID_FileOpenDialog); 84 | ATLASSERT(spFileDlg); 85 | if (FAILED(hr)) 86 | return 0; 87 | 88 | FILEOPENDIALOGOPTIONS options; 89 | spFileDlg->GetOptions(&options); 90 | spFileDlg->SetOptions(options | FOS_FORCEFILESYSTEM | FOS_FORCESHOWHIDDEN | FOS_PICKFOLDERS); 91 | if (S_OK == spFileDlg->Show(m_hWnd)) { 92 | CComPtr spItem; 93 | spFileDlg->GetResult(&spItem); 94 | ATLASSERT(spItem); 95 | PWSTR rpath; 96 | if (FAILED(spItem->GetDisplayName(SIGDN_FILESYSPATH, &rpath))) { 97 | AtlMessageBox(m_hWnd, L"Failed to retrieve selected folder", MB_ICONERROR); 98 | } 99 | else { 100 | SetDlgItemText(IDC_VALUE, rpath); 101 | ::CoTaskMemFree(rpath); 102 | } 103 | } 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /RegExp/StringValueDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "RegistryKey.h" 5 | 6 | class CStringValueDlg : 7 | public CDialogImpl, 8 | public CDialogHelper, 9 | public CDynamicDialogLayout { 10 | public: 11 | enum { IDD = IDD_STRINGVALUE }; 12 | 13 | CStringValueDlg(RegistryKey& key, PCWSTR name, bool readOnly); 14 | 15 | const CString& GetValue() const; 16 | DWORD GetType() const; 17 | bool IsModified() const; 18 | 19 | BEGIN_MSG_MAP(CStringValueDlg) 20 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 21 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 22 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 23 | COMMAND_ID_HANDLER(IDC_FILE, OnBrowseFile) 24 | COMMAND_ID_HANDLER(IDC_FOLDER, OnBrowseFolder) 25 | CHAIN_MSG_MAP(CDynamicDialogLayout) 26 | REFLECT_NOTIFICATIONS_EX() 27 | END_MSG_MAP() 28 | 29 | // Handler prototypes (uncomment arguments if needed): 30 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 31 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 32 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 33 | 34 | private: 35 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 36 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 37 | LRESULT OnBrowseFile(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 38 | LRESULT OnBrowseFolder(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 39 | 40 | RegistryKey& m_Key; 41 | CString m_Name; 42 | CString m_Value; 43 | DWORD m_Type{ 0 }; 44 | bool m_ReadOnly; 45 | bool m_Modified{ false }; 46 | }; 47 | -------------------------------------------------------------------------------- /RegExp/TreeHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "TreeHelper.h" 3 | 4 | HTREEITEM TreeHelper::FindChild(HTREEITEM item, PCWSTR name) const { 5 | item = _tv.GetChildItem(item); 6 | while (item) { 7 | CString text; 8 | _tv.GetItemText(item, text); 9 | if (text.CompareNoCase(name) == 0) 10 | return item; 11 | item = _tv.GetNextSiblingItem(item); 12 | } 13 | return nullptr; 14 | } 15 | 16 | HTREEITEM TreeHelper::FindItem(HTREEITEM hParent, PCWSTR path) { 17 | int start = 0; 18 | CString spath(path); 19 | if (spath[0] == L'\\') { 20 | // skip first 21 | spath = spath.Mid(spath.Find(L'\\', 1)); 22 | } 23 | HTREEITEM hItem = nullptr; 24 | while (hParent) { 25 | auto name = spath.Tokenize(L"\\", start); 26 | if (name.IsEmpty()) 27 | break; 28 | _tv.Expand(hParent, TVE_EXPAND); 29 | hItem = FindChild(hParent, name); 30 | if (!hItem) 31 | break; 32 | hParent = hItem; 33 | } 34 | return hItem; 35 | } 36 | 37 | int TreeHelper::DeleteChildren(HTREEITEM hItem) { 38 | int count = 0; 39 | hItem = _tv.GetChildItem(hItem); 40 | while (hItem) { 41 | auto hNext = _tv.GetNextSiblingItem(hItem); 42 | if (_tv.DeleteItem(hItem)) 43 | count++; 44 | hItem = hNext; 45 | } 46 | return count; 47 | } 48 | 49 | void TreeHelper::DoForEachItem(HTREEITEM hRoot, DWORD mask, std::function action) { 50 | CString text; 51 | auto hItem = _tv.GetChildItem(hRoot); 52 | while (hItem) { 53 | #ifdef _DEBUG 54 | _tv.GetItemText(hItem, text); 55 | ATLTRACE(L"DoForEachExpanded hItem: 0x%p (%s)\n", hItem, text); 56 | #endif 57 | auto state = _tv.GetItemState(hItem, mask); 58 | if (mask == 0 || state) { 59 | action(hItem, state); 60 | DoForEachItem(hItem, mask, action); 61 | } 62 | hItem = _tv.GetNextSiblingItem(hItem); 63 | } 64 | } 65 | 66 | std::map TreeHelper::GetChildItems(HTREEITEM hItem) { 67 | std::map items; 68 | hItem = _tv.GetChildItem(hItem); 69 | while (hItem) { 70 | CString text; 71 | _tv.GetItemText(hItem, text); 72 | items.insert({ text, hItem }); 73 | hItem = _tv.GetNextSiblingItem(hItem); 74 | } 75 | return items; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /RegExp/TreeHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TreeHelper { 4 | explicit TreeHelper(CTreeViewCtrlEx& tv) : _tv(tv) {} 5 | HTREEITEM FindChild(HTREEITEM item, PCWSTR name) const; 6 | HTREEITEM FindItem(HTREEITEM hParent, PCWSTR name); 7 | int DeleteChildren(HTREEITEM hItem); 8 | void DoForEachItem(HTREEITEM hRoot, DWORD state, std::function action); 9 | std::map GetChildItems(HTREEITEM hItem); 10 | 11 | private: 12 | CTreeViewCtrlEx& _tv; 13 | }; 14 | -------------------------------------------------------------------------------- /RegExp/cpp.hint: -------------------------------------------------------------------------------- 1 | // Hint files help the Visual Studio IDE interpret Visual C++ identifiers 2 | // such as names of functions and macros. 3 | // For more information see https://go.microsoft.com/fwlink/?linkid=865984 4 | #define BEGIN_SETTINGS(className) className() { InitSettings(); } void InitSettings() { 5 | -------------------------------------------------------------------------------- /RegExp/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 5 | // Windows Header Files 6 | #include 7 | // C RunTime Header Files 8 | #include 9 | #include 10 | #include 11 | #include 12 | -------------------------------------------------------------------------------- /RegExp/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | True/PM 22 | true 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /RegExp/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /RegExp/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #pragma once 8 | 9 | #include "targetver.h" 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | #define NOMINMAX 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | extern CAppModule _Module; 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #if defined _M_IX86 44 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 45 | #elif defined _M_IA64 46 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 47 | #elif defined _M_X64 48 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 49 | #else 50 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 51 | #endif 52 | -------------------------------------------------------------------------------- /RegExp/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // // Including SDKDDKVer.h defines the highest available Windows platform. 4 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 5 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 6 | #include 7 | -------------------------------------------------------------------------------- /TotalRegistry.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32408.312 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TotalReg", "RegExp\RegExp.vcxproj", "{C9050D58-5154-473A-B007-3D4FBB8692F9}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTLHelper", "WTLHelper\WTLHelper\WTLHelper.vcxproj", "{AE53419F-A769-4548-8E15-E311904DF7DF}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM = Debug|ARM 13 | Debug|ARM64 = Debug|ARM64 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|ARM = Release|ARM 17 | Release|ARM64 = Release|ARM64 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | ReleaseSigned|ARM = ReleaseSigned|ARM 21 | ReleaseSigned|ARM64 = ReleaseSigned|ARM64 22 | ReleaseSigned|x64 = ReleaseSigned|x64 23 | ReleaseSigned|x86 = ReleaseSigned|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Debug|ARM.ActiveCfg = Debug|x64 27 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Debug|ARM64.ActiveCfg = Debug|x64 28 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Debug|x64.ActiveCfg = Debug|x64 29 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Debug|x64.Build.0 = Debug|x64 30 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Debug|x86.ActiveCfg = Debug|x64 31 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|ARM.ActiveCfg = Release|x64 32 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|ARM64.ActiveCfg = Release|ARM64 33 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|ARM64.Build.0 = Release|ARM64 34 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|x64.ActiveCfg = Release|x64 35 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|x64.Build.0 = Release|x64 36 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.Release|x86.ActiveCfg = Release|x64 37 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|ARM.ActiveCfg = ReleaseSigned|x64 38 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|ARM.Build.0 = ReleaseSigned|x64 39 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 40 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 41 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 42 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 43 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|x64 44 | {C9050D58-5154-473A-B007-3D4FBB8692F9}.ReleaseSigned|x86.Build.0 = ReleaseSigned|x64 45 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM.ActiveCfg = Debug|x64 46 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM.Build.0 = Debug|x64 47 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 48 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.Build.0 = Debug|ARM64 49 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.ActiveCfg = Debug|x64 50 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.Build.0 = Debug|x64 51 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.ActiveCfg = Debug|Win32 52 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.Build.0 = Debug|Win32 53 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM.ActiveCfg = Release|x64 54 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM.Build.0 = Release|x64 55 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.ActiveCfg = Release|ARM64 56 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.Build.0 = Release|ARM64 57 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.ActiveCfg = Release|x64 58 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.Build.0 = Release|x64 59 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.ActiveCfg = Release|Win32 60 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.Build.0 = Release|Win32 61 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM.ActiveCfg = ReleaseSigned|x64 62 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM.Build.0 = ReleaseSigned|x64 63 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 64 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 65 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 66 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 67 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 68 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 69 | EndGlobalSection 70 | GlobalSection(SolutionProperties) = preSolution 71 | HideSolutionNode = FALSE 72 | EndGlobalSection 73 | GlobalSection(ExtensibilityGlobals) = postSolution 74 | SolutionGuid = {B3F029A3-AC8A-4AF7-AD13-473A37F40F72} 75 | EndGlobalSection 76 | EndGlobal 77 | -------------------------------------------------------------------------------- /regexp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/regexp1.png -------------------------------------------------------------------------------- /regexp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/regexp2.png -------------------------------------------------------------------------------- /regexp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/TotalRegistry/576be95c2aa33b4bbaeca1e9be39e940831cfca7/regexp3.png --------------------------------------------------------------------------------