├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── 3rd_party ├── include │ ├── METHODSTABLE.txt │ ├── MinHook.h │ └── kiero.h ├── lib │ ├── x64 │ │ └── minhook.lib │ └── x86 │ │ ├── ScintillaEdit4.lib │ │ └── minhook.lib └── src │ └── kiero.cpp ├── CMakeLists.txt ├── CMakeSettings.json ├── LICENSE ├── README.md ├── _config.yml ├── build.cmd ├── doc ├── class_struct.drawio ├── class_struct.svg ├── imageProc.drawio ├── ocr.md ├── ocr_flow.svg └── slider_window.svg ├── include └── libop.h ├── libop ├── CMakeLists.txt ├── algorithm │ └── AStar.hpp ├── background │ ├── Hook │ │ ├── DisplayHook.cpp │ │ ├── DisplayHook.h │ │ ├── HookExport.cpp │ │ ├── HookExport.h │ │ ├── InputHook.cpp │ │ ├── InputHook.h │ │ ├── d3dx12.h │ │ ├── dinput.md │ │ ├── opDx12Hook.cpp │ │ ├── opDx12Hook.h │ │ └── opMessage.h │ ├── display │ │ ├── IDisplay.cpp │ │ ├── IDisplay.h │ │ ├── frameInfo.h │ │ ├── opDXGI.cpp │ │ ├── opDXGI.h │ │ ├── opDxGL.cpp │ │ ├── opDxGL.h │ │ ├── opGDI.cpp │ │ ├── opGDI.h │ │ ├── opWGC.cpp │ │ └── opWGC.h │ ├── keypad │ │ ├── Bkkeypad.cpp │ │ ├── Bkkeypad.h │ │ ├── winkeypad.cpp │ │ └── winkeypad.h │ ├── mouse │ │ ├── opMouseDx.cpp │ │ ├── opMouseDx.h │ │ ├── opMouseWin.cpp │ │ └── opMouseWin.h │ ├── opBackground.cpp │ └── opBackground.h ├── com │ ├── OpInterface.cpp │ ├── OpInterface.h │ ├── OpInterface.rgs │ ├── compreg.cpp │ ├── compreg.h │ ├── dllmain.cpp │ ├── dllmain.h │ ├── op.cpp │ ├── op.def │ ├── op.idl │ ├── op.rc │ ├── op.rgs │ ├── opps.def │ ├── resource.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── core │ ├── Cmder.h │ ├── Pipe.cpp │ ├── Pipe.h │ ├── globalVar.cpp │ ├── globalVar.h │ ├── helpfunc.cpp │ ├── helpfunc.h │ ├── opEnv.cpp │ ├── opEnv.h │ └── optype.h ├── imageProc │ ├── ImageLoc.cpp │ ├── ImageLoc.h │ ├── ImageProc.cpp │ ├── ImageProc.h │ ├── OcrWrapper.cpp │ ├── OcrWrapper.h │ ├── compute │ │ ├── ThreadPool.cpp │ │ └── ThreadPool.h │ ├── imageView.hpp │ ├── tess_ocr.cpp │ └── tess_ocr.h ├── include │ ├── Dict.h │ ├── Image.hpp │ ├── bitfunc.h │ ├── color.h │ ├── promutex.h │ └── sharedmem.h ├── libop.cpp ├── libop.h ├── readme.md └── winapi │ ├── Injecter.cpp │ ├── Injecter.h │ ├── MemoryEx.cpp │ ├── MemoryEx.h │ ├── WinApi.cpp │ ├── WinApi.h │ ├── query_api.cpp │ └── query_api.h ├── make_Visual_Studio_2019.bat ├── makefile ├── mkDebug.bat ├── mkRelease.bat ├── swig ├── CMakeLists.txt ├── genPythonWrap.bat ├── op.i ├── op_wrap.c ├── op_wrap.cxx └── pyop.py ├── tests ├── CMakeLists.txt ├── main.cpp └── op_test.h ├── tools ├── CMakeLists.txt ├── EasyCom.cpp ├── EasyCom.h ├── dllmain.c └── framework.h └── 插件接口无法正常更新删除tlb!.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | *.code-workspace 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | *.zip 13 | CMakeSettings.json 14 | # Build results 15 | [Dd]ebug/ 16 | [Dd]ebugPublic/ 17 | [Rr]elease/ 18 | [Rr]eleases/ 19 | Build 20 | /lib 21 | bin/ 22 | bin_old/ 23 | bld/ 24 | out/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | .vscode/ 28 | Tool/ 29 | Launcher/ 30 | optool/ 31 | PyTest/ 32 | example/ 33 | remote/ 34 | # Visual Studio 2015 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # MSTest test Results 40 | [Tt]est[Rr]esult*/ 41 | [Bb]uild[Ll]og.* 42 | 43 | # NUNIT 44 | *.VisualState.xml 45 | TestResult.xml 46 | 47 | # Build Results of an ATL Project 48 | [Dd]ebugPS/ 49 | [Rr]eleasePS/ 50 | dlldata.c 51 | 52 | # DNX 53 | project.lock.json 54 | project.fragment.lock.json 55 | artifacts/ 56 | 57 | *_i.h 58 | *_p.c 59 | *_i.c 60 | *.ilk 61 | *.meta 62 | *.obj 63 | *.pch 64 | *.pdb 65 | *.pgc 66 | *.pgd 67 | *.rsp 68 | *.sbr 69 | *.tlb 70 | *.tli 71 | *.tlh 72 | *.tmp 73 | *.tmp_proj 74 | *.log 75 | *.vspscc 76 | *.vssscc 77 | .builds 78 | *.pidb 79 | *.svclog 80 | *.scc 81 | 82 | # Chutzpah Test files 83 | _Chutzpah* 84 | 85 | # Visual C++ cache files 86 | ipch/ 87 | *.aps 88 | *.ncb 89 | *.opendb 90 | *.opensdf 91 | *.sdf 92 | *.cachefile 93 | *.VC.db 94 | *.VC.VC.opendb 95 | 96 | # Visual Studio profiler 97 | *.psess 98 | *.vsp 99 | *.vspx 100 | *.sap 101 | 102 | # TFS 2012 Local Workspace 103 | $tf/ 104 | 105 | # Guidance Automation Toolkit 106 | *.gpState 107 | 108 | # ReSharper is a .NET coding add-in 109 | _ReSharper*/ 110 | *.[Rr]e[Ss]harper 111 | *.DotSettings.user 112 | 113 | # JustCode is a .NET coding add-in 114 | .JustCode 115 | 116 | # TeamCity is a build add-in 117 | _TeamCity* 118 | 119 | # DotCover is a Code Coverage Tool 120 | *.dotCover 121 | 122 | # NCrunch 123 | _NCrunch_* 124 | .*crunch*.local.xml 125 | nCrunchTemp_* 126 | 127 | # MightyMoose 128 | *.mm.* 129 | AutoTest.Net/ 130 | 131 | # Web workbench (sass) 132 | .sass-cache/ 133 | 134 | # Installshield output folder 135 | [Ee]xpress/ 136 | 137 | # DocProject is a documentation generator add-in 138 | DocProject/buildhelp/ 139 | DocProject/Help/*.HxT 140 | DocProject/Help/*.HxC 141 | DocProject/Help/*.hhc 142 | DocProject/Help/*.hhk 143 | DocProject/Help/*.hhp 144 | DocProject/Help/Html2 145 | DocProject/Help/html 146 | 147 | # Click-Once directory 148 | publish/ 149 | 150 | # Publish Web Output 151 | *.[Pp]ublish.xml 152 | *.azurePubxml 153 | # TODO: Comment the next line if you want to checkin your web deploy settings 154 | # but database connection strings (with potential passwords) will be unencrypted 155 | #*.pubxml 156 | *.publishproj 157 | 158 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 159 | # checkin your Azure Web App publish settings, but sensitive information contained 160 | # in these scripts will be unencrypted 161 | PublishScripts/ 162 | 163 | # NuGet Packages 164 | *.nupkg 165 | # The packages folder can be ignored because of Package Restore 166 | **/packages/* 167 | # except build/, which is used as an MSBuild target. 168 | !**/packages/build/ 169 | # Uncomment if necessary however generally it will be regenerated when needed 170 | #!**/packages/repositories.config 171 | # NuGet v3's project.json files produces more ignoreable files 172 | *.nuget.props 173 | *.nuget.targets 174 | 175 | # Microsoft Azure Build Output 176 | csx/ 177 | *.build.csdef 178 | 179 | # Microsoft Azure Emulator 180 | ecf/ 181 | rcf/ 182 | 183 | # Windows Store app package directories and files 184 | AppPackages/ 185 | BundleArtifacts/ 186 | Package.StoreAssociation.xml 187 | _pkginfo.txt 188 | 189 | # Visual Studio cache files 190 | # files ending in .cache can be ignored 191 | *.[Cc]ache 192 | # but keep track of directories ending in .cache 193 | !*.[Cc]ache/ 194 | 195 | # Others 196 | ClientBin/ 197 | ~$* 198 | *~ 199 | *.dbmdl 200 | *.dbproj.schemaview 201 | *.jfm 202 | *.pfx 203 | *.publishsettings 204 | node_modules/ 205 | orleans.codegen.cs 206 | 207 | # Since there are multiple workflows, uncomment next line to ignore bower_components 208 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 209 | #bower_components/ 210 | 211 | # RIA/Silverlight projects 212 | Generated_Code/ 213 | 214 | # Backup & report files from converting an old project file 215 | # to a newer Visual Studio version. Backup files are not needed, 216 | # because we have git ;-) 217 | _UpgradeReport_Files/ 218 | Backup*/ 219 | UpgradeLog*.XML 220 | UpgradeLog*.htm 221 | 222 | # SQL Server files 223 | *.mdf 224 | *.ldf 225 | 226 | # Business Intelligence projects 227 | *.rdl.data 228 | *.bim.layout 229 | *.bim_*.settings 230 | 231 | # Microsoft Fakes 232 | FakesAssemblies/ 233 | 234 | # GhostDoc plugin setting file 235 | *.GhostDoc.xml 236 | 237 | # Node.js Tools for Visual Studio 238 | .ntvs_analysis.dat 239 | 240 | # Visual Studio 6 build log 241 | *.plg 242 | 243 | # Visual Studio 6 workspace options file 244 | *.opt 245 | 246 | # Visual Studio LightSwitch build output 247 | **/*.HTMLClient/GeneratedArtifacts 248 | **/*.DesktopClient/GeneratedArtifacts 249 | **/*.DesktopClient/ModelManifest.xml 250 | **/*.Server/GeneratedArtifacts 251 | **/*.Server/ModelManifest.xml 252 | _Pvt_Extensions 253 | 254 | # Paket dependency manager 255 | .paket/paket.exe 256 | paket-files/ 257 | 258 | # FAKE - F# Make 259 | .fake/ 260 | 261 | # JetBrains Rider 262 | .idea/ 263 | *.sln.iml 264 | 265 | # CodeRush 266 | .cr/ 267 | 268 | # Python Tools for Visual Studio (PTVS) 269 | __pycache__/ 270 | *.pyc 271 | *.ini 272 | 273 | /dll_test 274 | /ConsoleTest 275 | !/PythonTest/*.py 276 | 277 | 278 | 279 | /MFCApp 280 | /PythonTest 281 | /op_test 282 | /Tool 283 | /tool_ex 284 | !/doc/*.chm 285 | 286 | /doc2 287 | 288 | /Ref 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | /libop/com/RCa09948 297 | -------------------------------------------------------------------------------- /3rd_party/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 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 | // pszTarget [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 | // pszTarget [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 | 187 | -------------------------------------------------------------------------------- /3rd_party/include/kiero.h: -------------------------------------------------------------------------------- 1 | #ifndef __KIERO_H__ 2 | #define __KIERO_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define KIERO_VERSION "1.1.8" 8 | 9 | #define KIERO_USE_MINHOOK 10 | 11 | #define KIERO_ARCH_X64 0 12 | #define KIERO_ARCH_X86 0 13 | 14 | #if defined(_M_X64) 15 | # undef KIERO_ARCH_X64 16 | # define KIERO_ARCH_X64 1 17 | #else 18 | # undef KIERO_ARCH_X86 19 | # define KIERO_ARCH_X86 1 20 | #endif 21 | 22 | #ifdef _UNICODE 23 | # define KIERO_TEXT(text) L##text 24 | #else 25 | # define KIERO_TEXT(text) text 26 | #endif 27 | 28 | #define KIERO_ARRAY_SIZE(arr) ((size_t)(sizeof(arr)/sizeof(arr[0]))) 29 | 30 | namespace kiero 31 | { 32 | struct Status 33 | { 34 | enum Enum 35 | { 36 | UnknownError = -1, 37 | NotSupportedError = -2, 38 | ModuleNotFoundError = -3, 39 | 40 | Success = 0, 41 | }; 42 | }; 43 | 44 | struct RenderType 45 | { 46 | enum Enum 47 | { 48 | None, 49 | 50 | D3D9, // Implemented 51 | D3D10, // Implemented 52 | D3D11, // Implemented 53 | D3D12, // Implemented 54 | 55 | OpenGL, // Implemented 56 | OpenglES, 57 | Vulkan // Implemented 58 | }; 59 | }; 60 | 61 | Status::Enum init(int renderType); 62 | 63 | void shutdown(); 64 | 65 | RenderType::Enum getRenderType(); 66 | 67 | #if KIERO_ARCH_X64 68 | uint64_t* getMethodsTable(); 69 | #else 70 | uint32_t* getMethodsTable(); 71 | #endif 72 | 73 | int bind(uint16_t index, void** original, void* function); 74 | 75 | int unbind(); 76 | } 77 | 78 | #endif // __KIERO_H__ -------------------------------------------------------------------------------- /3rd_party/lib/x64/minhook.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/3rd_party/lib/x64/minhook.lib -------------------------------------------------------------------------------- /3rd_party/lib/x86/ScintillaEdit4.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/3rd_party/lib/x86/ScintillaEdit4.lib -------------------------------------------------------------------------------- /3rd_party/lib/x86/minhook.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/3rd_party/lib/x86/minhook.lib -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt: 顶层 CMake 项目文件,在此处执行全局配置 2 | # 并包含子项目。 3 | # 4 | cmake_minimum_required (VERSION 3.10) 5 | 6 | if(NOT $ENV{BLACKBONE_ROOT} STREQUAL "") 7 | set(blackbone_include_path "$ENV{BLACKBONE_ROOT}/src") 8 | set(blackbone_lib32_path "$ENV{BLACKBONE_ROOT}/build/Win32/Release") 9 | set(blackbone_lib64_path "$ENV{BLACKBONE_ROOT}/build/X64/Release") 10 | endif() 11 | 12 | 13 | option(build_swig_py "build swig py,requrie python" ON) 14 | 15 | # 检查头文件是否设置正确 16 | if(EXISTS ${blackbone_include_path}/BlackBone/Process/Process.h) 17 | message(STATUS "${blackbone_include_path}/BlackBone/Process/Process.h finded" ) 18 | else() 19 | message(FATAL_ERROR "${blackbone_include_path}/BlackBone/Process/Process.h not finded" ) 20 | endif() 21 | 22 | # 检查库是否设置正确 23 | if(EXISTS ${blackbone_lib32_path}/BlackBone.lib) 24 | message(STATUS "32 blackbone lib find" ) 25 | else() 26 | message(FATAL_ERROR "${blackbone_lib32_path}/BlackBone.lib NOT find" ) 27 | endif() 28 | if(EXISTS ${blackbone_lib64_path}/BlackBone.lib) 29 | message(STATUS "64 BlackBone lib find" ) 30 | else() 31 | message(FATAL_ERROR "${blackbone_lib64_path}/blackbone.lib NOT find" ) 32 | endif() 33 | 34 | 35 | 36 | project ("op") 37 | add_compile_options("$<$:/utf-8>") 38 | add_compile_options("$<$:/utf-8>") 39 | 40 | set(CMAKE_CXX_STANDARD 17) 41 | 42 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 43 | MESSAGE(STATUS "----------------Now is MSVC EHA----------------") 44 | set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /EHa") 45 | set(CMAKE_C_FLAGS_RELEASE "/MT /O2 /EHa") 46 | set(CMAKE_CXX_FLAGS_DEBUG "/MT /Zi /EHa") 47 | set(CMAKE_C_FLAGS_DEBUG "/MT /Zi /EHa") 48 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /O2 /EHa") 49 | set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MT /O2 /EHa") 50 | endif() 51 | 52 | 53 | IF(CMAKE_SIZEOF_VOID_P EQUAL 8) 54 | link_directories( 55 | ${CMAKE_SOURCE_DIR}/3rd_party/lib/x64 56 | ${blackbone_lib64_path} 57 | ) 58 | set(op_com op_x64) 59 | MESSAGE(STATUS "----------------Platform x64----------------") 60 | ELSE() 61 | link_directories( 62 | ${CMAKE_SOURCE_DIR}/3rd_party/lib/x86 63 | ${blackbone_lib32_path} 64 | ) 65 | set(op_com op_x86) 66 | MESSAGE(STATUS "----------------Platform x86----------------") 67 | ENDIF() 68 | 69 | include_directories( 70 | ./ 71 | ${CMAKE_SOURCE_DIR}/3rd_party/include/ 72 | ${CMAKE_SOURCE_DIR}/3rd_party/include/3rd_party 73 | ${blackbone_include_path} 74 | ${blackbone_include_path}/3rd_party 75 | ) 76 | 77 | # 包含子项目。 78 | ## libop主项目 79 | add_subdirectory ("libop") 80 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libop/com/op_i.h") 81 | ## tools项目 82 | add_subdirectory("tools") 83 | ## 测试项目 84 | add_subdirectory("tests") 85 | endif() 86 | ## swig 项目 87 | if(build_swig_py) 88 | add_subdirectory("swig") 89 | endif() 90 | 91 | 92 | -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x64-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ "msvc_x64_x64" ], 8 | "buildRoot": "${projectDir}\\out\\build\\${name}", 9 | "installRoot": "${projectDir}\\out\\install\\${name}", 10 | "cmakeCommandArgs": "", 11 | "buildCommandArgs": "", 12 | "ctestCommandArgs": "" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 DeepFire 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # OP 自动化插件 3 | 4 | [![GitHub Release](https://img.shields.io/github/v/release/WallBreaker2/op?style=flat-square)](https://github.com/WallBreaker2/op/releases) 5 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 6 | 7 | ## 📖 项目概述 8 | 9 | **OP**(Operator & Open)是一款开源自动化工具,专为Windows平台设计。核心功能包括: 10 | 11 | - 🔍 **窗口自动化**:键鼠消息模拟/后台截图 12 | - 🖼️ **图像处理**:智能找图/色值识别 13 | - ✨ **OCR引擎**:传统算法+AI引擎双模式 14 | - 🛠️ **平台支持**:原生32/64位双版本 15 | 16 | ![架构图](doc/class_struct.svg) 17 | 18 | ## 🚀 核心特性 19 | 20 | ### 自动化控制 21 | - Windows消息级键鼠模拟 22 | - 多渲染引擎(GDI/DirectX/OpenGL)截图 23 | - 主流安卓模拟器最小化截图 24 | 25 | ### 图像识别 26 | - 智能模糊匹配(支持偏色/透明度) 27 | - 多区域并行搜索 28 | - 自适应屏幕缩放识别 29 | 30 | ### OCR引擎 31 | ```python 32 | # 双模式文字识别示例 33 | text = op.Ocr(0,0,2000,2000,"eng",0.8) # Tesseract引擎 34 | legacy_text = op.OcrEx(0,0,500,500,"sysfont") # 传统算法(最大255x255点阵) 35 | 36 | ## 📦 快速开始 37 | 38 | ### 环境准备 39 | 1. 下载最新发行版:[GitHub Releases](https://github.com/WallBreaker2/op/releases) 40 | 2. 注册COM组件(管理员权限): 41 | ```powershell 42 | regsvr32 op_x86.dll # 32位 43 | regsvr32 op_x64.dll # 64位 44 | ``` 45 | 46 | ### Python示例 47 | ```python 48 | from win32com.client import Dispatch 49 | 50 | op = Dispatch("op.opsoft") 51 | print(f"SDK版本: {op.Ver()}") 52 | 53 | # 图像搜索(返回坐标元组) 54 | found, x, y = op.FindPic( 55 | 0, 0, 1920, 1080, 56 | "button.png", 57 | "101010", # 偏色值 58 | 0.9, # 相似度 59 | 0 # 搜索模式 60 | ) 61 | ``` 62 | 63 | ## 🛠️ 开发指南 64 | 65 | ### 编译要求 66 | | 组件 | 版本要求 | 67 | |-------------------|------------------| 68 | | Visual Studio | 2022 (MSVC 143) | 69 | | CMake | ≥3.24 | 70 | | Windows SDK | 10.0.19041.0 | 71 | 72 | ### 依赖管理 73 | ```bash 74 | # 配置环境变量 75 | set BLACKBONE_ROOT="D:\libs\Blackbone" 76 | ``` 77 | 78 | | 依赖库 | 编译方式 | 备注 | 79 | |-------------------|----------|----------------------| 80 | | Blackbone | 静态链接 | 进程注入核心 | 81 | | Kiero | 源码集成 | DirectX Hook实现 | 82 | | Tesseract | 动态链接 | OCR引擎(默认包含) | 83 | 84 | ## 💬 社区支持 85 | - 官方讨论区: [GitHub Discussions](https://github.com/WallBreaker2/op/discussions) 86 | - QQ交流群: 27872381(新)743710486(满) 87 | - 问题追踪: [Issues](https://github.com/WallBreaker2/op/issues) 88 | 89 | ## 📜 开源协议 90 | 本项目基于 [MIT License](LICENSE) 开源,特别感谢: 91 | - [TSPLUG](https://github.com/tcplugins/tsplug) - Windows部分函数参考实现 92 | - [Kiero](https://github.com/Rebzzel/kiero) - DirectX注入方案 93 | ``` 94 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-time-machine -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Set the path to vcpkg 3 | set "vcpkg_path=D:/workspace/vcpkg" 4 | 5 | echo Starting the build process... 6 | 7 | REM Step 1: Create the build directory if it doesn't exist 8 | if not exist "build" ( 9 | mkdir build 10 | ) 11 | 12 | REM Navigate to the build directory 13 | cd build 14 | 15 | REM Step 2: Run CMake to configure the project 16 | cmake .. -DCMAKE_TOOLCHAIN_FILE=%vcpkg_path%/scripts/buildsystems/vcpkg.cmake ^ 17 | -DVCPKG_TARGET_TRIPLET=x86-windows-static ^ 18 | -DCMAKE_BUILD_TYPE=Release 19 | 20 | REM Step 3: Build the project 21 | cmake --build . --config Release 22 | 23 | echo Build process completed. 24 | pause -------------------------------------------------------------------------------- /doc/ocr.md: -------------------------------------------------------------------------------- 1 | ## 主要内容 2 | 本文主要介绍ocr算法的基本原理,主要流程以及具体实现和优化 3 | 4 | ## ocr流程 5 | 1. 将给定的RGB图像转化为灰度图像 6 | 2. 根据指定的灰度范围将灰度图像二值化 7 | 3. 使用滑动窗口将二值图像分为多个子区域 8 | 4. 对每个子区域,与字库做相识度计算,相识度符合要求的添加至结果列表 9 | 5. 对结果列表进行排序,输出 10 | 11 | 下图为流程图 12 | 13 | ![altr](./ocr_flow.svg) 14 | 15 | ## 原理 16 | ### 灰度化 17 | 由于彩色图像的RGB三个分量并不是独立的,因此转化为灰度一个分量有利于后续的处理,RGB值和灰度的转换,实际上是人眼对于彩色的感觉到亮度感觉的转换,这是一个心理学问题,有一个公式: 18 | 19 | Grey = 0.299*R + 0.587*G + 0.114*B 20 | 21 | 根据这个公式,依次读取每个像素点的R,G,B值,进行计算灰度值(转换为整型数),将灰度值赋值给新图像的相应位置,所有像素点遍历一遍后完成转换。 22 | 23 | 一张500X500的图像转换为同样大小的灰度图需要进行25万次上述公式的计算。进行优化是很有必要的,这个简单的算法是O(n)复杂度的,应该是不能优化了(或者用并行进行优化,本文不涉及),但是Grey = 0.299*R + 0.587*G + 0.114*B有更加高效的等价形式。 24 | 25 | 在ALU中,位操作快于整数加法,整数加法快于整数乘法(快多少取决于有没有乘法电路,乘法电路的结构),整数运算又比浮点数运算快得多。 26 | 27 | 所以可以通过将浮点数运算转化为整数运算,整数运算转换为位操作进行优化 28 | 29 | Grey = 0.299*R + 0.587*G + 0.114*B 30 | 31 | 可以转化为 32 | Grey = (299*R + 587*G + 114*B + 500) /1000; 33 | 34 | 整数运算会截断小数部分,加上500是为了四舍五入(找两个例子便可理解),减少精度损失。 35 | 36 | ### 二值化 37 | 为了进一步提取出字符的点阵信息,需要将灰度图像二值化,将字符的灰度值范围内的点阵填充为1,其余填充为0 38 | 39 | ### 滑动窗口 40 | 首先对输入图像进行不同窗口大小的滑窗进行从左往右、从上到下的滑动。每次滑动时候对当前窗口执行相识度计算(与某个字库)。如果当前窗口得到较高相识度,则认为检测到了文字。 41 | 42 | ![atr](slider_window.svg) 43 | 44 | 45 | ### 排序 46 | 提取了字符信息后,需要决定字符在字符串中的位置,所以需要排序。排序的规则为先上后下,先左后右。 47 | 48 | ## 优化 49 | 从上面的流程来看,ocr的整个流程还是比较简单的,但是算法的复杂度比较高,对于1920*1080区域,假设字库为12*12,字库总量为20000的汉字字库,则需要比较的像素次数为 50 | 51 | (1920-11)*(1080-11)*12*12*20000=5 877 276 480 000 52 | 53 | 以1ghz的处理器来计算,需要5877s,速度实现太慢了,因此优化在ocr很有必要。 54 | 55 | 主要的优化方式有以下几种: 56 | 1. 粗定位 57 | 2. 细分类 58 | 3. 二分查找 59 | 4. 筛选 -------------------------------------------------------------------------------- /doc/ocr_flow.svg: -------------------------------------------------------------------------------- 1 |
输入图片
输入图片
二值化
二值化
滑动窗口匹配
滑动窗口匹配
排序结果
排序结果
输出结果(字符+坐标)
输出结果(字符+坐标)
字库
字库
Viewer does not support full SVG 1.1
-------------------------------------------------------------------------------- /libop/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 1.cmake version 2 | cmake_minimum_required(VERSION 3.0.0) 3 | 4 | 5 | 6 | # 3.include path 7 | #INCLUDE_DIRECTORIES( 8 | # include 9 | #) 10 | 11 | 12 | 13 | 14 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEF:op.def /NODEFAULTLIB") 15 | 16 | 17 | 18 | # set_target_properties(target PROPERTIES VcpkgEnabled "true") 19 | 20 | # 4.source directory 21 | AUX_SOURCE_DIRECTORY(./ DIR_SRCS) 22 | 23 | #LINK_DIRECTORIES("/3rd_party/lib/x86") 24 | # 5.set environment variable 25 | # find_package(OpenCV REQUIRED) 26 | # include_directories(libop ${OpenCV_INCLUDE_DIRS}) 27 | 28 | 29 | #find_package(minhook CONFIG REQUIRED) 30 | #message(STATUS ${minhook_lib}) 31 | 32 | 33 | 34 | 35 | SET(SRC_FILES 36 | "./background/opBackground.cpp" 37 | 38 | "./background/display/opGDI.cpp" 39 | "./background/display/opDXGI.cpp" 40 | "./background/display/opDxGL.cpp" 41 | "./background/display/IDisplay.cpp" 42 | 43 | "./background/display/opWGC.cpp" 44 | 45 | 46 | "./background/mouse/opMouseWin.cpp" 47 | "./background/mouse/opMouseDx.cpp" 48 | 49 | "./background/keypad/bkkeypad.cpp" 50 | "./background/keypad/winkeypad.cpp" 51 | 52 | "./background/Hook/DisplayHook.cpp" 53 | "./background/Hook/InputHook.cpp" 54 | "./background/Hook/HookExport.cpp" 55 | "./background/Hook/opDx12Hook.cpp" 56 | 57 | 58 | "./core/globalVar.cpp" 59 | "./core/helpfunc.cpp" 60 | "./core/pipe.cpp" 61 | "./core/opEnv.cpp" 62 | 63 | 64 | "./imageProc/imageloc.cpp" 65 | "./imageProc/imageproc.cpp" 66 | # "imageProc/tess_ocr.cpp" 67 | "imageProc/OcrWrapper.cpp" 68 | "./winapi/injecter.cpp" 69 | "./winapi/memoryEx.cpp" 70 | "./winapi/query_api.cpp" 71 | "./winapi/winapi.cpp" 72 | "../3rd_party/src/kiero.cpp" 73 | "libop.cpp" 74 | ) 75 | 76 | SET(COM_SRC_FILES 77 | "./core/globalVar.cpp" 78 | "./com/op.cpp" 79 | "./com/opinterface.cpp" 80 | "./com/stdafx.cpp" 81 | "./com/compreg.cpp" 82 | "./com/dllmain.cpp" 83 | "./com/op_i.c" 84 | "./com/op.def") 85 | 86 | 87 | 88 | 89 | 90 | 91 | ADD_DEFINITIONS(-DUNICODE -D_UNICODE) 92 | ADD_DEFINITIONS(-D WIN32) 93 | ADD_DEFINITIONS(-D _WINDOWS) 94 | ADD_DEFINITIONS(-D _USRDLL) 95 | ADD_DEFINITIONS(-D _CRT_NON_CONFORMING_SWPRINTFS) 96 | ADD_DEFINITIONS(-D _CRT_SECURE_NO_WARNINGS) 97 | ADD_DEFINITIONS(-D _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING) 98 | ADD_DEFINITIONS(-D _WINDLL) 99 | ADD_DEFINITIONS(-D _UNICODE) 100 | ADD_DEFINITIONS(-D UNICODE) 101 | ADD_DEFINITIONS(-D OP_EXPORTS) 102 | 103 | 104 | # 6.add lib file 105 | #add_library(libop SHARED ${SRC_FILES}) 106 | 107 | add_library(libop ${SRC_FILES}) 108 | 109 | # ----------op_x86/x64 110 | 111 | add_custom_command( 112 | OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/com/op_i.c 113 | COMMAND COMMAND midl ${CMAKE_CURRENT_SOURCE_DIR}/com/op.idl /iid 114 | "./com/op_i.c" /env win32 /h "./com/op_i.h" /W1 /char signed /tlb 115 | "./com/op.tlb" /Oicf /target "NT60" /D "NDEBUG" /robust /nologo /proxy "op_p.c" 116 | # DEPENDS MakeTable 117 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 118 | ) 119 | 120 | add_library(${op_com} SHARED ${SRC_FILES} ${COM_SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/./com/op.rc) 121 | SET_TARGET_PROPERTIES(${op_com} PROPERTIES LINK_FLAGS "/DEF:\"op.def\" /NODEFAULTLIB:\"mfc110d\"") 122 | # add_custom_command(TARGET ${op_com} PRE_BUILD COMMAND midl ./com/op.idl /iid "./com/op_i.c" /env win32 /h "./com/op_i.h" /W1 /char signed /tlb "./com/op.tlb" /Oicf /target "NT60" /D "NDEBUG" /robust /nologo /proxy "op_p.c" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 123 | 124 | 125 | 126 | 127 | target_include_directories(${op_com} PUBLIC 128 | "${PROJECT_BINARY_DIR}" 129 | "${CMAKE_CURRENT_SOURCE_DIR}" 130 | ) 131 | 132 | include_directories( 133 | ./ 134 | ./core 135 | ) 136 | 137 | ## for tesseract lib 138 | # find_package(Tesseract) 139 | # include_directories(${Tesseract_INCLUDE_DIRS}) 140 | # target_link_libraries(${op_com} Tesseract::libtesseract) 141 | 142 | 143 | # 7.add link library 144 | #TARGET_LINK_LIBRARIES(libop BlackBone.lib) 145 | #TARGET_LINK_LIBRARIES(libop minhook.lib) 146 | TARGET_LINK_LIBRARIES(${op_com} BlackBone.lib) 147 | TARGET_LINK_LIBRARIES(${op_com} minhook.lib) 148 | 149 | # target_link_libraries(libop ${OpenCV_LIBS}) 150 | # target_link_libraries(libop msvcrt.lib) 151 | 152 | 153 | 154 | install(FILES libop.h DESTINATION "${PROJECT_SOURCE_DIR}/include") 155 | IF(CMAKE_CL_64) 156 | #install(TARGETS libop RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 157 | #install(TARGETS libop ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x64") 158 | install(TARGETS ${op_com} RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 159 | install(TARGETS ${op_com} ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x64") 160 | ELSE(CMAKE_CL_64) 161 | #install(TARGETS libop RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 162 | #install(TARGETS libop ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x86") 163 | install(TARGETS ${op_com} RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 164 | install(TARGETS ${op_com} ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x86") 165 | ENDIF(CMAKE_CL_64) 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /libop/algorithm/AStar.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/algorithm/AStar.hpp -------------------------------------------------------------------------------- /libop/background/Hook/DisplayHook.h: -------------------------------------------------------------------------------- 1 | //#pragma once 2 | #ifndef __DX9HOOK_H_ 3 | #define __DX9HOOK_H_ 4 | #include "../../core/globalVar.h" 5 | 6 | class DisplayHook 7 | { 8 | public: 9 | /*target window hwnd*/ 10 | static HWND render_hwnd; 11 | static int render_type; 12 | /*name of ...*/ 13 | static wchar_t shared_res_name[256]; 14 | static wchar_t mutex_name[256]; 15 | static void *old_address; 16 | static bool is_hooked ; 17 | // 18 | static int setup(HWND hwnd_, int render_type_); 19 | static int release(); 20 | }; 21 | //以下函数用于HOOK DX9 22 | 23 | //此函数做以下工作 24 | /* 25 | 1.hook相关函数 26 | 2.设置共享内存,互斥量 27 | 3.截图(hook)至共享内存 28 | */ 29 | void CopyImageData(char* dst_, const char* src_, int rows_, int cols_, int rowPitch, int fmt_); 30 | #endif // !__DX9HOOK_H_ -------------------------------------------------------------------------------- /libop/background/Hook/HookExport.cpp: -------------------------------------------------------------------------------- 1 | #include "HookExport.h" 2 | #include "DisplayHook.h" 3 | #include "InputHook.h" 4 | #include "../../core/opEnv.h" 5 | int refCount = 0; 6 | //--------------export function-------------------------- 7 | long __stdcall SetDisplayHook(HWND hwnd_, int render_type_) 8 | { 9 | int ret = 0; 10 | opEnv::m_showErrorMsg = 2; //this code is excuate in hookde process,so its better not show meesageBox(avoid suspend the work thread) 11 | if (!DisplayHook::is_hooked) 12 | { 13 | ret = DisplayHook::setup(hwnd_, render_type_); 14 | DisplayHook::is_hooked = ret == 1; 15 | refCount += DisplayHook::is_hooked; 16 | } 17 | else { 18 | //setlog("warning: ") 19 | ret = 1; 20 | } 21 | return ret; 22 | } 23 | 24 | long __stdcall ReleaseDisplayHook() 25 | { 26 | int ret = 0; 27 | if (DisplayHook::is_hooked){ 28 | DisplayHook::is_hooked = false; 29 | ret = DisplayHook::release(); 30 | refCount--; 31 | if(refCount==0){ 32 | ::FreeLibraryAndExitThread(static_cast(opEnv::getInstance()), 0); 33 | } 34 | 35 | } 36 | 37 | 38 | return ret; 39 | } 40 | 41 | long __stdcall SetInputHook(HWND hwnd_, int input_type_) 42 | { 43 | int ret = 0; 44 | if (!InputHook::is_hooked) 45 | { 46 | ret = InputHook::setup(hwnd_, input_type_); 47 | InputHook::is_hooked = ret == 1; 48 | refCount += InputHook::is_hooked; 49 | } 50 | return ret; 51 | } 52 | 53 | long __stdcall ReleaseInputHook() 54 | { 55 | if (InputHook::is_hooked) 56 | { 57 | InputHook::release(); 58 | InputHook::is_hooked = false; 59 | refCount--; 60 | if(refCount==0){ 61 | ::FreeLibraryAndExitThread(static_cast(opEnv::getInstance()), 0); 62 | } 63 | } 64 | return 1; 65 | } 66 | -------------------------------------------------------------------------------- /libop/background/Hook/HookExport.h: -------------------------------------------------------------------------------- 1 | #include "../../core/globalVar.h" 2 | 3 | 4 | //描述: 设置显示Hook 5 | //返回值:1 成功,0失败 6 | DLL_API long __stdcall SetDisplayHook(HWND hwnd_, int render_type_); 7 | 8 | //描述: 释放显示Hook 9 | //返回值:1 成功,0失败 10 | DLL_API long __stdcall ReleaseDisplayHook(); 11 | 12 | //描述: 设置输入Hook 13 | //返回值:1 成功,0失败 14 | DLL_API long __stdcall SetInputHook(HWND hwnd_, int input_type_); 15 | 16 | //描述: 释放输入Hook 17 | //返回值:1 成功,0失败 18 | DLL_API long __stdcall ReleaseInputHook(); 19 | -------------------------------------------------------------------------------- /libop/background/Hook/InputHook.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "InputHook.h" 3 | #include "../../core/opEnv.h" 4 | #include "../../core/helpfunc.h" 5 | #include "opMessage.h" 6 | #include "../../winapi/query_api.h" 7 | #include "MinHook.h" 8 | 9 | #include "dinput.h" 10 | #include 11 | 12 | const GUID OP_IID_IDirectInput8W = {0xBF798031, 0x483A, 0x4DA2, 0xAA, 0x99, 0x5D, 0x64, 0xED, 0x36, 0x97, 0x00}; 13 | const GUID OP_GUID_SysMouse = {0x6F1D2B60, 0xD5A0, 0x11CF, 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}; 14 | /*target window hwnd*/ 15 | HWND InputHook::input_hwnd; 16 | int InputHook::input_type; 17 | /*name of ...*/ 18 | wchar_t InputHook::shared_res_name[256]; 19 | wchar_t InputHook::mutex_name[256]; 20 | void *InputHook::old_address; 21 | // 22 | opMouseState InputHook::m_mouseState; 23 | bool InputHook::is_hooked = false; 24 | 25 | WNDPROC gRawWindowProc = 0; 26 | std::vector gDinputVtb; 27 | std::vector gDinputVtbRaw; 28 | 29 | const int indexAcquire = 7; 30 | const int indexGetDeviceState = 9; 31 | const int indexPoll = 25; 32 | 33 | int getDinputVtb(); 34 | 35 | HRESULT __stdcall hkAcquire(IDirectInputDevice8W *this_); 36 | 37 | HRESULT __stdcall hkPoll(IDirectInputDevice8W *this_); 38 | 39 | HRESULT __stdcall hkGetDeviceState(IDirectInputDevice8W *this_, DWORD size, LPVOID ptr); 40 | 41 | LRESULT CALLBACK opWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 42 | 43 | int InputHook::setup(HWND hwnd_, int input_type_) 44 | { 45 | if (!IsWindow(hwnd_)) 46 | return 0; 47 | opEnv::m_showErrorMsg = 2; //write data to file 48 | setlog("SetInputHook"); 49 | if (getDinputVtb() == 1) 50 | { 51 | MH_Initialize(); 52 | MH_CreateHook( 53 | gDinputVtb[indexGetDeviceState], 54 | hkGetDeviceState, 55 | &gDinputVtbRaw[indexGetDeviceState]); 56 | MH_CreateHook( 57 | gDinputVtb[indexPoll], 58 | hkPoll, 59 | &gDinputVtbRaw[indexPoll]); 60 | MH_EnableHook(NULL); 61 | gRawWindowProc = reinterpret_cast(SetWindowLongPtrA(hwnd_, GWLP_WNDPROC, reinterpret_cast(opWndProc))); 62 | InputHook::input_hwnd = hwnd_; 63 | } 64 | else 65 | { 66 | setlog("getDinputVtb false!"); 67 | } 68 | 69 | return gRawWindowProc ? 1 : -1; 70 | } 71 | int InputHook::release() 72 | { 73 | LONG_PTR ptr = 0; 74 | if (gRawWindowProc) 75 | { 76 | MH_RemoveHook(NULL); 77 | MH_Uninitialize(); 78 | ptr = SetWindowLongPtrA(InputHook::input_hwnd, GWLP_WNDPROC, reinterpret_cast(gRawWindowProc)); 79 | } 80 | return ptr ? 1 : 0; 81 | return 0; 82 | } 83 | 84 | void InputHook::upDataPos(LPARAM lp, int key, bool down) 85 | { 86 | m_mouseState.lAxisX = lp & 0xffff; 87 | m_mouseState.lAxisY = (lp >> 16) & 0xffff; 88 | setlog("upDataPos x=%d, y=%d", m_mouseState.lAxisX, m_mouseState.lAxisY); 89 | if (0 <= key && key < 3) 90 | { 91 | m_mouseState.abButtons[key] = down ? 0x80 : 0; 92 | } 93 | } 94 | 95 | int getDinputVtb() 96 | { 97 | using DirectInput8Create_t = decltype(DirectInput8Create); 98 | auto pDirectInput8Create = reinterpret_cast(query_api("dinput8.dll", "DirectInput8Create")); 99 | if (pDirectInput8Create) 100 | { 101 | WNDCLASSEX windowClass; 102 | windowClass.cbSize = sizeof(WNDCLASSEX); 103 | windowClass.style = CS_HREDRAW | CS_VREDRAW; 104 | windowClass.lpfnWndProc = DefWindowProc; 105 | windowClass.cbClsExtra = 0; 106 | windowClass.cbWndExtra = 0; 107 | windowClass.hInstance = GetModuleHandle(NULL); 108 | windowClass.hIcon = NULL; 109 | windowClass.hCursor = NULL; 110 | windowClass.hbrBackground = NULL; 111 | windowClass.lpszMenuName = NULL; 112 | windowClass.lpszClassName = L"Kiero"; 113 | windowClass.hIconSm = NULL; 114 | 115 | ::RegisterClassEx(&windowClass); 116 | 117 | HWND window = ::CreateWindowW(windowClass.lpszClassName, L"Kiero DirectX Window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, windowClass.hInstance, NULL); 118 | LPDIRECTINPUT8 pDinput = NULL; 119 | 120 | if (pDirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, 121 | OP_IID_IDirectInput8W, (VOID **)&pDinput, NULL) < 0) 122 | { 123 | ::DestroyWindow(window); 124 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); 125 | setlog("pDirectInput8Create false!"); 126 | return -1; 127 | } 128 | 129 | LPDIRECTINPUTDEVICE8 pMouse = NULL; 130 | if (pDinput->CreateDevice(OP_GUID_SysMouse, &pMouse, NULL) < 0) 131 | { 132 | ::DestroyWindow(window); 133 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); 134 | setlog("CreateDevice false!"); 135 | return -2; 136 | } 137 | gDinputVtb.resize(32); 138 | gDinputVtbRaw.resize(32); 139 | ::memcpy(&gDinputVtb[0], *(size_t **)pMouse, 32 * sizeof(size_t)); 140 | 141 | ::DestroyWindow(window); 142 | ::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance); 143 | 144 | return 1; 145 | //MH_Initialize(); 146 | } 147 | else 148 | { 149 | setlog("dinput8 not found"); 150 | return 0; 151 | } 152 | } 153 | 154 | HRESULT __stdcall hkAcquire(IDirectInputDevice8W *this_) 155 | { 156 | return DI_OK; 157 | } 158 | 159 | HRESULT __stdcall hkPoll(IDirectInputDevice8W *this_) 160 | { 161 | return DI_OK; 162 | } 163 | 164 | void EndianSwap(char *pData, int startIndex, int length) 165 | { 166 | int i,cnt,end,start; 167 | cnt = length / 2; 168 | start = startIndex; 169 | end = startIndex + length - 1; 170 | char tmp; 171 | for (i = 0; i < cnt; i++) 172 | { 173 | tmp = pData[start+i]; 174 | pData[start+i] = pData[end-i]; 175 | pData[end-i] = tmp; 176 | } 177 | } 178 | 179 | HRESULT __stdcall hkGetDeviceState(IDirectInputDevice8W *this_, DWORD size, LPVOID ptr) 180 | { 181 | //setlog("called hkGetDeviceState"); 182 | using GetDeviceState_t = decltype(hkGetDeviceState); 183 | 184 | if (size == sizeof(opMouseState)) 185 | { 186 | opMouseState state = {}; 187 | //setlog("called opMouseState"); 188 | // state.lAxisX = InputHook::m_mouseState.lAxisX; 189 | // state.lAxisY = InputHook::m_mouseState.lAxisY; 190 | // state.abButtons[0] 191 | state = InputHook::m_mouseState; 192 | //EndianSwap((char*)&state,0, sizeof(state)); 193 | memcpy(ptr, &state, sizeof(state)); 194 | return DI_OK; 195 | } 196 | else if (size == sizeof(DIMOUSESTATE)) 197 | { 198 | DIMOUSESTATE state = {}; 199 | setlog("called DIMOUSESTATE"); 200 | 201 | state.lX = InputHook::m_mouseState.lAxisX; 202 | state.lY = InputHook::m_mouseState.lAxisY; 203 | 204 | memcpy(ptr, &state, sizeof(state)); 205 | return DI_OK; 206 | } 207 | else if (size == sizeof(DIMOUSESTATE2)) 208 | { 209 | DIMOUSESTATE2 state = {}; 210 | setlog("called DIMOUSESTATE2"); 211 | state.lX = InputHook::m_mouseState.lAxisX; 212 | state.lY = InputHook::m_mouseState.lAxisY; 213 | memcpy(ptr, &state, sizeof(state)); 214 | return DI_OK; 215 | } 216 | else 217 | { 218 | return reinterpret_cast(gDinputVtbRaw[indexGetDeviceState])(this_, size, ptr); 219 | } 220 | } 221 | 222 | LRESULT CALLBACK opWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 223 | { 224 | setlog("%04X message", message); 225 | switch (message) 226 | { 227 | case OP_WM_MOUSEMOVE: 228 | { 229 | InputHook::upDataPos(lParam, -1, false); 230 | setlog("OP_WM_MOUSEMOVE message"); 231 | break; 232 | } 233 | case OP_WM_LBUTTONUP: 234 | InputHook::upDataPos(lParam, 0, false); 235 | setlog("OP_WM_LBUTTONUP message"); 236 | break; 237 | case OP_WM_LBUTTONDOWN: 238 | InputHook::upDataPos(lParam, 0, true); 239 | setlog("OP_WM_LBUTTONDOWN message"); 240 | break; 241 | case OP_WM_MBUTTONDOWN: 242 | InputHook::upDataPos(lParam, 1, true); 243 | setlog("OP_WM_MBUTTONDOWN message"); 244 | break; 245 | case OP_WM_MBUTTONUP: 246 | InputHook::upDataPos(lParam, 1, false); 247 | setlog("OP_WM_MBUTTONUP message"); 248 | break; 249 | case OP_WM_RBUTTONDOWN: 250 | InputHook::upDataPos(lParam, 2, true); 251 | setlog("OP_WM_RBUTTONDOWN message"); 252 | break; 253 | case OP_WM_RBUTTONUP: 254 | InputHook::upDataPos(lParam, 2, false); 255 | setlog("OP_WM_RBUTTONUP message"); 256 | break; 257 | case OP_WM_MOUSEWHEEL: 258 | //InputHook::upDataPos(wParam,2,true); 259 | setlog("OP_WM_MOUSEWHEEL message"); 260 | break; 261 | } 262 | return CallWindowProcA(gRawWindowProc, InputHook::input_hwnd, message, wParam, lParam); 263 | } 264 | -------------------------------------------------------------------------------- /libop/background/Hook/InputHook.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUT_HOOK_H 2 | #define __INPUT_HOOK_H 3 | 4 | #include "../../core/globalVar.h" 5 | 6 | struct opMouseState 7 | { 8 | LONG lAxisX; 9 | LONG lAxisY; 10 | BYTE abButtons[3]; 11 | BYTE bPadding; // Structure must be DWORD multiple in size. 12 | }; 13 | 14 | class InputHook 15 | { 16 | public: 17 | /*target window hwnd*/ 18 | static HWND input_hwnd; 19 | static int input_type; 20 | /*name of ...*/ 21 | static wchar_t shared_res_name[256]; 22 | static wchar_t mutex_name[256]; 23 | static void *old_address; 24 | static bool is_hooked; 25 | // 26 | static int setup(HWND hwnd_, int input_type_); 27 | static int release(); 28 | //LParam is pos,key:-1-2,means null, left mid and right, down means keyState 29 | static void upDataPos(LPARAM, int key, bool down); 30 | static opMouseState m_mouseState; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /libop/background/Hook/dinput.md: -------------------------------------------------------------------------------- 1 | ## dinput鼠标和键盘消息获取简介 2 | ### dinput的普通流程 3 | ```c++ 4 | //1. 注册DirectInput并获取IDirectInput接口指针 5 | DirectInput8Create( GetModuleHandle( NULL ), DIRECTINPUT_VERSION,IID_IDirectInput8, ( VOID** )&g_pDI, NULL ) 6 | //2. 获取系统鼠标 7 | g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) 8 | //3. 设置数据格式 9 | g_pMouse->SetDataFormat( &g_dfMouse) 10 | //4. 为该设备实例建立协作级别。合作级别决定了设备的这个实例如何与设备的其他实例和系统的其余部分交互。 11 | /* 12 | hwnd 13 | Window handle to be associated with the device. This parameter must be a valid top-level window handle that belongs to the process. The window associated with the device must not be destroyed while it is still active in a DirectInput device. 14 | dwFlags 15 | Flags that describe the cooperative level associated with the device. The following flags are defined: 16 | DISCL_BACKGROUND 17 | 该应用程序需要后台访问。如果授予后台访问权限,则可以随时获取设备,即使关联的窗口不是活动窗口。 18 | DISCL_EXCLUSIVE 19 | 该应用程序需要独占访问。如果授予独占访问权限,则设备的其他实例在获取该设备时无法获得对该设备的独占访问权限。但是,始终允许对设备进行非独占访问,即使另一个应用程序已获得独占访问权限。以独占模式获取鼠标或键盘设备的应用程序在收到 WM_ENTERSIZEMOVE 和 WM_ENTERMENULOOP 消息时应始终取消获取设备.否则,用户无法操作菜单或移动和调整窗口大小。 20 | DISCL_FOREGROUND 21 | 该应用程序需要前台访问。如果授予前台访问权限,则当关联的窗口移动到后台时,设备将自动取消获取。 22 | DISCL_NONEXCLUSIVE 23 | 该应用程序需要非独占访问。对设备的访问不会干扰正在访问同一设备的其他应用程序 24 | DISCL_NOWINKEY 25 | 禁用 Windows 徽标键。设置此标志可确保用户不会无意中退出应用程序。但请注意,当显示默认操作映射用户界面 (UI) 时,DISCL_NOWINKEY 不起作用,只要该 UI 存在,Windows 徽标键就会正常运行 26 | */ 27 | g_pMouse->SetCooperativeLevel( hDlg, DISCL_NONEXCLUSIVE | 28 | DISCL_FOREGROUND ) ) 29 | //5.从 DirectInput 设备上的轮询对象中检索数据,如果设备不需要轮询,则调用此方法无效。如果不定期轮询需要轮询的设备,则不会从该设备接收新数据。调用此方法会导致 DirectInput 更新设备状态、生成输入事件(如果启用了缓冲数据)并设置通知事件(如果启用了通知)。 30 | g_pMouse->Poll(); 31 | 32 | //6. 获得对输入设备的访问 33 | hr = g_pMouse->Acquire(); 34 | while( hr == DIERR_INPUTLOST ) 35 | hr = g_pMouse->Acquire(); 36 | 37 | //7. 从设备中检索即时数据。 38 | g_pMouse->GetDeviceState( sizeof( MouseState ), &ms ) 39 | /* 40 | cbData 41 | Size of the buffer in the lpvData parameter, in bytes. 42 | lpvData 43 | Address of a structure that receives the current state of the device. The format of the data is established by a prior call to the IDirectInputDevice8::SetDataFormat method. 44 | */ 45 | 46 | ``` 47 | The five predefined data formats require corresponding device state structures according to the following table: 48 | 49 | | Data format |State structure| 50 | |---|---| 51 | c_dfDIMouse |DIMOUSESTATE 52 | c_dfDIMouse2 |DIMOUSESTATE2 53 | c_dfDIKeyboard| array of 256 bytes 54 | c_dfDIJoystick| DIJOYSTATE 55 | c_dfDIJoystick2| DIJOYSTATE2 -------------------------------------------------------------------------------- /libop/background/Hook/opDx12Hook.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | //ref https://github.com/eugen15/directx-present-hook.git 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class opDx12Hook final { 14 | public: 15 | static opDx12Hook* Get(); 16 | 17 | // This method must be called only once! 18 | // There is no additional check inside. 19 | //HRESULT Hook(); 20 | 21 | // Captures some frames. 22 | HRESULT CaptureFrames(HWND windowHandleToCapture, 23 | std::wstring_view folderToSaveFrames, int maxFrames); 24 | void CaptureFrame(IDXGISwapChain* swapChain); 25 | private: 26 | opDx12Hook(); 27 | ~opDx12Hook(); 28 | 29 | 30 | 31 | 32 | // The command chain offset from the swap chain object pointer. 33 | std::uintptr_t commandQueueOffset_ = 0; 34 | 35 | // Hook pointers. 36 | std::uint64_t presentPointer_ = 0; 37 | std::uint64_t presentTrampoline_ = 0; 38 | 39 | // The resource to read frames from GPU. 40 | Microsoft::WRL::ComPtr readbackResource_; 41 | 42 | // Command allocator for a command list to copy the textures. 43 | Microsoft::WRL::ComPtr commandAllocator_; 44 | 45 | UINT readbackDataWidth_ = 0; 46 | UINT readbackDataHeight_ = 0; 47 | UINT readbackDataPitch_ = 0; 48 | 49 | void* readbackData_ = nullptr; 50 | 51 | // Capture details. 52 | HWND windowHandleToCapture_ = NULL; 53 | std::wstring folderToSaveFrames_; 54 | int frameIndex_ = 0; 55 | int maxFrames_ = 0; 56 | }; 57 | -------------------------------------------------------------------------------- /libop/background/Hook/opMessage.h: -------------------------------------------------------------------------------- 1 | #ifndef __OP_MESSAGE_H_ 2 | #define __OP_MESSAGE_H_ 3 | #include 4 | #define OP_MAKE_MESSAGE(msg) (WM_USER + msg) 5 | #define OP_WM_MOUSEMOVE (WM_USER + WM_MOUSEMOVE) 6 | #define OP_WM_LBUTTONUP (WM_USER + WM_LBUTTONUP) 7 | #define OP_WM_LBUTTONDOWN (WM_USER + WM_LBUTTONDOWN) 8 | #define OP_WM_MBUTTONDOWN (WM_USER + WM_MBUTTONDOWN) 9 | #define OP_WM_MBUTTONUP (WM_USER + WM_MBUTTONUP) 10 | #define OP_WM_RBUTTONDOWN (WM_USER + WM_RBUTTONDOWN) 11 | #define OP_WM_RBUTTONUP (WM_USER + WM_RBUTTONUP) 12 | #define OP_WM_MOUSEWHEEL (WM_USER + WM_MOUSEWHEEL) 13 | #endif -------------------------------------------------------------------------------- /libop/background/display/IDisplay.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "IDisplay.h" 3 | #include "./core/globalVar.h" 4 | #include "./core/helpfunc.h" 5 | IDisplay::IDisplay() 6 | :_hwnd(NULL), _shmem(nullptr), _pmutex(nullptr), 7 | _bind_state(0), _width(0), _height(0), 8 | _client_x(0), _client_y(0) 9 | { 10 | 11 | } 12 | 13 | 14 | IDisplay::~IDisplay() 15 | { 16 | bind_release(); 17 | _bind_state = 0; 18 | } 19 | 20 | long IDisplay::Bind(HWND hwnd, long flag) { 21 | //step 1 check window exists 22 | if (!::IsWindow(hwnd)) { 23 | return 0; 24 | } 25 | _hwnd = hwnd; 26 | //step 2. 准备资源 27 | bind_init(); 28 | //step 3. 调用特定的绑定函数 29 | 30 | if (BindEx(hwnd, flag) == 1) { 31 | _bind_state = 1; 32 | } 33 | else { 34 | bind_release(); 35 | _bind_state = 0; 36 | } 37 | 38 | 39 | return _bind_state; 40 | 41 | } 42 | 43 | long IDisplay::UnBind() { 44 | //setlog("UnBind("); 45 | if (_bind_state) { 46 | UnBindEx(); 47 | } 48 | bind_release(); 49 | _bind_state = 0; 50 | return 1; 51 | } 52 | 53 | long IDisplay::bind_init() { 54 | int res_size = 0; 55 | RECT rc; 56 | assert(::IsWindow(_hwnd)); 57 | ::GetWindowRect(_hwnd, &rc); 58 | res_size = (rc.right - rc.left) * (rc.bottom - rc.top) * 4+sizeof(FrameInfo); 59 | wsprintf(_shared_res_name, SHARED_RES_NAME_FORMAT, _hwnd); 60 | wsprintf(_mutex_name, MUTEX_NAME_FORMAT, _hwnd); 61 | //setlog(L"mem=%s mutex=%s", _shared_res_name, _mutex_name); 62 | //bind_release(); 63 | try { 64 | _shmem = new sharedmem(); 65 | _shmem->open_create(_shared_res_name, res_size); 66 | _pmutex = new promutex(); 67 | _pmutex->open_create(_mutex_name); 68 | } 69 | catch (std::exception& e) { 70 | setlog("bkdisplay::bind_init() %s exception:%s", _shared_res_name, e.what()); 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | long IDisplay::bind_release() { 77 | SAFE_DELETE(_shmem); 78 | SAFE_DELETE(_pmutex); 79 | 80 | _hwnd = NULL; 81 | //_image_data = nullptr; 82 | return 0; 83 | } 84 | 85 | void IDisplay::getFrameInfo(FrameInfo& info) { 86 | _pmutex->lock(); 87 | memcpy(&info, _shmem->data(), sizeof(FrameInfo)); 88 | _pmutex->unlock(); 89 | } 90 | 91 | //byte* bkdisplay::get_data() { 92 | // return _shmem->data(); 93 | //} 94 | 95 | -------------------------------------------------------------------------------- /libop/background/display/IDisplay.h: -------------------------------------------------------------------------------- 1 | #ifndef __IDISPLAY_H_ 2 | #define __IDISPLAY_H_ 3 | #include 4 | #include "./include/promutex.h" 5 | #include "./include/sharedmem.h" 6 | #include "frameInfo.h" 7 | struct Image; 8 | class IDisplay 9 | { 10 | public: 11 | IDisplay(); 12 | ~IDisplay(); 13 | //bind window 14 | long Bind(HWND hwnd, long flag); 15 | //unbind window 16 | long UnBind(); 17 | //unbind window 18 | //virtual long UnBind(HWND hwnd) = 0; 19 | virtual bool requestCapture(int x1, int y1, int w, int h, Image& img) = 0; 20 | 21 | 22 | promutex* get_mutex() { 23 | return _pmutex; 24 | } 25 | 26 | long get_height() { 27 | return _height; 28 | } 29 | 30 | long get_width() { 31 | return _width; 32 | } 33 | void getFrameInfo(FrameInfo& info); 34 | private: 35 | 36 | long bind_init(); 37 | 38 | long bind_release(); 39 | 40 | long _bind_state; 41 | protected: 42 | virtual long BindEx(HWND hwnd, long flag)=0; 43 | virtual long UnBindEx() = 0; 44 | 45 | HWND _hwnd; 46 | 47 | sharedmem* _shmem; 48 | 49 | promutex* _pmutex; 50 | 51 | wchar_t _shared_res_name[256]; 52 | 53 | wchar_t _mutex_name[256]; 54 | 55 | // 56 | int _render_type; 57 | 58 | long _width; 59 | long _height; 60 | 61 | int _client_x, _client_y; 62 | //need capture rect 63 | //RECT rect; 64 | 65 | }; 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /libop/background/display/frameInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __FRAME_INFO_H_ 2 | #define __FRAME_INFO_H_ 3 | #pragma pack(1) 4 | struct FrameInfo { 5 | unsigned __int64 hwnd; 6 | unsigned __int32 frameId; 7 | unsigned __int32 time; 8 | unsigned __int32 width; 9 | unsigned __int32 height; 10 | unsigned __int32 chk; 11 | void fmtChk() { 12 | chk = (hwnd >> 32) ^ (hwnd & 0xffffffffull) ^ frameId ^ time ^ width ^ height; 13 | } 14 | 15 | void format(HWND hwnd_, int w_, int h_) { 16 | hwnd = (unsigned __int64)hwnd_; 17 | frameId++; 18 | time = ::GetTickCount(); 19 | width = w_; 20 | height = h_; 21 | fmtChk(); 22 | } 23 | 24 | }; 25 | #pragma pack() 26 | #endif // !__FRAME_INFO_H_ 27 | -------------------------------------------------------------------------------- /libop/background/display/opDXGI.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/background/display/opDXGI.cpp -------------------------------------------------------------------------------- /libop/background/display/opDXGI.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/background/display/opDXGI.h -------------------------------------------------------------------------------- /libop/background/display/opDxGL.cpp: -------------------------------------------------------------------------------- 1 | 2 | //#include "stdafx.h" 3 | 4 | #include "opDxGL.h" 5 | #include "./core/globalVar.h" 6 | #include "./core/helpfunc.h" 7 | #include "./core/opEnv.h" 8 | #include 9 | #include "BlackBone/Process/Process.h" 10 | #include "BlackBone/Process/RPC/RemoteFunction.hpp" 11 | 12 | #include "./include/Image.hpp" 13 | 14 | #include 15 | opDxGL::opDxGL() :IDisplay(),m_opPath(opEnv::getBasePath()) 16 | { 17 | } 18 | 19 | opDxGL::~opDxGL() 20 | { 21 | //do clear 22 | UnBindEx(); 23 | } 24 | 25 | long opDxGL::BindEx(HWND hwnd, long render_type) { 26 | //setlog("BindEx"); 27 | _hwnd = hwnd; 28 | long bind_ret = 0; 29 | if (render_type == RDT_GL_NOX) { 30 | bind_ret = BindNox(hwnd, render_type); 31 | } 32 | else { 33 | _render_type = render_type; 34 | RECT rc; 35 | //获取客户区大小 36 | ::GetClientRect(hwnd, &rc); 37 | _width = rc.right - rc.left; 38 | _height = rc.bottom - rc.top; 39 | //bind_init(); 40 | if (render_type == RDT_GL_NOX) { 41 | } 42 | DWORD id; 43 | ::GetWindowThreadProcessId(_hwnd, &id); 44 | 45 | 46 | 47 | //attach 进程 48 | blackbone::Process proc; 49 | NTSTATUS hr; 50 | 51 | hr = proc.Attach(id); 52 | 53 | 54 | if (NT_SUCCESS(hr)) { 55 | wstring dllname = opEnv::getOpName(); 56 | //检查是否与插件相同的32/64位,如果不同,则使用另一种dll 57 | BOOL is64 = proc.modules().GetMainModule()->type == blackbone::eModType::mt_mod64; 58 | if (is64 != OP64) { 59 | dllname = is64 ? L"op_x64.dll" : L"op_x86.dll"; 60 | } 61 | 62 | bool injected = false; 63 | //判断是否已经注入 64 | auto _dllptr = proc.modules().GetModule(dllname); 65 | auto mods = proc.modules().GetAllModules(); 66 | if (_dllptr) { 67 | injected = true; 68 | } 69 | else { 70 | wstring opFile = m_opPath + L"\\" + dllname; 71 | if (::PathFileExistsW(opFile.data())) { 72 | auto iret = proc.modules().Inject(opFile); 73 | injected = (iret ? true : false); 74 | } 75 | else { 76 | setlog(L"file:<%s> not exists!", opFile.data()); 77 | } 78 | 79 | } 80 | if (injected) { 81 | //setlog("before MakeRemoteFunction"); 82 | using my_func_t = long(__stdcall*)(HWND, int); 83 | auto pSetXHook = blackbone::MakeRemoteFunction(proc, dllname, "SetDisplayHook"); 84 | if (pSetXHook) { 85 | //setlog("after MakeRemoteFunction"); 86 | auto cret = pSetXHook(hwnd, render_type); 87 | //setlog("after pSetXHook"); 88 | bind_ret = cret.result(); 89 | //setlog("after result"); 90 | } 91 | else { 92 | //setlog(L"remote function not found."); 93 | } 94 | } 95 | else { 96 | setlog(L"Inject false."); 97 | } 98 | } 99 | else { 100 | setlog(L"attach false."); 101 | } 102 | 103 | proc.Detach(); 104 | //setlog("after Detach"); 105 | } 106 | 107 | if (bind_ret == -1) { 108 | setlog("UnknownError"); 109 | } 110 | else if (bind_ret == -2) { 111 | setlog("NotSupportedError"); 112 | } 113 | else if (bind_ret == -3) { 114 | setlog("ModuleNotFoundError"); 115 | } 116 | return bind_ret; 117 | } 118 | 119 | long opDxGL::UnBindEx() { 120 | //setlog("bkdo::UnBindEx()"); 121 | if (_render_type == RDT_GL_NOX) 122 | return UnBindNox(); 123 | DWORD id; 124 | ::GetWindowThreadProcessId(_hwnd, &id); 125 | 126 | //attach 进程s 127 | blackbone::Process proc; 128 | NTSTATUS hr; 129 | //setlog("bkdo::Attach"); 130 | hr = proc.Attach(id); 131 | 132 | if (NT_SUCCESS(hr)) { 133 | wstring dllname = opEnv::getOpName(); 134 | //检查是否与插件相同的32/64位,如果不同,则使用另一种dll 135 | BOOL is64 = proc.modules().GetMainModule()->type == blackbone::eModType::mt_mod64; 136 | if (is64 != OP64) { 137 | dllname = is64 ? L"op_x64.dll" : L"op_x86.dll"; 138 | } 139 | //setlog(L"bkdo::dllname=%s",dllname); 140 | using my_func_t = long(__stdcall*)(void); 141 | auto pUnXHook = blackbone::MakeRemoteFunction(proc, dllname, "ReleaseDisplayHook"); 142 | if (pUnXHook) { 143 | //setlog(L"bkdo::pUnXHook"); 144 | pUnXHook(); 145 | //BOOL fret = ::FreeLibrary((HMODULE)proc.modules().GetModule(dllname)->baseAddress); 146 | //if (!fret)setlog("fret=%d", fret); 147 | /*proc.modules().RemoveManualModule(dllname, 148 | is64 ? blackbone::eModType::mt_mod64 : blackbone::eModType::mt_mod32);*/ 149 | } 150 | else { 151 | setlog(L"get unhook ptr false."); 152 | } 153 | } 154 | else { 155 | setlog("blackbone::MakeRemoteFunction false,errcode:%X,pid=%d,hwnd=%d", hr, id, _hwnd); 156 | } 157 | //setlog(L"bkdo::Detach"); 158 | proc.Detach(); 159 | //bind_release(); 160 | return 1; 161 | } 162 | 163 | long opDxGL::BindNox(HWND hwnd, long render_type) { 164 | _render_type = render_type; 165 | _hwnd = hwnd; 166 | RECT rc; 167 | //获取客户区大小 168 | ::GetClientRect(hwnd, &rc); 169 | _width = rc.right - rc.left; 170 | _height = rc.bottom - rc.top; 171 | //bind_init(); 172 | 173 | 174 | 175 | //attach 进程 176 | blackbone::Process proc; 177 | NTSTATUS hr = -1; 178 | 179 | 180 | wstring dllname = L"op_x64.dll"; 181 | 182 | 183 | hr = proc.Attach(L"NoxVMHandle.exe"); 184 | 185 | long bind_ret = 0; 186 | 187 | if (NT_SUCCESS(hr)) { 188 | /*_process.Resume();*/ 189 | bool injected = false; 190 | //判断是否已经注入 191 | auto _dllptr = proc.modules().GetModule(dllname); 192 | auto mods = proc.modules().GetAllModules(); 193 | if (_dllptr) { 194 | injected = true; 195 | } 196 | else { 197 | wstring opFile = m_opPath + L"\\" + dllname; 198 | if (::PathFileExistsW(opFile.data())) { 199 | auto iret = proc.modules().Inject(opFile); 200 | injected = (iret ? true : false); 201 | } 202 | else { 203 | setlog(L"file:<%s> not exists!", opFile.data()); 204 | } 205 | } 206 | if (injected) { 207 | using my_func_t = long(__stdcall*)(HWND, int); 208 | auto pSetXHook = blackbone::MakeRemoteFunction(proc, dllname, "SetDisplayHook"); 209 | if (pSetXHook) { 210 | auto cret = pSetXHook(hwnd, render_type); 211 | bind_ret = cret.result(); 212 | } 213 | else { 214 | setlog(L"remote function not found."); 215 | } 216 | } 217 | else { 218 | setlog(L"Inject false."); 219 | } 220 | 221 | 222 | 223 | } 224 | else { 225 | setlog(L"attach false."); 226 | } 227 | proc.Detach(); 228 | 229 | 230 | return bind_ret; 231 | } 232 | 233 | long opDxGL::UnBindNox() { 234 | 235 | //attach 进程 236 | blackbone::Process proc; 237 | NTSTATUS hr; 238 | 239 | hr = proc.Attach(L"NoxVMHandle.exe"); 240 | wstring dllname = L"op_x64.dll"; 241 | 242 | 243 | if (NT_SUCCESS(hr)) { 244 | 245 | using my_func_t = long(__stdcall*)(void); 246 | auto pUnXHook = blackbone::MakeRemoteFunction(proc, dllname, "ReleaseDisplayHook"); 247 | if (pUnXHook) { 248 | pUnXHook(); 249 | 250 | /*BOOL fret = ::FreeLibrary((HMODULE)proc.modules().GetModule(dllname)->baseAddress); 251 | if (!fret)setlog("fret=%d", fret);*/ 252 | } 253 | else { 254 | setlog(L"get unhook ptr false."); 255 | } 256 | } 257 | else { 258 | setlog("blackbone::MakeRemoteFunction false,errcode:%Xhwnd=%d", hr, _hwnd); 259 | } 260 | 261 | proc.Detach(); 262 | 263 | return 1; 264 | } 265 | 266 | bool opDxGL::requestCapture(int x1, int y1, int w, int h, Image& img) { 267 | img.create(w, h); 268 | _pmutex->lock(); 269 | uchar* const ppixels = _shmem->data() + sizeof(FrameInfo); 270 | FrameInfo* pInfo = (FrameInfo*)_shmem->data(); 271 | static bool first = true; 272 | if (first&&(pInfo->width != _width || pInfo->height != _height)) { 273 | first = false; 274 | std::wstringstream ss(std::wstringstream::in | std::wstringstream::out); 275 | ss << (*pInfo); 276 | setlog(L"error pInfo->width != _width || pInfo->height != _height\nframe info:\n%s", ss.str().data()); 277 | 278 | } 279 | 280 | 281 | if (GET_RENDER_TYPE(_render_type) == RENDER_TYPE::DX) {//NORMAL 282 | 283 | for (int i = 0; i < h; i++) { 284 | memcpy(img.ptr(i), ppixels + (i + y1) * 4 * _width + x1 * 4, 4 * w); 285 | } 286 | } 287 | else { 288 | 289 | for (int i = 0; i < h; i++) { 290 | memcpy(img.ptr(i), ppixels + (_height - 1 - i - y1) * _width * 4 + x1 * 4, 4 * w); 291 | } 292 | } 293 | 294 | 295 | _pmutex->unlock(); 296 | return true; 297 | } 298 | 299 | -------------------------------------------------------------------------------- /libop/background/display/opDxGL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __DXBACKGROUND_H_ 3 | #define __DXBACKGROUND_H_ 4 | 5 | #include "IDisplay.h" 6 | struct Image; 7 | class opDxGL : public IDisplay 8 | { 9 | public: 10 | opDxGL(); 11 | ~opDxGL(); 12 | //1 13 | long BindEx(HWND hwnd, long render_type) override; 14 | 15 | /*long UnBind(HWND hwnd);*/ 16 | 17 | long UnBindEx() override; 18 | 19 | virtual bool requestCapture(int x1, int y1, int w, int h, Image &img) override; 20 | 21 | //nox mode 22 | long BindNox(HWND hwnd, long render_type); 23 | // 24 | long UnBindNox(); 25 | 26 | private: 27 | //blackbone::Process _process; 28 | wstring m_opPath; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libop/background/display/opGDI.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "opGDI.h" 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "../../winapi/WinApi.h" 9 | #include "./include/Image.hpp" 10 | #include "globalVar.h" 11 | #include "helpfunc.h" 12 | opGDI::opGDI() { 13 | _render_type = 0; 14 | dx_ = 0; 15 | dy_ = 0; 16 | // 4*2^22=16*2^20=16MB 17 | //_image_data = new byte[MAX_IMAGE_WIDTH*MAX_IMAGE_WIDTH * 4]; 18 | } 19 | 20 | opGDI::~opGDI() { 21 | // SAFE_DELETE_ARRAY(_image_data); 22 | } 23 | 24 | long opGDI::BindEx(HWND hwnd, long render_type) { 25 | if (!::IsWindow(hwnd)) return 0; 26 | _hwnd = hwnd; 27 | _render_type = render_type; 28 | 29 | if (render_type == RDT_NORMAL) { 30 | RECT rc, rc2; 31 | ::GetWindowRect(_hwnd, &rc); 32 | ::GetClientRect(hwnd, &rc2); 33 | 34 | _width = rc2.right - rc2.left; 35 | _height = rc2.bottom - rc2.top; 36 | POINT pt = {0}; 37 | ::ClientToScreen(hwnd, &pt); 38 | dx_ = pt.x - rc.left; 39 | dy_ = pt.y - rc.top; 40 | _hdc = ::GetDC(NULL); 41 | } else { // client size 42 | RECT rc, rc2; 43 | ::GetWindowRect(_hwnd, &rc); 44 | ::GetClientRect(hwnd, &rc2); 45 | _width = rc2.right - rc2.left; 46 | _height = rc2.bottom - rc2.top; 47 | POINT pt = {0}; 48 | ::ClientToScreen(hwnd, &pt); 49 | dx_ = pt.x - rc.left; 50 | dy_ = pt.y - rc.top; 51 | /*setlog("dx=%d dy=%d", dx_, dy_);*/ 52 | if (_render_type == RDT_GDI) { 53 | _hdc = ::GetDC(_hwnd); 54 | //SetWindowLongA(topHwnd, GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED); 55 | //UpdateWindow(topHwnd); 56 | 57 | } else if (RDT_GDI_DX2 == render_type) { 58 | _hdc = ::GetDC(_hwnd); 59 | _device_caps = GetDeviceCaps(_hdc, BITSPIXEL); 60 | } else { 61 | /* HWND dx2TopHwnd = WinApi::GetTopWindowSp(_hwnd); 62 | GetPropA(dx2TopHwnd, "opstyle"); 63 | long dx2ExStyle = GetWindowLongA(dx2TopHwnd, GWL_EXSTYLE);*/ 64 | /*if (GetPropA(dx2TopHwnd, "opstyle_flag")) { 65 | dx2ExStyle = GetWindowLongA(dx2TopHwnd, GWL_EXSTYLE); 66 | } else { 67 | dx2ExStyle = GetWindowLongA(dx2TopHwnd, GWL_EXSTYLE); 68 | SetPropA(dx2TopHwnd, "opstyle", (HANDLE)dx2ExStyle); 69 | SetPropA(dx2TopHwnd, "opstyle_flag", (HANDLE)HANDLE_FLAG_INHERIT); 70 | } 71 | */ 72 | /* SetWindowLongA(dx2TopHwnd, GWL_EXSTYLE, dx2ExStyle | WS_EX_LAYERED); 73 | UpdateWindow(dx2TopHwnd);*/ 74 | _hdc = ::GetDC(_hwnd); 75 | } 76 | } 77 | 78 | if (_hdc == NULL) { 79 | setlog("hdc == NULL", _hdc); 80 | return 0; 81 | } 82 | 83 | //创建一个与指定设备兼容的内存设备上下文环境 84 | _hmdc = CreateCompatibleDC(_hdc); 85 | if (_hmdc == NULL) { 86 | setlog("CreateCompatibleDC false"); 87 | return -2; 88 | } 89 | 90 | // updata_screen(); 91 | return 1; 92 | } 93 | 94 | long opGDI::UnBindEx() { 95 | // setlog("bkgdi::UnBindEx()"); 96 | _hbmpscreen = (HBITMAP)SelectObject(_hmdc, _hbmp_old); 97 | // delete[dwLen_2]hDib; 98 | if (_hdc) DeleteDC(_hdc); 99 | _hdc = NULL; 100 | if (_hmdc) DeleteDC(_hmdc); 101 | _hmdc = NULL; 102 | 103 | if (_hbmpscreen) DeleteObject(_hbmpscreen); 104 | _hbmpscreen = NULL; 105 | // if (_hbmp_old)DeleteObject(_hbmp_old); _hbmp_old = NULL; 106 | return 1; 107 | } 108 | 109 | bool opGDI::requestCapture(int x1, int y1, int w, int h, Image& img) { 110 | // step 1.判断 窗口是否存在 111 | if (!::IsWindow(_hwnd)) return 0; 112 | img.create(w, h); 113 | if (_render_type == RDT_NORMAL) { // normal 拷贝的大小为实际需要的大小 114 | // 115 | /* int w = rect.right - rect.left; 116 | int h = rect.bottom - rect.top;*/ 117 | _hbmpscreen = CreateCompatibleBitmap( 118 | _hdc, w, h); //创建与指定的设备环境相关的设备兼容的位图 119 | _hbmp_old = (HBITMAP)SelectObject( 120 | _hmdc, _hbmpscreen); //选择一对象到指定的设备上下文环境中 121 | 122 | _bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 123 | _bfh.bfSize = _bfh.bfOffBits + w * h * 4; 124 | _bfh.bfType = static_cast(0x4d42); 125 | 126 | _bih.biBitCount = 32; //每个像素字节大小 127 | _bih.biCompression = BI_RGB; 128 | _bih.biHeight = h; //高度 129 | _bih.biPlanes = 1; 130 | _bih.biSize = sizeof(BITMAPINFOHEADER); 131 | _bih.biSizeImage = w * h * 4; //图像数据大小 132 | _bih.biWidth = w; //宽度 133 | 134 | //对指定的源设备环境区域中的像素进行位块(bit_block)转换 135 | 136 | RECT rc; 137 | ::GetWindowRect(_hwnd, &rc); 138 | // setlog("rect left =%d top =%d, dx =%d, dy = %d", rc.left, rc.top, dx_, 139 | // dy_); 140 | int src_x = x1 + rc.left + dx_; 141 | int src_y = y1 + rc.top + dy_; 142 | if (BitBlt(_hmdc, 0, 0, w, h, _hdc, src_x, src_y, SRCCOPY)) { 143 | // ok 144 | } else { 145 | setlog("error in bitbit"); 146 | } 147 | 148 | //函数获取指定兼容位图的位,然后将其作一个DIB—设备无关位图(Device-Independent 149 | // Bitmap)使用的指定格式复制到一个缓冲区中 _pmutex->lock(); 150 | uchar* pshare = _shmem->data(); 151 | fmtFrameInfo(pshare, _hwnd, w, h); 152 | GetDIBits(_hmdc, _hbmpscreen, 0L, (DWORD)h, pshare + sizeof(FrameInfo), 153 | (LPBITMAPINFO)&_bih, (DWORD)DIB_RGB_COLORS); 154 | 155 | //_pmutex->unlock(); 156 | if (_hbmpscreen) DeleteObject(_hbmpscreen); 157 | _hbmpscreen = NULL; 158 | 159 | //将数据拷贝到目标注意实际数据是反的 160 | 161 | for (int i = 0; i < h; i++) { 162 | memcpy(img.ptr(i), _shmem->data() + sizeof(FrameInfo) + (h - 1 - i) * 4 * w, 163 | 4 * w); 164 | } 165 | } else if (RDT_GDI_DX2 == _render_type) { 166 | ATL::CImage image; 167 | image.Create(w, h, _device_caps); 168 | BitBlt(image.GetDC(), 0, 0, w, h, _hdc, x1, y1, SRCCOPY); 169 | img.read(&image); 170 | image.ReleaseDC(); 171 | } else { // gdi ... 由于printwindow 函数的原因 172 | // 截取大小为实际的窗口大小,在后续的处理中,需要转化成客户区大小 173 | // 174 | RECT rc; 175 | ::GetWindowRect(_hwnd, &rc); 176 | int ww = rc.right - rc.left; 177 | int wh = rc.bottom - rc.top; 178 | // setlog("_w w=%d %d _h h=%d %d,dx=%d dy=%d", _width, w, _height, h, dx_, 179 | // dy_); 180 | _hbmpscreen = CreateCompatibleBitmap( 181 | _hdc, ww, wh); //创建与指定的设备环境相关的设备兼容的位图 182 | _hbmp_old = (HBITMAP)SelectObject( 183 | _hmdc, _hbmpscreen); //选择一对象到指定的设备上下文环境中 184 | 185 | _bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 186 | _bfh.bfSize = _bfh.bfOffBits + ww * wh * 4; 187 | _bfh.bfType = static_cast(0x4d42); 188 | 189 | _bih.biBitCount = 32; //每个像素字节大小 190 | _bih.biCompression = BI_RGB; 191 | _bih.biHeight = wh; //高度 192 | _bih.biPlanes = 1; 193 | _bih.biSize = sizeof(BITMAPINFOHEADER); 194 | _bih.biSizeImage = ww * wh * 4; //图像数据大小 195 | _bih.biWidth = ww; //宽度 196 | 197 | //对指定的源设备环境区域中的像素进行位块(bit_block)转换 198 | 199 | if (_render_type == RDT_GDI) { 200 | ::PrintWindow(_hwnd, _hmdc, 0); 201 | 202 | } else { 203 | ::UpdateWindow(_hwnd); 204 | //::RedrawWindow(_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | 205 | //:RDW_ALLCHILDREN | RDW_FRAME); 206 | ::PrintWindow(_hwnd, _hmdc, 0); 207 | } 208 | //函数获取指定兼容位图的位,然后将其作一个DIB—设备无关位图(Device-Independent 209 | // Bitmap)使用的指定格式复制到一个缓冲区中 _pmutex->lock(); 210 | uchar* pshare = _shmem->data(); 211 | fmtFrameInfo(pshare, _hwnd, w, h); 212 | GetDIBits(_hmdc, _hbmpscreen, 0L, (DWORD)wh, pshare + sizeof(FrameInfo), 213 | (LPBITMAPINFO)&_bih, (DWORD)DIB_RGB_COLORS); 214 | 215 | if (_hbmpscreen) DeleteObject(_hbmpscreen); 216 | _hbmpscreen = NULL; 217 | 218 | //将数据拷贝到目标注意实际数据是反的(注意偏移) 219 | auto ppixels = _shmem->data() + sizeof(FrameInfo); 220 | for (int i = 0; i < h; i++) { 221 | memcpy(img.ptr(i), 222 | ppixels + (wh - 1 - i - y1 - dy_) * 4 * ww + (x1 + dx_) * 4, 223 | 4 * w); 224 | } 225 | } 226 | return 1; 227 | } 228 | void opGDI::fmtFrameInfo(void* dst, HWND hwnd, int w, int h) { 229 | m_frameInfo.hwnd = (unsigned __int64)hwnd; 230 | m_frameInfo.frameId++; 231 | m_frameInfo.time = ::GetTickCount64(); 232 | m_frameInfo.width = w; 233 | m_frameInfo.height = h; 234 | m_frameInfo.fmtChk(); 235 | memcpy(dst, &m_frameInfo, sizeof(m_frameInfo)); 236 | } 237 | -------------------------------------------------------------------------------- /libop/background/display/opGDI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __BKDISPLAY_H_ 3 | #define __BKDISPLAY_H_ 4 | #include 5 | #include "optype.h" 6 | #include "IDisplay.h" 7 | struct Image; 8 | class opGDI:public IDisplay 9 | { 10 | public: 11 | opGDI(); 12 | ~opGDI(); 13 | //绑定 14 | long BindEx(HWND _hwnd, long render_type) override; 15 | //解绑 16 | long UnBindEx() override; 17 | 18 | virtual bool requestCapture(int x1, int y1, int w, int h, Image& img)override; 19 | 20 | private: 21 | //设备句柄 22 | HDC _hdc = NULL; 23 | int _device_caps = 0; 24 | HDC _hmdc = NULL; 25 | //位图句柄 26 | HBITMAP _hbmpscreen = NULL; 27 | HBITMAP _hbmp_old = NULL; 28 | //bmp 文件头 29 | BITMAPFILEHEADER _bfh = { 0 }; 30 | BITMAPINFOHEADER _bih = { 0 };//位图信息头 31 | int dx_, dy_;//去除标题栏 32 | //bytearray temp_src; 33 | FrameInfo m_frameInfo; 34 | void fmtFrameInfo(void* dst,HWND hwnd, int w, int h); 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /libop/background/display/opWGC.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/background/display/opWGC.cpp -------------------------------------------------------------------------------- /libop/background/display/opWGC.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/background/display/opWGC.h -------------------------------------------------------------------------------- /libop/background/keypad/Bkkeypad.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "Bkkeypad.h" 3 | //#include "globalVar.h" 4 | //#include "helpfunc.h" 5 | // 6 | //static uint oem_code(uint key){ 7 | // short code[256] = { 0 }; 8 | // code['q'] = 0x10; code['a'] = 0x1e; 9 | // code['w'] = 0x11; code['s'] = 0x1f; 10 | // code['e'] = 0x12; code['d'] = 0x20; 11 | // code['r'] = 0x13; code['f'] = 0x21; 12 | // code['t'] = 0x14; code['g'] = 0x22; 13 | // code['y'] = 0x15; code['h'] = 0x23; 14 | // code['u'] = 0x16; code['j'] = 0x24; 15 | // code['i'] = 0x17; code['k'] = 0x25; 16 | // code['o'] = 0x18; code['l'] = 0x26; 17 | // code['p'] = 0x19; code[':'] = 0x27; code[';'] = 0x27; 18 | // 19 | // code['z'] = 0x2c; 20 | // code['x'] = 0x2d; 21 | // code['c'] = 0x2e; 22 | // code['v'] = 0x2f; 23 | // code['b'] = 0x30; 24 | // code['n'] = 0x31; 25 | // code['m'] = 0x32; 26 | // return code[key & 0xffu]; 27 | // 28 | //} 29 | // 30 | bkkeypad::bkkeypad():_hwnd(0),_mode(0) 31 | { 32 | } 33 | // 34 | // 35 | bkkeypad::~bkkeypad() 36 | { 37 | UnBind(); 38 | } 39 | // 40 | //long bkkeypad::Bind(HWND hwnd, long mode) { 41 | // if (!::IsWindow(hwnd)) 42 | // return 0; 43 | // _hwnd = hwnd; 44 | // _mode = mode; 45 | // return 1; 46 | //} 47 | // 48 | long bkkeypad::UnBind() { 49 | _hwnd = NULL; 50 | _mode = 0; 51 | return 1; 52 | } 53 | // 54 | //long bkkeypad::GetKeyState(long vk_code) { 55 | // vk_code = toupper(vk_code); 56 | // return 0x8000 & ::GetAsyncKeyState(vk_code); 57 | //} 58 | // 59 | //long bkkeypad::KeyDown(long vk_code) { 60 | // long ret = 0; 61 | // vk_code=toupper(vk_code); 62 | // 63 | // switch (_mode) { 64 | // case INPUT_TYPE::IN_NORMAL: 65 | // { 66 | // POINT pt; 67 | // 68 | // 69 | // INPUT Input = { 0 }; 70 | // Input.type = INPUT_KEYBOARD; 71 | // Input.ki.wVk = vk_code; 72 | // Input.ki.dwFlags = 0; 73 | // 74 | // /*The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. 75 | // If the function returns zero, the input was already blocked by another thread. 76 | // To get extended error information, call GetLastError. 77 | // This function fails when it is blocked by UIPI. 78 | // Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking. 79 | // */ 80 | // ret = ::SendInput(1, &Input, sizeof(INPUT)); 81 | // break; 82 | // } 83 | // 84 | // case INPUT_TYPE::IN_WINDOWS: { 85 | // /*Specification of WM_KEYDOWN :*/ 86 | // 87 | // /*wParam 88 | // 89 | // Specifies the virtual - key code of the nonsystem key. 90 | // lParam 91 | // Specifies the repeat count, scan code, extended - key flag, context code, 92 | // previous key - state flag, 93 | // and transition - state flag, as shown in the following table. 94 | // 0 - 15 95 | // Specifies the repeat count for the current message.The value is 96 | // the number of times the keystroke is 97 | // autorepeated as a result of the user holding down the key.If the 98 | // keystroke is held long enough, multiple messages are sent.However, 99 | // the repeat count is not cumulative. 100 | // 16 - 23 101 | // Specifies the scan code.The value depends on the OEM. 102 | // 24 103 | // Specifies whether the key is an extended key, such as the 104 | // right - hand ALT and CTRL keys that 105 | // appear on an enhanced 101 - or 102 - key keyboard.The value 106 | // is 1 if it is an extended key; otherwise, it is 0. 107 | // 25 - 28 108 | // Reserved; do not use. 109 | // 29 110 | // Specifies the context code.The value is always 0 for a WM_KEYDOWN message. 111 | // 30 112 | // Specifies the previous key state.The value is 1 if the key 113 | // is down before the message is sent, or it is zero if the key is up. 114 | // 31 115 | // Specifies the transition state.The value is always zero for a WM_KEYDOWN message.*/ 116 | // 117 | // DWORD lparam = 1u; 118 | // if (vk_code == VK_RCONTROL) 119 | // lparam |= 1u << 24; 120 | // lparam |= oem_code(vk_code) << 16; 121 | // ret = ::PostMessageW(_hwnd, WM_KEYDOWN, vk_code, lparam); 122 | // //ret = ::SendMessageW(_hwnd, WM_KEYDOWN, vk_code, 0); 123 | // if (ret == 0)setlog("error code=%d", GetLastError()); 124 | // break; 125 | // } 126 | // } 127 | // 128 | // 129 | // return ret; 130 | //} 131 | // 132 | //long bkkeypad::KeyUp(long vk_code) { 133 | // long ret = 0; 134 | // vk_code = toupper(vk_code); 135 | // switch (_mode) { 136 | // case INPUT_TYPE::IN_NORMAL: 137 | // { 138 | // POINT pt; 139 | // 140 | // 141 | // INPUT Input = { 0 }; 142 | // Input.type = INPUT_KEYBOARD; 143 | // Input.ki.wVk = vk_code; 144 | // Input.ki.dwFlags = KEYEVENTF_KEYUP; 145 | // 146 | // /*The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. 147 | // If the function returns zero, the input was already blocked by another thread. 148 | // To get extended error information, call GetLastError. 149 | // This function fails when it is blocked by UIPI. 150 | // Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking. 151 | // */ 152 | // ret = ::SendInput(1, &Input, sizeof(INPUT)); 153 | // break; 154 | // } 155 | // 156 | // case INPUT_TYPE::IN_WINDOWS: { 157 | // /*Specification of WM_KEYUP 158 | // wParam 159 | // Specifies the virtual - key code of the nonsystem key. 160 | // lParam 161 | // Specifies the repeat count, scan code, extended - key flag, context code, 162 | // previous key - state flag, and transition - state flag, as shown in the following table. 163 | // 0 - 15 164 | // Specifies the repeat count for the current message.The value is the number of times the keystroke is 165 | // autorepeated as a result of the user holding down the key. 166 | // The repeat count is always one for a WM_KEYUP message. 167 | // 16 - 23 168 | // Specifies the scan code.The value depends on the OEM. 169 | // 24 170 | // Specifies whether the key is an extended key, such as the right - hand ALT and CTRL keys that 171 | // appear on an enhanced 101 - or 102 - key keyboard.The value is 1 if it is an extended key; otherwise, it is 0. 172 | // 25 - 28 173 | // Reserved; do not use. 174 | // 29 175 | // Specifies the context code.The value is always 0 for a WM_KEYUP message. 176 | // 30 177 | // Specifies the previous key state.The value is always 1 for a WM_KEYUP message. 178 | // 31 179 | // Specifies the transition state.The value is always 1 for a WM_KEYUP message.*/ 180 | // //ret = ::SendMessageW(_hwnd, WM_KEYUP, vk_code, 0); 181 | // DWORD lparam = 1u; 182 | // if (vk_code == VK_RCONTROL)lparam |= 1u << 24; 183 | // lparam |= oem_code(vk_code) << 16; 184 | // lparam |= 1u << 30; 185 | // lparam |= 1u << 31; 186 | // ret = ::PostMessageW(_hwnd, WM_KEYUP, vk_code, lparam); 187 | // if (ret == 0)setlog("error2 code=%d", GetLastError()); 188 | // break; 189 | // } 190 | // } 191 | // 192 | // 193 | // return ret; 194 | //} 195 | // 196 | //long bkkeypad::WaitKey(long vk_code, long time_out) { 197 | // auto deadline = ::GetTickCount() + time_out; 198 | // while (::GetTickCount() < deadline) { 199 | // if (GetKeyState(vk_code)) 200 | // return 1; 201 | // ::Sleep(1); 202 | // } 203 | // return 0; 204 | //} 205 | // 206 | //long bkkeypad::KeyPress(long vk_code) { 207 | // KeyDown(vk_code); 208 | // ::Delay(KEYPAD_DX_DELAY); 209 | // return KeyUp(vk_code); 210 | //} 211 | -------------------------------------------------------------------------------- /libop/background/keypad/Bkkeypad.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/optype.h" 3 | class bkkeypad 4 | { 5 | public: 6 | bkkeypad(); 7 | 8 | virtual ~bkkeypad(); 9 | 10 | virtual long Bind(HWND hwnd, long mode) = 0; 11 | 12 | virtual long UnBind(); 13 | 14 | virtual long GetKeyState(long vk_code) = 0; 15 | 16 | virtual long KeyDown(long vk_code) = 0; 17 | 18 | //virtual long GetKeyState(long vk_code); 19 | 20 | virtual long KeyUp(long vk_code) = 0; 21 | 22 | virtual long WaitKey(long vk_code, unsigned long time_out) = 0; 23 | 24 | virtual long KeyPress(long vk_code) = 0; 25 | protected: 26 | HWND _hwnd; 27 | int _mode; 28 | }; 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /libop/background/keypad/winkeypad.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "winkeypad.h" 3 | #include "./core/globalVar.h" 4 | #include "./core/helpfunc.h" 5 | 6 | static uint oem_code(uint key) { 7 | short code[256] = { 0 }; 8 | code['q'] = 0x10; code['a'] = 0x1e; 9 | code['w'] = 0x11; code['s'] = 0x1f; 10 | code['e'] = 0x12; code['d'] = 0x20; 11 | code['r'] = 0x13; code['f'] = 0x21; 12 | code['t'] = 0x14; code['g'] = 0x22; 13 | code['y'] = 0x15; code['h'] = 0x23; 14 | code['u'] = 0x16; code['j'] = 0x24; 15 | code['i'] = 0x17; code['k'] = 0x25; 16 | code['o'] = 0x18; code['l'] = 0x26; 17 | code['p'] = 0x19; code[':'] = 0x27; code[';'] = 0x27; 18 | 19 | code['z'] = 0x2c; 20 | code['x'] = 0x2d; 21 | code['c'] = 0x2e; 22 | code['v'] = 0x2f; 23 | code['b'] = 0x30; 24 | code['n'] = 0x31; 25 | code['m'] = 0x32; 26 | return code[key & 0xffu]; 27 | 28 | } 29 | 30 | winkeypad::winkeypad():bkkeypad() 31 | { 32 | } 33 | 34 | 35 | winkeypad::~winkeypad() 36 | { 37 | //UnBind(); 38 | } 39 | 40 | long winkeypad::Bind(HWND hwnd, long mode) { 41 | if (!::IsWindow(hwnd)) 42 | return 0; 43 | _hwnd = hwnd; 44 | _mode = mode; 45 | return 1; 46 | } 47 | 48 | long winkeypad::UnBind() { 49 | _hwnd = NULL; 50 | _mode = 0; 51 | return 1; 52 | } 53 | 54 | long winkeypad::GetKeyState(long vk_code) { 55 | vk_code = toupper(vk_code); 56 | return 0x8000 & ::GetAsyncKeyState(vk_code); 57 | } 58 | 59 | long winkeypad::KeyDown(long vk_code) { 60 | long ret = 0; 61 | // vk_code = toupper(vk_code); 62 | 63 | switch (_mode) { 64 | case INPUT_TYPE::IN_NORMAL: 65 | { 66 | 67 | INPUT Input = { 0 }; 68 | Input.type = INPUT_KEYBOARD; 69 | Input.ki.wVk = (WORD)vk_code; 70 | Input.ki.wScan = 0; 71 | Input.ki.dwFlags = 0; 72 | 73 | /*The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. 74 | If the function returns zero, the input was already blocked by another thread. 75 | To get extended error information, call GetLastError. 76 | This function fails when it is blocked by UIPI. 77 | Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking. 78 | */ 79 | ret = ::SendInput(1, &Input, sizeof(INPUT)); 80 | break; 81 | } 82 | case INPUT_TYPE::IN_NORMAL2: 83 | { 84 | INPUT Input = { 0 }; 85 | Input.type = INPUT_KEYBOARD; 86 | Input.ki.wVk = 0; 87 | Input.ki.wScan = MapVirtualKey(vk_code, MAPVK_VK_TO_VSC); 88 | Input.ki.dwFlags = KEYEVENTF_SCANCODE; 89 | ret = ::SendInput(1, &Input, sizeof(INPUT)); 90 | if (ret == 0) 91 | setlog("op:IN_NORMAL2 erro code:%s", GetLastErrorAsString().c_str()); 92 | break; 93 | } 94 | case INPUT_TYPE::IN_WINDOWS: { 95 | /*Specification of WM_KEYDOWN :*/ 96 | 97 | /*wParam 98 | 99 | Specifies the virtual - key code of the nonsystem key. 100 | lParam 101 | Specifies the repeat count, scan code, extended - key flag, context code, 102 | previous key - state flag, 103 | and transition - state flag, as shown in the following table. 104 | 0 - 15 105 | Specifies the repeat count for the current message.The value is 106 | the number of times the keystroke is 107 | autorepeated as a result of the user holding down the key.If the 108 | keystroke is held long enough, multiple messages are sent.However, 109 | the repeat count is not cumulative. 110 | 16 - 23 111 | Specifies the scan code.The value depends on the OEM. 112 | 24 113 | Specifies whether the key is an extended key, such as the 114 | right - hand ALT and CTRL keys that 115 | appear on an enhanced 101 - or 102 - key keyboard.The value 116 | is 1 if it is an extended key; otherwise, it is 0. 117 | 25 - 28 118 | Reserved; do not use. 119 | 29 120 | Specifies the context code.The value is always 0 for a WM_KEYDOWN message. 121 | 30 122 | Specifies the previous key state.The value is 1 if the key 123 | is down before the message is sent, or it is zero if the key is up. 124 | 31 125 | Specifies the transition state.The value is always zero for a WM_KEYDOWN message.*/ 126 | 127 | DWORD dwVKFkeyData; 128 | WORD dwScanCode = MapVirtualKey(vk_code, 0); 129 | dwVKFkeyData = 1; 130 | dwVKFkeyData |= dwScanCode << 16; 131 | dwVKFkeyData |= 0 << 24; 132 | dwVKFkeyData |= 0 << 29; 133 | ret = ::SendMessageTimeout(_hwnd, WM_KEYDOWN, vk_code, dwVKFkeyData, SMTO_BLOCK, 2000, nullptr); 134 | if (ret == 0)setlog("error code=%d", GetLastError()); 135 | break; 136 | } 137 | } 138 | 139 | 140 | return ret; 141 | } 142 | 143 | long winkeypad::KeyUp(long vk_code) { 144 | long ret = 0; 145 | // vk_code = toupper(vk_code); 146 | switch (_mode) { 147 | case INPUT_TYPE::IN_NORMAL: 148 | { 149 | 150 | INPUT Input = { 0 }; 151 | Input.type = INPUT_KEYBOARD; 152 | Input.ki.wVk = vk_code; 153 | Input.ki.wScan =0; 154 | Input.ki.dwFlags = KEYEVENTF_KEYUP; 155 | 156 | /*The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. 157 | If the function returns zero, the input was already blocked by another thread. 158 | To get extended error information, call GetLastError. 159 | This function fails when it is blocked by UIPI. 160 | Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking. 161 | */ 162 | ret = ::SendInput(1, &Input, sizeof(INPUT)); 163 | break; 164 | } 165 | case INPUT_TYPE::IN_NORMAL2: 166 | { 167 | INPUT Input = { 0 }; 168 | Input.type = INPUT_KEYBOARD; 169 | Input.ki.wVk = 0; 170 | Input.ki.wScan = MapVirtualKey(vk_code, MAPVK_VK_TO_VSC); 171 | Input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; 172 | ret = ::SendInput(1, &Input, sizeof(INPUT)); 173 | if (ret == 0) 174 | setlog("op:IN_NORMAL2 erro code:%s", GetLastErrorAsString().c_str()); 175 | break; 176 | } 177 | 178 | case INPUT_TYPE::IN_WINDOWS: { 179 | /*Specification of WM_KEYUP 180 | wParam 181 | Specifies the virtual - key code of the nonsystem key. 182 | lParam 183 | Specifies the repeat count, scan code, extended - key flag, context code, 184 | previous key - state flag, and transition - state flag, as shown in the following table. 185 | 0 - 15 186 | Specifies the repeat count for the current message.The value is the number of times the keystroke is 187 | autorepeated as a result of the user holding down the key. 188 | The repeat count is always one for a WM_KEYUP message. 189 | 16 - 23 190 | Specifies the scan code.The value depends on the OEM. 191 | 24 192 | Specifies whether the key is an extended key, such as the right - hand ALT and CTRL keys that 193 | appear on an enhanced 101 - or 102 - key keyboard.The value is 1 if it is an extended key; otherwise, it is 0. 194 | 25 - 28 195 | Reserved; do not use. 196 | 29 197 | Specifies the context code.The value is always 0 for a WM_KEYUP message. 198 | 30 199 | Specifies the previous key state.The value is always 1 for a WM_KEYUP message. 200 | 31 201 | Specifies the transition state.The value is always 1 for a WM_KEYUP message.*/ 202 | //ret = ::SendMessageW(_hwnd, WM_KEYUP, vk_code, 0); 203 | DWORD dwVKFkeyData; 204 | WORD dwScanCode = MapVirtualKey(vk_code, 0); 205 | dwVKFkeyData = 1; 206 | dwVKFkeyData |= dwScanCode << 16; 207 | dwVKFkeyData |= 0 << 24; 208 | dwVKFkeyData |= 0 << 29; 209 | dwVKFkeyData |= 3 << 30; 210 | ret = ::SendMessageTimeout(_hwnd, WM_KEYUP, vk_code, dwVKFkeyData, SMTO_BLOCK, 2000, nullptr); 211 | if (ret == 0)setlog("error code=%d", GetLastError()); 212 | break; 213 | } 214 | } 215 | 216 | 217 | return ret; 218 | } 219 | 220 | long winkeypad::WaitKey(long vk_code, unsigned long time_out) { 221 | auto deadline = ::GetTickCount64() + time_out; 222 | while (::GetTickCount64() < deadline) { 223 | if (GetKeyState(vk_code)) 224 | return 1; 225 | ::Sleep(1); 226 | } 227 | return 0; 228 | } 229 | 230 | long winkeypad::KeyPress(long vk_code) { 231 | KeyDown(vk_code); 232 | switch (_mode) { 233 | case INPUT_TYPE::IN_NORMAL: { 234 | ::Delay(KEYPAD_NORMAL_DELAY); 235 | break; 236 | } 237 | case INPUT_TYPE::IN_NORMAL2: { 238 | ::Delay(KEYPAD_NORMAL2_DELAY); 239 | break; 240 | } 241 | case INPUT_TYPE::IN_WINDOWS: { 242 | ::Delay(KEYPAD_WINDOWS_DELAY); 243 | break; 244 | } 245 | } 246 | return KeyUp(vk_code); 247 | } 248 | -------------------------------------------------------------------------------- /libop/background/keypad/winkeypad.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _WIN_KEYPAD_H_ 3 | #define _WIN_KEYPAD_H_ 4 | #include "Bkkeypad.h" 5 | class winkeypad:public bkkeypad 6 | { 7 | public: 8 | winkeypad(); 9 | 10 | virtual ~winkeypad(); 11 | 12 | virtual long Bind(HWND hwnd, long mode); 13 | 14 | virtual long UnBind(); 15 | 16 | virtual long GetKeyState(long vk_code); 17 | 18 | virtual long KeyDown(long vk_code); 19 | 20 | //virtual long GetKeyState(long vk_code); 21 | 22 | virtual long KeyUp(long vk_code); 23 | 24 | virtual long WaitKey(long vk_code, unsigned long time_out); 25 | 26 | virtual long KeyPress(long vk_code); 27 | }; 28 | #endif // !_WIN_KEYPAD_H_ 29 | 30 | 31 | -------------------------------------------------------------------------------- /libop/background/mouse/opMouseDx.cpp: -------------------------------------------------------------------------------- 1 | // #include "stdafx.h" 2 | #include "opMouseDx.h" 3 | #include "../core/globalVar.h" 4 | #include "../core/helpfunc.h" 5 | #include "BlackBone/Process/Process.h" 6 | #include "BlackBone/Process/RPC/RemoteFunction.hpp" 7 | #include "../core/opEnv.h" 8 | #include "../HOOK/opMessage.h" 9 | opMouseDx::opMouseDx() 10 | : _hwnd(NULL), _mode(0), _x(0), _y(0), _dpi(getDPI()) 11 | { 12 | } 13 | 14 | opMouseDx::~opMouseDx() 15 | { 16 | _hwnd = NULL; 17 | } 18 | 19 | long opMouseDx::Bind(HWND h, int mode) 20 | { 21 | _hwnd = h; 22 | _mode = mode; 23 | DWORD id; 24 | ::GetWindowThreadProcessId(_hwnd, &id); 25 | 26 | // attach 进程 27 | blackbone::Process proc; 28 | NTSTATUS hr; 29 | 30 | hr = proc.Attach(id); 31 | long ret = 0; 32 | if (NT_SUCCESS(hr)) 33 | { 34 | wstring dllname = opEnv::getOpName(); 35 | // 检查是否与插件相同的32/64位,如果不同,则使用另一种dll 36 | BOOL is64 = proc.modules().GetMainModule()->type == blackbone::eModType::mt_mod64; 37 | if (is64 != OP64) 38 | { 39 | dllname = is64 ? L"op_x64.dll" : L"op_x86.dll"; 40 | } 41 | 42 | bool injected = false; 43 | // 判断是否已经注入 44 | auto _dllptr = proc.modules().GetModule(dllname); 45 | auto mods = proc.modules().GetAllModules(); 46 | if (_dllptr) 47 | { 48 | injected = true; 49 | } 50 | else 51 | { 52 | wstring opFile = opEnv::getBasePath() + L"\\" + dllname; 53 | if (::PathFileExistsW(opFile.data())) 54 | { 55 | auto iret = proc.modules().Inject(opFile); 56 | injected = (iret ? true : false); 57 | } 58 | else 59 | { 60 | setlog(L"file:<%s> not exists!", opFile.data()); 61 | } 62 | } 63 | if (injected) 64 | { 65 | using my_func_t = long(__stdcall *)(HWND, int); 66 | auto PSetInputHook = blackbone::MakeRemoteFunction(proc, dllname, "SetInputHook"); 67 | if (PSetInputHook) 68 | { 69 | // setlog("after MakeRemoteFunction"); 70 | auto cret = PSetInputHook(_hwnd, _mode); 71 | // setlog("after pSetXHook"); 72 | ret = cret.result(); 73 | // setlog("after result"); 74 | } 75 | else 76 | { 77 | setlog(L"remote function 'SetInputHook' not found."); 78 | } 79 | } 80 | else 81 | { 82 | setlog(L"Inject false."); 83 | } 84 | } 85 | else 86 | { 87 | setlog(L"attach false."); 88 | } 89 | 90 | proc.Detach(); 91 | // setlog("after Detach"); 92 | 93 | return 1; 94 | } 95 | 96 | long opMouseDx::UnBind() 97 | { 98 | DWORD id; 99 | ::GetWindowThreadProcessId(_hwnd, &id); 100 | 101 | // attach 进程 102 | blackbone::Process proc; 103 | NTSTATUS hr; 104 | 105 | hr = proc.Attach(id); 106 | long ret = 0; 107 | if (NT_SUCCESS(hr)) 108 | { 109 | wstring dllname = opEnv::getOpName(); 110 | // 检查是否与插件相同的32/64位,如果不同,则使用另一种dll 111 | BOOL is64 = proc.modules().GetMainModule()->type == blackbone::eModType::mt_mod64; 112 | if (is64 != OP64) 113 | { 114 | dllname = is64 ? L"op_x64.dll" : L"op_x86.dll"; 115 | } 116 | using my_func_t = long(__stdcall *)(); 117 | auto pReleaseInputHook = blackbone::MakeRemoteFunction(proc, dllname, "ReleaseInputHook"); 118 | if (pReleaseInputHook) 119 | { 120 | // setlog("after MakeRemoteFunction"); 121 | auto cret = pReleaseInputHook(); 122 | // setlog("after pSetXHook"); 123 | ret = cret.result(); 124 | // setlog("after result"); 125 | } 126 | else 127 | { 128 | setlog(L"remote function 'ReleaseInputHook' not found."); 129 | } 130 | } 131 | else 132 | { 133 | setlog(L"attach false."); 134 | } 135 | 136 | proc.Detach(); 137 | // setlog("after Detach"); 138 | _hwnd = 0; 139 | _mode = 0; 140 | return 1; 141 | } 142 | 143 | long opMouseDx::GetCursorPos(long &x, long &y) 144 | { 145 | BOOL ret = FALSE; 146 | POINT pt; 147 | ret = ::GetCursorPos(&pt); 148 | if (_hwnd != ::GetDesktopWindow()) 149 | { 150 | ret = ::ScreenToClient(_hwnd, &pt); 151 | } 152 | x = pt.x; 153 | y = pt.y; 154 | return ret; 155 | } 156 | 157 | long opMouseDx::MoveR(int rx, int ry) 158 | { 159 | return MoveTo(_x + rx, _y + ry); 160 | } 161 | 162 | long opMouseDx::MoveTo(int x, int y) 163 | { 164 | // 启用DPI感知后,不需要在进行坐标处理 165 | // x = x * _dpi; 166 | // y = y * _dpi; 167 | long ret = 0; 168 | ret = ::SendMessage(_hwnd, OP_WM_MOUSEMOVE, 0, MAKELPARAM(x, y)) == 0 ? 1 : 0; 169 | 170 | _x = x, _y = y; 171 | return ret; 172 | } 173 | 174 | long opMouseDx::MoveToEx(int x, int y, int w, int h) 175 | { 176 | 177 | if (w >= 2 && h >= 2) 178 | return MoveTo(x + rand() % w, y + rand() % h); 179 | else 180 | return MoveTo(x, y); 181 | } 182 | 183 | long opMouseDx::LeftClick() 184 | { 185 | long ret = 0, ret2 = 0; 186 | 187 | /// ret=::PostMessage(_hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_x, _y)); 188 | ret = ::SendMessageTimeout(_hwnd, OP_WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_x, _y), SMTO_BLOCK, 2000, nullptr); 189 | // ret = ::SendNotifyMessage(_hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_x, _y)); 190 | ::Delay(MOUSE_DX_DELAY); 191 | // ret = ::SendMessage(_hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_x, _y)); 192 | ret2 = ::SendMessageTimeout(_hwnd, OP_WM_LBUTTONUP, 0, MAKELPARAM(_x, _y), SMTO_BLOCK, 2000, nullptr); 193 | 194 | return ret && ret2 ? 1 : 0; 195 | } 196 | 197 | long opMouseDx::LeftDoubleClick() 198 | { 199 | long r1, r2; 200 | r1 = LeftClick(); 201 | ::Delay(MOUSE_DX_DELAY); 202 | r2 = LeftClick(); 203 | return r1 & r2 ? 1 : 0; 204 | } 205 | 206 | long opMouseDx::LeftDown() 207 | { 208 | long ret = 0; 209 | 210 | ret = ::SendMessage(_hwnd, OP_WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(_x, _y)); 211 | 212 | return ret; 213 | } 214 | 215 | long opMouseDx::LeftUp() 216 | { 217 | long ret = 0; 218 | 219 | ret = ::SendMessage(_hwnd, OP_WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(_x, _y)); 220 | 221 | return ret; 222 | } 223 | 224 | long opMouseDx::MiddleClick() 225 | { 226 | long r1, r2; 227 | r1 = MiddleDown(); 228 | ::Delay(MOUSE_DX_DELAY); 229 | r2 = MiddleUp(); 230 | return r1 & r2 ? 1 : 0; 231 | } 232 | 233 | long opMouseDx::MiddleDown() 234 | { 235 | long ret = 0; 236 | 237 | ret = ::SendMessage(_hwnd, OP_WM_MBUTTONDOWN, MK_MBUTTON, MAKELPARAM(_x, _y)); 238 | 239 | return ret; 240 | } 241 | 242 | long opMouseDx::MiddleUp() 243 | { 244 | long ret = 0; 245 | 246 | ret = ::SendMessage(_hwnd, OP_WM_MBUTTONUP, MK_MBUTTON, MAKELPARAM(_x, _y)); 247 | 248 | return ret; 249 | } 250 | 251 | long opMouseDx::RightClick() 252 | { 253 | long ret = 0; 254 | long r1, r2; 255 | 256 | r1 = ::SendMessage(_hwnd, OP_WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(_x, _y)); 257 | ::Delay(MOUSE_DX_DELAY); 258 | r2 = ::SendMessage(_hwnd, OP_WM_RBUTTONUP, MK_RBUTTON, MAKELPARAM(_x, _y)); 259 | ret = r1 == 0 && r2 == 0 ? 1 : 0; 260 | 261 | return ret; 262 | } 263 | 264 | long opMouseDx::RightDown() 265 | { 266 | long ret = 0; 267 | 268 | ret = ::PostMessage(_hwnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(_x, _y)) == 0 ? 1 : 0; 269 | 270 | return ret; 271 | } 272 | 273 | long opMouseDx::RightUp() 274 | { 275 | long ret = 0; 276 | 277 | ret = ::PostMessage(_hwnd, OP_WM_RBUTTONUP, MK_RBUTTON, MAKELPARAM(_x, _y)); 278 | 279 | return ret; 280 | } 281 | 282 | long opMouseDx::WheelDown() 283 | { 284 | long ret = 0; 285 | 286 | /* 287 | wParam 288 | The high-order word indicates the distance the wheel is rotated, 289 | expressed in multiples or divisions of WHEEL_DELTA, which is 120. 290 | A positive value indicates that the wheel was rotated forward, away from the user; 291 | a negative value indicates that the wheel was rotated backward, toward the user. 292 | The low-order word indicates whether various virtual keys are down. 293 | This parameter can be one or more of the following values. 294 | lParam 295 | The low-order word specifies the x-coordinate of the pointer, 296 | relative to the upper-left corner of the screen. 297 | The high-order word specifies the y-coordinate of the pointer, 298 | relative to the upper-left corner of the screen. 299 | */ 300 | // If an application processes this message, it should return zero. 301 | ret = ::SendMessage(_hwnd, OP_WM_MOUSEWHEEL, MAKEWPARAM(-WHEEL_DELTA, 0), MAKELPARAM(_x, _y)) == 0 ? 1 : 0; 302 | 303 | return ret; 304 | } 305 | 306 | long opMouseDx::WheelUp() 307 | { 308 | long ret = 0; 309 | 310 | ret = ::SendMessage(_hwnd, OP_WM_MOUSEWHEEL, MAKEWPARAM(WHEEL_DELTA, 0), MAKELPARAM(_x, _y)) == 0 ? 1 : 0; 311 | 312 | return ret; 313 | } 314 | -------------------------------------------------------------------------------- /libop/background/mouse/opMouseDx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../core/optype.h" 3 | #include "opMouseWin.h" 4 | class opMouseDx: public opMouseWin 5 | { 6 | public: 7 | opMouseDx(); 8 | virtual ~opMouseDx(); 9 | 10 | virtual long Bind(HWND h,int mode); 11 | 12 | virtual long UnBind(); 13 | 14 | virtual long GetCursorPos(long&x, long& y); 15 | 16 | virtual long MoveR(int rx, int ry); 17 | 18 | virtual long MoveTo(int x, int y); 19 | 20 | virtual long MoveToEx(int x, int y,int w,int h); 21 | 22 | virtual long LeftClick(); 23 | 24 | virtual long LeftDoubleClick(); 25 | 26 | virtual long LeftDown(); 27 | 28 | virtual long LeftUp(); 29 | 30 | virtual long MiddleClick(); 31 | 32 | virtual long MiddleDown(); 33 | 34 | virtual long MiddleUp(); 35 | 36 | virtual long RightClick(); 37 | 38 | virtual long RightDown(); 39 | 40 | virtual long RightUp(); 41 | 42 | virtual long WheelDown(); 43 | 44 | virtual long WheelUp(); 45 | private: 46 | HWND _hwnd; 47 | int _mode; 48 | int _x,_y; 49 | float _dpi;//screen dpi 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /libop/background/mouse/opMouseWin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/optype.h" 3 | class opMouseWin 4 | { 5 | public: 6 | static float getDPI(); 7 | opMouseWin(); 8 | virtual ~opMouseWin(); 9 | 10 | virtual long Bind(HWND h,int mode); 11 | 12 | virtual long UnBind(); 13 | 14 | virtual long GetCursorPos(long&x, long& y); 15 | 16 | virtual long MoveR(int rx, int ry); 17 | 18 | virtual long MoveTo(int x, int y); 19 | 20 | virtual long MoveToEx(int x, int y,int w,int h); 21 | 22 | virtual long LeftClick(); 23 | 24 | virtual long LeftDoubleClick(); 25 | 26 | virtual long LeftDown(); 27 | 28 | virtual long LeftUp(); 29 | 30 | virtual long MiddleClick(); 31 | 32 | virtual long MiddleDown(); 33 | 34 | virtual long MiddleUp(); 35 | 36 | virtual long RightClick(); 37 | 38 | virtual long RightDown(); 39 | 40 | virtual long RightUp(); 41 | 42 | virtual long WheelDown(); 43 | 44 | virtual long WheelUp(); 45 | private: 46 | HWND _hwnd; 47 | int _mode; 48 | int _x,_y; 49 | float _dpi;//screen dpi 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /libop/background/opBackground.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __BACKBASE_H_ 3 | #define __BACKBASE_H_ 4 | #include 5 | #include "include/Image.hpp" 6 | 7 | #include "./display/IDisplay.h" 8 | 9 | #include "./mouse/opMouseWin.h" 10 | #include "./keypad/Bkkeypad.h" 11 | 12 | 13 | using std::wstring; 14 | 15 | 16 | class opBackground 17 | { 18 | public: 19 | 20 | opBackground(); 21 | ~opBackground(); 22 | public: 23 | virtual long BindWindow(long hwnd, const wstring& sdisplay, const wstring& smouse, const wstring& skeypad, long mode); 24 | virtual long UnBindWindow(); 25 | virtual long GetBindWindow(); 26 | virtual long IsBind(); 27 | //virtual long GetCursorPos(int& x, int& y); 28 | 29 | long GetDisplay(); 30 | /*byte* GetScreenData();*/ 31 | void lock_data(); 32 | void unlock_data(); 33 | long get_height(); 34 | long get_width(); 35 | long RectConvert(long&x1, long&y1, long&x2, long&y2); 36 | //0:normal;-1 reserve 1 need cut 37 | long get_image_type(); 38 | 39 | bool check_bind(); 40 | const std::pair& get_display_method()const; 41 | long set_display_method(const wstring& method); 42 | 43 | bool requestCapture(int x1,int y1,int w,int h,Image& img); 44 | private: 45 | HWND _hwnd; 46 | int _is_bind; 47 | int _display; 48 | int _mode; 49 | std::pair _display_method; 50 | Image _pic; 51 | 52 | IDisplay* createDisplay(int mode); 53 | opMouseWin* createMouse(int mode); 54 | bkkeypad* createKeypad(int mode); 55 | public: 56 | IDisplay* _pbkdisplay; 57 | opMouseWin* _bkmouse; 58 | bkkeypad* _keypad; 59 | wstring _curr_path; 60 | }; 61 | #endif 62 | 63 | 64 | -------------------------------------------------------------------------------- /libop/com/OpInterface.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | ForceRemove op.opsoft.1 = s 'OpInterface class' 4 | { 5 | CLSID = s '{12bec402-a06e-4fad-a7d4-830f967374c6}' 6 | } 7 | ForceRemove op.opsoft = s 'OpInterface class' 8 | { 9 | CurVer = s 'op.opsoft.1' 10 | } 11 | NoRemove CLSID 12 | { 13 | ForceRemove {12bec402-a06e-4fad-a7d4-830f967374c6} = s 'OpInterface class' 14 | { 15 | ProgID = s 'op.opsoft.1' 16 | VersionIndependentProgID = s 'op.opsoft' 17 | ForceRemove Programmable 18 | InprocServer32 = s '%MODULE%' 19 | { 20 | val ThreadingModel = s 'Apartment' 21 | } 22 | TypeLib = s '{66b9c175-82f2-45e9-af86-58ad5ded5adc}' 23 | Version = s '1.0' 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libop/com/compreg.cpp: -------------------------------------------------------------------------------- 1 | // compreg.cpp : CCompReg 的实现 2 | 3 | #include "stdafx.h" 4 | #include "compreg.h" 5 | 6 | 7 | // CCompReg 8 | -------------------------------------------------------------------------------- /libop/com/compreg.h: -------------------------------------------------------------------------------- 1 | // compreg.h : CCompReg 的声明 2 | 3 | #pragma once 4 | 5 | #include "resource.h" // 主符号 6 | #include "op_i.h" 7 | 8 | -------------------------------------------------------------------------------- /libop/com/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp: DllMain 的实现。 2 | 3 | 4 | #include "resource.h" 5 | #include "op_i.h" 6 | #include "dllmain.h" 7 | #include "compreg.h" 8 | #include "../core/opEnv.h" 9 | CopModule _AtlModule; 10 | 11 | // DLL 入口点 12 | extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 13 | { 14 | opEnv::setInstance(hInstance); 15 | return _AtlModule.DllMain(dwReason, lpReserved); 16 | } 17 | -------------------------------------------------------------------------------- /libop/com/dllmain.h: -------------------------------------------------------------------------------- 1 | // dllmain.h: 模块类的声明。 2 | #include 3 | #include 4 | #include 5 | class CopModule : public ATL::CAtlDllModuleT< CopModule > 6 | { 7 | public : 8 | DECLARE_LIBID(LIBID_opLib) 9 | DECLARE_REGISTRY_APPID_RESOURCEID(IDR_OP, "{66b9c175-82f2-45e9-af86-58ad5ded5adc}") 10 | }; 11 | 12 | extern class CopModule _AtlModule; 13 | -------------------------------------------------------------------------------- /libop/com/op.cpp: -------------------------------------------------------------------------------- 1 | // op.cpp: DLL 导出的实现。 2 | 3 | // 4 | // 注意: COM+ 1.0 信息: 5 | // 请记住运行 Microsoft Transaction Explorer 以安装组件。 6 | // 默认情况下不进行注册。 7 | 8 | #include "stdafx.h" 9 | #include "resource.h" 10 | #include "op_i.h" 11 | #include "dllmain.h" 12 | #include "compreg.h" 13 | 14 | 15 | using namespace ATL; 16 | 17 | // 用于确定 DLL 是否可由 OLE 卸载。 18 | _Use_decl_annotations_ 19 | STDAPI DllCanUnloadNow(void) 20 | { 21 | return _AtlModule.DllCanUnloadNow(); 22 | } 23 | 24 | // 返回一个类工厂以创建所请求类型的对象。 25 | _Use_decl_annotations_ 26 | STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv) 27 | { 28 | return _AtlModule.DllGetClassObject(rclsid, riid, ppv); 29 | } 30 | 31 | // DllRegisterServer - 向系统注册表中添加项。 32 | _Use_decl_annotations_ 33 | STDAPI DllRegisterServer(void) 34 | { 35 | // 注册对象、类型库和类型库中的所有接口 36 | HRESULT hr = _AtlModule.DllRegisterServer(); 37 | return hr; 38 | } 39 | 40 | // DllUnregisterServer - 移除系统注册表中的项。 41 | _Use_decl_annotations_ 42 | STDAPI DllUnregisterServer(void) 43 | { 44 | HRESULT hr = _AtlModule.DllUnregisterServer(); 45 | return hr; 46 | } 47 | 48 | // DllInstall - 按用户和计算机在系统注册表中逐一添加/移除项。 49 | STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine) 50 | { 51 | HRESULT hr = E_FAIL; 52 | static const wchar_t szUserSwitch[] = L"user"; 53 | 54 | if (pszCmdLine != nullptr) 55 | { 56 | if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) 57 | { 58 | ATL::AtlSetPerUserRegistration(true); 59 | } 60 | } 61 | 62 | if (bInstall) 63 | { 64 | hr = DllRegisterServer(); 65 | if (FAILED(hr)) 66 | { 67 | DllUnregisterServer(); 68 | } 69 | } 70 | else 71 | { 72 | hr = DllUnregisterServer(); 73 | } 74 | 75 | return hr; 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /libop/com/op.def: -------------------------------------------------------------------------------- 1 | ; op.def: 声明模块参数。 2 | 3 | LIBRARY 4 | 5 | EXPORTS 6 | DllCanUnloadNow PRIVATE 7 | DllGetClassObject PRIVATE 8 | DllRegisterServer PRIVATE 9 | DllUnregisterServer PRIVATE 10 | DllInstall PRIVATE 11 | SetDisplayHook PRIVATE 12 | ReleaseDisplayHook PRIVATE 13 | SetInputHook PRIVATE 14 | ReleaseInputHook PRIVATE 15 | 16 | -------------------------------------------------------------------------------- /libop/com/op.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/com/op.rc -------------------------------------------------------------------------------- /libop/com/op.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | NoRemove CLSID 4 | { 5 | ForceRemove {54ca0535-fb49-4d91-8709-786fb8725132} = s 'CompReg Class' 6 | { 7 | InprocServer32 = s '%MODULE%' 8 | { 9 | val ThreadingModel = s 'Apartment' 10 | } 11 | TypeLib = s '{66b9c175-82f2-45e9-af86-58ad5ded5adc}' 12 | Version = s '1.0' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libop/com/opps.def: -------------------------------------------------------------------------------- 1 | 2 | LIBRARY 3 | 4 | EXPORTS 5 | DllGetClassObject PRIVATE 6 | DllCanUnloadNow PRIVATE 7 | DllRegisterServer PRIVATE 8 | DllUnregisterServer PRIVATE 9 | -------------------------------------------------------------------------------- /libop/com/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ 生成的包含文件。 3 | // 供 op.rc 使用 4 | // 5 | #define IDS_PROJNAME 100 6 | #define IDR_OP 101 7 | #define IDR_OPINTERFACE 106 8 | 9 | // Next default values for new objects 10 | // 11 | #ifdef APSTUDIO_INVOKED 12 | #ifndef APSTUDIO_READONLY_SYMBOLS 13 | #define _APS_NEXT_RESOURCE_VALUE 201 14 | #define _APS_NEXT_COMMAND_VALUE 32768 15 | #define _APS_NEXT_CONTROL_VALUE 201 16 | #define _APS_NEXT_SYMED_VALUE 107 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /libop/com/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : 只包括标准包含文件的源文件 2 | // op.pch 将作为预编译标头 3 | // stdafx.obj 将包含预编译类型信息 4 | 5 | #include "stdafx.h" 6 | -------------------------------------------------------------------------------- /libop/com/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : 标准系统包含文件的包含文件, 2 | // 或是经常使用但不常更改的 3 | // 特定于项目的包含文件 4 | 5 | #pragma once 6 | 7 | #ifndef STRICT 8 | #define STRICT 9 | #endif 10 | 11 | #include "targetver.h" 12 | 13 | #define _ATL_APARTMENT_THREADED 14 | 15 | #define _ATL_NO_AUTOMATIC_NAMESPACE 16 | 17 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的 18 | 19 | 20 | #include 21 | 22 | #define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW 23 | 24 | #include "resource.h" 25 | //#include 26 | //#include 27 | //#include 28 | -------------------------------------------------------------------------------- /libop/com/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。 4 | 5 | // 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将 6 | // 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /libop/core/Cmder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Pipe.h" 3 | class Cmder : public Pipe { 4 | public: 5 | void on_read(const string& ss)override { 6 | _readed += ss; 7 | 8 | } 9 | string GetCmdStr(const string&cmd,size_t milseconds) { 10 | open(cmd); 11 | if (is_open()) { 12 | auto deadline = clock()+milseconds; 13 | while (is_open()&& clock() 4 | #include 5 | #include "globalVar.h" 6 | #include "helpfunc.h" 7 | Pipe::Pipe() 8 | { 9 | _hread = _hwrite = _hread2 = _hwrite2 = nullptr; 10 | _hprocess = nullptr; 11 | _reading = 0; 12 | _pthread = nullptr; 13 | } 14 | 15 | 16 | 17 | 18 | Pipe::~Pipe() 19 | { 20 | close(); 21 | } 22 | 23 | int Pipe::open(const string& cmd) { 24 | _ai.nLength = sizeof(SECURITY_ATTRIBUTES); 25 | _ai.bInheritHandle = true; 26 | _ai.lpSecurityDescriptor = nullptr; 27 | if (!CreatePipe(&_hread, &_hwrite, &_ai, 0)) 28 | return -1; 29 | if (!CreatePipe(&_hread2, &_hwrite2, &_ai, 0)) 30 | return -2; 31 | GetStartupInfoA(&_si); 32 | _si.cb = sizeof(STARTUPINFO); 33 | _si.hStdError = _hwrite; 34 | _si.hStdOutput = _hwrite; 35 | _si.hStdInput = _hread2; 36 | _si.wShowWindow = SW_HIDE; 37 | _si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; 38 | char buf[0xff]; 39 | memcpy(buf, cmd.data(), sizeof(char) * (1 + cmd.length())); 40 | if (!CreateProcessA(NULL, buf, nullptr, nullptr, true, NULL, nullptr, nullptr, &_si, &_pi)) 41 | return -3; 42 | _reading = 1; 43 | _pthread = new std::thread(&Pipe::reader, this); 44 | return 1; 45 | } 46 | 47 | int Pipe::close() { 48 | if (_reading) { 49 | _reading = 0; 50 | on_write("exit"); 51 | 52 | if (::WaitForSingleObject(_pi.hProcess, 1000) == WAIT_TIMEOUT) { 53 | ::TerminateProcess(_pi.hProcess, 0); 54 | TerminateThread(_pthread->native_handle(), -1); 55 | } 56 | else { 57 | 58 | } 59 | 60 | _pthread->join(); 61 | 62 | 63 | } 64 | SAFE_DELETE(_pthread); 65 | SAFE_CLOSE(_hread); 66 | SAFE_CLOSE(_hwrite); 67 | SAFE_CLOSE(_hwrite2); 68 | SAFE_CLOSE(_hread2); 69 | SAFE_CLOSE(_pi.hProcess); 70 | SAFE_CLOSE(_pi.hThread); 71 | return 0; 72 | } 73 | 74 | void Pipe::on_read(const string& info) { 75 | std::cout << info << std::endl; 76 | } 77 | 78 | int Pipe::on_write(const string& info) { 79 | if (_reading) { 80 | unsigned long wlen = 0; 81 | 82 | return WriteFile(_hwrite2, info.data(), info.length() * sizeof(char), &wlen, nullptr); 83 | } 84 | return 0; 85 | } 86 | 87 | void Pipe::reader() { 88 | const static int buf_size = 1 << 10; 89 | char buf[buf_size]; 90 | unsigned long read_len = 0; 91 | while (_reading) { 92 | memset(buf, 0, buf_size * sizeof(char)); 93 | if (ReadFile(_hread, buf, buf_size - 1, &read_len, NULL)) { 94 | //setlog("readed:%s", buf); 95 | on_read(buf); 96 | } 97 | else { 98 | _reading = 0; 99 | break; 100 | } 101 | } 102 | } 103 | 104 | bool Pipe::is_open() { 105 | if (_reading) { 106 | DWORD code = 0; 107 | ::GetExitCodeProcess(_pi.hProcess, &code); 108 | return code == STILL_ACTIVE; 109 | } 110 | return false; 111 | } 112 | 113 | -------------------------------------------------------------------------------- /libop/core/Pipe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | class Pipe 6 | { 7 | public: 8 | using handle_t = HANDLE; 9 | using string=std::string; 10 | Pipe(); 11 | virtual ~Pipe(); 12 | int open(const string& cmd); 13 | int close(); 14 | virtual void on_read(const string& info); 15 | virtual int on_write(const string& info); 16 | bool is_open(); 17 | private: 18 | handle_t _hread, _hwrite; 19 | handle_t _hread2, _hwrite2; 20 | handle_t _hprocess; 21 | SECURITY_ATTRIBUTES _ai; 22 | PROCESS_INFORMATION _pi; 23 | STARTUPINFOA _si; 24 | int _reading; 25 | std::thread* _pthread; 26 | void reader(); 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /libop/core/globalVar.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "optype.h" 3 | #include "globalVar.h" 4 | #include 5 | 6 | //HINSTANCE gInstance; 7 | 8 | //int gShowError = 1; 9 | 10 | //wstring m_opPath; 11 | 12 | //wstring g_op_name; 13 | 14 | long KEYPAD_NORMAL_DELAY = 30; 15 | long KEYPAD_NORMAL2_DELAY = 30; 16 | long KEYPAD_WINDOWS_DELAY = 10; 17 | long KEYPAD_DX_DELAY = 50; 18 | 19 | long MOUSE_NORMAL_DELAY = 30; 20 | long MOUSE_WINDOWS_DELAY = 10; 21 | long MOUSE_DX_DELAY = 40; 22 | 23 | -------------------------------------------------------------------------------- /libop/core/globalVar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __GLOBALVAR_H_ 3 | #define __GLOBALVAR_H_ 4 | #include "optype.h" 5 | #define SAFE_CLOSE(h) \ 6 | if (h) \ 7 | CloseHandle(h); \ 8 | h = NULL; 9 | template 10 | void SAFE_DELETE(Type *&ptr) 11 | { 12 | delete ptr; 13 | ptr = nullptr; 14 | } 15 | 16 | #define SAFE_DELETE_ARRAY(ptr) \ 17 | if (ptr) \ 18 | delete[] ptr; \ 19 | ptr = nullptr 20 | 21 | #define SAFE_RELEASE(obj) \ 22 | if (obj) \ 23 | obj->Release(); \ 24 | obj = nullptr 25 | 26 | //#define _sto_wstring(s) boost::locale::conv::to_utf(s, "GBK") 27 | //#define _wsto_string(s) boost::locale::conv::from_utf(s,"GBK") 28 | 29 | #define DLL_API extern "C" _declspec(dllexport) 30 | //normal windows,gdi;,dx;opengl; 31 | enum RENDER_TYPE 32 | { 33 | NORMAL = 0, 34 | GDI = 1, 35 | DX = 2, 36 | OPENGL = 3 37 | }; 38 | 39 | #define MAKE_RENDER(type, flag) ((type << 16) | flag) 40 | 41 | #define GET_RENDER_TYPE(t) (t >> 16) 42 | 43 | #define GET_RENDER_FLAG(t) (t & 0xffff) 44 | 45 | constexpr int RDT_NORMAL = MAKE_RENDER(NORMAL, 0); 46 | constexpr int RDT_NORMAL_DXGI = MAKE_RENDER(NORMAL, 1); 47 | constexpr int RDT_NORMAL_WGC = MAKE_RENDER(NORMAL, 2); 48 | constexpr int RDT_GDI = MAKE_RENDER(GDI, 0); 49 | constexpr int RDT_GDI2 = MAKE_RENDER(GDI, 1); 50 | constexpr int RDT_GDI_DX2 = MAKE_RENDER(GDI, 2); 51 | constexpr int RDT_DX_DEFAULT = MAKE_RENDER(DX, 0); 52 | constexpr int RDT_DX_D3D9 = MAKE_RENDER(DX, 1); 53 | constexpr int RDT_DX_D3D10 = MAKE_RENDER(DX, 2); 54 | constexpr int RDT_DX_D3D11 = MAKE_RENDER(DX, 3); 55 | constexpr int RDT_DX_D3D12 = MAKE_RENDER(DX, 4); 56 | constexpr int RDT_GL_DEFAULT = MAKE_RENDER(OPENGL, 0); 57 | constexpr int RDT_GL_STD = MAKE_RENDER(OPENGL, 1); 58 | constexpr int RDT_GL_NOX = MAKE_RENDER(OPENGL, 2); 59 | constexpr int RDT_GL_ES = MAKE_RENDER(OPENGL, 3); 60 | constexpr int RDT_GL_FI = MAKE_RENDER(OPENGL, 4); //glFinish 61 | 62 | enum INPUT_TYPE 63 | { 64 | IN_NORMAL = 0, 65 | IN_NORMAL2 = 1, 66 | IN_WINDOWS = 2, 67 | IN_DX = 3, 68 | }; 69 | //define Image byte format 70 | constexpr int IBF_R8G8B8A8 = 0; 71 | constexpr int IBF_B8G8R8A8 = 1; 72 | constexpr int IBF_R8G8B8 = 2; 73 | 74 | //const size_t MAX_IMAGE_WIDTH = 1<<11; 75 | //const size_t SHARED_MEMORY_SIZE = 1080 * 1928 * 4; 76 | 77 | constexpr auto SHARED_RES_NAME_FORMAT = L"op_mutex_%d"; 78 | constexpr auto MUTEX_NAME_FORMAT = L"op_shared_mem_%d"; 79 | 80 | extern long KEYPAD_NORMAL_DELAY; 81 | extern long KEYPAD_NORMAL2_DELAY; 82 | extern long KEYPAD_WINDOWS_DELAY; 83 | extern long KEYPAD_DX_DELAY; 84 | 85 | extern long MOUSE_NORMAL_DELAY; 86 | extern long MOUSE_WINDOWS_DELAY; 87 | extern long MOUSE_DX_DELAY; 88 | 89 | #ifndef _M_X64 90 | #define OP64 0 91 | #else 92 | #define OP64 1 93 | #endif 94 | 95 | #define _TOSTRING(x) #x 96 | 97 | #define MAKE_OP_VERSION(a, b, c, d) _TOSTRING(a##.##b##.##c##.##d) 98 | 99 | #define OP_VERSION MAKE_OP_VERSION(0, 4, 2, 0) 100 | //模块句柄 101 | //extern HINSTANCE gInstance; 102 | //是否显示错误信息 103 | //extern int gShowError; 104 | //op 路径 105 | //extern wstring m_opPath; 106 | 107 | //extern wstring g_op_name; 108 | 109 | #endif -------------------------------------------------------------------------------- /libop/core/helpfunc.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "helpfunc.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "globalVar.h" 9 | #include "opEnv.h" 10 | //#define USE_BOOST_STACK_TRACE 11 | #ifdef USE_BOOST_STACK_TRACE 12 | #include 13 | #endif 14 | 15 | std::wstring _s2wstring(const std::string&s) { 16 | size_t nlen = s.length(); 17 | 18 | wchar_t* m_char; 19 | int len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), nlen, NULL, 0); 20 | m_char = new wchar_t[len + 1]; 21 | MultiByteToWideChar(CP_ACP, 0, s.data(), nlen, m_char, len); 22 | m_char[len] = '\0'; 23 | std::wstring ws(m_char); 24 | delete[] m_char; 25 | return ws; 26 | } 27 | 28 | std::string _ws2string(const std::wstring&ws) { 29 | // std::string strLocale = setlocale(LC_ALL, ""); 30 | // const wchar_t* wchSrc = ws.c_str(); 31 | // size_t nDestSize = wcstombs(NULL, wchSrc, 0) + 1; 32 | // char *chDest = new char[nDestSize]; 33 | // memset(chDest, 0, nDestSize); 34 | // wcstombs(chDest, wchSrc, nDestSize); 35 | // std::string strResult = chDest; 36 | // delete[]chDest; 37 | // setlocale(LC_ALL, strLocale.c_str()); 38 | //return strResult; 39 | int nlen = ws.length(); 40 | 41 | char* m_char; 42 | int len = WideCharToMultiByte(CP_ACP, 0, ws.data(), nlen, NULL, 0, NULL, NULL); 43 | m_char = new char[len + 1]; 44 | WideCharToMultiByte(CP_ACP, 0, ws.data(), nlen, m_char, len, NULL, NULL); 45 | m_char[len] = '\0'; 46 | std::string s(m_char); 47 | delete[] m_char; 48 | return s; 49 | } 50 | 51 | string utf8_to_ansi(string strUTF8) { 52 | UINT nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, NULL, NULL); 53 | WCHAR* wszBuffer = new WCHAR[nLen + 1]; 54 | nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, wszBuffer, nLen); 55 | wszBuffer[nLen] = 0; 56 | nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL); 57 | CHAR* szBuffer = new CHAR[nLen + 1]; 58 | nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL); 59 | szBuffer[nLen] = 0; 60 | strUTF8 = szBuffer; 61 | delete[]szBuffer; 62 | delete[]wszBuffer; 63 | return strUTF8; 64 | } 65 | 66 | long Path2GlobalPath(const std::wstring&file, const std::wstring& curr_path, std::wstring& out) { 67 | if (::PathFileExistsW(file.c_str())) { 68 | out = file; 69 | return 1; 70 | } 71 | out.clear(); 72 | out = curr_path + L"\\" + file; 73 | if (::PathFileExistsW(out.c_str())) { 74 | return 1; 75 | } 76 | return 0; 77 | } 78 | 79 | long setlog(const wchar_t* format, ...) { 80 | va_list args; 81 | wchar_t buf[512]; 82 | va_start(args, format); 83 | vswprintf(buf, format, args); 84 | va_end(args); 85 | wstring tmpw = buf; 86 | string tmps = _ws2string(tmpw); 87 | 88 | return setlog(tmps.data()); 89 | } 90 | 91 | long setlog(const char* format, ...) { 92 | std::stringstream ss(std::wstringstream::in | std::wstringstream::out); 93 | va_list args; 94 | char buf[512]; 95 | SYSTEMTIME sys; 96 | GetLocalTime(&sys); 97 | char tm[128]; 98 | sprintf(tm, "[%4d/%02d/%02d %02d:%02d:%02d.%03d]", 99 | sys.wYear, sys.wMonth, sys.wDay, 100 | sys.wHour, sys.wMinute, sys.wSecond, 101 | sys.wMilliseconds); 102 | va_start(args, format); 103 | vsprintf(buf, format, args); 104 | va_end(args); 105 | ss << tm << (OP64 == 1 ? "x64" : "x32") << "info: " << buf << std::endl; 106 | #ifdef USE_BOOST_STACK_TRACE 107 | ss << "\n" 108 | << boost::stacktrace::stacktrace() << std::endl; 109 | #endif // USE_BOOST_STACK_TRACE 110 | 111 | 112 | string s = ss.str(); 113 | if (opEnv::m_showErrorMsg == 1) { 114 | MessageBoxA(NULL, s.data(), "error", MB_ICONERROR); 115 | } 116 | else if (opEnv::m_showErrorMsg == 2) { 117 | /* wchar_t dll_path[MAX_PATH]; 118 | ::GetModuleFileNameW(gInstance, dll_path, MAX_PATH); 119 | wstring fname = dll_path; 120 | fname = fname.substr(0, fname.rfind(L'\\')); 121 | fname += L"\\op.log";*/ 122 | std::fstream file; 123 | file.open("__op.log", std::ios::app | std::ios::out); 124 | if (!file.is_open()) 125 | return 0; 126 | file << s << std::endl; 127 | file.close(); 128 | } 129 | else if (opEnv::m_showErrorMsg == 3) { 130 | std::cout << s << std::endl; 131 | } 132 | 133 | return 1; 134 | } 135 | 136 | void split(const std::wstring& s, std::vector& v, const std::wstring& c) 137 | { 138 | std::wstring::size_type pos1, pos2; 139 | size_t len = s.length(); 140 | pos2 = s.find(c); 141 | pos1 = 0; 142 | v.clear(); 143 | while (std::wstring::npos != pos2) 144 | { 145 | v.emplace_back(s.substr(pos1, pos2 - pos1)); 146 | 147 | pos1 = pos2 + c.size(); 148 | pos2 = s.find(c, pos1); 149 | } 150 | if (pos1 != len) 151 | v.emplace_back(s.substr(pos1)); 152 | } 153 | 154 | void split(const std::string& s, std::vector& v, const std::string& c) 155 | { 156 | std::string::size_type pos1, pos2; 157 | size_t len = s.length(); 158 | pos2 = s.find(c); 159 | pos1 = 0; 160 | v.clear(); 161 | while (std::string::npos != pos2) 162 | { 163 | v.emplace_back(s.substr(pos1, pos2 - pos1)); 164 | 165 | pos1 = pos2 + c.size(); 166 | pos2 = s.find(c, pos1); 167 | } 168 | if (pos1 != len) 169 | v.emplace_back(s.substr(pos1)); 170 | } 171 | 172 | void wstring2upper(std::wstring& s) { 173 | std::transform(s.begin(), s.end(),s.begin(), towupper); 174 | } 175 | 176 | void string2upper(std::string& s) { 177 | std::transform(s.begin(), s.end(), s.begin(), toupper); 178 | } 179 | 180 | void wstring2lower(std::wstring& s) { 181 | std::transform(s.begin(), s.end(), s.begin(), towlower); 182 | } 183 | 184 | void string2lower(std::string& s) { 185 | std::transform(s.begin(), s.end(), s.begin(), tolower); 186 | } 187 | 188 | void replacea(string& str, const string&oldval, const string& newval) { 189 | size_t x0 = 0, dx = newval.length() - oldval.length() + 1; 190 | size_t idx = str.find(oldval, x0); 191 | while (idx != -1 && x0 >= 0) { 192 | str.replace(idx, oldval.length(), newval); 193 | x0 = idx + dx; 194 | idx = str.find(oldval, x0); 195 | } 196 | } 197 | 198 | void replacew(wstring& str, const wstring&oldval, const wstring& newval) { 199 | size_t x0 = 0, dx = newval.length() - oldval.length() + 1; 200 | size_t idx = str.find(oldval, x0); 201 | while (idx != -1 && x0 >= 0) { 202 | str.replace(idx, oldval.length(), newval); 203 | x0 = idx + dx; 204 | idx = str.find(oldval, x0); 205 | } 206 | } 207 | 208 | std::ostream& operator<<(std::ostream& o, point_t const& rhs) { 209 | o << rhs.x << "," << rhs.y; 210 | return o; 211 | } 212 | 213 | std::wostream& operator<<(std::wostream& o, point_t const& rhs) { 214 | o << rhs.x << L"," << rhs.y; 215 | return o; 216 | } 217 | 218 | std::ostream& operator<<(std::ostream& o, FrameInfo const& rhs) { 219 | o << "hwnd:" << rhs.hwnd << std::endl 220 | << "frameId:" << rhs.frameId << std::endl 221 | << "time:" << rhs.time << std::endl 222 | << "height" << rhs.height << std::endl 223 | << "width:" << rhs.width << std::endl; 224 | return o; 225 | } 226 | std::wostream& operator<<(std::wostream& o, FrameInfo const& rhs) { 227 | o << L"hwnd:" << rhs.hwnd << std::endl 228 | << L"frameId:" << rhs.frameId << std::endl 229 | << L"time:" << rhs.time << std::endl 230 | << L"height" << rhs.height << std::endl 231 | << L"width:" << rhs.width << std::endl; 232 | return o; 233 | } 234 | 235 | //Returns the last Win32 error, in string format. Returns an empty string if there is no error. 236 | std::string GetLastErrorAsString() 237 | { 238 | //Get the error message ID, if any. 239 | DWORD errorMessageID = ::GetLastError(); 240 | if (errorMessageID == 0) { 241 | return std::string(); //No error message has been recorded 242 | } 243 | 244 | LPSTR messageBuffer = nullptr; 245 | 246 | //Ask Win32 to give us the string version of that message ID. 247 | //The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be). 248 | size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 249 | NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); 250 | 251 | //Copy the error message into a std::string. 252 | std::string message(messageBuffer, size); 253 | 254 | //Free the Win32's string's buffer. 255 | LocalFree(messageBuffer); 256 | 257 | return message; 258 | } 259 | 260 | bool Delay(long mis) 261 | { 262 | MSG msg = {}; 263 | auto deadline = ::GetTickCount64() + mis; 264 | while (::GetTickCount64() < deadline) 265 | { 266 | // 除收到'WM_QUIT'消息,结果始终都是大于0的 267 | if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0) 268 | { 269 | TranslateMessage(&msg); 270 | DispatchMessage(&msg); 271 | } 272 | } 273 | return true; 274 | } 275 | 276 | bool Delays(long mis_min, long mis_max) 277 | { 278 | if (mis_min <= 0 || mis_max <= 0) 279 | return false; 280 | long mis = mis_min + rand() % mis_max; 281 | return Delay(mis); 282 | } 283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /libop/core/helpfunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __HELPFUCN_H_ 3 | #define __HELPFUNC_H_ 4 | #include "optype.h" 5 | #include "../background/display/frameInfo.h" 6 | std::wstring _s2wstring(const std::string&s); 7 | std::string _ws2string(const std::wstring&s); 8 | 9 | string utf8_to_ansi(string strUTF8); 10 | //将路径转化为全局路径 11 | long Path2GlobalPath(const std::wstring&file, const std::wstring& curr_path, std::wstring& out); 12 | 13 | void split(const std::wstring& s, std::vector& v, const std::wstring& c); 14 | void split(const std::string& s, std::vector& v, const std::string& c); 15 | 16 | void wstring2upper(std::wstring& s); 17 | void string2upper(std::string& s); 18 | 19 | void wstring2lower(std::wstring& s); 20 | void string2lower(std::string& s); 21 | 22 | void replacea(string& str, const string&oldval, const string& newval); 23 | void replacew(wstring& str, const wstring&oldval, const wstring& newval); 24 | 25 | 26 | //for debug 27 | long setlog(const wchar_t* format, ...); 28 | // 29 | long setlog(const char* format, ...); 30 | 31 | 32 | //Returns the last Win32 error, in string format. Returns an empty string if there is no error. 33 | std::string GetLastErrorAsString(); 34 | 35 | int inline hex2bin(int c) { 36 | return c <= L'9' ? c - L'0' : c - L'A' + 10; 37 | }; 38 | 39 | int inline bin2hex(int c) { 40 | int ans = 0; 41 | int c1 = c >> 4 & 0xf; 42 | int c2 = c & 0xf; 43 | ans |= (c1 <= 9 ? c1 + L'0' : c1 + 'A' - 10) << 8; 44 | ans |= c2 <= 9 ? c2 + L'0' : c2 + 'A' - 10; 45 | return ans; 46 | }; 47 | 48 | constexpr int PTY(uint pt) { 49 | return pt >> 16; 50 | } 51 | 52 | constexpr int PTX(uint pt) { 53 | return pt & 0xffff; 54 | } 55 | 56 | template 57 | void nextVal(const T& t, int* next) { 58 | next[0] = -1; 59 | int k = -1, j = 0; 60 | while (j < (int)t.size()-1) { 61 | if (k == -1 || t[k] == t[j]) { 62 | k++; 63 | j++; 64 | next[j] = k; 65 | } 66 | else { 67 | k = next[k]; 68 | } 69 | } 70 | } 71 | template 72 | int kmp(const T& s, const T& t) { 73 | vector next(t.size()); 74 | nextVal(t, next.data()); 75 | int i = 0, j = 0; 76 | while (i < (int)s.size() && j < (int)t.size()) { 77 | if (j == -1 || s[i] == t[j]) { 78 | i++; 79 | j++; 80 | } 81 | else { 82 | j = next[j]; 83 | } 84 | } 85 | return j == s.size() ? i - j : -1; 86 | } 87 | 88 | std::ostream& operator<<(std::ostream& o, point_t const& rhs); 89 | std::wostream& operator<<(std::wostream& o, point_t const& rhs); 90 | 91 | std::ostream& operator<<(std::ostream& o, FrameInfo const& rhs); 92 | std::wostream& operator<<(std::wostream& o, FrameInfo const& rhs); 93 | 94 | bool Delay(long mis); 95 | bool Delays(long mis_min, long mis_max); 96 | 97 | #endif // !__TOOL_H_ 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /libop/core/opEnv.cpp: -------------------------------------------------------------------------------- 1 | #include "opEnv.h" 2 | #include 3 | void* opEnv::m_instance = nullptr; 4 | std::wstring opEnv::m_basePath; 5 | std::wstring opEnv::m_opName; 6 | int opEnv::m_showErrorMsg = 1; 7 | void opEnv::setInstance(void *instance) 8 | { 9 | m_instance = instance; 10 | wchar_t buff[512]={}; 11 | ::GetModuleFileNameW(static_cast(m_instance),buff,512); 12 | std::wstring s(buff); 13 | size_t index =s.rfind(L"\\"); 14 | if(index!=s.npos){ 15 | m_basePath = s.substr(0,index); 16 | m_opName = s.substr(index + 1); 17 | } 18 | } 19 | void *opEnv::getInstance() 20 | { 21 | return m_instance; 22 | } 23 | 24 | std::wstring opEnv::getBasePath(){ 25 | 26 | return m_basePath; 27 | } 28 | 29 | std::wstring opEnv::getOpName(){ 30 | return m_opName; 31 | } -------------------------------------------------------------------------------- /libop/core/opEnv.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPENV_H_ 2 | #define __OPENV_H_ 3 | #include 4 | class opEnv 5 | { 6 | public: 7 | static void setInstance(void *instance); 8 | static void *getInstance(); 9 | static std::wstring getBasePath(); 10 | static std::wstring getOpName(); 11 | static int m_showErrorMsg; 12 | private: 13 | static void *m_instance; 14 | static std::wstring m_basePath; 15 | static std::wstring m_opName; 16 | 17 | }; 18 | #endif -------------------------------------------------------------------------------- /libop/core/optype.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __optype_h_ 3 | #define __optype_h_ 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | using uint = unsigned int; 11 | using uchar = unsigned char; 12 | 13 | using std::map; 14 | using std::string; 15 | using std::vector; 16 | using std::wstring; 17 | 18 | using bytearray = std::vector; 19 | 20 | struct point_t { 21 | int x, y; 22 | point_t() : x(0), y(0) {} 23 | point_t(int x_, int y_) : x(x_), y(y_) {} 24 | bool operator<(const point_t& rhs) const { 25 | if (std::abs(y - rhs.y) < 9) 26 | return x < rhs.x; 27 | else 28 | return y < rhs.y; 29 | } 30 | bool operator==(const point_t& rhs) const { return x == rhs.x && y == rhs.y; } 31 | }; 32 | 33 | using vpoint_t = std::vector; 34 | //(5,3) --> (2, 2, 1) 35 | class NumberGen { 36 | int _q, _r; 37 | 38 | public: 39 | NumberGen(int n, int cnt) : _q(n / cnt), _r(n % cnt) {} 40 | int operator[](int idx) const { return idx < _r ? _q + 1 : _q; } 41 | }; 42 | 43 | struct rect_t { 44 | rect_t() : x1(0), y1(0), x2(0), y2(0) {} 45 | rect_t(int x1_, int y1_, int x2_, int y2_) 46 | : x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} 47 | int x1, y1; 48 | int x2, y2; 49 | int width() const { return x2 - x1; } 50 | int height() const { return y2 - y1; } 51 | int area() const { return width() * height(); } 52 | rect_t& shrinkRect(int w, int h) { 53 | x2 -= w; 54 | y2 -= h; 55 | x2 += 1; 56 | y2 += 1; 57 | return *this; 58 | } 59 | bool valid() const { return 0 <= x1 && x1 < x2 && 0 <= y1 && y1 < y2; } 60 | 61 | void divideBlock(int count, bool vertical, std::vector& blocks) { 62 | assert(valid()); 63 | 64 | assert(count > 0); 65 | blocks.resize(count); 66 | if (vertical) { 67 | NumberGen gen(height(), count); 68 | int basey = y1; 69 | for (int i = 0; i < count; ++i) { 70 | blocks[i] = rect_t(x1, basey, x2, basey + gen[i]); 71 | basey += gen[i]; 72 | } 73 | 74 | } else { 75 | NumberGen gen(width(), count); 76 | int basex = x1; 77 | for (int i = 0; i < count; ++i) { 78 | blocks[i] = rect_t(basex, y1, basex + gen[i], y2); 79 | basex += gen[i]; 80 | } 81 | } 82 | assert(blocks.back().x2 == x2); 83 | assert(blocks.back().y2 == y2); 84 | } 85 | }; 86 | 87 | using vrect_t = std::vector; 88 | 89 | struct point_desc_t { 90 | int id; 91 | point_t pos; 92 | }; 93 | 94 | using vpoint_desc_t = std::vector; 95 | // ocr result 96 | struct ocr_rec_t { 97 | // BBox of the text 98 | point_t left_top; 99 | point_t right_bottom; 100 | // content of the text 101 | wstring text; 102 | // confidence of the text 103 | float confidence; 104 | }; 105 | 106 | using vocr_rec_t = std::vector; 107 | 108 | 109 | #endif -------------------------------------------------------------------------------- /libop/imageProc/ImageLoc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __IMAGELOC_H_ 3 | #define __IMAGELOC_H_ 4 | /* 5 | 常见的图像算法,例如图像查找,颜色序列匹配(多点着色) 6 | 由于ocr与图像查找类似,故也在类ImageLoc中实现 7 | */ 8 | #include 9 | #include "../core/optype.h" 10 | #include 11 | #include "../include/Dict.h" 12 | #include "../include/color.h" 13 | #include "./compute/ThreadPool.h" 14 | 15 | inline int HEX2INT(wchar_t c) { 16 | if (L'0' <= c && c <= L'9') 17 | return c - L'0'; 18 | if (L'A' <= c && c <= L'Z') 19 | return c - L'A' + 10; 20 | if (L'a' <= c && c <= L'z') 21 | return c - L'a' + 10; 22 | return 0; 23 | } 24 | 25 | 26 | #define SET_BIT(x, idx) (x |= 1u << (idx)) 27 | 28 | #define GET_BIT(x, idx) ((x >> (idx)) & 1u) 29 | 30 | using img_names = std::vector; 31 | //检查是否为透明图 32 | int check_transparent(Image* img); 33 | //获取匹配点 34 | void get_match_points(const Image& img, vector&points); 35 | //generate next index for kmp 36 | void gen_next(const Image& img, vector& next); 37 | //sum of all pixels 38 | int inline sum(uchar* begin, uchar* end) { 39 | int s = 0; 40 | while (begin != end) 41 | s += *begin++; 42 | return s; 43 | } 44 | 45 | void extractConnectivity(const ImageBin& src, int threshold, std::vector& out); 46 | 47 | 48 | struct gray_diff_t{ 49 | gray_diff_t(color_df_t const& cd):gray(cd.color.toGray()),diff(cd.df.toGray()){ 50 | 51 | } 52 | unsigned char gray; 53 | unsigned char diff; 54 | }; 55 | 56 | 57 | /* 58 | 此类用于实现一些图像功能,如图像定位,简单ocr等 59 | */ 60 | class ImageBase 61 | { 62 | public: 63 | 64 | const static int _max_return_obj_ct = 1800; 65 | 66 | using vcolor_diff_t = vector;//rgb color-diff 67 | using vgray_diff_t =vector;//gray 68 | 69 | ImageBase(); 70 | 71 | ~ImageBase(); 72 | 73 | //brief:输入图像,建立图形矩阵,在图像操作前调用 74 | //image_data: 4子节对齐的像素指针 75 | //widht: 图像宽度 76 | //hegith: h 77 | //x1,y1,x2,y2 拷贝区域 78 | //type: 输入类型,type=0表示正常输入,为-1时表示倒置输入 79 | //long input_image(byte* psrc, int cols, int height,long x1,long y1,long x2,long y2, int type = 0); 80 | 81 | void set_offset(int x1, int y1); 82 | 83 | long is_valid(long x, long y) { 84 | return x >= 0 && y >= 0 && x < _src.width && y < _src.height; 85 | } 86 | 87 | long GetPixel(long x, long y, color_t&cr); 88 | 89 | long CmpColor(color_t color, std::vector&colors, double sim); 90 | 91 | long FindColor(std::vector&colors,int dir, long&x, long&y); 92 | 93 | long FindColorEx(std::vector&colors, std::wstring& retstr); 94 | 95 | long FindMultiColor(std::vector&first_color, std::vector& offset_color, double sim, long dir, long&x, long&y); 96 | 97 | long FindMultiColorEx(std::vector&first_color, std::vector& offset_color, double sim, long dir, std::wstring& retstr); 98 | 99 | long FindPic(std::vector&pics,color_t dfcolor,double sim, long dir, long&x, long&y); 100 | 101 | long FindPicTh(std::vector&pics,color_t dfcolor,double sim, long dir, long&x, long&y); 102 | 103 | long FindPicEx(std::vector& pics, color_t dfcolor, double sim, long dir, vpoint_desc_t& vpd); 104 | 105 | long FindPicExTh(std::vector& pics, color_t dfcolor, double sim, long dir, vpoint_desc_t& vpd); 106 | 107 | long FindColorBlock(double sim, long count, long height, long width, long& x, long& y); 108 | 109 | long FindColorBlockEx(double sim, long count, long height, long width, std::wstring& retstr); 110 | 111 | long Ocr(Dict& dict, double sim, std::wstring& ret_str); 112 | 113 | long OcrEx(Dict& dict, double sim, std::wstring& out_str); 114 | 115 | long FindStr(std::map& ps, const vector& vstr, double sim, long& retx, long& rety); 116 | 117 | long FindStrEx(std::map& ps, const vector& vstr, double sim, std::wstring& out_str); 118 | //描述:查找目标图像中的直线 119 | //输入:精度 120 | //输出:outStr:直线描述[法线角度,直线到原点的距离];ret:该直线上的点的数量 121 | long FindLine(double sim, std::wstring& outStr); 122 | private: 123 | //rgb像素匹配 124 | template 125 | long simple_match(long x, long y, Image* timg, color_t dfcolor,int tnrom, double sim); 126 | //透明图匹配 127 | template 128 | long trans_match(long x, long y, Image* timg, color_t dfcolor, vectorpoints, int max_error); 129 | //灰度匹配 130 | long real_match(long x, long y, ImageBin* timg, int tnorm, double sim); 131 | //记录和 132 | void record_sum(const ImageBin & gray); 133 | //[x1,x2),[y1,y2) 134 | int region_sum(int x1, int y1, int x2, int y2); 135 | 136 | 137 | 138 | int get_bk_color(inputbin bin); 139 | 140 | 141 | 142 | //垂直方向投影,投到x轴 143 | void binshadowx(const rect_t& rc, std::vector& out_put); 144 | //水平方向投影,投到(y)轴 145 | void binshadowy(const rect_t& rc, std::vector&out_put); 146 | 147 | 148 | 149 | //ocr 完全匹配模式 150 | void _bin_ocr(const Dict& dict, std::map&ps); 151 | //ocr 模糊匹配模式 152 | void _bin_ocr(const Dict& dict,double sim, std::map&ps); 153 | 154 | public: 155 | /* 156 | if(abs(cr-src)<=df) pixel=1; 157 | else pixel=0; 158 | */ 159 | void bgr2binary(vector& colors); 160 | //二值化 auto 161 | void bgr2binarybk(const vector& bk_colors); 162 | //图像裁剪 163 | void bin_image_cut(int min_word_h, const rect_t& inrc, rect_t& outrc); 164 | void get_rois(int min_word_h, std::vector& vroi); 165 | //ocr识别,返回识别到的字及对应坐标 166 | 167 | void bin_ocr(const Dict& dict, double sim, std::map&ps); 168 | 169 | 170 | public: 171 | Image _src; 172 | ImageBin _gray; 173 | ImageBin _record; 174 | ImageBin _binary; 175 | Image _sum; 176 | //起始点 177 | int _x1, _y1; 178 | //偏移 179 | int _dx, _dy; 180 | private: 181 | 182 | ThreadPool m_threadPool; 183 | }; 184 | 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /libop/imageProc/ImageProc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "ImageLoc.h" 4 | #include 5 | //#include "tess_ocr.h" 6 | 7 | using std::wstring; 8 | /* 9 | 此类为图像处理,包含以下工作 10 | 1.像素比较,查找 11 | 2.颜色转化 12 | 3.图像定位 13 | 4.简单OCR 14 | 5.... 15 | */ 16 | class ImageProc:public ImageBase 17 | { 18 | public: 19 | const static int _max_dict = 10; 20 | 21 | ImageProc(); 22 | ~ImageProc(); 23 | // 24 | long Capture(const std::wstring& file); 25 | 26 | long CmpColor(long x, long y, const std::wstring& scolor, double sim); 27 | 28 | long FindColor(const wstring& color,double sim,long dir, long&x, long&y); 29 | 30 | long FindColoEx(const wstring& color, double sim, long dir, wstring& retstr); 31 | 32 | long FindMultiColor(const wstring& first_color,const wstring& offset_color, double sim, long dir, long&x, long&y); 33 | 34 | long FindMultiColorEx(const wstring& first_color, const wstring& offset_color, double sim, long dir, wstring& retstr); 35 | //图形定位 36 | long FindPic(const std::wstring& files,const wstring& delta_colors, double sim,long dir, long& x, long &y); 37 | // 38 | long FindPicEx(const std::wstring& files, const wstring& delta_colors, double sim, long dir, wstring& retstr, bool returnID = true); 39 | 40 | long FindColorBlock(const wstring& color, double sim, long count, long height, long width, long& x, long& y); 41 | 42 | long FindColorBlockEx(const wstring& color, double sim, long count, long height, long width, wstring& retstr); 43 | 44 | std::wstring GetColor(long x, long y); 45 | 46 | long SetMemDict(int idx, void* data,long size); 47 | 48 | long SetDict(int idx,const wstring& file); 49 | 50 | long UseDict(int idx); 51 | 52 | long OCR(const wstring& color, double sim, std::wstring& out_str); 53 | 54 | long OcrEx(const wstring& color, double sim, std::wstring& out_str); 55 | 56 | long FindStr(const wstring& str, const wstring& color, double sim, long& retx,long& rety); 57 | 58 | long FindStrEx(const wstring& str, const wstring& color, double sim, std::wstring& out_str); 59 | 60 | long OcrAuto(double sim, std::wstring& retstr); 61 | 62 | long OcrFromFile(const wstring& files,const wstring& color, double sim, std::wstring& retstr); 63 | 64 | long OcrAutoFromFile(const wstring& files, double sim, std::wstring& retstr); 65 | 66 | long FindLine(const wstring& color, double sim, wstring& retStr); 67 | 68 | long LoadPic(const wstring& files); 69 | 70 | long FreePic(const wstring& files); 71 | 72 | long LoadMemPic(const wstring& file_name, void* data, long size); 73 | private: 74 | //字库 75 | Dict _dicts[_max_dict]; 76 | //当前字库索引 77 | int _curr_idx; 78 | 79 | public: 80 | //当前目录 81 | wstring _curr_path; 82 | //图片缓存 83 | std::map _pic_cache; 84 | //是否使用图片缓存,默认开启 85 | int _enable_cache; 86 | 87 | private: 88 | //RETURN TYPE 0:word colors info; 1:bk color info 89 | int str2colordfs(const wstring& color_str, std::vector& colors); 90 | void str2colors(const wstring& color, std::vector& vcolor); 91 | void files2mats(const wstring& files, std::vector& vpic, std::vector& vstr); 92 | }; 93 | 94 | -------------------------------------------------------------------------------- /libop/imageProc/OcrWrapper.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/imageProc/OcrWrapper.cpp -------------------------------------------------------------------------------- /libop/imageProc/OcrWrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../core/optype.h" 3 | #include 4 | #define ocr_engine_ok 0 5 | #define ocr_engine_err 1 6 | struct ocr_engine; 7 | struct ocr_engine_ocr_result { 8 | int x1, y1, x2, y2; 9 | char* text; 10 | float confidence; 11 | }; 12 | 13 | typedef int(_stdcall* ocr_engine_init_t)(ocr_engine** obj, char* argv[], int argc); 14 | 15 | typedef int(_stdcall* ocr_engine_ocr_t)(ocr_engine* pocr, void* image, int w, int h, int bpp, ocr_engine_ocr_result** ppresult, int* num_of_result); 16 | 17 | typedef int(_stdcall* ocr_engine_release_t)(ocr_engine* obj); 18 | 19 | class OcrWrapper { 20 | private: 21 | OcrWrapper(); 22 | public: 23 | OcrWrapper(const OcrWrapper&) = delete; 24 | OcrWrapper operator=(const OcrWrapper&) = delete; 25 | static OcrWrapper* getInstance(); 26 | ~OcrWrapper(); 27 | int init(const std::wstring& enginePath, const std::wstring& dllName, const vector& argv); 28 | int release(); 29 | int ocr(byte* data, int w, int h, int bpp, vocr_rec_t& result); 30 | private: 31 | static ocr_engine_init_t ocr_engine_init; 32 | static ocr_engine_ocr_t ocr_engine_ocr; 33 | static ocr_engine_release_t ocr_engine_release; 34 | std::mutex m_mutex; 35 | ocr_engine* m_engine; 36 | }; -------------------------------------------------------------------------------- /libop/imageProc/compute/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadPool.h" 2 | 3 | // the destructor joins all threads 4 | ThreadPool::~ThreadPool() { 5 | { 6 | std::unique_lock lock(queue_mutex); 7 | stop = true; 8 | } 9 | condition.notify_all(); 10 | for (std::thread& worker : workers) { 11 | worker.join(); 12 | } 13 | } -------------------------------------------------------------------------------- /libop/imageProc/compute/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef THREAD_POOL_H 2 | #define THREAD_POOL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class ThreadPool { 15 | public: 16 | ThreadPool(size_t); 17 | template 18 | auto enqueue(F&& f, Args&&... args) 19 | -> std::future::type>; 20 | ~ThreadPool(); 21 | size_t getThreadNum()const{ 22 | return workers.size(); 23 | } 24 | private: 25 | // need to keep track of threads so we can join them 26 | std::vector< std::thread > workers; 27 | // the task queue 28 | std::queue< std::function > tasks; 29 | 30 | // synchronization 31 | std::mutex queue_mutex; 32 | std::condition_variable condition; 33 | bool stop; 34 | }; 35 | 36 | // the constructor just launches some amount of workers 37 | inline ThreadPool::ThreadPool(size_t threads) 38 | : stop(false) 39 | { 40 | for(size_t i = 0;i task; 47 | 48 | { 49 | std::unique_lock lock(this->queue_mutex); 50 | this->condition.wait(lock, 51 | [this]{ return this->stop || !this->tasks.empty(); }); 52 | if(this->stop && this->tasks.empty()) 53 | return; 54 | task = std::move(this->tasks.front()); 55 | this->tasks.pop(); 56 | } 57 | 58 | task(); 59 | } 60 | } 61 | ); 62 | } 63 | 64 | // add new work item to the pool 65 | template 66 | auto ThreadPool::enqueue(F&& f, Args&&... args) 67 | -> std::future::type> 68 | { 69 | using return_type = typename std::result_of::type; 70 | 71 | auto task = std::make_shared< std::packaged_task >( 72 | std::bind(std::forward(f), std::forward(args)...) 73 | ); 74 | 75 | std::future res = task->get_future(); 76 | { 77 | std::unique_lock lock(queue_mutex); 78 | 79 | // don't allow enqueueing after stopping the pool 80 | if(stop) 81 | throw std::runtime_error("enqueue on stopped ThreadPool"); 82 | 83 | tasks.emplace([task](){ (*task)(); }); 84 | } 85 | condition.notify_one(); 86 | return res; 87 | } 88 | 89 | // the destructor joins all threads 90 | inline ThreadPool::~ThreadPool() 91 | { 92 | { 93 | std::unique_lock lock(queue_mutex); 94 | stop = true; 95 | } 96 | condition.notify_all(); 97 | for(std::thread &worker: workers) 98 | worker.join(); 99 | } 100 | #endif -------------------------------------------------------------------------------- /libop/imageProc/imageView.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __IMAGE_VIEW_H 2 | #define __IMAGE_VIEW_H 3 | #include "../core/optype.h" 4 | #include "../include/Image.hpp" 5 | class imageView { 6 | private: 7 | 8 | 9 | public: 10 | imageView(ImageBin const& src, rect_t const& block); 11 | imageView(imageView const&) = delete; 12 | ~imageView(); 13 | 14 | /* data */ 15 | const ImageBin& _src; 16 | rect_t _block; 17 | }; 18 | 19 | imageView::imageView(ImageBin const& src, rect_t const& block) 20 | : _src(src), _block(block) {} 21 | 22 | imageView::~imageView() {} 23 | 24 | #endif -------------------------------------------------------------------------------- /libop/imageProc/tess_ocr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/libop/imageProc/tess_ocr.cpp -------------------------------------------------------------------------------- /libop/imageProc/tess_ocr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../core/optype.h" 3 | namespace tesseract { 4 | class TessBaseAPI; 5 | }; 6 | 7 | class tess_ocr { 8 | public: 9 | tess_ocr(); 10 | ~tess_ocr(); 11 | int init(); 12 | int release(); 13 | int ocr(byte* data, int w, int h, int bpp, vocr_rec_t& result); 14 | private: 15 | tesseract::TessBaseAPI* m_api; 16 | }; -------------------------------------------------------------------------------- /libop/include/Image.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __IMAGE_H_ 3 | #define __IMAGE_H_ 4 | #include 5 | 6 | #include 7 | struct Image 8 | { 9 | using iterator = unsigned __int32*; 10 | Image() :width(0), height(0), pdata(nullptr) { 11 | } 12 | Image(int w, int h) :pdata(nullptr) { 13 | 14 | create(w, h); 15 | } 16 | //copy ctr 17 | Image(const Image& rhs) :pdata(nullptr) { 18 | 19 | if (rhs.empty()) { 20 | this->clear(); 21 | } 22 | else { 23 | this->create(rhs.width, rhs.height); 24 | memcpy(this->pdata, rhs.pdata, width*height * 4); 25 | } 26 | 27 | } 28 | ~Image() { 29 | release(); 30 | } 31 | 32 | void create(int w, int h) { 33 | width = w, height = h; 34 | if (!pdata) { 35 | pdata = (unsigned char*)malloc(w*h * 4); 36 | } 37 | else { 38 | pdata = (unsigned char*)realloc(pdata, w*h * 4); 39 | } 40 | if (pdata == nullptr)throw("memory not enough"); 41 | } 42 | void release() { 43 | width = height = 0; 44 | if (pdata)free(pdata); 45 | pdata = nullptr; 46 | } 47 | 48 | int size() { 49 | return width * height; 50 | } 51 | void clear() { 52 | width = height = 0; 53 | } 54 | 55 | bool empty()const { 56 | return width == 0; 57 | } 58 | 59 | Image& operator=(const Image& rhs) { 60 | if (rhs.empty()) { 61 | this->clear(); 62 | } 63 | else if (this != &rhs) { 64 | this->create(rhs.width, rhs.height); 65 | memcpy(this->pdata, rhs.pdata, width*height * 4); 66 | } 67 | return *this; 68 | } 69 | bool read(LPCTSTR file) { 70 | clear(); 71 | ATL::CImage img; 72 | HRESULT hr = img.Load(file); 73 | if (hr == S_OK) { 74 | create(img.GetWidth(), img.GetHeight()); 75 | translate((unsigned char*)img.GetBits(), img.GetBPP() / 8, img.GetPitch()); 76 | return true; 77 | } 78 | else { 79 | return false; 80 | } 81 | } 82 | bool read(void* pMemData, long len) { 83 | clear(); 84 | ATL::CImage img; 85 | auto hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, len); 86 | if (hGlobal) 87 | { 88 | void* pData = GlobalLock(hGlobal); 89 | memcpy_s(pData, len, pMemData, len); 90 | GlobalUnlock(hGlobal); 91 | } 92 | else { 93 | return false; 94 | } 95 | 96 | IStream* pStream = NULL; 97 | if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) != S_OK) { 98 | GlobalFree(hGlobal); 99 | return false; 100 | } 101 | HRESULT hr = img.Load(pStream); 102 | if (hr == S_OK) { 103 | pStream->Release(); 104 | GlobalFree(hGlobal); 105 | create(img.GetWidth(), img.GetHeight()); 106 | translate((unsigned char*)img.GetBits(), img.GetBPP() / 8, img.GetPitch()); 107 | return true; 108 | } 109 | else { 110 | GlobalFree(hGlobal); 111 | return false; 112 | } 113 | } 114 | 115 | bool read(ATL::CImage* img) { 116 | translate((unsigned char*)img->GetBits(), img->GetBPP() / 8, img->GetPitch()); 117 | return true; 118 | } 119 | 120 | bool write(LPCTSTR file) { 121 | if (empty()) 122 | return false; 123 | ATL::CImage img; 124 | 125 | img.Create(width, height, 32); 126 | auto pdst = (unsigned char*)img.GetBits(); 127 | auto psrc = pdata; 128 | int pitch = img.GetPitch(); 129 | for (int i = 0; i < height; ++i) { 130 | for (int j = 0; j < width; ++j) { 131 | ((int*)pdst)[j] = ((int*)psrc)[j]; 132 | } 133 | pdst += pitch; 134 | psrc += width * 4; 135 | } 136 | return img.Save(file) == S_OK; 137 | } 138 | void translate(unsigned char* psrc, int pixSize, int pitch) { 139 | auto pdst = pdata; 140 | //gray 141 | if (pixSize == 1) { 142 | for (int i = 0; i < height; ++i) { 143 | for (int j = 0; j < width; ++j) { 144 | *pdst++ = psrc[j]; 145 | *pdst++ = psrc[j]; 146 | *pdst++ = psrc[j]; 147 | *pdst++ = 0xff; 148 | } 149 | psrc += pitch; 150 | 151 | } 152 | }//bgr 153 | else if (pixSize == 3) { 154 | for (int i = 0; i < height; ++i) { 155 | for (int j = 0; j < width; ++j) { 156 | *pdst++ = psrc[j * 3 + 0]; 157 | *pdst++ = psrc[j * 3 + 1]; 158 | *pdst++ = psrc[j * 3 + 2]; 159 | *pdst++ = 0xff; 160 | } 161 | psrc += pitch; 162 | 163 | } 164 | } 165 | else if (pixSize == 4) { 166 | for (int i = 0; i < height; ++i) { 167 | for (int j = 0; j < width; ++j) { 168 | *pdst++ = psrc[j * 4 + 0]; 169 | *pdst++ = psrc[j * 4 + 1]; 170 | *pdst++ = psrc[j * 4 + 2]; 171 | *pdst++ = psrc[j * 4 + 3]; 172 | } 173 | psrc += pitch; 174 | 175 | } 176 | } 177 | } 178 | template 179 | Tp at(int y, int x)const { 180 | return ((Tp*)pdata)[y*width + x]; 181 | } 182 | template 183 | Tp& at(int y, int x) { 184 | return ((Tp*)pdata)[y*width + x]; 185 | } 186 | template 187 | Tp* ptr(int y) { 188 | return (Tp*)(pdata + y * width * 4); 189 | } 190 | 191 | template 192 | const Tp* ptr(int y)const { 193 | return (Tp*)(pdata + y * width * 4); 194 | } 195 | 196 | iterator begin() { 197 | return (iterator)pdata; 198 | } 199 | iterator end() { 200 | return (iterator)pdata + width * height; 201 | } 202 | 203 | iterator begin()const { 204 | return (iterator)pdata; 205 | } 206 | iterator end()const { 207 | return (iterator)pdata + width * height; 208 | } 209 | 210 | void fill(unsigned int val) { 211 | std::fill(begin(), end(), val); 212 | } 213 | void fill(int row,int col,int h,int w,unsigned int val) { 214 | for (int i = 0; i < h; ++i) { 215 | auto p = ptr(row + i)+col; 216 | std::fill(p,p + w,val); 217 | } 218 | } 219 | int width, height; 220 | unsigned char* pdata; 221 | }; 222 | //单通道图像 223 | struct ImageBin { 224 | using iterator = unsigned char*; 225 | ImageBin() :width(0), height(0) {} 226 | ImageBin(const ImageBin& rhs) { 227 | this->width = rhs.width; 228 | this->height = rhs.height; 229 | this->pixels = rhs.pixels; 230 | } 231 | void create(int w, int h) { 232 | width = w, height = h; 233 | pixels.resize(w*h); 234 | } 235 | void clear() { 236 | width = height = 0; 237 | } 238 | int size()const { 239 | return width*height; 240 | } 241 | bool empty()const { 242 | return width == 0; 243 | } 244 | unsigned char* data() { 245 | return pixels.data(); 246 | } 247 | ImageBin& operator=(const ImageBin& rhs) { 248 | this->width = rhs.width; 249 | this->height = rhs.height; 250 | this->pixels = rhs.pixels; 251 | return *this; 252 | } 253 | unsigned char at(int y,int x)const { 254 | return pixels[y*width + x]; 255 | } 256 | unsigned char& at(int y, int x) { 257 | return pixels[y*width + x]; 258 | } 259 | 260 | unsigned char* ptr(int y) { 261 | return pixels.data() + y * width; 262 | } 263 | 264 | unsigned char const* ptr(int y) const{ 265 | return pixels.data() + y * width; 266 | } 267 | 268 | void fromImage4(const Image& img4) { 269 | create(img4.width, img4.height); 270 | auto psrc = img4.pdata; 271 | for (size_t i = 0; i < pixels.size(); ++i) { 272 | //pixels[i] = (psrc[0] + psrc[1] + psrc[2]) / 3; 273 | // Gray = (R*299 + G*587 + B*114 + 500) / 1000 274 | pixels[i] = (psrc[2] * 299 + psrc[1] * 587 + psrc[0] * 114 + 500) / 1000; 275 | psrc += 4; 276 | } 277 | } 278 | 279 | bool write(LPCTSTR file) { 280 | if (empty()) 281 | return false; 282 | ATL::CImage img; 283 | 284 | img.Create(width, height, 32); 285 | auto pdst = (unsigned char*)img.GetBits(); 286 | auto psrc = pixels.data(); 287 | int pitch = img.GetPitch(); 288 | for (int i = 0; i < height; ++i) { 289 | for (int j = 0; j < width; ++j) { 290 | //((int*)pdst)[j] = ((int*)psrc)[j]; 291 | uchar v = psrc[j] == 1 ? 0xff : 0; 292 | pdst[j*4] = pdst[j*4 + 1] = pdst[j*4 + 2] =v; 293 | pdst[j * 4 + 3] = 0xff; 294 | 295 | } 296 | pdst += pitch; 297 | psrc += width; 298 | } 299 | return img.Save(file) == S_OK; 300 | } 301 | 302 | iterator begin() { 303 | return pixels.data(); 304 | } 305 | iterator end() { 306 | return pixels.data() + pixels.size(); 307 | } 308 | int width, height; 309 | std::vector pixels; 310 | }; 311 | 312 | 313 | using inputimg = const Image&; 314 | using outputimg = Image&; 315 | 316 | using inputbin = const ImageBin&; 317 | using outputbin = ImageBin & ; 318 | 319 | #endif -------------------------------------------------------------------------------- /libop/include/bitfunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __BITFUNC_H_ 3 | #define __BITFUNC_H_ 4 | template 5 | constexpr void SET_BIT(T& x,int idx) { 6 | x |= 1u << idx; 7 | } 8 | template 9 | constexpr int GET_BIT(T x, int idx) { 10 | return (x >> idx) & 1u; 11 | } 12 | 13 | template 14 | constexpr int get_bit_count(T x) { 15 | int s = 0; 16 | while (x) { 17 | s += x & 1; 18 | x >>= 1; 19 | } 20 | return s; 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /libop/include/color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __COLOR_H_ 3 | #define __COLOR_H_ 4 | #include 5 | #include "../core/optype.h" 6 | #define WORD_BKCOLOR 0 7 | #define WORD_COLOR 1 8 | //#include "../Tool.h" 9 | #include 10 | #define color2uint(color) (*(uint*)&color) 11 | template 12 | constexpr T OP_ABS(T x) { 13 | return x < 0 ? -x : x; 14 | } 15 | template 16 | constexpr bool IN_RANGE(T lhs, T rhs, T df) { 17 | return OP_ABS(lhs.b-rhs.b)<=df.b 18 | &&OP_ABS(lhs.g-rhs.g)<=df.g 19 | &&OP_ABS(lhs.r-rhs.r)<=df.r; 20 | } 21 | //��ɫ�ṹ 22 | 23 | //#pragma pack(push) 24 | #pragma pack(1) 25 | struct color_t { 26 | //b is in low address ,alpha is in high address 27 | uchar b, g, r, alpha; 28 | color_t() :b(0), g(0), r(0), alpha(0) {} 29 | color_t(int b_, int g_, int r_) :b(b_), g(g_), r(r_),alpha(0xffu) {} 30 | 31 | color_t& str2color(const std::wstring& s) { 32 | int r = 0, g = 0, b = 0; 33 | std::wstring ss = s; 34 | std::transform(ss.begin(), ss.end(), ss.begin(), ::towupper); 35 | int cnt = swscanf(ss.c_str(), L"%02X%02X%02X", &r, &g, &b); 36 | this->b = b; this->r = r; this->g = g; 37 | return *this; 38 | } 39 | color_t& str2color(const std::string&s) { 40 | int r, g, b; 41 | std::string ss = s; 42 | std::transform(ss.begin(), ss.end(), ss.begin(), ::toupper); 43 | int cnt = sscanf(ss.c_str(), "%02X%02X%02X", &r, &g, &b); 44 | this->b = b; this->r = r; this->g = g; 45 | return *this; 46 | } 47 | std::string tostr() { 48 | char buff[10]; 49 | sprintf(buff, "%02X%02X%02X", r, g, b); 50 | return buff; 51 | } 52 | std::wstring towstr() { 53 | wchar_t buff[10]; 54 | wsprintf(buff, L"%02X%02X%02X", r, g, b); 55 | return buff; 56 | } 57 | uchar toGray() const{ 58 | return (r * 299 + g * 587 + b * 114 + 500) / 1000; 59 | } 60 | }; 61 | #pragma pack() 62 | //��ɫ-ƫɫ�ṹ 63 | struct color_df_t { 64 | //��ɫ 65 | color_t color; 66 | //ƫɫ 67 | color_t df; 68 | }; 69 | //����-��ɫ-ƫɫ�ṹ 70 | struct pt_cr_df_t { 71 | int x, y; 72 | std::vector crdfs; 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /libop/include/promutex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using std::wstring; 6 | class promutex 7 | { 8 | public: 9 | explicit promutex():_hmutex(NULL) { 10 | } 11 | ~promutex() { 12 | if (_hmutex) { 13 | unlock(); 14 | ::CloseHandle(_hmutex); 15 | _hmutex = NULL; 16 | } 17 | } 18 | bool open_create(const wstring& name_) { 19 | HANDLE temp; 20 | temp = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, name_.data()); 21 | if (!temp) { 22 | temp = CreateMutexW(NULL, FALSE, name_.data()); 23 | } 24 | if (temp) { 25 | _hmutex = temp; 26 | return true; 27 | } 28 | else { 29 | return false; 30 | } 31 | 32 | } 33 | bool open(const wstring& name_) { 34 | HANDLE temp; 35 | temp = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, name_.data()); 36 | if (temp) { 37 | _hmutex = temp; 38 | return true; 39 | } 40 | return false; 41 | 42 | } 43 | void lock() { 44 | ::WaitForSingleObject(_hmutex, INFINITE); 45 | } 46 | 47 | DWORD try_lock(size_t time_) { 48 | return ::WaitForSingleObject(_hmutex, time_); 49 | } 50 | void unlock() { 51 | assert(_hmutex); 52 | ::ReleaseMutex(_hmutex); 53 | } 54 | protected: 55 | private: 56 | HANDLE _hmutex; 57 | }; 58 | -------------------------------------------------------------------------------- /libop/include/sharedmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using std::wstring; 5 | class sharedmem 6 | { 7 | public: 8 | explicit sharedmem(const wstring& name_,size_t size_):_hmap(nullptr),_paddress(nullptr),_ismaped(0){ 9 | open_create(name_, size_); 10 | 11 | } 12 | sharedmem() :_hmap(nullptr),_paddress(nullptr), _ismaped(0) { 13 | 14 | } 15 | ~sharedmem() { 16 | close(); 17 | } 18 | /*open or create a shared memory*/ 19 | bool open_create(const wstring& name_, size_t size_) { 20 | auto temph = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, name_.data()); 21 | if (!temph) { 22 | temph = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size_, name_.data()); 23 | if (!temph) 24 | return false; 25 | 26 | } 27 | _hmap = temph; 28 | if (!_ismaped) 29 | _paddress = MapViewOfFile(_hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0); 30 | _ismaped = 1; 31 | return true; 32 | 33 | } 34 | /*open only*/ 35 | bool open(const wstring& name_) { 36 | auto temph = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, name_.data()); 37 | if (temph) 38 | _hmap = temph; 39 | else 40 | return false; 41 | if (!_ismaped) 42 | _paddress = MapViewOfFile(_hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0); 43 | _ismaped = 1; 44 | return true; 45 | 46 | } 47 | /*close the shared memory*/ 48 | void close() { 49 | if (_ismaped) 50 | UnmapViewOfFile(_paddress); 51 | if (_hmap) 52 | CloseHandle(_hmap); 53 | _hmap = NULL; 54 | _ismaped = 0; 55 | _paddress = nullptr; 56 | } 57 | template 58 | T& at(int idx_) { 59 | //assert(_hmap&&_paddress); 60 | return (T)_paddress[idx_]; 61 | } 62 | template 63 | T* data() { 64 | return (T*)_paddress; 65 | } 66 | protected: 67 | /*sharedmem operator=(const sharedmem& rhs) { 68 | return rhs; 69 | }*/ 70 | private: 71 | //handle of shared file map 72 | HANDLE _hmap; 73 | //address of shared memory 74 | void* _paddress; 75 | //state of is maped 76 | int _ismaped; 77 | }; -------------------------------------------------------------------------------- /libop/readme.md: -------------------------------------------------------------------------------- 1 | # 文件目录 2 | * core: op插件各个模块依赖的公共数据结构,函数,宏和全局变量等 3 | * background:前台截图,后台(gdi,opengl,dx)截图;鼠标键盘操作 4 | * imageProc:找图,OCR等图像操作功能的实现 5 | * algorithm:op项目实现的一些算法 6 | * com: op插件提供给用户的com接口 7 | -------------------------------------------------------------------------------- /libop/winapi/Injecter.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "Injecter.h" 3 | 4 | 5 | Injecter::Injecter() 6 | { 7 | } 8 | 9 | 10 | Injecter::~Injecter() 11 | { 12 | } 13 | 14 | BOOL Injecter::EnablePrivilege(BOOL enable) 15 | { 16 | // 得到令牌句柄 17 | HANDLE hToken = NULL; 18 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &hToken)) 19 | return FALSE; 20 | 21 | // 得到特权值 22 | LUID luid; 23 | if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) 24 | return FALSE; 25 | 26 | // 提升令牌句柄权限 27 | TOKEN_PRIVILEGES tp = {}; 28 | tp.PrivilegeCount = 1; 29 | tp.Privileges[0].Luid = luid; 30 | tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; 31 | if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) 32 | return FALSE; 33 | 34 | // 关闭令牌句柄 35 | CloseHandle(hToken); 36 | 37 | return TRUE; 38 | } 39 | 40 | 41 | long Injecter::InjectDll(DWORD pid, LPCTSTR dllPath,long& error_code) 42 | { 43 | 44 | auto jhandle=::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 45 | /**pid = processInfo.dwProcessId; 46 | *process = processInfo.hProcess;*/ 47 | if (!jhandle) { 48 | error_code = ::GetLastError(); 49 | return -1; 50 | } 51 | DWORD dllPathSize = ((DWORD)wcslen(dllPath) + 1) * sizeof(TCHAR); 52 | 53 | // 申请内存用来存放DLL路径 54 | void* remoteMemory = VirtualAllocEx(jhandle, NULL, dllPathSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 55 | if (remoteMemory == NULL) 56 | { 57 | //setlog(L"申请内存失败,错误代码:%u\n", GetLastError()); 58 | error_code = ::GetLastError(); 59 | return -2; 60 | } 61 | 62 | // 写入DLL路径 63 | if (!WriteProcessMemory(jhandle, remoteMemory, dllPath, dllPathSize, NULL)) 64 | { 65 | //setlog(L"写入内存失败,错误代码:%u\n", GetLastError()); 66 | error_code = ::GetLastError(); 67 | return -3; 68 | } 69 | 70 | // 创建远线程调用LoadLibrary 71 | auto lpfn=GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"); 72 | if (!lpfn) { 73 | error_code = ::GetLastError(); 74 | return -4; 75 | } 76 | HANDLE remoteThread = CreateRemoteThread(jhandle, NULL, 0, (LPTHREAD_START_ROUTINE)lpfn, remoteMemory, 0, NULL); 77 | if (remoteThread == NULL) 78 | { 79 | //setlog(L"创建远线程失败,错误代码:%u\n", GetLastError()); 80 | error_code = ::GetLastError(); 81 | return -5; 82 | } 83 | // 等待远线程结束 84 | WaitForSingleObject(remoteThread, INFINITE); 85 | // 取DLL在目标进程的句柄 86 | DWORD remoteModule; 87 | GetExitCodeThread(remoteThread, &remoteModule); 88 | 89 | // 恢复线程 90 | //ResumeThread(processInfo.hThread); 91 | 92 | // 释放 93 | CloseHandle(remoteThread); 94 | VirtualFreeEx(jhandle, remoteMemory, dllPathSize, MEM_DECOMMIT); 95 | CloseHandle(jhandle); 96 | error_code = 0; 97 | return 1; 98 | } -------------------------------------------------------------------------------- /libop/winapi/Injecter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/optype.h" 3 | class Injecter 4 | { 5 | public: 6 | Injecter(); 7 | ~Injecter(); 8 | static BOOL EnablePrivilege(BOOL enable); 9 | // 10 | static long InjectDll(DWORD pid, LPCTSTR dllPath,long& error_code); 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /libop/winapi/MemoryEx.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "MemoryEx.h" 3 | #include "./core/helpfunc.h" 4 | #define push(s,x)s.push_back(x) 5 | #define pop(s) s.back();s.pop_back() 6 | 7 | int get_op_prior(wchar_t op) { 8 | if (op == L'+' || op == L'-') 9 | return 0; 10 | if (op == L'*' || op == L'/') 11 | return 1; 12 | return 2; 13 | } 14 | 15 | bool is_op(wchar_t op) { 16 | return op == L'+' || op == L'-' || op == L'*' || op == L'/'; 17 | } 18 | 19 | int do_op(int a, int b, wchar_t op) { 20 | int ans; 21 | if (op == L'+') 22 | ans = a + b; 23 | else if (op == L'-') 24 | ans = a - b; 25 | else if (op == L'*') 26 | ans = a * b; 27 | else if (op == L'/') 28 | ans = a / b; 29 | else 30 | ans = 0; 31 | return ans; 32 | } 33 | //like AA+BB+DD-CC*cc 34 | int stringcompute(const wchar_t* s) { 35 | int ans = 0; 36 | if (!s || !*s) 37 | return 0; 38 | wstring num; 39 | int op; 40 | vector ns; 41 | vector os; 42 | while (*s || !os.empty()) { 43 | if (is_op(*s) || *s == 0) { 44 | int x; 45 | swscanf(num.data(), L"%X", &x); 46 | 47 | if (!num.empty()) { 48 | push(ns, x); num.clear(); 49 | } 50 | 51 | if (ns.empty()) { /// 数字栈空,直接压入数据 52 | push(os, *s); 53 | s++; 54 | } 55 | else if (!os.empty()) { 56 | op = os.back(); 57 | if (*s == 0 || get_op_prior(op) >= get_op_prior(*s)) { // 进行运算 58 | int num2 = pop(ns); 59 | int num1 = pop(ns); 60 | op = pop(os); 61 | ans = do_op(num1, num2, op); 62 | push(ns, ans); 63 | //push(os, c); 64 | } 65 | else { // 将运算压入栈中 66 | push(os, *s); 67 | s++; 68 | } 69 | } 70 | else { 71 | push(os, *s); 72 | s++; 73 | } 74 | 75 | 76 | } 77 | else { 78 | num.push_back(*s); 79 | s++; 80 | } 81 | 82 | } 83 | 84 | return ns.back(); 85 | } 86 | 87 | MemoryEx::MemoryEx() 88 | { 89 | } 90 | 91 | 92 | MemoryEx::~MemoryEx() 93 | { 94 | } 95 | 96 | long MemoryEx::WriteData(HWND hwnd, const wstring& address, const wstring& data, LONG size) { 97 | _hwnd = hwnd; 98 | if (!checkaddress(address)) 99 | return 0; 100 | vector bin; 101 | hex2bins(bin, data,size); 102 | if (_hwnd) { 103 | if (!::IsWindow(hwnd)) 104 | return 0; 105 | DWORD pid; 106 | ::GetWindowThreadProcessId(hwnd, &pid); 107 | auto hr = _proc.Attach(pid); 108 | 109 | if (hr >= 0) { 110 | size_t addr = str2address(address); 111 | if (addr == 0)return 0; 112 | return mem_write(addr, bin.data(), size); 113 | 114 | } 115 | return 0; 116 | } 117 | else { 118 | size_t addr = str2address(address); 119 | if (addr == 0)return 0; 120 | return mem_write(addr,bin.data(), size); 121 | } 122 | 123 | 124 | } 125 | 126 | wstring MemoryEx::ReadData(HWND hwnd, const wstring& address, LONG size) { 127 | _hwnd = hwnd; 128 | if (!checkaddress(address)) 129 | return L""; 130 | vector bin; 131 | bin.resize(size); 132 | wstring hex; 133 | if (_hwnd) { 134 | if (!::IsWindow(hwnd)) 135 | return L""; 136 | DWORD pid; 137 | ::GetWindowThreadProcessId(hwnd, &pid); 138 | auto hr = _proc.Attach(pid); 139 | 140 | if (hr >= 0) { 141 | size_t addr = str2address(address); 142 | if (addr == 0)return L""; 143 | mem_read(bin.data(), addr, size); 144 | } 145 | } 146 | else { 147 | size_t addr = str2address(address); 148 | if (addr == 0)return L""; 149 | mem_read(bin.data(), addr, size); 150 | } 151 | 152 | bin2hexs(bin, hex); 153 | return hex; 154 | 155 | } 156 | 157 | bool MemoryEx::mem_read(void* dst, size_t src, size_t size) { 158 | if (_hwnd) { 159 | return _proc.memory().Read(src, size, dst) >= 0; 160 | } 161 | else { 162 | ::memcpy(dst, (void*)src, size); 163 | return true; 164 | } 165 | 166 | } 167 | 168 | bool MemoryEx::mem_write(size_t dst, void* src, size_t size) { 169 | if (_hwnd) { 170 | return _proc.memory().Write(dst, size, src) >= 0; 171 | } 172 | else { 173 | ::memcpy((void*)dst, src, size); 174 | return true; 175 | } 176 | } 177 | 178 | bool MemoryEx::checkaddress(const wstring& address) { 179 | vector sk; 180 | auto p = address.data(); 181 | while (*p) { 182 | if (*p == L'[' || *p == L']') { 183 | if (sk.empty()) 184 | sk.push_back(*p); 185 | else if (sk.back() == *p) 186 | sk.push_back(*p); 187 | else 188 | sk.pop_back(); 189 | } 190 | p++; 191 | } 192 | return sk.empty(); 193 | } 194 | 195 | size_t MemoryEx::str2address(const wstring& caddress) { 196 | wstring address = caddress; 197 | if (!checkaddress(address)) 198 | return 0; 199 | 200 | vector sk; 201 | int idx1 = 0, idx2 = 0; 202 | size_t re = 0; 203 | idx1 = address.find(L'<'); 204 | idx2 = address.find(L'>'); 205 | if (idx1 != -1 && idx2 != -1 && idx1 < idx2) { 206 | auto mod_name = address.substr(idx1 + 1, idx2 - idx1 - 1); 207 | HMODULE hmod = NULL; 208 | if (_hwnd == 0) 209 | hmod = ::GetModuleHandleW(mod_name.data()); 210 | else { 211 | auto mptr = _proc.modules().GetModule(mod_name); 212 | if (mptr)hmod = (HMODULE)mptr->baseAddress; 213 | } 214 | if (hmod == NULL)return 0; 215 | wchar_t buff[128]; 216 | wsprintf(buff, L"%X", hmod); 217 | address.replace(idx1, idx2 - idx1 + 1, buff); 218 | } 219 | for (int i = 0; i < address.size();) { 220 | if (address[i] == L'[')push(sk, i); 221 | if (address[i] == L']') { 222 | idx1 = pop(sk); 223 | idx2 = i; 224 | auto sad = address.substr(idx1 + 1, idx2 - idx1 - 1); 225 | size_t src = stringcompute(sad.data()); 226 | size_t next; 227 | if (!mem_read(&next, src, sizeof(size_t)) || next == 0) 228 | return 0; 229 | wchar_t buff[128]; 230 | wsprintf(buff, L"%X", next); 231 | address.replace(idx1, idx2 - idx1 + 1, buff); 232 | i = idx1; 233 | } 234 | ++i; 235 | } 236 | return stringcompute(address.data()); 237 | } 238 | 239 | void MemoryEx::hex2bins(vector&bin, const wstring& hex,size_t size) { 240 | bin.resize(size); 241 | ZeroMemory(bin.data(), bin.size()); 242 | int low = 1; 243 | for (int i = hex.size() - 1; i >= 0; --i) { 244 | 245 | bin[size - i / 2-1] |= low & 1 ? hex2bin(hex[i]) : hex2bin(hex[i]) << 4; 246 | low ^= 1; 247 | } 248 | } 249 | 250 | void MemoryEx::bin2hexs(const vector&bin, wstring& hex) { 251 | //hex.resize(bin.size() * 2); 252 | hex.reserve(bin.size() * 2); 253 | hex.clear(); 254 | for (int i = 0; i < bin.size(); ++i) { 255 | int ans = bin2hex(bin[i]); 256 | hex.push_back(ans >> 8); 257 | hex.push_back(ans & 0xff); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /libop/winapi/MemoryEx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __MEMORYEX_H_ 3 | #define __MEMORYEX_H_ 4 | #include "./core/helpfunc.h" 5 | #include "BlackBone/Process/Process.h" 6 | class MemoryEx 7 | { 8 | public: 9 | MemoryEx(); 10 | ~MemoryEx(); 11 | long WriteData(HWND hwnd, const wstring& address, const wstring& data, LONG size); 12 | wstring ReadData(HWND hwnd, const wstring& address, LONG size); 13 | bool checkaddress(const wstring& address); 14 | size_t str2address(const wstring& caddress); 15 | bool mem_read(void* dst, size_t src, size_t size); 16 | bool mem_write(size_t dst, void* src, size_t size); 17 | void hex2bins(vector&bin, const wstring& hex,size_t size); 18 | void bin2hexs(const vector&bin, wstring& hex); 19 | private: 20 | blackbone::Process _proc; 21 | HWND _hwnd; 22 | }; 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /libop/winapi/WinApi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __WINAPI_H_ 3 | #define __WINAPI_JH_ 4 | #include "../core/optype.h" 5 | #undef FindWindow 6 | #undef FindWindowEx 7 | class WinApi 8 | { 9 | public: 10 | WinApi(void); 11 | ~WinApi(void); 12 | 13 | 14 | public: 15 | int retstringlen; 16 | DWORD WindowVerion; 17 | DWORD IsEuemprosuccess; 18 | DWORD npid[MAX_PATH]; 19 | bool EnumWindow(HWND parent, const wchar_t *title, const wchar_t *class_name, LONG filter, wchar_t *retstring, const wchar_t *process_name = NULL); 20 | bool EnumWindowSuper(wchar_t *spec1, LONG flag1, LONG type1, wchar_t *spec2, LONG flag2, LONG type2, LONG sort, wchar_t *retstring = NULL); 21 | bool EnumProcess(const wchar_t *name, wchar_t *retstring); 22 | bool ClientToScreen(LONG hwnd, LONG &x, LONG &y); 23 | long FindWindow(const wchar_t *class_name, const wchar_t*title); 24 | long FindWindowEx(long parent, const wchar_t *class_name, const wchar_t*title); 25 | bool FindWindowByProcess(const wchar_t *class_name, const wchar_t *titl, LONG &rethwnd, const wchar_t *process_name = NULL, DWORD Pid = 0); 26 | bool GetClientRect(LONG hwnd, LONG &x, LONG &y, LONG &x1, LONG &y1); 27 | bool GetClientSize(LONG hwnd, LONG &width, LONG &height); 28 | bool GetMousePointWindow(LONG &rethwnd, LONG x = -1, LONG y = -1); 29 | bool GetProcessInfo(LONG pid, wchar_t *retstring); 30 | bool GetWindow(LONG hwnd, LONG flag, LONG &rethwnd); 31 | bool GetProcesspath(DWORD ProcessID, wchar_t* process_path); 32 | bool GetWindowState(LONG hwnd, LONG flag); 33 | bool SendPaste(LONG hwnd); 34 | bool SetWindowSize(LONG hwnd, LONG width, LONG hight, int type = 0); 35 | bool SetWindowState(LONG hwnd, LONG flag, LONG rethwnd = 0); 36 | bool SetWindowTransparent(LONG hwnd, LONG trans); 37 | bool SetClipboard(const wchar_t *values); 38 | bool GetClipboard(std::wstring &retstr); 39 | //2019.1 40 | long SendString(HWND hwnd, const wstring& str); 41 | long SendStringIme(HWND hwnd, const wstring& str); 42 | //2019.3 43 | long RunApp(const wstring& cmd, long mode); 44 | static HWND GetTopWindowSp(HWND hwnd); 45 | 46 | private: 47 | DWORD FindChildWnd(HWND hchile, const wchar_t *title, const wchar_t *classname, wchar_t *retstring, bool isGW_OWNER = false, bool isVisible = false, const wchar_t *process_name = NULL); 48 | BOOL EnumProcessbyName(DWORD dwPID, LPCWSTR ExeName, LONG type = 0); 49 | int GetProcessNumber();//获取CPU个数 50 | // 时间格式转换 51 | __int64 FileTimeToInt64(const FILETIME& time); 52 | double get_cpu_usage(DWORD ProcessID); //获取指定进程CPU使用率 53 | DWORD GetMemoryInfo(DWORD ProcessID); //或者指定进程内存使用率 54 | }; 55 | 56 | 57 | #endif -------------------------------------------------------------------------------- /libop/winapi/query_api.cpp: -------------------------------------------------------------------------------- 1 | //#include "stdafx.h" 2 | #include "core/optype.h" 3 | #include "query_api.h" 4 | 5 | 6 | void* query_api(const char* mod_name, const char* func_name) { 7 | auto hdll = ::GetModuleHandleA(mod_name); 8 | if (!hdll) { 9 | //_error_code = -1; 10 | return NULL; 11 | } 12 | void* paddress = (void*)::GetProcAddress(hdll, func_name); 13 | if (!paddress) { 14 | //_error_code = -2; 15 | return NULL; 16 | } 17 | //_error_code = 0; 18 | return paddress; 19 | 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /libop/winapi/query_api.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void* query_api(const char* mod_name, const char* func_name); 4 | 5 | 6 | -------------------------------------------------------------------------------- /make_Visual_Studio_2019.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 3 | Title Debug 4 | :BEGIN 5 | mkdir build 6 | cd build 7 | mkdir msvc16 8 | cd msvc16 9 | set CMAKE_PREFIX_PATH=K:\Qt5\lib\cmake 10 | cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\..\ -G"Visual Studio 16 2019" 11 | @echo msbuild Project.sln /p:Configuration=Debug /p:Platform=X64 /m 12 | cd ..\..\ 13 | echo %cd% 14 | echo ========================OK==================== 15 | pause 16 | goto BEGIN -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: 2 | .\mkDebug.bat 3 | 4 | release: 5 | .\mkRelease.bat 6 | 7 | clean: 8 | rd /s /q build\\release -------------------------------------------------------------------------------- /mkDebug.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" amd64 3 | Title Debug 4 | :BEGIN 5 | mkdir build 6 | cd build 7 | mkdir Debug 8 | cd Debug 9 | cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\..\ -G"NMake Makefiles" 10 | nmake 11 | cd ..\..\ 12 | echo %cd% 13 | rem pause 14 | rem goto :BEGIN 15 | echo ========================OK==================== -------------------------------------------------------------------------------- /mkRelease.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" amd64 3 | Title Release 4 | :BEGIN 5 | mkdir build 6 | cd build 7 | mkdir Release 8 | cd Release 9 | cmake -DCMAKE_BUILD_TYPE=Release ..\..\ -G"NMake Makefiles" 10 | nmake 11 | cd ..\..\ 12 | echo %cd% 13 | echo pause 14 | echo goto :BEGIN 15 | echo ========================OK==================== -------------------------------------------------------------------------------- /swig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | ADD_DEFINITIONS(-D _UNICODE) 4 | ADD_DEFINITIONS(-D UNICODE) 5 | 6 | ADD_DEFINITIONS(-D _CMAKE_BUILD) 7 | IF(CMAKE_SIZEOF_VOID_P EQUAL 8) 8 | SET(PYTHON_HOME $ENV{PYTHON64_ROOT}) 9 | else() 10 | SET(PYTHON_HOME $ENV{PYTHON32_ROOT}) 11 | endif() 12 | 13 | SET(SRC_FILES "op_wrap.cxx") 14 | 15 | add_library(pyop SHARED ${SRC_FILES}) 16 | 17 | target_include_directories(pyop PUBLIC 18 | "${PROJECT_BINARY_DIR}" 19 | "${CMAKE_CURRENT_SOURCE_DIR}" 20 | "${PYTHON_HOME}\\include" 21 | ) 22 | message(STATUS "${PYTHON_HOME}\\libs") 23 | target_link_directories(pyop PUBLIC "${PYTHON_HOME}\\libs") 24 | #find_library(OP_LIB op ../bin/Release NO_DEFAULT_PATH) 25 | set_target_properties(pyop PROPERTIES PREFIX "_") 26 | set_target_properties(pyop PROPERTIES SUFFIX ".pyd") 27 | 28 | 29 | target_link_libraries(pyop ${op_com}) 30 | target_link_libraries(pyop python310) 31 | 32 | IF(CMAKE_SIZEOF_VOID_P EQUAL 8) 33 | install(TARGETS pyop RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 34 | install(TARGETS pyop ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x64") 35 | install(FILES pyop.py DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 36 | ELSE() 37 | install(TARGETS pyop RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 38 | install(TARGETS pyop ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x86") 39 | install(FILES pyop.py DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 40 | ENDIF() 41 | -------------------------------------------------------------------------------- /swig/genPythonWrap.bat: -------------------------------------------------------------------------------- 1 | swig -python -c++ op.i -------------------------------------------------------------------------------- /swig/op.i: -------------------------------------------------------------------------------- 1 | #define OP_API 2 | %module pyop 3 | 4 | %{ 5 | #define OP_API 6 | #include "../libop/libop.h" 7 | %} 8 | 9 | %include "std_string.i" 10 | %include "std_wstring.i" 11 | %include "typemaps.i" 12 | %apply std::wstring &OUTPUT {std::wstring &} 13 | %apply long *OUTPUT {long *} 14 | %apply size_t *OUTPUT {size_t *} 15 | %include "../libop/libop.h" 16 | 17 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | ADD_DEFINITIONS(-D _UNICODE) 4 | ADD_DEFINITIONS(-D UNICODE) 5 | 6 | ADD_DEFINITIONS(-D _CMAKE_BUILD) 7 | 8 | SET(SRC_FILES "main.cpp" 9 | "../libop/com/op_i.c") 10 | 11 | include_directories( 12 | ./ 13 | ../libop/3rd_party/include/3rd_party 14 | ) 15 | 16 | add_executable(op_test ${SRC_FILES} ) 17 | 18 | target_link_libraries(op_test ${op_com}) 19 | 20 | IF(CMAKE_CL_64) 21 | install(TARGETS op_test DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 22 | ELSE(CMAKE_CL_64) 23 | install(TARGETS op_test DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 24 | ENDIF(CMAKE_CL_64) -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 |  2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include "op_test.h" 14 | #include "../libop/com/op_i.h" 15 | #include "../libop/imageProc/compute/ThreadPool.h" 16 | 17 | #include "../libop/core/optype.h" 18 | #pragma warning(disable : 4996) 19 | 20 | using namespace std; 21 | bool gRun = false; 22 | mutex gMutex; 23 | 24 | void proc_shared(libop* sharedOp) { 25 | void* data = 0; 26 | long size, ret; 27 | while (gRun) { 28 | this_thread::sleep_for(chrono::microseconds(100)); 29 | lock_guard lock(gMutex); 30 | cout << "thread:" << this_thread::get_id() << endl; 31 | sharedOp->GetScreenDataBmp(0, 0, 50, 50, (size_t*)&data, &size, &ret); 32 | } 33 | } 34 | 35 | void proc_unique(long hwnd) { 36 | void* data = 0; 37 | long size, ret; 38 | libop* uniqueOp = new libop(); 39 | uniqueOp->BindWindow(hwnd, L"normal", L"normal", L"normal", 0, &ret); 40 | while (gRun && ret) { 41 | // this_thread::sleep_for(chrono::microseconds(100)); 42 | // lock_guard lock(gMutex); 43 | cout << "thread:" << this_thread::get_id() << endl; 44 | 45 | uniqueOp->GetScreenDataBmp(0, 0, 50, 50, (size_t*)&data, &size, &ret); 46 | } 47 | delete uniqueOp; 48 | } 49 | 50 | void test_shared() { 51 | libop* sharedOp = new libop(); 52 | gRun = true; 53 | thread t1(proc_shared, sharedOp); 54 | thread t2(proc_shared, sharedOp); 55 | cin.get(); 56 | gRun = false; 57 | t1.join(); 58 | t2.join(); 59 | 60 | delete sharedOp; 61 | } 62 | 63 | void test_unique() { 64 | gRun = true; 65 | long hwnd[2] = { 0x001407EE, 0x00010472 }; 66 | thread t1(proc_unique, hwnd[0]); 67 | thread t2(proc_unique, hwnd[1]); 68 | cin.get(); 69 | gRun = false; 70 | t1.join(); 71 | t2.join(); 72 | } 73 | 74 | int test_com() { 75 | #ifdef _WIN64 76 | HMODULE hdll = LoadLibraryA("op_x64.dll"); 77 | #else 78 | HMODULE hdll = LoadLibraryA("op_x86.dll"); 79 | #endif 80 | if (!hdll) { 81 | printf("LoadLibraryA false!\n"); 82 | return -1; 83 | } 84 | typedef HRESULT(__stdcall* DllGetClassObject_t)( 85 | _In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv); 86 | DllGetClassObject_t pfun1 = 87 | (DllGetClassObject_t)GetProcAddress(hdll, "DllGetClassObject"); 88 | if (!pfun1) { 89 | printf("GetProcAddress false!\n"); 90 | return -2; 91 | } 92 | IClassFactory* fac = 0; 93 | pfun1(CLSID_OpInterface, IID_IClassFactory, (void**)&fac); 94 | if (!fac) { 95 | printf("DllGetClassObject false!\n"); 96 | return -3; 97 | } 98 | IOpInterface* op; 99 | fac->CreateInstance(NULL, IID_IOpInterface, (void**)&op); 100 | 101 | if (!op) { 102 | printf("CoCreateInstance false!\n"); 103 | return -4; 104 | } 105 | 106 | std::cout << "ok\n"; 107 | long hwnd = 0; 108 | op->GetPointWindow(100, 100, &hwnd); 109 | long ret = 0; 110 | op->GetWindowState(hwnd, 2, &ret); 111 | std::cout << "----ret----:" << ret << std::endl; 112 | return 0; 113 | } 114 | 115 | void printHR(HRESULT hr) { 116 | if (hr == S_OK) { 117 | printf("\n"); 118 | } 119 | else if (hr == E_OUTOFMEMORY) { 120 | printf("E_OUTOFMEMORY\n"); 121 | } 122 | else if (hr == DISP_E_UNKNOWNNAME) { 123 | printf("DISP_E_UNKNOWNNAME\n"); 124 | } 125 | else if (hr == DISP_E_UNKNOWNLCID) { 126 | printf("DISP_E_UNKNOWNLCID\n"); 127 | } 128 | else { 129 | printf("other error code=%08X\n", hr); 130 | } 131 | } 132 | 133 | int test_invoke() { 134 | IOpInterface* op; 135 | 136 | //CoCreateInstance(&CLSID_OpInterface, NULL, CLSCTX_INPROC, &IID_IOpInterface, &op); 137 | /*if (op) { 138 | printf("use free com ok!\n"); 139 | BSTR ver; 140 | op->lpVtbl->Ver(op, &ver); 141 | wprintf(L"op ver=%s", ver); 142 | }*/ 143 | IDispatch* dispatch; 144 | HRESULT hr = 0; 145 | hr = CoCreateInstance(CLSID_OpInterface, NULL, CLSCTX_INPROC, 146 | IID_IDispatch, (void**)&dispatch); wchar_t* names = new wchar_t[256]; 147 | memcpy(names, L"Ver", 8); 148 | if (dispatch == 0) { 149 | printf("error:CoCreateInstance\n"); 150 | printHR(hr); 151 | return 0; 152 | } 153 | 154 | DISPID id; 155 | VARIANT ret; 156 | hr = dispatch->GetIDsOfNames(IID_NULL, &names, 1, LOCALE_SYSTEM_DEFAULT, 157 | &id); if (hr < 0) { 158 | printf("error:GetIDsOfNames\n"); printHR(hr); return 0; 159 | } 160 | DISPPARAMS parms = { 161 | NULL, 162 | 0, 163 | 0 164 | }; 165 | 166 | hr = dispatch->Invoke(id, IID_NULL, LOCALE_SYSTEM_DEFAULT, 167 | DISPATCH_METHOD, &parms, &ret, NULL, NULL); if (hr < 0) { 168 | printf("error:Invoke\n"); 169 | printHR(hr); 170 | return 0; 171 | } 172 | 173 | if (ret.vt == VT_BSTR) { 174 | wprintf(ret.bstrVal); 175 | wprintf(L"\n"); 176 | } 177 | else { 178 | printf("error:ret.vt != VT_BSTR\n"); 179 | } 180 | return 0; 181 | } 182 | 183 | void test_threadPool(); 184 | 185 | void test_rect(); 186 | 187 | int main(int argc, char* argv[]) { 188 | locale loc("chs"); 189 | wcout.imbue(loc); 190 | int a[2] = { 0, 1 }; 191 | int b = *a + 1; 192 | int c = *(a + 1); 193 | std::cout << "b:" << b << ", c:" << c << std::endl; 194 | 195 | // test_shared(); 196 | CoInitialize(NULL); 197 | //test_unique(); 198 | //test_invoke(); 199 | //test_com(); 200 | test* ptest = new test; 201 | ptest->do_test(); 202 | delete ptest; 203 | ptest = nullptr; 204 | //test_paddle(); 205 | 206 | return 0; 207 | } 208 | 209 | void test_threadPool() { 210 | size_t maxThread = std::thread::hardware_concurrency(); 211 | std::cout << "max support thread num : " << maxThread << std::endl; 212 | ThreadPool pool(4); 213 | 214 | std::vector> results; 215 | 216 | for (int i = 0; i < 8; ++i) { 217 | results.emplace_back( 218 | pool.enqueue([i] { 219 | std::cout << "hello " << i << std::endl; 220 | std::this_thread::sleep_for(std::chrono::seconds(1)); 221 | std::cout << "world " << i << std::endl; 222 | return i * i; 223 | }) 224 | ); 225 | } 226 | 227 | for (auto&& result : results) 228 | std::cout << result.get() << ' '; 229 | std::cout << std::endl; 230 | 231 | 232 | } 233 | 234 | void test_rect() { 235 | rect_t rc(0, 0, 100, 100); 236 | std::vector blocks; 237 | rc.divideBlock(3, false, blocks); 238 | for (auto& r : blocks) { 239 | std::cout << r.x1 << "," << r.y1 << "," << r.x2 << "," << r.y2 << std::endl; 240 | } 241 | rc.divideBlock(3, true, blocks); 242 | for (auto& r : blocks) { 243 | std::cout << r.x1 << "," << r.y1 << "," << r.x2 << "," << r.y2 << std::endl; 244 | } 245 | 246 | } 247 | -------------------------------------------------------------------------------- /tests/op_test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __OP_TEST_H_ 3 | #define __OP_TEST_H_ 4 | #include 5 | 6 | #include 7 | 8 | #include "../libop/libop.h" 9 | #define op_check(name, express) \ 10 | std::cout << "check interface:'" << #name << "' condition:" << #express \ 11 | << ((express) ? "\npass\n" : "\nfailed\n");++total_cnt;pass_cnt+=express 12 | using namespace std; 13 | class test { 14 | public: 15 | test() : m_op(new libop()) {} 16 | virtual ~test() { 17 | delete m_op; 18 | m_op = nullptr; 19 | } 20 | 21 | int TestForeground() { 22 | long ret = 0; 23 | m_op->BindWindow(0, L"normal", L"normal", L"normal", 0, &ret); 24 | if (ret == 1) { 25 | std::cout << "bind normal normal normal ok\n"; 26 | do_some_test(m_op); 27 | m_op->UnBindWindow(&ret); 28 | } 29 | m_op->BindWindow(0, L"normal.dxgi", L"normal", L"normal", 0, &ret); 30 | if (ret == 1) { 31 | std::cout << "bind normal.dxgi normal normal ok\n"; 32 | do_some_test(m_op); 33 | m_op->UnBindWindow(&ret); 34 | } 35 | return 0; 36 | } 37 | 38 | int TestNox(libop *op) { 39 | long hwnd = 0, subhwnd = 0, ret = 0; 40 | op->FindWindow(L"Qt5QWindowIcon", L"夜神模拟器", &hwnd); 41 | if (!hwnd) { 42 | std::wcout << L"FindWindow of 夜神模拟器 false!\n"; 43 | 44 | return -1; 45 | } 46 | op->FindWindowEx(hwnd, L"Qt5QWindowIcon", L"centralWidgetWindow", &subhwnd); 47 | if (!subhwnd) { 48 | std::cout << "FindWindow of centralWidgetWindow false!\n"; 49 | return -2; 50 | } 51 | printf("find ok ,hwnd is %08x\n", subhwnd); 52 | op->BindWindow(subhwnd, L"opengl.nox", L"windows", L"windows", 0, &ret); 53 | if (!ret) { 54 | std::cout << "BindWindow Nox false!\n"; 55 | return -2; 56 | } 57 | // todo.. 58 | do_some_test(op); 59 | 60 | op->UnBindWindow(&ret); 61 | return ret; 62 | } 63 | int TestLD(libop *op) { 64 | long hwnd = 0, subhwnd = 0, ret = 0; 65 | op->FindWindow(L"LDPlayerMainFrame", L"雷电模拟器", &hwnd); 66 | if (!hwnd) { 67 | std::cout << "FindWindow of LDPlayerMainFrame false!\n"; 68 | return -1; 69 | } 70 | op->FindWindowEx(hwnd, L"RenderWindow", L"TheRender", &subhwnd); 71 | if (!subhwnd) { 72 | std::cout << "FindWindow of TheRender false!\n"; 73 | return -2; 74 | } 75 | printf("find LD ok ,hwnd is %08x\n", subhwnd); 76 | op->BindWindow(subhwnd, L"opengl", L"windows", L"windows", 0, &ret); 77 | if (!ret) { 78 | std::cout << "BindWindow Nox false!\n"; 79 | return -2; 80 | } 81 | // todo.. 82 | do_some_test(op); 83 | 84 | op->UnBindWindow(&ret); 85 | return ret; 86 | } 87 | 88 | int BindMine(libop *op) { 89 | long hwnd = 0; 90 | long ret = 0; 91 | op->FindWindow(L"扫雷", L"扫雷", &hwnd); 92 | // hwnd = 0x004608BC; 93 | if (hwnd) { 94 | op->BindWindow(hwnd, L"dx.d3d9", L"normal", L"normal", 0, &ret); 95 | if (ret) { 96 | do_some_test(op); 97 | } 98 | op->UnBindWindow(&ret); 99 | } 100 | return 0; 101 | } 102 | int do_some_test(libop *op) { 103 | printf("******************** do_some_test *************************** \n"); 104 | wstring ver, str; 105 | long lret = 0; 106 | m_op->Capture(10, 10, 200, 200, L"xxx.bmp", &lret); 107 | 108 | for (int i = 0; i < 10; i++) { 109 | Sleep(20); 110 | long frame_id, time; 111 | m_op->GetScreenFrameInfo(&frame_id, &time); 112 | printf("frame id=%d time=%.3lfs\n", frame_id, time / 1000.); 113 | } 114 | void *data=nullptr; 115 | long size; 116 | m_op->GetScreenDataBmp(0, 0, 200, 200, (size_t*)&data, &size, &lret); 117 | if (data) { 118 | std::ofstream os("GetScreenDataBmp.bmp", std::ios::binary); 119 | os.write((char*)data, size); 120 | os.close(); 121 | } 122 | m_op->FindLine(50, 50, 400, 400, L"", 0.95, ver); 123 | std::wcout << "FindLine result:" << ver << std::endl; 124 | 125 | std::wcout.imbue(locale("chs")); 126 | 127 | int pass_cnt = 0; 128 | int total_cnt = 0; 129 | // ***************** check base function ************************ 130 | ver = m_op->Ver(); 131 | op_check(Ver, ver == L"0.4.2.0"); 132 | 133 | m_op->SetShowErrorMsg(3, &lret); 134 | op_check(SetShowErrorMsg, lret); 135 | 136 | m_op->MatchPicName(L"s*.bmp", str); 137 | std::wcout << "MatchPicName:" << str << std::endl; 138 | 139 | m_op->FindNearestPos(L"1,2|3,4|5,6|7,8", 1, 3, 0, str); 140 | op_check(FindNearestPos, str == L"1,2"); 141 | 142 | 143 | ver = m_op->Ver(); 144 | wprintf(L"ver:%s\n", ver.data()); 145 | 146 | m_op->GetBasePath(str); 147 | wprintf(L"GetBasePath:%s\n", str.data()); 148 | // op_check(GetBasePath, str == L"E:\\project\\op\\bin\\x86"); 149 | 150 | // ***************** check ocr function ****************** 151 | 152 | //m_op->SetDict(0, L"st10.dict", &lret); 153 | //op_check(SetDict, lret == 1); 154 | m_op->Ocr(0, 0, 2000, 2000, L"000000", 0.8, str); 155 | std::wcout << L"ocr:" << str << std::endl; 156 | op_check(Ocr, str.length() > 0); 157 | m_op->GetWindowState((long)(::GetDesktopWindow()), 2, &lret); 158 | op_check(GetWindowState, lret == 1); 159 | 160 | // ***************** check color function ****************** 161 | 162 | std::wstring color; 163 | m_op->GetColor(20, 20, color); 164 | std::wcout << L"color in 20,20: " << std::endl; 165 | std::wcout << color << std::endl; 166 | op_check(GetColor, color.length() == 6); 167 | 168 | m_op->CmpColor(20, 20, color.data(), 1.0, &lret); 169 | op_check(CmpColor, lret == 1); 170 | 171 | long lx, ly; 172 | for(int dir=0;dir<4;++dir){ 173 | m_op->FindColor(0, 0, 2000, 2000, color.data(), 1.0, dir, &lx, &ly, &lret); 174 | std::cout <<"dir:"<< dir<<" ret:" << lret << "," << lx << "," << ly << std::endl; 175 | op_check(FindColor, lret == 1 && 0 <= lx && lx <= 2000); 176 | } 177 | wstring colors[3]; 178 | m_op->GetColor(20, 20, colors[0]); 179 | m_op->GetColor(21, 20, colors[1]); 180 | m_op->GetColor(20, 21, colors[2]); 181 | wstring offcolor = L"1|0|" + colors[1] + L",0|1|" + colors[2]; 182 | for(int dir=0;dir<4;dir++){ 183 | m_op->FindMultiColor(0, 0, 2000, 2000, colors[0].data(), offcolor.data(), 1.0, dir, &lx, &ly, &lret); 184 | std::cout <<"FindMultiColor dir:"<< dir<<" ret:" << lret << "," << lx << "," << ly << std::endl; 185 | op_check(FindMultiColor, lret == 1); 186 | } 187 | 188 | 189 | m_op->FindMultiColorEx(0, 0, 2000, 2000, colors[0].data(), offcolor.data(), 1.0, 0, str); 190 | op_check(FindMultiColorEx, str.length() > 0); 191 | 192 | // ***********************8 check screen capture *************8 193 | m_op->SetScreenDataMode(0, &lret); 194 | m_op->GetScreenDataBmp(0, 0, 200, 200, (size_t*) & data, &size, &lret); 195 | op_check(GetScreenDataBmp, lret == 1); 196 | 197 | m_op->FindColorBlock(0, 0, 2000, 2000, L"000000", 1.0, 200, 20, 20, &lx, &ly, &lret); 198 | op_check(FindColorBlock, lret == 1); 199 | 200 | m_op->FindColorBlockEx(0, 0, 2000, 2000, L"000000", 1.0, 200, 20, 20, str); 201 | //std::wcout << str << std::endl; 202 | op_check(FindColorBlockEx, str.length() > 0); 203 | 204 | m_op->Capture(60, 60, 100, 100, L"test.bmp", &lret); 205 | op_check(Capture, lret >= 0); 206 | 207 | for (int dir = 0; dir < 4; ++dir) { 208 | m_op->FindPic(0, 0, 2000, 2000, L"test.bmp", L"000000", 1.0, dir, &lx, &ly, &lret); 209 | std::cout <<"dir:"<< dir<<" ret:" << lret << "," << lx << "," << ly << std::endl; 210 | op_check(FindPic, lret >= 0); 211 | } 212 | for (int dir = 0; dir < 4; ++dir) { 213 | m_op->FindPicEx(0, 0, 2000, 2000, L"test.bmp", L"000000", 1.0, dir, str); 214 | std::wcout << "FindPicEx:" << str << std::endl; 215 | op_check(FindPicEx, str.length() > 0); 216 | } 217 | 218 | 219 | std::cout << "--------------total_test-----------:\n" 220 | << total_cnt << " passed:" << pass_cnt << std::endl; 221 | return 0; 222 | } 223 | void do_test() { 224 | 225 | // m_op->FindWindow() 226 | TestForeground(); 227 | 228 | TestNox(m_op); 229 | TestLD(m_op); 230 | BindMine(m_op); 231 | } 232 | 233 | protected: 234 | libop *m_op; 235 | }; 236 | #endif // !__TEST_H_ 237 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | ADD_DEFINITIONS(-D _UNICODE) 4 | ADD_DEFINITIONS(-D UNICODE) 5 | 6 | ADD_DEFINITIONS(-D _CMAKE_BUILD) 7 | 8 | #ADD_DEFINITIONS(-D EASYCOM_EXPORTS) 9 | 10 | # find_library(minhook_lib libminhook.x86 ./3rd_party/lib/x86 NO_DEFAULT_PATH) 11 | 12 | SET(TOOLS_SRC_FILES 13 | "dllmain.c" 14 | "../libop/com/op_i.c" 15 | "easycom.cpp") 16 | 17 | 18 | add_library(tools SHARED ${TOOLS_SRC_FILES}) 19 | 20 | TARGET_LINK_LIBRARIES(tools minhook) 21 | 22 | 23 | IF(CMAKE_SIZEOF_VOID_P EQUAL 8) 24 | install(TARGETS tools RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x64") 25 | install(TARGETS tools ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x64") 26 | ELSE() 27 | install(TARGETS tools RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/bin/x86") 28 | install(TARGETS tools ARCHIVE DESTINATION "${PROJECT_SOURCE_DIR}/lib/x86") 29 | ENDIF() -------------------------------------------------------------------------------- /tools/EasyCom.cpp: -------------------------------------------------------------------------------- 1 | // EasyCom.cpp : 定义 DLL 的导出函数。 2 | // 3 | #include "framework.h" 4 | #include "EasyCom.h" 5 | 6 | #include 7 | #include "../libop/com/op_i.h" 8 | #include "MinHook.h" 9 | #include 10 | #include 11 | #include 12 | #pragma warning(disable:4996) 13 | 14 | char dllpathA[512] = "op_x86.dll"; 15 | wchar_t dllpathW[512] = L"op_x86.dll"; 16 | HRESULT(__stdcall* oCLSIDFromProgID)( 17 | _In_ LPCOLESTR lpszProgID, 18 | _Out_ LPCLSID lpclsid 19 | ); 20 | 21 | HRESULT(__stdcall* oCoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, 22 | REFIID riid, LPVOID FAR* ppv); 23 | 24 | HRESULT(__stdcall* 25 | oCoGetClassObject)( 26 | _In_ REFCLSID rclsid, 27 | _In_ DWORD dwClsContext, 28 | _In_opt_ LPVOID pvReserved, 29 | _In_ REFIID riid, 30 | _Outptr_ LPVOID FAR* ppv 31 | ); 32 | 33 | HRESULT __stdcall myCLSIDFromProgID( 34 | _In_ LPCOLESTR lpszProgID, 35 | _Out_ LPCLSID lpclsid 36 | ) { 37 | //MessageBoxW(NULL, L"myCLSIDFromProgID",lpszProgID, 0); 38 | //printf("myCLSIDFromProgID\n"); 39 | if (wcscmp(lpszProgID, L"op.opsoft") == 0) { 40 | memcpy(lpclsid, &CLSID_OpInterface, sizeof(CLSID_OpInterface)); 41 | //MessageBoxW(NULL, L"memcpy", lpszProgID, 0); 42 | return S_OK; 43 | } 44 | else { 45 | //printf("oCLSIDFromProgID\n"); 46 | //MessageBoxW(NULL, L"oCLSIDFromProgID", lpszProgID, 0); 47 | return oCLSIDFromProgID(lpszProgID, lpclsid); 48 | } 49 | } 50 | 51 | 52 | 53 | HRESULT __stdcall 54 | myCoCreateInstance( 55 | _In_ REFCLSID rclsid, 56 | _In_opt_ LPUNKNOWN pUnkOuter, 57 | _In_ DWORD dwClsContext, 58 | _In_ REFIID riid, 59 | _COM_Outptr_ _At_(*ppv, _Post_readable_size_(_Inexpressible_(varies))) LPVOID FAR* ppv 60 | ) { 61 | /*if (IsEqualCLSID(rclsid, CLSID_OpInterface))printf("CLSID_OpInterface\n"); 62 | else printf("unknown clsid\n"); 63 | 64 | if (IsEqualCLSID(riid, IID_IDispatch)) 65 | printf("IID_IDispatch\n"); 66 | else if (IsEqualCLSID(riid, IID_IUnknown)) 67 | printf("IID_IUnknown\n"); 68 | else 69 | printf("unknown riid\n"); 70 | */ 71 | //return oCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); 72 | if (memcmp(&rclsid, &CLSID_OpInterface, sizeof(CLSID_OpInterface)) != 0 73 | /*|| memcmp(riid, &IID_IOpInterface, sizeof(IID_IOpInterface)) != 0*/) { 74 | 75 | //MessageBoxA(NULL, "oCoCreateInstance", "", 0); 76 | return oCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); 77 | 78 | } 79 | //return -1; 80 | *ppv = 0; 81 | printf("myCoCreateInstance\n"); 82 | 83 | HMODULE hdll = LoadLibraryA(dllpathA); 84 | if (!hdll) { 85 | printf("LoadLibraryA false!\n"); 86 | MessageBoxW(NULL, L"LoadLibraryA", NULL, 0); 87 | return -1; 88 | } 89 | //printf("LoadLibraryA !\n"); 90 | typedef HRESULT(__stdcall* DllGetClassObject_t)(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv); 91 | DllGetClassObject_t dynamiDllGetClassObject = (DllGetClassObject_t)GetProcAddress(hdll, "DllGetClassObject"); 92 | if (!dynamiDllGetClassObject) { 93 | //printf("GetProcAddress false!\n"); 94 | MessageBoxW(NULL, L"GetProcAddress", NULL, 0); 95 | return -2; 96 | } 97 | //printf("GetProcAddress !\n"); 98 | IClassFactory* fac = 0; 99 | 100 | dynamiDllGetClassObject(CLSID_OpInterface, IID_IClassFactory, (void**)&fac); 101 | 102 | //IClassFa 103 | //pfun1(&CLSID_OpInterface, riid, (void**)&fac); 104 | if (!fac) { 105 | //printf("DllGetClassObject false!\n"); 106 | MessageBoxW(NULL, L"DllGetClassObject", NULL, 0); 107 | return -3; 108 | } 109 | //printf("DllGetClassObject !\n"); 110 | IOpInterface* op; 111 | //fac->lpVtbl->CreateInstance(fac, NULL, &IID_IOpInterface, (void**)&op); 112 | fac->CreateInstance(NULL, riid, (void**)&op); 113 | //fac->lpVtbl->QueryInterface() 114 | if (!op) { 115 | //printf("CoCreateInstance false!\n"); 116 | MessageBoxW(NULL, L"CoCreateInstance", NULL, 0); 117 | return -4; 118 | } 119 | //printf("CreateInstance !\n"); 120 | *ppv = op; 121 | return S_OK; 122 | } 123 | 124 | HRESULT __stdcall 125 | myCoGetClassObject( 126 | _In_ REFCLSID rclsid, 127 | _In_ DWORD dwClsContext, 128 | _In_opt_ LPVOID pvReserved, 129 | _In_ REFIID riid, 130 | _Outptr_ LPVOID FAR* ppv 131 | ) { 132 | //printf("myCoGetClassObject\n"); 133 | //flaot:在这里如果走原始"oCoGetClassObject"则会失败,找注册表肯定找不到 134 | if (memcmp(&rclsid, &CLSID_OpInterface, sizeof(CLSID_OpInterface)) == 0) { 135 | 136 | HMODULE hdll = LoadLibraryA(dllpathA); 137 | if (!hdll) { 138 | printf("LoadLibraryA false!\n"); 139 | MessageBoxW(NULL, L"LoadLibraryA", NULL, 0); 140 | return -1; 141 | } 142 | typedef HRESULT(__stdcall* DllGetClassObject_t)(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv); 143 | DllGetClassObject_t dynamiDllGetClassObject = (DllGetClassObject_t)GetProcAddress(hdll, "DllGetClassObject"); 144 | if (!dynamiDllGetClassObject) { 145 | MessageBoxW(NULL, L"GetProcAddress", NULL, 0); 146 | return -2; 147 | } 148 | 149 | IClassFactory* fac = 0; 150 | dynamiDllGetClassObject(CLSID_OpInterface, IID_IClassFactory, (void**)&fac); 151 | *ppv = fac; 152 | return S_OK; 153 | } 154 | return oCoGetClassObject(rclsid, dwClsContext, pvReserved, riid, ppv); 155 | } 156 | 157 | HRESULT(__stdcall* oLoadRegTypeLib)(REFGUID rguid, WORD wVerMajor, WORD wVerMinor, 158 | LCID lcid, ITypeLib** pptlib); 159 | HRESULT __stdcall mLoadRegTypeLib(REFGUID rguid, WORD wVerMajor, WORD wVerMinor, 160 | LCID lcid, ITypeLib** pptlib) { 161 | //printf("mLoadRegTypeLib\n"); 162 | /*return memcmp(rguid, &LIBID_opLib, sizeof(LIBID_opLib)) == 0 ? LoadTypeLib(dllpath, pptlib) : 163 | oLoadRegTypeLib(rguid, wVerMajor, wVerMinor, lcid, pptlib);*/ 164 | HRESULT hr = memcmp(&rguid, &LIBID_opLib, sizeof(LIBID_opLib)) == 0 ? LoadTypeLib(dllpathW, pptlib) : 165 | oLoadRegTypeLib(rguid, wVerMajor, wVerMinor, lcid, pptlib); 166 | return hr; 167 | //return oLoadRegTypeLib(rguid, wVerMajor, wVerMinor, lcid, pptlib); 168 | } 169 | 170 | 171 | 172 | int sethook() { 173 | //MessageBoxA(NULL, "sethook", "", 0); 174 | //printf("sethook\n"); 175 | if (MH_Initialize() != MH_OK) { 176 | printf("MH_Initialize false\n"); 177 | return -1; 178 | } 179 | if (MH_CreateHook(&CoCreateInstance, &myCoCreateInstance, (void**)&oCoCreateInstance) != MH_OK) { 180 | printf("MH_CreateHook false \n"); 181 | return -2; 182 | } 183 | if (MH_CreateHook(&CLSIDFromProgID, &myCLSIDFromProgID, (void**)&oCLSIDFromProgID) != MH_OK) { 184 | printf("MH_CreateHook false \n"); 185 | return -3; 186 | } 187 | if (MH_CreateHook(&CoGetClassObject, &myCoGetClassObject, (void**)&oCoGetClassObject) != MH_OK) { 188 | printf("MH_CreateHook false \n"); 189 | return -4; 190 | } 191 | //LoadRegTypeLib 192 | if (MH_CreateHook(&LoadRegTypeLib, &mLoadRegTypeLib, (void**)&oLoadRegTypeLib) != MH_OK) { 193 | printf("MH_CreateHook false \n"); 194 | return -5; 195 | } 196 | if (MH_EnableHook(NULL) != MH_OK) { 197 | //printf("MH_EnableHook false\n"); 198 | return -6; 199 | } 200 | return 1; 201 | 202 | } 203 | 204 | // 这是导出变量的一个示例 205 | //EASYCOM_API int nEasyCom = 0; 206 | 207 | // 这是导出函数的一个示例。 208 | int setupA(const char* path) 209 | { 210 | //std::ifstream fin(path); 211 | // 212 | //if (!fin) { 213 | // return 0;//file not exist 214 | //} 215 | strcpy(dllpathA, path); 216 | wchar_t* m_wchar; 217 | int nlen = strlen(dllpathA); 218 | int len = MultiByteToWideChar(CP_ACP, 0, dllpathA,nlen , NULL, 0); 219 | m_wchar = new wchar_t[len + 1]; 220 | MultiByteToWideChar(CP_ACP, 0, dllpathA, nlen, m_wchar, len); 221 | m_wchar[len] = '\0'; 222 | memcpy(dllpathW, m_wchar, sizeof(wchar_t) * (len + 1)); 223 | delete[]m_wchar; 224 | 225 | 226 | return sethook(); 227 | 228 | 229 | } 230 | 231 | int setupW(const wchar_t* path) { 232 | //std::ifstream fin(path); 233 | 234 | //if (!fin) { 235 | // return 0;//file not exist 236 | //} 237 | int nlen = wcslen(path); 238 | wcscpy(dllpathW, path); 239 | char* m_char; 240 | int len = WideCharToMultiByte(CP_ACP, 0, path, nlen, NULL, 0, NULL, NULL); 241 | m_char = new char[len + 1]; 242 | WideCharToMultiByte(CP_ACP, 0, path, nlen, m_char, len, NULL, NULL); 243 | m_char[len] = '\0'; 244 | strcpy(dllpathA, m_char); 245 | delete[] m_char; 246 | 247 | return sethook(); 248 | 249 | } 250 | -------------------------------------------------------------------------------- /tools/EasyCom.h: -------------------------------------------------------------------------------- 1 |  2 | 3 | #define EASYCOM_API extern "C" __declspec(dllexport) 4 | 5 | 6 | //EASYCOM_API int nEasyCom; 7 | 8 | EASYCOM_API int setupA(const char* path); 9 | EASYCOM_API int setupW(const wchar_t* path); 10 | -------------------------------------------------------------------------------- /tools/dllmain.c: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : 定义 DLL 应用程序的入口点。 2 | #include "framework.h" 3 | 4 | BOOL APIENTRY DllMain( HMODULE hModule, 5 | DWORD ul_reason_for_call, 6 | LPVOID lpReserved 7 | ) 8 | { 9 | switch (ul_reason_for_call) 10 | { 11 | case DLL_PROCESS_ATTACH: 12 | case DLL_THREAD_ATTACH: 13 | case DLL_THREAD_DETACH: 14 | case DLL_PROCESS_DETACH: 15 | break; 16 | } 17 | return TRUE; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tools/framework.h: -------------------------------------------------------------------------------- 1 | // header.h: 标准系统包含文件的包含文件, 2 | // 或特定于项目的包含文件 3 | // 4 | 5 | #pragma once 6 | 7 | //#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 8 | // Windows 头文件 9 | #include 10 | -------------------------------------------------------------------------------- /插件接口无法正常更新删除tlb!.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WallBreaker2/op/3f94fb6616e000bd32ee4018ca94c9e66a37483e/插件接口无法正常更新删除tlb!.txt --------------------------------------------------------------------------------