├── .gitattributes ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── LICENSE ├── README.md ├── diagram.png ├── screenshot.png └── src ├── vscode-windhawk-ui ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode │ └── extensions.json ├── apps │ ├── .gitkeep │ ├── vscode-windhawk-ui-e2e │ │ ├── .eslintrc.json │ │ ├── cypress.config.ts │ │ ├── project.json │ │ ├── src │ │ │ ├── e2e │ │ │ │ └── app.cy.ts │ │ │ ├── fixtures │ │ │ │ └── example.json │ │ │ └── support │ │ │ │ ├── app.po.ts │ │ │ │ ├── commands.ts │ │ │ │ └── e2e.ts │ │ └── tsconfig.json │ └── vscode-windhawk-ui │ │ ├── .babelrc │ │ ├── .browserslistrc │ │ ├── .eslintrc.json │ │ ├── jest.config.ts │ │ ├── project.json │ │ ├── src │ │ ├── app │ │ │ ├── app.css │ │ │ ├── app.less │ │ │ ├── app.tsx │ │ │ ├── appUISettings.ts │ │ │ ├── components │ │ │ │ ├── InputWithContextMenu.tsx │ │ │ │ └── ReactMarkdownCustom.tsx │ │ │ ├── fonts │ │ │ │ └── Oxanium-Medium.ttf │ │ │ ├── i18n.ts │ │ │ ├── panel │ │ │ │ ├── About.tsx │ │ │ │ ├── AppHeader.tsx │ │ │ │ ├── CreateNewModButton.tsx │ │ │ │ ├── DevModeAction.tsx │ │ │ │ ├── ModCard.tsx │ │ │ │ ├── ModDetails.tsx │ │ │ │ ├── ModDetailsAdvanced.tsx │ │ │ │ ├── ModDetailsChangelog.tsx │ │ │ │ ├── ModDetailsHeader.tsx │ │ │ │ ├── ModDetailsReadme.tsx │ │ │ │ ├── ModDetailsSettings.tsx │ │ │ │ ├── ModDetailsSource.tsx │ │ │ │ ├── ModDetailsSourceDiff.tsx │ │ │ │ ├── ModPreview.tsx │ │ │ │ ├── ModsBrowserLocal.tsx │ │ │ │ ├── ModsBrowserOnline.tsx │ │ │ │ ├── Panel.tsx │ │ │ │ ├── SafeModeIndicator.tsx │ │ │ │ ├── Settings.tsx │ │ │ │ ├── assets │ │ │ │ │ ├── local-mod-icon.svg │ │ │ │ │ ├── logo-black.svg │ │ │ │ │ └── logo-white.svg │ │ │ │ └── mockData.ts │ │ │ ├── sidebar │ │ │ │ ├── EditorModeControls.tsx │ │ │ │ ├── Sidebar.tsx │ │ │ │ └── mockData.ts │ │ │ ├── swrHelpers.ts │ │ │ ├── vsCodeApi.ts │ │ │ ├── webviewIPC.ts │ │ │ └── webviewIPCMessages.ts │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── locales │ │ │ ├── DO_NOT_EDIT.txt │ │ │ ├── cs │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── da │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── de │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── el │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── en │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── es │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── fr │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── hr │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── hu │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── id │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── it │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── ja │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── ko │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── nl │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── pl │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── pt-BR │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── ro │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── ru │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── sv-SE │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── ta │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── tr │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── uk │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── vi │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ ├── zh-CN │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ │ └── zh-TW │ │ │ │ ├── DO_NOT_EDIT.txt │ │ │ │ └── translation.json │ │ ├── main.css │ │ ├── main.tsx │ │ └── polyfills.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.spec.json │ │ └── webpack.config.js ├── babel.config.json ├── jest.config.ts ├── jest.preset.js ├── libs │ └── .gitkeep ├── nx.json ├── package-lock.json ├── package.json ├── tools │ ├── generators │ │ └── .gitkeep │ └── tsconfig.tools.json └── tsconfig.base.json ├── vscode-windhawk ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── .vscode │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .vscodeignore ├── LICENSE ├── README.md ├── assets │ ├── main-icon.png │ ├── main-icon.svg │ ├── tab-icon-black.svg │ └── tab-icon-white.svg ├── files │ ├── DbgViewMini.exe │ └── mod_template.wh.cpp ├── helper_scripts │ └── disable_default_keybindings.py ├── package-lock.json ├── package.json ├── package.nls.json ├── src │ ├── config.ts │ ├── extension.ts │ ├── ini.ts │ ├── logOutputChannel.ts │ ├── storagePaths.ts │ ├── utils │ │ ├── appSettingsUtils.ts │ │ ├── compilerUtils.ts │ │ ├── editorWorkspaceUtils.ts │ │ ├── modConfigUtils.ts │ │ ├── modSourceUtils.ts │ │ ├── trayProgramUtils.ts │ │ └── userProfileUtils.ts │ └── webviewIPCMessages.ts ├── syntaxes │ └── cpp.injection.json ├── tsconfig.json └── webpack.config.js └── windhawk ├── .clang-format ├── .gitattributes ├── .gitignore ├── app ├── app.cpp ├── app.vcxproj ├── app.vcxproj.filters ├── engine_control.cpp ├── engine_control.h ├── event_viewer_crash_monitor.cpp ├── event_viewer_crash_monitor.h ├── functions.cpp ├── functions.h ├── libraries │ ├── nlohmann │ │ └── json.hpp │ └── winhttpwrappers │ │ └── WinHTTPWrappers.h ├── logger.cpp ├── logger.h ├── main_window.cpp ├── main_window.h ├── resource.h ├── rsrc.rc ├── rsrc.rc2 ├── rsrc │ ├── app.ico │ ├── app_notification.ico │ └── compatibility.manifest ├── service.cpp ├── service.h ├── service_common.h ├── stdafx.cpp ├── stdafx.h ├── storage_manager.cpp ├── storage_manager.h ├── task_manager_dlg.cpp ├── task_manager_dlg.h ├── toolkit_dlg.cpp ├── toolkit_dlg.h ├── tray_icon.cpp ├── tray_icon.h ├── ui_control.cpp ├── ui_control.h ├── update_checker.cpp ├── update_checker.h ├── userprofile.cpp ├── userprofile.h └── winhttpsimple.h ├── build.bat ├── engine ├── _exports.def ├── all_processes_injector.cpp ├── all_processes_injector.h ├── customization_session.cpp ├── customization_session.h ├── dll_inject.cpp ├── dll_inject.h ├── engine.vcxproj ├── engine.vcxproj.filters ├── functions.cpp ├── functions.h ├── inject_shellcode │ ├── .clang-format │ ├── InjectShellcode.filters │ ├── InjectShellcode.sln │ ├── InjectShellcode.vcxproj │ └── main.cpp ├── libraries │ ├── MinHook-Detours │ │ ├── MinHook.c │ │ ├── MinHook.h │ │ └── SlimDetours │ │ │ ├── .editorconfig │ │ │ ├── Disassembler.c │ │ │ ├── FuncTableHook.c │ │ │ ├── InlineHook.c │ │ │ ├── Instruction.c │ │ │ ├── LICENSE │ │ │ ├── Memory.c │ │ │ ├── SlimDetours.NDK.inl │ │ │ ├── SlimDetours.h │ │ │ ├── SlimDetours.inl │ │ │ ├── Thread.c │ │ │ ├── Trampoline.c │ │ │ ├── Transaction.c │ │ │ └── Utils.inl │ ├── MinHook │ │ ├── include │ │ │ └── MinHook.h │ │ └── src │ │ │ ├── buffer.c │ │ │ ├── buffer.h │ │ │ ├── hde │ │ │ ├── hde32.c │ │ │ ├── hde32.h │ │ │ ├── hde64.c │ │ │ ├── hde64.h │ │ │ ├── pstdint.h │ │ │ ├── table32.h │ │ │ └── table64.h │ │ │ ├── hook.c │ │ │ ├── trampoline.c │ │ │ └── trampoline.h │ ├── ThreadLocal.h │ ├── Zydis │ │ ├── Zydis.c │ │ └── Zydis.h │ ├── binaryninja-arm64-disassembler │ │ ├── arm64dis.h │ │ ├── decode.c │ │ ├── decode.h │ │ ├── decode0.c │ │ ├── decode1.c │ │ ├── decode1.h │ │ ├── decode2.c │ │ ├── decode2.h │ │ ├── decode_fields32.c │ │ ├── decode_fields32.h │ │ ├── decode_scratchpad.c │ │ ├── decompose_and_disassemble.c │ │ ├── decompose_and_disassemble.h │ │ ├── encodings_dec.c │ │ ├── encodings_dec.h │ │ ├── encodings_fmt.c │ │ ├── encodings_fmt.h │ │ ├── feature_flags.h │ │ ├── format.c │ │ ├── format.h │ │ ├── gofer.c │ │ ├── operations.c │ │ ├── operations.h │ │ ├── pcode.c │ │ ├── pcode.h │ │ ├── regs.c │ │ ├── regs.h │ │ ├── sysregs.c │ │ ├── sysregs.h │ │ ├── sysregs_fmt_gen.c │ │ ├── sysregs_fmt_gen.h │ │ ├── sysregs_gen.c │ │ └── sysregs_gen.h │ ├── dia │ │ ├── cvconst.h │ │ ├── dia2.h │ │ ├── diacreate.h │ │ └── lib │ │ │ ├── amd64 │ │ │ └── diaguids.lib │ │ │ ├── arm │ │ │ └── diaguids.lib │ │ │ ├── arm64 │ │ │ └── diaguids.lib │ │ │ └── diaguids.lib │ ├── phnt │ │ ├── CMakeLists.txt │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ntafd.h │ │ ├── ntbcd.h │ │ ├── ntdbg.h │ │ ├── ntexapi.h │ │ ├── ntgdi.h │ │ ├── ntimage.h │ │ ├── ntintsafe.h │ │ ├── ntioapi.h │ │ ├── ntkeapi.h │ │ ├── ntldr.h │ │ ├── ntlpcapi.h │ │ ├── ntmisc.h │ │ ├── ntmmapi.h │ │ ├── ntnls.h │ │ ├── ntobapi.h │ │ ├── ntpebteb.h │ │ ├── ntpfapi.h │ │ ├── ntpnpapi.h │ │ ├── ntpoapi.h │ │ ├── ntpsapi.h │ │ ├── ntregapi.h │ │ ├── ntrtl.h │ │ ├── ntsam.h │ │ ├── ntseapi.h │ │ ├── ntsmss.h │ │ ├── ntstrsafe.h │ │ ├── ntsxs.h │ │ ├── nttmapi.h │ │ ├── nttp.h │ │ ├── ntuser.h │ │ ├── ntwmi.h │ │ ├── ntwow64.h │ │ ├── ntxcapi.h │ │ ├── ntzwapi.h │ │ ├── phnt.h │ │ ├── phnt_ntdef.h │ │ ├── phnt_windows.h │ │ ├── smbios.h │ │ ├── subprocesstag.h │ │ ├── usermgr.h │ │ └── winsta.h │ ├── thread-call-stack-scanner │ │ ├── Memory.c │ │ ├── Memory.h │ │ ├── Thread.c │ │ ├── Thread.h │ │ ├── ThreadsCallStackIterate.c │ │ ├── ThreadsCallStackIterate.h │ │ ├── ThreadsCallStackWaitForRegions.c │ │ └── ThreadsCallStackWaitForRegions.h │ └── wow64pp │ │ └── wow64pp.hpp ├── logger.cpp ├── logger.h ├── main.cpp ├── mod.cpp ├── mod.h ├── mods_api.cpp ├── mods_api.h ├── mods_api_internal.h ├── mods_manager.cpp ├── mods_manager.h ├── new_process_injector.cpp ├── new_process_injector.h ├── no_destructor.cpp ├── no_destructor.h ├── process_lists.h ├── resource.h ├── rsrc.rc ├── rsrc.rc2 ├── session_private_namespace.cpp ├── session_private_namespace.h ├── stdafx.cpp ├── stdafx.h ├── storage_manager.cpp ├── storage_manager.h ├── symbol_enum.cpp ├── symbol_enum.h └── var_init_once.h ├── shared ├── libraries │ └── wil │ │ ├── Tracelogging.h │ │ ├── _version.txt │ │ ├── com.h │ │ ├── com_apartment_variable.h │ │ ├── common.h │ │ ├── coroutine.h │ │ ├── cppwinrt.h │ │ ├── cppwinrt_authoring.h │ │ ├── cppwinrt_helpers.h │ │ ├── cppwinrt_notifiable_module_lock.h │ │ ├── cppwinrt_register_com_server.h │ │ ├── cppwinrt_wrl.h │ │ ├── filesystem.h │ │ ├── nt_result_macros.h │ │ ├── registry.h │ │ ├── registry_helpers.h │ │ ├── resource.h │ │ ├── result.h │ │ ├── result_macros.h │ │ ├── result_originate.h │ │ ├── rpc_helpers.h │ │ ├── safecast.h │ │ ├── stl.h │ │ ├── token_helpers.h │ │ ├── traceloggingconfig.h │ │ ├── win32_helpers.h │ │ ├── win32_result_macros.h │ │ ├── windowing.h │ │ ├── winrt.h │ │ ├── wistd_config.h │ │ ├── wistd_functional.h │ │ ├── wistd_memory.h │ │ ├── wistd_type_traits.h │ │ └── wrl.h ├── logger_base.cpp ├── logger_base.h ├── portable_settings.cpp ├── portable_settings.h └── version.h └── windhawk.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | # Apply override to all files and directories in the directory 2 | # https://github.com/github-linguist/linguist/blob/master/docs/overrides.md#vendored-code 3 | /src/windhawk/*/libraries/** linguist-vendored 4 | /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/app.css linguist-vendored 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://ramensoftware.com/donate'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug in Windhawk 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for Windhawk 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windhawk 2 | 3 | ![Screenshot](screenshot.png) 4 | 5 | Windhawk aims to make it easier to customize Windows programs. For more details, see [the official website](https://windhawk.net/) and [the announcement](https://ramensoftware.com/windhawk). 6 | 7 | This repository is used to [report issues](https://github.com/ramensoftware/windhawk/issues) and to [discuss Windhawk](https://github.com/ramensoftware/windhawk/discussions). For discussing Windhawk mods, refer to [the windhawk-mods repository](https://github.com/ramensoftware/windhawk-mods). 8 | 9 | You're also welcome to join [the Windhawk Discord channel](https://discord.com/servers/windhawk-923944342991818753) for a live discussion. 10 | 11 | ## Technical details 12 | 13 | High level architecture: 14 | 15 | ![High level architecture diagram](diagram.png) 16 | 17 | For technical details about the global injection and hooking method that is used, refer to the following blog post: [Implementing Global Injection and Hooking in Windows](https://m417z.com/Implementing-Global-Injection-and-Hooking-in-Windows/). 18 | 19 | ## Source code 20 | 21 | The Windhawk source code can be found in the `src` folder, which contains the following subfolders: 22 | 23 | * `windhawk`: The code of the main `windhawk.exe` executable and the 32-bit and 64-bit `windhawk.dll` engine libraries. 24 | 25 | * `vscode-windhawk`: The code of the VSCode extension that is responsible for UI operations such as installing mods and listing installed mods. 26 | 27 | * `vscode-windhawk-ui`: The UI part of the VSCode extension. 28 | 29 | A simple way to get started is by extracting the portable version of Windhawk with the official installer, building the part of Windhawk that you want to modify, and then replacing the corresponding files in the portable version with the newly built files. 30 | 31 | ## Additional resources 32 | 33 | Code which demonstrates the global injection and hooking method that is used can be found in this repository: [global-inject-demo](https://github.com/m417z/global-inject-demo). 34 | -------------------------------------------------------------------------------- /diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/diagram.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/screenshot.png -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nrwl/nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nrwl/nx/javascript"], 32 | "rules": {} 33 | }, 34 | { 35 | "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"], 36 | "env": { 37 | "jest": true 38 | }, 39 | "rules": {} 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .nx/cache 42 | .nx/workspace-data 43 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk-ui/apps/.gitkeep -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress'; 2 | import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset'; 3 | 4 | export default defineConfig({ 5 | e2e: nxE2EPreset(__dirname), 6 | }); 7 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-windhawk-ui-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/vscode-windhawk-ui-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nrwl/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/vscode-windhawk-ui-e2e/cypress.config.ts", 11 | "devServerTarget": "vscode-windhawk-ui:serve:development", 12 | "testingType": "e2e" 13 | }, 14 | "configurations": { 15 | "production": { 16 | "devServerTarget": "vscode-windhawk-ui:serve:production" 17 | } 18 | } 19 | }, 20 | "lint": { 21 | "executor": "@nrwl/linter:eslint", 22 | "outputs": ["{options.outputFile}"], 23 | "options": { 24 | "lintFilePatterns": ["apps/vscode-windhawk-ui-e2e/**/*.{js,ts}"] 25 | } 26 | } 27 | }, 28 | "tags": [], 29 | "implicitDependencies": ["vscode-windhawk-ui"] 30 | } 31 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/src/e2e/app.cy.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('vscode-windhawk-ui', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome vscode-windhawk-ui'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/src/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"] 8 | }, 9 | "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nrwl/react/babel", 5 | { 6 | "runtime": "automatic" 7 | } 8 | ] 9 | ], 10 | "plugins": [["styled-components", { "pure": true, "ssr": true }]] 11 | } 12 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by: 2 | # 1. autoprefixer to adjust CSS to support the below specified browsers 3 | # 2. babel preset-env to adjust included polyfills 4 | # 5 | # For additional information regarding the format and rule options, please see: 6 | # https://github.com/browserslist/browserslist#queries 7 | # 8 | # If you need to support different browsers in production, you may tweak the list below. 9 | 10 | last 1 Chrome version 11 | last 1 Firefox version 12 | last 2 Edge major versions 13 | last 2 Safari major version 14 | last 2 iOS major versions 15 | Firefox ESR 16 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'vscode-windhawk-ui', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest', 7 | '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nrwl/react/babel'] }], 8 | }, 9 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 10 | coverageDirectory: '../../coverage/apps/vscode-windhawk-ui', 11 | }; 12 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-windhawk-ui", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/vscode-windhawk-ui/src", 5 | "projectType": "application", 6 | "targets": { 7 | "build": { 8 | "executor": "@nrwl/webpack:webpack", 9 | "outputs": ["{options.outputPath}"], 10 | "defaultConfiguration": "production", 11 | "options": { 12 | "compiler": "babel", 13 | "outputPath": "dist/apps/vscode-windhawk-ui", 14 | "index": "apps/vscode-windhawk-ui/src/index.html", 15 | "main": "apps/vscode-windhawk-ui/src/main.tsx", 16 | "polyfills": "apps/vscode-windhawk-ui/src/polyfills.ts", 17 | "tsConfig": "apps/vscode-windhawk-ui/tsconfig.app.json", 18 | "assets": [ 19 | "apps/vscode-windhawk-ui/src/favicon.ico", 20 | "apps/vscode-windhawk-ui/src/locales" 21 | ], 22 | "styles": [], 23 | "scripts": [], 24 | "webpackConfig": "apps/vscode-windhawk-ui/webpack.config.js" 25 | }, 26 | "configurations": { 27 | "development": { 28 | "extractLicenses": false, 29 | "optimization": false, 30 | "sourceMap": true, 31 | "vendorChunk": true 32 | }, 33 | "production": { 34 | "fileReplacements": [ 35 | { 36 | "replace": "apps/vscode-windhawk-ui/src/environments/environment.ts", 37 | "with": "apps/vscode-windhawk-ui/src/environments/environment.prod.ts" 38 | } 39 | ], 40 | "optimization": true, 41 | "outputHashing": "all", 42 | "sourceMap": false, 43 | "namedChunks": false, 44 | "extractLicenses": true, 45 | "vendorChunk": false 46 | } 47 | } 48 | }, 49 | "serve": { 50 | "executor": "@nrwl/webpack:dev-server", 51 | "defaultConfiguration": "development", 52 | "options": { 53 | "buildTarget": "vscode-windhawk-ui:build", 54 | "hmr": true 55 | }, 56 | "configurations": { 57 | "development": { 58 | "buildTarget": "vscode-windhawk-ui:build:development" 59 | }, 60 | "production": { 61 | "buildTarget": "vscode-windhawk-ui:build:production", 62 | "hmr": false 63 | } 64 | } 65 | }, 66 | "lint": { 67 | "executor": "@nrwl/linter:eslint", 68 | "outputs": ["{options.outputFile}"], 69 | "options": { 70 | "lintFilePatterns": ["apps/vscode-windhawk-ui/**/*.{ts,tsx,js,jsx}"] 71 | } 72 | }, 73 | "test": { 74 | "executor": "@nrwl/jest:jest", 75 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 76 | "options": { 77 | "jestConfig": "apps/vscode-windhawk-ui/jest.config.ts", 78 | "passWithNoTests": true 79 | } 80 | } 81 | }, 82 | "tags": [] 83 | } 84 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/app.less: -------------------------------------------------------------------------------- 1 | @import 'antd/dist/antd.dark.less'; 2 | 3 | @font-face { 4 | font-family: 'Oxanium'; 5 | src: local('Oxanium'), url(./fonts/Oxanium-Medium.ttf) format('truetype'); 6 | } 7 | 8 | :root { 9 | --app-max-width: 1200px; 10 | --app-background-color: var(--vscode-editor-background, #1e1e1e); 11 | 12 | // https://github.com/otakustay/react-diff-view/blob/f9e5f9f248f331598e5c9e7839fccb211efe43c2/site/components/DiffView/diff.global.less 13 | --diff-background-color: #1e1e1e; 14 | --diff-text-color: #fafafa; 15 | --diff-selection-background-color: #5a5f80; 16 | --diff-gutter-insert-background-color: #082525; 17 | --diff-gutter-delete-background-color: #2b1523; 18 | --diff-gutter-selected-background-color: #5a5f80; 19 | --diff-code-insert-background-color: #082525; 20 | --diff-code-delete-background-color: #2b1523; 21 | --diff-code-insert-edit-background-color: #00462f; 22 | --diff-code-delete-edit-background-color: #4e2436; 23 | --diff-code-selected-background-color: #5a5f80; 24 | --diff-omit-background-color: #101120; 25 | --diff-decoration-gutter-background-color: #222; 26 | --diff-decoration-gutter-color: #ababab; 27 | --diff-decoration-content-background-color: #222; 28 | --diff-decoration-content-color: #ababab; 29 | } 30 | 31 | body[data-content="sidebar"] { 32 | --app-background-color: var(--vscode-sideBar-background); 33 | } 34 | 35 | @body-background: var(--app-background-color); 36 | 37 | body.windhawk-no-pointer-events { 38 | pointer-events: none; 39 | 40 | .ant-modal-content { 41 | pointer-events: none; 42 | } 43 | 44 | .ant-select.ant-select-open, 45 | .windhawk-popup-content, 46 | .windhawk-popup-content-no-select { 47 | pointer-events: auto; 48 | } 49 | } 50 | 51 | .windhawk-popup-content-no-select { 52 | user-select: none; 53 | } 54 | 55 | // An ugly patch providing dark theme for select elements. 56 | .@{select-prefix-cls} { 57 | &-item { 58 | &-option { 59 | &-active:not(&-disabled) { 60 | color: @text-color-inverse; 61 | background-color: @menu-dark-bg; 62 | } 63 | 64 | &-selected:not(&-disabled) { 65 | color: @text-color-inverse; 66 | background-color: @primary-color; 67 | } 68 | } 69 | } 70 | } 71 | 72 | .rc-virtual-list-scrollbar-thumb { 73 | border-radius: 0 !important; 74 | background: rgba(121, 121, 121, 0.4) !important; 75 | } 76 | 77 | // An ugly patch providing dark theme for dropdown menu elements. 78 | .@{dropdown-prefix-cls} { 79 | &-menu { 80 | &-item { 81 | &-active:not(&-disabled) { 82 | color: @text-color-inverse; 83 | background-color: @menu-dark-bg; 84 | } 85 | 86 | &-selected:not(&-disabled) { 87 | color: @text-color-inverse; 88 | background-color: @primary-color; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import 'prism-themes/themes/prism-vsc-dark-plus.css'; 2 | import { useCallback, useEffect, useMemo, useState } from 'react'; 3 | import 'react-diff-view/style/index.css'; 4 | import { useTranslation } from 'react-i18next'; 5 | import './App.css'; 6 | import { 7 | AppUISettingsContextType, 8 | AppUISettingsContext, 9 | } from './appUISettings'; 10 | import { setLanguage } from './i18n'; 11 | import { useMockData } from './panel/mockData'; 12 | import Panel from './panel/Panel'; 13 | import Sidebar from './sidebar/Sidebar'; 14 | import { useGetInitialAppSettings, useSetNewAppSettings } from './webviewIPC'; 15 | 16 | function WhenTranslationIsReady( 17 | props: React.PropsWithChildren> 18 | ) { 19 | const { ready } = useTranslation(); 20 | // https://stackoverflow.com/a/63898849 21 | // eslint-disable-next-line react/jsx-no-useless-fragment 22 | return ready ? <>{props.children} : null; 23 | } 24 | 25 | function App() { 26 | const content = useMemo( 27 | () => 28 | document.querySelector('body')?.getAttribute('data-content') ?? 29 | (document.location.hash === '#/debug_sidebar' ? 'sidebar' : 'panel'), 30 | [] 31 | ); 32 | 33 | const [appUISettings, setAppUISettings] = 34 | useState(null); 35 | 36 | const { getInitialAppSettings } = useGetInitialAppSettings( 37 | useCallback((data) => { 38 | setLanguage(data.appUISettings?.language); 39 | setAppUISettings(data.appUISettings || {}); 40 | }, []) 41 | ); 42 | 43 | useEffect(() => { 44 | if (!useMockData) { 45 | getInitialAppSettings({}); 46 | } else { 47 | setLanguage(); 48 | setAppUISettings({}); 49 | } 50 | }, [getInitialAppSettings]); 51 | 52 | useSetNewAppSettings( 53 | useCallback((data) => { 54 | setLanguage(data.appUISettings?.language); 55 | setAppUISettings(data.appUISettings || {}); 56 | }, []) 57 | ); 58 | 59 | if (!content || !appUISettings) { 60 | return null; 61 | } 62 | 63 | return ( 64 | 65 | 66 | {content === 'panel' ? ( 67 | 68 | ) : content === 'sidebar' ? ( 69 | 70 | ) : ( 71 | '' 72 | )} 73 | 74 | 75 | ); 76 | } 77 | 78 | export default App; 79 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/appUISettings.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AppUISettings } from './webviewIPCMessages'; 3 | 4 | export type AppUISettingsContextType = Partial; 5 | 6 | export const AppUISettingsContext = 7 | React.createContext({}); 8 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/components/ReactMarkdownCustom.tsx: -------------------------------------------------------------------------------- 1 | import ReactMarkdown from 'react-markdown'; 2 | import rehypeSlug from 'rehype-slug'; 3 | import remarkGfm from 'remark-gfm'; 4 | import styled from 'styled-components'; 5 | 6 | const ReactMarkdownStyleWrapper = styled.div` 7 | // Word-wrap long lines. 8 | overflow-wrap: break-word; 9 | 10 | // Table style. 11 | // https://github.com/micromark/micromark-extension-gfm-table#css 12 | 13 | table { 14 | border-spacing: 0; 15 | border-collapse: collapse; 16 | display: block; 17 | margin-top: 0; 18 | margin-bottom: 16px; 19 | width: max-content; 20 | max-width: 100%; 21 | overflow: auto; 22 | } 23 | 24 | td, 25 | th { 26 | padding: 6px 13px; 27 | border: 1px solid #434343; 28 | } 29 | `; 30 | 31 | interface Props { 32 | markdown: string; 33 | } 34 | 35 | function ReactMarkdownCustom({ markdown }: Props) { 36 | return ( 37 | 38 | 45 | 46 | ); 47 | } 48 | 49 | export default ReactMarkdownCustom; 50 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/fonts/Oxanium-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/fonts/Oxanium-Medium.ttf -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/i18n.ts: -------------------------------------------------------------------------------- 1 | import i18n from 'i18next'; 2 | import Backend from 'i18next-http-backend'; 3 | import { initReactI18next } from 'react-i18next'; 4 | 5 | let initialized = false; 6 | const defaultLanguage = 'en'; 7 | 8 | function i18nInitialize(language: string) { 9 | i18n 10 | // load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales) 11 | // learn more: https://github.com/i18next/i18next-http-backend 12 | .use(Backend) 13 | // pass the i18n instance to react-i18next. 14 | .use(initReactI18next) 15 | // init i18next 16 | // for all options read: https://www.i18next.com/overview/configuration-options 17 | .init({ 18 | lng: language, 19 | fallbackLng: defaultLanguage, 20 | //debug: true, 21 | 22 | returnNull: false, 23 | returnEmptyString: false, 24 | 25 | interpolation: { 26 | escapeValue: false, // not needed for react as it escapes by default 27 | }, 28 | 29 | react: { 30 | useSuspense: false, 31 | }, 32 | 33 | backend: { 34 | // Use a relative load path. 35 | loadPath: './locales/{{lng}}/{{ns}}.json', 36 | }, 37 | }); 38 | } 39 | 40 | export function setLanguage(language?: string) { 41 | if (initialized) { 42 | i18n.changeLanguage(language || defaultLanguage); 43 | return; 44 | } 45 | 46 | i18nInitialize(language || defaultLanguage); 47 | initialized = true; 48 | } 49 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/AppHeader.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | faCog, 3 | faHome, 4 | faInfo, 5 | faList, 6 | } from '@fortawesome/free-solid-svg-icons'; 7 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 8 | import { Badge, Button } from 'antd'; 9 | import { useCallback, useContext } from 'react'; 10 | import { useTranslation } from 'react-i18next'; 11 | import { useLocation, useNavigate } from 'react-router-dom'; 12 | import styled from 'styled-components'; 13 | import { AppUISettingsContext } from '../appUISettings'; 14 | import logo from './assets/logo-white.svg'; 15 | 16 | const Header = styled.header` 17 | display: flex; 18 | align-items: center; 19 | flex-wrap: wrap; 20 | padding: 20px 20px 0; 21 | column-gap: 20px; 22 | margin: 0 auto; 23 | width: 100%; 24 | max-width: var(--app-max-width); 25 | `; 26 | 27 | const HeaderLogo = styled.div` 28 | cursor: pointer; 29 | margin-right: auto; 30 | font-size: 40px; 31 | white-space: nowrap; 32 | font-family: Oxanium; 33 | user-select: none; 34 | `; 35 | 36 | const LogoImage = styled.img` 37 | height: 80px; 38 | margin-right: 6px; 39 | `; 40 | 41 | const HeaderButtonsWrapper = styled.div` 42 | display: flex; 43 | flex-wrap: wrap; 44 | gap: 10px; 45 | margin: 12px 0; 46 | `; 47 | 48 | const HeaderIcon = styled(FontAwesomeIcon)` 49 | margin-right: 8px; 50 | `; 51 | 52 | function AppHeader() { 53 | const { t } = useTranslation(); 54 | 55 | const navigate = useNavigate(); 56 | const replace = useCallback( 57 | (to: string) => navigate(to, { replace: true }), 58 | [navigate] 59 | ); 60 | 61 | const location = useLocation(); 62 | 63 | const { updateIsAvailable } = useContext(AppUISettingsContext); 64 | 65 | const buttons = [ 66 | { 67 | text: t('appHeader.home'), 68 | route: '/', 69 | icon: faHome, 70 | }, 71 | { 72 | text: t('appHeader.explore'), 73 | route: '/mods-browser', 74 | icon: faList, 75 | }, 76 | { 77 | text: t('appHeader.settings'), 78 | route: '/settings', 79 | icon: faCog, 80 | }, 81 | { 82 | text: t('appHeader.about'), 83 | route: '/about', 84 | icon: faInfo, 85 | hasBadge: updateIsAvailable, 86 | }, 87 | ]; 88 | 89 | return ( 90 |
91 | replace('/')}> 92 | Windhawk 93 | 94 | 95 | {buttons.map(({ text, route, icon, hasBadge }) => ( 96 | 97 | 105 | 106 | ))} 107 | 108 |
109 | ); 110 | } 111 | 112 | export default AppHeader; 113 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/CreateNewModButton.tsx: -------------------------------------------------------------------------------- 1 | import { faPen } from '@fortawesome/free-solid-svg-icons'; 2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 3 | import { Button } from 'antd'; 4 | import { useTranslation } from 'react-i18next'; 5 | import styled from 'styled-components'; 6 | import { createNewMod } from '../webviewIPC'; 7 | import DevModeAction from './DevModeAction'; 8 | 9 | const ButtonContainer = styled.div` 10 | position: fixed; 11 | bottom: 0; 12 | left: 0; 13 | right: 0; 14 | margin: 0 auto; 15 | width: 100%; 16 | max-width: var(--app-max-width); 17 | `; 18 | 19 | const CreateButton = styled(Button)` 20 | position: absolute; 21 | right: 32px; 22 | bottom: 20px; 23 | background-color: var(--app-background-color) !important; 24 | box-shadow: 0 3px 6px rgb(100 100 100 / 16%), 0 1px 2px rgb(100 100 100 / 23%); 25 | `; 26 | 27 | const CreateButtonIcon = styled(FontAwesomeIcon)` 28 | margin-right: 8px; 29 | `; 30 | 31 | function CreateNewModButton() { 32 | const { t } = useTranslation(); 33 | 34 | return ( 35 | 36 | createNewMod()} 39 | renderButton={(onClick) => ( 40 | 41 | {t('createNewModButton.title')} 42 | 43 | )} 44 | /> 45 | 46 | ); 47 | } 48 | 49 | export default CreateNewModButton; 50 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/DevModeAction.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox } from 'antd'; 2 | import { TooltipPlacement } from 'antd/lib/tooltip'; 3 | import React, { JSX, useContext, useState } from 'react'; 4 | import { useTranslation } from 'react-i18next'; 5 | import styled from 'styled-components'; 6 | import { AppUISettingsContext } from '../appUISettings'; 7 | import { PopconfirmModal } from '../components/InputWithContextMenu'; 8 | import { useUpdateAppSettings } from '../webviewIPC'; 9 | 10 | const PopconfirmTitleContent = styled.div` 11 | display: flex; 12 | flex-direction: column; 13 | row-gap: 8px; 14 | max-width: 300px; 15 | `; 16 | 17 | interface Props { 18 | disabled?: boolean; 19 | popconfirmPlacement?: TooltipPlacement; 20 | onClick: () => void; 21 | renderButton: (onClick?: () => void) => JSX.Element; 22 | } 23 | 24 | function DevModeAction(props: React.PropsWithChildren) { 25 | const { t } = useTranslation(); 26 | 27 | const { devModeOptOut, devModeUsedAtLeastOnce } = 28 | useContext(AppUISettingsContext); 29 | 30 | const [optOutChecked, setOptOutChecked] = useState(false); 31 | 32 | const { updateAppSettings } = useUpdateAppSettings(() => undefined); 33 | 34 | if (devModeOptOut) { 35 | return null; 36 | } 37 | 38 | return ( 39 | 44 |
{t('devModeAction.message')}
45 | setOptOutChecked(e.target.checked)} 48 | > 49 | {t('devModeAction.hideOptionsCheckbox')} 50 | 51 | 52 | } 53 | okText={ 54 | optOutChecked 55 | ? t('devModeAction.hideOptionsButton') 56 | : t('devModeAction.beginCodingButton') 57 | } 58 | cancelText={t('devModeAction.cancelButton')} 59 | onConfirm={() => { 60 | if (optOutChecked) { 61 | updateAppSettings({ 62 | appSettings: { 63 | devModeOptOut: true, 64 | }, 65 | }); 66 | } else { 67 | updateAppSettings({ 68 | appSettings: { 69 | devModeUsedAtLeastOnce: true, 70 | }, 71 | }); 72 | props.onClick(); 73 | } 74 | }} 75 | onOpenChange={(open) => open && setOptOutChecked(false)} 76 | > 77 | {props.renderButton( 78 | !devModeUsedAtLeastOnce ? undefined : () => props.onClick() 79 | )} 80 |
81 | ); 82 | } 83 | 84 | export default DevModeAction; 85 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/ModDetailsChangelog.tsx: -------------------------------------------------------------------------------- 1 | import { Trans, useTranslation } from 'react-i18next'; 2 | import styled from 'styled-components'; 3 | import useSWR from 'swr'; 4 | import ReactMarkdownCustom from '../components/ReactMarkdownCustom'; 5 | import { fetchText } from '../swrHelpers'; 6 | 7 | const ErrorMessage = styled.div` 8 | color: rgba(255, 255, 255, 0.45); 9 | font-style: italic; 10 | `; 11 | 12 | interface Props { 13 | modId: string; 14 | loadingNode: React.ReactElement; 15 | } 16 | 17 | function ModDetailsChangelog({ modId, loadingNode }: Props) { 18 | const { t } = useTranslation(); 19 | 20 | const url = `https://mods.windhawk.net/changelogs/${modId}.md`; 21 | 22 | const { data, error, isLoading } = useSWR(url, fetchText); 23 | 24 | if (error) { 25 | const githubUrl = `https://github.com/ramensoftware/windhawk-mods/blob/pages/changelogs/${modId}.md`; 26 | return ( 27 | 28 | GitHub]} 32 | /> 33 | 34 | ); 35 | } 36 | 37 | if (isLoading) { 38 | return loadingNode; 39 | } 40 | 41 | return ; 42 | } 43 | 44 | export default ModDetailsChangelog; 45 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/ModDetailsReadme.tsx: -------------------------------------------------------------------------------- 1 | import ReactMarkdownCustom from '../components/ReactMarkdownCustom'; 2 | 3 | interface Props { 4 | markdown: string; 5 | } 6 | 7 | function ModDetailsReadme({ markdown }: Props) { 8 | return ; 9 | } 10 | 11 | export default ModDetailsReadme; 12 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/ModPreview.tsx: -------------------------------------------------------------------------------- 1 | import { Empty, message } from 'antd'; 2 | import { useCallback, useEffect, useLayoutEffect, useState } from 'react'; 3 | import { useTranslation } from 'react-i18next'; 4 | import { useParams } from 'react-router-dom'; 5 | import styled from 'styled-components'; 6 | import { useGetInstalledMods } from '../webviewIPC'; 7 | import { ModConfig, ModMetadata } from '../webviewIPCMessages'; 8 | import { mockModsBrowserLocalInitialMods } from './mockData'; 9 | import ModDetails from './ModDetails'; 10 | 11 | const CenteredContainer = styled.div` 12 | display: flex; 13 | flex-direction: column; 14 | height: 100%; 15 | `; 16 | 17 | const CenteredContent = styled.div` 18 | margin: auto; 19 | 20 | // Without this the centered content looks too low. 21 | padding-bottom: 10vh; 22 | `; 23 | 24 | type ModDetailsType = { 25 | metadata: ModMetadata | null; 26 | config: ModConfig | null; 27 | updateAvailable?: boolean; 28 | userRating?: number; 29 | }; 30 | 31 | interface Props { 32 | ContentWrapper: React.ComponentType< 33 | React.ComponentPropsWithoutRef<'div'> & { $hidden?: boolean } 34 | >; 35 | } 36 | 37 | function ModPreview({ ContentWrapper }: Props) { 38 | const { t } = useTranslation(); 39 | 40 | useLayoutEffect(() => { 41 | const header = document.querySelector('header'); 42 | if (header) { 43 | header.style.display = 'none'; 44 | } 45 | }, []); 46 | 47 | const { modId: displayedModId } = useParams<{ 48 | modId: string; 49 | }>(); 50 | 51 | const [installedMods, setInstalledMods] = useState | null>(mockModsBrowserLocalInitialMods); 55 | 56 | const { getInstalledMods } = useGetInstalledMods( 57 | useCallback((data) => { 58 | setInstalledMods(data.installedMods); 59 | }, []) 60 | ); 61 | 62 | useEffect(() => { 63 | getInstalledMods({}); 64 | }, [getInstalledMods]); 65 | 66 | const [messageApi, contextHolder] = message.useMessage(); 67 | 68 | const disabledAction = useCallback(() => { 69 | messageApi.info(t('modPreview.actionUnavailable'), 1); 70 | }, [messageApi, t]); 71 | 72 | if (!installedMods || !displayedModId) { 73 | return null; 74 | } 75 | 76 | if (!installedMods[displayedModId]) { 77 | return ( 78 | 79 | 80 | 84 | 85 | 86 | ); 87 | } 88 | 89 | return ( 90 | 91 | {contextHolder} 92 | 105 | 106 | ); 107 | } 108 | 109 | export default ModPreview; 110 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/SafeModeIndicator.tsx: -------------------------------------------------------------------------------- 1 | import { Alert, Button } from 'antd'; 2 | import { useCallback, useContext } from 'react'; 3 | import { useTranslation } from 'react-i18next'; 4 | import styled from 'styled-components'; 5 | import { AppUISettingsContext } from '../appUISettings'; 6 | import { PopconfirmModal } from '../components/InputWithContextMenu'; 7 | import { useUpdateAppSettings } from '../webviewIPC'; 8 | 9 | const FullWidthAlert = styled(Alert)` 10 | padding-left: calc(20px + max(50% - var(--app-max-width) / 2, 0px)); 11 | padding-right: calc(20px + max(50% - var(--app-max-width) / 2, 0px)); 12 | `; 13 | 14 | const FullWidthAlertContent = styled.div` 15 | display: flex; 16 | align-items: center; 17 | gap: 8px; 18 | `; 19 | 20 | function SafeModeIndicator() { 21 | const { t } = useTranslation(); 22 | 23 | const { updateAppSettings } = useUpdateAppSettings( 24 | useCallback((data) => { 25 | // Do nothing, we should be restarted soon. 26 | }, []) 27 | ); 28 | 29 | const { safeMode } = useContext(AppUISettingsContext); 30 | 31 | if (!safeMode) { 32 | return null; 33 | } 34 | 35 | return ( 36 | 39 |
{t('safeMode.alert')}
40 |
41 | { 46 | updateAppSettings({ 47 | appSettings: { 48 | safeMode: false, 49 | }, 50 | }); 51 | }} 52 | > 53 | 54 | 55 |
56 | 57 | } 58 | banner 59 | /> 60 | ); 61 | } 62 | 63 | export default SafeModeIndicator; 64 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/assets/local-mod-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Layer 1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/assets/logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | background 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/panel/assets/logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | background 4 | 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/sidebar/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useEffect, useState } from 'react'; 2 | import { 3 | getInitialSidebarParams, 4 | useSetEditedModDetails, 5 | } from '../webviewIPC'; 6 | import EditorModeControls, { ModDetails } from './EditorModeControls'; 7 | import { mockSidebarModDetails } from './mockData'; 8 | 9 | function Sidebar() { 10 | const [modDetails, setModDetails] = useState( 11 | mockSidebarModDetails 12 | ); 13 | 14 | useEffect(() => { 15 | getInitialSidebarParams(); 16 | }, []); 17 | 18 | useSetEditedModDetails( 19 | useCallback((data) => { 20 | if (!data.modDetails) { 21 | setModDetails({ 22 | modId: data.modId, 23 | modWasModified: data.modWasModified, 24 | compiled: false, 25 | }); 26 | } else { 27 | setModDetails({ 28 | modId: data.modId, 29 | modWasModified: data.modWasModified, 30 | compiled: true, 31 | disabled: data.modDetails.disabled, 32 | loggingEnabled: data.modDetails.loggingEnabled, 33 | debugLoggingEnabled: data.modDetails.debugLoggingEnabled, 34 | }); 35 | } 36 | }, []) 37 | ); 38 | 39 | const onExitEditorMode = useCallback(() => { 40 | setModDetails(null); 41 | }, []); 42 | 43 | if (!modDetails) { 44 | return null; 45 | } 46 | 47 | return ( 48 | 53 | ); 54 | } 55 | 56 | export default Sidebar; 57 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/sidebar/mockData.ts: -------------------------------------------------------------------------------- 1 | import vsCodeApi from '../vsCodeApi'; 2 | 3 | export const useMockData = !vsCodeApi; 4 | 5 | export const mockSidebarModDetails = !useMockData 6 | ? null 7 | : { 8 | modId: 'new-mod-test', 9 | modWasModified: false, 10 | compiled: true, 11 | disabled: false, 12 | loggingEnabled: false, 13 | debugLoggingEnabled: false, 14 | }; 15 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/swrHelpers.ts: -------------------------------------------------------------------------------- 1 | export const fetchText = (input: RequestInfo | URL, init?: RequestInit) => 2 | fetch(input, init).then((res) => res.text()); 3 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/app/vsCodeApi.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/microsoft/vscode/issues/96221#issuecomment-735408921 2 | declare function acquireVsCodeApi(): { 3 | getState: () => T; 4 | setState: (data: T) => void; 5 | postMessage: (msg: unknown) => void; 6 | }; 7 | 8 | const vsCodeApi = 9 | typeof acquireVsCodeApi !== 'undefined' ? acquireVsCodeApi() : null; 10 | 11 | export default vsCodeApi; 12 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // When building for production, this file is replaced with `environment.prod.ts`. 3 | 4 | export const environment = { 5 | production: false, 6 | }; 7 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/favicon.ico -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Windhawk 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/cs/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/da/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/de/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/el/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/en/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/es/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/fr/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/hr/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/hu/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/id/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/it/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/ja/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/ko/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/nl/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/pl/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/pt-BR/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/ro/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/ru/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/sv-SE/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/ta/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/tr/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/uk/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/vi/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/zh-CN/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/locales/zh-TW/DO_NOT_EDIT.txt: -------------------------------------------------------------------------------- 1 | The files in this folder are generated automatically. 2 | 3 | To submit a translation update, please refer to this repository: 4 | https://github.com/ramensoftware/windhawk-translate 5 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | /* remove padding set by vscode */ 3 | padding: 0; 4 | 5 | margin: 0; 6 | 7 | /* scrollbars sometimes show up because of Ant Design's context menu, hide 8 | them, we aren't using them anyway */ 9 | overflow: hidden; 10 | } 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react'; 2 | import * as ReactDOM from 'react-dom/client'; 3 | import App from './app/app'; 4 | import './main.css'; 5 | 6 | const params = document.querySelector('body')?.getAttribute('data-params'); 7 | const previewModId = params && JSON.parse(params).previewModId; 8 | if (previewModId) { 9 | const url = new URL(window.location.href); 10 | url.hash = '#/mod-preview/' + previewModId; 11 | window.history.replaceState(null, '', url); 12 | } 13 | 14 | const root = ReactDOM.createRoot( 15 | document.getElementById('root') as HTMLElement 16 | ); 17 | root.render( 18 | 19 | 20 | 21 | ); 22 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. 3 | * 4 | * See: https://github.com/zloirock/core-js#babel 5 | */ 6 | import 'core-js/stable'; 7 | import 'regenerator-runtime/runtime'; 8 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node"] 6 | }, 7 | "files": [ 8 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 9 | "../../node_modules/@nrwl/react/typings/image.d.ts" 10 | ], 11 | "exclude": [ 12 | "jest.config.ts", 13 | "**/*.spec.ts", 14 | "**/*.test.ts", 15 | "**/*.spec.tsx", 16 | "**/*.test.tsx", 17 | "**/*.spec.js", 18 | "**/*.test.js", 19 | "**/*.spec.jsx", 20 | "**/*.test.jsx" 21 | ], 22 | "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] 23 | } 24 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "files": [], 16 | "include": [], 17 | "references": [ 18 | { 19 | "path": "./tsconfig.app.json" 20 | }, 21 | { 22 | "path": "./tsconfig.spec.json" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "**/*.test.ts", 11 | "**/*.spec.ts", 12 | "**/*.test.tsx", 13 | "**/*.spec.tsx", 14 | "**/*.test.js", 15 | "**/*.spec.js", 16 | "**/*.test.jsx", 17 | "**/*.spec.jsx", 18 | "**/*.d.ts" 19 | ], 20 | "files": [ 21 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 22 | "../../node_modules/@nrwl/react/typings/image.d.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/apps/vscode-windhawk-ui/webpack.config.js: -------------------------------------------------------------------------------- 1 | // Reference: 2 | // https://github.com/ideafast/ideafast-portal/blob/59fb91104db81a86fc282491ac936d49fb4ef0e8/packages/itmat-ui-react/webpack.config.js#L7 3 | 4 | const webpack = require('webpack'); 5 | const { composePlugins, withNx } = require('@nx/webpack'); 6 | const { withReact } = require('@nx/react'); 7 | const { version } = require('../../package.json'); 8 | 9 | module.exports = composePlugins( 10 | withNx(), 11 | withReact(), 12 | (config) => { 13 | config.plugins.splice(0, 0, new webpack.EnvironmentPlugin({ 14 | REACT_APP_VERSION: version, 15 | })); 16 | 17 | return config; 18 | } 19 | ); 20 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "babelrcRoots": ["*"] 3 | } 4 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjects } from '@nrwl/jest'; 2 | 3 | export default { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nrwl/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk-ui/libs/.gitkeep -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 | "npmScope": "vscode-windhawk-ui-nx", 4 | "affected": { 5 | "defaultBase": "master" 6 | }, 7 | "tasksRunnerOptions": { 8 | "default": { 9 | "runner": "nx/tasks-runners/default", 10 | "options": { 11 | "cacheableOperations": ["build", "lint", "test", "e2e"] 12 | } 13 | } 14 | }, 15 | "targetDefaults": { 16 | "build": { 17 | "dependsOn": ["^build"], 18 | "inputs": ["production", "^production"] 19 | }, 20 | "test": { 21 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"] 22 | }, 23 | "e2e": { 24 | "inputs": ["default", "^production"] 25 | }, 26 | "lint": { 27 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"] 28 | } 29 | }, 30 | "namedInputs": { 31 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 32 | "production": [ 33 | "default", 34 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 35 | "!{projectRoot}/tsconfig.spec.json", 36 | "!{projectRoot}/jest.config.[jt]s", 37 | "!{projectRoot}/.eslintrc.json" 38 | ], 39 | "sharedGlobals": [ 40 | "{workspaceRoot}/babel.config.json", 41 | "{workspaceRoot}/package.json" 42 | ] 43 | }, 44 | "generators": { 45 | "@nrwl/react": { 46 | "application": { 47 | "style": "styled-components", 48 | "unitTestRunner": "jest", 49 | "linter": "eslint", 50 | "babel": true 51 | }, 52 | "component": { 53 | "style": "styled-components" 54 | }, 55 | "library": { 56 | "style": "styled-components", 57 | "unitTestRunner": "jest", 58 | "linter": "eslint" 59 | } 60 | } 61 | }, 62 | "defaultProject": "vscode-windhawk-ui" 63 | } 64 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-windhawk-ui-nx", 3 | "version": "1.6.1", 4 | "scripts": { 5 | "start": "nx serve", 6 | "watch": "nx build --configuration=development --watch", 7 | "build": "nx build", 8 | "build-ext": "npm run build && (robocopy /MIR dist/apps/vscode-windhawk-ui ../vscode-windhawk/webview) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0", 9 | "test": "nx test", 10 | "build-css": "less-watch-compiler --enable-js --run-once --main-file=app.less apps/vscode-windhawk-ui/src/app/ apps/vscode-windhawk-ui/src/app/", 11 | "watch-css": "npm run build-css && less-watch-compiler --enable-js --main-file=app.less apps/vscode-windhawk-ui/src/app/ apps/vscode-windhawk-ui/src/app/" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@fortawesome/fontawesome-svg-core": "^1.2.36", 16 | "@fortawesome/free-brands-svg-icons": "^5.15.4", 17 | "@fortawesome/free-solid-svg-icons": "^5.15.4", 18 | "@fortawesome/react-fontawesome": "^0.2.2", 19 | "antd": "^4.24.16", 20 | "core-js": "^3.42.0", 21 | "i18next": "^25.0.2", 22 | "i18next-http-backend": "^3.0.2", 23 | "immer": "^10.1.1", 24 | "prism-themes": "^1.9.0", 25 | "react": "18.3.1", 26 | "react-diff-view": "^2.6.0", 27 | "react-dom": "18.3.1", 28 | "react-i18next": "^15.5.1", 29 | "react-infinite-scroll-component": "^6.1.0", 30 | "react-is": "18.3.1", 31 | "react-markdown": "^10.1.0", 32 | "react-router-dom": "^7.5.3", 33 | "react-syntax-highlighter": "^15.6.1", 34 | "refractor": "^3.6.0", 35 | "regenerator-runtime": "0.14.1", 36 | "rehype-slug": "^6.0.0", 37 | "remark-gfm": "^4.0.1", 38 | "styled-components": "6.1.17", 39 | "swr": "^2.3.3", 40 | "tslib": "^2.8.1", 41 | "unidiff": "^1.0.4", 42 | "usehooks-ts": "^3.1.1" 43 | }, 44 | "devDependencies": { 45 | "@nrwl/cli": "15.9.7", 46 | "@nrwl/cypress": "19.8.14", 47 | "@nrwl/eslint-plugin-nx": "19.8.14", 48 | "@nrwl/jest": "19.8.14", 49 | "@nrwl/linter": "19.8.14", 50 | "@nrwl/react": "19.8.14", 51 | "@nrwl/web": "19.8.14", 52 | "@nrwl/webpack": "^19.8.14", 53 | "@nrwl/workspace": "19.8.14", 54 | "@pmmmwh/react-refresh-webpack-plugin": "^0.6.0", 55 | "@svgr/webpack": "^8.1.0", 56 | "@testing-library/react": "16.3.0", 57 | "@types/jest": "29.5.14", 58 | "@types/node": "22.15.3", 59 | "@types/react": "18.3.20", 60 | "@types/react-dom": "18.3.6", 61 | "@types/react-is": "18.3.1", 62 | "@types/react-syntax-highlighter": "^15.5.13", 63 | "@types/styled-components": "5.1.34", 64 | "@typescript-eslint/eslint-plugin": "^8.31.1", 65 | "@typescript-eslint/parser": "^8.31.1", 66 | "babel-jest": "29.7.0", 67 | "babel-plugin-styled-components": "2.1.4", 68 | "cypress": "^14.3.2", 69 | "eslint": "~8.57.0", 70 | "eslint-config-prettier": "9.1.0", 71 | "eslint-plugin-cypress": "^3.6.0", 72 | "eslint-plugin-import": "2.31.0", 73 | "eslint-plugin-jsx-a11y": "6.10.2", 74 | "eslint-plugin-react": "7.37.5", 75 | "eslint-plugin-react-hooks": "4.6.2", 76 | "jest": "29.7.0", 77 | "jest-environment-jsdom": "29.7.0", 78 | "less-watch-compiler": "^1.16.3", 79 | "nx": "20.8.1", 80 | "prettier": "^3.5.3", 81 | "react-refresh": "^0.17.0", 82 | "react-test-renderer": "18.3.1", 83 | "ts-jest": "29.3.2", 84 | "ts-node": "10.9.2", 85 | "typescript": "~5.8.3", 86 | "url-loader": "^4.1.1" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/tools/generators/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk-ui/tools/generators/.gitkeep -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /src/vscode-windhawk-ui/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": {} 18 | }, 19 | "exclude": ["node_modules", "tmp"] 20 | } 21 | -------------------------------------------------------------------------------- /src/vscode-windhawk/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: [ 7 | '@typescript-eslint', 8 | ], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | ], 13 | rules: { 14 | 'semi': [2, "always"], 15 | '@typescript-eslint/no-unused-vars': 0, 16 | '@typescript-eslint/no-explicit-any': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-non-null-assertion': 0, 19 | } 20 | }; -------------------------------------------------------------------------------- /src/vscode-windhawk/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | out/ 3 | webview/ 4 | prebuilds/ 5 | dist/ 6 | windhawk*.vsix 7 | -------------------------------------------------------------------------------- /src/vscode-windhawk/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /src/vscode-windhawk/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } -------------------------------------------------------------------------------- /src/vscode-windhawk/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 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 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Launch Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceRoot}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/dist/**/*.js" 18 | ], 19 | "preLaunchTask": "npm: webpack" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /src/vscode-windhawk/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": false, 3 | "cSpell.words": [ 4 | "DUNICODE", 5 | "DWORD", 6 | "HKCU", 7 | "HKEY", 8 | "HKLM", 9 | "Windhawk", 10 | "cppbuild", 11 | "cppdbg", 12 | "localizable", 13 | "opendir", 14 | "userprofile" 15 | ] 16 | } -------------------------------------------------------------------------------- /src/vscode-windhawk/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/vscode-windhawk/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | helper_scripts/** 3 | src/** 4 | out/** 5 | node_modules/** 6 | tsconfig.json 7 | .gitignore 8 | -------------------------------------------------------------------------------- /src/vscode-windhawk/README.md: -------------------------------------------------------------------------------- 1 | # Windhawk VSCode extension 2 | 3 | Part of the Windhawk Windows customization tool. 4 | 5 | https://windhawk.net/ 6 | -------------------------------------------------------------------------------- /src/vscode-windhawk/assets/main-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk/assets/main-icon.png -------------------------------------------------------------------------------- /src/vscode-windhawk/assets/main-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | background 4 | 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/vscode-windhawk/assets/tab-icon-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | background 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk/assets/tab-icon-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | background 4 | 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/vscode-windhawk/files/DbgViewMini.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/vscode-windhawk/files/DbgViewMini.exe -------------------------------------------------------------------------------- /src/vscode-windhawk/package.nls.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": "Windhawk", 3 | "commands.category": "Windhawk", 4 | "commands.start.title": "Open Windhawk Tab" 5 | } 6 | -------------------------------------------------------------------------------- /src/vscode-windhawk/src/config.ts: -------------------------------------------------------------------------------- 1 | // https://stackoverflow.com/a/45074641 2 | declare const v8debug: any; 3 | const debug = typeof v8debug === 'object' 4 | || /--debug|--inspect/.test(process.execArgv.join(' ')); 5 | 6 | export default { 7 | urls: { 8 | modsUrlRoot: 'https://mods.windhawk.net/', 9 | modsFolder: 'https://mods.windhawk.net/mods/', 10 | }, 11 | debug: debug ? { 12 | reactProjectBuildPath: String.raw`C:\Windhawk-dev\vscode-windhawk-ui\dist\apps\vscode-windhawk-ui`, 13 | appRootPath: String.raw`C:\Windhawk-dev\Windhawk`, 14 | disableMinimalMode: true, 15 | disableEnvVarCheck: true, 16 | } : { 17 | reactProjectBuildPath: null, 18 | appRootPath: null, 19 | disableMinimalMode: false, 20 | disableEnvVarCheck: false, 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/vscode-windhawk/src/ini.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as fsExt from 'fs-ext'; 3 | import * as ini from 'ini-win'; 4 | 5 | export type iniValue = { 6 | [key: string]: { 7 | [key: string]: string 8 | } 9 | }; 10 | 11 | export function fromFile(filePath: string) { 12 | const fd = fs.openSync(filePath, 'r'); 13 | fsExt.flockSync(fd, 'sh'); 14 | const buffer = fs.readFileSync(fd); 15 | fsExt.flockSync(fd, 'un'); 16 | fs.closeSync(fd); 17 | 18 | let contents: string; 19 | if (buffer[0] === 0xFF && buffer[1] === 0xFE) { 20 | contents = buffer.slice(2).toString('utf16le'); 21 | } else { 22 | contents = buffer.toString('utf8'); 23 | } 24 | 25 | const parsed = ini.parse(contents); 26 | 27 | const result: iniValue = {}; 28 | for (const [sectionName, section] of Object.entries(parsed)) { 29 | for (const [key, value] of Object.entries(section)) { 30 | if (typeof value === 'string') { 31 | result[sectionName] = result[sectionName] || {}; 32 | result[sectionName][key] = value; 33 | } 34 | } 35 | } 36 | 37 | return result; 38 | } 39 | 40 | export function fromFileOrDefault(filePath: string, defaultValue: iniValue = {}) { 41 | try { 42 | return fromFile(filePath); 43 | } catch (e) { 44 | // Ignore if file doesn't exist. 45 | if (e.code !== 'ENOENT') { 46 | throw e; 47 | } 48 | return defaultValue; 49 | } 50 | } 51 | 52 | export function toFile(filePath: string, value: iniValue) { 53 | const fd = fs.openSync(filePath, 'w'); 54 | fsExt.flockSync(fd, 'ex'); 55 | fs.writeFileSync(fd, '\uFEFF' + ini.stringify(value), 'utf16le'); 56 | fsExt.flockSync(fd, 'un'); 57 | fs.closeSync(fd); 58 | } 59 | -------------------------------------------------------------------------------- /src/vscode-windhawk/src/storagePaths.ts: -------------------------------------------------------------------------------- 1 | import * as reg from 'native-reg'; 2 | import * as path from 'path'; 3 | import * as vscode from 'vscode'; 4 | import config from './config'; 5 | import * as ini from './ini'; 6 | 7 | type FileSystemPaths = { 8 | appRootPath: string, 9 | appDataPath: string, 10 | enginePath: string, 11 | compilerPath: string, 12 | uiPath: string 13 | }; 14 | 15 | type StoragePathsPortable = { 16 | portable: true, 17 | fsPaths: FileSystemPaths 18 | }; 19 | 20 | type StoragePathsNonPortable = { 21 | portable: false, 22 | fsPaths: FileSystemPaths, 23 | regKey: reg.HKEY, 24 | regSubKey: string 25 | }; 26 | 27 | export type StoragePaths = 28 | | StoragePathsPortable 29 | | StoragePathsNonPortable; 30 | 31 | function getAppRootPath() { 32 | const debugAppRootPath = config.debug.appRootPath; 33 | if (debugAppRootPath) { 34 | return debugAppRootPath; 35 | } 36 | 37 | const vscodeInstallPath = vscode.env.appRoot; // returns \resources\app 38 | return path.dirname(path.dirname(path.dirname(vscodeInstallPath))); 39 | } 40 | 41 | function getStorageConfig(appRootPath: string) { 42 | const iniFilePath = path.join(appRootPath, 'windhawk.ini'); 43 | return ini.fromFile(iniFilePath); 44 | } 45 | 46 | function expandEnvironmentVariables(path: string) { 47 | // https://stackoverflow.com/a/21363956 48 | return path.replace(/%([^%]+)%/g, (original, matched) => { 49 | return process.env[matched] ?? original; 50 | }); 51 | } 52 | 53 | export function getStoragePaths(): StoragePaths { 54 | const appRootPath = getAppRootPath(); 55 | const storageConfig = getStorageConfig(appRootPath); 56 | 57 | const portable = !!parseInt(storageConfig.Storage.Portable, 10); 58 | 59 | const processPath = (p: string) => path.resolve(appRootPath, expandEnvironmentVariables(p)); 60 | 61 | const appDataPath = processPath(storageConfig.Storage.AppDataPath); 62 | const enginePath = processPath(storageConfig.Storage.EnginePath); 63 | const compilerPath = processPath(storageConfig.Storage.CompilerPath); 64 | const uiPath = processPath(storageConfig.Storage.UIPath); 65 | 66 | if (portable) { 67 | return { 68 | portable, 69 | fsPaths: { 70 | appRootPath, 71 | appDataPath, 72 | enginePath, 73 | compilerPath, 74 | uiPath 75 | } 76 | }; 77 | } 78 | 79 | const registryKey = storageConfig.Storage.RegistryKey; 80 | let i = registryKey.indexOf('\\'); 81 | if (i === -1) { 82 | i = registryKey.length; 83 | } 84 | 85 | let regKey: reg.HKEY; 86 | switch (registryKey.slice(0, i)) { 87 | case 'HKEY_CURRENT_USER': 88 | case 'HKCU': 89 | regKey = reg.HKCU; 90 | break; 91 | 92 | case 'HKEY_USERS': 93 | case 'HKU': 94 | regKey = reg.HKU; 95 | break; 96 | 97 | case 'HKEY_LOCAL_MACHINE': 98 | case 'HKLM': 99 | regKey = reg.HKLM; 100 | break; 101 | 102 | default: 103 | throw new Error('Unsupported registry path'); 104 | } 105 | 106 | const regSubKey = registryKey.slice(i + 1); 107 | 108 | return { 109 | portable, 110 | fsPaths: { 111 | appRootPath, 112 | appDataPath, 113 | enginePath, 114 | compilerPath, 115 | uiPath 116 | }, 117 | regKey, 118 | regSubKey 119 | }; 120 | } 121 | -------------------------------------------------------------------------------- /src/vscode-windhawk/src/utils/trayProgramUtils.ts: -------------------------------------------------------------------------------- 1 | import * as child_process from 'child_process'; 2 | import * as path from 'path'; 3 | import * as vscode from 'vscode'; 4 | 5 | export default class TrayProgramUtils { 6 | private trayProgramPath: string; 7 | 8 | public constructor(appRootPath: string) { 9 | this.trayProgramPath = path.join(appRootPath, 'windhawk.exe'); 10 | } 11 | 12 | private getCleanProcessEnv() { 13 | // Return the process environment, but without any environment variables 14 | // that are specific to Electron or VSCode. This is because the tray 15 | // process might run another instance of VSCode, and these variables 16 | // might cause problems (e.g. ELECTRON_RUN_AS_NODE=1). 17 | const cleanEnv: NodeJS.ProcessEnv = {}; 18 | for (const [key, value] of Object.entries(process.env)) { 19 | if (!key.startsWith('ELECTRON_') && 20 | !key.startsWith('VSCODE_') && 21 | !key.startsWith('WINDHAWK_')) { 22 | cleanEnv[key] = value; 23 | } 24 | } 25 | 26 | return cleanEnv; 27 | } 28 | 29 | private runTrayProgramWithArgs(args: string[]) { 30 | try { 31 | const ps = child_process.spawn(this.trayProgramPath, args, { 32 | env: this.getCleanProcessEnv(), 33 | }); 34 | 35 | let gotError = false; 36 | 37 | ps.on('error', err => { 38 | //console.log('Oh no, the error: ' + err); 39 | gotError = true; 40 | vscode.window.showErrorMessage(err.message); 41 | }); 42 | 43 | ps.on('close', code => { 44 | //console.log(`ps process exited with code ${code}`); 45 | if (!gotError && code !== 0) { 46 | vscode.window.showWarningMessage('Communication with the Windhawk tray icon process failed, make sure it\'s running'); 47 | } 48 | }); 49 | } catch (e) { 50 | vscode.window.showErrorMessage(e.message); 51 | } 52 | } 53 | 54 | public postAppRestartBg() { 55 | this.runTrayProgramWithArgs([ 56 | '-restart-bg' 57 | ]); 58 | } 59 | 60 | public postNewUpdatesFound() { 61 | this.runTrayProgramWithArgs([ 62 | '-new-updates-found' 63 | ]); 64 | } 65 | 66 | public postAppSettingsChanged() { 67 | this.runTrayProgramWithArgs([ 68 | '-app-settings-changed' 69 | ]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/vscode-windhawk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2019", 5 | "lib": ["ES2019"], 6 | "outDir": "out", 7 | "sourceMap": true, 8 | "strict": true, 9 | "rootDir": "src", 10 | "useUnknownInCatchVariables": false, 11 | "moduleResolution":"node" 12 | }, 13 | "include": [ 14 | "src/**/*.ts", 15 | "./node_modules/vscode/vscode.d.ts", 16 | "./node_modules/vscode/lib/*", 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/vscode-windhawk/webpack.config.js: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | *--------------------------------------------------------------------------------------------*/ 5 | 6 | //@ts-check 7 | 8 | 'use strict'; 9 | 10 | const path = require('path'); 11 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 12 | 13 | /**@type {import('webpack').Configuration}*/ 14 | const config = { 15 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ 16 | 17 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ 18 | output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ 19 | path: path.resolve(__dirname, 'dist'), 20 | filename: 'extension.js', 21 | libraryTarget: "commonjs2", 22 | devtoolModuleFilenameTemplate: "../[resource-path]", 23 | }, 24 | devtool: 'source-map', 25 | externals: { 26 | vscode: "commonjs vscode" // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ 27 | }, 28 | resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader 29 | extensions: ['.ts', '.js'], 30 | alias: { 31 | // Workaround for https://github.com/baudehlo/node-fs-ext/pull/104 32 | './build/Release/fs-ext': './build/Release/fs-ext.node' 33 | } 34 | }, 35 | module: { 36 | rules: [{ 37 | test: /\.ts$/, 38 | exclude: /node_modules/, 39 | use: [{ 40 | loader: 'ts-loader', 41 | options: { 42 | compilerOptions: { 43 | "module": "es6" // override `tsconfig.json` so that TypeScript emits native JavaScript modules. 44 | } 45 | } 46 | }] 47 | }, 48 | { 49 | test: /\.node$/, 50 | loader: "node-loader", 51 | }] 52 | }, 53 | plugins: [ 54 | new CopyWebpackPlugin({ 55 | patterns: [ 56 | { from: 'node_modules/native-reg/prebuilds', to: '../prebuilds' } 57 | ] 58 | }) 59 | ] 60 | }; 61 | 62 | module.exports = config; 63 | -------------------------------------------------------------------------------- /src/windhawk/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Chromium 2 | IndentWidth: 4 3 | 4 | # Reference: https://github.com/chromium/chromium/blob/3d90e395a5e87e305e567c097c434549f0d0874e/.clang-format 5 | # Make sure code like: 6 | # BEGIN_MESSAGE_MAP() 7 | # MESSAGE_HANDLER(WidgetHostViewHost_Update, OnUpdate) 8 | # END_MESSAGE_MAP() 9 | # gets correctly indented. 10 | MacroBlockBegin: "^\ 11 | BEGIN_MSG_MAP|\ 12 | BEGIN_MSG_MAP_EX|\ 13 | BEGIN_DLGRESIZE_MAP$" 14 | MacroBlockEnd: "^\ 15 | END_MSG_MAP|\ 16 | END_DLGRESIZE_MAP$" 17 | -------------------------------------------------------------------------------- /src/windhawk/.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 | -------------------------------------------------------------------------------- /src/windhawk/app/engine_control.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "engine_control.h" 4 | 5 | #include "storage_manager.h" 6 | 7 | EngineControl::EngineControl() { 8 | auto engineLibraryPath = 9 | StorageManager::GetInstance().GetEnginePath() / L"windhawk.dll"; 10 | 11 | engineModule.reset(LoadLibrary(engineLibraryPath.c_str())); 12 | THROW_LAST_ERROR_IF_NULL_MSG( 13 | engineModule, 14 | "Failed to load engine library: %ls, make sure that the engine path " 15 | "that's specified in windhawk.ini is correct", 16 | engineLibraryPath.c_str()); 17 | 18 | pGlobalHookSessionStart = reinterpret_cast( 19 | GetProcAddress(engineModule.get(), "GlobalHookSessionStart")); 20 | THROW_LAST_ERROR_IF_NULL(pGlobalHookSessionStart); 21 | 22 | pGlobalHookSessionHandleNewProcesses = 23 | reinterpret_cast( 24 | GetProcAddress(engineModule.get(), 25 | "GlobalHookSessionHandleNewProcesses")); 26 | THROW_LAST_ERROR_IF_NULL(pGlobalHookSessionHandleNewProcesses); 27 | 28 | pGlobalHookSessionEnd = reinterpret_cast( 29 | GetProcAddress(engineModule.get(), "GlobalHookSessionEnd")); 30 | THROW_LAST_ERROR_IF_NULL(pGlobalHookSessionEnd); 31 | 32 | hGlobalHookSession = pGlobalHookSessionStart(); 33 | if (!hGlobalHookSession) { 34 | throw std::runtime_error("Failed to start the global hooking session"); 35 | } 36 | } 37 | 38 | EngineControl::~EngineControl() { 39 | pGlobalHookSessionEnd(hGlobalHookSession); 40 | } 41 | 42 | BOOL EngineControl::HandleNewProcesses() { 43 | return pGlobalHookSessionHandleNewProcesses(hGlobalHookSession); 44 | } 45 | -------------------------------------------------------------------------------- /src/windhawk/app/engine_control.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class EngineControl { 4 | public: 5 | EngineControl(); 6 | ~EngineControl(); 7 | 8 | EngineControl(const EngineControl&) = delete; 9 | EngineControl(EngineControl&&) = delete; 10 | EngineControl& operator=(const EngineControl&) = delete; 11 | EngineControl& operator=(EngineControl&&) = delete; 12 | 13 | BOOL HandleNewProcesses(); 14 | 15 | private: 16 | using GLOBAL_HOOK_SESSION_START = HANDLE (*)(); 17 | using GLOBAL_HOOK_SESSION_HANDLE_NEW_PROCESSES = BOOL (*)(HANDLE hSession); 18 | using GLOBAL_HOOK_SESSION_END = BOOL (*)(HANDLE hSession); 19 | 20 | wil::unique_hmodule engineModule; 21 | GLOBAL_HOOK_SESSION_START pGlobalHookSessionStart; 22 | GLOBAL_HOOK_SESSION_HANDLE_NEW_PROCESSES 23 | pGlobalHookSessionHandleNewProcesses; 24 | GLOBAL_HOOK_SESSION_END pGlobalHookSessionEnd; 25 | HANDLE hGlobalHookSession; 26 | }; 27 | -------------------------------------------------------------------------------- /src/windhawk/app/event_viewer_crash_monitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class EventViewerCrashMonitor { 4 | public: 5 | EventViewerCrashMonitor(std::wstring_view targetAppPath); 6 | 7 | HANDLE GetEventHandle() const; 8 | int GetAmountOfNewEvents(); 9 | 10 | private: 11 | bool DoesEventMatch(EVT_HANDLE eventHandle); 12 | 13 | std::wstring m_targetAppPath; 14 | wil::unique_event m_event; 15 | wil::unique_evt_handle m_subscription; 16 | DWORD m_lastProcessId = 0; 17 | DWORD64 m_lastProcessCreationTime = 0; 18 | }; 19 | -------------------------------------------------------------------------------- /src/windhawk/app/functions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Functions { 4 | 5 | BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege); 6 | BOOL SetDebugPrivilege(BOOL bEnablePrivilege); 7 | HANDLE CreateEventForMediumIntegrity(PCWSTR eventName, 8 | BOOL manualReset = FALSE); 9 | BOOL IsRunAsAdmin(); 10 | PCWSTR LoadStrFromRsrc(UINT uStrId); 11 | std::vector SplitString(std::wstring_view s, WCHAR delim); 12 | std::vector SplitStringToViews(std::wstring_view s, 13 | WCHAR delim); 14 | std::wstring ReplaceAll(std::wstring_view source, 15 | std::wstring_view from, 16 | std::wstring_view to, 17 | bool ignoreCase = false); 18 | UINT GetDpiForWindowWithFallback(HWND hWnd); 19 | int GetSystemMetricsForDpiWithFallback(int nIndex, UINT dpi); 20 | int GetSystemMetricsForWindow(HWND hWnd, int nIndex); 21 | 22 | // Returns true for suspended UWP processes. 23 | // https://stackoverflow.com/a/50173965 24 | bool IsProcessFrozen(HANDLE hProcess); 25 | 26 | void GetNtVersionNumbers(ULONG* pNtMajorVersion, 27 | ULONG* pNtMinorVersion, 28 | ULONG* pNtBuildNumber); 29 | bool IsWindowsVersionOrGreaterWithBuildNumber(WORD wMajorVersion, 30 | WORD wMinorVersion, 31 | WORD wBuildNumber); 32 | NTSTATUS CreateExecutionRequiredRequest(_In_ HANDLE ProcessHandle, 33 | _Out_ PHANDLE PowerRequestHandle); 34 | 35 | } // namespace Functions 36 | -------------------------------------------------------------------------------- /src/windhawk/app/libraries/winhttpwrappers/WinHTTPWrappers.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/app/libraries/winhttpwrappers/WinHTTPWrappers.h -------------------------------------------------------------------------------- /src/windhawk/app/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "logger.h" 4 | 5 | #include "storage_manager.h" 6 | 7 | namespace { 8 | 9 | Logger::Verbosity GetVerbosityFromConfig() { 10 | try { 11 | auto settings = 12 | StorageManager::GetInstance().GetAppConfig(L"Settings", false); 13 | int verbosity = settings->GetInt(L"LoggingVerbosity").value_or(0); 14 | 15 | switch (verbosity) { 16 | case static_cast(Logger::Verbosity::kOff): 17 | return Logger::Verbosity::kOff; 18 | 19 | case static_cast(Logger::Verbosity::kOn): 20 | return Logger::Verbosity::kOn; 21 | 22 | case static_cast(Logger::Verbosity::kVerbose): 23 | return Logger::Verbosity::kVerbose; 24 | } 25 | } catch (const std::exception&) { 26 | // Ignore and use default settings. We can't log it, anyway. 27 | } 28 | 29 | return Logger::kDefaultVerbosity; 30 | } 31 | 32 | } // namespace 33 | 34 | Logger::Logger(Verbosity initialVerbosity) : LoggerBase(initialVerbosity) {} 35 | 36 | // static 37 | Logger& Logger::GetInstance() { 38 | static Logger s(GetVerbosityFromConfig()); 39 | return s; 40 | } 41 | -------------------------------------------------------------------------------- /src/windhawk/app/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logger_base.h" 4 | 5 | class Logger : public LoggerBase { 6 | public: 7 | Logger(Verbosity initialVerbosity); 8 | 9 | static Logger& GetInstance(); 10 | }; 11 | 12 | #define LOG_WITH_VERBOSITY(verbosity, message, ...) \ 13 | do { \ 14 | auto& inst = Logger::GetInstance(); \ 15 | if (inst.GetVerbosity() >= verbosity) { \ 16 | inst.LogLine(L"[WH] [%S]: " message L"\n", __FUNCTION__, \ 17 | __VA_ARGS__); \ 18 | } \ 19 | } while (0) 20 | 21 | #define LOG(message, ...) \ 22 | LOG_WITH_VERBOSITY(Logger::Verbosity::kOn, message, __VA_ARGS__) 23 | #define VERBOSE(message, ...) \ 24 | LOG_WITH_VERBOSITY(Logger::Verbosity::kVerbose, message, __VA_ARGS__) 25 | -------------------------------------------------------------------------------- /src/windhawk/app/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by rsrc.rc 4 | // 5 | #define IDR_MAINFRAME 0x80 6 | #define IDI_NOTIFICATION 0x81 7 | #define IDD_TASK_MANAGER 0x82 8 | #define IDD_TOOLKIT 0x83 9 | #define IDS_TRAY_OPEN 0x90 10 | #define IDS_TRAY_LOADED_MODS 0x91 11 | #define IDS_TRAY_TOOLKIT 0xA0 12 | #define IDS_TRAY_EXIT 0xB0 13 | #define IDS_EXITDLG_TITLE 0xB1 14 | #define IDS_EXITDLG_CONTENT 0xB2 15 | #define IDS_EXITDLG_CHECKBOX_AUTOSTART 0xB3 16 | #define IDS_EXITDLG_BUTTON_EXIT 0xB4 17 | #define IDS_EXITDLG_BUTTON_CANCEL 0xB5 18 | #define IDS_NOTIFICATION_UPDATE_APP 0xB6 19 | #define IDS_NOTIFICATION_UPDATE_APP_MOD 0xB7 20 | #define IDS_NOTIFICATION_UPDATE_APP_MODS 0xB8 21 | #define IDS_NOTIFICATION_UPDATE_MOD 0xB9 22 | #define IDS_NOTIFICATION_UPDATE_MODS 0xBA 23 | #define IDS_TRAYICON_TOOLTIP_UPDATE 0xBB 24 | #define IDS_TASKDLG_TITLE_LOADED_MODS 0xBC 25 | #define IDS_TASKDLG_TITLE_TASKS_IN_PROGRESS 0xBD 26 | #define IDS_TASKDLG_BUTTON_OPEN_APP 0xBE 27 | #define IDS_TASKDLG_COLUMN_MOD 0xBF 28 | #define IDS_TASKDLG_COLUMN_PROCESS 0xC0 29 | #define IDS_TASKDLG_COLUMN_PID 0xC1 30 | #define IDS_TASKDLG_COLUMN_STATUS 0xC2 31 | #define IDS_TASKDLG_STATUS_PENDING 0xC3 32 | #define IDS_TASKDLG_STATUS_LOADING 0xC4 33 | #define IDS_TASKDLG_STATUS_LOADED 0xC5 34 | #define IDS_TASKDLG_STATUS_UNLOADED 0xC6 35 | #define IDS_TASKDLG_TASK_INITIALIZING 0xC7 36 | #define IDS_TASKDLG_TASK_LOADING_SYMBOLS 0xC8 37 | #define IDS_TASKDLG_TASK_UNINITIALIZING 0xD0 38 | #define IDS_TASKDLG_PROCESS_SUSPENDED 0xE0 39 | #define IDS_TOOLKITDLG_TITLE 0xF0 40 | #define IDS_TOOLKITDLG_EXPLANATION_CRASH 0x100 41 | #define IDS_TOOLKITDLG_BUTTON_OPEN 0x111 42 | #define IDS_TOOLKITDLG_BUTTON_LOADED_MODS 0x112 43 | #define IDS_TOOLKITDLG_BUTTON_EXIT 0x113 44 | #define IDS_TOOLKITDLG_BUTTON_SAFE_MODE 0x114 45 | #define IDS_TOOLKITDLG_BUTTON_CLOSE 0x115 46 | #define IDS_SAFE_MODE_TITLE 0x116 47 | #define IDS_SAFE_MODE_TEXT 0x117 48 | #define IDS_SAFE_MODE_DETECTED_TITLE 0x120 49 | #define IDS_SAFE_MODE_DETECTED_TEXT 0x121 50 | #define IDC_TASK_LIST 1001 51 | #define IDC_TOOLKIT_EXPLANATION 1002 52 | #define IDC_TOOLKIT_LOADED_MODS 1003 53 | #define IDC_TOOLKIT_EXIT 1004 54 | #define IDC_TOOLKIT_SAFE_MODE 1005 55 | #define IDC_TOOLKIT_CLOSE 1006 56 | 57 | // Next default values for new objects 58 | // 59 | #ifdef APSTUDIO_INVOKED 60 | #ifndef APSTUDIO_READONLY_SYMBOLS 61 | #define _APS_NEXT_RESOURCE_VALUE 0x122 62 | #define _APS_NEXT_COMMAND_VALUE 32775 63 | #define _APS_NEXT_CONTROL_VALUE 1007 64 | #define _APS_NEXT_SYMED_VALUE 101 65 | #endif 66 | #endif 67 | -------------------------------------------------------------------------------- /src/windhawk/app/rsrc.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/app/rsrc.rc -------------------------------------------------------------------------------- /src/windhawk/app/rsrc.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/app/rsrc.rc2 -------------------------------------------------------------------------------- /src/windhawk/app/rsrc/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/app/rsrc/app.ico -------------------------------------------------------------------------------- /src/windhawk/app/rsrc/app_notification.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/app/rsrc/app_notification.ico -------------------------------------------------------------------------------- /src/windhawk/app/rsrc/compatibility.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | true 20 | PerMonitorV2 21 | true 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/windhawk/app/service.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Service { 4 | 5 | void Run(); 6 | bool IsRunning(bool waitIfStarting); 7 | void Start(); 8 | void Stop(bool disableAutoStart); 9 | 10 | } // namespace Service 11 | -------------------------------------------------------------------------------- /src/windhawk/app/service_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace ServiceCommon { 4 | 5 | static inline constexpr WCHAR kName[] = L"Windhawk"; 6 | 7 | static inline constexpr WCHAR kInfoFileMappingName[] = 8 | L"Global\\WindhawkServiceInfoFileMapping"; 9 | 10 | static inline constexpr WCHAR kMutexName[] = L"Global\\WindhawkServiceMutex"; 11 | 12 | static inline constexpr WCHAR kScanForProcessesEventName[] = 13 | L"Global\\WindhawkScanForProcesses"; 14 | 15 | static inline constexpr WCHAR kEmergencyStopEventName[] = 16 | L"Global\\WindhawkServiceEmergencyStopEvent"; 17 | 18 | static inline constexpr WCHAR kSafeModeStopEventName[] = 19 | L"Global\\WindhawkServiceSafeModeStopEvent"; 20 | 21 | struct ServiceInfo { 22 | DWORD version; 23 | DWORD processId; 24 | ULONGLONG processCreationTime; 25 | }; 26 | 27 | } // namespace ServiceCommon 28 | -------------------------------------------------------------------------------- /src/windhawk/app/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // app.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | -------------------------------------------------------------------------------- /src/windhawk/app/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Change these values to use different versions 4 | #define WINVER _WIN32_WINNT_WIN7 5 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 6 | #define _WIN32_IE _WIN32_IE_IE80 7 | #define _RICHEDIT_VER 0x0500 8 | 9 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 10 | #define NOMINMAX 11 | 12 | ////////////////////////////////////////////////////////////////////////// 13 | // WTL 14 | 15 | #define _WTL_NO_CSTRING 16 | #define _WTL_NO_WTYPES 17 | #define _WTL_NO_UNION_CLASSES 18 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | extern CAppModule _Module; 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | // #include 35 | #include 36 | // #include 37 | 38 | ////////////////////////////////////////////////////////////////////////// 39 | // Windows 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | ////////////////////////////////////////////////////////////////////////// 54 | // STL 55 | 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | 69 | ////////////////////////////////////////////////////////////////////////// 70 | // Libraries 71 | 72 | // https://github.com/nlohmann/json#implicit-conversions 73 | #define JSON_USE_IMPLICIT_CONVERSIONS 0 74 | 75 | #include 76 | #include 77 | 78 | #include // must be included before other wil includes 79 | 80 | #include 81 | #include 82 | #include 83 | #include 84 | #include 85 | -------------------------------------------------------------------------------- /src/windhawk/app/storage_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "portable_settings.h" 4 | 5 | class StorageManager { 6 | public: 7 | StorageManager(const StorageManager&) = delete; 8 | StorageManager(StorageManager&&) = delete; 9 | StorageManager& operator=(const StorageManager&) = delete; 10 | StorageManager& operator=(StorageManager&&) = delete; 11 | 12 | static StorageManager& GetInstance(); 13 | 14 | std::unique_ptr GetAppConfig(PCWSTR section, bool write); 15 | 16 | std::filesystem::path GetModMetadataPath(PCWSTR metadataCategory); 17 | 18 | bool IsPortable(); 19 | std::filesystem::path GetEnginePath( 20 | USHORT machine = IMAGE_FILE_MACHINE_UNKNOWN); 21 | std::filesystem::path GetUIPath(); 22 | std::filesystem::path GetCompilerPath(); 23 | std::filesystem::path GetUIDataPath(); 24 | std::filesystem::path GetEditorWorkspacePath(); 25 | std::filesystem::path GetUserProfileJsonPath(); 26 | 27 | class ModMetadataChangeNotification { 28 | public: 29 | ModMetadataChangeNotification(PCWSTR metadataCategory); 30 | 31 | HANDLE GetHandle(); 32 | void ContinueMonitoring(); 33 | 34 | private: 35 | wil::unique_hfind_change m_findChange; 36 | }; 37 | 38 | private: 39 | StorageManager(); 40 | ~StorageManager(); 41 | 42 | std::filesystem::path GetEngineAppDataPath(); 43 | 44 | struct RegistryPath { 45 | HKEY hKey = 0; 46 | std::wstring subKey; 47 | }; 48 | 49 | struct IniFilePath { 50 | std::wstring path; 51 | }; 52 | 53 | bool portableStorage; 54 | std::filesystem::path appDataPath; 55 | std::filesystem::path enginePath; 56 | std::filesystem::path uiPath; 57 | std::filesystem::path compilerPath; 58 | std::variant settingsPath; 59 | }; 60 | -------------------------------------------------------------------------------- /src/windhawk/app/task_manager_dlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | class CTaskManagerDlg : public CDialogImpl, 6 | public CDialogResize { 7 | public: 8 | enum { IDD = IDD_TASK_MANAGER }; 9 | 10 | BEGIN_DLGRESIZE_MAP(CTaskManagerDlg) 11 | DLGRESIZE_CONTROL(IDC_TASK_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y) 12 | DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y) 13 | END_DLGRESIZE_MAP() 14 | 15 | enum class DataSource { 16 | kModStatus, 17 | kModTask, 18 | }; 19 | 20 | using DlgCallback = std::function; 21 | 22 | // Wait before showing the autonomous dialog in case the data is short 23 | // lived. 24 | static constexpr int kAutonomousModeShowDelayDefault = 2000; 25 | static constexpr int kAutonomousModeShowDelayMin = 400; 26 | 27 | struct DialogOptions { 28 | DataSource dataSource = DataSource::kModStatus; 29 | bool autonomousMode = false; 30 | int autonomousModeShowDelay = kAutonomousModeShowDelayDefault; 31 | DWORD sessionManagerProcessId{}; 32 | ULONGLONG sessionManagerProcessCreationTime{}; 33 | DlgCallback runButtonCallback; 34 | DlgCallback finalMessageCallback; 35 | }; 36 | 37 | static bool IsDataSourceEmpty(DataSource dataSource); 38 | 39 | CTaskManagerDlg(DialogOptions dialogOptions); 40 | 41 | void LoadLanguageStrings(); 42 | void DataChanged(); 43 | 44 | private: 45 | enum class Timer { 46 | kUpdateProcessesStatus = 1, 47 | kRefreshList, 48 | kShowDlg, 49 | }; 50 | 51 | BEGIN_MSG_MAP_EX(CTaskManagerDlg) 52 | CHAIN_MSG_MAP(CDialogResize) 53 | MSG_WM_INITDIALOG(OnInitDialog) 54 | MSG_WM_DESTROY(OnDestroy) 55 | MSG_WM_TIMER(OnTimer) 56 | MSG_WM_DPICHANGED(OnDpiChanged) 57 | COMMAND_ID_HANDLER_EX(IDOK, OnOK) 58 | COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 59 | NOTIFY_HANDLER_EX(IDC_TASK_LIST, NM_RCLICK, OnListRightClick) 60 | END_MSG_MAP() 61 | 62 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 63 | void OnDestroy(); 64 | void OnTimer(UINT_PTR nIDEvent); 65 | void OnDpiChanged(UINT nDpiX, UINT nDpiY, PRECT pRect); 66 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 67 | void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl); 68 | LRESULT OnListRightClick(LPNMHDR pnmh); 69 | 70 | void OnFinalMessage(HWND hWnd) override; 71 | UINT_PTR SetTimer(Timer nIDEvent, 72 | UINT nElapse, 73 | TIMERPROC lpfnTimer = nullptr); 74 | BOOL KillTimer(Timer nIDEvent); 75 | void ReloadMainIcon(); 76 | void PlaceWindowAtTrayArea(); 77 | void InitTaskList(); 78 | void LoadTaskList(); 79 | bool LoadTaskItemFromMetadataFile(const std::filesystem::path& filePath, 80 | int itemIndex); 81 | void AddItemToList(int itemIndex, 82 | PCWSTR filePath, 83 | PCWSTR mod, 84 | PCWSTR processName, 85 | DWORD processId, 86 | PCWSTR status, 87 | FILETIME creationTime); 88 | void RefreshTaskList(); 89 | void UpdateTaskListProcessesStatus(); 90 | void UpdateDialogAfterListUpdate(); 91 | 92 | const DialogOptions m_dialogOptions; 93 | CSortListViewCtrl m_taskListSort; 94 | bool m_refreshListOnDataChangePending = false; 95 | bool m_showDlgPending = false; 96 | }; 97 | -------------------------------------------------------------------------------- /src/windhawk/app/toolkit_dlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | class CToolkitDlg : public CDialogImpl { 6 | public: 7 | enum { IDD = IDD_TOOLKIT }; 8 | 9 | using DlgCallback = std::function; 10 | 11 | struct DialogOptions { 12 | bool createInactive = false; 13 | bool showTaskbarCrashExplanation = false; 14 | DlgCallback runButtonCallback; 15 | DlgCallback loadedModsButtonCallback; 16 | DlgCallback exitButtonCallback; 17 | DlgCallback safeModeButtonCallback; 18 | DlgCallback finalMessageCallback; 19 | }; 20 | 21 | CToolkitDlg(DialogOptions dialogOptions); 22 | 23 | void LoadLanguageStrings(); 24 | 25 | bool WasActive(); 26 | void Close(); 27 | 28 | private: 29 | BEGIN_MSG_MAP_EX(CToolkitDlg) 30 | MSG_WM_INITDIALOG(OnInitDialog) 31 | MSG_WM_DESTROY(OnDestroy) 32 | MSG_WM_ACTIVATE(OnActivate) 33 | MSG_WM_DPICHANGED(OnDpiChanged) 34 | COMMAND_ID_HANDLER_EX(IDOK, OnOK) 35 | COMMAND_ID_HANDLER_EX(IDC_TOOLKIT_LOADED_MODS, OnLoadedMods) 36 | COMMAND_ID_HANDLER_EX(IDC_TOOLKIT_EXIT, OnExit) 37 | COMMAND_ID_HANDLER_EX(IDC_TOOLKIT_SAFE_MODE, OnSafeMode) 38 | COMMAND_ID_HANDLER_EX(IDC_TOOLKIT_CLOSE, OnClose) 39 | END_MSG_MAP() 40 | 41 | BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 42 | void OnDestroy(); 43 | void OnActivate(UINT nState, BOOL bMinimized, CWindow wndOther); 44 | void OnDpiChanged(UINT nDpiX, UINT nDpiY, PRECT pRect); 45 | void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl); 46 | void OnLoadedMods(UINT uNotifyCode, int nID, CWindow wndCtl); 47 | void OnExit(UINT uNotifyCode, int nID, CWindow wndCtl); 48 | void OnSafeMode(UINT uNotifyCode, int nID, CWindow wndCtl); 49 | void OnClose(UINT uNotifyCode, int nID, CWindow wndCtl); 50 | 51 | void OnFinalMessage(HWND hWnd) override; 52 | void ReloadMainIcon(); 53 | void PlaceWindowAtTrayArea(); 54 | 55 | const DialogOptions m_dialogOptions; 56 | bool m_wasActive = false; 57 | }; 58 | -------------------------------------------------------------------------------- /src/windhawk/app/tray_icon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class AppTrayIcon { 4 | public: 5 | enum class TrayAction { 6 | kNone, 7 | kDefault, 8 | kBalloon, 9 | kContextMenu, 10 | }; 11 | 12 | static inline constexpr size_t kMaxNotificationTooltipSize = 13 | ARRAYSIZE(NOTIFYICONDATA::szInfo); 14 | 15 | AppTrayIcon(HWND hWnd, UINT uCallbackMsg, bool hidden = false); 16 | 17 | void Create(); 18 | void Modify(); 19 | void UpdateIcons(HWND hWnd); 20 | void Hide(bool hidden); 21 | void SetNotificationIconAndTooltip(PCWSTR pText); 22 | void ShowNotificationMessage(PCWSTR pText); 23 | void Remove(); 24 | TrayAction HandleMsg(WPARAM wParam, LPARAM lParam); 25 | 26 | private: 27 | void ReloadIcons(HWND hWnd); 28 | 29 | CIcon m_trayIcon; 30 | CIcon m_balloonIcon; 31 | CIcon m_trayIconWithNotification; 32 | NOTIFYICONDATA m_nid{}; 33 | DWORD m_lastClickTickCount = 0; 34 | }; 35 | -------------------------------------------------------------------------------- /src/windhawk/app/ui_control.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace UIControl { 4 | 5 | void RunUI(); 6 | bool RunUIViaSchedTask(); 7 | std::vector GetOpenUIWindows(); 8 | bool BringUIToFront(); 9 | void RunUIOrBringToFront(HWND hWnd, bool mustRunAsAdmin); 10 | bool CloseUI(); 11 | 12 | } // namespace UIControl 13 | -------------------------------------------------------------------------------- /src/windhawk/app/update_checker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "userprofile.h" 4 | #include "winhttpsimple.h" 5 | 6 | class UpdateChecker { 7 | public: 8 | struct Result { 9 | HRESULT hrError; 10 | DWORD httpStatusCode; 11 | UserProfile::UpdateStatus updateStatus; 12 | }; 13 | 14 | enum { 15 | kFlagPortable = 1, 16 | }; 17 | 18 | UpdateChecker(DWORD flags, std::function onUpdateCheckDone); 19 | void Abort(); 20 | Result HandleResponse(); 21 | 22 | private: 23 | bool ShouldRetryWithAGetRequest(); 24 | void OnRequestDone(); 25 | 26 | std::atomic m_aborted = false; 27 | DWORD m_flags = 0; 28 | std::string m_postedData; 29 | CWinHTTPSimple m_httpSimple; 30 | std::unique_ptr m_httpSimpleGetRequest; 31 | std::mutex m_httpSimpleGetRequestMutex; 32 | std::function m_onUpdateCheckDone; 33 | }; 34 | -------------------------------------------------------------------------------- /src/windhawk/app/userprofile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace UserProfile { 4 | 5 | struct UpdateStatus { 6 | bool appUpdateAvailable; 7 | int modUpdatesAvailable; 8 | bool newUpdatesFound; 9 | }; 10 | 11 | std::string GetLocalUpdatedContentAsString(); 12 | UpdateStatus UpdateContentWithOnlineData(PCSTR onlineData, 13 | size_t onlineDataLength); 14 | UpdateStatus GetUpdateStatus(); 15 | 16 | } // namespace UserProfile 17 | -------------------------------------------------------------------------------- /src/windhawk/build.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM // Usage: 4 | REM // build.bat Debug "" 5 | REM // build.bat Release :rebuild 6 | 7 | SET "VSCMD_START_DIR=%CD%" 8 | IF "%FrameworkVersion%" == "" CALL "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" 9 | 10 | MSBuild.exe "windhawk.sln" /m /t:"app%~2" /p:Configuration="%~1" /p:Platform="Win32" || GOTO fail 11 | MSBuild.exe "windhawk.sln" /m /t:"engine%~2" /p:Configuration="%~1" /p:Platform="Win32" || GOTO fail 12 | MSBuild.exe "windhawk.sln" /m /t:"engine%~2" /p:Configuration="%~1" /p:Platform="x64" || GOTO fail 13 | MSBuild.exe "windhawk.sln" /m /t:"engine%~2" /p:Configuration="%~1" /p:Platform="ARM64" || GOTO fail 14 | 15 | REM // Done 16 | EXIT /b 0 17 | 18 | :fail 19 | EXIT /b %ERRORLEVEL% 20 | -------------------------------------------------------------------------------- /src/windhawk/engine/_exports.def: -------------------------------------------------------------------------------- 1 | LIBRARY "windhawk.dll" 2 | EXPORTS 3 | InjectInit 4 | GlobalHookSessionStart 5 | GlobalHookSessionHandleNewProcesses 6 | GlobalHookSessionEnd 7 | InternalWh_IsLogEnabled 8 | InternalWh_Log 9 | InternalWh_GetIntValue 10 | InternalWh_SetIntValue 11 | InternalWh_GetStringValue 12 | InternalWh_SetStringValue 13 | InternalWh_GetBinaryValue 14 | InternalWh_SetBinaryValue 15 | InternalWh_DeleteValue 16 | InternalWh_GetModStoragePath 17 | InternalWh_GetIntSetting 18 | InternalWh_GetStringSetting 19 | InternalWh_FreeStringSetting 20 | InternalWh_SetFunctionHook 21 | InternalWh_RemoveFunctionHook 22 | InternalWh_ApplyHookOperations 23 | InternalWh_FindFirstSymbol 24 | InternalWh_FindFirstSymbol2 25 | InternalWh_FindFirstSymbol3 26 | InternalWh_FindFirstSymbol4 27 | InternalWh_FindNextSymbol 28 | InternalWh_FindNextSymbol2 29 | InternalWh_FindCloseSymbol 30 | InternalWh_HookSymbols 31 | InternalWh_Disasm 32 | InternalWh_GetUrlContent 33 | InternalWh_FreeUrlContent 34 | -------------------------------------------------------------------------------- /src/windhawk/engine/all_processes_injector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class AllProcessesInjector { 4 | public: 5 | AllProcessesInjector(); 6 | 7 | int InjectIntoNewProcesses() noexcept; 8 | 9 | private: 10 | bool ShouldSkipNewProcess(HANDLE hProcess, 11 | DWORD dwProcessId, 12 | bool* threadAttachExempt); 13 | void InjectIntoNewProcess(HANDLE hProcess, 14 | DWORD dwProcessId, 15 | bool threadAttachExempt); 16 | 17 | using NtGetNextProcess_t = NTSTATUS(NTAPI*)(_In_opt_ HANDLE ProcessHandle, 18 | _In_ ACCESS_MASK DesiredAccess, 19 | _In_ ULONG HandleAttributes, 20 | _In_ ULONG Flags, 21 | _Out_ PHANDLE NewProcessHandle); 22 | 23 | using NtGetNextThread_t = NTSTATUS(NTAPI*)(_In_ HANDLE ProcessHandle, 24 | _In_opt_ HANDLE ThreadHandle, 25 | _In_ ACCESS_MASK DesiredAccess, 26 | _In_ ULONG HandleAttributes, 27 | _In_ ULONG Flags, 28 | _Out_ PHANDLE NewThreadHandle); 29 | 30 | NtGetNextProcess_t m_NtGetNextProcess; 31 | NtGetNextThread_t m_NtGetNextThread; 32 | DWORD64 m_pRtlUserThreadStart = 0; 33 | DWORD64 m_pRtlUserThreadStart_x64OnArm64 = 0; 34 | wil::unique_private_namespace_destroy m_appPrivateNamespace; 35 | std::wstring m_includePattern; 36 | std::wstring m_excludePattern; 37 | std::wstring m_threadAttachExemptPattern; 38 | wil::unique_process_handle m_lastEnumeratedProcess; 39 | }; 40 | -------------------------------------------------------------------------------- /src/windhawk/engine/dll_inject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DllInject { 4 | 5 | constexpr ACCESS_MASK kProcessAccess = PROCESS_CREATE_THREAD | 6 | PROCESS_VM_OPERATION | PROCESS_VM_READ | 7 | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | 8 | PROCESS_QUERY_INFORMATION | SYNCHRONIZE; 9 | 10 | struct LOAD_LIBRARY_REMOTE_DATA { 11 | INT32 nLogVerbosity; 12 | BOOL bRunningFromAPC; 13 | BOOL bThreadAttachExempt; 14 | union { 15 | HANDLE hSessionManagerProcess; 16 | // Make sure 32-bit/64-bit layouts are the same. 17 | DWORD64 dw64SessionManagerProcess; 18 | }; 19 | union { 20 | HANDLE hSessionMutex; 21 | // Make sure 32-bit/64-bit layouts are the same. 22 | DWORD64 dw64SessionMutex; 23 | }; 24 | union { 25 | void* pInjectedShellcodeAddress; 26 | // Make sure 32-bit/64-bit layouts are the same. 27 | DWORD64 dw64InjectedShellcodeAddress; 28 | }; 29 | WCHAR szDllName[1]; // flexible array member 30 | }; 31 | 32 | void DllInject(HANDLE hProcess, 33 | HANDLE hThreadForAPC, 34 | HANDLE hSessionManagerProcess, 35 | HANDLE hSessionMutex, 36 | bool threadAttachExempt); 37 | 38 | } // namespace DllInject 39 | -------------------------------------------------------------------------------- /src/windhawk/engine/functions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Functions { 4 | 5 | bool wcsmatch(PCWSTR pat, size_t plen, PCWSTR str, size_t slen); 6 | std::vector SplitString(std::wstring_view s, WCHAR delim); 7 | std::vector SplitStringToViews(std::wstring_view s, 8 | WCHAR delim); 9 | std::wstring ReplaceAll(std::wstring_view source, 10 | std::wstring_view from, 11 | std::wstring_view to, 12 | bool ignoreCase = false); 13 | bool DoesPathMatchPattern(std::wstring_view path, 14 | std::wstring_view pattern, 15 | bool explicitOnly = false); 16 | void** FindImportPtr(HMODULE hFindInModule, 17 | PCSTR pModuleName, 18 | PCSTR pImportName); 19 | BOOL GetFullAccessSecurityDescriptor( 20 | _Outptr_ PSECURITY_DESCRIPTOR* SecurityDescriptor, 21 | _Out_opt_ PULONG SecurityDescriptorSize); 22 | 23 | // https://waleedassar.blogspot.com/2012/12/skipthreadattach.html 24 | enum MyCreateRemoteThreadFlags : ULONG { 25 | MY_REMOTE_THREAD_CREATE_SUSPENDED = 0x01, 26 | MY_REMOTE_THREAD_THREAD_ATTACH_EXEMPT = 0x02, 27 | MY_REMOTE_THREAD_HIDE_FROM_DEBUGGER = 0x04, 28 | MY_REMOTE_THREAD_LOADER_WORKER = 0x10, // since THRESHOLD 29 | MY_REMOTE_THREAD_SKIP_LOADER_INIT = 0x20, // since REDSTONE2 30 | MY_REMOTE_THREAD_BYPASS_PROCESS_FREEZE = 0x40, // since 19H1 31 | }; 32 | 33 | // Using MyCreateRemoteThread instead of CreateRemoteThread provides the 34 | // following benefits: 35 | // * On Windows 7, it allows to create a remote thread in a process running in 36 | // another session. 37 | // * It allows providing extra flags. We use the 38 | // MY_REMOTE_THREAD_THREAD_ATTACH_EXEMPT flag to reduce incompatibility with 39 | // other processes. 40 | HANDLE MyCreateRemoteThread(HANDLE hProcess, 41 | LPTHREAD_START_ROUTINE lpStartAddress, 42 | LPVOID lpParameter, 43 | ULONG createFlags); 44 | 45 | void GetNtVersionNumbers(ULONG* pNtMajorVersion, 46 | ULONG* pNtMinorVersion, 47 | ULONG* pNtBuildNumber); 48 | bool IsWindowsVersionOrGreaterWithBuildNumber(WORD wMajorVersion, 49 | WORD wMinorVersion, 50 | WORD wBuildNumber); 51 | bool ModuleGetPDBInfo(HANDLE hOsHandle, 52 | _Out_ GUID* pGuidSignature, 53 | _Out_ DWORD* pdwAge); 54 | std::string GetModuleVersion(HMODULE hModule); 55 | 56 | } // namespace Functions 57 | -------------------------------------------------------------------------------- /src/windhawk/engine/inject_shellcode/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Microsoft 2 | UseTab: ForContinuationAndIndentation 3 | PointerAlignment: Left 4 | AlignConsecutiveMacros: AcrossEmptyLines 5 | -------------------------------------------------------------------------------- /src/windhawk/engine/inject_shellcode/InjectShellcode.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;hh;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 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/windhawk/engine/inject_shellcode/InjectShellcode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32901.215 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectShellcode", "InjectShellcode.vcxproj", "{EDF9A877-A2A8-43AF-8BCC-897F5B28E104}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM64 = Debug|ARM64 11 | Debug|Win32 = Debug|Win32 12 | Debug|x64 = Debug|x64 13 | Release|ARM64 = Release|ARM64 14 | Release|Win32 = Release|Win32 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|ARM64.ActiveCfg = Debug|ARM64 19 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|ARM64.Build.0 = Debug|ARM64 20 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|Win32.Build.0 = Debug|Win32 22 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|x64.ActiveCfg = Debug|x64 23 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Debug|x64.Build.0 = Debug|x64 24 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|ARM64.ActiveCfg = Release|ARM64 25 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|ARM64.Build.0 = Release|ARM64 26 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|Win32.ActiveCfg = Release|Win32 27 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|Win32.Build.0 = Release|Win32 28 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|x64.ActiveCfg = Release|x64 29 | {EDF9A877-A2A8-43AF-8BCC-897F5B28E104}.Release|x64.Build.0 = Release|x64 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {ECA2D17E-0AA3-4DA9-941B-8F0232D3A06D} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook-Detours/SlimDetours/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Windows-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = crlf 9 | insert_final_newline = true 10 | 11 | # 4 space indentation 12 | [*.{c,h,inl}] 13 | indent_style = space 14 | indent_size = 4 15 | 16 | # Trim trailing whitespaces 17 | [*.{c,h,inl}] 18 | trim_trailing_whitespace = true 19 | 20 | # UTF-8 21 | [*.{c,h,inl}] 22 | charset = utf-8-bom 23 | 24 | # C/C++ code formatting 25 | [*.{c,h,inl}] 26 | cpp_new_line_before_else = false 27 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook-Detours/SlimDetours/InlineHook.c: -------------------------------------------------------------------------------- 1 | /* 2 | * KNSoft.SlimDetours (https://github.com/KNSoft/KNSoft.SlimDetours) Inline Hook Wrappers 3 | * Copyright (c) KNSoft.org (https://github.com/KNSoft). All rights reserved. 4 | * Licensed under the MIT license. 5 | */ 6 | 7 | #include "SlimDetours.inl" 8 | 9 | HRESULT 10 | NTAPI 11 | SlimDetoursInlineHook( 12 | _In_ BOOL bEnable, 13 | _Inout_ PVOID* ppPointer, 14 | _In_ PVOID pDetour) 15 | { 16 | HRESULT hr; 17 | 18 | hr = SlimDetoursTransactionBegin(); 19 | if (FAILED(hr)) 20 | { 21 | return hr; 22 | } 23 | hr = bEnable ? SlimDetoursAttach(ppPointer, pDetour) : SlimDetoursDetach(ppPointer, pDetour); 24 | if (FAILED(hr)) 25 | { 26 | SlimDetoursTransactionAbort(); 27 | return hr; 28 | } 29 | return SlimDetoursTransactionCommit(); 30 | } 31 | 32 | HRESULT 33 | NTAPI 34 | SlimDetoursInitInlineHooks( 35 | _In_ HMODULE hModule, 36 | _In_ ULONG ulCount, 37 | _Inout_updates_(ulCount) PDETOUR_INLINE_HOOK pHooks) 38 | { 39 | NTSTATUS Status; 40 | ULONG i, uOridinal; 41 | ANSI_STRING FuncName, *pFuncName; 42 | 43 | for (i = 0; i < ulCount; i++) 44 | { 45 | if ((UINT_PTR)pHooks[i].pszFuncName > MAXWORD) 46 | { 47 | Status = RtlInitAnsiStringEx(&FuncName, pHooks[i].pszFuncName); 48 | if (!NT_SUCCESS(Status)) 49 | { 50 | return HRESULT_FROM_NT(Status); 51 | } 52 | pFuncName = &FuncName; 53 | uOridinal = 0; 54 | } else 55 | { 56 | pFuncName = NULL; 57 | uOridinal = (ULONG)(UINT_PTR)pHooks[i].pszFuncName; 58 | } 59 | Status = LdrGetProcedureAddress(hModule, pFuncName, uOridinal, pHooks[i].ppPointer); 60 | if (!NT_SUCCESS(Status)) 61 | { 62 | return HRESULT_FROM_NT(Status); 63 | } 64 | } 65 | 66 | return HRESULT_FROM_NT(STATUS_SUCCESS); 67 | } 68 | 69 | HRESULT 70 | NTAPI 71 | SlimDetoursInlineHooks( 72 | _In_ BOOL bEnable, 73 | _In_ ULONG ulCount, 74 | _Inout_updates_(ulCount) PDETOUR_INLINE_HOOK pHooks) 75 | { 76 | HRESULT hr; 77 | ULONG i; 78 | 79 | hr = SlimDetoursTransactionBegin(); 80 | if (FAILED(hr)) 81 | { 82 | return hr; 83 | } 84 | for (i = 0; i < ulCount; i++) 85 | { 86 | hr = bEnable ? 87 | SlimDetoursAttach(pHooks[i].ppPointer, pHooks[i].pDetour) : 88 | SlimDetoursDetach(pHooks[i].ppPointer, pHooks[i].pDetour); 89 | if (FAILED(hr)) 90 | { 91 | SlimDetoursTransactionAbort(); 92 | return hr; 93 | } 94 | } 95 | return SlimDetoursTransactionCommit(); 96 | } 97 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook-Detours/SlimDetours/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) KNSoft.org 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 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook-Detours/SlimDetours/SlimDetours.NDK.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapt to NDKs to access low-level Windows NT APIs 3 | * 4 | * SlimDetours uses KNSoft.NDK by default, and also support other NDKs. 5 | * 6 | * KNSoft.NDK 7 | * Used when macro `_USE_KNSOFT_NDK` is defined, this is the default behavior on offical project. 8 | * 9 | * ReactOS NDK 10 | * Used when macro `__REACTOS__` is defined, can be built with ReactOS. 11 | * 12 | * Other NDKs 13 | * Include other NDKs (e.g. phnt) header before SlimDetours, they should provide what we need. 14 | */ 15 | 16 | #pragma once 17 | 18 | #if defined(_USE_KNSOFT_NDK) 19 | 20 | #include 21 | 22 | #elif defined(__REACTOS__) 23 | 24 | #define WIN32_NO_STATUS 25 | #include 26 | #include 27 | 28 | #define NTOS_MODE_USER 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #endif 38 | 39 | /* Backwards compatible */ 40 | #if (NTDDI_VERSION < NTDDI_WIN8) 41 | typedef ULONG LOGICAL, *PLOGICAL; 42 | #endif 43 | 44 | #ifndef FAST_FAIL_INVALID_ARG 45 | #define FAST_FAIL_INVALID_ARG 5 46 | #endif 47 | 48 | /* Add KNSoft.NDK specific stuff */ 49 | #ifndef _USE_KNSOFT_NDK 50 | 51 | /* Use phnt */ 52 | #include 53 | #include 54 | #undef NtCurrentProcessId 55 | #undef NtCurrentThreadId 56 | 57 | #define PAGE_SIZE 0x1000 58 | #define MM_ALLOCATION_GRANULARITY 0x10000 59 | 60 | #if defined(_X86_) 61 | #define CONTEXT_PC Eip 62 | #elif defined(_AMD64_) 63 | #define CONTEXT_PC Rip 64 | #elif defined(_ARM64_) 65 | #define CONTEXT_PC Pc 66 | #endif 67 | 68 | #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I))) 69 | #define PtrOffset(B,O) ((ULONG)((ULONG_PTR)(O) - (ULONG_PTR)(B))) 70 | 71 | #define KB_TO_BYTES(x) ((x) * 1024UL) 72 | #define MB_TO_KB(x) ((x) * 1024UL) 73 | #define MB_TO_BYTES(x) (KB_TO_BYTES(MB_TO_KB(x))) 74 | #define GB_TO_MB(x) ((x) * 1024UL) 75 | #define GB_TO_BYTES(x) (MB_TO_BYTES(GB_TO_MB(x))) 76 | 77 | #define MM_LOWEST_USER_ADDRESS ((PVOID)0x10000) 78 | 79 | #if defined(_WIN64) 80 | 81 | /* [0x00007FF7FFFF0000 ... 0x00007FFFFFFF0000], 32G */ 82 | #define MI_ASLR_BITMAP_SIZE 0x10000 83 | #define MI_ASLR_HIGHEST_SYSTEM_RANGE_ADDRESS ((PVOID)0x00007FFFFFFF0000ULL) 84 | 85 | #else 86 | 87 | /* [0x50000000 ... 0x78000000], 640M */ 88 | #define MI_ASLR_BITMAP_SIZE 0x500 89 | #define MI_ASLR_HIGHEST_SYSTEM_RANGE_ADDRESS ((PVOID)0x78000000UL) 90 | 91 | #endif 92 | 93 | #define NtCurrentProcessId() ((ULONG)(ULONG_PTR)NtCurrentTeb()->ClientId.UniqueProcess) 94 | #define NtCurrentThreadId() ((ULONG)(ULONG_PTR)NtCurrentTeb()->ClientId.UniqueThread) 95 | #define NtGetProcessHeap() (NtCurrentPeb()->ProcessHeap) 96 | #define NtGetNtdllBase() (CONTAINING_RECORD(NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks)->DllBase) 97 | 98 | #if defined(_WIN64) 99 | #define SIZE_OF_POINTER 8 100 | #else 101 | #define SIZE_OF_POINTER 4 102 | #endif 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook-Detours/SlimDetours/Utils.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SlimDetours.NDK.inl" 4 | 5 | /* 6 | * Run Once 7 | * Similar to RtlRunOnce* but sync only and inline, 8 | * taken from KNSoft.MakeLifeEasier library 9 | */ 10 | 11 | typedef DECLSPEC_ALIGN(SIZE_OF_POINTER) struct _PS_RUNONCE 12 | { 13 | DECLSPEC_ALIGN(SIZE_OF_POINTER) _Interlocked_operand_ PVOID volatile Ptr; 14 | } PS_RUNONCE, *PPS_RUNONCE; 15 | 16 | #define PS_RUNONCE_INIT { NULL } 17 | 18 | #define PS_RUNONCE_STATE_MASK 0b11 19 | #define PS_RUNONCE_STATE_INIT 0b00 20 | #define PS_RUNONCE_STATE_PENDING 0b01 21 | #define PS_RUNONCE_STATE_COMPLETED 0b10 22 | 23 | C_ASSERT(PS_RUNONCE_STATE_MASK < 4); 24 | 25 | FORCEINLINE 26 | LOGICAL 27 | PS_RunOnceBegin( 28 | _Inout_ PPS_RUNONCE RunOnce) 29 | { 30 | PPS_RUNONCE Value; 31 | ULONG_PTR Next, State; 32 | 33 | _Start: 34 | Value = RunOnce->Ptr; 35 | State = (ULONG_PTR)Value & PS_RUNONCE_STATE_MASK; 36 | if (State == PS_RUNONCE_STATE_INIT) 37 | { 38 | if (_InterlockedCompareExchangePointer(&RunOnce->Ptr, 39 | (PVOID)PS_RUNONCE_STATE_PENDING, 40 | (PVOID)PS_RUNONCE_STATE_INIT) == (PVOID)PS_RUNONCE_STATE_INIT) 41 | { 42 | return TRUE; 43 | } 44 | } else if (State == PS_RUNONCE_STATE_PENDING) 45 | { 46 | Next = (ULONG_PTR)Value & ~PS_RUNONCE_STATE_MASK; 47 | if (_InterlockedCompareExchangePointer(&RunOnce->Ptr, 48 | (PVOID)((ULONG_PTR)&Next | PS_RUNONCE_STATE_PENDING), 49 | Value) == Value) 50 | { 51 | NtWaitForKeyedEvent(NULL, &Next, FALSE, NULL); 52 | } 53 | } else if (State == PS_RUNONCE_STATE_COMPLETED) 54 | { 55 | return FALSE; 56 | } else 57 | { 58 | __fastfail(FAST_FAIL_INVALID_ARG); 59 | } 60 | goto _Start; 61 | } 62 | 63 | FORCEINLINE 64 | VOID 65 | PS_RunOnceEnd( 66 | _Inout_ PPS_RUNONCE RunOnce, 67 | _In_ LOGICAL Complete) 68 | { 69 | PPS_RUNONCE Next, Value; 70 | 71 | _Start: 72 | Value = RunOnce->Ptr; 73 | if (((ULONG_PTR)Value & PS_RUNONCE_STATE_MASK) == PS_RUNONCE_STATE_PENDING) 74 | { 75 | if (_InterlockedCompareExchangePointer((PVOID*)&RunOnce->Ptr, 76 | (PVOID)(ULONG_PTR)(Complete ? PS_RUNONCE_STATE_COMPLETED : PS_RUNONCE_STATE_INIT), 77 | Value) == Value) 78 | { 79 | Value = (PPS_RUNONCE)((ULONG_PTR)Value & ~PS_RUNONCE_STATE_MASK); 80 | while (Value != NULL) 81 | { 82 | Next = Value->Ptr; 83 | NtReleaseKeyedEvent(NULL, Value, FALSE, NULL); 84 | Value = Next; 85 | } 86 | return; 87 | } 88 | } else 89 | { 90 | __fastfail(FAST_FAIL_INVALID_ARG); 91 | } 92 | goto _Start; 93 | } 94 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook/src/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | // Size of each memory slot. 32 | #if defined(_M_X64) || defined(__x86_64__) 33 | #define MEMORY_SLOT_SIZE 64 34 | #else 35 | #define MEMORY_SLOT_SIZE 64 36 | #endif 37 | 38 | VOID InitializeBuffer(VOID); 39 | VOID UninitializeBuffer(VOID); 40 | LPVOID AllocateBuffer(LPVOID pOrigin); 41 | VOID FreeBuffer(LPVOID pBuffer); 42 | BOOL IsExecutableAddress(LPVOID pAddress); 43 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook/src/hde/hde32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 3 | * Copyright (c) 2006-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde32.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE32_H_ 11 | #define _HDE32_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_DISP8 0x00000020 30 | #define F_DISP16 0x00000040 31 | #define F_DISP32 0x00000080 32 | #define F_RELATIVE 0x00000100 33 | #define F_2IMM16 0x00000800 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_ANY 0x3f000000 47 | 48 | #define PREFIX_SEGMENT_CS 0x2e 49 | #define PREFIX_SEGMENT_SS 0x36 50 | #define PREFIX_SEGMENT_DS 0x3e 51 | #define PREFIX_SEGMENT_ES 0x26 52 | #define PREFIX_SEGMENT_FS 0x64 53 | #define PREFIX_SEGMENT_GS 0x65 54 | #define PREFIX_LOCK 0xf0 55 | #define PREFIX_REPNZ 0xf2 56 | #define PREFIX_REPX 0xf3 57 | #define PREFIX_OPERAND_SIZE 0x66 58 | #define PREFIX_ADDRESS_SIZE 0x67 59 | 60 | #pragma pack(push,1) 61 | 62 | typedef struct { 63 | uint8_t len; 64 | uint8_t p_rep; 65 | uint8_t p_lock; 66 | uint8_t p_seg; 67 | uint8_t p_66; 68 | uint8_t p_67; 69 | uint8_t opcode; 70 | uint8_t opcode2; 71 | uint8_t modrm; 72 | uint8_t modrm_mod; 73 | uint8_t modrm_reg; 74 | uint8_t modrm_rm; 75 | uint8_t sib; 76 | uint8_t sib_scale; 77 | uint8_t sib_index; 78 | uint8_t sib_base; 79 | union { 80 | uint8_t imm8; 81 | uint16_t imm16; 82 | uint32_t imm32; 83 | } imm; 84 | union { 85 | uint8_t disp8; 86 | uint16_t disp16; 87 | uint32_t disp32; 88 | } disp; 89 | uint32_t flags; 90 | } hde32s; 91 | 92 | #pragma pack(pop) 93 | 94 | #ifdef __cplusplus 95 | extern "C" { 96 | #endif 97 | 98 | /* __cdecl */ 99 | unsigned int hde32_disasm(const void *code, hde32s *hs); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif /* _HDE32_H_ */ 106 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook/src/hde/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/MinHook/src/hde/pstdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | 31 | // Integer types for HDE. 32 | typedef INT8 int8_t; 33 | typedef INT16 int16_t; 34 | typedef INT32 int32_t; 35 | typedef INT64 int64_t; 36 | typedef UINT8 uint8_t; 37 | typedef UINT16 uint16_t; 38 | typedef UINT32 uint32_t; 39 | typedef UINT64 uint64_t; 40 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/arm64dis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "decode.h" 4 | #include "format.h" 5 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/decode.c: -------------------------------------------------------------------------------- 1 | #include "decode.h" 2 | #include "feature_flags.h" 3 | 4 | int decode_spec(context* ctx, Instruction* dec); // from decode0.cpp 5 | int decode_scratchpad(context* ctx, Instruction* dec); // from decode_scratchpad.c 6 | 7 | int aarch64_decompose(uint32_t instructionValue, Instruction* instr, uint64_t address) 8 | { 9 | context ctx = {0}; 10 | ctx.halted = 1; // enable disassembly of exception instructions like DCPS1 11 | ctx.insword = instructionValue; 12 | ctx.address = address; 13 | ctx.features0 = ARCH_FEATURES_ALL; 14 | ctx.features1 = ARCH_FEATURES_ALL; 15 | ctx.EDSCR_HDE = 1; 16 | 17 | /* have the spec-generated code populate all the pcode variables */ 18 | int rc = decode_spec(&ctx, instr); 19 | 20 | if (rc != DECODE_STATUS_OK) 21 | { 22 | /* exceptional cases where we accept a non-OK decode status */ 23 | if (rc == DECODE_STATUS_END_OF_INSTRUCTION && instr->encoding == ENC_HINT_HM_HINTS) 24 | { 25 | while (0) 26 | ; 27 | } 28 | /* no exception! fail! */ 29 | else 30 | return rc; 31 | } 32 | 33 | /* if UDF encoding, return undefined */ 34 | // if(instr->encoding == ENC_UDF_ONLY_PERM_UNDEF) 35 | // return DECODE_STATUS_UNDEFINED; 36 | 37 | /* convert the pcode variables to list of operands, etc. */ 38 | return decode_scratchpad(&ctx, instr); 39 | } 40 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/decode_fields32.h: -------------------------------------------------------------------------------- 1 | /* GENERATED FILE */ 2 | #pragma once 3 | void decode_fields32(enum ENCODING enc, context *ctx, Instruction *dec); 4 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/decompose_and_disassemble.c: -------------------------------------------------------------------------------- 1 | #include "decompose_and_disassemble.h" 2 | 3 | #include "decode.h" 4 | #include "format.h" 5 | 6 | int aarch64_decompose_and_disassemble(uint64_t address, uint32_t insword, char* result, size_t result_buf_sz) 7 | { 8 | int rc; 9 | Instruction instr; 10 | memset(&instr, 0, sizeof(instr)); 11 | 12 | rc = aarch64_decompose(insword, &instr, address); 13 | if (rc) 14 | return rc; 15 | 16 | rc = aarch64_disassemble(&instr, result, result_buf_sz); 17 | if (rc) 18 | return rc; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/decompose_and_disassemble.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" 7 | { 8 | #endif 9 | 10 | int aarch64_decompose_and_disassemble(uint64_t address, uint32_t insword, char* result, size_t result_buf_sz); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/encodings_fmt.h: -------------------------------------------------------------------------------- 1 | /* GENERATED FILE */ 2 | #pragma once 3 | const char *enc_to_str(enum ENCODING); 4 | const char *enc_to_xml(enum ENCODING); 5 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/format.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "decode.h" 7 | #include "encodings_dec.h" 8 | #include "encodings_fmt.h" 9 | #include "operations.h" 10 | #include "regs.h" 11 | #include "sysregs_fmt_gen.h" 12 | 13 | //----------------------------------------------------------------------------- 14 | // disassembly function prototypes, return values 15 | //----------------------------------------------------------------------------- 16 | 17 | /* these get returned by the disassemble_instruction() function */ 18 | enum FailureCode { 19 | DISASM_SUCCESS=0, 20 | INVALID_ARGUMENTS, 21 | FAILED_TO_DISASSEMBLE_OPERAND, 22 | FAILED_TO_DISASSEMBLE_OPERATION, 23 | FAILED_TO_DISASSEMBLE_REGISTER, 24 | FAILED_TO_DECODE_INSTRUCTION, 25 | OUTPUT_BUFFER_TOO_SMALL, 26 | OPERAND_IS_NOT_REGISTER, 27 | NOT_MEMORY_OPERAND 28 | }; 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | // get a text representation of the decomposed instruction 35 | int aarch64_disassemble(Instruction *instruction, char *buf, size_t buf_sz); 36 | 37 | // register (and related) to string 38 | int get_register_full(enum Register, const InstructionOperand *, char *result); 39 | const char *get_register_arrspec(enum Register, const InstructionOperand *); 40 | 41 | // miscellany to string 42 | const char *get_operation(const Instruction *instruction); 43 | const char *get_shift(ShiftType shift); 44 | const char *get_condition(Condition cond); 45 | uint32_t get_implementation_specific( 46 | const InstructionOperand *operand, 47 | char *outBuffer, 48 | uint32_t outBufferSize); 49 | const char *get_arrspec_str(ArrangementSpec arrspec); 50 | const char *get_arrspec_str_truncated(ArrangementSpec arrspec); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/gofer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "decode.h" 8 | #include "format.h" 9 | 10 | void disassemble(uint64_t addr, uint8_t *data, int len, char *result, bool verbose) 11 | { 12 | Instruction instr; 13 | memset(&instr, 0, sizeof(instr)); 14 | 15 | aarch64_decompose(*(uint32_t *)data, &instr, addr); 16 | 17 | aarch64_disassemble(&instr, result, 1024); 18 | } 19 | 20 | uint32_t get_encoding(uint8_t *data) 21 | { 22 | Instruction instr; 23 | //printf("sizeof(instr): %lu\n", sizeof(instr)); 24 | //printf("sizeof(instr.encoding): %lu\n", sizeof(instr.encoding)); 25 | memset(&instr, 0, sizeof(instr)); 26 | aarch64_decompose(*(uint32_t *)data, &instr, 0); 27 | return instr.encoding; 28 | } 29 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/binaryninja-arm64-disassembler/sysregs_fmt_gen.h: -------------------------------------------------------------------------------- 1 | /* GENERATED FILE - DO NOT MODIFY - SUBMIT GITHUB ISSUE IF PROBLEM FOUND */ 2 | #pragma once 3 | 4 | #include "sysregs_gen.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | const char *get_system_register_name(enum SystemReg); 10 | const char *get_system_register_name_decomposed(int op0, int op1, int CRn, int CRm, int op2); 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/dia/diacreate.h: -------------------------------------------------------------------------------- 1 | // diacreate.h - creation helper functions for DIA initialization 2 | //----------------------------------------------------------------- 3 | // 4 | // Copyright Microsoft Corporation. All Rights Reserved. 5 | // 6 | //--------------------------------------------------------------- 7 | #ifndef _DIACREATE_H_ 8 | #define _DIACREATE_H_ 9 | 10 | // 11 | // Create a dia data source object from the dia dll (by dll name - does not access the registry). 12 | // 13 | 14 | HRESULT STDMETHODCALLTYPE NoRegCoCreate( const __wchar_t *dllName, 15 | REFCLSID rclsid, 16 | REFIID riid, 17 | void **ppv); 18 | 19 | #ifndef _NATIVE_WCHAR_T_DEFINED 20 | #ifdef __cplusplus 21 | 22 | // When compiling with /Zc:wchar_t- this becomes unsigned short overload that maps back to real __wchar_t function 23 | 24 | inline HRESULT STDMETHODCALLTYPE NoRegCoCreate( const wchar_t *dllName, 25 | REFCLSID rclsid, 26 | REFIID riid, 27 | void **ppv) 28 | { 29 | return NoRegCoCreate( (const __wchar_t *)dllName, rclsid, riid, ppv ); 30 | } 31 | 32 | #endif 33 | #endif 34 | 35 | 36 | // 37 | // Create a dia data source object from the dia dll (looks up the class id in the registry). 38 | // 39 | HRESULT STDMETHODCALLTYPE NoOleCoCreate( REFCLSID rclsid, 40 | REFIID riid, 41 | void **ppv); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/dia/lib/amd64/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/engine/libraries/dia/lib/amd64/diaguids.lib -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/dia/lib/arm/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/engine/libraries/dia/lib/arm/diaguids.lib -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/dia/lib/arm64/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/engine/libraries/dia/lib/arm64/diaguids.lib -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/dia/lib/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/engine/libraries/dia/lib/diaguids.lib -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/phnt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(phnt) 4 | 5 | add_library(phnt INTERFACE) 6 | target_include_directories(phnt INTERFACE "${CMAKE_CURRENT_LIST_DIR}") 7 | target_link_libraries(phnt INTERFACE "ntdll.lib") 8 | 9 | add_library(phnt::phnt ALIAS phnt) -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/phnt/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Winsider Seminars & Solutions, Inc. 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 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/phnt/README.md: -------------------------------------------------------------------------------- 1 | This collection of Native API header files has been maintained since 2009 for the System Informer project, and is the most up-to-date set of Native API definitions that we know of. We have gathered these definitions from official Microsoft header files and symbol files, as well as a lot of reverse engineering and guessing. See `phnt.h` for more information. 2 | 3 | ## Usage 4 | 5 | First make sure that your program is using the latest Windows SDK. 6 | 7 | These header files are designed to be used by user-mode programs. Instead of `#include `, place 8 | 9 | ``` 10 | #include 11 | #include 12 | ``` 13 | 14 | at the top of your program. The first line provides access to the Win32 API as well as the `NTSTATUS` values. The second line provides access to the entire Native API. By default, only definitions present in Windows XP are included into your program. To change this, use one of the following: 15 | 16 | ``` 17 | #define PHNT_VERSION PHNT_WINXP // Windows XP 18 | #define PHNT_VERSION PHNT_WS03 // Windows Server 2003 19 | #define PHNT_VERSION PHNT_VISTA // Windows Vista 20 | #define PHNT_VERSION PHNT_WIN7 // Windows 7 21 | #define PHNT_VERSION PHNT_WIN8 // Windows 8 22 | #define PHNT_VERSION PHNT_WINBLUE // Windows 8.1 23 | #define PHNT_VERSION PHNT_THRESHOLD // Windows 10 24 | #define PHNT_VERSION PHNT_WIN11 // Windows 11 25 | ``` 26 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/phnt/ntnls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * National Language Support functions 3 | * 4 | * This file is part of System Informer. 5 | */ 6 | 7 | #ifndef _NTNLS_H 8 | #define _NTNLS_H 9 | 10 | #define MAXIMUM_LEADBYTES 12 11 | 12 | typedef struct _CPTABLEINFO 13 | { 14 | USHORT CodePage; 15 | USHORT MaximumCharacterSize; 16 | USHORT DefaultChar; 17 | USHORT UniDefaultChar; 18 | USHORT TransDefaultChar; 19 | USHORT TransUniDefaultChar; 20 | USHORT DBCSCodePage; 21 | UCHAR LeadByte[MAXIMUM_LEADBYTES]; 22 | PUSHORT MultiByteTable; 23 | PVOID WideCharTable; 24 | PUSHORT DBCSRanges; 25 | PUSHORT DBCSOffsets; 26 | } CPTABLEINFO, *PCPTABLEINFO; 27 | 28 | typedef struct _NLSTABLEINFO 29 | { 30 | CPTABLEINFO OemTableInfo; 31 | CPTABLEINFO AnsiTableInfo; 32 | PUSHORT UpperCaseTable; 33 | PUSHORT LowerCaseTable; 34 | } NLSTABLEINFO, *PNLSTABLEINFO; 35 | 36 | #if (PHNT_MODE != PHNT_MODE_KERNEL) 37 | NTSYSAPI USHORT NlsAnsiCodePage; 38 | NTSYSAPI BOOLEAN NlsMbCodePageTag; 39 | NTSYSAPI BOOLEAN NlsMbOemCodePageTag; 40 | #endif // (PHNT_MODE != PHNT_MODE_KERNEL) 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/phnt/subprocesstag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Subprocess tag information 3 | * 4 | * This file is part of System Informer. 5 | */ 6 | 7 | #ifndef _SUBPROCESSTAG_H 8 | #define _SUBPROCESSTAG_H 9 | 10 | typedef enum _TAG_INFO_LEVEL 11 | { 12 | eTagInfoLevelNameFromTag = 1, // TAG_INFO_NAME_FROM_TAG 13 | eTagInfoLevelNamesReferencingModule, // TAG_INFO_NAMES_REFERENCING_MODULE 14 | eTagInfoLevelNameTagMapping, // TAG_INFO_NAME_TAG_MAPPING 15 | eTagInfoLevelMax 16 | } TAG_INFO_LEVEL; 17 | 18 | typedef enum _TAG_TYPE 19 | { 20 | eTagTypeService = 1, 21 | eTagTypeMax 22 | } TAG_TYPE; 23 | 24 | typedef struct _TAG_INFO_NAME_FROM_TAG_IN_PARAMS 25 | { 26 | ULONG ProcessId; 27 | ULONG ServiceTag; 28 | } TAG_INFO_NAME_FROM_TAG_IN_PARAMS, *PTAG_INFO_NAME_FROM_TAG_IN_PARAMS; 29 | 30 | typedef struct _TAG_INFO_NAME_FROM_TAG_OUT_PARAMS 31 | { 32 | ULONG TagType; 33 | PCWSTR Name; 34 | } TAG_INFO_NAME_FROM_TAG_OUT_PARAMS, *PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS; 35 | 36 | typedef struct _TAG_INFO_NAME_FROM_TAG 37 | { 38 | TAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams; 39 | TAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutParams; 40 | } TAG_INFO_NAME_FROM_TAG, *PTAG_INFO_NAME_FROM_TAG; 41 | 42 | typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS 43 | { 44 | ULONG ProcessId; 45 | PCWSTR ModuleName; 46 | } TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS, *PTAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS; 47 | 48 | typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS 49 | { 50 | ULONG TagType; 51 | PCWSTR Names; 52 | } TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS, *PTAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS; 53 | 54 | typedef struct _TAG_INFO_NAMES_REFERENCING_MODULE 55 | { 56 | TAG_INFO_NAMES_REFERENCING_MODULE_IN_PARAMS InParams; 57 | TAG_INFO_NAMES_REFERENCING_MODULE_OUT_PARAMS OutParams; 58 | } TAG_INFO_NAMES_REFERENCING_MODULE, *PTAG_INFO_NAMES_REFERENCING_MODULE; 59 | 60 | typedef struct _TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS 61 | { 62 | ULONG ProcessId; 63 | } TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS, *PTAG_INFO_NAME_TAG_MAPPING_IN_PARAMS; 64 | 65 | typedef struct _TAG_INFO_NAME_TAG_MAPPING_ELEMENT 66 | { 67 | ULONG TagType; 68 | ULONG Tag; 69 | PCWSTR Name; 70 | PCWSTR GroupName; 71 | } TAG_INFO_NAME_TAG_MAPPING_ELEMENT, *PTAG_INFO_NAME_TAG_MAPPING_ELEMENT; 72 | 73 | typedef struct _TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS 74 | { 75 | ULONG Count; 76 | PTAG_INFO_NAME_TAG_MAPPING_ELEMENT NameTagMappingElements; 77 | } TAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS, *PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS; 78 | 79 | typedef struct _TAG_INFO_NAME_TAG_MAPPING 80 | { 81 | TAG_INFO_NAME_TAG_MAPPING_IN_PARAMS InParams; 82 | PTAG_INFO_NAME_TAG_MAPPING_OUT_PARAMS pOutParams; 83 | } TAG_INFO_NAME_TAG_MAPPING, *PTAG_INFO_NAME_TAG_MAPPING; 84 | 85 | _Must_inspect_result_ 86 | NTSYSAPI 87 | ULONG 88 | NTAPI 89 | I_QueryTagInformation( 90 | _In_opt_ PCWSTR MachineName, 91 | _In_ TAG_INFO_LEVEL InfoLevel, 92 | _Inout_ PVOID TagInfo 93 | ); 94 | 95 | typedef _Function_class_(QUERY_TAG_INFORMATION) 96 | ULONG NTAPI QUERY_TAG_INFORMATION( 97 | _In_opt_ PCWSTR MachineName, 98 | _In_ TAG_INFO_LEVEL InfoLevel, 99 | _Inout_ PVOID TagInfo 100 | ); 101 | typedef QUERY_TAG_INFORMATION *PQUERY_TAG_INFORMATION; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/Memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * KNSoft.SlimDetours (https://github.com/KNSoft/KNSoft.SlimDetours) Memory Management 3 | * Copyright (c) KNSoft.org (https://github.com/KNSoft). All rights reserved. 4 | * Licensed under the MIT license. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "Memory.h" 11 | 12 | static HANDLE _threadscan_memory_heap = NULL; 13 | 14 | static 15 | _Ret_notnull_ 16 | HANDLE 17 | threadscan_memory_init(VOID) 18 | { 19 | HANDLE hHeap; 20 | 21 | /* Initialize private heap */ 22 | hHeap = RtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); 23 | if (hHeap == NULL) 24 | { 25 | //DETOUR_TRACE("RtlCreateHeap failed, fallback to use process default heap\n"); 26 | hHeap = NtCurrentPeb()->ProcessHeap; 27 | } 28 | 29 | return hHeap; 30 | } 31 | 32 | _Must_inspect_result_ 33 | _Ret_maybenull_ 34 | _Post_writable_byte_size_(Size) 35 | PVOID 36 | threadscan_memory_alloc( 37 | _In_ SIZE_T Size) 38 | { 39 | /* 40 | * threadscan_memory_alloc is called BEFORE any other threadscan_memory_* functions, 41 | * and only one thread that owning pending transaction could reach here, 42 | * so it's safe to do the initialzation here and not use a lock. 43 | */ 44 | if (_threadscan_memory_heap == NULL) 45 | { 46 | _threadscan_memory_heap = threadscan_memory_init(); 47 | } 48 | 49 | return RtlAllocateHeap(_threadscan_memory_heap, 0, Size); 50 | } 51 | 52 | _Must_inspect_result_ 53 | _Ret_maybenull_ 54 | _Post_writable_byte_size_(Size) 55 | PVOID 56 | threadscan_memory_realloc( 57 | _Frees_ptr_opt_ PVOID BaseAddress, 58 | _In_ SIZE_T Size) 59 | { 60 | return RtlReAllocateHeap(_threadscan_memory_heap, 0, BaseAddress, Size); 61 | } 62 | 63 | BOOL 64 | threadscan_memory_free( 65 | _Frees_ptr_ PVOID BaseAddress) 66 | { 67 | return RtlFreeHeap(_threadscan_memory_heap, 0, BaseAddress); 68 | } 69 | 70 | BOOL 71 | threadscan_memory_uninitialize(VOID) 72 | { 73 | if (_threadscan_memory_heap != NULL && _threadscan_memory_heap != NtCurrentPeb()->ProcessHeap) 74 | { 75 | _threadscan_memory_heap = RtlDestroyHeap(_threadscan_memory_heap); 76 | return _threadscan_memory_heap == NULL; 77 | } 78 | 79 | return TRUE; 80 | } 81 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/Memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | _Must_inspect_result_ 4 | _Ret_maybenull_ 5 | _Post_writable_byte_size_(Size) 6 | PVOID 7 | threadscan_memory_alloc( 8 | _In_ SIZE_T Size); 9 | 10 | _Must_inspect_result_ 11 | _Ret_maybenull_ 12 | _Post_writable_byte_size_(Size) 13 | PVOID 14 | threadscan_memory_realloc( 15 | _Frees_ptr_opt_ PVOID BaseAddress, 16 | _In_ SIZE_T Size); 17 | 18 | BOOL 19 | threadscan_memory_free( 20 | _Frees_ptr_ PVOID BaseAddress); 21 | 22 | BOOL 23 | threadscan_memory_uninitialize(VOID); 24 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/Thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | NTSTATUS 4 | threadscan_thread_suspend( 5 | _Outptr_result_maybenull_ PHANDLE* SuspendedHandles, 6 | _Out_ PULONG SuspendedHandleCount, 7 | _In_ ULONG ThreadIdToSkip); 8 | 9 | VOID 10 | threadscan_thread_resume( 11 | _In_reads_(SuspendedHandleCount) PHANDLE SuspendedHandles, 12 | _In_ ULONG SuspendedHandleCount); 13 | 14 | VOID 15 | threadscan_thread_free( 16 | _In_reads_(SuspendedHandleCount) _Frees_ptr_ PHANDLE SuspendedHandles, 17 | _In_ ULONG SuspendedHandleCount); 18 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/ThreadsCallStackIterate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef BOOL(*ThreadCallStackIterCallback)( 4 | HANDLE threadHandle, 5 | void* stackFrameAddress, 6 | void* userData); 7 | 8 | // Iterates over the call stacks of all threads and calls the callback for each 9 | // stack frame address. The callback should return TRUE to continue iterating 10 | // or FALSE to stop iterating. The callback might be called from a different 11 | // thread than the one that called this function. 12 | // 13 | // The function will suspend all threads and resume them after the iteration is 14 | // done. Therefore, the callback must be careful not to acquire any locks, 15 | // including indirectly by e.g. using the process heap. 16 | BOOL ThreadsCallStackIterate( 17 | ThreadCallStackIterCallback callback, 18 | void* userData, 19 | DWORD timeout); 20 | 21 | void ThreadsCallStackCleanup(); 22 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/ThreadsCallStackWaitForRegions.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ThreadsCallStackWaitForRegions.h" 4 | 5 | #include "ThreadsCallStackIterate.h" 6 | 7 | typedef struct { 8 | const ThreadCallStackRegionInfo* regionInfos; 9 | DWORD regionInfosCount; 10 | BOOL found; 11 | } ThreadCallStackIterateParam; 12 | 13 | static BOOL ThreadCallStackIterateProc(HANDLE threadHandle, void* stackFrameAddress, void* userData) { 14 | ThreadCallStackIterateParam* param = (ThreadCallStackIterateParam*)userData; 15 | 16 | const ThreadCallStackRegionInfo* regionInfos = param->regionInfos; 17 | DWORD regionInfosCount = param->regionInfosCount; 18 | 19 | for (DWORD i = 0; i < regionInfosCount; i++) { 20 | DWORD_PTR address = regionInfos[i].address; 21 | DWORD_PTR size = regionInfos[i].size; 22 | if ((DWORD_PTR)stackFrameAddress >= address && 23 | (DWORD_PTR)stackFrameAddress < address + size) { 24 | param->found = TRUE; 25 | return FALSE; // Stop iterating 26 | } 27 | } 28 | 29 | return TRUE; // Continue iterating 30 | } 31 | 32 | BOOL ThreadsCallStackWaitForRegions( 33 | const ThreadCallStackRegionInfo* regionInfos, 34 | DWORD regionInfosCount, 35 | DWORD maxIterations, 36 | DWORD timeoutPerIteration) { 37 | ThreadCallStackIterateParam param = { 38 | .regionInfos = regionInfos, 39 | .regionInfosCount = regionInfosCount, 40 | }; 41 | BOOL result = FALSE; 42 | 43 | for (DWORD i = 0; i < maxIterations; i++) { 44 | DWORD startTime = GetTickCount(); 45 | 46 | param.found = FALSE; 47 | if (ThreadsCallStackIterate(ThreadCallStackIterateProc, ¶m, timeoutPerIteration) && !param.found) { 48 | result = TRUE; 49 | break; 50 | } 51 | 52 | if (i < maxIterations - 1) { 53 | DWORD elapsedTime = GetTickCount() - startTime; 54 | if (elapsedTime < timeoutPerIteration) { 55 | Sleep(timeoutPerIteration - elapsedTime); 56 | } 57 | } 58 | } 59 | 60 | ThreadsCallStackCleanup(); 61 | 62 | return result; 63 | } 64 | -------------------------------------------------------------------------------- /src/windhawk/engine/libraries/thread-call-stack-scanner/ThreadsCallStackWaitForRegions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct { 4 | DWORD_PTR address; 5 | DWORD_PTR size; 6 | } ThreadCallStackRegionInfo; 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | // Iterates over the call stacks of all threads and waits until no address is 13 | // within any of the specified regions. Can be used to wait for a specific 14 | // module to stop executing in order to safely unload it. 15 | BOOL ThreadsCallStackWaitForRegions( 16 | const ThreadCallStackRegionInfo* regionInfos, 17 | DWORD regionInfosCount, 18 | DWORD maxIterations, 19 | DWORD timeoutPerIteration); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /src/windhawk/engine/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "logger.h" 4 | #include "storage_manager.h" 5 | #include "var_init_once.h" 6 | 7 | namespace { 8 | 9 | Logger::Verbosity GetVerbosityFromConfig() { 10 | try { 11 | auto settings = StorageManager::GetInstance().GetAppConfig(L"Settings"); 12 | int verbosity = settings->GetInt(L"LoggingVerbosity").value_or(0); 13 | 14 | switch (verbosity) { 15 | case static_cast(Logger::Verbosity::kOff): 16 | return Logger::Verbosity::kOff; 17 | 18 | case static_cast(Logger::Verbosity::kOn): 19 | return Logger::Verbosity::kOn; 20 | 21 | case static_cast(Logger::Verbosity::kVerbose): 22 | return Logger::Verbosity::kVerbose; 23 | } 24 | } catch (const std::exception&) { 25 | // Ignore and use default settings. We can't log it, anyway. 26 | } 27 | 28 | return Logger::kDefaultVerbosity; 29 | } 30 | 31 | } // namespace 32 | 33 | Logger::ScopedThreadVerbosity::ScopedThreadVerbosity(Verbosity verbosity) { 34 | m_inUse = GetInstance().SetThreadVerbosity(verbosity); 35 | } 36 | 37 | Logger::ScopedThreadVerbosity::~ScopedThreadVerbosity() { 38 | if (m_inUse) { 39 | GetInstance().ResetThreadVerbosity(); 40 | } 41 | } 42 | 43 | Logger::Logger(Verbosity initialVerbosity) 44 | : m_initialVerbosity(initialVerbosity), LoggerBase(initialVerbosity) {} 45 | 46 | // static 47 | Logger& Logger::GetInstance() { 48 | STATIC_INIT_ONCE(Logger, s, GetVerbosityFromConfig()); 49 | return *s; 50 | } 51 | 52 | bool Logger::ShouldLog(Verbosity verbosity) { 53 | auto& threadVerbosity = GetThreadVerbosity(); 54 | return threadVerbosity ? *threadVerbosity >= verbosity 55 | : m_initialVerbosity >= verbosity; 56 | } 57 | 58 | // static 59 | std::optional& Logger::GetThreadVerbosity() { 60 | STATIC_INIT_ONCE(ThreadLocal>, s); 61 | return *s; 62 | } 63 | 64 | bool Logger::SetThreadVerbosity(Verbosity verbosity) { 65 | auto& threadVerbosity = GetThreadVerbosity(); 66 | if (threadVerbosity) { 67 | // Only one ScopedThreadVerbosity is supported at a time. 68 | return false; 69 | } 70 | 71 | threadVerbosity = verbosity; 72 | 73 | std::lock_guard guard(m_threadVerbosityMutex); 74 | 75 | m_threadVerbosityCount++; 76 | 77 | if (GetVerbosity() < verbosity) { 78 | SetVerbosity(verbosity); 79 | } 80 | 81 | return true; 82 | } 83 | 84 | void Logger::ResetThreadVerbosity() { 85 | auto& threadVerbosity = GetThreadVerbosity(); 86 | threadVerbosity.reset(); 87 | 88 | std::lock_guard guard(m_threadVerbosityMutex); 89 | 90 | if (--m_threadVerbosityCount == 0) { 91 | SetVerbosity(m_initialVerbosity); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/windhawk/engine/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logger_base.h" 4 | 5 | class Logger : public LoggerBase { 6 | public: 7 | // Use to temporarily change the verbosity of the current thread. 8 | class ScopedThreadVerbosity { 9 | public: 10 | ScopedThreadVerbosity(Verbosity verbosity); 11 | ~ScopedThreadVerbosity(); 12 | 13 | ScopedThreadVerbosity(const ScopedThreadVerbosity&) = delete; 14 | ScopedThreadVerbosity(ScopedThreadVerbosity&&) = delete; 15 | ScopedThreadVerbosity& operator=(const ScopedThreadVerbosity&) = delete; 16 | ScopedThreadVerbosity& operator=(ScopedThreadVerbosity&&) = delete; 17 | 18 | private: 19 | bool m_inUse = false; 20 | }; 21 | 22 | Logger(Verbosity initialVerbosity); 23 | 24 | static Logger& GetInstance(); 25 | 26 | bool ShouldLog(Verbosity verbosity); 27 | 28 | private: 29 | static std::optional& GetThreadVerbosity(); 30 | bool SetThreadVerbosity(Verbosity verbosity); 31 | void ResetThreadVerbosity(); 32 | 33 | const std::atomic m_initialVerbosity; 34 | std::mutex m_threadVerbosityMutex; 35 | int m_threadVerbosityCount = 0; 36 | }; 37 | 38 | #define LOG_WITH_VERBOSITY(verbosity, message, ...) \ 39 | do { \ 40 | auto& inst = Logger::GetInstance(); \ 41 | if (inst.GetVerbosity() >= verbosity && inst.ShouldLog(verbosity)) { \ 42 | inst.LogLine(L"[WH] [%S]: " message L"\n", __FUNCTION__, \ 43 | __VA_ARGS__); \ 44 | } \ 45 | } while (0) 46 | 47 | #define LOG(message, ...) \ 48 | LOG_WITH_VERBOSITY(Logger::Verbosity::kOn, message, __VA_ARGS__) 49 | #define VERBOSE(message, ...) \ 50 | LOG_WITH_VERBOSITY(Logger::Verbosity::kVerbose, message, __VA_ARGS__) 51 | -------------------------------------------------------------------------------- /src/windhawk/engine/mods_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mod.h" 4 | 5 | class ModsManager { 6 | public: 7 | ModsManager(); 8 | ~ModsManager(); 9 | 10 | ModsManager(const ModsManager&) = delete; 11 | ModsManager& operator=(const ModsManager&) = delete; 12 | 13 | void AfterInit(); 14 | void BeforeUninit(); 15 | void ReloadModsAndSettings(); 16 | 17 | private: 18 | std::unordered_map m_mods; 19 | }; 20 | -------------------------------------------------------------------------------- /src/windhawk/engine/new_process_injector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class NewProcessInjector { 4 | public: 5 | NewProcessInjector(HANDLE hSessionManagerProcess); 6 | ~NewProcessInjector(); 7 | 8 | // Disable copying and moving to keep using the same counter variable. 9 | NewProcessInjector(const NewProcessInjector&) = delete; 10 | NewProcessInjector(NewProcessInjector&&) noexcept = delete; 11 | NewProcessInjector& operator=(const NewProcessInjector&) = delete; 12 | NewProcessInjector& operator=(NewProcessInjector&&) noexcept = delete; 13 | 14 | private: 15 | using CreateProcessInternalW_t = 16 | BOOL(WINAPI*)(HANDLE hToken, 17 | LPCWSTR lpApplicationName, 18 | LPWSTR lpCommandLine, 19 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 20 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 21 | BOOL bInheritHandles, 22 | DWORD dwCreationFlags, 23 | LPVOID lpEnvironment, 24 | LPCWSTR lpCurrentDirectory, 25 | LPSTARTUPINFOW lpStartupInfo, 26 | LPPROCESS_INFORMATION lpProcessInformation, 27 | DWORD_PTR unknown); 28 | 29 | static BOOL WINAPI 30 | CreateProcessInternalW_Hook(HANDLE hToken, 31 | LPCWSTR lpApplicationName, 32 | LPWSTR lpCommandLine, 33 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 34 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 35 | BOOL bInheritHandles, 36 | DWORD dwCreationFlags, 37 | LPVOID lpEnvironment, 38 | LPCWSTR lpCurrentDirectory, 39 | LPSTARTUPINFOW lpStartupInfo, 40 | LPPROCESS_INFORMATION lpProcessInformation, 41 | DWORD_PTR unknown); 42 | void HandleCreatedProcess(LPPROCESS_INFORMATION lpProcessInformation); 43 | bool ShouldSkipNewProcess(HANDLE hProcess, 44 | DWORD dwProcessId, 45 | bool* threadAttachExempt); 46 | 47 | // Limited to a single instance at a time. 48 | static std::atomic m_pThis; 49 | 50 | HANDLE m_sessionManagerProcess; 51 | CreateProcessInternalW_t m_originalCreateProcessInternalW = nullptr; 52 | std::atomic m_hookProcCallCounter = 0; 53 | std::wstring m_includePattern; 54 | std::wstring m_excludePattern; 55 | std::wstring m_threadAttachExemptPattern; 56 | }; 57 | -------------------------------------------------------------------------------- /src/windhawk/engine/no_destructor.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "no_destructor.h" 4 | 5 | // static 6 | std::atomic NoDestructorIfTerminatingBase::m_is_terminating = false; 7 | -------------------------------------------------------------------------------- /src/windhawk/engine/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by rsrc.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /src/windhawk/engine/rsrc.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United States) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | LANGUAGE 9, 1 20 | 21 | #ifdef APSTUDIO_INVOKED 22 | ///////////////////////////////////////////////////////////////////////////// 23 | // 24 | // TEXTINCLUDE 25 | // 26 | 27 | 1 TEXTINCLUDE 28 | BEGIN 29 | "resource.h\0" 30 | END 31 | 32 | 2 TEXTINCLUDE 33 | BEGIN 34 | "#include ""winres.h""\r\n" 35 | "\0" 36 | END 37 | 38 | 3 TEXTINCLUDE 39 | BEGIN 40 | "#include ""rsrc.rc2""\r\n" 41 | "\0" 42 | END 43 | 44 | #endif // APSTUDIO_INVOKED 45 | 46 | #endif // English (United States) resources 47 | ///////////////////////////////////////////////////////////////////////////// 48 | 49 | 50 | 51 | #ifndef APSTUDIO_INVOKED 52 | ///////////////////////////////////////////////////////////////////////////// 53 | // 54 | // Generated from the TEXTINCLUDE 3 resource. 55 | // 56 | #include "rsrc.rc2" 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | #endif // not APSTUDIO_INVOKED 60 | -------------------------------------------------------------------------------- /src/windhawk/engine/rsrc.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramensoftware/windhawk/69e9a419161654afd85baf42a8ac5a8b2e2bdebd/src/windhawk/engine/rsrc.rc2 -------------------------------------------------------------------------------- /src/windhawk/engine/session_private_namespace.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "functions.h" 4 | #include "session_private_namespace.h" 5 | 6 | namespace { 7 | 8 | constexpr auto kBoundaryDescriptorName = L"Windhawk"; 9 | 10 | wil::unique_boundary_descriptor BuildBoundaryDescriptor() { 11 | wil::unique_boundary_descriptor boundaryDesc( 12 | CreateBoundaryDescriptor(kBoundaryDescriptorName, 0)); 13 | THROW_LAST_ERROR_IF_NULL(boundaryDesc); 14 | 15 | { 16 | wil::unique_sid pSID; 17 | SID_IDENTIFIER_AUTHORITY SIDWorldAuth = SECURITY_WORLD_SID_AUTHORITY; 18 | THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid( 19 | &SIDWorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID)); 20 | 21 | THROW_IF_WIN32_BOOL_FALSE( 22 | AddSIDToBoundaryDescriptor(boundaryDesc.addressof(), pSID.get())); 23 | } 24 | 25 | { 26 | wil::unique_sid pSID; 27 | SID_IDENTIFIER_AUTHORITY SIDMandatoryLabelAuth = 28 | SECURITY_MANDATORY_LABEL_AUTHORITY; 29 | THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid( 30 | &SIDMandatoryLabelAuth, 1, SECURITY_MANDATORY_MEDIUM_RID, 0, 0, 0, 31 | 0, 0, 0, 0, &pSID)); 32 | 33 | THROW_IF_WIN32_BOOL_FALSE(AddIntegrityLabelToBoundaryDescriptor( 34 | boundaryDesc.addressof(), pSID.get())); 35 | } 36 | 37 | return boundaryDesc; 38 | } 39 | 40 | } // namespace 41 | 42 | namespace SessionPrivateNamespace { 43 | 44 | int MakeName(WCHAR szPrivateNamespaceName[kPrivateNamespaceMaxLen + 1], 45 | DWORD dwSessionManagerProcessId) noexcept { 46 | static_assert(kPrivateNamespaceMaxLen + 1 == 47 | sizeof("WindhawkSession1234567890")); 48 | return swprintf_s(szPrivateNamespaceName, kPrivateNamespaceMaxLen + 1, 49 | L"WindhawkSession%u", dwSessionManagerProcessId); 50 | } 51 | 52 | wil::unique_private_namespace_destroy Create(DWORD dwSessionManagerProcessId) { 53 | wil::unique_boundary_descriptor boundaryDesc(BuildBoundaryDescriptor()); 54 | 55 | wil::unique_hlocal secDesc; 56 | THROW_IF_WIN32_BOOL_FALSE( 57 | Functions::GetFullAccessSecurityDescriptor(&secDesc, nullptr)); 58 | 59 | SECURITY_ATTRIBUTES secAttr = {sizeof(SECURITY_ATTRIBUTES)}; 60 | secAttr.lpSecurityDescriptor = secDesc.get(); 61 | secAttr.bInheritHandle = FALSE; 62 | 63 | WCHAR szPrivateNamespaceName[kPrivateNamespaceMaxLen + 1]; 64 | MakeName(szPrivateNamespaceName, dwSessionManagerProcessId); 65 | 66 | wil::unique_private_namespace_destroy privateNamespace( 67 | CreatePrivateNamespace(&secAttr, (void*)boundaryDesc.get(), 68 | szPrivateNamespaceName)); 69 | THROW_LAST_ERROR_IF_NULL(privateNamespace); 70 | 71 | return privateNamespace; 72 | } 73 | 74 | wil::unique_private_namespace_close Open(DWORD dwSessionManagerProcessId) { 75 | wil::unique_boundary_descriptor boundaryDesc(BuildBoundaryDescriptor()); 76 | 77 | WCHAR szPrivateNamespaceName[kPrivateNamespaceMaxLen + 1]; 78 | MakeName(szPrivateNamespaceName, dwSessionManagerProcessId); 79 | 80 | wil::unique_private_namespace_close privateNamespace(OpenPrivateNamespace( 81 | (void*)boundaryDesc.get(), szPrivateNamespaceName)); 82 | THROW_LAST_ERROR_IF_NULL(privateNamespace); 83 | 84 | return privateNamespace; 85 | } 86 | 87 | } // namespace SessionPrivateNamespace 88 | -------------------------------------------------------------------------------- /src/windhawk/engine/session_private_namespace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace SessionPrivateNamespace { 4 | 5 | constexpr size_t kPrivateNamespaceMaxLen = 6 | sizeof("WindhawkSession1234567890") - 1; 7 | 8 | int MakeName(WCHAR szPrivateNamespaceName[kPrivateNamespaceMaxLen + 1], 9 | DWORD dwSessionManagerProcessId) noexcept; 10 | wil::unique_private_namespace_destroy Create(DWORD dwSessionManagerProcessId); 11 | wil::unique_private_namespace_close Open(DWORD dwSessionManagerProcessId); 12 | 13 | } // namespace SessionPrivateNamespace 14 | -------------------------------------------------------------------------------- /src/windhawk/engine/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /src/windhawk/engine/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WINVER _WIN32_WINNT_WIN7 4 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 5 | #define _WIN32_IE _WIN32_IE_IE80 6 | #define NTDDI_VERSION NTDDI_WIN7 7 | 8 | #define WIN32_LEAN_AND_MEAN 9 | #define NOMINMAX 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // STL 20 | 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 | // Libraries 44 | 45 | #include 46 | #include 47 | 48 | #include 49 | 50 | #define TLS_NO_DEBUG 51 | #include 52 | 53 | #include // must be included before other wil includes 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #ifdef _M_IX86 62 | #include 63 | #endif 64 | 65 | // Disasm engine 66 | 67 | #if defined(_M_IX86) || defined(_M_X64) 68 | #include 69 | #elif defined(_M_ARM64) 70 | #include 71 | #endif 72 | 73 | // Hooking engine 74 | 75 | #if defined(_M_IX86) || defined(_M_X64) 76 | #define WH_HOOKING_ENGINE_MINHOOK 77 | #include 78 | #elif defined(_M_ARM64) 79 | #define WH_HOOKING_ENGINE_MINHOOK 80 | #define WH_HOOKING_ENGINE_MINHOOK_DETOURS 81 | #include 82 | #else 83 | #error "This option is only for testing" 84 | #endif 85 | -------------------------------------------------------------------------------- /src/windhawk/engine/storage_manager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "no_destructor.h" 4 | #include "portable_settings.h" 5 | 6 | class StorageManager { 7 | public: 8 | StorageManager(const StorageManager&) = delete; 9 | StorageManager(StorageManager&&) = delete; 10 | StorageManager& operator=(const StorageManager&) = delete; 11 | StorageManager& operator=(StorageManager&&) = delete; 12 | 13 | static StorageManager& GetInstance(); 14 | 15 | std::unique_ptr GetAppConfig(PCWSTR section); 16 | std::unique_ptr GetModConfig(PCWSTR modName, 17 | PCWSTR section); 18 | std::unique_ptr GetModWritableConfig(PCWSTR modName, 19 | PCWSTR section, 20 | bool write); 21 | void EnumMods(std::function enumCallback); 22 | 23 | std::filesystem::path GetModStoragePath(PCWSTR modName); 24 | 25 | std::filesystem::path GetModMetadataPath(PCWSTR metadataCategory); 26 | wil::unique_hfile CreateModMetadataFile(PCWSTR metadataCategory, 27 | PCWSTR modInstanceId); 28 | void SetModMetadataValue(wil::unique_hfile& file, PCWSTR value); 29 | 30 | std::filesystem::path GetEnginePath( 31 | USHORT machine = IMAGE_FILE_MACHINE_UNKNOWN); 32 | std::filesystem::path GetModsPath( 33 | USHORT machine = IMAGE_FILE_MACHINE_UNKNOWN); 34 | std::filesystem::path GetSymbolsPath(); 35 | 36 | class ModConfigChangeNotification { 37 | public: 38 | ModConfigChangeNotification(); 39 | 40 | HANDLE GetHandle(); 41 | void ContinueMonitoring(); 42 | bool CanMonitorAcrossThreads(); 43 | 44 | private: 45 | struct RegistryState { 46 | wil::unique_hkey key; 47 | DWORD regNotifyChangeKeyValueFlags; 48 | wil::unique_event_nothrow eventHandle; 49 | }; 50 | 51 | struct IniFileState { 52 | wil::unique_hfind_change handle; 53 | }; 54 | 55 | std::variant 56 | monitoringState; 57 | }; 58 | 59 | private: 60 | friend class NoDestructorIfTerminating; 61 | 62 | StorageManager(); 63 | ~StorageManager(); 64 | 65 | void RegistryEnumMods(std::function enumCallback); 66 | void IniFilesEnumMods(std::function enumCallback); 67 | 68 | struct RegistryPath { 69 | HKEY hKey = 0; 70 | std::wstring subKey; 71 | }; 72 | 73 | struct IniFilePath { 74 | std::wstring path; 75 | }; 76 | 77 | bool portableStorage; 78 | std::filesystem::path appDataPath; 79 | std::variant settingsPath; 80 | }; 81 | -------------------------------------------------------------------------------- /src/windhawk/engine/symbol_enum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void MySysFreeString(BSTR bstrString); 4 | 5 | using my_unique_bstr = 6 | wil::unique_any; 7 | 8 | class SymbolEnum { 9 | public: 10 | enum class UndecorateMode { 11 | Default = 0, 12 | OldVersionCompatible, 13 | None, 14 | }; 15 | 16 | struct Callbacks { 17 | std::function queryCancel; 18 | std::function notifyProgress; 19 | }; 20 | 21 | SymbolEnum(HMODULE moduleBase, 22 | PCWSTR symbolServer, 23 | UndecorateMode undecorateMode, 24 | Callbacks callbacks = {}); 25 | SymbolEnum(PCWSTR modulePath, 26 | HMODULE moduleBase, 27 | PCWSTR symbolServer, 28 | UndecorateMode undecorateMode, 29 | Callbacks callbacks = {}); 30 | 31 | struct Symbol { 32 | void* address; 33 | PCWSTR name; 34 | PCWSTR nameUndecorated; 35 | }; 36 | 37 | std::optional GetNextSymbol(); 38 | 39 | // https://ntdoc.m417z.com/image_chpe_range_entry 40 | typedef struct _IMAGE_CHPE_RANGE_ENTRY { 41 | union { 42 | ULONG StartOffset; 43 | struct { 44 | ULONG NativeCode : 1; 45 | ULONG AddressBits : 31; 46 | } DUMMYSTRUCTNAME; 47 | } DUMMYUNIONNAME; 48 | 49 | ULONG Length; 50 | } IMAGE_CHPE_RANGE_ENTRY, *PIMAGE_CHPE_RANGE_ENTRY; 51 | 52 | private: 53 | void InitModuleInfo(HMODULE module); 54 | wil::com_ptr LoadMsdia(); 55 | 56 | static constexpr enum SymTagEnum kSymTags[] = { 57 | SymTagPublicSymbol, 58 | SymTagFunction, 59 | SymTagData, 60 | }; 61 | 62 | struct ModuleInfo { 63 | WORD magic; 64 | bool isHybrid; 65 | std::vector chpeRanges; 66 | }; 67 | 68 | HMODULE m_moduleBase; 69 | UndecorateMode m_undecorateMode; 70 | ModuleInfo m_moduleInfo; 71 | wil::unique_hmodule m_msdiaModule; 72 | wil::com_ptr m_diaGlobal; 73 | wil::com_ptr m_diaSymbols; 74 | size_t m_symTagIndex = 0; 75 | my_unique_bstr m_currentSymbolName; 76 | my_unique_bstr m_currentSymbolNameUndecorated; 77 | std::wstring m_currentSymbolNameUndecoratedWithPrefixes; 78 | }; 79 | -------------------------------------------------------------------------------- /src/windhawk/shared/libraries/wil/_version.txt: -------------------------------------------------------------------------------- 1 | https://github.com/microsoft/wil/tree/v1.0.250325.1 2 | -------------------------------------------------------------------------------- /src/windhawk/shared/libraries/wil/cppwinrt_notifiable_module_lock.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License. 5 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 6 | // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 7 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 8 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | // 10 | //********************************************************* 11 | //! @file 12 | //! Utilities for implementing OOP COM server with cppwinrt only 13 | 14 | #ifndef __WIL_CPPWINRT_NOTIFIABLE_MODULE_LOCK_INCLUDED 15 | #define __WIL_CPPWINRT_NOTIFIABLE_MODULE_LOCK_INCLUDED 16 | 17 | #ifdef WINRT_BASE_H 18 | #error You must include this header before including any winrt header 19 | #endif 20 | 21 | #ifndef WINRT_CUSTOM_MODULE_LOCK 22 | #error You must define 'WINRT_CUSTOM_MODULE_LOCK' at the project level 23 | #endif 24 | 25 | #include 26 | #include 27 | 28 | namespace wil 29 | { 30 | // Adopted from cppwinrt 31 | struct notifiable_module_lock_base 32 | { 33 | notifiable_module_lock_base() = default; 34 | 35 | notifiable_module_lock_base(uint32_t count) : m_count(count) 36 | { 37 | } 38 | 39 | uint32_t operator=(uint32_t count) noexcept 40 | { 41 | return m_count = count; 42 | } 43 | 44 | uint32_t operator++() noexcept 45 | { 46 | return m_count.fetch_add(1, std::memory_order_relaxed) + 1; 47 | } 48 | 49 | uint32_t operator--() noexcept 50 | { 51 | auto const remaining = m_count.fetch_sub(1, std::memory_order_release) - 1; 52 | 53 | if (remaining == 0) 54 | { 55 | std::atomic_thread_fence(std::memory_order_acquire); 56 | if (notifier) // Protect against callback not being set yet 57 | { 58 | notifier(); 59 | } 60 | } 61 | else if (remaining < 0) 62 | { 63 | abort(); 64 | } 65 | 66 | return remaining; 67 | } 68 | 69 | operator uint32_t() const noexcept 70 | { 71 | return m_count; 72 | } 73 | 74 | template 75 | void set_notifier(Func&& func) 76 | { 77 | notifier = std::forward(func); 78 | } 79 | 80 | void set_notifier(std::nullptr_t) noexcept 81 | { 82 | notifier = nullptr; 83 | } 84 | 85 | private: 86 | std::atomic m_count{0}; 87 | std::function notifier{}; 88 | }; 89 | 90 | struct notifiable_module_lock final : notifiable_module_lock_base 91 | { 92 | static notifiable_module_lock& instance() noexcept 93 | { 94 | static notifiable_module_lock lock; 95 | return lock; 96 | } 97 | }; 98 | } // namespace wil 99 | 100 | #ifndef WIL_CPPWINRT_COM_SERVER_CUSTOM_MODULE_LOCK 101 | 102 | namespace winrt 103 | { 104 | auto& get_module_lock() 105 | { 106 | return wil::notifiable_module_lock::instance(); 107 | } 108 | } // namespace winrt 109 | 110 | #endif 111 | 112 | #endif -------------------------------------------------------------------------------- /src/windhawk/shared/libraries/wil/cppwinrt_register_com_server.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License. 5 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 6 | // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 7 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 8 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | // 10 | //********************************************************* 11 | //! @file 12 | //! Utilities for making managing COM server easier 13 | 14 | #ifndef __WIL_CPPWINRT_REGISTER_COM_SERVER_INCLUDED 15 | #define __WIL_CPPWINRT_REGISTER_COM_SERVER_INCLUDED 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace wil::details 23 | { 24 | template 25 | struct CppWinRTClassFactory : winrt::implements, IClassFactory, winrt::no_module_lock> 26 | { 27 | HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final 28 | try 29 | { 30 | *result = nullptr; 31 | 32 | if (outer) 33 | { 34 | return CLASS_E_NOAGGREGATION; 35 | } 36 | return winrt::make_self().as(iid, result); 37 | } 38 | CATCH_RETURN() 39 | 40 | HRESULT __stdcall LockServer(BOOL) noexcept final 41 | { 42 | return S_OK; 43 | } 44 | }; 45 | 46 | template 47 | void register_com_server(std::vector& registrations) 48 | { 49 | DWORD registration{}; 50 | winrt::check_hresult(CoRegisterClassObject( 51 | winrt::guid_of(), winrt::make>().get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®istration)); 52 | // This emplace_back is no-throw as wil::register_com_server already reserves enough capacity 53 | registrations.emplace_back(registration); 54 | register_com_server(registrations); 55 | } 56 | 57 | template <> 58 | void register_com_server(std::vector&) 59 | { 60 | } 61 | } // namespace wil::details 62 | 63 | namespace wil 64 | { 65 | template 66 | [[nodiscard]] std::vector register_com_server() 67 | { 68 | std::vector registrations; 69 | registrations.reserve(sizeof...(Rest) + 1); 70 | details::register_com_server(registrations); 71 | // C++17 doesn't provide guaranteed copy elision, but the copy should be elided nonetheless. 72 | return registrations; 73 | } 74 | } // namespace wil 75 | 76 | #endif -------------------------------------------------------------------------------- /src/windhawk/shared/libraries/wil/cppwinrt_wrl.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License. 5 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 6 | // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 7 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 8 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | // 10 | //********************************************************* 11 | //! @file 12 | //! Provides interoperability between C++/WinRT types and the WRL Module system. 13 | #ifndef __WIL_CPPWINRT_WRL_INCLUDED 14 | #define __WIL_CPPWINRT_WRL_INCLUDED 15 | 16 | #include "cppwinrt.h" 17 | #include 18 | 19 | #include "result_macros.h" 20 | #include 21 | 22 | // wil::wrl_factory_for_winrt_com_class provides interopability between a 23 | // C++/WinRT class and the WRL Module system, allowing the winrt class to be 24 | // CoCreatable. 25 | // 26 | // Usage: 27 | // - In your cpp, add: 28 | // CoCreatableCppWinRtClass(className) 29 | // 30 | // - In the dll.cpp (or equivalent) for the module containing your class, add: 31 | // CoCreatableClassWrlCreatorMapInclude(className) 32 | // 33 | namespace wil 34 | { 35 | /// @cond 36 | namespace details 37 | { 38 | template 39 | class module_count_wrapper : public TCppWinRTClass 40 | { 41 | public: 42 | module_count_wrapper() 43 | { 44 | if (auto modulePtr = ::Microsoft::WRL::GetModuleBase()) 45 | { 46 | modulePtr->IncrementObjectCount(); 47 | } 48 | } 49 | 50 | virtual ~module_count_wrapper() 51 | { 52 | if (auto modulePtr = ::Microsoft::WRL::GetModuleBase()) 53 | { 54 | modulePtr->DecrementObjectCount(); 55 | } 56 | } 57 | }; 58 | } // namespace details 59 | /// @endcond 60 | 61 | template 62 | class wrl_factory_for_winrt_com_class : public ::Microsoft::WRL::ClassFactory<> 63 | { 64 | public: 65 | IFACEMETHODIMP CreateInstance(_In_opt_ ::IUnknown* unknownOuter, REFIID riid, _COM_Outptr_ void** object) noexcept 66 | try 67 | { 68 | *object = nullptr; 69 | RETURN_HR_IF(CLASS_E_NOAGGREGATION, unknownOuter != nullptr); 70 | 71 | return winrt::make>().as(riid, object); 72 | } 73 | CATCH_RETURN() 74 | }; 75 | } // namespace wil 76 | 77 | #define CoCreatableCppWinRtClass(className) \ 78 | CoCreatableClassWithFactory(className, ::wil::wrl_factory_for_winrt_com_class) 79 | 80 | #endif // __WIL_CPPWINRT_WRL_INCLUDED 81 | -------------------------------------------------------------------------------- /src/windhawk/shared/logger_base.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "logger_base.h" 4 | 5 | LoggerBase::LoggerBase(Verbosity initialVerbosity) 6 | : m_verbosity(initialVerbosity) {} 7 | 8 | void LoggerBase::SetVerbosity(Verbosity verbosity) { 9 | m_verbosity = verbosity; 10 | } 11 | 12 | LoggerBase::Verbosity LoggerBase::GetVerbosity() { 13 | return m_verbosity; 14 | } 15 | 16 | void LoggerBase::VLogLine(PCWSTR format, va_list args) { 17 | WCHAR buffer[1025]; 18 | int len = _vsnwprintf_s(buffer, _TRUNCATE, format, args); 19 | if (len == -1) { 20 | // Truncation occurred. 21 | len = _countof(buffer) - 1; 22 | } 23 | 24 | while (--len >= 0 && buffer[len] == L'\n') { 25 | // Skip all newlines at the end. 26 | } 27 | 28 | // Leave only a single trailing newline. 29 | if (buffer[len + 1] == L'\n' && buffer[len + 2] == L'\n') { 30 | buffer[len + 2] = L'\0'; 31 | } 32 | 33 | OutputDebugString(buffer); 34 | } 35 | 36 | void LoggerBase::LogLine(PCWSTR format, ...) { 37 | va_list args; 38 | va_start(args, format); 39 | VLogLine(format, args); 40 | va_end(args); 41 | } 42 | -------------------------------------------------------------------------------- /src/windhawk/shared/logger_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class LoggerBase { 4 | public: 5 | enum class Verbosity { 6 | kOff, 7 | kOn, 8 | kVerbose, 9 | }; 10 | 11 | static constexpr auto kDefaultVerbosity = Verbosity::kOn; 12 | 13 | LoggerBase(Verbosity initialVerbosity); 14 | 15 | void SetVerbosity(Verbosity verbosity); 16 | Verbosity GetVerbosity(); 17 | void VLogLine(PCWSTR format, va_list args); 18 | void LogLine(PCWSTR format, ...); 19 | 20 | private: 21 | std::atomic m_verbosity = kDefaultVerbosity; 22 | }; 23 | -------------------------------------------------------------------------------- /src/windhawk/shared/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Version 4 | #define VERSION_MAJOR 1 5 | #define VERSION_MINOR 6 6 | #define VERSION_REVISION 1 7 | #define VERSION_BUILD 0 8 | 9 | // etc. 10 | #define STRINGIZE2(s) #s 11 | #define STRINGIZE(s) STRINGIZE2(s) 12 | #define W2(x) L ## x 13 | #define W(x) W2(x) 14 | #define N(x) x 15 | #define LONG_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) 16 | 17 | #define VER_FILE_VERSION VERSION_MAJOR,VERSION_MINOR,VERSION_REVISION,VERSION_BUILD 18 | 19 | #if VERSION_BUILD == 0 20 | #if VERSION_REVISION == 0 // a.b 21 | #define VER_FILE_VERSION_TSTR(t) t(STRINGIZE(VERSION_MAJOR)) t(".") \ 22 | t(STRINGIZE(VERSION_MINOR)) 23 | #else // a.b.c 24 | #define VER_FILE_VERSION_TSTR(t) t(STRINGIZE(VERSION_MAJOR)) t(".") \ 25 | t(STRINGIZE(VERSION_MINOR)) t(".") \ 26 | t(STRINGIZE(VERSION_REVISION)) 27 | #endif // VERSION_REVISION == 0 28 | #else // a.b.c.d 29 | #define VER_FILE_VERSION_TSTR(t) t(STRINGIZE(VERSION_MAJOR)) t(".") \ 30 | t(STRINGIZE(VERSION_MINOR)) t(".") \ 31 | t(STRINGIZE(VERSION_REVISION)) t(".") \ 32 | t(STRINGIZE(VERSION_BUILD)) 33 | #endif // VERSION_BUILD == 0 34 | 35 | #define VER_FILE_VERSION_STR VER_FILE_VERSION_TSTR(N) 36 | #define VER_FILE_VERSION_WSTR VER_FILE_VERSION_TSTR(W) 37 | 38 | #define VER_FILE_VERSION_LONG LONG_ID(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD) 39 | -------------------------------------------------------------------------------- /src/windhawk/windhawk.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32901.215 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine", "engine\engine.vcxproj", "{16DD1B11-BB29-4015-8BFD-AACD0AF63A79}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "app", "app\app.vcxproj", "{0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM64 = Debug|ARM64 13 | Debug|Win32 = Debug|Win32 14 | Debug|x64 = Debug|x64 15 | Release|ARM64 = Release|ARM64 16 | Release|Win32 = Release|Win32 17 | Release|x64 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|ARM64.ActiveCfg = Debug|ARM64 21 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|ARM64.Build.0 = Debug|ARM64 22 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|Win32.ActiveCfg = Debug|Win32 23 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|Win32.Build.0 = Debug|Win32 24 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|x64.ActiveCfg = Debug|x64 25 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Debug|x64.Build.0 = Debug|x64 26 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|ARM64.ActiveCfg = Release|ARM64 27 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|ARM64.Build.0 = Release|ARM64 28 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|Win32.ActiveCfg = Release|Win32 29 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|Win32.Build.0 = Release|Win32 30 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|x64.ActiveCfg = Release|x64 31 | {16DD1B11-BB29-4015-8BFD-AACD0AF63A79}.Release|x64.Build.0 = Release|x64 32 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|ARM64.ActiveCfg = Debug|ARM64 33 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|ARM64.Build.0 = Debug|ARM64 34 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|Win32.ActiveCfg = Debug|Win32 35 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|Win32.Build.0 = Debug|Win32 36 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|x64.ActiveCfg = Debug|x64 37 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Debug|x64.Build.0 = Debug|x64 38 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|ARM64.ActiveCfg = Release|ARM64 39 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|ARM64.Build.0 = Release|ARM64 40 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|Win32.ActiveCfg = Release|Win32 41 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|Win32.Build.0 = Release|Win32 42 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|x64.ActiveCfg = Release|x64 43 | {0F288B9E-2D98-4728-8C40-CD5C1D1A95FD}.Release|x64.Build.0 = Release|x64 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {97781E74-7298-4130-A81F-F8E0984A4661} 50 | EndGlobalSection 51 | EndGlobal 52 | --------------------------------------------------------------------------------