The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .github
    └── workflows
    │   ├── ci.yml
    │   └── package.yml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── CMakePresets.json
├── CMakeUserPresets.json
├── LICENSE
├── OpenSpeedy_en_US.ts
├── OpenSpeedy_zh_CN.ts
├── OpenSpeedy_zh_TW.ts
├── README.md
├── aboutdialog.cpp
├── aboutdialog.h
├── aboutdialog.ui
├── bridge
    ├── CMakeLists.txt
    └── main.cpp
├── config.h
├── cpuutils.cpp
├── cpuutils.h
├── docs
    ├── README_cn.md
    └── README_ja.md
├── icons.rc
├── images
    ├── icon.ico
    ├── icon_16.ico
    ├── icon_32.ico
    ├── icon_64.ico
    └── logo.png
├── installer
    ├── config
    │   └── config.xml
    ├── create_installer.bat
    └── packages
    │   └── com.openspeedy.app
    │       ├── data
    │           └── .gitkeep
    │       └── meta
    │           ├── installscript.qs
    │           └── package.xml
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── memutils.cpp
├── memutils.h
├── preferencedialog.cpp
├── preferencedialog.h
├── preferencedialog.ui
├── processmonitor.cpp
├── processmonitor.h
├── qsinglekeysequenceedit.cpp
├── qsinglekeysequenceedit.h
├── resources.qrc
├── script
    ├── build32.bat
    ├── build64.bat
    └── initenv.bat
├── speedpatch
    ├── CMakeLists.txt
    ├── SpeedPatch_global.h
    ├── speedpatch.cpp
    ├── speedpatch.h
    └── vcpkg.json
├── taskscheduler.cpp
├── taskscheduler.h
├── third_party
    └── minhook
    │   ├── .editorconfig
    │   ├── .github
    │       └── workflows
    │       │   └── msbuild.yml
    │   ├── .gitignore
    │   ├── AUTHORS.txt
    │   ├── CMakeLists.txt
    │   ├── LICENSE.txt
    │   ├── README.md
    │   ├── build
    │       └── MinGW
    │       │   ├── make.bat
    │       │   └── make.sh
    │   ├── cmake
    │       └── minhook-config.cmake.in
    │   ├── dll_resources
    │       └── MinHook.def
    │   ├── 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
├── translations
    ├── OpenSpeedy_en_US.qm
    ├── OpenSpeedy_zh_CN.qm
    └── OpenSpeedy_zh_TW.qm
├── windbg.h
├── winutils.cpp
└── winutils.h


/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
 1 | name: Build OpenSpeedy
 2 | 
 3 | on:
 4 |   pull_request:
 5 |     branches: [ master ]
 6 |   workflow_dispatch:
 7 | 
 8 | jobs:
 9 |   build:
10 |     runs-on: self-hosted
11 |     outputs:
12 |       artifact-id: ${{ steps.upload-unsigned-artifacts.outputs.artifact-id }}
13 | 
14 |     steps:
15 |     - name: Checkout
16 |       uses: actions/checkout@v4
17 |       
18 |     - name: Build 32-bit
19 |       shell: cmd
20 |       run: |
21 |         echo Building 32-bit...
22 |         call script\initenv.bat
23 |         call script\build32.bat
24 | 
25 |     - name: Build 64-bit
26 |       shell: cmd
27 |       run: |
28 |         echo Building 64-bit...
29 |         call script\initenv.bat
30 |         call script\build64.bat
31 | 
32 |     - name: Collect artifacts to flat directory
33 |       shell: cmd
34 |       run: |
35 |         echo Collecting artifacts...
36 |         
37 |         if not exist "artifacts" mkdir "artifacts"
38 |         
39 |         copy "build\CMAKE-64bit-Release\OpenSpeedy.exe" "artifacts\"
40 |         copy "build\CMAKE-64bit-Release\speedpatch64.dll" "artifacts\"
41 |         copy "build\CMAKE-64bit-Release\bridge64.exe" "artifacts\"
42 |         copy "build\CMAKE-32bit-Release\speedpatch32.dll" "artifacts\"
43 |         copy "build\CMAKE-32bit-Release\bridge32.exe" "artifacts\"
44 |         
45 |         echo Artifacts directory contents:
46 |         dir "artifacts"
47 |         
48 |     - name: Upload unsigned artifacts
49 |       id: upload-unsigned-artifacts
50 |       uses: actions/upload-artifact@v4
51 |       if: success()
52 |       with:
53 |         name: OpenSpeedy-unsigned-artifacts
54 |         path: artifacts/
55 |         if-no-files-found: warn
56 |     
57 | 


--------------------------------------------------------------------------------
/.github/workflows/package.yml:
--------------------------------------------------------------------------------
  1 | name: Package
  2 | on:
  3 |   workflow_dispatch:
  4 |     inputs:
  5 |       build_id:
  6 |         description: '构建工作流ID'
  7 |         required: true
  8 |         type: string
  9 |       version:
 10 |         description: '版本号'
 11 |         required: true
 12 |         default: '1.0.0'
 13 |         type: string
 14 |       artifact_name:
 15 |         description: '签名的制品名称'
 16 |         required: true
 17 |         default: 'OpenSpeedy-unsigned-artifacts'
 18 |         type: string
 19 | 
 20 | jobs:
 21 |   package:
 22 |     runs-on: windows-latest  # GitHub-hosted runner
 23 |     
 24 |     steps:
 25 |     - name: Checkout
 26 |       uses: actions/checkout@v4
 27 | 
 28 |     - name: Download build artifact
 29 |       uses: actions/download-artifact@v4
 30 |       with:
 31 |         name: ${{ github.event.inputs.artifact_name }}
 32 |         run-id: ${{ github.event.inputs.build_id }}
 33 |         path: artifacts/
 34 |         github-token: ${{ secrets.GITHUB_TOKEN }}
 35 | 
 36 |     - id: upload-unsigned-artifacts
 37 |       name: Re-upload as new artifact
 38 |       uses: actions/upload-artifact@v4
 39 |       with:
 40 |         name: OpenSpeedy-unsigned-artifacts  
 41 |         path: artifacts/          
 42 |         retention-days: 30       
 43 |         
 44 |     - name: SignPath signing
 45 |       uses: signpath/github-action-submit-signing-request@v1.1
 46 |       with:
 47 |         api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
 48 |         organization-id: '58b9835d-38ea-4898-a564-76610c01cecd'
 49 |         project-slug: OpenSpeedy
 50 |         signing-policy-slug: test-signing
 51 |         github-artifact-id: ${{ steps.upload-unsigned-artifacts.outputs.artifact-id }}
 52 |         artifact-configuration-slug: initial
 53 |         wait-for-completion: true
 54 |         output-artifact-directory: signed-artifacts/
 55 |         parameters: |
 56 |           version: ${{ toJSON(github.event.inputs.version) }}
 57 |         
 58 |     - name: Upload signed artifacts
 59 |       uses: actions/upload-artifact@v4
 60 |       with:
 61 |         name: OpenSpeedy-signed-artifacts
 62 |         path: signed-artifacts/
 63 |         retention-days: 30
 64 | 
 65 |     - uses: actions/setup-python@v5
 66 |       with:
 67 |         python-version: '3.13' 
 68 | 
 69 |     - name: Cache Qt Installer Framework
 70 |       uses: actions/cache@v4
 71 |       id: cache-qtifw
 72 |       with:
 73 |         path: ${{ github.workspace }}/Qt/Tools/QtInstallerFramework
 74 |         key: qtifw-4.7.0-${{ runner.os }}
 75 |         restore-keys: |
 76 |           qtifw-4.7.0-
 77 |           qtifw-
 78 | 
 79 |     - name: Install Qt Installer Framework
 80 |       if: steps.cache-qtifw.outputs.cache-hit != 'true'
 81 |       run: |
 82 |         pip install aqtinstall
 83 |         python3 -m aqt install-tool -O ${{ github.workspace }}/Qt/ windows desktop tools_ifw qt.tools.ifw.47
 84 |     
 85 |     - name: Add Qt Installer Framework to PATH
 86 |       run: |
 87 |         echo "${{ github.workspace }}/Qt/Tools/QtInstallerFramework/4.7/bin/" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
 88 | 
 89 |     - name: Package installer
 90 |       run: |
 91 |         Copy-Item -Path "signed-artifacts/*" -Destination "installer/packages/com.openspeedy.app/data/" -Recurse -Force
 92 |         $version = "${{ github.event.inputs.version }}"
 93 | 
 94 |         $configXmlPath = "installer\config\config.xml"
 95 |         [xml]$configXml = Get-Content $configXmlPath
 96 |         $configXml.Installer.Version = $version
 97 |         $configXml.Save((Resolve-Path $configXmlPath))
 98 | 
 99 |         $packageXmlPath = "installer\packages\com.openspeedy.app\meta\package.xml"
100 |         [xml]$packageXml = Get-Content $packageXmlPath
101 |         $packageXml.Package.Version = $version
102 |         $packageXml.Save((Resolve-Path $packageXmlPath))
103 | 
104 |         Write-Host "Updated package version to: $version"
105 |         binarycreator.exe -c installer\config\config.xml -p installer\packages OpenSpeedy-installer-${{ github.event.inputs.version }}.exe
106 | 
107 |     - id: upload-unsigned-installer
108 |       name: Upload installer
109 |       uses: actions/upload-artifact@v4
110 |       with:
111 |         name: OpenSpeedy-unsigned-installer-${{ github.event.inputs.version }}
112 |         path: OpenSpeedy-installer-${{ github.event.inputs.version }}.exe
113 | 
114 |     - name: SignPath signing
115 |       uses: signpath/github-action-submit-signing-request@v1.1
116 |       with:
117 |         api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
118 |         organization-id: '58b9835d-38ea-4898-a564-76610c01cecd'
119 |         project-slug: OpenSpeedy
120 |         signing-policy-slug: test-signing
121 |         github-artifact-id: ${{ steps.upload-unsigned-installer.outputs.artifact-id }}
122 |         artifact-configuration-slug: installer
123 |         wait-for-completion: true
124 |         output-artifact-directory: signed-installer/
125 |         parameters: |
126 |           version: ${{ toJSON(github.event.inputs.version) }}    
127 | 
128 |     - name: Upload signed installer
129 |       uses: actions/upload-artifact@v4
130 |       with:
131 |         name: OpenSpeedy-signed-installer-${{ github.event.inputs.version }}
132 |         path: signed-installer/
133 |         retention-days: 30


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | # This file is used to ignore files which are generated
 2 | # ----------------------------------------------------------------------------
 3 | 
 4 | *~
 5 | *.autosave
 6 | *.a
 7 | *.core
 8 | *.moc
 9 | *.o
10 | *.obj
11 | *.orig
12 | *.rej
13 | *.so
14 | *.so.*
15 | *_pch.h.cpp
16 | *_resource.rc
17 | *.qm
18 | .#*
19 | *.*#
20 | core
21 | !core/
22 | tags
23 | .DS_Store
24 | .directory
25 | *.debug
26 | Makefile*
27 | *.prl
28 | *.app
29 | moc_*.cpp
30 | ui_*.h
31 | qrc_*.cpp
32 | Thumbs.db
33 | *.res
34 | *.rc
35 | /.qmake.cache
36 | /.qmake.stash
37 | 
38 | # qtcreator generated files
39 | *.pro.user*
40 | *.qbs.user*
41 | CMakeLists.txt.user*
42 | 
43 | # xemacs temporary files
44 | *.flc
45 | 
46 | # Vim temporary files
47 | .*.swp
48 | 
49 | # Visual Studio generated files
50 | *.ib_pdb_index
51 | *.idb
52 | *.ilk
53 | *.pdb
54 | *.sln
55 | *.suo
56 | *.vcproj
57 | *vcproj.*.*.user
58 | *.ncb
59 | *.sdf
60 | *.opensdf
61 | *.vcxproj
62 | *vcxproj.*
63 | 
64 | # MinGW generated files
65 | *.Debug
66 | *.Release
67 | 
68 | # Python byte code
69 | *.pyc
70 | 
71 | # Binaries
72 | # --------
73 | *.dll
74 | *.exe
75 | 
76 | # Directories with generated files
77 | .moc/
78 | .obj/
79 | .pch/
80 | .rcc/
81 | .uic/
82 | /build*/
83 | .vs/
84 | out/


--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/.gitmodules


--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
  1 | cmake_minimum_required(VERSION 3.16)
  2 | 
  3 | project(OpenSpeedy VERSION 0.1 LANGUAGES CXX)
  4 | 
  5 | set(CMAKE_AUTOUIC ON)
  6 | set(CMAKE_AUTOMOC ON)
  7 | set(CMAKE_AUTORCC ON)
  8 | 
  9 | set(CMAKE_CXX_STANDARD 17)
 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
 11 | 
 12 | # 启用Qt静态链接
 13 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded
lt;
lt;CONFIG:Debug>:Debug>")
 14 | 
 15 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
 16 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network WinExtras LinguistTools)
 17 | set(TS_FILES
 18 |   OpenSpeedy_zh_CN.ts
 19 |   OpenSpeedy_en_US.ts
 20 |   OpenSpeedy_zh_TW.ts
 21 | )
 22 | 
 23 | set(PROJECT_SOURCES
 24 |         main.cpp
 25 |         mainwindow.cpp
 26 |         mainwindow.h
 27 |         mainwindow.ui
 28 |         ${TS_FILES}
 29 | )
 30 | 
 31 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
 32 |     qt_add_executable(OpenSpeedy
 33 |         MANUAL_FINALIZATION
 34 |         ${PROJECT_SOURCES}
 35 |         winutils.h winutils.cpp
 36 |         processmonitor.h processmonitor.cpp
 37 |         resources.qrc
 38 |         images/icon.ico images/logo.png
 39 |         icons.rc
 40 |     )
 41 | 
 42 | # Define target properties for Android with Qt 6 as:
 43 | #    set_property(TARGET OpenSpeedy APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
 44 | #                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
 45 | # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
 46 | 
 47 |     qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
 48 | else()
 49 |       qt5_create_translation(QM_FILES
 50 |         ${CMAKE_SOURCE_DIR}
 51 |         ${TS_FILES})
 52 | 
 53 |       add_definitions("-DUNICODE -DNOMINMAX")
 54 |       add_executable(OpenSpeedy
 55 |           ${PROJECT_SOURCES}
 56 |           processmonitor.h processmonitor.cpp
 57 |           resources.qrc
 58 |           images/icon.ico images/logo.png
 59 |           icons.rc
 60 |           config.h
 61 |           windbg.h
 62 |           aboutdialog.ui
 63 |           aboutdialog.h aboutdialog.cpp aboutdialog.ui
 64 |           preferencedialog.h preferencedialog.cpp preferencedialog.ui
 65 |           qsinglekeysequenceedit.h qsinglekeysequenceedit.cpp
 66 |           ${QM_FILES}
 67 | 
 68 | 
 69 |       )
 70 | 
 71 |       add_library(winutils
 72 |         winutils.h winutils.cpp
 73 |         cpuutils.h cpuutils.cpp
 74 |         memutils.h memutils.cpp
 75 |         taskscheduler.h
 76 |         taskscheduler.cpp
 77 |       )
 78 | 
 79 |       target_include_directories(winutils PUBLIC
 80 |           ${CMAKE_CURRENT_SOURCE_DIR}
 81 |       )
 82 | 
 83 |     target_link_libraries(winutils PUBLIC
 84 |       Qt${QT_VERSION_MAJOR}::Core
 85 |       pdh
 86 |       ole32
 87 |       oleaut32
 88 |       taskschd)
 89 | endif()
 90 | 
 91 | 
 92 | 
 93 | target_link_libraries(OpenSpeedy PRIVATE
 94 |   Qt${QT_VERSION_MAJOR}::Widgets
 95 |   Qt${QT_VERSION_MAJOR}::Network
 96 |   Qt${QT_VERSION_MAJOR}::WinExtras
 97 |   winutils
 98 | )
 99 | 
100 | # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
101 | # If you are developing for iOS or macOS you should consider setting an
102 | # explicit, fixed bundle identifier manually though.
103 | if(${QT_VERSION} VERSION_LESS 6.1.0)
104 |   set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.OpenSpeedy)
105 | endif()
106 | set_target_properties(OpenSpeedy PROPERTIES
107 |     ${BUNDLE_ID_OPTION}
108 |     MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
109 |     MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
110 |     MACOSX_BUNDLE TRUE
111 |     WIN32_EXECUTABLE TRUE
112 |     #LINK_FLAGS "/MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\" /SUBSYSTEM:WINDOWS"
113 | )
114 | 
115 | include(GNUInstallDirs)
116 | install(TARGETS OpenSpeedy
117 |     BUNDLE DESTINATION .
118 |     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
119 |     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
120 | )
121 | 
122 | if(QT_VERSION_MAJOR EQUAL 6)
123 |     qt_finalize_executable(OpenSpeedy)
124 | endif()
125 | 
126 | add_subdirectory(third_party/minhook)
127 | add_subdirectory(speedpatch)
128 | add_subdirectory(bridge)
129 | 
130 | 


--------------------------------------------------------------------------------
/CMakePresets.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "version": 3,
 3 |   "configurePresets": [
 4 |     {
 5 |       "hidden": true,
 6 |       "name": "Qt",
 7 |       "cacheVariables": {
 8 |         "CMAKE_PREFIX_PATH": "$env{QTDIR}"
 9 |       },
10 |       "vendor": {
11 |         "qt-project.org/Qt": {
12 |           "checksum": "wVa86FgEkvdCTVp1/nxvrkaemJc="
13 |         }
14 |       }
15 |     }
16 |   ],
17 |   "vendor": {
18 |     "qt-project.org/Presets": {
19 |       "checksum": "67SmY24ZeVbebyKD0fGfIzb/bGI="
20 |     }
21 |   }
22 | }


--------------------------------------------------------------------------------
/CMakeUserPresets.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "version": 3,
 3 |   "configurePresets": [
 4 |     {
 5 |       "name": "Qt-Debug",
 6 |       "inherits": "Qt-Default",
 7 |       "binaryDir": "${sourceDir}/out/build/debug",
 8 |       "cacheVariables": {
 9 |         "CMAKE_BUILD_TYPE": "Debug",
10 |         "CMAKE_CXX_FLAGS": "-DQT_QML_DEBUG"
11 |       },
12 |       "environment": {
13 |         "QML_DEBUG_ARGS": "-qmljsdebugger=file:{68d8eccf-89d3-401a-a51b-854d41e11c66},block"
14 |       }
15 |     },
16 |     {
17 |       "name": "Qt-Release",
18 |       "inherits": "Qt-Default",
19 |       "binaryDir": "${sourceDir}/out/build/release",
20 |       "cacheVariables": {
21 |         "CMAKE_BUILD_TYPE": "Release"
22 |       }
23 |     },
24 |     {
25 |       "hidden": true,
26 |       "name": "Qt-Default",
27 |       "inherits": "6.9.0_msvc2022_64",
28 |       "vendor": {
29 |         "qt-project.org/Default": {
30 |           "checksum": "p2g8qSfRuZwrHdoqsydD/azGQjs="
31 |         }
32 |       }
33 |     },
34 |     {
35 |       "hidden": true,
36 |       "name": "6.9.0_msvc2022_64",
37 |       "inherits": "Qt",
38 |       "environment": {
39 |         "QTDIR": "D:/Qt/6.9.0/msvc2022_64"
40 |       },
41 |       "architecture": {
42 |         "strategy": "external",
43 |         "value": "x64"
44 |       },
45 |       "generator": "Ninja",
46 |       "vendor": {
47 |         "qt-project.org/Version": {
48 |           "checksum": "sBywmcWZZXChcZz0AVGlSBNHGws="
49 |         }
50 |       }
51 |     }
52 |   ],
53 |   "vendor": {
54 |     "qt-project.org/Presets": {
55 |       "checksum": "IQB0bB4OeX7kqF6cObd8brpl2ck="
56 |     }
57 |   }
58 | }


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | <h1 align="center"> OpenSpeedy </h1>
  2 | 
  3 | <p align="center">
  4 |   <img style="margin:0 auto" width=100 height=100 src="https://github.com/user-attachments/assets/bdbe4a60-7692-4e9c-9df4-ad1711337c57">
  5 |   </img>  
  6 | </p>
  7 | 
  8 | <p align="center">
  9 |   OpenSpeedy is an open-source and free game speed tool that helps you break frame rate limitations and provides a smoother, silkier gaming acceleration experience.
 10 | </p>
 11 | 
 12 | <p align="center">
 13 |   <img src="https://api.visitorbadge.io/api/visitors?path=game1024.openspeedy&countColor=%234ecdc4">
 14 |   <br/>
 15 |     
 16 |   <a href="https://github.com/game1024/OpenSpeedy/stargazers">
 17 |     <img src="https://img.shields.io/github/stars/game1024/OpenSpeedy?style=for-the-badge&color=yellow" alt="GitHub Stars">
 18 |   </a>
 19 | 
 20 |   <img src="https://img.shields.io/github/forks/game1024/OpenSpeedy?style=for-the-badge&color=8a2be2" alt="GitHub Forks">
 21 | 
 22 |   <a href="https://github.com/game1024/OpenSpeedy/issues">
 23 |     <img src="https://img.shields.io/github/issues-raw/game1024/OpenSpeedy?style=for-the-badge&label=Issues&color=orange" alt="Github Issues">
 24 |   </a>
 25 |   <br/>  
 26 |   
 27 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 28 |     <img src="https://img.shields.io/github/downloads/game1024/OpenSpeedy/total?style=for-the-badge" alt="Downloads">
 29 |   </a>
 30 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 31 |     <img src="https://img.shields.io/github/v/release/game1024/OpenSpeedy?style=for-the-badge&color=brightgreen" alt="Version">
 32 |   </a>
 33 |   <a href="https://github.com/game1024/OpenSpeedy/actions">
 34 |       <img src="https://img.shields.io/github/actions/workflow/status/game1024/OpenSpeedy/ci.yml?style=for-the-badge" alt="Github Action">
 35 |   </a>
 36 |   <a href="https://github.com/game1024/OpenSpeedy">
 37 |     <img src="https://img.shields.io/badge/Platform-Windows-lightblue?style=for-the-badge" alt="Platform">
 38 |   </a>
 39 |   <br/>
 40 |   
 41 |   <a href="https://github.com/game1024/OpenSpeedy/commits">
 42 |     <img src="https://img.shields.io/github/commit-activity/m/game1024/OpenSpeedy?style=for-the-badge" alt="Commit Activity">
 43 |   </a>
 44 |   <img src="https://img.shields.io/badge/language-C/C++-blue?style=for-the-badge">
 45 |   <img src="https://img.shields.io/badge/License-GPLv3-green.svg?style=for-the-badge">
 46 |   <br/>
 47 | 
 48 |   <a href="https://hellogithub.com/repository/975f473c56ad4369a1c30ac9aa5819e0" target="_blank">
 49 |     <img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=975f473c56ad4369a1c30ac9aa5819e0&claim_uid=kmUCncHJr9SpNV7&theme=neutral" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" />
 50 |   </a>
 51 | </p>
 52 | 
 53 | <p align="center">
 54 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_cn.md">
 55 |     简体中文
 56 |   </a>
 57 |   ·
 58 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_ja.md">
 59 |     日本語
 60 |   </a>
 61 |   ·
 62 |   <a href="https://github.com/game1024/OpenSpeedy?tab=readme-ov-file#-openspeedy-">
 63 |     English
 64 |   </a>
 65 | </p>
 66 | 
 67 | # 🚀 Features
 68 | - Completely free and open-source
 69 | - Easy-to-use interface
 70 | - Customizable speed multiplier
 71 | - Good compatibility with various game engines
 72 | - Low system resource consumption
 73 | - Supports accelerating both x86 and x64 processes
 74 | - Non-invasive to the kernel: Ring3 level Hook, does not compromise the system kernel
 75 | 
 76 | # 💾 Installation
 77 | 📦 **Method1: Winget**
 78 | 
 79 | ``` powershell
 80 | # install 
 81 | winget install openspeedy
 82 | 
 83 | # open a new terminal, you can run openspeedy by following command
 84 | openspeedy
 85 | ``` 
 86 | 
 87 | 📥 **Method2: Manual Download**
 88 | 
 89 | Visit the [Installation Page](https://github.com/game1024/OpenSpeedy/releases) to download the latest version
 90 | 
 91 | 
 92 | 
 93 | # 💻 System Requirements
 94 | - OS: Windows 10 or later
 95 | - Platform: x86 (32-bit) and x64 (64-bit)
 96 | 
 97 | # 📝 Usage Instructions
 98 | 1. Start OpenSpeedy
 99 | 2. Launch the target game you want to speed up
100 | <img src="https://github.com/user-attachments/assets/648e721d-9c3a-4d82-954c-19b16355d084" width="50%">
101 | 
102 | 3. Select the game process, and adjust the speed multiplier in the OpenSpeedy interface
103 | <img src="https://github.com/user-attachments/assets/9469aae9-8be0-4e40-884d-1fbea3206e73" width="50%">
104 | 
105 | 4. The effect takes effect immediately. Compare the results below
106 | 
107 | <video src="https://github.com/user-attachments/assets/74471b1f-7f95-4de8-b5aa-7edc85c9d5f0" width="70%"></video>
108 | 
109 | # 🔧 Technical Principle
110 | OpenSpeedy achieves game speed adjustment by hooking the following Windows system time functions:
111 | 
112 | | Function Name | Library | Description |
113 | |---------------|---------|-------------|
114 | | Sleep | user32.dll | Thread sleep |
115 | | SetTimer | user32.dll | Create message-based timer |
116 | | timeGetTime | winmm.dll | Get milliseconds elapsed since system startup |
117 | | GetTickCount | kernel32.dll | Get milliseconds elapsed since system startup |
118 | | GetTickCount64 | kernel32.dll | Get milliseconds elapsed since system startup (64-bit) |
119 | | QueryPerformanceCounter | kernel32.dll | High precision performance counter |
120 | | GetSystemTimeAsFileTime | kernel32.dll | Get system time |
121 | | GetSystemTimePreciseAsFileTime | kernel32.dll | Get high precision system time |
122 | 
123 | # ⚠️ Notes
124 | - This tool is for learning and research purposes only
125 | - Some online games may have anti-cheat systems. Using this tool may result in your account being banned
126 | - Excessive speeding up may cause the game physics engine to malfunction or crash
127 | - Not recommended for use in competitive online games
128 | - Open source product does not include digital signature and may be falsely flagged by antivirus software
129 | 
130 | # 🔄 Feedback
131 | If you encounter any issues during use, feel free to provide feedback via:
132 | - [FAQ](https://github.com/game1024/OpenSpeedy/wiki#faq) - You can first check the wiki to locate the issue.
133 | - [GitHub Issues](https://github.com/game1024/OpenSpeedy/issues) - Submit issue reports
134 | - WeChat Group
135 | <img width="30%" src="https://github.com/user-attachments/assets/d77cb35d-6c92-4480-89c9-40f124c4df08">
136 | 
137 | # 🎁 Sponosor
138 | If you find the OpenSpeedy project helpful, you can buy me a coffee~ ☕️
139 | 
140 | 365VPN uses dedicated lines to connect worldwide, offering speeds of up to 10Gbps. Download now to start surfing for free🏄: https://ref.365tz87989.com/?r=RWQVZD
141 | 
142 | # 📜 License
143 | OpenSpeedy is licensed under the GNU v3 License.
144 | 
145 | # 🙏 Acknowledgements
146 | OpenSpeedy uses source code from the following projects. Thanks to the open-source community! If OpenSpeedy helps you, please give us a Star!
147 | - [minhook](https://github.com/TsudaKageyu/minhook): For API Hooking
148 | - [Qt](https://www.qt.io/): GUI
149 | 
150 | Disclaimer: OpenSpeedy is intended for educational and research purposes only. Users assume all risks and responsibilities for using this software. The author is not responsible for any loss or legal liability resulting from the use of this software.
151 | 
152 | <p align="center">
153 |   <img src="https://api.star-history.com/svg?repos=game1024/openspeedy&type=Date" Alt="Star History Chart">
154 | </p>
155 | 


--------------------------------------------------------------------------------
/aboutdialog.cpp:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #include "aboutdialog.h"
19 | #include "ui_aboutdialog.h"
20 | #include <QPushButton>
21 | #include <QScreen>
22 | AboutDialog::AboutDialog(QWidget* parent)
23 |   : QDialog(parent)
24 |   , ui(new Ui::AboutDialog)
25 | {
26 |     ui->setupUi(this);
27 |     ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确认"));
28 |     ui->versionContent->setText(QString("%1").arg(OPENSPEEDY_VERSION));
29 |     connect(QGuiApplication::primaryScreen(),
30 |             &QScreen::logicalDotsPerInchChanged,
31 |             this,
32 |             &AboutDialog::recreate);
33 |     setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
34 | }
35 | 
36 | AboutDialog::~AboutDialog()
37 | {
38 |     delete ui;
39 | }
40 | 
41 | void
42 | AboutDialog::recreate()
43 | {
44 |     layout()->invalidate();
45 |     layout()->activate();
46 |     adjustSize();
47 | }
48 | 


--------------------------------------------------------------------------------
/aboutdialog.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  * 
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  * 
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  * 
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef ABOUTDIALOG_H
19 | #define ABOUTDIALOG_H
20 | #include "config.h"
21 | #include <QDialog>
22 | 
23 | namespace Ui
24 | {
25 | class AboutDialog;
26 | }
27 | 
28 | class AboutDialog : public QDialog
29 | {
30 |     Q_OBJECT
31 | 
32 |   public:
33 |     explicit AboutDialog(QWidget* parent = nullptr);
34 |     ~AboutDialog();
35 | 
36 |   private slots:
37 |     void recreate();
38 | 
39 |   private:
40 |     Ui::AboutDialog* ui;
41 | };
42 | 
43 | #endif // ABOUTDIALOG_H
44 | 


--------------------------------------------------------------------------------
/aboutdialog.ui:
--------------------------------------------------------------------------------
  1 | <?xml version="1.0" encoding="UTF-8"?>
  2 | <ui version="4.0">
  3 |  <class>AboutDialog</class>
  4 |  <widget class="QDialog" name="AboutDialog">
  5 |   <property name="windowModality">
  6 |    <enum>Qt::ApplicationModal</enum>
  7 |   </property>
  8 |   <property name="geometry">
  9 |    <rect>
 10 |     <x>0</x>
 11 |     <y>0</y>
 12 |     <width>440</width>
 13 |     <height>215</height>
 14 |    </rect>
 15 |   </property>
 16 |   <property name="sizePolicy">
 17 |    <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
 18 |     <horstretch>0</horstretch>
 19 |     <verstretch>0</verstretch>
 20 |    </sizepolicy>
 21 |   </property>
 22 |   <property name="minimumSize">
 23 |    <size>
 24 |     <width>0</width>
 25 |     <height>0</height>
 26 |    </size>
 27 |   </property>
 28 |   <property name="maximumSize">
 29 |    <size>
 30 |     <width>16777215</width>
 31 |     <height>16777215</height>
 32 |    </size>
 33 |   </property>
 34 |   <property name="windowTitle">
 35 |    <string>关于</string>
 36 |   </property>
 37 |   <property name="sizeGripEnabled">
 38 |    <bool>false</bool>
 39 |   </property>
 40 |   <property name="modal">
 41 |    <bool>false</bool>
 42 |   </property>
 43 |   <layout class="QVBoxLayout" name="verticalLayout">
 44 |    <property name="spacing">
 45 |     <number>7</number>
 46 |    </property>
 47 |    <property name="sizeConstraint">
 48 |     <enum>QLayout::SetFixedSize</enum>
 49 |    </property>
 50 |    <item>
 51 |     <widget class="QLabel" name="appTitle">
 52 |      <property name="font">
 53 |       <font>
 54 |        <family>微软雅黑</family>
 55 |        <pointsize>12</pointsize>
 56 |       </font>
 57 |      </property>
 58 |      <property name="text">
 59 |       <string>OpenSpeedy</string>
 60 |      </property>
 61 |      <property name="alignment">
 62 |       <set>Qt::AlignCenter</set>
 63 |      </property>
 64 |     </widget>
 65 |    </item>
 66 |    <item>
 67 |     <layout class="QGridLayout" name="gridLayout">
 68 |      <property name="sizeConstraint">
 69 |       <enum>QLayout::SetMaximumSize</enum>
 70 |      </property>
 71 |      <property name="verticalSpacing">
 72 |       <number>4</number>
 73 |      </property>
 74 |      <item row="2" column="1">
 75 |       <widget class="QLabel" name="label_3">
 76 |        <property name="sizePolicy">
 77 |         <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
 78 |          <horstretch>0</horstretch>
 79 |          <verstretch>0</verstretch>
 80 |         </sizepolicy>
 81 |        </property>
 82 |        <property name="font">
 83 |         <font>
 84 |          <family>微软雅黑</family>
 85 |         </font>
 86 |        </property>
 87 |        <property name="text">
 88 |         <string>版本:</string>
 89 |        </property>
 90 |        <property name="scaledContents">
 91 |         <bool>false</bool>
 92 |        </property>
 93 |        <property name="alignment">
 94 |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 95 |        </property>
 96 |        <property name="wordWrap">
 97 |         <bool>true</bool>
 98 |        </property>
 99 |       </widget>
100 |      </item>
101 |      <item row="0" column="0">
102 |       <widget class="QLabel" name="authorIcon">
103 |        <property name="sizePolicy">
104 |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
105 |          <horstretch>0</horstretch>
106 |          <verstretch>0</verstretch>
107 |         </sizepolicy>
108 |        </property>
109 |        <property name="font">
110 |         <font>
111 |          <family>Segoe UI Emoji</family>
112 |          <pointsize>12</pointsize>
113 |         </font>
114 |        </property>
115 |        <property name="text">
116 |         <string>😄</string>
117 |        </property>
118 |       </widget>
119 |      </item>
120 |      <item row="0" column="1">
121 |       <widget class="QLabel" name="label">
122 |        <property name="sizePolicy">
123 |         <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
124 |          <horstretch>0</horstretch>
125 |          <verstretch>0</verstretch>
126 |         </sizepolicy>
127 |        </property>
128 |        <property name="font">
129 |         <font>
130 |          <family>微软雅黑</family>
131 |         </font>
132 |        </property>
133 |        <property name="text">
134 |         <string>作者:</string>
135 |        </property>
136 |        <property name="scaledContents">
137 |         <bool>false</bool>
138 |        </property>
139 |        <property name="alignment">
140 |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
141 |        </property>
142 |        <property name="wordWrap">
143 |         <bool>true</bool>
144 |        </property>
145 |       </widget>
146 |      </item>
147 |      <item row="3" column="0">
148 |       <widget class="QLabel" name="licenseIcon">
149 |        <property name="sizePolicy">
150 |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
151 |          <horstretch>0</horstretch>
152 |          <verstretch>0</verstretch>
153 |         </sizepolicy>
154 |        </property>
155 |        <property name="font">
156 |         <font>
157 |          <family>Segoe UI Emoji</family>
158 |          <pointsize>12</pointsize>
159 |         </font>
160 |        </property>
161 |        <property name="text">
162 |         <string>📜</string>
163 |        </property>
164 |       </widget>
165 |      </item>
166 |      <item row="3" column="2">
167 |       <widget class="QLabel" name="licenseContent">
168 |        <property name="font">
169 |         <font>
170 |          <family>微软雅黑</family>
171 |         </font>
172 |        </property>
173 |        <property name="text">
174 |         <string>General Public License v3</string>
175 |        </property>
176 |       </widget>
177 |      </item>
178 |      <item row="1" column="0">
179 |       <widget class="QLabel" name="homeIcon">
180 |        <property name="sizePolicy">
181 |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
182 |          <horstretch>0</horstretch>
183 |          <verstretch>0</verstretch>
184 |         </sizepolicy>
185 |        </property>
186 |        <property name="font">
187 |         <font>
188 |          <family>Segoe UI Emoji</family>
189 |          <pointsize>12</pointsize>
190 |         </font>
191 |        </property>
192 |        <property name="text">
193 |         <string>🚀</string>
194 |        </property>
195 |       </widget>
196 |      </item>
197 |      <item row="0" column="2">
198 |       <widget class="QLabel" name="authorContent">
199 |        <property name="font">
200 |         <font>
201 |          <family>微软雅黑</family>
202 |         </font>
203 |        </property>
204 |        <property name="text">
205 |         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/game1024&quot;&gt;&lt;span style=&quot; text-decoration: none; color:#003e92;&quot;&gt;game1024&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
206 |        </property>
207 |        <property name="openExternalLinks">
208 |         <bool>true</bool>
209 |        </property>
210 |       </widget>
211 |      </item>
212 |      <item row="2" column="0">
213 |       <widget class="QLabel" name="versionIcon">
214 |        <property name="sizePolicy">
215 |         <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
216 |          <horstretch>0</horstretch>
217 |          <verstretch>0</verstretch>
218 |         </sizepolicy>
219 |        </property>
220 |        <property name="font">
221 |         <font>
222 |          <family>Segoe UI Emoji</family>
223 |          <pointsize>12</pointsize>
224 |         </font>
225 |        </property>
226 |        <property name="text">
227 |         <string>🌳</string>
228 |        </property>
229 |       </widget>
230 |      </item>
231 |      <item row="1" column="2">
232 |       <widget class="QLabel" name="homeContent">
233 |        <property name="font">
234 |         <font>
235 |          <family>微软雅黑</family>
236 |         </font>
237 |        </property>
238 |        <property name="text">
239 |         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/game1024/OpenSpeedy&quot;&gt;&lt;span style=&quot; text-decoration: none; color:#003e92;&quot;&gt;game1024/OpenSpeedy&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
240 |        </property>
241 |        <property name="openExternalLinks">
242 |         <bool>true</bool>
243 |        </property>
244 |       </widget>
245 |      </item>
246 |      <item row="2" column="2">
247 |       <widget class="QLabel" name="versionContent">
248 |        <property name="font">
249 |         <font>
250 |          <family>微软雅黑</family>
251 |         </font>
252 |        </property>
253 |        <property name="text">
254 |         <string>v0.0.0</string>
255 |        </property>
256 |       </widget>
257 |      </item>
258 |      <item row="3" column="1">
259 |       <widget class="QLabel" name="label_4">
260 |        <property name="sizePolicy">
261 |         <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
262 |          <horstretch>0</horstretch>
263 |          <verstretch>0</verstretch>
264 |         </sizepolicy>
265 |        </property>
266 |        <property name="font">
267 |         <font>
268 |          <family>微软雅黑</family>
269 |         </font>
270 |        </property>
271 |        <property name="text">
272 |         <string>协议:</string>
273 |        </property>
274 |        <property name="scaledContents">
275 |         <bool>false</bool>
276 |        </property>
277 |        <property name="alignment">
278 |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
279 |        </property>
280 |        <property name="wordWrap">
281 |         <bool>true</bool>
282 |        </property>
283 |       </widget>
284 |      </item>
285 |      <item row="1" column="1">
286 |       <widget class="QLabel" name="label_2">
287 |        <property name="sizePolicy">
288 |         <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
289 |          <horstretch>0</horstretch>
290 |          <verstretch>0</verstretch>
291 |         </sizepolicy>
292 |        </property>
293 |        <property name="font">
294 |         <font>
295 |          <family>微软雅黑</family>
296 |         </font>
297 |        </property>
298 |        <property name="text">
299 |         <string>主页:</string>
300 |        </property>
301 |        <property name="scaledContents">
302 |         <bool>false</bool>
303 |        </property>
304 |        <property name="alignment">
305 |         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
306 |        </property>
307 |        <property name="wordWrap">
308 |         <bool>true</bool>
309 |        </property>
310 |       </widget>
311 |      </item>
312 |     </layout>
313 |    </item>
314 |    <item>
315 |     <widget class="QDialogButtonBox" name="buttonBox">
316 |      <property name="standardButtons">
317 |       <set>QDialogButtonBox::Ok</set>
318 |      </property>
319 |     </widget>
320 |    </item>
321 |   </layout>
322 |  </widget>
323 |  <resources/>
324 |  <connections>
325 |   <connection>
326 |    <sender>buttonBox</sender>
327 |    <signal>accepted()</signal>
328 |    <receiver>AboutDialog</receiver>
329 |    <slot>accept()</slot>
330 |    <hints>
331 |     <hint type="sourcelabel">
332 |      <x>219</x>
333 |      <y>154</y>
334 |     </hint>
335 |     <hint type="destinationlabel">
336 |      <x>219</x>
337 |      <y>89</y>
338 |     </hint>
339 |    </hints>
340 |   </connection>
341 |  </connections>
342 | </ui>
343 | 


--------------------------------------------------------------------------------
/bridge/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.16)
 2 | 
 3 | project(Bridge LANGUAGES CXX)
 4 | 
 5 | set(CMAKE_AUTOUIC ON)
 6 | set(CMAKE_AUTOMOC ON)
 7 | set(CMAKE_AUTORCC ON)
 8 | 
 9 | set(CMAKE_CXX_STANDARD 17)
10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
11 | 
12 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ..)
13 | 
14 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
15 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
16 | 
17 | # 判断是32位还是64位
18 | if(CMAKE_SIZEOF_VOID_P EQUAL 8)
19 |   set(TARGET_NAME "bridge64")
20 |   set(SPEEDPATCH_LIBRARY "speedpatch64")
21 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
22 |   set(TARGET_NAME "bridge32")
23 |   set(SPEEDPATCH_LIBRARY "speedpatch32")
24 | else()
25 |   set(TARGET_NAME "bridge64")
26 |   set(SPEEDPATCH_LIBRARY "speedpatch")
27 | endif()
28 | 
29 | add_executable(${TARGET_NAME}
30 |   main.cpp
31 | )
32 | 
33 | target_link_libraries(${TARGET_NAME} Qt${QT_VERSION_MAJOR}::Core ${SPEEDPATCH_LIBRARY} winutils)
34 | 
35 | include(GNUInstallDirs)
36 | install(TARGETS ${TARGET_NAME}
37 |     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
38 |     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
39 | )
40 | 


--------------------------------------------------------------------------------
/bridge/main.cpp:
--------------------------------------------------------------------------------
  1 | #include "../config.h"
  2 | #include "../speedpatch/speedpatch.h"
  3 | #include "../windbg.h"
  4 | #include "../winutils.h"
  5 | #include <QCoreApplication>
  6 | #include <QDebug>
  7 | #include <QDir>
  8 | #include <QRegularExpression>
  9 | #include <QTextStream>
 10 | 
 11 | #ifndef _WIN64
 12 | #define SPEEDPATCH_DLL SPEEDPATCH32_DLL
 13 | #else
 14 | #define SPEEDPATCH_DLL SPEEDPATCH64_DLL
 15 | #endif
 16 | 
 17 | void
 18 | handleInject(int processId, QString dllPath)
 19 | {
 20 |     qDebug() << "执行 inject,进程ID:" << processId;
 21 |     winutils::injectDll(processId, dllPath);
 22 |     SetProcessStatus(processId, true);
 23 | }
 24 | 
 25 | void
 26 | handleUnhook(int processId, QString dllPath)
 27 | {
 28 |     qDebug() << "执行 unhook,进程ID:" << processId;
 29 |     SetProcessStatus(processId, false);
 30 | }
 31 | 
 32 | void
 33 | handleChange(double factor)
 34 | {
 35 |     qDebug() << "执行 change,参数:" << factor;
 36 |     ChangeSpeed(factor);
 37 | }
 38 | 
 39 | int
 40 | main(int argc, char* argv[])
 41 | {
 42 |     SetUnhandledExceptionFilter(createMiniDump);
 43 |     QCoreApplication a(argc, argv);
 44 |     if (winutils::enableAllPrivilege())
 45 |     {
 46 |         qDebug() << "权限提升成功";
 47 |     }
 48 | 
 49 |     QString dllPath = QDir::toNativeSeparators(
 50 |       QCoreApplication::applicationDirPath() + "/" + SPEEDPATCH_DLL);
 51 | 
 52 |     QTextStream in(stdin);
 53 |     QTextStream out(stdout);
 54 | 
 55 |     QRegularExpression injectRegex("^\\s*inject\\s+(\\d+)\\s*
quot;,
 56 |                                    QRegularExpression::CaseInsensitiveOption);
 57 |     QRegularExpression unhookRegex("^\\s*unhook\\s+(\\d+)\\s*
quot;,
 58 |                                    QRegularExpression::CaseInsensitiveOption);
 59 |     QRegularExpression changeRegex("^\\s*change\\s+([+-]?\\d*\\.?\\d+)\\s*
quot;,
 60 |                                    QRegularExpression::CaseInsensitiveOption);
 61 |     QRegularExpression exitRegex("^\\s*exit\\s*
quot;,
 62 |                                  QRegularExpression::CaseInsensitiveOption);
 63 | 
 64 |     while (true)
 65 |     {
 66 |         QString line = in.readLine();
 67 |         if (line.isNull())
 68 |         {
 69 |             // 管道关闭或输入结束
 70 |             break;
 71 |         }
 72 |         line = line.trimmed();
 73 |         if (line.isEmpty())
 74 |             continue;
 75 | 
 76 |         QRegularExpressionMatch match;
 77 |         if ((match = injectRegex.match(line)).hasMatch())
 78 |         {
 79 |             int pid = match.captured(1).toInt();
 80 |             handleInject(pid, dllPath);
 81 |         }
 82 |         else if ((match = unhookRegex.match(line)).hasMatch())
 83 |         {
 84 |             int pid = match.captured(1).toInt();
 85 |             handleUnhook(pid, dllPath);
 86 |         }
 87 |         else if ((match = changeRegex.match(line)).hasMatch())
 88 |         {
 89 |             double factor = match.captured(1).toDouble();
 90 |             handleChange(factor);
 91 |         }
 92 |         else if (exitRegex.match(line).hasMatch())
 93 |         {
 94 |             qDebug() << "收到exit命令,程序即将退出。";
 95 |             break;
 96 |         }
 97 |         else
 98 |         {
 99 |             qDebug() << "无效命令:" << line;
100 |         }
101 |     }
102 | 
103 |     return 0;
104 | }
105 | 


--------------------------------------------------------------------------------
/config.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef CONFIG_H
19 | #define CONFIG_H
20 | 
21 | #define OPENSPEEDY_VERSION "v1.7.6"
22 | 
23 | #define BRIDGE32_EXE "bridge32.exe"
24 | #define BRIDGE64_EXE "bridge64.exe"
25 | 
26 | #define SPEEDPATCH32_DLL "speedpatch32.dll"
27 | #define SPEEDPATCH64_DLL "speedpatch64.dll"
28 | 
29 | #define CONFIG_LANGUAGE "General/Language"
30 | 
31 | // 热键ID
32 | enum HotkeyIds
33 | {
34 |     HOTKEY_INCREASE_SPEED = 1001,
35 |     HOTKEY_DECREASE_SPEED = 1002,
36 |     HOTKEY_RESET_SPEED = 1003,
37 |     HOTKEY_SHIFT1 = 1011,
38 |     HOTKEY_SHIFT2 = 1012,
39 |     HOTKEY_SHIFT3 = 1013,
40 |     HOTKEY_SHIFT4 = 1014,
41 |     HOTKEY_SHIFT5 = 1015
42 | };
43 | 
44 | #endif // CONFIG_H
45 | 


--------------------------------------------------------------------------------
/cpuutils.cpp:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #include "cpuutils.h"
19 | 
20 | CpuUtils::CpuUtils()
21 | {
22 | }
23 | 
24 | bool CpuUtils::init()
25 | {
26 |     // 创建查询
27 |     if (PdhOpenQuery(NULL, NULL, &hQuery) != ERROR_SUCCESS) return false;
28 | 
29 |     if (PdhAddEnglishCounter(hQuery,
30 |                              L"\\Processor(_Total)\\% Processor Time",
31 |                              NULL,
32 |                              &hCounter) != ERROR_SUCCESS)
33 |     {
34 |         PdhCloseQuery(hQuery);
35 |         return false;
36 |     }
37 | 
38 |     // 第一次采样
39 |     PdhCollectQueryData(hQuery);
40 |     initialized = true;
41 |     return true;
42 | }
43 | 
44 | double CpuUtils::getUsage()
45 | {
46 |     if (!initialized) return -1;
47 | 
48 |     // 收集数据
49 |     if (PdhCollectQueryData(hQuery) != ERROR_SUCCESS) return -1;
50 | 
51 |     PDH_FMT_COUNTERVALUE value;
52 |     if (PdhGetFormattedCounterValue(hCounter, PDH_FMT_DOUBLE, NULL, &value) !=
53 |         ERROR_SUCCESS)
54 |         return -1;
55 | 
56 |     return value.doubleValue;
57 | }
58 | 
59 | QString CpuUtils::getModel()
60 | {
61 |     int cpuInfo[4];
62 |     char cpuBrand[48 + 1] = {0};
63 | 
64 |     // 获取CPU品牌字符串(需要调用3次CPUID)
65 |     __cpuid(cpuInfo, 0x80000002);
66 |     memcpy(cpuBrand, cpuInfo, sizeof(cpuInfo));
67 | 
68 |     __cpuid(cpuInfo, 0x80000003);
69 |     memcpy(cpuBrand + 16, cpuInfo, sizeof(cpuInfo));
70 | 
71 |     __cpuid(cpuInfo, 0x80000004);
72 |     memcpy(cpuBrand + 32, cpuInfo, sizeof(cpuInfo));
73 | 
74 |     QString result(cpuBrand);
75 | 
76 |     return result.trimmed();
77 | }
78 | 
79 | CpuUtils::~CpuUtils()
80 | {
81 |     if (hCounter) PdhRemoveCounter(hCounter);
82 |     if (hQuery) PdhCloseQuery(hQuery);
83 | }
84 | 


--------------------------------------------------------------------------------
/cpuutils.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  * 
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  * 
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  * 
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef CPUUTILS_H
19 | #define CPUUTILS_H
20 | 
21 | #include <windows.h>
22 | #include <QString>
23 | #include <pdh.h>
24 | 
25 | class CpuUtils
26 | {
27 |    private:
28 |     PDH_HQUERY hQuery = NULL;
29 |     PDH_HCOUNTER hCounter = NULL;
30 |     bool initialized = false;
31 | 
32 |    public:
33 |     CpuUtils();
34 | 
35 |     ~CpuUtils();
36 | 
37 |     bool init();
38 | 
39 |     double getUsage();
40 | 
41 |     QString getModel();
42 | };
43 | 
44 | #endif  // CPUUTILS_H
45 | 


--------------------------------------------------------------------------------
/docs/README_cn.md:
--------------------------------------------------------------------------------
  1 | <h1 align="center"> OpenSpeedy </h1>
  2 | 
  3 | 
  4 | <p align="center">
  5 |   <img style="margin:0 auto" width=100 height=100 src="https://github.com/user-attachments/assets/bdbe4a60-7692-4e9c-9df4-ad1711337c57">
  6 |   </img>  
  7 | </p>
  8 | 
  9 | <p align="center">
 10 |   OpenSpeedy 是一款开源免费的游戏变速工具,让你的游戏突破帧率限制,提供更流畅丝滑的游戏加速体验。
 11 | </p>
 12 | 
 13 | <p align="center">
 14 |   <img src="https://api.visitorbadge.io/api/visitors?path=game1024.openspeedy&countColor=%234ecdc4">
 15 |   <br/>
 16 |     
 17 |   <a href="https://github.com/game1024/OpenSpeedy/stargazers">
 18 |     <img src="https://img.shields.io/github/stars/game1024/OpenSpeedy?style=for-the-badge&color=yellow" alt="GitHub Stars">
 19 |   </a>
 20 | 
 21 |   <img src="https://img.shields.io/github/forks/game1024/OpenSpeedy?style=for-the-badge&color=8a2be2" alt="GitHub Forks">
 22 | 
 23 |   <a href="https://github.com/game1024/OpenSpeedy/issues">
 24 |     <img src="https://img.shields.io/github/issues-raw/game1024/OpenSpeedy?style=for-the-badge&label=Issues&color=orange" alt="Github Issues">
 25 |   </a>
 26 |   <br/>  
 27 |   
 28 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 29 |     <img src="https://img.shields.io/github/downloads/game1024/OpenSpeedy/total?style=for-the-badge" alt="Downloads">
 30 |   </a>
 31 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 32 |     <img src="https://img.shields.io/github/v/release/game1024/OpenSpeedy?style=for-the-badge&color=brightgreen" alt="Version">
 33 |   </a>
 34 |   <a href="https://github.com/game1024/OpenSpeedy/actions">
 35 |       <img src="https://img.shields.io/github/actions/workflow/status/game1024/OpenSpeedy/ci.yml?style=for-the-badge" alt="Github Action">
 36 |   </a>
 37 |   <a href="https://github.com/game1024/OpenSpeedy">
 38 |     <img src="https://img.shields.io/badge/Platform-Windows-lightblue?style=for-the-badge" alt="Platform">
 39 |   </a>
 40 |   <br/>
 41 |   
 42 |   <a href="https://github.com/game1024/OpenSpeedy/commits">
 43 |     <img src="https://img.shields.io/github/commit-activity/m/game1024/OpenSpeedy?style=for-the-badge" alt="提交活跃度">
 44 |   </a>
 45 |   <img src="https://img.shields.io/badge/language-C/C++-blue?style=for-the-badge">
 46 |   <img src="https://img.shields.io/badge/License-GPLv3-green.svg?style=for-the-badge">
 47 |   <br/>
 48 | 
 49 |   <a href="https://hellogithub.com/repository/975f473c56ad4369a1c30ac9aa5819e0" target="_blank">
 50 |     <img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=975f473c56ad4369a1c30ac9aa5819e0&claim_uid=kmUCncHJr9SpNV7&theme=neutral" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" />
 51 |   </a>
 52 | </p>
 53 | 
 54 | <p align="center">
 55 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_cn.md">
 56 |     简体中文
 57 |   </a>
 58 |   ·
 59 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_ja.md">
 60 |     日本語
 61 |   </a>
 62 |   ·
 63 |   <a href="https://github.com/game1024/OpenSpeedy?tab=readme-ov-file#-openspeedy-">
 64 |     English
 65 |   </a>
 66 | </p>
 67 | 
 68 | 
 69 | # 🚀 特性
 70 | - 完全免费且开源
 71 | - 简单易用的界面
 72 | - 可自定义变速倍率
 73 | - 对多种游戏引擎兼容性良好
 74 | - 低系统资源占用
 75 | - 同时可以加速x86和x64平台进程
 76 | - 无内核侵入性,Ring3层Hook,不破坏系统内核
 77 | 
 78 | 
 79 | 
 80 | 
 81 | 
 82 | # 💾 安装
 83 | 📦 **方式1: Winget**
 84 | 
 85 | ``` powershell
 86 | # 安装命令如下
 87 | winget install openspeedy
 88 | 
 89 | # 打开一个新的终端,运行openspeedy
 90 | openspeedy
 91 | ```
 92 | 
 93 | 📥 **方式2: 手动下载**
 94 | 
 95 | 访问 [安装页面](https://github.com/game1024/OpenSpeedy/releases) 下载最新版本
 96 | 
 97 | 
 98 | # 💻 操作系统要求
 99 | - OS: Windows10 以上
100 | - 平台:x86(32位) 和 x64 (64位)
101 | 
102 | 
103 | # 📝 使用说明
104 | 1. 启动 OpenSpeedy
105 | 2. 运行需要变速的目标游戏
106 | <img src="https://github.com/user-attachments/assets/648e721d-9c3a-4d82-954c-19b16355d084" width="50%">
107 | 
108 | 3. 勾选游戏进程,在 OpenSpeedy 界面中调整速度倍率
109 | <img src="https://github.com/user-attachments/assets/9469aae9-8be0-4e40-884d-1fbea3206e73" width="50%">
110 | 
111 | 4. 即刻生效,对比效果如下
112 | 
113 | <video src="https://github.com/user-attachments/assets/74471b1f-7f95-4de8-b5aa-7edc85c9d5f0" width="70%"></video>
114 | 
115 | # 🔧 技术原理
116 | OpenSpeedy 通过 Hook 以下 Windows 系统时间函数来实现游戏速度调整:
117 | 
118 | |函数名	| 所属库 |	功能 |
119 | |--------|----------|------------------|
120 | |Sleep|user32.dll|线程休眠|
121 | |SetTimer|user32.dll|创建基于消息的计时器|
122 | |timeGetTime | winmm.dll	| 获取系统启动后经过的毫秒数 |
123 | |GetTickCount | kernel32.dll	| 获取系统启动后经过的毫秒数 |
124 | |GetTickCount64	| kernel32.dll	| 获取系统启动后经过的毫秒数(64位) |
125 | |QueryPerformanceCounter |	kernel32.dll	| 高精度性能计数器 |
126 | |GetSystemTimeAsFileTime |	kernel32.dll	| 获取系统时间 |
127 | |GetSystemTimePreciseAsFileTime |	kernel32.dll	| 获取高精度系统时间 |
128 | 
129 | # ⚠️ 注意事项
130 | - 本工具仅供学习和研究使用
131 | - 部分在线游戏可能有反作弊系统,使用本工具可能导致账号被封禁
132 | - 过度加速可能导致游戏物理引擎异常或崩溃
133 | - 不建议在竞技类在线游戏中使用
134 | - 开源产品不带数字签名,可能被杀毒软件误报
135 | 
136 | # 🔄 反馈
137 | 如果在使用过程中遇到任何问题,欢迎通过以下方式反馈:
138 | - [FAQ](https://github.com/game1024/OpenSpeedy/wiki#faq) - 先查看wiki定位常见问题
139 | - [GitHub Issues](https://github.com/game1024/OpenSpeedy/issues) - 提交问题报告, 网盘类问题请勿提issue, 我不支持, 谢谢合作~🙏
140 | - 微信群聊(x盘类问题不要进群,谢谢合作~🙏)
141 | <img width="30%" src="https://github.com/user-attachments/assets/d77cb35d-6c92-4480-89c9-40f124c4df08">
142 | 
143 | 
144 | # 🎁 赞助
145 | 如果觉得OpenSpeedy项目对你有帮助,可以请我喝杯咖啡~☕️
146 | 
147 | 365VPN使用专线连接全球,体验至高10Gbps/s网速。 下载立刻开始免费冲浪🏄:https://ref.365tz87989.com/?r=RWQVZD
148 | 
149 | # 📜 开源协议
150 | OpenSpeedy 遵循 GNU v3 许可证。
151 | 
152 | # 🙏 鸣谢
153 | OpenSpeedy使用到以下项目的源码,感谢开源社区的力量,如果OpenSpeedy对你有帮助,欢迎Star!
154 | - [minhook](https://github.com/TsudaKageyu/minhook): 用于API Hook
155 | - [Qt](https://www.qt.io/): GUI
156 | 
157 | 免责声明: OpenSpeedy 仅用于教育和研究目的。用户应自行承担使用本软件的所有风险和责任。作者不对因使用本软件导致的任何损失或法律责任负责。
158 | 
159 | <p align="center">
160 |   <img src="https://api.star-history.com/svg?repos=game1024/openspeedy&type=Date" Alt="Star History Chart">
161 | </p>
162 | 


--------------------------------------------------------------------------------
/docs/README_ja.md:
--------------------------------------------------------------------------------
  1 | <h1 align="center"> OpenSpeedy </h1>
  2 | 
  3 | <p align="center">
  4 |   <img style="margin:0 auto" width=100 height=100 src="https://github.com/user-attachments/assets/bdbe4a60-7692-4e9c-9df4-ad1711337c57">
  5 |   </img>  
  6 | </p>
  7 | 
  8 | <p align="center">
  9 |   OpenSpeedyは、フレームレート制限を突破し、よりスムーズで快適なゲーム加速体験を提供する、オープンソースかつ無料のゲーム速度調整ツールです。
 10 | </p>
 11 | 
 12 | <p align="center">
 13 |   <img src="https://api.visitorbadge.io/api/visitors?path=game1024.openspeedy&countColor=%234ecdc4">
 14 |   <br/>
 15 |     
 16 |   <a href="https://github.com/game1024/OpenSpeedy/stargazers">
 17 |     <img src="https://img.shields.io/github/stars/game1024/OpenSpeedy?style=for-the-badge&color=yellow" alt="GitHub Stars">
 18 |   </a>
 19 | 
 20 |   <img src="https://img.shields.io/github/forks/game1024/OpenSpeedy?style=for-the-badge&color=8a2be2" alt="GitHub Forks">
 21 | 
 22 |   <a href="https://github.com/game1024/OpenSpeedy/issues">
 23 |     <img src="https://img.shields.io/github/issues-raw/game1024/OpenSpeedy?style=for-the-badge&label=Issues&color=orange" alt="Github Issues">
 24 |   </a>
 25 |   <br/>  
 26 |   
 27 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 28 |     <img src="https://img.shields.io/github/downloads/game1024/OpenSpeedy/total?style=for-the-badge" alt="Downloads">
 29 |   </a>
 30 |   <a href="https://github.com/game1024/OpenSpeedy/releases">
 31 |     <img src="https://img.shields.io/github/v/release/game1024/OpenSpeedy?style=for-the-badge&color=brightgreen" alt="Version">
 32 |   </a>
 33 |   <a href="https://github.com/game1024/OpenSpeedy/actions">
 34 |       <img src="https://img.shields.io/github/actions/workflow/status/game1024/OpenSpeedy/ci.yml?style=for-the-badge" alt="Github Action">
 35 |   </a>
 36 |   <a href="https://github.com/game1024/OpenSpeedy">
 37 |     <img src="https://img.shields.io/badge/Platform-Windows-lightblue?style=for-the-badge" alt="Platform">
 38 |   </a>
 39 |   <br/>
 40 |   
 41 |   <a href="https://github.com/game1024/OpenSpeedy/commits">
 42 |     <img src="https://img.shields.io/github/commit-activity/m/game1024/OpenSpeedy?style=for-the-badge" alt="コミットアクティビティ">
 43 |   </a>
 44 |   <img src="https://img.shields.io/badge/language-C/C++-blue?style=for-the-badge">
 45 |   <img src="https://img.shields.io/badge/License-GPLv3-green.svg?style=for-the-badge">
 46 |   <br/>
 47 | </p>
 48 | 
 49 | <p align="center">
 50 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_cn.md">
 51 |     简体中文
 52 |   </a>
 53 |   ·
 54 |   <a href="https://github.com/game1024/OpenSpeedy/blob/master/docs/README_ja.md">
 55 |     日本語
 56 |   </a>
 57 |   ·
 58 |   <a href="https://github.com/game1024/OpenSpeedy?tab=readme-ov-file#-openspeedy-">
 59 |     English
 60 |   </a>
 61 | </p>
 62 | 
 63 | # 🚀 特徴
 64 | - 完全無料・オープンソース
 65 | - シンプルで使いやすいインターフェース
 66 | - 速度倍率をカスタマイズ可能
 67 | - 様々なゲームエンジンとの高い互換性
 68 | - 低いシステムリソース消費
 69 | - x86およびx64プラットフォームのプロセスを同時に加速可能
 70 | - カーネル非侵入型、Ring3レベルのHook、システムカーネルを破壊しない
 71 | 
 72 | # 📥 インストール
 73 | 1. [インストールページ](https://github.com/game1024/OpenSpeedy/releases)にアクセスし、最新版をダウンロードしてください
 74 | 2. ダウンロードしたファイルを任意の場所に解凍してください
 75 | 3. インストール不要、「OpenSpeedy.exe」を直接実行するだけで利用できます
 76 | 
 77 | # 💻 動作環境
 78 | - OS: Windows10以降
 79 | - プラットフォーム:x86(32ビット)およびx64(64ビット)
 80 | 
 81 | # 📝 使い方
 82 | 1. OpenSpeedyを起動する
 83 | 2. 速度を変更したいゲームを起動する
 84 | <img src="https://github.com/user-attachments/assets/648e721d-9c3a-4d82-954c-19b16355d084" width="50%">
 85 | 
 86 | 3. ゲームプロセスを選択し、OpenSpeedyの画面で速度倍率を調整する
 87 | <img src="https://github.com/user-attachments/assets/9469aae9-8be0-4e40-884d-1fbea3206e73" width="50%">
 88 | 
 89 | 4. すぐに効果が反映されます。下記の比較動画をご覧ください
 90 | 
 91 | <video src="https://github.com/user-attachments/assets/74471b1f-7f95-4de8-b5aa-7edc85c9d5f0" width="70%"></video>
 92 | 
 93 | # 🔧 技術原理
 94 | OpenSpeedyは、以下のWindowsシステム時間関数をHookすることで、ゲーム速度を調整しています:
 95 | 
 96 | | 関数名 | 所属ライブラリ | 機能 |
 97 | |--------|--------|------------------|
 98 | | Sleep | user32.dll | スレッドのスリープ |
 99 | | SetTimer | user32.dll | メッセージベースのタイマー作成 |
100 | | timeGetTime | winmm.dll | システム起動後の経過ミリ秒数取得 |
101 | | GetTickCount | kernel32.dll | システム起動後の経過ミリ秒数取得 |
102 | | GetTickCount64 | kernel32.dll | システム起動後の経過ミリ秒数取得 (64ビット) |
103 | | QueryPerformanceCounter | kernel32.dll | 高精度パフォーマンスカウンタ |
104 | | GetSystemTimeAsFileTime | kernel32.dll | システム時刻の取得 |
105 | | GetSystemTimePreciseAsFileTime | kernel32.dll | 高精度なシステム時刻の取得 |
106 | 
107 | # ⚠️ 注意事項
108 | - 本ツールは学習および研究用途のみを目的としています
109 | - 一部オンラインゲームにはアンチチートシステムが搭載されています。本ツールの使用によりアカウントがBANされる場合があります
110 | - 過度な加速は、ゲームの物理エンジン異常やクラッシュの原因となる場合があります
111 | - 対戦型オンラインゲームでの利用は推奨しません
112 | - オープンソース製品のためデジタル署名は付与しておらず、ウイルス対策ソフトによる誤検出の可能性があります
113 | 
114 | # 🔄 フィードバック
115 | 使用中に問題が発生した場合は、以下の方法でご連絡ください:
116 | - [FAQ](https://github.com/game1024/OpenSpeedy/wiki#faq) - まずはWikiを確認して問題の場所を特定できます
117 | - [GitHub Issues](https://github.com/game1024/OpenSpeedy/issues) - 不具合報告
118 | - WeChat Group
119 | <img width="30%" src="https://github.com/user-attachments/assets/d77cb35d-6c92-4480-89c9-40f124c4df08">
120 | 
121 | # 🎁 スポンサー
122 | もしOpenSpeedyプロジェクトが役に立ったと感じたら、コーヒーをご馳走していただけると嬉しいです~ ☕️
123 | 
124 | 365VPNは専用回線を利用して世界中を接続し、最大10Gbpsの速度を提供します。今すぐダウンロードして無料でサーフィンを始めましょう🏄: https://ref.365tz87989.com/?r=RWQVZD
125 | 
126 | # 📜 ライセンス
127 | OpenSpeedyはGNU v3ライセンスに従っています。
128 | 
129 | # 🙏 クレジット
130 | OpenSpeedyは以下のプロジェクトのソースコードを使用しています。オープンソースコミュニティに感謝します。OpenSpeedyが役立った場合はStarをお願いします!
131 | - [minhook](https://github.com/TsudaKageyu/minhook): APIフック用
132 | - [Qt](https://www.qt.io/): GUI
133 | 
134 | 免責事項: OpenSpeedyは教育及び研究目的のみでご利用ください。本ソフトウェアの使用に伴うすべてのリスクと責任は利用者にあります。著者は本ソフトウェアの使用によるいかなる損害や法的責任も一切負いません。
135 | 
136 | <p align="center">
137 |   <img src="https://api.star-history.com/svg?repos=game1024/openspeedy&type=Date" Alt="Star History Chart">
138 | </p>
139 | 


--------------------------------------------------------------------------------
/icons.rc:
--------------------------------------------------------------------------------
1 | IDI_APP_ICON ICON DISCARDABLE "images/icon_64.ico"
2 | 


--------------------------------------------------------------------------------
/images/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/images/icon.ico


--------------------------------------------------------------------------------
/images/icon_16.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/images/icon_16.ico


--------------------------------------------------------------------------------
/images/icon_32.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/images/icon_32.ico


--------------------------------------------------------------------------------
/images/icon_64.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/images/icon_64.ico


--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/images/logo.png


--------------------------------------------------------------------------------
/installer/config/config.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <Installer>
 3 |   <Name>OpenSpeedy</Name>
 4 |   <Version>1.0.0</Version>
 5 |   <Title>OpenSpeedy</Title>
 6 |   <Publisher>Game1024</Publisher>
 7 |   <StartMenuDir>OpenSpeedy</StartMenuDir>
 8 |   <TargetDir>@HomeDir@/OpenSpeedy</TargetDir>
 9 |   <WizardStyle>Modern</WizardStyle>
10 |   <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>
11 | </Installer>


--------------------------------------------------------------------------------
/installer/create_installer.bat:
--------------------------------------------------------------------------------
1 | set QTIFWDIR=D:\Qt\Tools\QtInstallerFramework\4.9\bin
2 | %QTIFWDIR%\binarycreator.exe -c %~dp0config\config.xml -p packages OpenSpeedy-installer.exe
3 | 


--------------------------------------------------------------------------------
/installer/packages/com.openspeedy.app/data/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/installer/packages/com.openspeedy.app/data/.gitkeep


--------------------------------------------------------------------------------
/installer/packages/com.openspeedy.app/meta/installscript.qs:
--------------------------------------------------------------------------------
 1 | function Component()
 2 | {
 3 | }
 4 | 
 5 | Component.prototype.createOperations = function()
 6 | {
 7 |     try 
 8 |     {
 9 |         // call the base create operations function
10 |         component.createOperations();
11 |         
12 |         component.addOperation("CreateShortcut", "@TargetDir@/OpenSpeedy.exe", "@DesktopDir@/OpenSpeedy.lnk");
13 |     } 
14 |     catch (e) 
15 |     {
16 |         console.log(e);
17 |     }
18 | }
19 | 


--------------------------------------------------------------------------------
/installer/packages/com.openspeedy.app/meta/package.xml:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Package>
3 |     <DisplayName>OpenSpeedy Application</DisplayName>
4 |     <Description>OpenSpeedy</Description>
5 |     <Version>1.0.0</Version>
6 |     <ReleaseDate>2025-06-14</ReleaseDate>
7 |     <Default>true</Default>
8 |     <Essential>true</Essential>
9 | </Package>


--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #include "mainwindow.h"
 19 | #include "windbg.h"
 20 | #include <QApplication>
 21 | #include <QCommandLineParser>
 22 | #include <QLocalServer>
 23 | #include <QLocalSocket>
 24 | #include <QLocale>
 25 | #include <QTranslator>
 26 | #include <ShellScalingApi.h>
 27 | int
 28 | main(int argc, char* argv[])
 29 | {
 30 |     SetUnhandledExceptionFilter(createMiniDump);
 31 |     SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
 32 |     QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 33 |     QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
 34 |     QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
 35 |     QApplication a(argc, argv);
 36 |     winutils::enableAllPrivilege();
 37 | 
 38 |     // 检查是否已有实例在运行
 39 |     QString unique = "OpenSpeedy";
 40 |     QLocalSocket socket;
 41 |     socket.connectToServer(unique);
 42 |     if (socket.waitForConnected(500))
 43 |     {
 44 |         socket.close();
 45 |         return -1;
 46 |     }
 47 | 
 48 |     // 使用资源文件中的图标
 49 |     QIcon appIcon;
 50 |     appIcon.addFile(":/icons/images/icon_16.ico", QSize(16, 16));
 51 |     appIcon.addFile(":/icons/images/icon_32.ico", QSize(32, 32));
 52 |     appIcon.addFile(":/icons/images/icon_64.ico", QSize(64, 64));
 53 |     a.setWindowIcon(appIcon);
 54 | 
 55 |     QSettings settings =
 56 |       QSettings(QCoreApplication::applicationDirPath() + "/config.ini",
 57 |                 QSettings::IniFormat);
 58 | 
 59 |     QTranslator translator;
 60 |     const QString baseName =
 61 |       "OpenSpeedy_" +
 62 |       settings.value(CONFIG_LANGUAGE, QLocale().system().name()).toString();
 63 | 
 64 |     if (translator.load(":/i18n/translations/" + baseName))
 65 |     {
 66 |         a.installTranslator(&translator);
 67 |     }
 68 | 
 69 |     // 解析命令行参数
 70 |     QCommandLineParser parser;
 71 |     parser.setApplicationDescription("OpenSpeedy");
 72 |     QCommandLineOption minimizeOption(
 73 |       QStringList() << "m" << "minimize-to-tray", "启动时最小化到托盘");
 74 |     parser.addOption(minimizeOption);
 75 |     parser.process(a);
 76 | 
 77 |     MainWindow w;
 78 |     w.resize(1024, 768);
 79 | 
 80 |     if (parser.isSet(minimizeOption))
 81 |     {
 82 |         w.hide();
 83 |     }
 84 |     else
 85 |     {
 86 |         w.show();
 87 |     }
 88 | 
 89 |     // 创建并启动本地服务器
 90 |     QLocalServer server;
 91 |     QLocalServer::removeServer(unique);
 92 |     server.listen(unique);
 93 |     // 当用户尝试再运行一个进程时,将窗口显示到最前台
 94 |     QObject::connect(&server,
 95 |                      &QLocalServer::newConnection,
 96 |                      [&]
 97 |                      {
 98 |                          w.show();
 99 |                          w.raise();
100 |                          w.showNormal();
101 |                          w.activateWindow();
102 |                      });
103 |     return a.exec();
104 | }
105 | 


--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #ifndef MAINWINDOW_H
 19 | #define MAINWINDOW_H
 20 | #include "aboutdialog.h"
 21 | #include "config.h"
 22 | #include "cpuutils.h"
 23 | #include "memutils.h"
 24 | #include "preferencedialog.h"
 25 | #include "processmonitor.h"
 26 | #include "winutils.h"
 27 | #include <QAbstractNativeEventFilter>
 28 | #include <QActionGroup>
 29 | #include <QMainWindow>
 30 | #include <QSettings>
 31 | #include <QSystemTrayIcon>
 32 | #define CONFIG_SLIDERVALUE_KEY "MainWindow/SliderValue"
 33 | 
 34 | QT_BEGIN_NAMESPACE
 35 | namespace Ui
 36 | {
 37 | class MainWindow;
 38 | }
 39 | QT_END_NAMESPACE
 40 | 
 41 | class MainWindow
 42 |   : public QMainWindow
 43 |   , public QAbstractNativeEventFilter
 44 | {
 45 |     Q_OBJECT
 46 | 
 47 |   public:
 48 |     MainWindow(QWidget* parent = nullptr);
 49 |     ~MainWindow();
 50 | 
 51 |   private slots:
 52 |     void recreate();
 53 | 
 54 |     void refresh();
 55 | 
 56 |     void on_sliderCtrl_valueChanged(int value);
 57 | 
 58 |     void on_sliderInputSpinBox_editingFinished();
 59 | 
 60 |     void on_processNameFilter_textChanged(const QString& text);
 61 | 
 62 |     void iconActivated(QSystemTrayIcon::ActivationReason reason);
 63 | 
 64 |     void recreateTray();
 65 | 
 66 |     void on_sliderLabel_clicked();
 67 | 
 68 |     void on_autoStartCheckBox_stateChanged(int arg1);
 69 | 
 70 |   private:
 71 |     Ui::MainWindow* ui;
 72 |     AboutDialog* m_aboutDlg;
 73 |     PreferenceDialog* m_preferenceDlg;
 74 | 
 75 |     QThread* m_thread;
 76 |     ProcessMonitor* m_processMonitor;
 77 |     QTimer* m_timer;
 78 | 
 79 |     QSystemTrayIcon* trayIcon;
 80 |     QMenu* trayMenu;
 81 |     QAction* showAction;
 82 |     QAction* hideAction;
 83 |     QAction* quitAction;
 84 | 
 85 |     CpuUtils* m_cpu;
 86 |     MemUtils* m_mem;
 87 | 
 88 |     QSettings* m_settings;
 89 | 
 90 |     int m_back;
 91 | 
 92 |     QActionGroup* m_languageGroup;
 93 | 
 94 |     void init();
 95 | 
 96 |     void createTray();
 97 | 
 98 |     double speedFactor(int sliderValue);
 99 | 
100 |     int sliderValue(double speedFactor);
101 | 
102 |   protected:
103 |     void closeEvent(QCloseEvent* event) override;
104 | 
105 |     bool nativeEventFilter(const QByteArray& eventType,
106 |                            void* message,
107 |                            long* result) override;
108 | };
109 | #endif // MAINWINDOW_H
110 | 


--------------------------------------------------------------------------------
/memutils.cpp:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #include "memutils.h"
19 | 
20 | MemUtils::MemUtils()
21 | {
22 | }
23 | 
24 | bool MemUtils::init()
25 | {
26 |     if (PdhOpenQuery(NULL, NULL, &hQuery) != ERROR_SUCCESS) return false;
27 | 
28 |     if (PdhAddEnglishCounter(hQuery,
29 |                              L"\\Memory\\Available Bytes",
30 |                              NULL,
31 |                              &hCounter) != ERROR_SUCCESS)
32 |     {
33 |         PdhCloseQuery(hQuery);
34 |         return false;
35 |     }
36 | 
37 |     PdhCollectQueryData(hQuery);
38 |     initialized = true;
39 |     return true;
40 | }
41 | 
42 | double MemUtils::getTotal()
43 | {
44 |     MEMORYSTATUSEX memInfo;
45 |     memInfo.dwLength = sizeof(MEMORYSTATUSEX);
46 |     GlobalMemoryStatusEx(&memInfo);
47 |     return memInfo.ullTotalPhys / (1024.0 * 1024.0 * 1024.0);
48 | }
49 | 
50 | double MemUtils::getUsage()
51 | {
52 |     if (!initialized) return -1;
53 | 
54 |     if (PdhCollectQueryData(hQuery) != ERROR_SUCCESS) return -1;
55 | 
56 |     PDH_FMT_COUNTERVALUE available;
57 |     if (PdhGetFormattedCounterValue(hCounter,
58 |                                     PDH_FMT_DOUBLE,
59 |                                     NULL,
60 |                                     &available) != ERROR_SUCCESS)
61 |         return -1;
62 | 
63 |     double totalMemory = getTotal() * 1024 * 1024 * 1024;
64 |     double usageMemory = totalMemory - available.doubleValue;
65 | 
66 |     return usageMemory / (1024.0 * 1024.0 * 1024.0);
67 | }
68 | 


--------------------------------------------------------------------------------
/memutils.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  * 
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  * 
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  * 
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef MEMUTILS_H
19 | #define MEMUTILS_H
20 | #include <windows.h>
21 | #include <pdh.h>
22 | 
23 | class MemUtils
24 | {
25 |    private:
26 |     PDH_HQUERY hQuery = NULL;
27 |     PDH_HCOUNTER hCounter = NULL;
28 |     bool initialized = false;
29 | 
30 |    public:
31 |     MemUtils();
32 | 
33 |     bool init();
34 | 
35 |     double getTotal();
36 | 
37 |     double getUsage();
38 | };
39 | 
40 | #endif  // MEMUTILS_H
41 | 


--------------------------------------------------------------------------------
/preferencedialog.cpp:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #include "preferencedialog.h"
 19 | #include "ui_preferencedialog.h"
 20 | #include <QDebug>
 21 | #include <QPushButton>
 22 | #include <QScreen>
 23 | PreferenceDialog::PreferenceDialog(HWND hMainWindow,
 24 |                                    QSettings* settings,
 25 |                                    QLabel* increaseSpeedLabel,
 26 |                                    QLabel* decreaseSpeedLabel,
 27 |                                    QLabel* resetSpeedLabel,
 28 |                                    QWidget* parent)
 29 |   : QDialog(parent)
 30 |   , ui(new Ui::PreferenceDialog)
 31 |   , m_settings(settings)
 32 |   , m_increaseSpeedLabel(increaseSpeedLabel)
 33 |   , m_decreaseSpeedLabel(decreaseSpeedLabel)
 34 |   , m_resetSpeedLabel(resetSpeedLabel)
 35 |   , m_mainwindow(hMainWindow)
 36 | {
 37 |     ui->setupUi(this);
 38 |     setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
 39 | 
 40 |     ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确认"));
 41 |     ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("取消"));
 42 | 
 43 |     loadShortcut(
 44 |       HOTKEY_INCREASE_SPEED, CONFIG_HOTKEY_SPEEDUP, DEFAULT_HOTKEY_SPEEDUP);
 45 |     loadShortcut(
 46 |       HOTKEY_DECREASE_SPEED, CONFIG_HOTKEY_SPEEDDOWN, DEFAULT_HOTKEY_SPEEDDOWN);
 47 |     loadShortcut(
 48 |       HOTKEY_RESET_SPEED, CONFIG_HOTKEY_RESETSPEED, DEFAULT_HOTKEY_RERSETSPEED);
 49 |     loadShortcut(HOTKEY_SHIFT1, CONFIG_HOTKEY_SHIFT1, DEFAULT_HOTKEY_SHIFT1);
 50 |     loadShortcut(HOTKEY_SHIFT2, CONFIG_HOTKEY_SHIFT2, DEFAULT_HOTKEY_SHIFT2);
 51 |     loadShortcut(HOTKEY_SHIFT3, CONFIG_HOTKEY_SHIFT3, DEFAULT_HOTKEY_SHIFT3);
 52 |     loadShortcut(HOTKEY_SHIFT4, CONFIG_HOTKEY_SHIFT4, DEFAULT_HOTKEY_SHIFT4);
 53 |     loadShortcut(HOTKEY_SHIFT5, CONFIG_HOTKEY_SHIFT5, DEFAULT_HOTKEY_SHIFT5);
 54 | 
 55 |     m_shift1Value =
 56 |       m_settings->value(CONFIG_SHIFT1_VALUE, DEFAULT_SHIFT1_VALUE).toDouble();
 57 |     m_shift2Value =
 58 |       m_settings->value(CONFIG_SHIFT2_VALUE, DEFAULT_SHIFT2_VALUE).toDouble();
 59 |     m_shift3Value =
 60 |       m_settings->value(CONFIG_SHIFT3_VALUE, DEFAULT_SHIFT3_VALUE).toDouble();
 61 |     m_shift4Value =
 62 |       m_settings->value(CONFIG_SHIFT4_VALUE, DEFAULT_SHIFT4_VALUE).toDouble();
 63 |     m_shift5Value =
 64 |       m_settings->value(CONFIG_SHIFT5_VALUE, DEFAULT_SHIFT5_VALUE).toDouble();
 65 | 
 66 |     m_increaseStep =
 67 |       m_settings->value(CONFIG_INCREASE_STEP, DEFAULT_INCREASE_STEP).toInt();
 68 |     m_decreaseStep =
 69 |       m_settings->value(CONFIG_DECREASE_STEP, DEFAULT_DECREASE_STEP).toInt();
 70 | 
 71 |     connect(QGuiApplication::primaryScreen(),
 72 |             &QScreen::logicalDotsPerInchChanged,
 73 |             this,
 74 |             &PreferenceDialog::recreate);
 75 |     redraw();
 76 |     adjustSize();
 77 |     setupGlobalHotkeys();
 78 | }
 79 | 
 80 | PreferenceDialog::~PreferenceDialog()
 81 | {
 82 |     unregisterGlobalHotkeys();
 83 |     delete ui;
 84 | }
 85 | 
 86 | int
 87 | PreferenceDialog::getIncreaseStep()
 88 | {
 89 |     return m_increaseStep;
 90 | }
 91 | 
 92 | int
 93 | PreferenceDialog::getDecreaseStep()
 94 | {
 95 |     return m_decreaseStep;
 96 | }
 97 | 
 98 | double
 99 | PreferenceDialog::getShift1()
100 | {
101 |     return m_shift1Value;
102 | }
103 | 
104 | double
105 | PreferenceDialog::getShift2()
106 | {
107 |     return m_shift2Value;
108 | }
109 | 
110 | double
111 | PreferenceDialog::getShift3()
112 | {
113 |     return m_shift3Value;
114 | }
115 | 
116 | double
117 | PreferenceDialog::getShift4()
118 | {
119 |     return m_shift4Value;
120 | }
121 | 
122 | double
123 | PreferenceDialog::getShift5()
124 | {
125 |     return m_shift5Value;
126 | }
127 | 
128 | void
129 | PreferenceDialog::show()
130 | {
131 |     unregisterGlobalHotkeys();
132 |     QDialog::show();
133 | }
134 | 
135 | void
136 | PreferenceDialog::setupGlobalHotkeys()
137 | {
138 |     for (auto it = m_shortcuts.begin(); it != m_shortcuts.end(); it++)
139 |     {
140 |         int id = it.key();
141 |         QtCombinedKey combined = it.value();
142 | 
143 |         UINT vk = QSingleKeySequenceEdit::toVK(combined.key, combined.modifier);
144 |         UINT modifier = QSingleKeySequenceEdit::toModifier(combined.modifier);
145 |         RegisterHotKey(m_mainwindow, id, modifier, vk);
146 |     }
147 | 
148 |     qDebug() << "全局快捷键已注册:";
149 | }
150 | 
151 | void
152 | PreferenceDialog::unregisterGlobalHotkeys()
153 | {
154 |     for (auto it = m_shortcuts.begin(); it != m_shortcuts.end(); it++)
155 |     {
156 |         int id = it.key();
157 |         UnregisterHotKey(m_mainwindow, id);
158 |     }
159 |     qDebug() << "全局快捷键已注销";
160 | }
161 | 
162 | void
163 | PreferenceDialog::loadShortcut(int id,
164 |                                const QString& config,
165 |                                const QString& defaultValue)
166 | {
167 |     m_shortcuts.insert(id,
168 |                        QSingleKeySequenceEdit::toQtCombinedKey(
169 |                          m_settings->value(config, defaultValue).toString()));
170 | }
171 | 
172 | void
173 | PreferenceDialog::dump()
174 | {
175 |     dumpShortcut(CONFIG_HOTKEY_SPEEDUP,
176 |                  ui->speedUpKeySequenceEdit->getKeyText());
177 |     dumpShortcut(CONFIG_HOTKEY_SPEEDDOWN,
178 |                  ui->speedDownKeySequenceEdit->getKeyText());
179 |     dumpShortcut(CONFIG_HOTKEY_RESETSPEED,
180 |                  ui->resetSpeedKeySequenceEdit->getKeyText());
181 | 
182 |     dumpShortcut(CONFIG_HOTKEY_SHIFT1, ui->shift1KeySequenceEdit->getKeyText());
183 |     dumpShortcut(CONFIG_HOTKEY_SHIFT2, ui->shift2KeySequenceEdit->getKeyText());
184 |     dumpShortcut(CONFIG_HOTKEY_SHIFT3, ui->shift3KeySequenceEdit->getKeyText());
185 |     dumpShortcut(CONFIG_HOTKEY_SHIFT4, ui->shift4KeySequenceEdit->getKeyText());
186 |     dumpShortcut(CONFIG_HOTKEY_SHIFT5, ui->shift5KeySequenceEdit->getKeyText());
187 |     m_settings->setValue(CONFIG_INCREASE_STEP,
188 |                          ui->increaseStepSpinBox->value());
189 |     m_settings->setValue(CONFIG_DECREASE_STEP,
190 |                          ui->decreaseStepSpinBox->value());
191 |     m_settings->setValue(CONFIG_SHIFT1_VALUE, ui->shift1DoubleSpinBox->value());
192 |     m_settings->setValue(CONFIG_SHIFT2_VALUE, ui->shift2DoubleSpinBox->value());
193 |     m_settings->setValue(CONFIG_SHIFT3_VALUE, ui->shift3DoubleSpinBox->value());
194 |     m_settings->setValue(CONFIG_SHIFT4_VALUE, ui->shift4DoubleSpinBox->value());
195 |     m_settings->setValue(CONFIG_SHIFT5_VALUE, ui->shift5DoubleSpinBox->value());
196 |     m_settings->sync();
197 | }
198 | 
199 | void
200 | PreferenceDialog::dumpShortcut(const QString& config, const QString& keyText)
201 | {
202 |     m_settings->setValue(config, keyText);
203 | }
204 | 
205 | void
206 | PreferenceDialog::updateShortcut(int id, QSingleKeySequenceEdit* keyEdit)
207 | {
208 |     m_shortcuts[id] = keyEdit->getQtCombinedKey();
209 | }
210 | 
211 | void
212 | PreferenceDialog::update()
213 | {
214 |     updateShortcut(HOTKEY_INCREASE_SPEED, ui->speedUpKeySequenceEdit);
215 |     updateShortcut(HOTKEY_DECREASE_SPEED, ui->speedDownKeySequenceEdit);
216 |     updateShortcut(HOTKEY_RESET_SPEED, ui->resetSpeedKeySequenceEdit);
217 |     updateShortcut(HOTKEY_SHIFT1, ui->shift1KeySequenceEdit);
218 |     updateShortcut(HOTKEY_SHIFT2, ui->shift2KeySequenceEdit);
219 |     updateShortcut(HOTKEY_SHIFT3, ui->shift3KeySequenceEdit);
220 |     updateShortcut(HOTKEY_SHIFT4, ui->shift4KeySequenceEdit);
221 |     updateShortcut(HOTKEY_SHIFT5, ui->shift5KeySequenceEdit);
222 | 
223 |     m_increaseStep = ui->increaseStepSpinBox->value();
224 |     m_decreaseStep = ui->decreaseStepSpinBox->value();
225 |     m_shift1Value = ui->shift1DoubleSpinBox->value();
226 |     m_shift2Value = ui->shift2DoubleSpinBox->value();
227 |     m_shift3Value = ui->shift3DoubleSpinBox->value();
228 |     m_shift4Value = ui->shift4DoubleSpinBox->value();
229 |     m_shift5Value = ui->shift5DoubleSpinBox->value();
230 | }
231 | 
232 | void
233 | PreferenceDialog::redrawSpinBox(QSpinBox* spinbox, int value)
234 | {
235 |     spinbox->setValue(value);
236 | }
237 | 
238 | void
239 | PreferenceDialog::redrawSpinBox(QDoubleSpinBox* spinbox, double value)
240 | {
241 |     spinbox->setValue(value);
242 | }
243 | 
244 | void
245 | PreferenceDialog::redrawKeyEdit(QSingleKeySequenceEdit* keyEdit, int id)
246 | {
247 |     QtCombinedKey combinedKey = m_shortcuts[id];
248 |     keyEdit->setKeySequence(combinedKey.key | combinedKey.modifier);
249 | }
250 | 
251 | void
252 | PreferenceDialog::redraw()
253 | {
254 |     redrawKeyEdit(ui->speedUpKeySequenceEdit, HOTKEY_INCREASE_SPEED);
255 |     redrawKeyEdit(ui->speedDownKeySequenceEdit, HOTKEY_DECREASE_SPEED);
256 |     redrawKeyEdit(ui->resetSpeedKeySequenceEdit, HOTKEY_RESET_SPEED);
257 |     redrawKeyEdit(ui->shift1KeySequenceEdit, HOTKEY_SHIFT1);
258 |     redrawKeyEdit(ui->shift2KeySequenceEdit, HOTKEY_SHIFT2);
259 |     redrawKeyEdit(ui->shift3KeySequenceEdit, HOTKEY_SHIFT3);
260 |     redrawKeyEdit(ui->shift4KeySequenceEdit, HOTKEY_SHIFT4);
261 |     redrawKeyEdit(ui->shift5KeySequenceEdit, HOTKEY_SHIFT5);
262 | 
263 |     redrawSpinBox(ui->increaseStepSpinBox, m_increaseStep);
264 |     redrawSpinBox(ui->decreaseStepSpinBox, m_decreaseStep);
265 |     redrawSpinBox(ui->shift1DoubleSpinBox, m_shift1Value);
266 |     redrawSpinBox(ui->shift2DoubleSpinBox, m_shift2Value);
267 |     redrawSpinBox(ui->shift3DoubleSpinBox, m_shift3Value);
268 |     redrawSpinBox(ui->shift4DoubleSpinBox, m_shift4Value);
269 |     redrawSpinBox(ui->shift5DoubleSpinBox, m_shift5Value);
270 | 
271 |     m_increaseSpeedLabel->setText(
272 |       QString(tr("%1 增加速度"))
273 |         .arg(QSingleKeySequenceEdit::wrapText(
274 |           ui->speedUpKeySequenceEdit->getKeyText())));
275 | 
276 |     m_decreaseSpeedLabel->setText(
277 |       QString(tr("%1 减少速度"))
278 |         .arg(QSingleKeySequenceEdit::wrapText(
279 |           ui->speedDownKeySequenceEdit->getKeyText())));
280 | 
281 |     m_resetSpeedLabel->setText(
282 |       QString(tr("%1 重置速度"))
283 |         .arg(QSingleKeySequenceEdit::wrapText(
284 |           ui->resetSpeedKeySequenceEdit->getKeyText())));
285 | 
286 |     adjustSize();
287 | }
288 | 
289 | void
290 | PreferenceDialog::on_buttonBox_accepted()
291 | {
292 |     update();
293 |     setupGlobalHotkeys();
294 |     redraw();
295 |     dump();
296 | }
297 | 
298 | void
299 | PreferenceDialog::on_buttonBox_rejected()
300 | {
301 |     redraw();
302 |     setupGlobalHotkeys();
303 | }
304 | 
305 | void
306 | PreferenceDialog::recreate()
307 | {
308 |     layout()->invalidate();
309 |     layout()->activate();
310 |     adjustSize();
311 | }
312 | 


--------------------------------------------------------------------------------
/preferencedialog.h:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #ifndef PREFERENCEDIALOG_H
 19 | #define PREFERENCEDIALOG_H
 20 | 
 21 | #include <windows.h>
 22 | #include "config.h"
 23 | #include "qsinglekeysequenceedit.h"
 24 | #include <QDialog>
 25 | #include <QDoubleSpinBox>
 26 | #include <QLabel>
 27 | #include <QMap>
 28 | #include <QSettings>
 29 | #include <QSpinBox>
 30 | 
 31 | namespace Ui
 32 | {
 33 | class PreferenceDialog;
 34 | }
 35 | 
 36 | #define CONFIG_HOTKEY_SPEEDUP "Hotkey/SpeedUp"
 37 | #define CONFIG_HOTKEY_SPEEDDOWN "Hotkey/SpeedDown"
 38 | #define CONFIG_HOTKEY_RESETSPEED "Hotkey/ResetSpeed"
 39 | #define CONFIG_HOTKEY_SHIFT1 "Hotkey/Shift1"
 40 | #define CONFIG_HOTKEY_SHIFT2 "Hotkey/Shift2"
 41 | #define CONFIG_HOTKEY_SHIFT3 "Hotkey/Shift3"
 42 | #define CONFIG_HOTKEY_SHIFT4 "Hotkey/Shift4"
 43 | #define CONFIG_HOTKEY_SHIFT5 "Hotkey/Shift5"
 44 | 
 45 | #define CONFIG_SHIFT1_VALUE "Shift/Shift1Value"
 46 | #define CONFIG_SHIFT2_VALUE "Shift/Shift2Value"
 47 | #define CONFIG_SHIFT3_VALUE "Shift/Shift3Value"
 48 | #define CONFIG_SHIFT4_VALUE "Shift/Shift4Value"
 49 | #define CONFIG_SHIFT5_VALUE "Shift/Shift5Value"
 50 | #define CONFIG_INCREASE_STEP "Shift/IncreaseStep"
 51 | #define CONFIG_DECREASE_STEP "Shift/DecreaseStep"
 52 | 
 53 | #define DEFAULT_SHIFT1_VALUE 10.0
 54 | #define DEFAULT_SHIFT2_VALUE 20.0
 55 | #define DEFAULT_SHIFT3_VALUE 30.0
 56 | #define DEFAULT_SHIFT4_VALUE 40.0
 57 | #define DEFAULT_SHIFT5_VALUE 50.0
 58 | #define DEFAULT_INCREASE_STEP 1
 59 | #define DEFAULT_DECREASE_STEP 1
 60 | 
 61 | #define DEFAULT_HOTKEY_SPEEDUP "Ctrl+Alt+Up"
 62 | #define DEFAULT_HOTKEY_SPEEDDOWN "Ctrl+Alt+Down"
 63 | #define DEFAULT_HOTKEY_RERSETSPEED "Ctrl+Alt+0"
 64 | #define DEFAULT_HOTKEY_SHIFT1 "Ctrl+Alt+1"
 65 | #define DEFAULT_HOTKEY_SHIFT2 "Ctrl+Alt+2"
 66 | #define DEFAULT_HOTKEY_SHIFT3 "Ctrl+Alt+3"
 67 | #define DEFAULT_HOTKEY_SHIFT4 "Ctrl+Alt+4"
 68 | #define DEFAULT_HOTKEY_SHIFT5 "Ctrl+Alt+5"
 69 | 
 70 | class PreferenceDialog : public QDialog
 71 | {
 72 |     Q_OBJECT
 73 | 
 74 |   public:
 75 |     explicit PreferenceDialog(HWND hMainWindow,
 76 |                               QSettings* settings,
 77 |                               QLabel* increaseSpeedLabel,
 78 |                               QLabel* decreaseSpeedLabel,
 79 |                               QLabel* resetSpeedLabel,
 80 |                               QWidget* parent = nullptr);
 81 |     ~PreferenceDialog();
 82 | 
 83 |     int getIncreaseStep();
 84 | 
 85 |     int getDecreaseStep();
 86 | 
 87 |     double getShift1();
 88 | 
 89 |     double getShift2();
 90 | 
 91 |     double getShift3();
 92 | 
 93 |     double getShift4();
 94 | 
 95 |     double getShift5();
 96 | 
 97 |   public slots:
 98 |     void show();
 99 | 
100 |   private slots:
101 |     void on_buttonBox_accepted();
102 | 
103 |     void on_buttonBox_rejected();
104 | 
105 |     void recreate();
106 | 
107 |   private:
108 |     void setupGlobalHotkeys();
109 | 
110 |     void unregisterGlobalHotkeys();
111 | 
112 |     void loadShortcut(int id,
113 |                       const QString& config,
114 |                       const QString& defaultValue);
115 | 
116 |     void dumpShortcut(const QString& config, const QString& keyText);
117 |     void dump();
118 | 
119 |     void updateShortcut(int id, QSingleKeySequenceEdit* keyEdit);
120 |     void update();
121 | 
122 |     void redrawSpinBox(QSpinBox* spinbox, int value);
123 |     void redrawSpinBox(QDoubleSpinBox* spinbox, double value);
124 |     void redrawKeyEdit(QSingleKeySequenceEdit* keyEdit, int id);
125 |     void redraw();
126 | 
127 |     Ui::PreferenceDialog* ui;
128 | 
129 |     QSettings* m_settings;
130 | 
131 |     QLabel* m_increaseSpeedLabel;
132 |     QLabel* m_decreaseSpeedLabel;
133 |     QLabel* m_resetSpeedLabel;
134 | 
135 |     QMap<int, QtCombinedKey> m_shortcuts;
136 | 
137 |     double m_shift1Value;
138 |     double m_shift2Value;
139 |     double m_shift3Value;
140 |     double m_shift4Value;
141 |     double m_shift5Value;
142 | 
143 |     int m_increaseStep;
144 |     int m_decreaseStep;
145 | 
146 |     HWND m_mainwindow;
147 | };
148 | 
149 | #endif // PREFERENCEDIALOG_H
150 | 


--------------------------------------------------------------------------------
/processmonitor.h:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #ifndef PROCESSMONITOR_H
 19 | #define PROCESSMONITOR_H
 20 | #include <windows.h>
 21 | #include "winutils.h"
 22 | #include <QLabel>
 23 | #include <QMap>
 24 | #include <QObject>
 25 | #include <QProcess>
 26 | #include <QSettings>
 27 | #include <QThread>
 28 | #include <QTimer>
 29 | #include <QTreeWidget>
 30 | #include <tlhelp32.h>
 31 | 
 32 | #define CONFIG_TARGETNAMES_KEY "ProcessMonitor/TargetNames"
 33 | 
 34 | class ProcessMonitor : public QObject
 35 | {
 36 | Q_OBJECT
 37 | public:
 38 | explicit ProcessMonitor(QSettings*   settings,
 39 |                         QTreeWidget* treeWidget,
 40 |                         QLabel*      treeStatusLabel,
 41 |                         QLabel*      injector32StatusLabel,
 42 |                         QLabel*      injector64StatusLabel,
 43 | 
 44 |                         QObject*     parent = nullptr);
 45 | ~ProcessMonitor();
 46 | 
 47 | // 设置刷新间隔(毫秒)
 48 | void setInterval(int msec);
 49 | // 设置过滤
 50 | void setFilter(QString processName);
 51 | 
 52 | void changeSpeed(double factor);
 53 | 
 54 | public slots:
 55 | // 定时刷新槽函数
 56 | void refresh();
 57 | 
 58 | void start();
 59 | 
 60 | private slots:
 61 | void onItemChanged(QTreeWidgetItem* item, int column);
 62 | 
 63 | private:
 64 | QTreeWidget* m_treeWidget;
 65 | QLabel* m_treeStatusLabel;
 66 | QLabel* m_injector32StatusLabel;
 67 | QLabel* m_injector64StatusLabel;
 68 | QString m_filter;
 69 | QTimer* m_timer = nullptr;
 70 | QString m_dllPath;
 71 | 
 72 | QProcess* m_bridge32;
 73 | QProcess* m_bridge64;
 74 | 
 75 | QSettings* m_settings;
 76 | 
 77 | // 图标缓存
 78 | QHash<QString, QIcon> m_iconCache;
 79 | 
 80 | // 存储进程ID到TreeWidgetItem的映射
 81 | QMap<DWORD, QTreeWidgetItem*> m_processItems;
 82 | 
 83 | // 存储需要加速的进程
 84 | QSet<QString> m_targetNames;
 85 | 
 86 | void init();
 87 | 
 88 | void dump();
 89 | 
 90 | void update(const QList<ProcessInfo>& processList);
 91 | 
 92 | void injectDll(DWORD processId, bool is64Bit);
 93 | 
 94 | void unhookDll(DWORD processId, bool is64Bit);
 95 | 
 96 | void startBridge32();
 97 | 
 98 | void startBridge64();
 99 | 
100 | void healthcheckBridge();
101 | 
102 | void terminalBridge();
103 | 
104 | // 获取进程图标
105 | static QIcon getProcessIcon(QString processPath);
106 | 
107 | static QIcon getDefaultIcon(const QString& processName);
108 | 
109 | QIcon getProcessIconCached(DWORD proccessId);
110 | };
111 | 
112 | class SortTreeWidgetItem : public QTreeWidgetItem
113 | {
114 | public:
115 | SortTreeWidgetItem(QTreeWidget* parent = nullptr)
116 |     : QTreeWidgetItem(parent)
117 | {
118 | }
119 | 
120 | bool operator<(const QTreeWidgetItem& other) const override
121 | {
122 |     int column = treeWidget()->sortColumn();
123 | 
124 |     QVariant ldata = this->data(column, Qt::UserRole);
125 |     QVariant rdata = other.data(column, Qt::UserRole);
126 |     if (ldata.isValid() && rdata.isValid())
127 |     {
128 |         if (ldata.type() == QVariant::UInt && rdata.type() == QVariant::UInt)
129 |         {
130 |             return ldata.toUInt() < rdata.toUInt();
131 |         }
132 |         else
133 |         {
134 |             return ldata.toString() < rdata.toString();
135 |         }
136 |     }
137 |     else
138 |     {
139 |         QString ltext = this->text(column);
140 |         QString rtext = other.text(column);
141 |         return ltext < rtext;
142 |     }
143 | }
144 | 
145 | bool operator>(const QTreeWidgetItem& other) const
146 | {
147 |     int column = treeWidget()->sortColumn();
148 | 
149 |     QVariant ldata = this->data(column, Qt::UserRole);
150 |     QVariant rdata = other.data(column, Qt::UserRole);
151 |     if (ldata.isValid() && rdata.isValid())
152 |     {
153 |         if (ldata.type() == QVariant::UInt && rdata.type() == QVariant::UInt)
154 |         {
155 |             return ldata.toUInt() > rdata.toUInt();
156 |         }
157 |         else
158 |         {
159 |             return ldata.toString() > rdata.toString();
160 |         }
161 |     }
162 |     else
163 |     {
164 |         QString ltext = this->text(column);
165 |         QString rtext = other.text(column);
166 |         return ltext > rtext;
167 |     }
168 | }
169 | };
170 | 
171 | #endif // PROCESSMONITOR_H
172 | 


--------------------------------------------------------------------------------
/qsinglekeysequenceedit.cpp:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  * 
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  * 
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  * 
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #include "qsinglekeysequenceedit.h"
 19 | #include <QDebug>
 20 | 
 21 | QSingleKeySequenceEdit::QSingleKeySequenceEdit(QWidget* parent)
 22 |   : QKeySequenceEdit(parent)
 23 | {
 24 |     setStyleSheet(":focus {"
 25 |                   "    border: 2px solid #3498db;"
 26 |                   "    background-color: #ebf3fd;"
 27 |                   "    font-weight: bold;"
 28 |                   "    outline: none;"
 29 |                   "}");
 30 | 
 31 |     connect(this,
 32 |             &QKeySequenceEdit::keySequenceChanged,
 33 |             this,
 34 |             &QSingleKeySequenceEdit::update);
 35 | }
 36 | 
 37 | UINT
 38 | QSingleKeySequenceEdit::getVK()
 39 | {
 40 |     return toVK(m_key, m_modifier);
 41 | }
 42 | 
 43 | UINT
 44 | QSingleKeySequenceEdit::getModifier()
 45 | {
 46 |     return toModifier(m_modifier);
 47 | }
 48 | 
 49 | QtCombinedKey
 50 | QSingleKeySequenceEdit::getQtCombinedKey()
 51 | {
 52 |     return QtCombinedKey{ m_key, m_modifier };
 53 | }
 54 | 
 55 | QString
 56 | QSingleKeySequenceEdit::getKeyText()
 57 | {
 58 |     return keySequence().toString(QKeySequence::NativeText);
 59 | }
 60 | 
 61 | void
 62 | QSingleKeySequenceEdit::keyPressEvent(QKeyEvent* event)
 63 | {
 64 |     int key = event->key();
 65 |     Qt::KeyboardModifiers modifiers = event->modifiers();
 66 | 
 67 |     // 忽略单独的修饰键
 68 |     if (isModifierKey(key))
 69 |     {
 70 |         return;
 71 |     }
 72 | 
 73 |     m_key = key;
 74 |     m_modifier = modifiers;
 75 | 
 76 |     // 创建单个按键序列
 77 |     QKeySequence singleKey(key | modifiers);
 78 |     setKeySequence(singleKey);
 79 | 
 80 |     // 🔚 结束编辑
 81 |     emit editingFinished();
 82 |     clearFocus();
 83 | }
 84 | 
 85 | void
 86 | QSingleKeySequenceEdit::update()
 87 | {
 88 |     QKeySequence sequence = keySequence();
 89 | 
 90 |     if (sequence.isEmpty())
 91 |     {
 92 |         m_key = 0;
 93 |         m_modifier = Qt::NoModifier;
 94 |     }
 95 |     else
 96 |     {
 97 |         int combinedKey = sequence[0];
 98 |         m_modifier =
 99 |           Qt::KeyboardModifiers(combinedKey & Qt::KeyboardModifierMask);
100 |         m_key = combinedKey & ~Qt::KeyboardModifierMask;
101 |     }
102 | }
103 | 
104 | bool
105 | QSingleKeySequenceEdit::isModifierKey(int key) const
106 | {
107 |     return (key == Qt::Key_Control || key == Qt::Key_Alt ||
108 |             key == Qt::Key_Shift || key == Qt::Key_Meta);
109 | }
110 | 
111 | UINT
112 | QSingleKeySequenceEdit::toVK(int qtKey, Qt::KeyboardModifiers qtMod)
113 | {
114 |     // 🔤 字母键 A-Z
115 |     if (qtKey >= Qt::Key_A && qtKey <= Qt::Key_Z)
116 |     {
117 |         return qtKey; // Qt 和 Windows 的 A-Z 键码相同
118 |     }
119 | 
120 |     // 🔢 小键盘 0-9
121 |     if (qtMod & Qt::KeypadModifier)
122 |     {
123 |         switch (qtKey)
124 |         {
125 |                 // 数字键盘
126 |             case Qt::Key_0:
127 |                 return VK_NUMPAD0;
128 |             case Qt::Key_1:
129 |                 return VK_NUMPAD1;
130 |             case Qt::Key_2:
131 |                 return VK_NUMPAD2;
132 |             case Qt::Key_3:
133 |                 return VK_NUMPAD3;
134 |             case Qt::Key_4:
135 |                 return VK_NUMPAD4;
136 |             case Qt::Key_5:
137 |                 return VK_NUMPAD5;
138 |             case Qt::Key_6:
139 |                 return VK_NUMPAD6;
140 |             case Qt::Key_7:
141 |                 return VK_NUMPAD7;
142 |             case Qt::Key_8:
143 |                 return VK_NUMPAD8;
144 |             case Qt::Key_9:
145 |                 return VK_NUMPAD9;
146 |         }
147 |     }
148 | 
149 |     // 🔢 数字键 0-9
150 |     if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
151 |     {
152 |         return qtKey; // Qt 和 Windows 的 0-9 键码相同
153 |     }
154 | 
155 |     // 🎯 功能键映射
156 |     switch (qtKey)
157 |     {
158 |         // F1-F12
159 |         case Qt::Key_F1:
160 |             return VK_F1;
161 |         case Qt::Key_F2:
162 |             return VK_F2;
163 |         case Qt::Key_F3:
164 |             return VK_F3;
165 |         case Qt::Key_F4:
166 |             return VK_F4;
167 |         case Qt::Key_F5:
168 |             return VK_F5;
169 |         case Qt::Key_F6:
170 |             return VK_F6;
171 |         case Qt::Key_F7:
172 |             return VK_F7;
173 |         case Qt::Key_F8:
174 |             return VK_F8;
175 |         case Qt::Key_F9:
176 |             return VK_F9;
177 |         case Qt::Key_F10:
178 |             return VK_F10;
179 |         case Qt::Key_F11:
180 |             return VK_F11;
181 |         case Qt::Key_F12:
182 |             return VK_F12;
183 | 
184 |         // 方向键
185 |         case Qt::Key_Left:
186 |             return VK_LEFT;
187 |         case Qt::Key_Right:
188 |             return VK_RIGHT;
189 |         case Qt::Key_Up:
190 |             return VK_UP;
191 |         case Qt::Key_Down:
192 |             return VK_DOWN;
193 | 
194 |         // 特殊键
195 |         case Qt::Key_Enter:
196 |         case Qt::Key_Return:
197 |             return VK_RETURN;
198 |         case Qt::Key_Escape:
199 |             return VK_ESCAPE;
200 |         case Qt::Key_Tab:
201 |             return VK_TAB;
202 |         case Qt::Key_Backspace:
203 |             return VK_BACK;
204 |         case Qt::Key_Delete:
205 |             return VK_DELETE;
206 |         case Qt::Key_Insert:
207 |             return VK_INSERT;
208 |         case Qt::Key_Home:
209 |             return VK_HOME;
210 |         case Qt::Key_End:
211 |             return VK_END;
212 |         case Qt::Key_PageUp:
213 |             return VK_PRIOR;
214 |         case Qt::Key_PageDown:
215 |             return VK_NEXT;
216 |         case Qt::Key_Space:
217 |             return VK_SPACE;
218 | 
219 |         // 符号键
220 |         case Qt::Key_Semicolon:
221 |             return VK_OEM_1; // ;
222 |         case Qt::Key_Equal:
223 |             return VK_OEM_PLUS; // =
224 |         case Qt::Key_Comma:
225 |             return VK_OEM_COMMA; // ,
226 |         case Qt::Key_Minus:
227 |             return VK_OEM_MINUS; // -
228 |         case Qt::Key_Period:
229 |             return VK_OEM_PERIOD; // .
230 |         case Qt::Key_Slash:
231 |             return VK_OEM_2; // /
232 |         case Qt::Key_QuoteLeft:
233 |             return VK_OEM_3; // `
234 |         case Qt::Key_BracketLeft:
235 |             return VK_OEM_4; // [
236 |         case Qt::Key_Backslash:
237 |             return VK_OEM_5; //
238 |         case Qt::Key_BracketRight:
239 |             return VK_OEM_6; // ]
240 |         case Qt::Key_Apostrophe:
241 |             return VK_OEM_7; // '
242 | 
243 |         // 其他常用键
244 |         case Qt::Key_CapsLock:
245 |             return VK_CAPITAL;
246 |         case Qt::Key_NumLock:
247 |             return VK_NUMLOCK;
248 |         case Qt::Key_ScrollLock:
249 |             return VK_SCROLL;
250 |         case Qt::Key_Pause:
251 |             return VK_PAUSE;
252 |         case Qt::Key_Print:
253 |             return VK_PRINT;
254 | 
255 |         default:
256 |             qDebug() << "Unknown Qt key:" << qtKey;
257 |             return 0; // 未知按键
258 |     }
259 | }
260 | 
261 | UINT
262 | QSingleKeySequenceEdit::toModifier(Qt::KeyboardModifiers qtMod)
263 | {
264 |     UINT winMod = 0;
265 | 
266 |     if (qtMod & Qt::ControlModifier)
267 |     {
268 |         winMod |= MOD_CONTROL;
269 |     }
270 |     if (qtMod & Qt::AltModifier)
271 |     {
272 |         winMod |= MOD_ALT;
273 |     }
274 |     if (qtMod & Qt::ShiftModifier)
275 |     {
276 |         winMod |= MOD_SHIFT;
277 |     }
278 |     if (qtMod & Qt::MetaModifier)
279 |     {
280 |         winMod |= MOD_WIN; // Windows 键
281 |     }
282 | 
283 |     return winMod;
284 | }
285 | 
286 | QString
287 | QSingleKeySequenceEdit::wrapText(QString keyText)
288 | {
289 |     return keyText.replace("Up", "⬆️")
290 |       .replace("Down", "⬇️")
291 |       .replace("Left", "⬅️")
292 |       .replace("Right", "➡️");
293 | }
294 | 
295 | QtCombinedKey
296 | QSingleKeySequenceEdit::toQtCombinedKey(const QString& keyText)
297 | {
298 |     QKeySequence sequence = QKeySequence(keyText);
299 | 
300 |     if (!sequence.isEmpty())
301 |     {
302 |         int combinedKey = sequence[0];
303 |         Qt::KeyboardModifiers modifier =
304 |           Qt::KeyboardModifiers(combinedKey & Qt::KeyboardModifierMask);
305 |         int key = combinedKey & ~Qt::KeyboardModifierMask;
306 |         return QtCombinedKey{ key, modifier };
307 |     }
308 |     else
309 |     {
310 |         return QtCombinedKey{ 0, Qt::NoModifier };
311 |     }
312 | }
313 | 


--------------------------------------------------------------------------------
/qsinglekeysequenceedit.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  * 
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  * 
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  * 
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef QSINGLEKEYSEQUENCEEDIT_H
19 | #define QSINGLEKEYSEQUENCEEDIT_H
20 | 
21 | #include <windows.h>
22 | #include <QKeyEvent>
23 | #include <QKeySequenceEdit>
24 | #include <QObject>
25 | #define QKEYSEQUENCEEDIT_DEFAULT_PLACEHOLDER "点击设置热键"
26 | 
27 | struct QtCombinedKey
28 | {
29 |     int key;
30 |     Qt::KeyboardModifiers modifier;
31 | };
32 | 
33 | class QSingleKeySequenceEdit : public QKeySequenceEdit
34 | {
35 |     Q_OBJECT
36 | 
37 |   public:
38 |     explicit QSingleKeySequenceEdit(QWidget* parent = nullptr);
39 | 
40 |     static UINT toVK(int qtKey, Qt::KeyboardModifiers qtMod);
41 | 
42 |     static UINT toModifier(Qt::KeyboardModifiers qtMod);
43 | 
44 |     static QtCombinedKey toQtCombinedKey(const QString& keyText);
45 | 
46 |     static QString wrapText(QString keyText);
47 | 
48 |     UINT getVK();
49 | 
50 |     UINT getModifier();
51 | 
52 |     QtCombinedKey getQtCombinedKey();
53 | 
54 |     QString getKeyText();
55 | 
56 |   protected:
57 |     void keyPressEvent(QKeyEvent* event) override;
58 | 
59 |   private slots:
60 |     void update();
61 | 
62 |   private:
63 |     bool isModifierKey(int key) const;
64 | 
65 |     int m_key;
66 |     Qt::KeyboardModifiers m_modifier;
67 | };
68 | 
69 | #endif // QSINGLEKEYSEQUENCEEDIT_H
70 | 


--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
 1 | <RCC>
 2 |     <qresource prefix="/icons">
 3 |         <file>images/icon.ico</file>
 4 |         <file>images/logo.png</file>
 5 |         <file>images/icon_16.ico</file>
 6 |         <file>images/icon_32.ico</file>
 7 |         <file>images/icon_64.ico</file>
 8 |     </qresource>
 9 |     <qresource prefix="/i18n">
10 |         <file>translations/OpenSpeedy_en_US.qm</file>
11 |         <file>translations/OpenSpeedy_zh_CN.qm</file>
12 |         <file>translations/OpenSpeedy_zh_TW.qm</file>
13 |     </qresource>
14 | </RCC>
15 | 


--------------------------------------------------------------------------------
/script/build32.bat:
--------------------------------------------------------------------------------
 1 | @echo off
 2 | echo =================================
 3 | echo Build 32 bit Qt5.15 static library
 4 | echo =================================
 5 | 
 6 | if "%VCINSTALLDIR%"=="" (
 7 |     echo Initializing Visual Studio 2022 32-bit environment...
 8 |     call %VC_TOOLS_32BIT%
 9 | ) else (
10 |     echo Visual Studio environment already initialized
11 |     echo VCINSTALLDIR: %VCINSTALLDIR%
12 | )
13 | 
14 | set SCRIPT_DIR=%~dp0
15 | set SOURCE_DIR=%SCRIPT_DIR%..\
16 | set BUILD_DIR=%BUILD_DIR_32BIT%
17 | set QT_QMAKE_EXECUTABLE=%QT_QMAKE_EXECUTABLE_32BIT%
18 | 
19 | REM 将命令执行结果存储在变量中
20 | for /f "delims=" %%i in ('"%QT_QMAKE_EXECUTABLE%" -query QT_INSTALL_PREFIX') do set QT_INSTALL_PREFIX=%%i
21 | echo "%QT_QMAKE_EXECUTABLE%"
22 | echo "%QT_INSTALL_PREFIX%"
23 | 
24 | cmake.exe ^
25 | -DQT_QMAKE_EXECUTABLE:FILEPATH="%QT_QMAKE_EXECUTABLE%" ^
26 | -DCMAKE_PREFIX_PATH:PATH="%QT_INSTALL_PREFIX%" ^
27 | -DCMAKE_BUILD_TYPE=Release ^
28 | -S %SOURCE_DIR% ^
29 | -B %BUILD_DIR%
30 | 
31 | cmake.exe --build "%BUILD_DIR%" --config Release
32 | 


--------------------------------------------------------------------------------
/script/build64.bat:
--------------------------------------------------------------------------------
 1 | @echo off
 2 | echo =================================
 3 | echo Build 64 bit Qt5.15 static library
 4 | echo =================================
 5 | 
 6 | if "%VCINSTALLDIR%"=="" (
 7 |     echo Initializing Visual Studio 2022 64-bit environment...
 8 |     call %VC_TOOLS_64BIT%
 9 | ) else (
10 |     echo Visual Studio environment already initialized
11 |     echo VCINSTALLDIR: %VCINSTALLDIR%
12 | )
13 | 
14 | set SCRIPT_DIR=%~dp0
15 | set SOURCE_DIR=%SCRIPT_DIR%..\
16 | set BUILD_DIR=%BUILD_DIR_64BIT%
17 | set QT_QMAKE_EXECUTABLE=%QT_QMAKE_EXECUTABLE_64BIT%
18 | 
19 | REM 将命令执行结果存储在变量中
20 | for /f "delims=" %%i in ('"%QT_QMAKE_EXECUTABLE%" -query QT_INSTALL_PREFIX') do set QT_INSTALL_PREFIX=%%i
21 | echo "%QT_QMAKE_EXECUTABLE%"
22 | echo "%QT_INSTALL_PREFIX%"
23 | 
24 | cmake.exe ^
25 | -DQT_QMAKE_EXECUTABLE:FILEPATH="%QT_QMAKE_EXECUTABLE%" ^
26 | -DCMAKE_PREFIX_PATH:PATH="%QT_INSTALL_PREFIX%" ^
27 | -DCMAKE_BUILD_TYPE=Release ^
28 | -S %SOURCE_DIR% ^
29 | -B %BUILD_DIR%
30 | 
31 | cmake.exe --build "%BUILD_DIR%" --config Release
32 | 


--------------------------------------------------------------------------------
/script/initenv.bat:
--------------------------------------------------------------------------------
1 | set VC_TOOLS_32BIT="D:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Auxiliary\Build\vcvars32.bat"
2 | set VC_TOOLS_64BIT="D:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Auxiliary\Build\vcvars64.bat"
3 | set BUILD_DIR_32BIT="%~dp0..\build\CMAKE-32bit-Release"
4 | set BUILD_DIR_64BIT="%~dp0..\build\CMAKE-64bit-Release"
5 | set QT_QMAKE_EXECUTABLE_32BIT="E:\source\github\vcpkg\installed\x86-windows-static\tools\qt5\bin\qmake.exe"
6 | set QT_QMAKE_EXECUTABLE_64BIT="E:\source\github\vcpkg\installed\x64-windows-static\tools\qt5\bin\qmake.exe"


--------------------------------------------------------------------------------
/speedpatch/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.16)
 2 | 
 3 | project(speedpatch LANGUAGES CXX)
 4 | 
 5 | set(CMAKE_AUTOUIC ON)
 6 | set(CMAKE_AUTOMOC ON)
 7 | set(CMAKE_AUTORCC ON)
 8 | set(CMAKE_CXX_STANDARD 17)
 9 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
10 | 
11 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ..)
12 | 
13 | # 判断是32位还是64位
14 | if(CMAKE_SIZEOF_VOID_P EQUAL 8)
15 |     set(SUFFIX "64")
16 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
17 |     set(SUFFIX "32")
18 | else()
19 |     set(SUFFIX "")
20 | endif()
21 | 
22 | # 设置目标名带后缀
23 | set(TARGET_NAME "speedpatch${SUFFIX}")
24 | 
25 | add_library(${TARGET_NAME} SHARED
26 |   speedpatch.cpp
27 |   speedpatch.h
28 |   vcpkg.json
29 | 
30 | )
31 | 
32 | target_link_libraries(${TARGET_NAME} PRIVATE
33 |   minhook
34 | )
35 | target_compile_definitions(${TARGET_NAME} PRIVATE SPEEDPATCH_LIBRARY)
36 | 


--------------------------------------------------------------------------------
/speedpatch/SpeedPatch_global.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  * 
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  * 
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  * 
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef SPEEDPATCH_GLOBAL_H
19 | #define SPEEDPATCH_GLOBAL_H
20 | 
21 | 
22 | #endif // SPEEDPATCH_GLOBAL_H
23 | 


--------------------------------------------------------------------------------
/speedpatch/speedpatch.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef SPEEDPATCH_H
19 | #define SPEEDPATCH_H
20 | #include <windows.h>
21 | #include <string>
22 | 
23 | #if defined(SPEEDPATCH_LIBRARY)
24 | #define SPEEDPATCH_API __declspec(dllexport)
25 | #else
26 | #define SPEEDPATCH_API __declspec(dllimport)
27 | #endif
28 | 
29 | std::wstring
30 | GetCurrentProcessName();
31 | 
32 | std::wstring
33 | GetProcessFileMapName(DWORD processId);
34 | 
35 | extern "C"
36 | {
37 | SPEEDPATCH_API void Init();
38 | SPEEDPATCH_API void Clean();
39 | SPEEDPATCH_API BOOL GetStatus();
40 | SPEEDPATCH_API void SetProcessStatus(DWORD processId,BOOL status);
41 | SPEEDPATCH_API void ChangeSpeed(double factor_);
42 | SPEEDPATCH_API LRESULT CALLBACK HookProc(int    nCode,
43 |                                          WPARAM wParam,
44 |                                          LPARAM lParam
45 |                                          );
46 | }
47 | 
48 | #endif // SPEEDPATCH_H
49 | 


--------------------------------------------------------------------------------
/speedpatch/vcpkg.json:
--------------------------------------------------------------------------------
1 | {
2 |   "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
3 |   "name": "mypackage",
4 |   "version-string": "0.0.1",
5 |   "dependencies": [
6 |     "minhook"
7 |   ]
8 | }
9 | 


--------------------------------------------------------------------------------
/taskscheduler.cpp:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  *
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #include "taskscheduler.h"
 19 | #include <QDebug>
 20 | #include <QDir>
 21 | #include <QProcess>
 22 | TaskScheduler::TaskScheduler(QObject *parent) : QObject{parent}
 23 | {
 24 | }
 25 | 
 26 | TaskScheduler::~TaskScheduler()
 27 | {
 28 | }
 29 | 
 30 | bool TaskScheduler::createStartupTask(const QString &taskName,
 31 |                                       const QString &executablePath)
 32 | {
 33 |     if (taskName.isEmpty() || executablePath.isEmpty())
 34 |     {
 35 |         qWarning() << "任务名称或可执行文件路径不能为空";
 36 |         return false;
 37 |     }
 38 | 
 39 |     if (!QFile::exists(executablePath))
 40 |     {
 41 |         qWarning() << "可执行文件不存在" << executablePath;
 42 |         return false;
 43 |     }
 44 | 
 45 |     QStringList arguments;
 46 |     arguments << "/create"
 47 |               << "/f"
 48 |               << "/tn" << taskName << "/tr"
 49 |               << QString("\"%1\" --minimize-to-tray").arg(executablePath)
 50 |               << "/sc" << "onlogon"
 51 |               << "/delay" << "0000:10"
 52 |               << "/rl" << "highest";
 53 | 
 54 |     return execute(arguments);
 55 | }
 56 | 
 57 | bool TaskScheduler::deleteTask(const QString &taskName)
 58 | {
 59 |     if (taskName.isEmpty())
 60 |     {
 61 |         qWarning() << "任务名称不能为空";
 62 |         return false;
 63 |     }
 64 | 
 65 |     if (!isTaskExists(taskName))
 66 |     {
 67 |         qWarning() << "任务不存在, 无需删除" << taskName;
 68 |         return true;
 69 |     }
 70 | 
 71 |     QStringList arguments;
 72 |     arguments << "/delete"
 73 |               << "/f"
 74 |               << "/tn" << taskName;
 75 | 
 76 |     return execute(arguments);
 77 | }
 78 | 
 79 | bool TaskScheduler::enableTask(const QString &taskName, bool enable)
 80 | {
 81 |     if (!isTaskExists(taskName))
 82 |     {
 83 |         qWarning() << "任务不存在:" << taskName;
 84 |         return false;
 85 |     }
 86 | 
 87 |     QStringList arguments;
 88 |     arguments << "/change"
 89 |               << "/tn" << taskName << (enable ? "/enable" : "/disable");
 90 |     return execute(arguments);
 91 | }
 92 | 
 93 | bool TaskScheduler::isTaskExists(const QString &taskName)
 94 | {
 95 |     QStringList arguments;
 96 |     arguments << "/query" << "/tn" << taskName;
 97 | 
 98 |     return execute(arguments);
 99 | }
100 | 
101 | bool TaskScheduler::execute(const QStringList &arguments)
102 | {
103 |     QProcess process;
104 |     process.setProgram("schtasks");
105 |     process.setArguments(arguments);
106 | 
107 |     const int timeout = 10000;
108 |     process.start();
109 |     if (!process.waitForStarted(timeout))
110 |     {
111 |         qWarning() << "无法运行:" << process.errorString();
112 |         return false;
113 |     }
114 | 
115 |     if (!process.waitForFinished(timeout))
116 |     {
117 |         qWarning() << "执行超时";
118 |         process.kill();
119 |         return false;
120 |     }
121 | 
122 |     int exitcode = process.exitCode();
123 |     QString stdout_ = QString::fromLocal8Bit(process.readAllStandardOutput());
124 |     QString stderr_ = QString::fromLocal8Bit(process.readAllStandardError());
125 | 
126 |     if (exitcode == 0)
127 |     {
128 |         qDebug() << "执行成功:" << arguments;
129 |         qDebug() << "输出:" << stdout_;
130 |         return true;
131 |     }
132 |     else
133 |     {
134 |         qDebug() << "执行失败:" << arguments;
135 |         qDebug() << "错误输出:" << stderr_;
136 |         qDebug() << "标准输出:" << stdout_;
137 |         return false;
138 |     }
139 | }
140 | 
141 | bool TaskScheduler::createStartupShortcut(const QString &taskName,
142 |                                           const QString &executablePath)
143 | {
144 |     QString home = QDir::homePath();
145 |     QString startupDir =
146 |         home +
147 |         "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
148 |     QString shortcutPath = QDir(startupDir).absoluteFilePath(taskName + ".lnk");
149 |     QString arguments = "--minimize-to-tray";
150 | 
151 |     QString psScript =
152 |         QString("$WScriptShell = New-Object -ComObject WScript.Shell; "
153 |                 "$Shortcut = $WScriptShell.CreateShortcut('%1'); "
154 |                 "$Shortcut.TargetPath = '%2'; "
155 |                 "$Shortcut.Arguments = '%3'; "
156 |                 "$Shortcut.Description = '%4'; "
157 |                 "$Shortcut.Save()")
158 |         .arg(shortcutPath, executablePath, arguments,
159 |              QString("启动 %1").arg(QFileInfo(executablePath).baseName()));
160 | 
161 |     return executePs(psScript);
162 | }
163 | 
164 | bool TaskScheduler::deleteStartupShortcut(const QString &taskName)
165 | {
166 |     QString home = QDir::homePath();
167 |     QString startupDir =
168 |         home + "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
169 |     QString shortcutPath = QDir(startupDir).absoluteFilePath(taskName + ".lnk");
170 | 
171 |     QString psScript = QString("Remove-Item '%1' -Force").arg(shortcutPath);
172 | 
173 |     return executePs(psScript);
174 | }
175 | 
176 | bool TaskScheduler::isStartupShortcutExists(const QString &taskName)
177 | {
178 |     QString home = QDir::homePath();
179 |     QString startupDir =
180 |         home +
181 |         "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
182 |     QString shortcutPath = QDir(startupDir).absoluteFilePath(taskName + ".lnk");
183 | 
184 |     return QFile::exists(shortcutPath);
185 | }
186 | 
187 | bool TaskScheduler::executePs(const QString &psScript)
188 | {
189 |     QProcess process;
190 |     process.setProgram("powershell");
191 |     process.setArguments({"-ExecutionPolicy", "Bypass", "-Command", psScript});
192 | 
193 |     process.start();
194 |     if (!process.waitForStarted(5000))
195 |     {
196 |         qDebug() << "PowerShell 启动失败:" << process.errorString();
197 |         return false;
198 |     }
199 | 
200 |     if (process.waitForFinished(5000) && process.exitCode() == 0)
201 |     {
202 |         qDebug() << "PowerShell 执行成功";
203 |         return true;
204 |     }
205 |     else
206 |     {
207 |         QString error = QString::fromLocal8Bit(process.readAllStandardError());
208 |         qDebug() << "PowerShell 执行失败:" << error;
209 |     }
210 | 
211 |     return false;
212 | }
213 | 


--------------------------------------------------------------------------------
/taskscheduler.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef TASKSCHEDULER_H
19 | #define TASKSCHEDULER_H
20 | 
21 | #include <windows.h>
22 | #include <QObject>
23 | #include <QString>
24 | class TaskScheduler : public QObject
25 | {
26 |     Q_OBJECT
27 |   public:
28 |     explicit TaskScheduler(QObject *parent = nullptr);
29 |     ~TaskScheduler();
30 | 
31 |     bool createStartupTask(const QString &taskName,
32 |                            const QString &executablePath);
33 |     bool deleteTask(const QString &taskName);
34 |     bool enableTask(const QString &taskName, bool enable);
35 |     bool isTaskExists(const QString &taskName);
36 |     bool execute(const QStringList &arguments);
37 | 
38 |     bool createStartupShortcut(const QString &taskName,
39 |                                const QString &executablePath);
40 |     bool deleteStartupShortcut(const QString &taskName);
41 |     bool isStartupShortcutExists(const QString &taskName);
42 |     bool executePs(const QString &psScript);
43 | };
44 | 
45 | #endif // TASKSCHEDULER_H
46 | 


--------------------------------------------------------------------------------
/third_party/minhook/.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,def}]
13 | indent_style = space
14 | indent_size = 4
15 | 
16 | # Trim trailing whitespaces
17 | [*.{c,h,def,txt}]
18 | trim_trailing_whitespace = true
19 | 
20 | # UTF-8 with BOM
21 | [*.{c,h,def,txt}]
22 | charset=utf-8-bom
23 | 
24 | # C/C++ code formatting
25 | [*.{c,h}]
26 | cpp_space_pointer_reference_alignment = right
27 | 


--------------------------------------------------------------------------------
/third_party/minhook/.github/workflows/msbuild.yml:
--------------------------------------------------------------------------------
 1 | name: Build
 2 | 
 3 | on:
 4 |   workflow_dispatch:
 5 |   push:
 6 |     branches: [ "master" ]
 7 | 
 8 | env:
 9 |   # Path to the solution file relative to the root of the project.
10 |   SOLUTION_FILE_PATH: build/VC17/MinHookVC17.sln
11 | 
12 |   # Configuration type to build.
13 |   # You can convert this to a build matrix if you need coverage of multiple configuration types.
14 |   # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
15 |   BUILD_CONFIGURATION: Release
16 | 
17 | jobs:
18 |   build:
19 |     runs-on: windows-latest
20 | 
21 |     steps:
22 |       - uses: actions/checkout@v4
23 | 
24 |       - name: Add MSBuild to PATH
25 |         uses: microsoft/setup-msbuild@v2
26 | 
27 |       - name: Build Win32
28 |         # Add additional options to the MSBuild command line here (like platform or verbosity level).
29 |         # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
30 |         run: msbuild /m /p:Configuration=${{ env.BUILD_CONFIGURATION }} /p:Platform="Win32" ${{ env.SOLUTION_FILE_PATH }}
31 | 
32 |       - name: Build x64
33 |         # Add additional options to the MSBuild command line here (like platform or verbosity level).
34 |         # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
35 |         run: msbuild /m /p:Configuration=${{ env.BUILD_CONFIGURATION }} /p:Platform="x64" ${{ env.SOLUTION_FILE_PATH }}
36 | 
37 |       - name: Collect artifacts
38 |         shell: bash
39 |         run: |
40 |           mkdir "${{ runner.temp }}/artifacts"
41 |           mv "build/VC17/bin/${{ env.BUILD_CONFIGURATION }}" "${{ runner.temp }}/artifacts/bin"
42 |           mv "build/VC17/lib/${{ env.BUILD_CONFIGURATION }}" "${{ runner.temp }}/artifacts/lib"
43 |           cp -r include "${{ runner.temp }}/artifacts/include"
44 | 
45 |       - name: Package bin
46 |         uses: actions/upload-artifact@v4
47 |         with:
48 |           name: MinHook_bin
49 |           path: |
50 |             ${{ runner.temp }}/artifacts/bin/
51 |             ${{ runner.temp }}/artifacts/include/
52 | 
53 |       - name: Package lib
54 |         uses: actions/upload-artifact@v4
55 |         with:
56 |           name: MinHook_lib
57 |           path: |
58 |             ${{ runner.temp }}/artifacts/lib/
59 |             ${{ runner.temp }}/artifacts/include/
60 | 


--------------------------------------------------------------------------------
/third_party/minhook/.gitignore:
--------------------------------------------------------------------------------
 1 | #OS junk files
 2 | [Tt]humbs.db
 3 | *.DS_Store
 4 | 
 5 | #Visual Studio files
 6 | *.[Oo]bj
 7 | *.user
 8 | *.aps
 9 | *.pch
10 | *.vspscc
11 | *.vssscc
12 | *_i.c
13 | *_p.c
14 | *.ncb
15 | *.suo
16 | *.tlb
17 | *.tlh
18 | *.bak
19 | *.[Cc]ache
20 | *.ilk
21 | *.log
22 | *.sbr
23 | *.sdf
24 | *.opensdf
25 | *.unsuccessfulbuild
26 | ipch/
27 | obj/
28 | [Ll]ib
29 | [Bb]in
30 | [Dd]ebug*/
31 | [Rr]elease*/
32 | Ankh.NoLoad
33 | *.VC.db
34 | .vs/
35 | 
36 | #GCC files
37 | *.o
38 | *.d
39 | *.res
40 | *.dll
41 | *.a
42 | 
43 | #Visual Studio Code files
44 | .vscode/
45 | 


--------------------------------------------------------------------------------
/third_party/minhook/AUTHORS.txt:
--------------------------------------------------------------------------------
1 | Tsuda Kageyu <tsuda.kageyu@gmail.com>
2 |  Creator, maintainer
3 | 
4 | Michael Maltsev <leahcimmar@gmail.com>
5 |  Added "Queue" functions. A lot of bug fixes.
6 | 
7 | Andrey Unis <uniskz@gmail.com>
8 |  Rewrote the hook engine in plain C.
9 | 


--------------------------------------------------------------------------------
/third_party/minhook/CMakeLists.txt:
--------------------------------------------------------------------------------
  1 | #  MinHook - The Minimalistic API Hooking Library for x64/x86
  2 | #  Copyright (C) 2009-2017 Tsuda Kageyu.
  3 | #  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 COPYRIGHT HOLDERS AND CONTRIBUTORS
 16 | #  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 17 | #  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 18 | #  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 19 | #  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 20 | #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 21 | #  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 22 | #  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 23 | #  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 24 | #  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 25 | #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 | 
 27 | cmake_minimum_required(VERSION 3.0...3.5)
 28 | 
 29 | project(minhook LANGUAGES C)
 30 | 
 31 | include(CMakePackageConfigHelpers)
 32 | 
 33 | set(MINHOOK_MAJOR_VERSION 1)
 34 | set(MINHOOK_MINOR_VERSION 3)
 35 | set(MINHOOK_PATCH_VERSION 3)
 36 | set(MINHOOK_VERSION ${MINHOOK_MAJOR_VERSION}.${MINHOOK_MINOR_VERSION}.${MINHOOK_PATCH_VERSION})
 37 | 
 38 | ################
 39 | #    BUILD     # 
 40 | ################
 41 | 
 42 | option(BUILD_SHARED_LIBS "build shared version" OFF)
 43 | 
 44 | set(SOURCES_MINHOOK 
 45 |   "src/buffer.c"
 46 |   "src/hook.c"
 47 |   "src/trampoline.c"
 48 | )
 49 | 
 50 | if(CMAKE_SIZEOF_VOID_P EQUAL 8)
 51 |   set(SOURCES_HDE "src/hde/hde64.c")
 52 | else()
 53 |   set(SOURCES_HDE "src/hde/hde32.c")
 54 | endif()
 55 | 
 56 | if(BUILD_SHARED_LIBS)
 57 |   set(RESOURCES 
 58 |     "dll_resources/MinHook.rc"
 59 |     "dll_resources/MinHook.def"
 60 |   )
 61 | endif()
 62 | 
 63 | add_library(minhook ${SOURCES_MINHOOK} ${SOURCES_HDE} ${RESOURCES})
 64 | 
 65 | target_include_directories(minhook PUBLIC
 66 |   
lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
 67 |   
lt;INSTALL_INTERFACE:include>
 68 | )
 69 | 
 70 | target_include_directories(minhook PRIVATE "src/")
 71 | target_include_directories(minhook PRIVATE "src/hde/")
 72 | 
 73 | if(WIN32)
 74 |   set_target_properties(minhook PROPERTIES PREFIX "")
 75 |   if(CMAKE_SIZEOF_VOID_P EQUAL 8)   
 76 |     set_target_properties(minhook PROPERTIES DEBUG_POSTFIX ".x64d")
 77 |     set_target_properties(minhook PROPERTIES RELEASE_POSTFIX ".x64")
 78 |     set_target_properties(minhook PROPERTIES RELWITHDEBINFO_POSTFIX ".x64")
 79 |     set_target_properties(minhook PROPERTIES MINSIZEREL_POSTFIX ".x64")
 80 |   else()
 81 |     set_target_properties(minhook PROPERTIES DEBUG_POSTFIX ".x32d")
 82 |     set_target_properties(minhook PROPERTIES RELEASE_POSTFIX ".x32")
 83 |     set_target_properties(minhook PROPERTIES RELWITHDEBINFO_POSTFIX ".x32")
 84 |     set_target_properties(minhook PROPERTIES MINSIZEREL_POSTFIX ".x32")
 85 |   endif()
 86 | else()
 87 |   set_target_properties(minhook PROPERTIES PREFIX "lib")
 88 |   set_target_properties(minhook PROPERTIES POSTFIX "")
 89 |   set_target_properties(minhook PROPERTIES DEBUG_POSTFIX "d")
 90 | endif()
 91 | 
 92 | ################
 93 | # CMAKE CONFIG # 
 94 | ################
 95 | 
 96 | configure_package_config_file(
 97 |     "cmake/minhook-config.cmake.in"
 98 |     "minhook-config.cmake"
 99 |   INSTALL_DESTINATION 
100 |     "lib/minhook"
101 | )
102 | 
103 | write_basic_package_version_file(
104 |   "minhook-config-version.cmake"
105 | VERSION 
106 |   ${MINHOOK_VERSION}
107 | COMPATIBILITY
108 |   AnyNewerVersion
109 | )
110 | 
111 | install(
112 |   FILES 
113 |     "${CMAKE_CURRENT_BINARY_DIR}/minhook-config.cmake"
114 |     "${CMAKE_CURRENT_BINARY_DIR}/minhook-config-version.cmake"
115 |   DESTINATION 
116 |     "lib/minhook"
117 | )
118 | 
119 | ###################
120 | #     INSTALL     #
121 | ###################
122 | 
123 | install(TARGETS minhook
124 |         EXPORT minhook-targets
125 |         RUNTIME DESTINATION "bin"
126 |         ARCHIVE DESTINATION "lib"
127 |         LIBRARY DESTINATION "lib"
128 | )
129 | 
130 | install(
131 |   EXPORT
132 |     minhook-targets
133 |   NAMESPACE 
134 |     minhook::
135 |   DESTINATION 
136 |     "lib/minhook"
137 | )
138 | 
139 | install(
140 |   DIRECTORY include DESTINATION .
141 | )
142 | 


--------------------------------------------------------------------------------
/third_party/minhook/LICENSE.txt:
--------------------------------------------------------------------------------
 1 | MinHook - The Minimalistic API Hooking Library for x64/x86
 2 | Copyright (C) 2009-2017 Tsuda Kageyu.
 3 | 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | 
27 | ================================================================================
28 | Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov.
29 | ================================================================================
30 | Hacker Disassembler Engine 32 C
31 | Copyright (c) 2008-2009, Vyacheslav Patkov.
32 | All rights reserved.
33 | 
34 | Redistribution and use in source and binary forms, with or without
35 | modification, are permitted provided that the following conditions
36 | are met:
37 | 
38 |  1. Redistributions of source code must retain the above copyright
39 |     notice, this list of conditions and the following disclaimer.
40 |  2. Redistributions in binary form must reproduce the above copyright
41 |     notice, this list of conditions and the following disclaimer in the
42 |     documentation and/or other materials provided with the distribution.
43 | 
44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
48 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
49 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
50 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
52 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
53 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
54 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 | 
56 | -------------------------------------------------------------------------------
57 | Hacker Disassembler Engine 64 C
58 | Copyright (c) 2008-2009, Vyacheslav Patkov.
59 | All rights reserved.
60 | 
61 | Redistribution and use in source and binary forms, with or without
62 | modification, are permitted provided that the following conditions
63 | are met:
64 | 
65 |  1. Redistributions of source code must retain the above copyright
66 |     notice, this list of conditions and the following disclaimer.
67 |  2. Redistributions in binary form must reproduce the above copyright
68 |     notice, this list of conditions and the following disclaimer in the
69 |     documentation and/or other materials provided with the distribution.
70 | 
71 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
72 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
73 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
74 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
75 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
76 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
77 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
78 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
79 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
80 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
81 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/third_party/minhook/README.md:
--------------------------------------------------------------------------------
 1 | # MinHook
 2 | 
 3 | [![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause)
 4 | 
 5 | The Minimalistic x86/x64 API Hooking Library for Windows
 6 | 
 7 | http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
 8 | 
 9 | ### Version history
10 | 
11 | - **v1.3.4 - 28 Mar 2025**
12 |   * Improved error handling for enumerating and suspending threads.
13 |   * Visual Studio 2022 support.
14 |   * CMake support.
15 |   * Fixed compilation with Clang.
16 |   * Fixed compilation as C++ code.
17 | 
18 | - **v1.3.3 - 8 Jan 2017**
19 |   * Added a helper function ```MH_CreateHookApiEx```. (Thanks to asm256)
20 |   * Support Visual Studio 2017 RC.
21 | 
22 | - **v1.3.2.1 - 9 Nov 2015**  (Nuget package only)
23 |   * Fixed an insufficient support for Visual Studio 2015.
24 | 
25 | - **v1.3.2 - 1 Nov 2015**
26 |   * Support Visual Studio 2015.
27 |   * Support MinGW.
28 | 
29 | - **v1.3.2-beta3 - 21 Jul 2015**  (Nuget package only)
30 |   * Support MinGW. (Experimental)
31 | 
32 | - **v1.3.2-beta2 - 18 May 2015**
33 |   * Fixed some subtle bugs. (Thanks to RaMMicHaeL)
34 |   * Added a helper function ```MH_StatusToString```. (Thanks to Jan Klass)
35 | 
36 | - **v1.3.2-beta - 12 May 2015**
37 |   * Fixed a possible thread deadlock in x64 mode. (Thanks to Aleh Kazakevich)
38 |   * Reduced the footprint a little more.
39 |   * Support Visual Studio 2015 RC. (Experimental)
40 | 
41 | - **v1.3.1.1 - 7 Apr 2015**  (Nuget package only)
42 |   * Support for WDK8.0 and 8.1.
43 | 
44 | - **v1.3.1 - 19 Mar 2015**
45 |   * No major changes from v1.3.1-beta.
46 | 
47 | - **v1.3.1-beta - 11 Mar 2015**
48 |   * Added a helper function ```MH_CreateHookApi```. (Thanks to uniskz).
49 |   * Fixed a false memory leak reported by some tools.
50 |   * Fixed a degradated compatibility issue.
51 | 
52 | - **v1.3 - 13 Sep 2014**
53 |   * No major changes from v1.3-beta3.
54 | 
55 | - **v1.3-beta3 - 31 Jul 2014**
56 |   * Fixed some small bugs.
57 |   * Improved the memory management.
58 | 
59 | - **v1.3-beta2 - 21 Jul 2014**
60 |   * Changed the parameters to Windows-friendly types. (void* to LPVOID)
61 |   * Fixed some small bugs.
62 |   * Reorganized the source files.
63 |   * Reduced the footprint a little more.
64 | 
65 | - **v1.3-beta - 17 Jul 2014**
66 |   * Rewrote in plain C to reduce the footprint and memory usage. (suggested by Andrey Unis)
67 |   * Simplified the overall code base to make it more readable and maintainable.
68 |   * Changed the license from 3-clause to 2-clause BSD License.
69 | 
70 | - **v1.2 - 28 Sep 2013**
71 |   * Removed boost dependency ([jarredholman](https://github.com/jarredholman/minhook)).
72 |   * Fixed a small bug in the GetRelativeBranchDestination function ([pillbug99](http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx)).
73 |   * Added the ```MH_RemoveHook``` function, which removes a hook created with the ```MH_CreateHook``` function.
74 |   * Added the following functions to enable or disable multiple hooks in one go: ```MH_QueueEnableHook```, ```MH_QueueDisableHook```, ```MH_ApplyQueued```. This is the preferred way of handling multiple hooks as every call to `MH_EnableHook` or `MH_DisableHook` suspends and resumes all threads.
75 |   * Made the functions ```MH_EnableHook``` and ```MH_DisableHook``` enable/disable all created hooks when the ```MH_ALL_HOOKS``` parameter is passed. This, too, is an efficient way of handling multiple hooks.
76 |   * If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the ```MH_CreateHook``` function returns ```MH_ERROR_UNSUPPORTED_FUNCTION```. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 ([reported by Obble](http://www.codeproject.com/Messages/4578613/Re-Bug-LoadLibraryExW-hook-fails-on-windows-2008-r.aspx)).
77 | 
78 | - **v1.1 - 26 Nov 2009**
79 |   * Changed the interface to create a hook and a trampoline function in one go to prevent the detour function from being called before the trampoline function is created. ([reported by xliqz](http://www.codeproject.com/Messages/3280374/Unsafe.aspx))
80 |   * Shortened the function names from ```MinHook_*``` to ```MH_*``` to make them handier.
81 | 
82 | - **v1.0 - 22 Nov 2009**
83 |   * Initial release.
84 | 
85 | ### Building MinHook - Using vcpkg
86 | 
87 | You can download and install MinHook using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
88 | 
89 |     git clone https://github.com/microsoft/vcpkg
90 |     .\vcpkg\bootstrap-vcpkg.bat
91 |     .\vcpkg\vcpkg integrate install
92 |     .\vcpkg\vcpkg install minhook
93 | 
94 | The MinHook port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
95 | 


--------------------------------------------------------------------------------
/third_party/minhook/build/MinGW/make.bat:
--------------------------------------------------------------------------------
1 | windres -i ../../dll_resources/MinHook.rc -o MinHook_rc.o && dllwrap --driver-name g++ -o MinHook.dll -masm=intel --def ../../dll_resources/MinHook.def -Wl,-enable-stdcall-fixup -Wall MinHook_rc.o ../../src/*.c ../../src/HDE/*.c -I../../include -I../../src -Werror -std=c++11 -s -static-libgcc -static-libstdc++|| pause


--------------------------------------------------------------------------------
/third_party/minhook/build/MinGW/make.sh:
--------------------------------------------------------------------------------
1 | x86_64-w64-mingw32-windres -i ../../dll_resources/MinHook.rc -o MinHook_rc.o &&
2 | x86_64-w64-mingw32-dllwrap -o MinHook.dll -masm=intel --def ../../dll_resources/MinHook.def -Wl,-enable-stdcall-fixup -Wall MinHook_rc.o ../../src/*.c ../../src/hde/*.c -I../../include -I../../src -Werror -s -static-libgcc -static-libstdc++
3 | 


--------------------------------------------------------------------------------
/third_party/minhook/cmake/minhook-config.cmake.in:
--------------------------------------------------------------------------------
 1 | #  MinHook - The Minimalistic API Hooking Library for x64/x86
 2 | #  Copyright (C) 2009-2017 Tsuda Kageyu.
 3 | #  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 COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | #  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 | #  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 | #  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
19 | #  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 | #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 | #  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 | #  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 | #  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 | #  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | #  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | 
27 | set(MINHOOK_MAJOR_VERSION "@MINHOOK_MAJOR_VERSION@")
28 | set(MINHOOK_MINOR_VERSION "@MINHOOK_MINOR_VERSION@")
29 | set(MINHOOK_PATCH_VERSION "@MINHOOK_PATCH_VERSION@")
30 | set(MINHOOK_VERSION "@MINHOOK_VERSION@")
31 | 
32 | @PACKAGE_INIT@
33 |  
34 | set(MINHOOK_FOUND ON)
35 | 
36 | set_and_check(MINHOOK_INCLUDE_DIRS  "${PACKAGE_PREFIX_DIR}/include/")
37 | set_and_check(MINHOOK_LIBRARY_DIRS  "${PACKAGE_PREFIX_DIR}/lib")
38 |  
39 | include("${PACKAGE_PREFIX_DIR}/lib/minhook/minhook-targets.cmake")
40 | 


--------------------------------------------------------------------------------
/third_party/minhook/dll_resources/MinHook.def:
--------------------------------------------------------------------------------
 1 | EXPORTS
 2 |     MH_Initialize
 3 |     MH_Uninitialize
 4 | 
 5 |     MH_CreateHook
 6 |     MH_CreateHookApi
 7 |     MH_CreateHookApiEx
 8 |     MH_RemoveHook
 9 |     MH_EnableHook
10 |     MH_DisableHook
11 |     MH_QueueEnableHook
12 |     MH_QueueDisableHook
13 |     MH_ApplyQueued
14 |     MH_StatusToString
15 | 


--------------------------------------------------------------------------------
/third_party/minhook/include/MinHook.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 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
 32 |     #error MinHook supports only x86 and x64 systems.
 33 | #endif
 34 | 
 35 | #include <windows.h>
 36 | 
 37 | // MinHook Error Codes.
 38 | typedef enum MH_STATUS
 39 | {
 40 |     // Unknown error. Should not be returned.
 41 |     MH_UNKNOWN = -1,
 42 | 
 43 |     // Successful.
 44 |     MH_OK = 0,
 45 | 
 46 |     // MinHook is already initialized.
 47 |     MH_ERROR_ALREADY_INITIALIZED,
 48 | 
 49 |     // MinHook is not initialized yet, or already uninitialized.
 50 |     MH_ERROR_NOT_INITIALIZED,
 51 | 
 52 |     // The hook for the specified target function is already created.
 53 |     MH_ERROR_ALREADY_CREATED,
 54 | 
 55 |     // The hook for the specified target function is not created yet.
 56 |     MH_ERROR_NOT_CREATED,
 57 | 
 58 |     // The hook for the specified target function is already enabled.
 59 |     MH_ERROR_ENABLED,
 60 | 
 61 |     // The hook for the specified target function is not enabled yet, or already
 62 |     // disabled.
 63 |     MH_ERROR_DISABLED,
 64 | 
 65 |     // The specified pointer is invalid. It points the address of non-allocated
 66 |     // and/or non-executable region.
 67 |     MH_ERROR_NOT_EXECUTABLE,
 68 | 
 69 |     // The specified target function cannot be hooked.
 70 |     MH_ERROR_UNSUPPORTED_FUNCTION,
 71 | 
 72 |     // Failed to allocate memory.
 73 |     MH_ERROR_MEMORY_ALLOC,
 74 | 
 75 |     // Failed to change the memory protection.
 76 |     MH_ERROR_MEMORY_PROTECT,
 77 | 
 78 |     // The specified module is not loaded.
 79 |     MH_ERROR_MODULE_NOT_FOUND,
 80 | 
 81 |     // The specified function is not found.
 82 |     MH_ERROR_FUNCTION_NOT_FOUND
 83 | }
 84 | MH_STATUS;
 85 | 
 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
 87 | // MH_QueueEnableHook or MH_QueueDisableHook.
 88 | #define MH_ALL_HOOKS NULL
 89 | 
 90 | #ifdef __cplusplus
 91 | extern "C" {
 92 | #endif
 93 | 
 94 |     // Initialize the MinHook library. You must call this function EXACTLY ONCE
 95 |     // at the beginning of your program.
 96 |     MH_STATUS WINAPI MH_Initialize(VOID);
 97 | 
 98 |     // Uninitialize the MinHook library. You must call this function EXACTLY
 99 |     // ONCE at the end of your program.
100 |     MH_STATUS WINAPI MH_Uninitialize(VOID);
101 | 
102 |     // Creates a hook for the specified target function, in disabled state.
103 |     // Parameters:
104 |     //   pTarget     [in]  A pointer to the target function, which will be
105 |     //                     overridden by the detour function.
106 |     //   pDetour     [in]  A pointer to the detour function, which will override
107 |     //                     the target function.
108 |     //   ppOriginal  [out] A pointer to the trampoline function, which will be
109 |     //                     used to call the original target function.
110 |     //                     This parameter can be NULL.
111 |     MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
112 | 
113 |     // Creates a hook for the specified API function, in disabled state.
114 |     // Parameters:
115 |     //   pszModule   [in]  A pointer to the loaded module name which contains the
116 |     //                     target function.
117 |     //   pszProcName [in]  A pointer to the target function name, which will be
118 |     //                     overridden by the detour function.
119 |     //   pDetour     [in]  A pointer to the detour function, which will override
120 |     //                     the target function.
121 |     //   ppOriginal  [out] A pointer to the trampoline function, which will be
122 |     //                     used to call the original target function.
123 |     //                     This parameter can be NULL.
124 |     MH_STATUS WINAPI MH_CreateHookApi(
125 |         LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
126 | 
127 |     // Creates a hook for the specified API function, in disabled state.
128 |     // Parameters:
129 |     //   pszModule   [in]  A pointer to the loaded module name which contains the
130 |     //                     target function.
131 |     //   pszProcName [in]  A pointer to the target function name, which will be
132 |     //                     overridden by the detour function.
133 |     //   pDetour     [in]  A pointer to the detour function, which will override
134 |     //                     the target function.
135 |     //   ppOriginal  [out] A pointer to the trampoline function, which will be
136 |     //                     used to call the original target function.
137 |     //                     This parameter can be NULL.
138 |     //   ppTarget    [out] A pointer to the target function, which will be used
139 |     //                     with other functions.
140 |     //                     This parameter can be NULL.
141 |     MH_STATUS WINAPI MH_CreateHookApiEx(
142 |         LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
143 | 
144 |     // Removes an already created hook.
145 |     // Parameters:
146 |     //   pTarget [in] A pointer to the target function.
147 |     MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
148 | 
149 |     // Enables an already created hook.
150 |     // Parameters:
151 |     //   pTarget [in] A pointer to the target function.
152 |     //                If this parameter is MH_ALL_HOOKS, all created hooks are
153 |     //                enabled in one go.
154 |     MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
155 | 
156 |     // Disables an already created hook.
157 |     // Parameters:
158 |     //   pTarget [in] A pointer to the target function.
159 |     //                If this parameter is MH_ALL_HOOKS, all created hooks are
160 |     //                disabled in one go.
161 |     MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
162 | 
163 |     // Queues to enable an already created hook.
164 |     // Parameters:
165 |     //   pTarget [in] A pointer to the target function.
166 |     //                If this parameter is MH_ALL_HOOKS, all created hooks are
167 |     //                queued to be enabled.
168 |     MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
169 | 
170 |     // Queues to disable an already created hook.
171 |     // Parameters:
172 |     //   pTarget [in] A pointer to the target function.
173 |     //                If this parameter is MH_ALL_HOOKS, all created hooks are
174 |     //                queued to be disabled.
175 |     MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
176 | 
177 |     // Applies all queued changes in one go.
178 |     MH_STATUS WINAPI MH_ApplyQueued(VOID);
179 | 
180 |     // Translates the MH_STATUS to its name as a string.
181 |     const char *WINAPI MH_StatusToString(MH_STATUS status);
182 | 
183 | #ifdef __cplusplus
184 | }
185 | #endif
186 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/buffer.c:
--------------------------------------------------------------------------------
  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 | #include <windows.h>
 30 | #include "buffer.h"
 31 | 
 32 | // Size of each memory block. (= page size of VirtualAlloc)
 33 | #define MEMORY_BLOCK_SIZE 0x1000
 34 | 
 35 | // Max range for seeking a memory block. (= 1024MB)
 36 | #define MAX_MEMORY_RANGE 0x40000000
 37 | 
 38 | // Memory protection flags to check the executable address.
 39 | #define PAGE_EXECUTE_FLAGS \
 40 |     (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
 41 | 
 42 | // Memory slot.
 43 | typedef struct _MEMORY_SLOT
 44 | {
 45 |     union
 46 |     {
 47 |         struct _MEMORY_SLOT *pNext;
 48 |         UINT8 buffer[MEMORY_SLOT_SIZE];
 49 |     };
 50 | } MEMORY_SLOT, *PMEMORY_SLOT;
 51 | 
 52 | // Memory block info. Placed at the head of each block.
 53 | typedef struct _MEMORY_BLOCK
 54 | {
 55 |     struct _MEMORY_BLOCK *pNext;
 56 |     PMEMORY_SLOT pFree;         // First element of the free slot list.
 57 |     UINT usedCount;
 58 | } MEMORY_BLOCK, *PMEMORY_BLOCK;
 59 | 
 60 | //-------------------------------------------------------------------------
 61 | // Global Variables:
 62 | //-------------------------------------------------------------------------
 63 | 
 64 | // First element of the memory block list.
 65 | static PMEMORY_BLOCK g_pMemoryBlocks;
 66 | 
 67 | //-------------------------------------------------------------------------
 68 | VOID InitializeBuffer(VOID)
 69 | {
 70 |     // Nothing to do for now.
 71 | }
 72 | 
 73 | //-------------------------------------------------------------------------
 74 | VOID UninitializeBuffer(VOID)
 75 | {
 76 |     PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
 77 |     g_pMemoryBlocks = NULL;
 78 | 
 79 |     while (pBlock)
 80 |     {
 81 |         PMEMORY_BLOCK pNext = pBlock->pNext;
 82 |         VirtualFree(pBlock, 0, MEM_RELEASE);
 83 |         pBlock = pNext;
 84 |     }
 85 | }
 86 | 
 87 | //-------------------------------------------------------------------------
 88 | #if defined(_M_X64) || defined(__x86_64__)
 89 | static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
 90 | {
 91 |     ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
 92 | 
 93 |     // Round down to the allocation granularity.
 94 |     tryAddr -= tryAddr % dwAllocationGranularity;
 95 | 
 96 |     // Start from the previous allocation granularity multiply.
 97 |     tryAddr -= dwAllocationGranularity;
 98 | 
 99 |     while (tryAddr >= (ULONG_PTR)pMinAddr)
100 |     {
101 |         MEMORY_BASIC_INFORMATION mbi;
102 |         if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
103 |             break;
104 | 
105 |         if (mbi.State == MEM_FREE)
106 |             return (LPVOID)tryAddr;
107 | 
108 |         if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
109 |             break;
110 | 
111 |         tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
112 |     }
113 | 
114 |     return NULL;
115 | }
116 | #endif
117 | 
118 | //-------------------------------------------------------------------------
119 | #if defined(_M_X64) || defined(__x86_64__)
120 | static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
121 | {
122 |     ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
123 | 
124 |     // Round down to the allocation granularity.
125 |     tryAddr -= tryAddr % dwAllocationGranularity;
126 | 
127 |     // Start from the next allocation granularity multiply.
128 |     tryAddr += dwAllocationGranularity;
129 | 
130 |     while (tryAddr <= (ULONG_PTR)pMaxAddr)
131 |     {
132 |         MEMORY_BASIC_INFORMATION mbi;
133 |         if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
134 |             break;
135 | 
136 |         if (mbi.State == MEM_FREE)
137 |             return (LPVOID)tryAddr;
138 | 
139 |         tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
140 | 
141 |         // Round up to the next allocation granularity.
142 |         tryAddr += dwAllocationGranularity - 1;
143 |         tryAddr -= tryAddr % dwAllocationGranularity;
144 |     }
145 | 
146 |     return NULL;
147 | }
148 | #endif
149 | 
150 | //-------------------------------------------------------------------------
151 | static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
152 | {
153 |     PMEMORY_BLOCK pBlock;
154 | #if defined(_M_X64) || defined(__x86_64__)
155 |     ULONG_PTR minAddr;
156 |     ULONG_PTR maxAddr;
157 | 
158 |     SYSTEM_INFO si;
159 |     GetSystemInfo(&si);
160 |     minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
161 |     maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
162 | 
163 |     // pOrigin ± 512MB
164 |     if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
165 |         minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
166 | 
167 |     if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
168 |         maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
169 | 
170 |     // Make room for MEMORY_BLOCK_SIZE bytes.
171 |     maxAddr -= MEMORY_BLOCK_SIZE - 1;
172 | #endif
173 | 
174 |     // Look the registered blocks for a reachable one.
175 |     for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
176 |     {
177 | #if defined(_M_X64) || defined(__x86_64__)
178 |         // Ignore the blocks too far.
179 |         if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
180 |             continue;
181 | #endif
182 |         // The block has at least one unused slot.
183 |         if (pBlock->pFree != NULL)
184 |             return pBlock;
185 |     }
186 | 
187 | #if defined(_M_X64) || defined(__x86_64__)
188 |     // Alloc a new block above if not found.
189 |     {
190 |         LPVOID pAlloc = pOrigin;
191 |         while ((ULONG_PTR)pAlloc >= minAddr)
192 |         {
193 |             pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
194 |             if (pAlloc == NULL)
195 |                 break;
196 | 
197 |             pBlock = (PMEMORY_BLOCK)VirtualAlloc(
198 |                 pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
199 |             if (pBlock != NULL)
200 |                 break;
201 |         }
202 |     }
203 | 
204 |     // Alloc a new block below if not found.
205 |     if (pBlock == NULL)
206 |     {
207 |         LPVOID pAlloc = pOrigin;
208 |         while ((ULONG_PTR)pAlloc <= maxAddr)
209 |         {
210 |             pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
211 |             if (pAlloc == NULL)
212 |                 break;
213 | 
214 |             pBlock = (PMEMORY_BLOCK)VirtualAlloc(
215 |                 pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
216 |             if (pBlock != NULL)
217 |                 break;
218 |         }
219 |     }
220 | #else
221 |     // In x86 mode, a memory block can be placed anywhere.
222 |     pBlock = (PMEMORY_BLOCK)VirtualAlloc(
223 |         NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
224 | #endif
225 | 
226 |     if (pBlock != NULL)
227 |     {
228 |         // Build a linked list of all the slots.
229 |         PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
230 |         pBlock->pFree = NULL;
231 |         pBlock->usedCount = 0;
232 |         do
233 |         {
234 |             pSlot->pNext = pBlock->pFree;
235 |             pBlock->pFree = pSlot;
236 |             pSlot++;
237 |         } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
238 | 
239 |         pBlock->pNext = g_pMemoryBlocks;
240 |         g_pMemoryBlocks = pBlock;
241 |     }
242 | 
243 |     return pBlock;
244 | }
245 | 
246 | //-------------------------------------------------------------------------
247 | LPVOID AllocateBuffer(LPVOID pOrigin)
248 | {
249 |     PMEMORY_SLOT  pSlot;
250 |     PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
251 |     if (pBlock == NULL)
252 |         return NULL;
253 | 
254 |     // Remove an unused slot from the list.
255 |     pSlot = pBlock->pFree;
256 |     pBlock->pFree = pSlot->pNext;
257 |     pBlock->usedCount++;
258 | #ifdef _DEBUG
259 |     // Fill the slot with INT3 for debugging.
260 |     memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
261 | #endif
262 |     return pSlot;
263 | }
264 | 
265 | //-------------------------------------------------------------------------
266 | VOID FreeBuffer(LPVOID pBuffer)
267 | {
268 |     PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
269 |     PMEMORY_BLOCK pPrev = NULL;
270 |     ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
271 | 
272 |     while (pBlock != NULL)
273 |     {
274 |         if ((ULONG_PTR)pBlock == pTargetBlock)
275 |         {
276 |             PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
277 | #ifdef _DEBUG
278 |             // Clear the released slot for debugging.
279 |             memset(pSlot, 0x00, sizeof(MEMORY_SLOT));
280 | #endif
281 |             // Restore the released slot to the list.
282 |             pSlot->pNext = pBlock->pFree;
283 |             pBlock->pFree = pSlot;
284 |             pBlock->usedCount--;
285 | 
286 |             // Free if unused.
287 |             if (pBlock->usedCount == 0)
288 |             {
289 |                 if (pPrev)
290 |                     pPrev->pNext = pBlock->pNext;
291 |                 else
292 |                     g_pMemoryBlocks = pBlock->pNext;
293 | 
294 |                 VirtualFree(pBlock, 0, MEM_RELEASE);
295 |             }
296 | 
297 |             break;
298 |         }
299 | 
300 |         pPrev = pBlock;
301 |         pBlock = pBlock->pNext;
302 |     }
303 | }
304 | 
305 | //-------------------------------------------------------------------------
306 | BOOL IsExecutableAddress(LPVOID pAddress)
307 | {
308 |     MEMORY_BASIC_INFORMATION mi;
309 |     VirtualQuery(pAddress, &mi, sizeof(mi));
310 | 
311 |     return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
312 | }
313 | 


--------------------------------------------------------------------------------
/third_party/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 32
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 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/hde/hde32.c:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Hacker Disassembler Engine 32 C
  3 |  * Copyright (c) 2008-2009, Vyacheslav Patkov.
  4 |  * All rights reserved.
  5 |  *
  6 |  */
  7 | 
  8 | #if defined(_M_IX86) || defined(__i386__)
  9 | 
 10 | #include <string.h>
 11 | #include "hde32.h"
 12 | #include "table32.h"
 13 | 
 14 | unsigned int hde32_disasm(const void *code, hde32s *hs)
 15 | {
 16 |     uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
 17 |     uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
 18 | 
 19 |     memset(hs, 0, sizeof(hde32s));
 20 | 
 21 |     for (x = 16; x; x--)
 22 |         switch (c = *p++) {
 23 |             case 0xf3:
 24 |                 hs->p_rep = c;
 25 |                 pref |= PRE_F3;
 26 |                 break;
 27 |             case 0xf2:
 28 |                 hs->p_rep = c;
 29 |                 pref |= PRE_F2;
 30 |                 break;
 31 |             case 0xf0:
 32 |                 hs->p_lock = c;
 33 |                 pref |= PRE_LOCK;
 34 |                 break;
 35 |             case 0x26: case 0x2e: case 0x36:
 36 |             case 0x3e: case 0x64: case 0x65:
 37 |                 hs->p_seg = c;
 38 |                 pref |= PRE_SEG;
 39 |                 break;
 40 |             case 0x66:
 41 |                 hs->p_66 = c;
 42 |                 pref |= PRE_66;
 43 |                 break;
 44 |             case 0x67:
 45 |                 hs->p_67 = c;
 46 |                 pref |= PRE_67;
 47 |                 break;
 48 |             default:
 49 |                 goto pref_done;
 50 |         }
 51 |   pref_done:
 52 | 
 53 |     hs->flags = (uint32_t)pref << 23;
 54 | 
 55 |     if (!pref)
 56 |         pref |= PRE_NONE;
 57 | 
 58 |     if ((hs->opcode = c) == 0x0f) {
 59 |         hs->opcode2 = c = *p++;
 60 |         ht += DELTA_OPCODES;
 61 |     } else if (c >= 0xa0 && c <= 0xa3) {
 62 |         if (pref & PRE_67)
 63 |             pref |= PRE_66;
 64 |         else
 65 |             pref &= ~PRE_66;
 66 |     }
 67 | 
 68 |     opcode = c;
 69 |     cflags = ht[ht[opcode / 4] + (opcode % 4)];
 70 | 
 71 |     if (cflags == C_ERROR) {
 72 |         hs->flags |= F_ERROR | F_ERROR_OPCODE;
 73 |         cflags = 0;
 74 |         if ((opcode & -3) == 0x24)
 75 |             cflags++;
 76 |     }
 77 | 
 78 |     x = 0;
 79 |     if (cflags & C_GROUP) {
 80 |         uint16_t t;
 81 |         t = *(uint16_t *)(ht + (cflags & 0x7f));
 82 |         cflags = (uint8_t)t;
 83 |         x = (uint8_t)(t >> 8);
 84 |     }
 85 | 
 86 |     if (hs->opcode2) {
 87 |         ht = hde32_table + DELTA_PREFIXES;
 88 |         if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
 89 |             hs->flags |= F_ERROR | F_ERROR_OPCODE;
 90 |     }
 91 | 
 92 |     if (cflags & C_MODRM) {
 93 |         hs->flags |= F_MODRM;
 94 |         hs->modrm = c = *p++;
 95 |         hs->modrm_mod = m_mod = c >> 6;
 96 |         hs->modrm_rm = m_rm = c & 7;
 97 |         hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
 98 | 
 99 |         if (x && ((x << m_reg) & 0x80))
100 |             hs->flags |= F_ERROR | F_ERROR_OPCODE;
101 | 
102 |         if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
103 |             uint8_t t = opcode - 0xd9;
104 |             if (m_mod == 3) {
105 |                 ht = hde32_table + DELTA_FPU_MODRM + t*8;
106 |                 t = ht[m_reg] << m_rm;
107 |             } else {
108 |                 ht = hde32_table + DELTA_FPU_REG;
109 |                 t = ht[t] << m_reg;
110 |             }
111 |             if (t & 0x80)
112 |                 hs->flags |= F_ERROR | F_ERROR_OPCODE;
113 |         }
114 | 
115 |         if (pref & PRE_LOCK) {
116 |             if (m_mod == 3) {
117 |                 hs->flags |= F_ERROR | F_ERROR_LOCK;
118 |             } else {
119 |                 uint8_t *table_end, op = opcode;
120 |                 if (hs->opcode2) {
121 |                     ht = hde32_table + DELTA_OP2_LOCK_OK;
122 |                     table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
123 |                 } else {
124 |                     ht = hde32_table + DELTA_OP_LOCK_OK;
125 |                     table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
126 |                     op &= -2;
127 |                 }
128 |                 for (; ht != table_end; ht++)
129 |                     if (*ht++ == op) {
130 |                         if (!((*ht << m_reg) & 0x80))
131 |                             goto no_lock_error;
132 |                         else
133 |                             break;
134 |                     }
135 |                 hs->flags |= F_ERROR | F_ERROR_LOCK;
136 |               no_lock_error:
137 |                 ;
138 |             }
139 |         }
140 | 
141 |         if (hs->opcode2) {
142 |             switch (opcode) {
143 |                 case 0x20: case 0x22:
144 |                     m_mod = 3;
145 |                     if (m_reg > 4 || m_reg == 1)
146 |                         goto error_operand;
147 |                     else
148 |                         goto no_error_operand;
149 |                 case 0x21: case 0x23:
150 |                     m_mod = 3;
151 |                     if (m_reg == 4 || m_reg == 5)
152 |                         goto error_operand;
153 |                     else
154 |                         goto no_error_operand;
155 |             }
156 |         } else {
157 |             switch (opcode) {
158 |                 case 0x8c:
159 |                     if (m_reg > 5)
160 |                         goto error_operand;
161 |                     else
162 |                         goto no_error_operand;
163 |                 case 0x8e:
164 |                     if (m_reg == 1 || m_reg > 5)
165 |                         goto error_operand;
166 |                     else
167 |                         goto no_error_operand;
168 |             }
169 |         }
170 | 
171 |         if (m_mod == 3) {
172 |             uint8_t *table_end;
173 |             if (hs->opcode2) {
174 |                 ht = hde32_table + DELTA_OP2_ONLY_MEM;
175 |                 table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
176 |             } else {
177 |                 ht = hde32_table + DELTA_OP_ONLY_MEM;
178 |                 table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
179 |             }
180 |             for (; ht != table_end; ht += 2)
181 |                 if (*ht++ == opcode) {
182 |                     if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
183 |                         goto error_operand;
184 |                     else
185 |                         break;
186 |                 }
187 |             goto no_error_operand;
188 |         } else if (hs->opcode2) {
189 |             switch (opcode) {
190 |                 case 0x50: case 0xd7: case 0xf7:
191 |                     if (pref & (PRE_NONE | PRE_66))
192 |                         goto error_operand;
193 |                     break;
194 |                 case 0xd6:
195 |                     if (pref & (PRE_F2 | PRE_F3))
196 |                         goto error_operand;
197 |                     break;
198 |                 case 0xc5:
199 |                     goto error_operand;
200 |             }
201 |             goto no_error_operand;
202 |         } else
203 |             goto no_error_operand;
204 | 
205 |       error_operand:
206 |         hs->flags |= F_ERROR | F_ERROR_OPERAND;
207 |       no_error_operand:
208 | 
209 |         c = *p++;
210 |         if (m_reg <= 1) {
211 |             if (opcode == 0xf6)
212 |                 cflags |= C_IMM8;
213 |             else if (opcode == 0xf7)
214 |                 cflags |= C_IMM_P66;
215 |         }
216 | 
217 |         switch (m_mod) {
218 |             case 0:
219 |                 if (pref & PRE_67) {
220 |                     if (m_rm == 6)
221 |                         disp_size = 2;
222 |                 } else
223 |                     if (m_rm == 5)
224 |                         disp_size = 4;
225 |                 break;
226 |             case 1:
227 |                 disp_size = 1;
228 |                 break;
229 |             case 2:
230 |                 disp_size = 2;
231 |                 if (!(pref & PRE_67))
232 |                     disp_size <<= 1;
233 |                 break;
234 |         }
235 | 
236 |         if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
237 |             hs->flags |= F_SIB;
238 |             p++;
239 |             hs->sib = c;
240 |             hs->sib_scale = c >> 6;
241 |             hs->sib_index = (c & 0x3f) >> 3;
242 |             if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
243 |                 disp_size = 4;
244 |         }
245 | 
246 |         p--;
247 |         switch (disp_size) {
248 |             case 1:
249 |                 hs->flags |= F_DISP8;
250 |                 hs->disp.disp8 = *p;
251 |                 break;
252 |             case 2:
253 |                 hs->flags |= F_DISP16;
254 |                 hs->disp.disp16 = *(uint16_t *)p;
255 |                 break;
256 |             case 4:
257 |                 hs->flags |= F_DISP32;
258 |                 hs->disp.disp32 = *(uint32_t *)p;
259 |                 break;
260 |         }
261 |         p += disp_size;
262 |     } else if (pref & PRE_LOCK)
263 |         hs->flags |= F_ERROR | F_ERROR_LOCK;
264 | 
265 |     if (cflags & C_IMM_P66) {
266 |         if (cflags & C_REL32) {
267 |             if (pref & PRE_66) {
268 |                 hs->flags |= F_IMM16 | F_RELATIVE;
269 |                 hs->imm.imm16 = *(uint16_t *)p;
270 |                 p += 2;
271 |                 goto disasm_done;
272 |             }
273 |             goto rel32_ok;
274 |         }
275 |         if (pref & PRE_66) {
276 |             hs->flags |= F_IMM16;
277 |             hs->imm.imm16 = *(uint16_t *)p;
278 |             p += 2;
279 |         } else {
280 |             hs->flags |= F_IMM32;
281 |             hs->imm.imm32 = *(uint32_t *)p;
282 |             p += 4;
283 |         }
284 |     }
285 | 
286 |     if (cflags & C_IMM16) {
287 |         if (hs->flags & F_IMM32) {
288 |             hs->flags |= F_IMM16;
289 |             hs->disp.disp16 = *(uint16_t *)p;
290 |         } else if (hs->flags & F_IMM16) {
291 |             hs->flags |= F_2IMM16;
292 |             hs->disp.disp16 = *(uint16_t *)p;
293 |         } else {
294 |             hs->flags |= F_IMM16;
295 |             hs->imm.imm16 = *(uint16_t *)p;
296 |         }
297 |         p += 2;
298 |     }
299 |     if (cflags & C_IMM8) {
300 |         hs->flags |= F_IMM8;
301 |         hs->imm.imm8 = *p++;
302 |     }
303 | 
304 |     if (cflags & C_REL32) {
305 |       rel32_ok:
306 |         hs->flags |= F_IMM32 | F_RELATIVE;
307 |         hs->imm.imm32 = *(uint32_t *)p;
308 |         p += 4;
309 |     } else if (cflags & C_REL8) {
310 |         hs->flags |= F_IMM8 | F_RELATIVE;
311 |         hs->imm.imm8 = *p++;
312 |     }
313 | 
314 |   disasm_done:
315 | 
316 |     if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
317 |         hs->flags |= F_ERROR | F_ERROR_LENGTH;
318 |         hs->len = 15;
319 |     }
320 | 
321 |     return (unsigned int)hs->len;
322 | }
323 | 
324 | #endif // defined(_M_IX86) || defined(__i386__)
325 | 


--------------------------------------------------------------------------------
/third_party/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 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/hde/hde64.c:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Hacker Disassembler Engine 64 C
  3 |  * Copyright (c) 2008-2009, Vyacheslav Patkov.
  4 |  * All rights reserved.
  5 |  *
  6 |  */
  7 | 
  8 | #if defined(_M_X64) || defined(__x86_64__)
  9 | 
 10 | #include <string.h>
 11 | #include "hde64.h"
 12 | #include "table64.h"
 13 | 
 14 | unsigned int hde64_disasm(const void *code, hde64s *hs)
 15 | {
 16 |     uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
 17 |     uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
 18 |     uint8_t op64 = 0;
 19 | 
 20 |     memset(hs, 0, sizeof(hde64s));
 21 | 
 22 |     for (x = 16; x; x--)
 23 |         switch (c = *p++) {
 24 |             case 0xf3:
 25 |                 hs->p_rep = c;
 26 |                 pref |= PRE_F3;
 27 |                 break;
 28 |             case 0xf2:
 29 |                 hs->p_rep = c;
 30 |                 pref |= PRE_F2;
 31 |                 break;
 32 |             case 0xf0:
 33 |                 hs->p_lock = c;
 34 |                 pref |= PRE_LOCK;
 35 |                 break;
 36 |             case 0x26: case 0x2e: case 0x36:
 37 |             case 0x3e: case 0x64: case 0x65:
 38 |                 hs->p_seg = c;
 39 |                 pref |= PRE_SEG;
 40 |                 break;
 41 |             case 0x66:
 42 |                 hs->p_66 = c;
 43 |                 pref |= PRE_66;
 44 |                 break;
 45 |             case 0x67:
 46 |                 hs->p_67 = c;
 47 |                 pref |= PRE_67;
 48 |                 break;
 49 |             default:
 50 |                 goto pref_done;
 51 |         }
 52 |   pref_done:
 53 | 
 54 |     hs->flags = (uint32_t)pref << 23;
 55 | 
 56 |     if (!pref)
 57 |         pref |= PRE_NONE;
 58 | 
 59 |     if ((c & 0xf0) == 0x40) {
 60 |         hs->flags |= F_PREFIX_REX;
 61 |         if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
 62 |             op64++;
 63 |         hs->rex_r = (c & 7) >> 2;
 64 |         hs->rex_x = (c & 3) >> 1;
 65 |         hs->rex_b = c & 1;
 66 |         if (((c = *p++) & 0xf0) == 0x40) {
 67 |             opcode = c;
 68 |             goto error_opcode;
 69 |         }
 70 |     }
 71 | 
 72 |     if ((hs->opcode = c) == 0x0f) {
 73 |         hs->opcode2 = c = *p++;
 74 |         ht += DELTA_OPCODES;
 75 |     } else if (c >= 0xa0 && c <= 0xa3) {
 76 |         op64++;
 77 |         if (pref & PRE_67)
 78 |             pref |= PRE_66;
 79 |         else
 80 |             pref &= ~PRE_66;
 81 |     }
 82 | 
 83 |     opcode = c;
 84 |     cflags = ht[ht[opcode / 4] + (opcode % 4)];
 85 | 
 86 |     if (cflags == C_ERROR) {
 87 |       error_opcode:
 88 |         hs->flags |= F_ERROR | F_ERROR_OPCODE;
 89 |         cflags = 0;
 90 |         if ((opcode & -3) == 0x24)
 91 |             cflags++;
 92 |     }
 93 | 
 94 |     x = 0;
 95 |     if (cflags & C_GROUP) {
 96 |         uint16_t t;
 97 |         t = *(uint16_t *)(ht + (cflags & 0x7f));
 98 |         cflags = (uint8_t)t;
 99 |         x = (uint8_t)(t >> 8);
100 |     }
101 | 
102 |     if (hs->opcode2) {
103 |         ht = hde64_table + DELTA_PREFIXES;
104 |         if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
105 |             hs->flags |= F_ERROR | F_ERROR_OPCODE;
106 |     }
107 | 
108 |     if (cflags & C_MODRM) {
109 |         hs->flags |= F_MODRM;
110 |         hs->modrm = c = *p++;
111 |         hs->modrm_mod = m_mod = c >> 6;
112 |         hs->modrm_rm = m_rm = c & 7;
113 |         hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
114 | 
115 |         if (x && ((x << m_reg) & 0x80))
116 |             hs->flags |= F_ERROR | F_ERROR_OPCODE;
117 | 
118 |         if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
119 |             uint8_t t = opcode - 0xd9;
120 |             if (m_mod == 3) {
121 |                 ht = hde64_table + DELTA_FPU_MODRM + t*8;
122 |                 t = ht[m_reg] << m_rm;
123 |             } else {
124 |                 ht = hde64_table + DELTA_FPU_REG;
125 |                 t = ht[t] << m_reg;
126 |             }
127 |             if (t & 0x80)
128 |                 hs->flags |= F_ERROR | F_ERROR_OPCODE;
129 |         }
130 | 
131 |         if (pref & PRE_LOCK) {
132 |             if (m_mod == 3) {
133 |                 hs->flags |= F_ERROR | F_ERROR_LOCK;
134 |             } else {
135 |                 uint8_t *table_end, op = opcode;
136 |                 if (hs->opcode2) {
137 |                     ht = hde64_table + DELTA_OP2_LOCK_OK;
138 |                     table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
139 |                 } else {
140 |                     ht = hde64_table + DELTA_OP_LOCK_OK;
141 |                     table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
142 |                     op &= -2;
143 |                 }
144 |                 for (; ht != table_end; ht++)
145 |                     if (*ht++ == op) {
146 |                         if (!((*ht << m_reg) & 0x80))
147 |                             goto no_lock_error;
148 |                         else
149 |                             break;
150 |                     }
151 |                 hs->flags |= F_ERROR | F_ERROR_LOCK;
152 |               no_lock_error:
153 |                 ;
154 |             }
155 |         }
156 | 
157 |         if (hs->opcode2) {
158 |             switch (opcode) {
159 |                 case 0x20: case 0x22:
160 |                     m_mod = 3;
161 |                     if (m_reg > 4 || m_reg == 1)
162 |                         goto error_operand;
163 |                     else
164 |                         goto no_error_operand;
165 |                 case 0x21: case 0x23:
166 |                     m_mod = 3;
167 |                     if (m_reg == 4 || m_reg == 5)
168 |                         goto error_operand;
169 |                     else
170 |                         goto no_error_operand;
171 |             }
172 |         } else {
173 |             switch (opcode) {
174 |                 case 0x8c:
175 |                     if (m_reg > 5)
176 |                         goto error_operand;
177 |                     else
178 |                         goto no_error_operand;
179 |                 case 0x8e:
180 |                     if (m_reg == 1 || m_reg > 5)
181 |                         goto error_operand;
182 |                     else
183 |                         goto no_error_operand;
184 |             }
185 |         }
186 | 
187 |         if (m_mod == 3) {
188 |             uint8_t *table_end;
189 |             if (hs->opcode2) {
190 |                 ht = hde64_table + DELTA_OP2_ONLY_MEM;
191 |                 table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
192 |             } else {
193 |                 ht = hde64_table + DELTA_OP_ONLY_MEM;
194 |                 table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
195 |             }
196 |             for (; ht != table_end; ht += 2)
197 |                 if (*ht++ == opcode) {
198 |                     if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
199 |                         goto error_operand;
200 |                     else
201 |                         break;
202 |                 }
203 |             goto no_error_operand;
204 |         } else if (hs->opcode2) {
205 |             switch (opcode) {
206 |                 case 0x50: case 0xd7: case 0xf7:
207 |                     if (pref & (PRE_NONE | PRE_66))
208 |                         goto error_operand;
209 |                     break;
210 |                 case 0xd6:
211 |                     if (pref & (PRE_F2 | PRE_F3))
212 |                         goto error_operand;
213 |                     break;
214 |                 case 0xc5:
215 |                     goto error_operand;
216 |             }
217 |             goto no_error_operand;
218 |         } else
219 |             goto no_error_operand;
220 | 
221 |       error_operand:
222 |         hs->flags |= F_ERROR | F_ERROR_OPERAND;
223 |       no_error_operand:
224 | 
225 |         c = *p++;
226 |         if (m_reg <= 1) {
227 |             if (opcode == 0xf6)
228 |                 cflags |= C_IMM8;
229 |             else if (opcode == 0xf7)
230 |                 cflags |= C_IMM_P66;
231 |         }
232 | 
233 |         switch (m_mod) {
234 |             case 0:
235 |                 if (pref & PRE_67) {
236 |                     if (m_rm == 6)
237 |                         disp_size = 2;
238 |                 } else
239 |                     if (m_rm == 5)
240 |                         disp_size = 4;
241 |                 break;
242 |             case 1:
243 |                 disp_size = 1;
244 |                 break;
245 |             case 2:
246 |                 disp_size = 2;
247 |                 if (!(pref & PRE_67))
248 |                     disp_size <<= 1;
249 |                 break;
250 |         }
251 | 
252 |         if (m_mod != 3 && m_rm == 4) {
253 |             hs->flags |= F_SIB;
254 |             p++;
255 |             hs->sib = c;
256 |             hs->sib_scale = c >> 6;
257 |             hs->sib_index = (c & 0x3f) >> 3;
258 |             if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
259 |                 disp_size = 4;
260 |         }
261 | 
262 |         p--;
263 |         switch (disp_size) {
264 |             case 1:
265 |                 hs->flags |= F_DISP8;
266 |                 hs->disp.disp8 = *p;
267 |                 break;
268 |             case 2:
269 |                 hs->flags |= F_DISP16;
270 |                 hs->disp.disp16 = *(uint16_t *)p;
271 |                 break;
272 |             case 4:
273 |                 hs->flags |= F_DISP32;
274 |                 hs->disp.disp32 = *(uint32_t *)p;
275 |                 break;
276 |         }
277 |         p += disp_size;
278 |     } else if (pref & PRE_LOCK)
279 |         hs->flags |= F_ERROR | F_ERROR_LOCK;
280 | 
281 |     if (cflags & C_IMM_P66) {
282 |         if (cflags & C_REL32) {
283 |             if (pref & PRE_66) {
284 |                 hs->flags |= F_IMM16 | F_RELATIVE;
285 |                 hs->imm.imm16 = *(uint16_t *)p;
286 |                 p += 2;
287 |                 goto disasm_done;
288 |             }
289 |             goto rel32_ok;
290 |         }
291 |         if (op64) {
292 |             hs->flags |= F_IMM64;
293 |             hs->imm.imm64 = *(uint64_t *)p;
294 |             p += 8;
295 |         } else if (!(pref & PRE_66)) {
296 |             hs->flags |= F_IMM32;
297 |             hs->imm.imm32 = *(uint32_t *)p;
298 |             p += 4;
299 |         } else
300 |             goto imm16_ok;
301 |     }
302 | 
303 | 
304 |     if (cflags & C_IMM16) {
305 |       imm16_ok:
306 |         hs->flags |= F_IMM16;
307 |         hs->imm.imm16 = *(uint16_t *)p;
308 |         p += 2;
309 |     }
310 |     if (cflags & C_IMM8) {
311 |         hs->flags |= F_IMM8;
312 |         hs->imm.imm8 = *p++;
313 |     }
314 | 
315 |     if (cflags & C_REL32) {
316 |       rel32_ok:
317 |         hs->flags |= F_IMM32 | F_RELATIVE;
318 |         hs->imm.imm32 = *(uint32_t *)p;
319 |         p += 4;
320 |     } else if (cflags & C_REL8) {
321 |         hs->flags |= F_IMM8 | F_RELATIVE;
322 |         hs->imm.imm8 = *p++;
323 |     }
324 | 
325 |   disasm_done:
326 | 
327 |     if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
328 |         hs->flags |= F_ERROR | F_ERROR_LENGTH;
329 |         hs->len = 15;
330 |     }
331 | 
332 |     return (unsigned int)hs->len;
333 | }
334 | 
335 | #endif // defined(_M_X64) || defined(__x86_64__)
336 | 


--------------------------------------------------------------------------------
/third_party/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 | 


--------------------------------------------------------------------------------
/third_party/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 <windows.h>
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 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/hde/table32.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Hacker Disassembler Engine 32 C
 3 |  * Copyright (c) 2008-2009, Vyacheslav Patkov.
 4 |  * All rights reserved.
 5 |  *
 6 |  */
 7 | 
 8 | #define C_NONE    0x00
 9 | #define C_MODRM   0x01
10 | #define C_IMM8    0x02
11 | #define C_IMM16   0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8    0x20
14 | #define C_REL32   0x40
15 | #define C_GROUP   0x80
16 | #define C_ERROR   0xff
17 | 
18 | #define PRE_ANY  0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2   0x02
21 | #define PRE_F3   0x04
22 | #define PRE_66   0x08
23 | #define PRE_67   0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG  0x40
26 | #define PRE_ALL  0xff
27 | 
28 | #define DELTA_OPCODES      0x4a
29 | #define DELTA_FPU_REG      0xf1
30 | #define DELTA_FPU_MODRM    0xf8
31 | #define DELTA_PREFIXES     0x130
32 | #define DELTA_OP_LOCK_OK   0x1a1
33 | #define DELTA_OP2_LOCK_OK  0x1b9
34 | #define DELTA_OP_ONLY_MEM  0x1cb
35 | #define DELTA_OP2_ONLY_MEM 0x1da
36 | 
37 | unsigned char hde32_table[] = {
38 |   0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
39 |   0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
40 |   0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
41 |   0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
42 |   0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
43 |   0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
44 |   0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
45 |   0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
46 |   0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
47 |   0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
48 |   0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
49 |   0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
50 |   0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
51 |   0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
52 |   0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
53 |   0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
54 |   0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
55 |   0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
56 |   0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 |   0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
58 |   0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
59 |   0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
60 |   0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
61 |   0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
62 |   0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
63 |   0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
64 |   0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
65 |   0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
66 |   0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
67 |   0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
68 |   0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
69 |   0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
70 |   0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
71 |   0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
72 |   0xe7,0x08,0x00,0xf0,0x02,0x00
73 | };
74 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/hde/table64.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Hacker Disassembler Engine 64 C
 3 |  * Copyright (c) 2008-2009, Vyacheslav Patkov.
 4 |  * All rights reserved.
 5 |  *
 6 |  */
 7 | 
 8 | #define C_NONE    0x00
 9 | #define C_MODRM   0x01
10 | #define C_IMM8    0x02
11 | #define C_IMM16   0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8    0x20
14 | #define C_REL32   0x40
15 | #define C_GROUP   0x80
16 | #define C_ERROR   0xff
17 | 
18 | #define PRE_ANY  0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2   0x02
21 | #define PRE_F3   0x04
22 | #define PRE_66   0x08
23 | #define PRE_67   0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG  0x40
26 | #define PRE_ALL  0xff
27 | 
28 | #define DELTA_OPCODES      0x4a
29 | #define DELTA_FPU_REG      0xfd
30 | #define DELTA_FPU_MODRM    0x104
31 | #define DELTA_PREFIXES     0x13c
32 | #define DELTA_OP_LOCK_OK   0x1ae
33 | #define DELTA_OP2_LOCK_OK  0x1c6
34 | #define DELTA_OP_ONLY_MEM  0x1d8
35 | #define DELTA_OP2_ONLY_MEM 0x1e7
36 | 
37 | unsigned char hde64_table[] = {
38 |   0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
39 |   0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
40 |   0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
41 |   0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
42 |   0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
43 |   0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
44 |   0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
45 |   0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
46 |   0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
47 |   0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
48 |   0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
49 |   0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
50 |   0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
51 |   0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
52 |   0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
53 |   0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
54 |   0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
55 |   0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
56 |   0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
57 |   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
58 |   0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
59 |   0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
60 |   0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
61 |   0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
62 |   0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
63 |   0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
64 |   0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
65 |   0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
66 |   0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
67 |   0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
68 |   0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
69 |   0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
70 |   0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
71 |   0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
72 |   0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
73 |   0x00,0xf0,0x02,0x00
74 | };
75 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/trampoline.c:
--------------------------------------------------------------------------------
  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 | #include <windows.h>
 30 | 
 31 | #if defined(_MSC_VER) && !defined(MINHOOK_DISABLE_INTRINSICS)
 32 |     #define ALLOW_INTRINSICS
 33 |     #include <intrin.h>
 34 | #endif
 35 | 
 36 | #ifndef ARRAYSIZE
 37 |     #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
 38 | #endif
 39 | 
 40 | #if defined(_M_X64) || defined(__x86_64__)
 41 |     #include "./hde/hde64.h"
 42 |     typedef hde64s HDE;
 43 |     #define HDE_DISASM(code, hs) hde64_disasm(code, hs)
 44 | #else
 45 |     #include "./hde/hde32.h"
 46 |     typedef hde32s HDE;
 47 |     #define HDE_DISASM(code, hs) hde32_disasm(code, hs)
 48 | #endif
 49 | 
 50 | #include "trampoline.h"
 51 | #include "buffer.h"
 52 | 
 53 | // Maximum size of a trampoline function.
 54 | #if defined(_M_X64) || defined(__x86_64__)
 55 |     #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
 56 | #else
 57 |     #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
 58 | #endif
 59 | 
 60 | //-------------------------------------------------------------------------
 61 | static BOOL IsCodePadding(LPBYTE pInst, UINT size)
 62 | {
 63 |     UINT i;
 64 | 
 65 |     if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
 66 |         return FALSE;
 67 | 
 68 |     for (i = 1; i < size; ++i)
 69 |     {
 70 |         if (pInst[i] != pInst[0])
 71 |             return FALSE;
 72 |     }
 73 |     return TRUE;
 74 | }
 75 | 
 76 | //-------------------------------------------------------------------------
 77 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
 78 | {
 79 | #if defined(_M_X64) || defined(__x86_64__)
 80 |     CALL_ABS call = {
 81 |         0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
 82 |         0xEB, 0x08,             // EB 08:         JMP +10
 83 |         0x0000000000000000ULL   // Absolute destination address
 84 |     };
 85 |     JMP_ABS jmp = {
 86 |         0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
 87 |         0x0000000000000000ULL   // Absolute destination address
 88 |     };
 89 |     JCC_ABS jcc = {
 90 |         0x70, 0x0E,             // 7* 0E:         J** +16
 91 |         0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
 92 |         0x0000000000000000ULL   // Absolute destination address
 93 |     };
 94 | #else
 95 |     CALL_REL call = {
 96 |         0xE8,                   // E8 xxxxxxxx: CALL +5+xxxxxxxx
 97 |         0x00000000              // Relative destination address
 98 |     };
 99 |     JMP_REL jmp = {
100 |         0xE9,                   // E9 xxxxxxxx: JMP +5+xxxxxxxx
101 |         0x00000000              // Relative destination address
102 |     };
103 |     JCC_REL jcc = {
104 |         0x0F, 0x80,             // 0F8* xxxxxxxx: J** +6+xxxxxxxx
105 |         0x00000000              // Relative destination address
106 |     };
107 | #endif
108 | 
109 |     UINT8     oldPos   = 0;
110 |     UINT8     newPos   = 0;
111 |     ULONG_PTR jmpDest  = 0;     // Destination address of an internal jump.
112 |     BOOL      finished = FALSE; // Is the function completed?
113 | #if defined(_M_X64) || defined(__x86_64__)
114 |     UINT8     instBuf[16];
115 | #endif
116 | 
117 |     ct->patchAbove = FALSE;
118 |     ct->nIP        = 0;
119 | 
120 |     do
121 |     {
122 |         HDE       hs;
123 |         UINT      copySize;
124 |         LPVOID    pCopySrc;
125 |         ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget     + oldPos;
126 |         ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
127 | 
128 |         copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
129 |         if (hs.flags & F_ERROR)
130 |             return FALSE;
131 | 
132 |         pCopySrc = (LPVOID)pOldInst;
133 |         if (oldPos >= sizeof(JMP_REL))
134 |         {
135 |             // The trampoline function is long enough.
136 |             // Complete the function with the jump to the target function.
137 | #if defined(_M_X64) || defined(__x86_64__)
138 |             jmp.address = pOldInst;
139 | #else
140 |             jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
141 | #endif
142 |             pCopySrc = &jmp;
143 |             copySize = sizeof(jmp);
144 | 
145 |             finished = TRUE;
146 |         }
147 | #if defined(_M_X64) || defined(__x86_64__)
148 |         else if ((hs.modrm & 0xC7) == 0x05)
149 |         {
150 |             // Instructions using RIP relative addressing. (ModR/M = 00???101B)
151 | 
152 |             // Modify the RIP relative address.
153 |             PUINT32 pRelAddr;
154 | 
155 |             // Avoid using memcpy to reduce the footprint.
156 | #ifndef ALLOW_INTRINSICS
157 |             memcpy(instBuf, (LPBYTE)pOldInst, copySize);
158 | #else
159 |             __movsb(instBuf, (LPBYTE)pOldInst, copySize);
160 | #endif
161 |             pCopySrc = instBuf;
162 | 
163 |             // Relative address is stored at (instruction length - immediate value length - 4).
164 |             pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
165 |             *pRelAddr
166 |                 = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
167 | 
168 |             // Complete the function if JMP (FF /4).
169 |             if (hs.opcode == 0xFF && hs.modrm_reg == 4)
170 |                 finished = TRUE;
171 |         }
172 | #endif
173 |         else if (hs.opcode == 0xE8)
174 |         {
175 |             // Direct relative CALL
176 |             ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
177 | #if defined(_M_X64) || defined(__x86_64__)
178 |             call.address = dest;
179 | #else
180 |             call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
181 | #endif
182 |             pCopySrc = &call;
183 |             copySize = sizeof(call);
184 |         }
185 |         else if ((hs.opcode & 0xFD) == 0xE9)
186 |         {
187 |             // Direct relative JMP (EB or E9)
188 |             ULONG_PTR dest = pOldInst + hs.len;
189 | 
190 |             if (hs.opcode == 0xEB) // isShort jmp
191 |                 dest += (INT8)hs.imm.imm8;
192 |             else
193 |                 dest += (INT32)hs.imm.imm32;
194 | 
195 |             // Simply copy an internal jump.
196 |             if ((ULONG_PTR)ct->pTarget <= dest
197 |                 && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
198 |             {
199 |                 if (jmpDest < dest)
200 |                     jmpDest = dest;
201 |             }
202 |             else
203 |             {
204 | #if defined(_M_X64) || defined(__x86_64__)
205 |                 jmp.address = dest;
206 | #else
207 |                 jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
208 | #endif
209 |                 pCopySrc = &jmp;
210 |                 copySize = sizeof(jmp);
211 | 
212 |                 // Exit the function if it is not in the branch.
213 |                 finished = (pOldInst >= jmpDest);
214 |             }
215 |         }
216 |         else if ((hs.opcode & 0xF0) == 0x70
217 |             || (hs.opcode & 0xFC) == 0xE0
218 |             || (hs.opcode2 & 0xF0) == 0x80)
219 |         {
220 |             // Direct relative Jcc
221 |             ULONG_PTR dest = pOldInst + hs.len;
222 | 
223 |             if ((hs.opcode & 0xF0) == 0x70      // Jcc
224 |                 || (hs.opcode & 0xFC) == 0xE0)  // LOOPNZ/LOOPZ/LOOP/JECXZ
225 |                 dest += (INT8)hs.imm.imm8;
226 |             else
227 |                 dest += (INT32)hs.imm.imm32;
228 | 
229 |             // Simply copy an internal jump.
230 |             if ((ULONG_PTR)ct->pTarget <= dest
231 |                 && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
232 |             {
233 |                 if (jmpDest < dest)
234 |                     jmpDest = dest;
235 |             }
236 |             else if ((hs.opcode & 0xFC) == 0xE0)
237 |             {
238 |                 // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
239 |                 return FALSE;
240 |             }
241 |             else
242 |             {
243 |                 UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
244 | #if defined(_M_X64) || defined(__x86_64__)
245 |                 // Invert the condition in x64 mode to simplify the conditional jump logic.
246 |                 jcc.opcode  = 0x71 ^ cond;
247 |                 jcc.address = dest;
248 | #else
249 |                 jcc.opcode1 = 0x80 | cond;
250 |                 jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
251 | #endif
252 |                 pCopySrc = &jcc;
253 |                 copySize = sizeof(jcc);
254 |             }
255 |         }
256 |         else if ((hs.opcode & 0xFE) == 0xC2)
257 |         {
258 |             // RET (C2 or C3)
259 | 
260 |             // Complete the function if not in a branch.
261 |             finished = (pOldInst >= jmpDest);
262 |         }
263 | 
264 |         // Can't alter the instruction length in a branch.
265 |         if (pOldInst < jmpDest && copySize != hs.len)
266 |             return FALSE;
267 | 
268 |         // Trampoline function is too large.
269 |         if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
270 |             return FALSE;
271 | 
272 |         // Trampoline function has too many instructions.
273 |         if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
274 |             return FALSE;
275 | 
276 |         ct->oldIPs[ct->nIP] = oldPos;
277 |         ct->newIPs[ct->nIP] = newPos;
278 |         ct->nIP++;
279 | 
280 |         // Avoid using memcpy to reduce the footprint.
281 | #ifndef ALLOW_INTRINSICS
282 |         memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
283 | #else
284 |         __movsb((LPBYTE)ct->pTrampoline + newPos, (LPBYTE)pCopySrc, copySize);
285 | #endif
286 |         newPos += copySize;
287 |         oldPos += hs.len;
288 |     } while (!finished);
289 | 
290 |     // Is there enough place for a long jump?
291 |     if (oldPos < sizeof(JMP_REL)
292 |         && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
293 |     {
294 |         // Is there enough place for a short jump?
295 |         if (oldPos < sizeof(JMP_REL_SHORT)
296 |             && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
297 |         {
298 |             return FALSE;
299 |         }
300 | 
301 |         // Can we place the long jump above the function?
302 |         if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
303 |             return FALSE;
304 | 
305 |         if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
306 |             return FALSE;
307 | 
308 |         ct->patchAbove = TRUE;
309 |     }
310 | 
311 | #if defined(_M_X64) || defined(__x86_64__)
312 |     // Create a relay function.
313 |     jmp.address = (ULONG_PTR)ct->pDetour;
314 | 
315 |     ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
316 |     memcpy(ct->pRelay, &jmp, sizeof(jmp));
317 | #endif
318 | 
319 |     return TRUE;
320 | }
321 | 


--------------------------------------------------------------------------------
/third_party/minhook/src/trampoline.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 | #pragma pack(push, 1)
 32 | 
 33 | // Structs for writing x86/x64 instructions.
 34 | 
 35 | // 8-bit relative jump.
 36 | typedef struct _JMP_REL_SHORT
 37 | {
 38 |     UINT8  opcode;      // EB xx: JMP +2+xx
 39 |     UINT8  operand;
 40 | } JMP_REL_SHORT, *PJMP_REL_SHORT;
 41 | 
 42 | // 32-bit direct relative jump/call.
 43 | typedef struct _JMP_REL
 44 | {
 45 |     UINT8  opcode;      // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
 46 |     UINT32 operand;     // Relative destination address
 47 | } JMP_REL, *PJMP_REL, CALL_REL;
 48 | 
 49 | // 64-bit indirect absolute jump.
 50 | typedef struct _JMP_ABS
 51 | {
 52 |     UINT8  opcode0;     // FF25 00000000: JMP [+6]
 53 |     UINT8  opcode1;
 54 |     UINT32 dummy;
 55 |     UINT64 address;     // Absolute destination address
 56 | } JMP_ABS, *PJMP_ABS;
 57 | 
 58 | // 64-bit indirect absolute call.
 59 | typedef struct _CALL_ABS
 60 | {
 61 |     UINT8  opcode0;     // FF15 00000002: CALL [+6]
 62 |     UINT8  opcode1;
 63 |     UINT32 dummy0;
 64 |     UINT8  dummy1;      // EB 08:         JMP +10
 65 |     UINT8  dummy2;
 66 |     UINT64 address;     // Absolute destination address
 67 | } CALL_ABS;
 68 | 
 69 | // 32-bit direct relative conditional jumps.
 70 | typedef struct _JCC_REL
 71 | {
 72 |     UINT8  opcode0;     // 0F8* xxxxxxxx: J** +6+xxxxxxxx
 73 |     UINT8  opcode1;
 74 |     UINT32 operand;     // Relative destination address
 75 | } JCC_REL;
 76 | 
 77 | // 64bit indirect absolute conditional jumps that x64 lacks.
 78 | typedef struct _JCC_ABS
 79 | {
 80 |     UINT8  opcode;      // 7* 0E:         J** +16
 81 |     UINT8  dummy0;
 82 |     UINT8  dummy1;      // FF25 00000000: JMP [+6]
 83 |     UINT8  dummy2;
 84 |     UINT32 dummy3;
 85 |     UINT64 address;     // Absolute destination address
 86 | } JCC_ABS;
 87 | 
 88 | #pragma pack(pop)
 89 | 
 90 | typedef struct _TRAMPOLINE
 91 | {
 92 |     LPVOID pTarget;         // [In] Address of the target function.
 93 |     LPVOID pDetour;         // [In] Address of the detour function.
 94 |     LPVOID pTrampoline;     // [In] Buffer address for the trampoline and relay function.
 95 | 
 96 | #if defined(_M_X64) || defined(__x86_64__)
 97 |     LPVOID pRelay;          // [Out] Address of the relay function.
 98 | #endif
 99 |     BOOL   patchAbove;      // [Out] Should use the hot patch area?
100 |     UINT   nIP;             // [Out] Number of the instruction boundaries.
101 |     UINT8  oldIPs[8];       // [Out] Instruction boundaries of the target function.
102 |     UINT8  newIPs[8];       // [Out] Instruction boundaries of the trampoline function.
103 | } TRAMPOLINE, *PTRAMPOLINE;
104 | 
105 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct);
106 | 


--------------------------------------------------------------------------------
/translations/OpenSpeedy_en_US.qm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/translations/OpenSpeedy_en_US.qm


--------------------------------------------------------------------------------
/translations/OpenSpeedy_zh_CN.qm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/translations/OpenSpeedy_zh_CN.qm


--------------------------------------------------------------------------------
/translations/OpenSpeedy_zh_TW.qm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/game1024/OpenSpeedy/b54416000c2bea56654a9f628f2641cd55038780/translations/OpenSpeedy_zh_TW.qm


--------------------------------------------------------------------------------
/windbg.h:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * OpenSpeedy - Open Source Game Speed Controller
  3 |  * Copyright (C) 2025 Game1024
  4 |  * 
  5 |  * This program is free software: you can redistribute it and/or modify
  6 |  * it under the terms of the GNU General Public License as published by
  7 |  * the Free Software Foundation, either version 3 of the License, or
  8 |  * (at your option) any later version.
  9 |  * 
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  * 
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17 |  */
 18 | #ifndef WINDBG_H
 19 | #define WINDBG_H
 20 | #include <windows.h>
 21 | #include <QDateTime>
 22 | #include <QDir>
 23 | #include <dbghelp.h>
 24 | // 链接dbghelp库
 25 | #pragma comment(lib, "dbghelp.lib")
 26 | 
 27 | typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(
 28 |     HANDLE hProcess,
 29 |     DWORD ProcessId,
 30 |     HANDLE hFile,
 31 |     MINIDUMP_TYPE DumpType,
 32 |     PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
 33 |     PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
 34 |     PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
 35 | 
 36 | // 自定义异常处理函数
 37 | LONG WINAPI createMiniDump(EXCEPTION_POINTERS *exceptionPointers)
 38 | {
 39 |     // 创建dump文件目录
 40 |     QDir dumpDir(QDir::currentPath() + "/dumps");
 41 |     if (!dumpDir.exists())
 42 |     {
 43 |         dumpDir.mkpath(".");
 44 |     }
 45 | 
 46 |     // 生成带时间戳的文件名
 47 |     QString dumpFileName =
 48 |         QString("%1/crash_%2.dmp")
 49 |             .arg(dumpDir.absolutePath())
 50 |             .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss"));
 51 | 
 52 |     // 创建文件
 53 |     HANDLE hFile = CreateFile(dumpFileName.toStdWString().c_str(),
 54 |                               GENERIC_WRITE, FILE_SHARE_READ, NULL,
 55 |                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 56 | 
 57 |     if (hFile == INVALID_HANDLE_VALUE)
 58 |     {
 59 |         return EXCEPTION_CONTINUE_SEARCH;
 60 |     }
 61 | 
 62 |     // 加载dbghelp.dll
 63 |     HMODULE dbgHelp = LoadLibrary(L"dbghelp.dll");
 64 |     if (!dbgHelp)
 65 |     {
 66 |         CloseHandle(hFile);
 67 |         return EXCEPTION_CONTINUE_SEARCH;
 68 |     }
 69 | 
 70 |     // 获取MiniDumpWriteDump函数地址
 71 |     MINIDUMPWRITEDUMP miniDumpWriteDump =
 72 |         (MINIDUMPWRITEDUMP)GetProcAddress(dbgHelp, "MiniDumpWriteDump");
 73 | 
 74 |     if (!miniDumpWriteDump)
 75 |     {
 76 |         FreeLibrary(dbgHelp);
 77 |         CloseHandle(hFile);
 78 |         return EXCEPTION_CONTINUE_SEARCH;
 79 |     }
 80 | 
 81 |     // 配置异常信息
 82 |     MINIDUMP_EXCEPTION_INFORMATION exInfo;
 83 |     exInfo.ThreadId = GetCurrentThreadId();
 84 |     exInfo.ExceptionPointers = exceptionPointers;
 85 |     exInfo.ClientPointers = FALSE;
 86 | 
 87 |     // 设置dump类型
 88 |     MINIDUMP_TYPE dumpType =
 89 |         (MINIDUMP_TYPE)(MiniDumpWithFullMemory |      // 包含完整内存
 90 |                         MiniDumpWithFullMemoryInfo |  // 包含内存信息
 91 |                         MiniDumpWithHandleData |      // 包含句柄数据
 92 |                         MiniDumpWithThreadInfo |      // 包含线程信息
 93 |                         MiniDumpWithUnloadedModules   // 包含卸载的模块
 94 |         );
 95 | 
 96 |     // 写入dump文件
 97 |     BOOL success = miniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
 98 |                                      hFile, dumpType, &exInfo, NULL, NULL);
 99 | 
100 |     // 清理资源
101 |     FreeLibrary(dbgHelp);
102 |     CloseHandle(hFile);
103 | 
104 |     // 显示通知
105 |     if (success)
106 |     {
107 |         std::wstring message =
108 |             QString("程序遇到错误已退出,崩溃转储文件已保存到:\n%1")
109 |                 .arg(dumpFileName)
110 |                 .toStdWString();
111 |         MessageBoxW(nullptr, message.c_str(), L"程序崩溃",
112 |                     MB_OK | MB_ICONERROR);
113 |     }
114 | 
115 |     return EXCEPTION_EXECUTE_HANDLER;
116 | }
117 | 
118 | #endif  // WINDBG_H
119 | 


--------------------------------------------------------------------------------
/winutils.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * OpenSpeedy - Open Source Game Speed Controller
 3 |  * Copyright (C) 2025 Game1024
 4 |  *
 5 |  * This program is free software: you can redistribute it and/or modify
 6 |  * it under the terms of the GNU General Public License as published by
 7 |  * the Free Software Foundation, either version 3 of the License, or
 8 |  * (at your option) any later version.
 9 |  *
10 |  * This program is distributed in the hope that it will be useful,
11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 |  * GNU General Public License for more details.
14 |  *
15 |  * You should have received a copy of the GNU General Public License
16 |  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 |  */
18 | #ifndef WINUTILS_H
19 | #define WINUTILS_H
20 | #include <windows.h>
21 | #include "taskscheduler.h"
22 | #include <QSet>
23 | #include <QString>
24 | #include <string>
25 | #include <tlhelp32.h>
26 | struct ProcessInfo
27 | {
28 |     DWORD pid;
29 |     DWORD parentPid;
30 |     QString name;
31 |     DWORD threadCount;
32 |     bool is64Bit;
33 |     DWORD priorityClass;
34 |     SIZE_T memoryUsage;
35 | };
36 | 
37 | class winutils
38 | {
39 |   public:
40 |     winutils();
41 | 
42 |   public:
43 |     // DLL 注入
44 |     static bool injectDll(DWORD processId, const QString& dllPath);
45 | 
46 |     // 远程 DLL 注入
47 |     static bool injectDllViaCRTA(DWORD processId, const QString& dllPath);
48 |     static bool injectDllViaCRTW(DWORD processId, const QString& dllPath);
49 | 
50 |     // APC DLL 注入
51 |     static bool injectDllViaAPCA(DWORD processId, const QString& dllPath);
52 |     static bool injectDllViaAPCW(DWORD processId, const QString& dllPath);
53 | 
54 |     // Windows Hooks 注入
55 |     static bool injectDllViaWHKA(DWORD processId, const QString& dllPath);
56 |     static bool injectDllViaWHKW(DWORD processId, const QString& dllPath);
57 | 
58 |     // DLL 卸载
59 |     static bool unhookDll(DWORD processId, const QString& dllPath);
60 | 
61 |     // 检查DLL是否已挂载
62 |     static bool checkDllExist(DWORD processId, const QString& dllPath);
63 | 
64 |     static bool checkProcessProtection(DWORD processId);
65 | 
66 |     static void setAutoStart(bool enable,
67 |                              const QString& appName,
68 |                              const QString& execPath);
69 | 
70 |     static bool isAutoStartEnabled(const QString& appName);
71 | 
72 |     static BOOL getWindowsVersion(DWORD* majorVersion,
73 |                                   DWORD* minorVersion,
74 |                                   DWORD* buildNumber);
75 | 
76 |     static QString getWindowsVersion();
77 | 
78 |     // 获取进程快照
79 |     static QList<ProcessInfo> getProcessList();
80 | 
81 |     // 获取进程路径
82 |     static QString getProcessPath(DWORD processId);
83 | 
84 |     // 获取进程中的主线程
85 |     static DWORD getProcessMainThread(DWORD processId);
86 | 
87 |     static QString getProcessNameById(DWORD processId);
88 | 
89 |     static bool enableAllPrivilege();
90 | };
91 | 
92 | #endif // WINUTILS_H
93 | 


--------------------------------------------------------------------------------