├── .gitignore ├── LICENSE ├── README.md ├── TrackPointDriver.sln ├── TrackPointDriver_ARM64.ddf ├── TrackPointDriver_x64.ddf ├── TrackPointDriver_x86.ddf ├── appveyor.yml ├── docs └── trackpoint-sensitivity-report.md └── driver ├── SlionTrackPoint.inf ├── Trace.h ├── driver.c ├── driver.rc ├── driver.vcxproj ├── driver.vcxproj.Filters └── moufiltr.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | 352 | driver/RC* 353 | driver/RD* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TrackPointDriver 2 | This is an alternative ThinkPad TrackPoint driver for Windows 3 | offering a reliable TrackPoint scrolling experience. 4 | 5 | # Story 6 | I've been using a couple of [Lenovo ThinkPad USB Keyboard with TrackPoint] for over a decade 7 | and they are still going strong. 8 | The newest [ThinkPad TrackPoint Keyboard II], while pleasant to type on, 9 | has a rather unimpressive layout by comparison. I ruled out upgrading for the time being. 10 | One unique feature I use most on the TrackPoint is scrolling while holding down the middle button. 11 | However with Lenovo [official driver], TrackPoint scrolling is rather unreliable. 12 | On some application it just won't work. 13 | On others like Visual Studio it will work for a while until it won't. 14 | This driver primary goal is therefore to get the scrolling working everywhere, reliably, 15 | exactly like your standard mouse wheel. 16 | 17 | # Feature 18 | TrackPoint scrolling: hold down middle button to scroll vertically or horizontally using your TrackPoint. 19 | 20 | # Download 21 | Available from [slions.net]. 22 | 23 | # Installation 24 | * First install the [official driver] from Lenovo. 25 | You will still need it to be able to adjust sensitivy and other parameters from Windows Mouse Properties settings. 26 | * [Nefarius] kindly signed this driver's latest version. You can skip the next step when using a signed driver. 27 | * Make sure you enable the [installation of unsigned drivers] on you computer. This is best done by running the following command as administrator: `bcdedit /set testsigning on`. 28 | If this is denied because of UEFI Secure Boot and you can’t deactivate it then you won't be able to install that driver until a signed version is available. 29 | * Go to Windows Device Manager. 30 | * Locate your TrackPoint device below "Mice and other pointing devices". 31 | * Right click your TrackPoint device and select "Update driver". 32 | * Click "Browse my computer for drivers". 33 | * Click "Let me pick a list off available drivers on my computer". 34 | * Click "Have Disk…" button. 35 | * "Browse" to this driver location on your computer and select the INF file. 36 | * Select the driver and click "Next". 37 | * Validate various Windows warning messages if needed until installation succeeds. 38 | 39 | # Usage 40 | You can still adjust TrackPoint stick sensitivity as usual from Windows Mouse Properties. 41 | Hold down the middle button and use your TrackPoint for mouse wheel emulation. 42 | It works both vertically and horizontally. 43 | 44 | # Hardware 45 | While designed to work for [Lenovo ThinkPad USB Keyboard with TrackPoint] 46 | this driver could potentially work for other TrackPoint hardware or even any mouse pointer device. 47 | 48 | # Development 49 | 50 | ## prerequisite 51 | After installing Visual Studio 2019 make sure you install the [Windows Driver Kit]. 52 | You may also need to add some missing components through Visual Studio Installer, notably those Spectre-mitigated libs. 53 | 54 | ## Debugging 55 | Use [DebugView] and Enable Verbose Kernel Output from the Capture menu to obtain debug output from a driver debug build. 56 | I have not used actual step-by-step debugging as it requires a more complex setup with an host and a target machine, physical or virtual. 57 | 58 | [Nefarius] enabled WPP tracing. You can use [TraceView] to visualize them. 59 | To enable WPP tracing create the following `DWORD` registry key and set it to 1: 60 | `HKLM\SYSTEM\CurrentControlSet\Services\SlionTrackPoint\Parameters\VerboseOn`. 61 | Reboot your computer and open the `PDB` with [TraceView]. 62 | 63 | # Omissions 64 | Our target hardware can be configured by sending it HID reports. Settings such as TrackPoint sensitivity can thus be changed and possibly read I guess. 65 | However we spared ourselves the task of reverse engineering that configuration protocol. 66 | In fact it turns out using the [official driver] mouse properties page works just fine together with our custom driver. 67 | Nevertheless it's clearly possible to analyze communications between the [official driver] and the hardware using [WireShark] together with [USBPcap]. 68 | Note that [USBPcap] is bundled with [WireShark]. Such a reverse engineering was done for that [Linux driver]. 69 | See [sensitivity report](docs/trackpoint-sensitivity-report.md). 70 | 71 | # Further development 72 | - We could add some configuration options through an UWP application or a [property sheet]. 73 | - Communications with the driver could be done through WMI I guess, see [Microsoft Firefly Driver Sample] for details of such an implementation. 74 | - Driver could be packaged in an installer, I believe there is such a thing as a Visual Studio driver package project. 75 | - Driver and installer could be signed to allow installation on UEFI Secure Boot machine. Though an EV Code Signing Certificate is needed and those ain’t cheap and are only granted to companies apparently. 76 | - To avoid needing such expensive EV Code Signing Certificate we should check if we could implement that driver using User Mode Driver Framework as suggested [there](https://github.com/desowin/usbpcap/issues/117). 77 | 78 | # Conclusion 79 | That was an interesting dip in Windows kernel driver development. 80 | Actually implementing a proper mouse wheel emulation from a mouse driver filter was really straight forward. 81 | That brings the question: why could Lenevo engineers not get this done years ago? Go figure! 82 | 83 | # Resources 84 | * Upstream forks: 85 | * [Invertible USB Mouse Driver Filter Driver] 86 | * [Microsoft Firefly Driver Sample] 87 | * Lenovo ThinkPad USB Keyboard with TrackPoint: 88 | * [Official site] 89 | * [Official driver] 90 | * [User guide] 91 | * [Linux driver] for the same hardware 92 | 93 | [Linux driver]: https://github.com/bseibold/tpkbdctl 94 | [user guide]: http://download.lenovo.com/ibmdl/pub/pc/pccbbs/options_iso/45k1918_ug.pdf 95 | [Official site]: https://support.lenovo.com/us/en/solutions/pd005137-thinkpad-usb-keyboard-with-trackpoint-overview 96 | [Official driver]: https://download.lenovo.com/ibmdl/pub/pc/pccbbs/options/thinkpad_usb_keyboard_with_trackpoint_112.exe 97 | [Lenovo ThinkPad USB Keyboard with TrackPoint]: https://support.lenovo.com/us/en/solutions/pd005137-thinkpad-usb-keyboard-with-trackpoint-overview 98 | [ThinkPad TrackPoint Keyboard II]: https://www.lenovo.com/us/en/accessories-and-monitors/keyboards-and-mice/keyboards/KBD-BO-TrackPoint-KBD-US-English/p/4Y40X49493 99 | [Windows Driver Kit]: https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk 100 | [Invertible USB Mouse Driver Filter Driver]: https://github.com/tthk/Invertible-USB-Mouse-Driver-Filter-Driver 101 | [Microsoft Firefly Driver Sample]: https://github.com/microsoft/Windows-driver-samples/tree/master/hid/firefly 102 | [WireShark]: https://www.wireshark.org 103 | [USBPcap]: https://desowin.org/usbpcap/ 104 | [DebugView]: https://docs.microsoft.com/en-gb/sysinternals/downloads/debugview 105 | [installation of unsigned drivers]: https://www.maketecheasier.com/install-unsigned-drivers-windows10/ 106 | [slions.net]: https://slions.net/resources/trackpoint-driver.12 107 | [property sheet]: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/hh127447(v=vs.85) 108 | [Nefarius]: https://github.com/nefarius 109 | [TraceView]: https://www.mgtek.com/traceview 110 | -------------------------------------------------------------------------------- /TrackPointDriver.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.10.35013.160 5 | MinimumVisualStudioVersion = 12.0 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Driver", "Driver", "{484B7AA0-E373-45FD-8FA2-C666B5167541}" 7 | ProjectSection(SolutionItems) = preProject 8 | README.md = README.md 9 | docs\trackpoint-sensitivity-report.md = docs\trackpoint-sensitivity-report.md 10 | EndProjectSection 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SlionTrackPoint", "driver\driver.vcxproj", "{FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|ARM64 = Debug|ARM64 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|ARM64 = Release|ARM64 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|ARM64.ActiveCfg = Debug|ARM64 25 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|ARM64.Build.0 = Debug|ARM64 26 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|ARM64.Deploy.0 = Debug|ARM64 27 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x64.ActiveCfg = Debug|x64 28 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x64.Build.0 = Debug|x64 29 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x64.Deploy.0 = Debug|x64 30 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x86.ActiveCfg = Debug|Win32 31 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x86.Build.0 = Debug|Win32 32 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Debug|x86.Deploy.0 = Debug|Win32 33 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|ARM64.ActiveCfg = Release|ARM64 34 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|ARM64.Build.0 = Release|ARM64 35 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|ARM64.Deploy.0 = Release|ARM64 36 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x64.ActiveCfg = Release|x64 37 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x64.Build.0 = Release|x64 38 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x64.Deploy.0 = Release|x64 39 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x86.ActiveCfg = Release|Win32 40 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x86.Build.0 = Release|Win32 41 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5}.Release|x86.Deploy.0 = Release|Win32 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(NestedProjects) = preSolution 47 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5} = {484B7AA0-E373-45FD-8FA2-C666B5167541} 48 | EndGlobalSection 49 | GlobalSection(ExtensibilityGlobals) = postSolution 50 | SolutionGuid = {B582DB81-3D6C-4BA4-95C0-DA208F6BD70C} 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /TrackPointDriver_ARM64.ddf: -------------------------------------------------------------------------------- 1 | ; SlionTrackPoint cab file for attestation submission 2 | .OPTION EXPLICIT 3 | .Set CabinetFileCountThreshold=0 4 | .Set FolderFileCountThreshold=0 5 | .Set FolderSizeThreshold=0 6 | .Set MaxCabinetSize=0 7 | .Set MaxDiskFileCount=0 8 | .Set MaxDiskSize=0 9 | .Set CompressionType=MSZIP 10 | .Set Cabinet=on 11 | .Set Compress=on 12 | ; ARM64 13 | .Set CabinetNameTemplate=SlionTrackPoint_ARM64.cab 14 | .Set DestinationDir=SlionTrackPoint_ARM64 15 | LICENSE 16 | bin\ARM64\SlionTrackPoint.pdb 17 | bin\ARM64\SlionTrackPoint\SlionTrackPoint.inf 18 | bin\ARM64\SlionTrackPoint\SlionTrackPoint.sys -------------------------------------------------------------------------------- /TrackPointDriver_x64.ddf: -------------------------------------------------------------------------------- 1 | ; SlionTrackPoint cab file for attestation submission 2 | .OPTION EXPLICIT 3 | .Set CabinetFileCountThreshold=0 4 | .Set FolderFileCountThreshold=0 5 | .Set FolderSizeThreshold=0 6 | .Set MaxCabinetSize=0 7 | .Set MaxDiskFileCount=0 8 | .Set MaxDiskSize=0 9 | .Set CompressionType=MSZIP 10 | .Set Cabinet=on 11 | .Set Compress=on 12 | ; x64 13 | .Set CabinetNameTemplate=SlionTrackPoint_x64.cab 14 | .Set DestinationDir=SlionTrackPoint_x64 15 | LICENSE 16 | bin\x64\SlionTrackPoint.pdb 17 | bin\x64\SlionTrackPoint\SlionTrackPoint.inf 18 | bin\x64\SlionTrackPoint\SlionTrackPoint.sys -------------------------------------------------------------------------------- /TrackPointDriver_x86.ddf: -------------------------------------------------------------------------------- 1 | ; SlionTrackPoint cab file for attestation submission 2 | .OPTION EXPLICIT 3 | .Set CabinetFileCountThreshold=0 4 | .Set FolderFileCountThreshold=0 5 | .Set FolderSizeThreshold=0 6 | .Set MaxCabinetSize=0 7 | .Set MaxDiskFileCount=0 8 | .Set MaxDiskSize=0 9 | .Set CompressionType=MSZIP 10 | .Set Cabinet=on 11 | .Set Compress=on 12 | ; x86 13 | .Set CabinetNameTemplate=SlionTrackPoint_x86.cab 14 | .Set DestinationDir=SlionTrackPoint_x86 15 | LICENSE 16 | bin\x86\SlionTrackPoint.pdb 17 | bin\x86\SlionTrackPoint\SlionTrackPoint.inf 18 | bin\x86\SlionTrackPoint\SlionTrackPoint.sys -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build}.0 2 | image: Visual Studio 2019 3 | platform: 4 | - x86 5 | - x64 6 | - ARM64 7 | configuration: 8 | - Release 9 | install: 10 | - cmd: git submodule -q update --init 11 | before_build: 12 | - cmd: dotnet tool install --global Nefarius.Tools.Vpatch 13 | - cmd: vpatch --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\driver\driver.vcxproj" --vcxproj.inf-time-stamp 14 | - cmd: vpatch --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\driver\driver.rc" --resource.file-version --resource.product-version 15 | build: 16 | project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln 17 | after_build: 18 | - cmd: makecab.exe /f .\TrackPointDriver_%PLATFORM%.ddf 19 | artifacts: 20 | - path: 'disk1\*.cab' 21 | - path: 'bin**\SlionTrackPoint\*.inf' 22 | - path: 'bin**\SlionTrackPoint\*.cat' 23 | - path: 'bin**\SlionTrackPoint\*.sys' 24 | - path: 'bin**\*.pdb' 25 | deploy: 26 | - provider: Environment 27 | name: BUILDBOT 28 | on: 29 | appveyor_repo_tag: true -------------------------------------------------------------------------------- /docs/trackpoint-sensitivity-report.md: -------------------------------------------------------------------------------- 1 | Those are USBHID SET_REPORT Request when changing TrackPoint Stick sensitivity. 2 | 3 | Only thing that's changing is: 4 | - IRPID which is bytes 2 to 9 which is a pointer to something so that's to be expected I guess. 5 | - Byte marked by ^^ is most certainly the sensitivity value being sent to our TrackPoint keyboard. 6 | 7 | Min sensitivity: 8 | ``` 9 | ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ 10 | 0000 1c 00 40 91 9c 49 06 8d ff ff 00 00 00 00 1b 00 11 | 0010 00 01 00 07 00 00 02 0d 00 00 00 00 21 09 04 03 12 | 0020 01 00 05 00 04 6a 03 66 38 13 | ^^ 14 | ``` 15 | 16 | Max sensitivity: 17 | ``` 18 | ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ 19 | 0000 1c 00 a0 f7 b0 3e 06 8d ff ff 00 00 00 00 1b 00 20 | 0010 00 01 00 07 00 00 02 0d 00 00 00 00 21 09 04 03 21 | 0020 01 00 05 00 04 6a 03 fc 38 22 | ^^ 23 | ``` 24 | 25 | Back to normal: 26 | ``` 27 | ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ ˇˇ 28 | 0000 1c 00 10 20 5f 41 06 8d ff ff 00 00 00 00 1b 00 29 | 0010 00 01 00 07 00 00 02 0d 00 00 00 00 21 09 04 03 30 | 0020 01 00 05 00 04 6a 03 b3 38 31 | ^^ 32 | ``` 33 | -------------------------------------------------------------------------------- /driver/SlionTrackPoint.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slion/TrackPointDriver/6e7eb9c1e26416937adf0bac0b203a6f7b8c3d38/driver/SlionTrackPoint.inf -------------------------------------------------------------------------------- /driver/Trace.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | Trace.h 6 | 7 | Abstract: 8 | 9 | Header file for the debug tracing related function definitions and macros. 10 | 11 | Environment: 12 | 13 | Kernel mode 14 | 15 | --*/ 16 | 17 | // 18 | // Define the tracing flags. 19 | // 20 | // Tracing GUID - e60faf57-d4d2-4de5-99dd-42acc10e1614 21 | // 22 | 23 | #define WPP_CONTROL_GUIDS \ 24 | WPP_DEFINE_CONTROL_GUID( \ 25 | SlionTrackPointTraceGuid, (e60faf57,d4d2,4de5,99dd,42acc10e1614), \ 26 | \ 27 | WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ 28 | WPP_DEFINE_BIT(TRACE_DRIVER) \ 29 | WPP_DEFINE_BIT(TRACE_DEVICE) \ 30 | ) 31 | 32 | #define WPP_FLAG_LEVEL_LOGGER(flag, level) \ 33 | WPP_LEVEL_LOGGER(flag) 34 | 35 | #define WPP_FLAG_LEVEL_ENABLED(flag, level) \ 36 | (WPP_LEVEL_ENABLED(flag) && \ 37 | WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) 38 | 39 | #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ 40 | WPP_LEVEL_LOGGER(flags) 41 | 42 | #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ 43 | (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) 44 | 45 | // 46 | // WPP orders static parameters before dynamic parameters. To support the Trace function 47 | // defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to 48 | // reorder the arguments to what the .tpl configuration file expects. 49 | // 50 | #define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags) 51 | #define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags) 52 | 53 | 54 | // 55 | // This comment block is scanned by the trace preprocessor to define our 56 | // Trace function. 57 | // 58 | // USEPREFIX and USESUFFIX strip all trailing whitespace, so we need to surround 59 | // FuncExit messages with brackets 60 | // 61 | // begin_wpp config 62 | // FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); 63 | // FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); 64 | // FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 65 | // FUNC FuncEntryArguments{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...); 66 | // FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...); 67 | // FUNC FuncExitVoid{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 68 | // FUNC TraceError{LEVEL=TRACE_LEVEL_ERROR}(FLAGS, MSG, ...); 69 | // FUNC TraceInformation{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS, MSG, ...); 70 | // FUNC TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...); 71 | // FUNC FuncExitNoReturn{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 72 | // USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> Entry"); 73 | // USEPREFIX(FuncEntryArguments, "%!STDPREFIX! [%!FUNC!] --> Entry <"); 74 | // USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <-- Exit <"); 75 | // USESUFFIX(FuncExit, ">"); 76 | // USEPREFIX(FuncExitVoid, "%!STDPREFIX! [%!FUNC!] <-- Exit"); 77 | // USEPREFIX(TraceError, "%!STDPREFIX! [%!FUNC!] ERROR:"); 78 | // USEPREFIX(TraceEvents, "%!STDPREFIX! [%!FUNC!] "); 79 | // USEPREFIX(TraceInformation, "%!STDPREFIX! [%!FUNC!] "); 80 | // USEPREFIX(TraceVerbose, "%!STDPREFIX! [%!FUNC!] "); 81 | // USEPREFIX(FuncExitNoReturn, "%!STDPREFIX! [%!FUNC!] <--"); 82 | // end_wpp 83 | -------------------------------------------------------------------------------- /driver/driver.c: -------------------------------------------------------------------------------- 1 | #include "moufiltr.h" 2 | #include 3 | #include "driver.tmh" 4 | 5 | #ifdef ALLOC_PRAGMA 6 | #pragma alloc_text (INIT, DriverEntry) 7 | #pragma alloc_text (PAGE, MouFilter_EvtDeviceAdd) 8 | #pragma alloc_text (PAGE, MouFilter_EvtIoInternalDeviceControl) 9 | #pragma alloc_text (PAGE, MouFilter_EvtDriverContextCleanup) 10 | #endif 11 | 12 | #pragma warning(push) 13 | #pragma warning(disable:4055) // type case from PVOID to PSERVICE_CALLBACK_ROUTINE 14 | #pragma warning(disable:4152) // function/data pointer conversion in expression 15 | 16 | NTSTATUS 17 | DriverEntry( 18 | IN PDRIVER_OBJECT DriverObject, 19 | IN PUNICODE_STRING RegistryPath 20 | ) 21 | /*++ 22 | Routine Description: 23 | 24 | Installable driver initialization entry point. 25 | This entry point is called directly by the I/O system. 26 | 27 | --*/ 28 | { 29 | // 30 | // Initialize WPP Tracing 31 | // 32 | WPP_INIT_TRACING(DriverObject, RegistryPath); 33 | 34 | WDF_DRIVER_CONFIG config; 35 | NTSTATUS status; 36 | WDF_OBJECT_ATTRIBUTES attributes; 37 | 38 | FuncEntry(TRACE_DRIVER); 39 | 40 | // Initialize driver config to control the attributes that 41 | // are global to the driver. Note that framework by default 42 | // provides a driver unload routine. If you create any resources 43 | // in the DriverEntry and want to be cleaned in driver unload, 44 | // you can override that by manually setting the EvtDriverUnload in the 45 | // config structure. In general xxx_CONFIG_INIT macros are provided to 46 | // initialize most commonly used members. 47 | 48 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 49 | attributes.EvtCleanupCallback = MouFilter_EvtDriverContextCleanup; 50 | 51 | WDF_DRIVER_CONFIG_INIT( 52 | &config, 53 | MouFilter_EvtDeviceAdd 54 | ); 55 | 56 | // 57 | // Create a framework driver object to represent our driver. 58 | // 59 | status = WdfDriverCreate(DriverObject, 60 | RegistryPath, 61 | WDF_NO_OBJECT_ATTRIBUTES, 62 | &config, 63 | WDF_NO_HANDLE); // hDriver optional 64 | if (!NT_SUCCESS(status)) { 65 | TraceEvents( 66 | TRACE_LEVEL_ERROR, 67 | TRACE_DRIVER, 68 | "WdfDriverCreate failed with status %!STATUS!", 69 | status 70 | ); 71 | WPP_CLEANUP(DriverObject); 72 | return status; 73 | } 74 | 75 | FuncExit(TRACE_DRIVER, "status=%!STATUS!", status); 76 | 77 | return status; 78 | } 79 | 80 | NTSTATUS 81 | MouFilter_EvtDeviceAdd( 82 | IN WDFDRIVER Driver, 83 | IN PWDFDEVICE_INIT DeviceInit 84 | ) 85 | /*++ 86 | Routine Description: 87 | 88 | EvtDeviceAdd is called by the framework in response to AddDevice 89 | call from the PnP manager. Here you can query the device properties 90 | using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based 91 | on that, decide to create a filter device object and attach to the 92 | function stack. 93 | 94 | If you are not interested in filtering this particular instance of the 95 | device, you can just return STATUS_SUCCESS without creating a framework 96 | device. 97 | 98 | Arguments: 99 | 100 | Driver - Handle to a framework driver object created in DriverEntry 101 | 102 | DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. 103 | 104 | Return Value: 105 | 106 | NTSTATUS 107 | 108 | --*/ 109 | { 110 | WDF_OBJECT_ATTRIBUTES deviceAttributes; 111 | NTSTATUS status; 112 | WDFDEVICE hDevice; 113 | WDF_IO_QUEUE_CONFIG ioQueueConfig; 114 | 115 | UNREFERENCED_PARAMETER(Driver); 116 | 117 | PAGED_CODE(); 118 | 119 | FuncEntry(TRACE_DRIVER); 120 | 121 | // 122 | // Tell the framework that you are filter driver. Framework 123 | // takes care of inheriting all the device flags & characteristics 124 | // from the lower device you are attaching to. 125 | // 126 | WdfFdoInitSetFilter(DeviceInit); 127 | 128 | WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_MOUSE); 129 | 130 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, 131 | DEVICE_EXTENSION); 132 | 133 | 134 | // 135 | // Create a framework device object. This call will in turn create 136 | // a WDM device object, attach to the lower stack and set the 137 | // appropriate flags and attributes. 138 | // 139 | status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); 140 | if (!NT_SUCCESS(status)) { 141 | DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); 142 | return status; 143 | } 144 | 145 | 146 | // 147 | // Configure the default queue to be Parallel. Do not use sequential queue 148 | // if this driver is going to be filtering PS2 ports because it can lead to 149 | // deadlock. The PS2 port driver sends a request to the top of the stack when it 150 | // receives an ioctl request and waits for it to be completed. If you use a 151 | // a sequential queue, this request will be stuck in the queue because of the 152 | // outstanding ioctl request sent earlier to the port driver. 153 | // 154 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, 155 | WdfIoQueueDispatchParallel); 156 | 157 | // 158 | // Framework by default creates non-power managed queues for 159 | // filter drivers. 160 | // 161 | ioQueueConfig.EvtIoInternalDeviceControl = MouFilter_EvtIoInternalDeviceControl; 162 | 163 | status = WdfIoQueueCreate(hDevice, 164 | &ioQueueConfig, 165 | WDF_NO_OBJECT_ATTRIBUTES, 166 | WDF_NO_HANDLE // pointer to default queue 167 | ); 168 | if (!NT_SUCCESS(status)) { 169 | TraceError( 170 | TRACE_DRIVER, 171 | "WdfIoQueueCreate failed with status %!STATUS!", 172 | status 173 | ); 174 | return status; 175 | } 176 | 177 | FuncExit(TRACE_DRIVER, "status=%!STATUS!", status); 178 | 179 | return status; 180 | } 181 | 182 | 183 | 184 | VOID 185 | MouFilter_DispatchPassThrough( 186 | _In_ WDFREQUEST Request, 187 | _In_ WDFIOTARGET Target 188 | ) 189 | /*++ 190 | Routine Description: 191 | 192 | Passes a request on to the lower driver. 193 | 194 | 195 | --*/ 196 | { 197 | // 198 | // Pass the IRP to the target 199 | // 200 | 201 | WDF_REQUEST_SEND_OPTIONS options; 202 | BOOLEAN ret; 203 | NTSTATUS status = STATUS_SUCCESS; 204 | 205 | FuncEntry(TRACE_DRIVER); 206 | 207 | // 208 | // We are not interested in post processing the IRP so 209 | // fire and forget. 210 | // 211 | WDF_REQUEST_SEND_OPTIONS_INIT(&options, 212 | WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); 213 | 214 | ret = WdfRequestSend(Request, Target, &options); 215 | 216 | if (ret == FALSE) { 217 | status = WdfRequestGetStatus(Request); 218 | TraceError( 219 | TRACE_DRIVER, 220 | "WdfRequestSend failed with status %!STATUS!", 221 | status 222 | ); 223 | WdfRequestComplete(Request, status); 224 | } 225 | 226 | FuncExitNoReturn(TRACE_DRIVER); 227 | } 228 | 229 | VOID 230 | MouFilter_EvtIoInternalDeviceControl( 231 | IN WDFQUEUE Queue, 232 | IN WDFREQUEST Request, 233 | IN size_t OutputBufferLength, 234 | IN size_t InputBufferLength, 235 | IN ULONG IoControlCode 236 | ) 237 | /*++ 238 | 239 | Routine Description: 240 | 241 | This routine is the dispatch routine for internal device control requests. 242 | There are two specific control codes that are of interest: 243 | 244 | IOCTL_INTERNAL_MOUSE_CONNECT: 245 | Store the old context and function pointer and replace it with our own. 246 | This makes life much simpler than intercepting IRPs sent by the RIT and 247 | modifying them on the way back up. 248 | 249 | IOCTL_INTERNAL_I8042_HOOK_MOUSE: 250 | Add in the necessary function pointers and context values so that we can 251 | alter how the ps/2 mouse is initialized. 252 | 253 | NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_MOUSE is *NOT* necessary if 254 | all you want to do is filter MOUSE_INPUT_DATAs. You can remove 255 | the handling code and all related device extension fields and 256 | functions to conserve space. 257 | 258 | 259 | --*/ 260 | { 261 | 262 | PDEVICE_EXTENSION devExt; 263 | PCONNECT_DATA connectData; 264 | PINTERNAL_I8042_HOOK_MOUSE hookMouse; 265 | NTSTATUS status = STATUS_SUCCESS; 266 | WDFDEVICE hDevice; 267 | size_t length; 268 | 269 | UNREFERENCED_PARAMETER(OutputBufferLength); 270 | UNREFERENCED_PARAMETER(InputBufferLength); 271 | 272 | PAGED_CODE(); 273 | 274 | FuncEntry(TRACE_DRIVER); 275 | 276 | hDevice = WdfIoQueueGetDevice(Queue); 277 | devExt = FilterGetData(hDevice); 278 | 279 | switch (IoControlCode) { 280 | 281 | // 282 | // Connect a mouse class device driver to the port driver. 283 | // 284 | case IOCTL_INTERNAL_MOUSE_CONNECT: 285 | // 286 | // Only allow one connection. 287 | // 288 | if (devExt->UpperConnectData.ClassService != NULL) { 289 | status = STATUS_SHARING_VIOLATION; 290 | break; 291 | } 292 | 293 | // 294 | // Copy the connection parameters to the device extension. 295 | // 296 | status = WdfRequestRetrieveInputBuffer(Request, 297 | sizeof(CONNECT_DATA), 298 | &connectData, 299 | &length); 300 | if (!NT_SUCCESS(status)) { 301 | TraceError( 302 | TRACE_DRIVER, 303 | "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", 304 | status 305 | ); 306 | break; 307 | } 308 | 309 | 310 | devExt->UpperConnectData = *connectData; 311 | 312 | // 313 | // Hook into the report chain. Everytime a mouse packet is reported to 314 | // the system, MouFilter_ServiceCallback will be called 315 | // 316 | connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice); 317 | connectData->ClassService = MouFilter_ServiceCallback; 318 | 319 | break; 320 | 321 | // 322 | // Disconnect a mouse class device driver from the port driver. 323 | // 324 | case IOCTL_INTERNAL_MOUSE_DISCONNECT: 325 | 326 | // 327 | // Clear the connection parameters in the device extension. 328 | // 329 | // devExt->UpperConnectData.ClassDeviceObject = NULL; 330 | // devExt->UpperConnectData.ClassService = NULL; 331 | 332 | status = STATUS_NOT_IMPLEMENTED; 333 | break; 334 | 335 | // 336 | // Attach this driver to the initialization and byte processing of the 337 | // i8042 (ie PS/2) mouse. This is only necessary if you want to do PS/2 338 | // specific functions, otherwise hooking the CONNECT_DATA is sufficient 339 | // 340 | case IOCTL_INTERNAL_I8042_HOOK_MOUSE: 341 | 342 | TraceVerbose( 343 | TRACE_DRIVER, 344 | "hook mouse received!" 345 | ); 346 | 347 | // Get the input buffer from the request 348 | // (Parameters.DeviceIoControl.Type3InputBuffer) 349 | // 350 | status = WdfRequestRetrieveInputBuffer(Request, 351 | sizeof(INTERNAL_I8042_HOOK_MOUSE), 352 | &hookMouse, 353 | &length); 354 | if (!NT_SUCCESS(status)) { 355 | TraceError( 356 | TRACE_DRIVER, 357 | "WdfRequestRetrieveInputBuffer failed with status %!STATUS!", 358 | status 359 | ); 360 | break; 361 | } 362 | 363 | // 364 | // Set isr routine and context and record any values from above this driver 365 | // 366 | devExt->UpperContext = hookMouse->Context; 367 | hookMouse->Context = (PVOID)devExt; 368 | 369 | if (hookMouse->IsrRoutine) { 370 | devExt->UpperIsrHook = hookMouse->IsrRoutine; 371 | } 372 | hookMouse->IsrRoutine = (PI8042_MOUSE_ISR)MouFilter_IsrHook; 373 | 374 | // 375 | // Store all of the other functions we might need in the future 376 | // 377 | devExt->IsrWritePort = hookMouse->IsrWritePort; 378 | devExt->CallContext = hookMouse->CallContext; 379 | devExt->QueueMousePacket = hookMouse->QueueMousePacket; 380 | 381 | status = STATUS_SUCCESS; 382 | break; 383 | 384 | // 385 | // Might want to capture this in the future. For now, then pass it down 386 | // the stack. These queries must be successful for the RIT to communicate 387 | // with the mouse. 388 | // 389 | case IOCTL_MOUSE_QUERY_ATTRIBUTES: 390 | default: 391 | break; 392 | } 393 | 394 | if (!NT_SUCCESS(status)) { 395 | WdfRequestComplete(Request, status); 396 | return; 397 | } 398 | 399 | MouFilter_DispatchPassThrough(Request, WdfDeviceGetIoTarget(hDevice)); 400 | 401 | FuncExitNoReturn(TRACE_DRIVER); 402 | } 403 | 404 | 405 | BOOLEAN 406 | MouFilter_IsrHook( 407 | PVOID DeviceExtension, 408 | PMOUSE_INPUT_DATA CurrentInput, 409 | POUTPUT_PACKET CurrentOutput, 410 | UCHAR StatusByte, 411 | PUCHAR DataByte, 412 | PBOOLEAN ContinueProcessing, 413 | PMOUSE_STATE MouseState, 414 | PMOUSE_RESET_SUBSTATE ResetSubState 415 | ) 416 | /*++ 417 | 418 | Remarks: 419 | i8042prt specific code, if you are writing a packet only filter driver, you 420 | can remove this function 421 | 422 | Arguments: 423 | 424 | DeviceExtension - Our context passed during IOCTL_INTERNAL_I8042_HOOK_MOUSE 425 | 426 | CurrentInput - Current input packet being formulated by processing all the 427 | interrupts 428 | 429 | CurrentOutput - Current list of bytes being written to the mouse or the 430 | i8042 port. 431 | 432 | StatusByte - Byte read from I/O port 60 when the interrupt occurred 433 | 434 | DataByte - Byte read from I/O port 64 when the interrupt occurred. 435 | This value can be modified and i8042prt will use this value 436 | if ContinueProcessing is TRUE 437 | 438 | ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of 439 | the interrupt. If FALSE, i8042prt will return from the 440 | interrupt after this function returns. Also, if FALSE, 441 | it is this functions responsibilityt to report the input 442 | packet via the function provided in the hook IOCTL or via 443 | queueing a DPC within this driver and calling the 444 | service callback function acquired from the connect IOCTL 445 | 446 | Return Value: 447 | 448 | Status is returned. 449 | 450 | --+*/ 451 | { 452 | PDEVICE_EXTENSION devExt; 453 | BOOLEAN retVal = TRUE; 454 | 455 | FuncEntry(TRACE_DRIVER); 456 | 457 | devExt = DeviceExtension; 458 | 459 | if (devExt->UpperIsrHook) { 460 | retVal = (*devExt->UpperIsrHook) (devExt->UpperContext, 461 | CurrentInput, 462 | CurrentOutput, 463 | StatusByte, 464 | DataByte, 465 | ContinueProcessing, 466 | MouseState, 467 | ResetSubState 468 | ); 469 | 470 | if (!retVal || !(*ContinueProcessing)) { 471 | 472 | FuncExit(TRACE_DRIVER, "retVal=%d", retVal); 473 | return retVal; 474 | } 475 | } 476 | 477 | *ContinueProcessing = TRUE; 478 | 479 | FuncExit(TRACE_DRIVER, "retVal=%d", retVal); 480 | 481 | return retVal; 482 | } 483 | 484 | 485 | 486 | VOID 487 | MouFilter_ServiceCallback( 488 | IN PDEVICE_OBJECT DeviceObject, 489 | IN PMOUSE_INPUT_DATA InputDataStart, 490 | IN PMOUSE_INPUT_DATA InputDataEnd, 491 | IN OUT PULONG InputDataConsumed 492 | ) 493 | /*++ 494 | 495 | Routine Description: 496 | 497 | Called when there are mouse packets to report to the RIT. You can do 498 | anything you like to the packets. For instance: 499 | 500 | o Drop a packet altogether 501 | o Mutate the contents of a packet 502 | o Insert packets into the stream 503 | 504 | Arguments: 505 | 506 | DeviceObject - Context passed during the connect IOCTL 507 | 508 | InputDataStart - First packet to be reported 509 | 510 | InputDataEnd - One past the last packet to be reported. Total number of 511 | packets is equal to InputDataEnd - InputDataStart 512 | 513 | InputDataConsumed - Set to the total number of packets consumed by the RIT 514 | (via the function pointer we replaced in the connect 515 | IOCTL) 516 | 517 | Return Value: 518 | 519 | Status is returned. 520 | 521 | --*/ 522 | { 523 | FuncEntry(TRACE_DRIVER); 524 | 525 | // Track state of our middle button 526 | static BOOLEAN middleButtonDown = FALSE; 527 | PDEVICE_EXTENSION devExt; 528 | WDFDEVICE hDevice; 529 | 530 | hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject); 531 | 532 | devExt = FilterGetData(hDevice); 533 | // 534 | // UpperConnectData must be called at DISPATCH 535 | // 536 | 537 | for (PMOUSE_INPUT_DATA InputData = InputDataStart; InputData < InputDataEnd; ++InputData) { 538 | //DebugPrint(("KTT:MouseButtons : %#010x\n", InputData->Buttons)); 539 | 540 | 541 | // Check if middle button went up 542 | if (InputData->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) { 543 | TraceVerbose( 544 | TRACE_DRIVER, 545 | "KTT:MiddleButton: DOWN" 546 | ); 547 | middleButtonDown = TRUE; 548 | // Filter out middle button 549 | InputData->ButtonFlags &= ~MOUSE_MIDDLE_BUTTON_DOWN; 550 | } 551 | 552 | // Check if middle button went up 553 | if (InputData->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) { 554 | TraceVerbose( 555 | TRACE_DRIVER, 556 | "KTT:MiddleButton: UP" 557 | ); 558 | middleButtonDown = FALSE; 559 | // Filter out middle button actions 560 | InputData->ButtonFlags &= ~MOUSE_MIDDLE_BUTTON_UP; 561 | } 562 | 563 | 564 | // If middle button is down start scrolling then 565 | if (middleButtonDown) 566 | { 567 | TraceVerbose( 568 | TRACE_DRIVER, 569 | "KTT:Scrolling: %d , %d", 570 | InputData->LastX, InputData->LastY 571 | ); 572 | 573 | // Can't do both horizontal and vertical scroll without injecting data and I'm not sure how to do that 574 | // For the time being we just do one or the other but not both at the same time and that's just ok anyway. 575 | if (abs(InputData->LastY) >= abs(InputData->LastX)) 576 | { 577 | // Scrolling vertically 578 | InputData->ButtonFlags |= MOUSE_WHEEL; 579 | // Square of our offset actually provides a good acceleration effect 580 | InputData->ButtonData = (USHORT)-(InputData->LastY * abs(InputData->LastY)); 581 | } 582 | else 583 | { 584 | // Scrolling horizontally 585 | InputData->ButtonFlags |= MOUSE_HWHEEL; 586 | // Square of our offset actually provides a good acceleration effect 587 | InputData->ButtonData = (USHORT)(InputData->LastX * abs(InputData->LastX)); 588 | } 589 | 590 | // Cancel all actual mouse move 591 | InputData->LastY = 0; 592 | InputData->LastX = 0; 593 | } 594 | } 595 | 596 | // I guess that's passing on our filtered data input 597 | // We could use that to do some injection maybe? Yes that's what it says in the function doc above :) 598 | (*(PSERVICE_CALLBACK_ROUTINE)devExt->UpperConnectData.ClassService)( 599 | devExt->UpperConnectData.ClassDeviceObject, 600 | InputDataStart, 601 | InputDataEnd, 602 | InputDataConsumed 603 | ); 604 | 605 | FuncExitNoReturn(TRACE_DRIVER); 606 | } 607 | 608 | #pragma warning(pop) 609 | 610 | VOID 611 | MouFilter_EvtDriverContextCleanup( 612 | _In_ WDFOBJECT DriverObject 613 | ) 614 | /*++ 615 | Routine Description: 616 | 617 | Free all the resources allocated in DriverEntry. 618 | 619 | Arguments: 620 | 621 | DriverObject - handle to a WDF Driver object. 622 | 623 | Return Value: 624 | 625 | VOID. 626 | 627 | --*/ 628 | { 629 | UNREFERENCED_PARAMETER(DriverObject); 630 | 631 | PAGED_CODE(); 632 | 633 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); 634 | 635 | // 636 | // Stop WPP Tracing 637 | // 638 | WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); 639 | } 640 | -------------------------------------------------------------------------------- /driver/driver.rc: -------------------------------------------------------------------------------- 1 | // 2 | // Include the necessary resources 3 | // 4 | #include 5 | #include 6 | 7 | #ifdef RC_INVOKED 8 | 9 | // 10 | // Set up debug information 11 | // 12 | #if DBG 13 | #define VER_DBG VS_FF_DEBUG 14 | #else 15 | #define VER_DBG 0 16 | #endif 17 | 18 | // ------- version info ------------------------------------------------------- 19 | 20 | VS_VERSION_INFO VERSIONINFO 21 | FILEVERSION 1,0,0,1 22 | PRODUCTVERSION 1,0,0,1 23 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 24 | FILEFLAGS VER_DBG 25 | FILEOS VOS_NT 26 | FILETYPE VFT_DRV 27 | FILESUBTYPE VFT2_DRV_SYSTEM 28 | BEGIN 29 | BLOCK "StringFileInfo" 30 | BEGIN 31 | BLOCK "040904b0" 32 | BEGIN 33 | VALUE "Comments", "ThinkPad USB TrackPoint Filter by Slions" 34 | VALUE "CompanyName", "Nefarius Software Solutions e.U." 35 | VALUE "FileDescription", "ThinkPad USB TrackPoint Filter by Slions" 36 | VALUE "FileVersion", "1.0.0.1" 37 | VALUE "InternalName", "ThinkPad USB TrackPoint Filter by Slions" 38 | VALUE "LegalCopyright", "(C) 2022 Nefarius Software Solutions e.U." 39 | VALUE "OriginalFilename", "SlionTrackPoint.sys" 40 | VALUE "ProductName", "ThinkPad USB TrackPoint Filter by Slions" 41 | VALUE "ProductVersion", "1.0.0.1" 42 | END 43 | END 44 | BLOCK "VarFileInfo" 45 | BEGIN 46 | VALUE "Translation", 0x0409,1200 47 | END 48 | END 49 | #endif -------------------------------------------------------------------------------- /driver/driver.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | {FF968AD9-B8FF-450D-93A0-4CC5AC2B49B5} 31 | $(MSBuildProjectName) 32 | 1 33 | Debug 34 | Win32 35 | {2DD1A137-CFE3-476C-B434-CE31733A7325} 36 | SlionTrackPoint 37 | $(LatestTargetPlatformVersion) 38 | 39 | 40 | 41 | Windows10 42 | False 43 | Universal 44 | KMDF 45 | WindowsKernelModeDriver10.0 46 | Driver 47 | Off 48 | 49 | 50 | Windows10 51 | False 52 | Universal 53 | KMDF 54 | WindowsKernelModeDriver10.0 55 | Driver 56 | Off 57 | 58 | 59 | Windows10 60 | True 61 | Universal 62 | KMDF 63 | WindowsKernelModeDriver10.0 64 | Driver 65 | 66 | 67 | Windows10 68 | True 69 | Universal 70 | KMDF 71 | WindowsKernelModeDriver10.0 72 | Driver 73 | 74 | 75 | Windows10 76 | False 77 | Universal 78 | KMDF 79 | WindowsKernelModeDriver10.0 80 | Driver 81 | Off 82 | 83 | 84 | Windows10 85 | True 86 | Universal 87 | KMDF 88 | WindowsKernelModeDriver10.0 89 | Driver 90 | 91 | 92 | 93 | $(SolutionDir)bin\$(DDKPlatform)\ 94 | 95 | 96 | 97 | 98 | 99 | SlionTrackPoint 100 | true 101 | 102 | 103 | SlionTrackPoint 104 | true 105 | 106 | 107 | SlionTrackPoint 108 | 109 | 110 | SlionTrackPoint 111 | 112 | 113 | SlionTrackPoint 114 | true 115 | 116 | 117 | SlionTrackPoint 118 | 119 | 120 | 121 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 122 | 123 | 124 | %(PreprocessorDefinitions) 125 | 126 | 127 | true 128 | true 129 | Trace.h 130 | 131 | 132 | %(PreprocessorDefinitions) 133 | 134 | 135 | %(PreprocessorDefinitions) 136 | 137 | 138 | 1.0.0.1 139 | 140 | 141 | SHA256 142 | 143 | 144 | 145 | 146 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 147 | 148 | 149 | %(PreprocessorDefinitions) 150 | 151 | 152 | true 153 | true 154 | Trace.h 155 | 156 | 157 | %(PreprocessorDefinitions) 158 | 159 | 160 | %(PreprocessorDefinitions) 161 | 162 | 163 | 1.0.0.1 164 | 165 | 166 | SHA256 167 | 168 | 169 | 170 | 171 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 172 | 173 | 174 | %(PreprocessorDefinitions) 175 | 176 | 177 | true 178 | true 179 | Trace.h 180 | 181 | 182 | %(PreprocessorDefinitions) 183 | 184 | 185 | %(PreprocessorDefinitions) 186 | 187 | 188 | 1.0.0.1 189 | 190 | 191 | SHA256 192 | 193 | 194 | 195 | 196 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 197 | 198 | 199 | %(PreprocessorDefinitions) 200 | 201 | 202 | true 203 | true 204 | Trace.h 205 | 206 | 207 | %(PreprocessorDefinitions) 208 | 209 | 210 | %(PreprocessorDefinitions) 211 | 212 | 213 | 1.0.0.1 214 | 215 | 216 | SHA256 217 | 218 | 219 | 220 | 221 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 222 | 223 | 224 | %(PreprocessorDefinitions) 225 | 226 | 227 | true 228 | true 229 | Trace.h 230 | 231 | 232 | %(PreprocessorDefinitions) 233 | 234 | 235 | %(PreprocessorDefinitions) 236 | 237 | 238 | 1.0.0.1 239 | 240 | 241 | SHA256 242 | 243 | 244 | 245 | 246 | %(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib 247 | 248 | 249 | %(PreprocessorDefinitions) 250 | 251 | 252 | true 253 | true 254 | Trace.h 255 | 256 | 257 | %(PreprocessorDefinitions) 258 | 259 | 260 | %(PreprocessorDefinitions) 261 | 262 | 263 | 1.0.0.1 264 | 265 | 266 | SHA256 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /driver/driver.vcxproj.Filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {849BE81A-B9DC-4096-AC00-2D7D742FB0E8} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {29531875-8C9E-4110-BBE3-1CFC9D282A6B} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {AE3E2BD7-4200-448A-8100-6C69BE4720FE} 15 | 16 | 17 | inf;inv;inx;mof;mc; 18 | {617E5D49-6208-482D-BEA6-DCF17EDD8033} 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Resource Files 40 | 41 | 42 | 43 | 44 | Driver Files 45 | 46 | 47 | -------------------------------------------------------------------------------- /driver/moufiltr.h: -------------------------------------------------------------------------------- 1 | #ifndef MOUFILTER_H 2 | #define MOUFILTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Trace.h" 10 | 11 | #if DBG 12 | 13 | #define TRAP() DbgBreakPoint() 14 | 15 | #define DebugPrint(_x_) DbgPrint _x_ 16 | 17 | #else // DBG 18 | 19 | #define TRAP() 20 | 21 | #define DebugPrint(_x_) 22 | 23 | #endif 24 | 25 | 26 | typedef struct _DEVICE_EXTENSION 27 | { 28 | 29 | // 30 | // Previous hook routine and context 31 | // 32 | PVOID UpperContext; 33 | 34 | PI8042_MOUSE_ISR UpperIsrHook; 35 | 36 | // 37 | // Write to the mouse in the context of MouFilter_IsrHook 38 | // 39 | IN PI8042_ISR_WRITE_PORT IsrWritePort; 40 | 41 | // 42 | // Context for IsrWritePort, QueueMousePacket 43 | // 44 | IN PVOID CallContext; 45 | 46 | // 47 | // Queue the current packet (ie the one passed into MouFilter_IsrHook) 48 | // to be reported to the class driver 49 | // 50 | IN PI8042_QUEUE_PACKET QueueMousePacket; 51 | 52 | // 53 | // The real connect data that this driver reports to 54 | // 55 | CONNECT_DATA UpperConnectData; 56 | 57 | 58 | } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 59 | 60 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, 61 | FilterGetData) 62 | 63 | // 64 | // Prototypes 65 | // 66 | DRIVER_INITIALIZE DriverEntry; 67 | 68 | EVT_WDF_DRIVER_DEVICE_ADD MouFilter_EvtDeviceAdd; 69 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL MouFilter_EvtIoInternalDeviceControl; 70 | EVT_WDF_OBJECT_CONTEXT_CLEANUP MouFilter_EvtDriverContextCleanup; 71 | 72 | 73 | 74 | VOID 75 | MouFilter_DispatchPassThrough( 76 | _In_ WDFREQUEST Request, 77 | _In_ WDFIOTARGET Target 78 | ); 79 | 80 | BOOLEAN 81 | MouFilter_IsrHook ( 82 | PVOID DeviceExtension, 83 | PMOUSE_INPUT_DATA CurrentInput, 84 | POUTPUT_PACKET CurrentOutput, 85 | UCHAR StatusByte, 86 | PUCHAR DataByte, 87 | PBOOLEAN ContinueProcessing, 88 | PMOUSE_STATE MouseState, 89 | PMOUSE_RESET_SUBSTATE ResetSubState 90 | ); 91 | 92 | VOID 93 | MouFilter_ServiceCallback( 94 | IN PDEVICE_OBJECT DeviceObject, 95 | IN PMOUSE_INPUT_DATA InputDataStart, 96 | IN PMOUSE_INPUT_DATA InputDataEnd, 97 | IN OUT PULONG InputDataConsumed 98 | ); 99 | 100 | #endif // MOUFILTER_H 101 | 102 | 103 | --------------------------------------------------------------------------------