72 Commits

Author SHA1 Message Date
Benjamin Höglinger-Stelzer
31e6b91706 Fixes #131 2022-06-26 03:19:28 +02:00
Benjamin Höglinger-Stelzer
ab8850e2ac Updated badges
Fixed project name
2022-06-26 02:07:56 +02:00
Benjamin Höglinger-Stelzer
0c32f7fc2d Added new setup 2022-06-25 22:52:25 +02:00
Benjamin Höglinger-Stelzer
4e669c3e6b Created ViGEmBus_ARM64.ddf 2022-06-25 22:15:05 +02:00
Benjamin Höglinger-Stelzer
f65bf6b22a More fixes 2022-06-25 19:58:59 +02:00
Benjamin Höglinger-Stelzer
318fe888af Added ARM64 to build script 2022-06-25 19:55:19 +02:00
Benjamin Höglinger-Stelzer
6b02661056 Uncheck some builds 2022-06-25 19:48:17 +02:00
Benjamin Höglinger-Stelzer
1e1191a247 Fixed appveyor.yml 2022-06-25 19:46:23 +02:00
Benjamin Höglinger-Stelzer
b134e6f1de Fixed DMF path 2022-06-25 19:45:33 +02:00
Benjamin Höglinger-Stelzer
1723e0ecd7 Added ARM64 2022-06-25 19:42:26 +02:00
Benjamin Höglinger-Stelzer
c63d68340a Added ARM64 build settings 2022-06-25 19:41:59 +02:00
Benjamin Höglinger-Stelzer
4cbb3357dc Changed DMF build instructions to speed up build 2022-06-25 17:49:05 +02:00
Benjamin Höglinger-Stelzer
efe14cd917 Updated tracing routines 2022-06-25 17:46:52 +02:00
Benjamin Höglinger-Stelzer
6942f17e36 Updated links in README.md 2022-06-25 15:20:24 +02:00
Benjamin Höglinger-Stelzer
ee83bbaa45 Updated to latest nuke 2022-06-25 15:18:14 +02:00
Benjamin Höglinger-Stelzer
83b89dc860 Fixed cache settings 2022-06-24 22:41:48 +02:00
Benjamin Höglinger-Stelzer
fa43acce66 Fixed appveyor.yml 2022-06-24 22:40:20 +02:00
Benjamin Höglinger-Stelzer
735ee2984f Added cache instruction 2022-06-24 22:38:29 +02:00
Benjamin Höglinger-Stelzer
10825759c8 Bumped version 2022-06-24 22:36:34 +02:00
Benjamin Höglinger-Stelzer
53673bda45 Updated to more secure memory allocation function 2022-06-24 22:34:02 +02:00
Benjamin Höglinger-Stelzer
da4b8419f5 Downgraded to WDK for Windows 10, version 2004 2022-06-24 12:36:04 +02:00
Benjamin Höglinger-Stelzer
01b9ebd75e Updated WDK in appveyor.yml 2022-06-24 12:06:48 +02:00
Benjamin Höglinger-Stelzer
a9e7d6b38b Create support.yml 2021-12-31 05:26:18 +01:00
Benjamin Höglinger-Stelzer
7411c4fee3 Typo fix 2021-09-20 11:27:53 +02:00
Benjamin Höglinger-Stelzer
816ebc524f Delete you-need-support.md 2021-08-17 09:40:18 +02:00
Benjamin Höglinger-Stelzer
4316457837 Create config.yml 2021-08-17 09:39:46 +02:00
Benjamin Höglinger-Stelzer
3102c94dfc Create use-this-for-problems-with-the-setup.md 2021-07-05 20:46:54 +02:00
Benjamin Höglinger
442ae3b856 Delete FUNDING.yml 2021-04-06 11:57:03 +02:00
Benjamin Höglinger-Stelzer
41cc4f8398 Merge branch 'master' of github.com:ViGEm/ViGEmBus 2021-01-08 22:16:34 +01:00
Benjamin Höglinger-Stelzer
a33e223774 Fixed build output formatting 2021-01-08 22:16:24 +01:00
Benjamin Höglinger
d24ab69f45 Merge pull request #70 from Filoppi/patch-1
Fix Y touchpad resolution comment
2021-01-07 19:54:03 +01:00
Filippo Tarpini
7d3027c7db Fix Y touchpad resolution comment 2021-01-07 19:24:28 +02:00
Benjamin Höglinger
a1b58be426 Added Windows Server versions to supported systems 2021-01-07 13:44:34 +01:00
Benjamin Höglinger-Stelzer
9fdbe34bac Fix for issue #65 2020-12-22 22:51:46 +01:00
Benjamin Höglinger-Stelzer
346548689d Added devcon binaries compiled with /MT 2020-12-21 16:36:18 +01:00
Benjamin Höglinger-Stelzer
111ff8e170 Added missing README.md 2020-12-17 16:21:54 +01:00
Benjamin Höglinger-Stelzer
c5ecfbdd03 Updated outdated links 2020-12-17 16:20:22 +01:00
Benjamin Höglinger-Stelzer
df39fe6ed3 Minor formatting update 2020-12-17 08:30:12 +01:00
Benjamin Höglinger-Stelzer
2b02e029c1 Updated test signing link 2020-12-17 08:28:41 +01:00
Benjamin Höglinger-Stelzer
dce6de1a6f Corrected version compatibility 2020-12-16 20:46:10 +01:00
Benjamin Höglinger-Stelzer
4ddf7639e3 Added Regame - Cloud Gaming Engine 2020-12-16 20:20:59 +01:00
Benjamin Höglinger-Stelzer
b4980ceb82 Updated build instructions 2020-12-16 20:19:41 +01:00
Benjamin Höglinger-Stelzer
23052bcb67 Fixed broken INF version stamping on release builds 2020-12-14 15:17:11 +01:00
Benjamin Höglinger-Stelzer
6ef839228d Added recursive switch to removal command 2020-12-14 14:12:53 +01:00
Benjamin Höglinger-Stelzer
40aa12d889 Turned off test-signing for release builds 2020-12-04 12:45:58 +01:00
Benjamin Höglinger-Stelzer
b22bb6b665 Removed searching for DLL artifacts 2020-12-04 12:42:57 +01:00
Benjamin Höglinger-Stelzer
8b8ba943b1 Removed co-installer reference from DDF files 2020-12-04 12:29:37 +01:00
Benjamin Höglinger-Stelzer
47a28733cd Removed outdated co-installer reference 2020-12-04 12:21:09 +01:00
Benjamin Höglinger-Stelzer
dc2feda23c Added missing project reference for setup project 2020-12-04 12:13:53 +01:00
Benjamin Höglinger-Stelzer
4001a9990b Fixed paths in setup project 2020-12-04 11:49:42 +01:00
Benjamin Höglinger-Stelzer
5861ea36f3 Added fix for 32-Bit build of DMF 2020-12-04 11:40:33 +01:00
Benjamin Höglinger-Stelzer
f14ba5db9c Added missing git command 2020-12-04 11:24:40 +01:00
Benjamin Höglinger-Stelzer
92e6937633 Updated build procedure to build DMF dependency via nuke 2020-12-04 11:22:08 +01:00
Benjamin Höglinger-Stelzer
2eb8a2e349 Added nuke to support CI build with DMF 2020-12-04 11:07:12 +01:00
Benjamin Höglinger-Stelzer
9f5247fd57 Fixed callback issue with DS4 notification 2020-12-04 10:55:20 +01:00
Benjamin Höglinger-Stelzer
ad1373248d Fixed rumble packet size handling in XUSB devices 2020-11-30 17:39:59 +01:00
Benjamin Höglinger-Stelzer
3fcdec87da Fixed incorrect NTSTATUS values in interrupt processing 2020-11-30 17:18:31 +01:00
Benjamin Höglinger-Stelzer
8567ee21b4 Added some more tracing 2020-11-26 22:11:35 +01:00
Benjamin Höglinger-Stelzer
a958721b44 Removed legacy code 2020-11-26 11:07:21 +01:00
Benjamin Höglinger-Stelzer
16fb8a2bb1 Implemented new queueing in Ds4Pdo.cpp 2020-11-23 23:22:29 +01:00
Benjamin Höglinger-Stelzer
97fd8fd9fa Finished new notification implementation for XusbPdo.cpp 2020-11-23 22:39:41 +01:00
Benjamin Höglinger-Stelzer
c3c4047cfa Implementing new notification logic 2020-11-23 22:23:48 +01:00
Benjamin Höglinger-Stelzer
703842c753 Fixed project file and build settings 2020-11-22 09:46:25 +01:00
Benjamin Höglinger-Stelzer
5d39f31a13 Clean-up 2020-11-21 14:18:10 +01:00
Benjamin Höglinger-Stelzer
a3c05a5aca More clean-up 2020-11-21 14:11:07 +01:00
Benjamin Höglinger-Stelzer
0afae253b8 More include clean-up 2020-11-21 14:08:30 +01:00
Benjamin Höglinger-Stelzer
8f1ddc86db Reworked includes
Added DMF include and library paths
2020-11-21 14:06:43 +01:00
Benjamin Höglinger-Stelzer
1a401ff65b Fixed issue with ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady not reporting online children 2020-11-03 17:03:13 +01:00
Benjamin Höglinger-Stelzer
27555457a7 Setup now in-place upgrades from v1.16.x 2020-11-03 14:44:03 +01:00
Benjamin Höglinger-Stelzer
9adbb268ed Added minimal UI to setup 2020-11-03 14:07:30 +01:00
Benjamin Höglinger-Stelzer
a8dc03a661 Updated copyright year to 2020
Signed x86 build of devcon.exe
2020-10-07 22:26:06 +02:00
Benjamin Höglinger-Stelzer
75c007b4c4 Signed devcon binary 2020-10-07 22:20:06 +02:00
49 changed files with 2402 additions and 979 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1,2 +0,0 @@
patreon: nefarius
custom: ["https://paypal.me/NefariusMaximus"]

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 💬 Community support
url: https://vigem.org/Community-Support/
about: Use these resources for support.
- name: 📖 Documentation
url: https://vigem.org/projects/
about: Extended documentation about the projects.
- name: ❓ Other issue?
url: https://forums.vigem.org/
about: Search on the community forums.

View File

@@ -0,0 +1,30 @@
---
name: Setup issues
about: Use this if you have problems with the setup
---
## README first
Before you report issues with the setup, make sure to check the following things **first**:
- Are you on anything older than Windows **10**? Windows XP/Vista/7/8/8.1 **are not supported** so don't report this as an issue, it is intentional.
- [Have you chosen the right setup for your CPU architecture?](https://vigem.org/research/How-to-check-architecture/)
- You **can not mix these**, make sure to download and run the correct setup.
- **ARM/ARM64** is **not supported**. See above link to check for yourself.
## I verified all that and am still stuck
Please provide the following **log files** and attach them to the issue. Failing to do so will result in the issue being closed without any further comment.
### Setup log
Run the setup from the command line (either old-school `cmd` or PowerShell) with the following additional arguments: `/L*V .\install.log`
This will generate the log file `install.log` in the same directory the setup resides in. Attach it once the setup is "done" failing.
Last but not least look for `C:\Windows\INF\setupapi.dev.log` and attach it as well.
Optionally compress both files down if it gives you troubles uploading.
Your compliance is appreciated! 😘

View File

@@ -1,7 +0,0 @@
---
name: You need support
about: This is the wrong place to ask for support
---
**Please don't abuse the issue tracker as a helpdesk!** We have a Discord server (linked in the README) where you can ask the lovely like-minded folks for assistance. Thank you for your compliance :smiley:

25
.github/workflows/support.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: 'Support Requests'
on:
issues:
types: [labeled, unlabeled, reopened]
permissions:
issues: write
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/support-requests@v2
with:
github-token: ${{ github.token }}
support-label: 'support'
issue-comment: >
:wave: @{issue-author}, we use the issue tracker exclusively
for bug reports and feature requests. However, this issue appears
to be a support request. Please use our support channels
to get help with the project.
close-issue: true
lock-issue: true
issue-lock-reason: 'off-topic'

2
.gitignore vendored
View File

@@ -363,3 +363,5 @@ FodyWeavers.xsd
/setup.rpt
/drivers
/_setup
/setup/Setup Files
/setup/ViGEmBus-cache

1
.nuke Normal file
View File

@@ -0,0 +1 @@
ViGEmBus.sln

View File

@@ -2,7 +2,7 @@
Windows kernel-mode driver emulating well-known USB game controllers.
[![Build status](https://ci.appveyor.com/api/projects/status/rv74ufluwib52dq2?svg=true)](https://ci.appveyor.com/project/nefarius/vigembus) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus)
[![Build status](https://ci.appveyor.com/api/projects/status/rv74ufluwib52dq2?svg=true)](https://ci.appveyor.com/project/nefarius/vigembus) [![GitHub All Releases](https://img.shields.io/github/downloads/ViGEm/ViGEmBus/total)](https://somsubhra.github.io/github-release-stats/?username=ViGEm&repository=ViGEmBus) [![Discord](https://img.shields.io/discord/346756263763378176.svg)](https://discord.vigem.org) [![Website](https://img.shields.io/website-up-down-green-red/https/vigem.org.svg?label=ViGEm.org)](https://vigem.org/) [![GitHub followers](https://img.shields.io/github/followers/nefarius.svg?style=social&label=Follow)](https://github.com/nefarius) [![Twitter Follow](https://img.shields.io/twitter/follow/nefariusmaximus.svg?style=social&label=Follow)](https://twitter.com/nefariusmaximus)
<sub>(This project is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using components of ViGEm, please consider reaching out.)</sub>
@@ -37,19 +37,30 @@ A few examples of the most common use cases for `ViGEm` are:
## Supported Systems
The driver is built for Windows 7/8.1/10 (x86 and amd64).
### Version 1.16 and below
The driver is built for Windows 7/8.1/10/Server 2016/Server 2019 (x86 and amd64).
### Version 1.17 and above
The driver is built for Windows 10/Server 2016/Server 2019 only (x86 and amd64).
## License
The `ViGEm` Bus Driver is licensed under the **BSD-3-Clause**, see [LICENSE](./LICENSE.md) for more information.
The ViGEm Bus Driver is licensed under the **BSD-3-Clause**, see [LICENSE](./LICENSE.md) for more information.
## How to build
[Install Visual Studio 2019 and WDK for Windows 10, version 1903](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk#wdk-for-windows-10-version-1903).
### Prerequisites
- [Step 1: Install Visual Studio 2019](https://docs.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads#step-1-install-visual-studio)
- [Step 2: Install WDK for Windows 10, version 2004](https://docs.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads#step-2-install-the-wdk)
- [Step 3: Clone the Driver Module Framework (DMF)](https://github.com/microsoft/DMF) into the same parent directory.
- Build the `DmfK` project with Release and Debug configurations for all architectures (x64 and Win32).
You can build directly within Visual Studio.
Do bear in mind that you'll need to **sign** the driver to use it without [test mode](<https://technet.microsoft.com/en-us/ff553484(v=vs.96)>).
Do bear in mind that you'll need to **sign** the driver to use it without [test mode](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/the-testsigning-boot-configuration-option#enable-or-disable-use-of-test-signed-code).
## Contribute
@@ -72,8 +83,8 @@ Pre-built production-signed binaries are provided by `Nefarius Software Solution
Sponsors listed here have helped the project flourish by either financial support or by gifting licenses:
- [3dRudder](https://www.3drudder.com/)
- [Parsec](https://parsecgaming.com/)
- [Rainway, Inc](https://rainway.io/)
- [Parsec](https://parsec.app/)
- [Rainway, Inc](https://rainway.com/)
- [JetBrains](https://www.jetbrains.com/resharper/)
- [Advanced Installer](https://www.advancedinstaller.com/)
- [ICAROS](https://www.icaros.com/)
@@ -85,18 +96,20 @@ A brief listing of projects/companies/vendors known to build upon the powers of
This list is non-exhaustive, if you'd like to see your project included, contact us!
- [3dRudder](https://www.3drudder.com/)
- [Parsec](https://parsecgaming.com/)
- [Parsec](https://parsec.app/)
- [GloSC](https://github.com/Alia5/GloSC)
- [UCR](https://github.com/Snoothy/UCR)
- [InputMapper](https://inputmapper.com/)
- [Oculus VR, LLC.](https://www.oculus.com/)
- [Rainway, Inc](https://rainway.io/)
- [Rainway, Inc](https://rainway.com/)
- [WiimoteHook](https://forum.cemu.info/showthread.php/140-WiimoteHook-Nintendo-Wii-Remote-with-Motion-Rumble-and-Nunchuk-support)
- [XJoy](https://github.com/sam0x17/XJoy)
- [HP](https://www8.hp.com/us/en/campaigns/gamingpcs/overview.html)
- [HP](https://www8.hp.com/us/en/gaming/omen.html)
- [DS4Windows](https://ryochan7.github.io/ds4windows-site/)
- [XOutput](https://github.com/csutorasa/XOutput)
- [RdpGamepad](https://github.com/microsoft/RdpGamepad)
- [Touchmote](https://github.com/Ryochan7/Touchmote/tree/ryochan7)
- [Mi-ViGEm](https://github.com/grayver/mi-vigem)
- [BetterJoy](https://github.com/Davidobot/BetterJoy)
- [Regame](https://github.com/ksyun-kenc/liuguang)
- [NetInput](https://github.com/usertoroot/NetInput)

View File

@@ -15,105 +15,171 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup", "Setup", "{D138F6D3
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ViGEmBusSetup", "setup\ViGEmBusSetup.wixproj", "{C722B85E-FC7D-475F-A518-C8E13ECDB201}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_DLL|ARM64 = Debug_DLL|ARM64
Debug_DLL|x64 = Debug_DLL|x64
Debug_DLL|x86 = Debug_DLL|x86
Debug_LIB|ARM64 = Debug_LIB|ARM64
Debug_LIB|x64 = Debug_LIB|x64
Debug_LIB|x86 = Debug_LIB|x86
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release_DLL|ARM64 = Release_DLL|ARM64
Release_DLL|x64 = Release_DLL|x64
Release_DLL|x86 = Release_DLL|x86
Release_LIB|ARM64 = Release_LIB|ARM64
Release_LIB|x64 = Release_LIB|x64
Release_LIB|x86 = Release_LIB|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|ARM64.ActiveCfg = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|ARM64.Build.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|ARM64.Deploy.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x64.ActiveCfg = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x64.Build.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x64.Deploy.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x86.ActiveCfg = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x86.Build.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_DLL|x86.Deploy.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|ARM64.ActiveCfg = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|ARM64.Build.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|ARM64.Deploy.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x64.ActiveCfg = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x64.Build.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x64.Deploy.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x86.ActiveCfg = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x86.Build.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug_LIB|x86.Deploy.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.ActiveCfg = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.Build.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|ARM64.Deploy.0 = Debug|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.ActiveCfg = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.Build.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x64.Deploy.0 = Debug|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.ActiveCfg = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.Build.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Debug|x86.Deploy.0 = Debug|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|ARM64.ActiveCfg = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|ARM64.Build.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|ARM64.Deploy.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x64.ActiveCfg = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x64.Build.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x64.Deploy.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x86.ActiveCfg = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x86.Build.0 = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_DLL|x86.Deploy.0 = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|ARM64.ActiveCfg = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|ARM64.Build.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|ARM64.Deploy.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x64.ActiveCfg = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x64.Build.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x64.Deploy.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x86.ActiveCfg = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x86.Build.0 = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release_LIB|x86.Deploy.0 = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.ActiveCfg = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.Build.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|ARM64.Deploy.0 = Release|ARM64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.ActiveCfg = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.Build.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x64.Deploy.0 = Release|x64
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.ActiveCfg = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.Build.0 = Release|Win32
{040101B0-EE5C-4EF1-99EE-9F81C795C001}.Release|x86.Deploy.0 = Release|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|ARM64.ActiveCfg = Debug_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|ARM64.Build.0 = Debug_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x64.Build.0 = Debug_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.ActiveCfg = Debug_DLL|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_DLL|x86.Build.0 = Debug_DLL|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|ARM64.ActiveCfg = Debug_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|ARM64.Build.0 = Debug_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.ActiveCfg = Debug_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x64.Build.0 = Debug_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.ActiveCfg = Debug_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug_LIB|x86.Build.0 = Debug_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM64.ActiveCfg = Debug_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|ARM64.Build.0 = Debug_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.ActiveCfg = Debug_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x64.Build.0 = Debug_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.ActiveCfg = Debug_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Debug|x86.Build.0 = Debug_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|ARM64.ActiveCfg = Release_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|ARM64.Build.0 = Release_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.ActiveCfg = Release_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x64.Build.0 = Release_DLL|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.ActiveCfg = Release_DLL|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_DLL|x86.Build.0 = Release_DLL|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|ARM64.ActiveCfg = Release_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|ARM64.Build.0 = Release_LIB|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.ActiveCfg = Release_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x64.Build.0 = Release_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.ActiveCfg = Release_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release_LIB|x86.Build.0 = Release_LIB|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM64.ActiveCfg = Release_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|ARM64.Build.0 = Release_DLL|ARM64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.ActiveCfg = Release_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x64.Build.0 = Release_LIB|x64
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.ActiveCfg = Release_DLL|Win32
{7DB06674-1F4F-464B-8E1C-172E9587F9DC}.Release|x86.Build.0 = Release_DLL|Win32
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|ARM64.ActiveCfg = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|ARM64.Build.0 = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|x64.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|x64.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|x86.ActiveCfg = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_DLL|x86.Build.0 = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|ARM64.ActiveCfg = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|ARM64.Build.0 = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|x64.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|x64.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|x86.ActiveCfg = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug_LIB|x86.Build.0 = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug|ARM64.ActiveCfg = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug|x64.ActiveCfg = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug|x86.ActiveCfg = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Debug|x86.Build.0 = Debug|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|ARM64.ActiveCfg = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|ARM64.Build.0 = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|x64.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|x64.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|x86.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_DLL|x86.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|ARM64.ActiveCfg = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|ARM64.Build.0 = Debug|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|x64.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|x64.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|x86.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release_LIB|x86.Build.0 = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|ARM64.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x64.ActiveCfg = Release|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x64.Build.0 = Release|x64
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x86.ActiveCfg = Release|x86
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x86.Build.0 = Release|x86
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_DLL|ARM64.ActiveCfg = Debug|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_DLL|x64.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_DLL|x86.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_LIB|ARM64.ActiveCfg = Debug|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_LIB|x64.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_LIB|x86.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug|ARM64.ActiveCfg = Debug|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug|x64.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug|x86.ActiveCfg = Debug|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_DLL|ARM64.ActiveCfg = Release|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_DLL|x64.ActiveCfg = Release|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_DLL|x86.ActiveCfg = Release|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_LIB|ARM64.ActiveCfg = Release|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_LIB|x64.ActiveCfg = Release|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_LIB|x86.ActiveCfg = Release|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release|ARM64.ActiveCfg = Release|ARM64
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release|x64.ActiveCfg = Release|Any CPU
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

18
ViGEmBus_ARM64.ddf Normal file
View File

@@ -0,0 +1,18 @@
; ViGEmBus cab file for attestation submission
.OPTION EXPLICIT
.Set CabinetFileCountThreshold=0
.Set FolderFileCountThreshold=0
.Set FolderSizeThreshold=0
.Set MaxCabinetSize=0
.Set MaxDiskFileCount=0
.Set MaxDiskSize=0
.Set CompressionType=MSZIP
.Set Cabinet=on
.Set Compress=on
; ARM64
.Set CabinetNameTemplate=ViGEmBus_ARM64.cab
.Set DestinationDir=ViGEmBus_ARM64
LICENSE
bin\ARM64\ViGEmBus.pdb
bin\ARM64\ViGEmBus\ViGEmBus.inf
bin\ARM64\ViGEmBus\ViGEmBus.sys

View File

@@ -15,5 +15,4 @@
LICENSE
bin\x64\ViGEmBus.pdb
bin\x64\ViGEmBus\ViGEmBus.inf
bin\x64\ViGEmBus\ViGEmBus.sys
bin\x64\ViGEmBus\WdfCoinstaller01009.dll
bin\x64\ViGEmBus\ViGEmBus.sys

View File

@@ -15,5 +15,4 @@
LICENSE
bin\x86\ViGEmBus.pdb
bin\x86\ViGEmBus\ViGEmBus.inf
bin\x86\ViGEmBus\ViGEmBus.sys
bin\x86\ViGEmBus\WdfCoinstaller01009.dll
bin\x86\ViGEmBus\ViGEmBus.sys

View File

@@ -1,24 +1,38 @@
version: 1.17.{build}.0
version: 1.18.{build}.0
image: Visual Studio 2019
skip_commits:
files:
- '**/*.md'
cache:
- C:\projects\DMF
platform:
- x86
- x64
- ARM64
configuration:
- Release
environment:
DmfRootPath: C:\projects\DMF
install:
- ps: iwr "https://download.microsoft.com/download/c/f/8/cf80b955-d578-4635-825c-2801911f9d79/wdk/wdksetup.exe" -OutFile wdksetup.exe
- cmd: .\wdksetup.exe /features + /q /norestart
- cmd: git submodule -q update --init
- cmd: git clone -q https://github.com/microsoft/DMF.git C:\projects\DMF 2> nul || set ERRORLEVEL=0
- cmd: |
cd "C:\projects\DMF"
git pull > NUL
cd %appveyor_build_folder%
before_build:
- ps: Invoke-WebRequest "https://github.com/nefarius/vpatch/releases/latest/download/vpatch.exe" -OutFile vpatch.exe
- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\ViGEmBus.vcxproj" --vcxproj.inf-time-stamp
- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\ViGEmBus.rc" --resource.file-version --resource.product-version
build:
project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln
build_script:
- cmd: .\build.cmd
after_build:
- cmd: makecab.exe /f ViGEmBus_%PLATFORM%.ddf
artifacts:
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.inf'
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.sys'
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.dll'
- path: 'bin**\*.pdb'
- path: 'disk1\*.cab'
- path: 'bin**\*.msi'

7
build.cmd Executable file
View File

@@ -0,0 +1,7 @@
:; set -eo pipefail
:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
:; ${SCRIPT_DIR}/build.sh "$@"
:; exit $?
@ECHO OFF
powershell -ExecutionPolicy ByPass -NoProfile %0\..\build.ps1 %*

69
build.ps1 Normal file
View File

@@ -0,0 +1,69 @@
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$BuildArguments
)
Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
###########################################################################
# CONFIGURATION
###########################################################################
$BuildProjectFile = "$PSScriptRoot\build\_build.csproj"
$TempDirectory = "$PSScriptRoot\\.tmp"
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
$DotNetChannel = "Current"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
$env:DOTNET_MULTILEVEL_LOOKUP = 0
###########################################################################
# EXECUTION
###########################################################################
function ExecSafe([scriptblock] $cmd) {
& $cmd
if ($LASTEXITCODE) { exit $LASTEXITCODE }
}
# If dotnet CLI is installed globally and it matches requested version, use for execution
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path
}
else {
# Download install script
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
# If global.json exists, load expected version
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}
# Install by channel or version
$DotNetDirectory = "$TempDirectory\dotnet-win"
if (!(Test-Path variable:DotNetVersion)) {
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
} else {
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
}
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
}
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }

62
build.sh Executable file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env bash
bash --version 2>&1 | head -n 1
set -eo pipefail
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
###########################################################################
# CONFIGURATION
###########################################################################
BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj"
TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
DOTNET_CHANNEL="Current"
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
export DOTNET_MULTILEVEL_LOOKUP=0
###########################################################################
# EXECUTION
###########################################################################
function FirstJsonValue {
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
}
# If dotnet CLI is installed globally and it matches requested version, use for execution
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
export DOTNET_EXE="$(command -v dotnet)"
else
# Download install script
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
mkdir -p "$TEMP_DIRECTORY"
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
chmod +x "$DOTNET_INSTALL_FILE"
# If global.json exists, load expected version
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
if [[ "$DOTNET_VERSION" == "" ]]; then
unset DOTNET_VERSION
fi
fi
# Install by channel or version
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
if [[ -z ${DOTNET_VERSION+x} ]]; then
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
else
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
fi
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
fi
echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"

11
build/.editorconfig Normal file
View File

@@ -0,0 +1,11 @@
[*.cs]
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning
dotnet_style_require_accessibility_modifiers = never:warning
csharp_style_expression_bodied_methods = true:silent
csharp_style_expression_bodied_properties = true:warning
csharp_style_expression_bodied_indexers = true:warning
csharp_style_expression_bodied_accessors = true:warning

82
build/Build.cs Normal file
View File

@@ -0,0 +1,82 @@
using System;
using System.Linq;
using Nuke.Common;
using Nuke.Common.CI;
using Nuke.Common.CI.AppVeyor;
using Nuke.Common.Execution;
using Nuke.Common.Git;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.MSBuild;
using Nuke.Common.Utilities.Collections;
using static Nuke.Common.EnvironmentInfo;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
[CheckBuildProjectConfigurations]
class Build : NukeBuild
{
/// Support plugins are available for:
/// - JetBrains ReSharper https://nuke.build/resharper
/// - JetBrains Rider https://nuke.build/rider
/// - Microsoft VisualStudio https://nuke.build/visualstudio
/// - Microsoft VSCode https://nuke.build/vscode
public static int Main () => Execute<Build>(x => x.Compile);
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
[Solution] readonly Solution Solution;
[GitRepository] readonly GitRepository GitRepository;
AbsolutePath DmfSolution => RootDirectory / "../DMF/Dmf.sln";
Target Restore => _ => _
.Executes(() =>
{
MSBuild(s => s
.SetTargetPath(Solution)
.SetTargets("Restore"));
});
Target BuildDmf => _ => _
.Executes(() =>
{
if (IsLocalBuild)
return;
Console.WriteLine($"DMF solution path: {DmfSolution}");
var platform = MSBuildTargetPlatform.x64;
if (AppVeyor.Instance.Platform is "x86")
platform = MSBuildTargetPlatform.Win32;
if (AppVeyor.Instance.Platform is "ARM64")
platform = (MSBuildTargetPlatform) "ARM64";
MSBuild(s => s
.SetTargetPath(DmfSolution)
.SetTargets("Build")
.SetConfiguration(Configuration)
.SetTargetPlatform(platform)
.SetMaxCpuCount(Environment.ProcessorCount)
.SetNodeReuse(IsLocalBuild));
});
Target Compile => _ => _
.DependsOn(BuildDmf)
.Executes(() =>
{
MSBuild(s => s
.SetTargetPath(Solution)
.SetTargets("Rebuild")
.SetConfiguration(Configuration)
.SetMaxCpuCount(Environment.ProcessorCount)
.SetNodeReuse(IsLocalBuild));
});
}

16
build/Configuration.cs Normal file
View File

@@ -0,0 +1,16 @@
using System;
using System.ComponentModel;
using System.Linq;
using Nuke.Common.Tooling;
[TypeConverter(typeof(TypeConverter<Configuration>))]
public class Configuration : Enumeration
{
public static Configuration Debug = new Configuration { Value = nameof(Debug) };
public static Configuration Release = new Configuration { Value = nameof(Release) };
public static implicit operator string(Configuration configuration)
{
return configuration.Value;
}
}

17
build/_build.csproj Normal file
View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace></RootNamespace>
<NoWarn>CS0649;CS0169</NoWarn>
<NukeRootDirectory>..</NukeRootDirectory>
<NukeScriptDirectory>..</NukeScriptDirectory>
<Platforms>AnyCPU;ARM64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nuke.Common" Version="6.1.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,27 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=HeapView_002EDelegateAllocation/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VariableHidesOuterVariable/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeMadeStatic_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Implicit</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">0</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ATTRIBUTE_LENGTH_FOR_SAME_LINE/@EntryValue">120</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

3
drivers/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Drivers directory
Place the attestation signed driver files into the corresponding sub-directories and locally build the setup and sign it afterwards for production release.

Binary file not shown.

Binary file not shown.

View File

@@ -212,7 +212,7 @@ typedef struct _DS4_TOUCH
BYTE bTouchData1[3]; // Two 12 bits values (for X and Y)
// middle byte holds last 4 bits of X and the starting 4 bits of Y
BYTE bIsUpTrackingNum2; // second touch data immediately follows data of first touch
BYTE bTouchData2[3]; // resolution is 1920x943
BYTE bTouchData2[3]; // resolution is 1920x942
} DS4_TOUCH, * PDS4_TOUCH;
//

View File

@@ -67,7 +67,5 @@ typedef struct _VIGEM_TARGET_T
FARPROC Notification;
LPVOID NotificationUserData;
bool closingNotificationThreads;
HANDLE cancelNotificationThreadEvent;
std::unique_ptr<std::vector<std::thread>> notificationThreadList;
} VIGEM_TARGET;

View File

@@ -74,76 +74,6 @@ LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExcep
#endif
//
// DeviceIOControl request notification handler classes for X360 and DS4 controller types.
// vigem_target_XXX_register_notification functions use x360 or DS4 derived class instances in a notification thread handlers.
//
class NotificationRequestPayload
{
public:
LPVOID lpPayloadBuffer;
DWORD payloadBufferSize;
DWORD ioControlCode;
public:
NotificationRequestPayload(DWORD _bufferSize, DWORD _ioControlCode)
{
lpPayloadBuffer = malloc(_bufferSize);
payloadBufferSize = _bufferSize;
ioControlCode = _ioControlCode;
}
virtual ~NotificationRequestPayload()
{
free(lpPayloadBuffer);
}
virtual void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) = 0;
};
class NotificationRequestPayloadX360 : public NotificationRequestPayload
{
public:
NotificationRequestPayloadX360(ULONG _serialNo) : NotificationRequestPayload(sizeof(XUSB_REQUEST_NOTIFICATION), IOCTL_XUSB_REQUEST_NOTIFICATION)
{
// Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function
XUSB_REQUEST_NOTIFICATION_INIT((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo);
}
void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override
{
if(target->Notification != nullptr)
PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target,
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LargeMotor,
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->SmallMotor,
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber,
target->NotificationUserData
);
}
};
class NotificationRequestPayloadDS4 : public NotificationRequestPayload
{
public:
NotificationRequestPayloadDS4(ULONG _serialNo) : NotificationRequestPayload(sizeof(DS4_REQUEST_NOTIFICATION), IOCTL_DS4_REQUEST_NOTIFICATION)
{
// Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function
DS4_REQUEST_NOTIFICATION_INIT((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo);
}
void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override
{
if (target->Notification != nullptr)
PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target,
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LargeMotor,
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.SmallMotor,
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor,
target->NotificationUserData
);
}
};
//
// Initializes a virtual gamepad object.
//
@@ -161,7 +91,6 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT(
target->Size = sizeof(VIGEM_TARGET);
target->State = VIGEM_TARGET_INITIALIZED;
target->Type = Type;
target->notificationThreadList = nullptr;
return target;
}
@@ -616,117 +545,6 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target)
return VIGEM_ERROR_REMOVAL_FAILED;
}
// Num of items in Notification DeviceIOControl queue (at any time there should be at least one extra call waiting for the new events or there is danger that notification events are lost).
// The size of this queue is based on "scientific" experimentals and estimations (few games seem to sometimes flood the FFB driver interface).
#define NOTIFICATION_OVERLAPPED_QUEUE_SIZE 6
void vigem_notification_thread_worker(
PVIGEM_CLIENT client,
PVIGEM_TARGET target,
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> pNotificationRequestPayload
)
{
int idx;
DWORD error;
HANDLE waitObjects[2];
BOOL devIoResult[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
DWORD lastIoError[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
DWORD transferred[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
OVERLAPPED lOverlapped[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
int currentOverlappedIdx;
int futureOverlappedIdx;
memset(lOverlapped, 0, sizeof(lOverlapped));
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
lOverlapped[idx].hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
waitObjects[0] = target->cancelNotificationThreadEvent;
currentOverlappedIdx = 0;
futureOverlappedIdx = NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1;
// Send out DeviceIOControl calls to wait for incoming feedback notifications. Use N pending requests to make sure that events are not lost even when application would flood FFB events.
// The order of DeviceIoControl calls and GetOverlappedResult requests is important to ensure that feedback callback function is called in correct order (ie. FIFO buffer with FFB events).
// Note! This loop doesn't call DevIo for the last lOverlapped item on purpose. The DO while loop does it as a first step (futureOverlappedIdx=NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1 in the first loop round).
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1; idx++)
{
devIoResult[idx] = DeviceIoControl(client->hBusDevice,
(*pNotificationRequestPayload)[idx]->ioControlCode,
(*pNotificationRequestPayload)[idx]->lpPayloadBuffer,
(*pNotificationRequestPayload)[idx]->payloadBufferSize,
(*pNotificationRequestPayload)[idx]->lpPayloadBuffer,
(*pNotificationRequestPayload)[idx]->payloadBufferSize,
&transferred[idx],
&lOverlapped[idx]);
lastIoError[idx] = GetLastError();
}
do
{
// Before reading data from "current overlapped request" then send a new DeviceIoControl request to wait for upcoming new FFB events (ring buffer of overlapped objects).
devIoResult[futureOverlappedIdx] = DeviceIoControl(client->hBusDevice,
(*pNotificationRequestPayload)[futureOverlappedIdx]->
ioControlCode,
(*pNotificationRequestPayload)[futureOverlappedIdx]->
lpPayloadBuffer,
(*pNotificationRequestPayload)[futureOverlappedIdx]->
payloadBufferSize,
(*pNotificationRequestPayload)[futureOverlappedIdx]->
lpPayloadBuffer,
(*pNotificationRequestPayload)[futureOverlappedIdx]->
payloadBufferSize,
&transferred[futureOverlappedIdx],
&lOverlapped[futureOverlappedIdx]);
lastIoError[futureOverlappedIdx] = GetLastError();
// currentOverlappedIdx is an index to the "oldest" DeviceIOControl call, so it will receive the next FFB event in a FFB sequence (in case there are multiple FFB events coming in)
if (!devIoResult[currentOverlappedIdx])
{
if (lastIoError[currentOverlappedIdx] == ERROR_IO_PENDING)
{
// DeviceIoControl is not yet completed to return all data. Wait for overlapped completion and thread cancellation events
waitObjects[1] = lOverlapped[currentOverlappedIdx].hEvent;
error = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE);
if (error != (WAIT_OBJECT_0 + 1))
break;
// Cancel event signaled or error while waiting for events (maybe handles were closed?). Quit this thread worker
// At this point overlapped event was signaled by a device driver and data is ready and waiting for in a buffer. The next GetOverlappedResult call should return immediately.
}
else
// Hmm... DeviceIoControl failed and is not just in async pending state. Quit the notification thread because the virtual controller may be in unknown state or device handles were closed
break;
}
if (GetOverlappedResult(client->hBusDevice, &lOverlapped[currentOverlappedIdx],
&transferred[currentOverlappedIdx], TRUE) != 0)
(*pNotificationRequestPayload)[currentOverlappedIdx]->ProcessNotificationRequest(client, target);
if (currentOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1)
currentOverlappedIdx = 0;
else
currentOverlappedIdx++;
if (futureOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1)
futureOverlappedIdx = 0;
else
futureOverlappedIdx++;
}
while (target->closingNotificationThreads != TRUE && target->Notification != nullptr);
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
if (lOverlapped[idx].hEvent)
CloseHandle(lOverlapped[idx].hEvent);
// Caller created the unique_ptr object, but this thread worker function should delete the object because it is no longer needed (thread specific object)
pNotificationRequestPayload.reset();
}
VIGEM_ERROR vigem_target_x360_register_notification(
PVIGEM_CLIENT vigem,
PVIGEM_TARGET target,
@@ -752,26 +570,70 @@ VIGEM_ERROR vigem_target_x360_register_notification(
target->Notification = reinterpret_cast<FARPROC>(notification);
target->NotificationUserData = userData;
if (target->cancelNotificationThreadEvent == 0)
target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
else
ResetEvent(target->cancelNotificationThreadEvent);
if (target->cancelNotificationThreadEvent == nullptr)
target->cancelNotificationThreadEvent = CreateEvent(
nullptr,
TRUE,
FALSE,
nullptr
);
else
ResetEvent(target->cancelNotificationThreadEvent);
if(target->notificationThreadList == nullptr)
target->notificationThreadList = std::make_unique<std::vector<std::thread>>();
std::thread _async{
[](
PVIGEM_TARGET _Target,
PVIGEM_CLIENT _Client,
LPVOID _UserData)
{
DWORD transferred = 0;
OVERLAPPED lOverlapped = {0};
lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
target->closingNotificationThreads = FALSE;
XUSB_REQUEST_NOTIFICATION xrn;
XUSB_REQUEST_NOTIFICATION_INIT(&xrn, _Target->SerialNo);
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> payloadVector = std::make_unique<std::vector<std::unique_ptr<NotificationRequestPayload>>>();
payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE);
for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
payloadVector->push_back(std::make_unique<NotificationRequestPayloadX360>(target->SerialNo));
do
{
DeviceIoControl(
_Client->hBusDevice,
IOCTL_XUSB_REQUEST_NOTIFICATION,
&xrn,
xrn.Size,
&xrn,
xrn.Size,
&transferred,
&lOverlapped
);
// Nowadays there is only one background thread listening for incoming FFB events, but there used to be more. This code still uses notificationThreadList vector even
// when there is only one item in the vector. If it is someday find out that this logic needs more background threads then it is easy to do because the thread vector is already in place.
//for (int i = 0; i < 1; i++)
target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector)));
if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0)
{
if (_Target->Notification == nullptr)
{
CloseHandle(lOverlapped.hEvent);
return;
}
reinterpret_cast<PFN_VIGEM_X360_NOTIFICATION>(_Target->Notification)(
_Client, _Target, xrn.LargeMotor, xrn.SmallMotor, xrn.LedNumber, _UserData
);
continue;
}
if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_OPERATION_ABORTED)
{
CloseHandle(lOverlapped.hEvent);
return;
}
}
while (TRUE);
},
target, vigem, userData
};
_async.detach();
return VIGEM_ERROR_NONE;
}
@@ -801,45 +663,83 @@ VIGEM_ERROR vigem_target_ds4_register_notification(
target->NotificationUserData = userData;
if (target->cancelNotificationThreadEvent == 0)
target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
target->cancelNotificationThreadEvent = CreateEvent(
nullptr,
TRUE,
FALSE,
nullptr
);
else
ResetEvent(target->cancelNotificationThreadEvent);
if (target->notificationThreadList == nullptr)
target->notificationThreadList = std::make_unique<std::vector<std::thread>>();
std::thread _async{
[](
PVIGEM_TARGET _Target,
PVIGEM_CLIENT _Client,
LPVOID _UserData)
{
DWORD transferred = 0;
OVERLAPPED lOverlapped = {0};
lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
target->closingNotificationThreads = FALSE;
DS4_REQUEST_NOTIFICATION ds4rn;
DS4_REQUEST_NOTIFICATION_INIT(&ds4rn, _Target->SerialNo);
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> payloadVector = std::make_unique<std::vector<std::unique_ptr<NotificationRequestPayload>>>();
payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE);
for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
payloadVector->push_back(std::make_unique<NotificationRequestPayloadDS4>(target->SerialNo));
do
{
DeviceIoControl(
_Client->hBusDevice,
IOCTL_DS4_REQUEST_NOTIFICATION,
&ds4rn,
ds4rn.Size,
&ds4rn,
ds4rn.Size,
&transferred,
&lOverlapped
);
//for (int i = 0; i < 1; i++)
target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector)));
if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0)
{
if (_Target->Notification == nullptr)
{
CloseHandle(lOverlapped.hEvent);
return;
}
reinterpret_cast<PFN_VIGEM_DS4_NOTIFICATION>(_Target->Notification)(
_Client, _Target, ds4rn.Report.LargeMotor,
ds4rn.Report.SmallMotor,
ds4rn.Report.LightbarColor, _UserData
);
continue;
}
if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_OPERATION_ABORTED)
{
CloseHandle(lOverlapped.hEvent);
return;
}
}
while (TRUE);
},
target, vigem, userData
};
_async.detach();
return VIGEM_ERROR_NONE;
}
void vigem_target_x360_unregister_notification(PVIGEM_TARGET target)
{
target->closingNotificationThreads = TRUE;
{
if (target->cancelNotificationThreadEvent != 0)
SetEvent(target->cancelNotificationThreadEvent);
if (target->notificationThreadList != nullptr)
{
// Wait for completion of all notification threads before cleaning up target object and Notification function pointer (a thread may be in the middle of handling a notification request, so close it cleanly)
std::for_each(target->notificationThreadList->begin(), target->notificationThreadList->end(), std::mem_fn(&std::thread::join));
target->notificationThreadList.reset();
target->notificationThreadList = nullptr;
}
if (target->cancelNotificationThreadEvent != 0)
if (target->cancelNotificationThreadEvent != nullptr)
{
CloseHandle(target->cancelNotificationThreadEvent);
target->cancelNotificationThreadEvent = 0;
target->cancelNotificationThreadEvent = nullptr;
}
target->Notification = nullptr;

View File

@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug_DLL|ARM64">
<Configuration>Debug_DLL</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug_DLL|Win32">
<Configuration>Debug_DLL</Configuration>
<Platform>Win32</Platform>
@@ -9,10 +13,18 @@
<Configuration>Debug_DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug_LIB|ARM64">
<Configuration>Debug_LIB</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug_LIB|Win32">
<Configuration>Debug_LIB</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release_DLL|ARM64">
<Configuration>Release_DLL</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release_DLL|Win32">
<Configuration>Release_DLL</Configuration>
<Platform>Win32</Platform>
@@ -21,6 +33,10 @@
<Configuration>Release_DLL</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release_LIB|ARM64">
<Configuration>Release_LIB</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release_LIB|Win32">
<Configuration>Release_LIB</Configuration>
<Platform>Win32</Platform>
@@ -78,12 +94,24 @@
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -91,6 +119,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -98,6 +133,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@@ -118,15 +160,27 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release_LIB|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|Win32'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
@@ -148,18 +202,30 @@
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)lib\debug\$(PlatformShortName)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|ARM64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|x64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)bin\debug\$(PlatformShortName)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|ARM64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|x64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)lib\release\$(PlatformShortName)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|ARM64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
<OutDir>$(SolutionDir)bin\release\$(PlatformShortName)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|ARM64'">
<IncludePath>$(ProjectDir)../include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|Win32'">
<ClCompile>
<PrecompiledHeader>
@@ -206,6 +272,20 @@
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_LIB|ARM64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|x64'">
<ClCompile>
<PrecompiledHeader>
@@ -221,6 +301,21 @@
<AdditionalDependencies>setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_DLL|ARM64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -279,6 +374,24 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_LIB|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -298,6 +411,25 @@
<AdditionalDependencies>setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;VIGEM_DYNAMIC;VIGEM_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>setupapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\include\ViGEm\Client.h" />
<ClInclude Include="..\include\ViGEm\Common.h" />

BIN
setup/LICENSE.rtf Normal file

Binary file not shown.

View File

@@ -28,7 +28,7 @@
<!-- basic product properties -->
<Product Id="*" Name="Nefarius Virtual Gamepad Emulation Bus Driver" Language="1033" Version="$(var.VERSION)"
Manufacturer="Nefarius Software Solutions e.U."
UpgradeCode="b935b0e2-a67f-4f2f-88de-2457dbd70c6e">
UpgradeCode="0A4A02DE-0BE3-4BF4-91F0-1EA47AD26881">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<!-- use single MSI file only -->
@@ -38,17 +38,18 @@
<Icon Id="ViGEm.ico" SourceFile="ViGEm.ico" />
<Property Id="ARPPRODUCTICON" Value="ViGEm.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://github.com/ViGEm/ViGEmBus" />
<Property Id="ARPNOMODIFY" Value="1" />
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" />
<!-- always perform major upgrade and remove previous versions -->
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="b935b0e2-a67f-4f2f-88de-2457dbd70c6e">
<Upgrade Id="0A4A02DE-0BE3-4BF4-91F0-1EA47AD26881">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="$(var.VERSION)"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
<!-- don't allow downgrades -->
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<!-- https://stackoverflow.com/a/31991006 -->
@@ -60,20 +61,20 @@
<!-- https://stackoverflow.com/a/23061358 -->
<Condition Message="This application can only be installed on Windows 10.">
<![CDATA[WIN10FOUND]]>
<![CDATA[Installed OR WIN10FOUND]]>
</Condition>
<!-- write version value to registry -->
<DirectoryRef Id="TARGETDIR">
<Component Id="RegistryEntries" Guid="85C87E47-E2C7-4684-A3FB-6F7853A86B41">
<RegistryKey Root="HKLM"
Key="SOFTWARE\Nefarius Software Solutions e.U.\ViGEm Bus Driver"
Action="createAndRemoveOnUninstall">
Key="SOFTWARE\Nefarius Software Solutions e.U.\ViGEm Bus Driver">
<RegistryValue Type="string" Name="Version" Value="$(var.VERSION)" KeyPath="yes"/>
</RegistryKey>
</Component>
</DirectoryRef>
<!-- main feature are the driver files and some version registry values -->
<Feature Id="ProductFeature" Title="Nefarius Virtual Gamepad Emulation Bus Driver" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentRef Id="RegistryEntries" />
@@ -92,7 +93,7 @@
<!-- build removal command -->
<CustomAction Id="DevconRemovePropertyAssign"
Property="DevconRemoveQuiet"
Value="&quot;[INSTALLFOLDER]devcon.exe&quot; remove &quot;Nefarius\ViGEmBus\Gen1&quot;"
Value="&quot;[INSTALLFOLDER]devcon.exe&quot; /r remove &quot;Nefarius\ViGEmBus\Gen1&quot;"
Execute="immediate" />
<!-- execute removal with suppressed UI -->
@@ -106,13 +107,23 @@
<Custom Action="DevconInstallQuiet" Before="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
<Custom Action='DevconRemoveQuiet' After='InstallInitialize'>REMOVE="ALL"</Custom>
</InstallExecuteSequence>
<!-- use LICENSE as EULA, not technically an EULA but for now it has to do -->
<WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)LICENSE.rtf" />
<!-- use minimalistic UI with EULA approval -->
<UIRef Id="WixUI_Minimal" />
</Product>
<!-- build program files directory -->
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="INSTALLFOLDER" Name="Nefarius Virtual Gamepad Emulation Bus Driver" />
<!-- the "e.U." is butchered so omitted -->
<Directory Id="NSS" Name="Nefarius Software Solutions">
<Directory Id="INSTALLFOLDER" Name="Virtual Gamepad Emulation Bus Driver" />
</Directory>
</Directory>
</Directory>
</Fragment>
@@ -126,21 +137,19 @@
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.sys" />
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.inf" />
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.cat" />
<File Name="WdfCoinstaller01009.dll" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\WdfCoinstaller01009.dll" />
<File Name="devcon.exe" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\devcon.exe" />
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)\drivers\devcon-LICENSE" />
<File Name="LICENSE" Source="$(var.SolutionDir)\LICENSE" />
<?else ?>
<!-- CI build -->
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.sys" />
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.inf" />
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.cat" />
<File Name="WdfCoinstaller01009.dll" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\WdfCoinstaller01009.dll" />
<File Name="devcon.exe" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\devcon.exe" />
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)\drivers\devcon-LICENSE" />
<File Name="LICENSE" Source="$(var.SolutionDir)\LICENSE" />
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.sys" />
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.inf" />
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.cat" />
<File Name="devcon.exe" Source="$(var.SolutionDir)drivers\$(var.ArchDir)\devcon.exe" />
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)drivers\devcon-LICENSE" />
<File Name="LICENSE" Source="$(var.SolutionDir)LICENSE" />
<?endif ?>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
</Wix>

323
setup/ViGEmBus.aip Normal file
View File

@@ -0,0 +1,323 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DOCUMENT Type="Advanced Installer" CreateVersion="19.5" version="19.5" Modules="enterprise" RootPath="." Language="en_GB" Id="{AF87FF38-9FCC-4C1C-9EB0-FFD1F6AE0A13}">
<COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
<ROW Name="HiddenItems" Value="AppXProductDetailsComponent;AppXDependenciesComponent;AppXAppDetailsComponent;AppXVisualAssetsComponent;AppXCapabilitiesComponent;AppXAppDeclarationsComponent;AppXUriRulesComponent;SccmComponent;ActSyncAppComponent;CPLAppletComponent;FixupComponent;MsiXDiffComponent;MsixManifestEditorComponent"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
<ROW Property="AI_CURRENT_YEAR" Value="2022" ValueLocId="-"/>
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
<ROW Property="AI_PACKAGING_TOOL" Value="Advanced Installer 19.5 build 36301275" ValueLocId="-"/>
<ROW Property="ALLUSERS" Value="1"/>
<ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/>
<ROW Property="ARPHELPLINK" Value="https://vigem.org/projects/ViGEm/"/>
<ROW Property="ARPNOMODIFY" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="ARPNOREPAIR" Value="1" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="ARPPRODUCTICON" Value="ViGEm.exe" Type="8"/>
<ROW Property="ARPURLINFOABOUT" Value="https://vigem.org/Community-Support/"/>
<ROW Property="ARPURLUPDATEINFO" Value="https://github.com/ViGEm/ViGEmBus/releases"/>
<ROW Property="AiLicenseAgreementLink" Value="https://github.com/ViGEm/ViGEmBus/blob/master/LICENSE" Type="4"/>
<ROW Property="IAgree" Value="No" Type="4"/>
<ROW Property="Manufacturer" Value="Nefarius Software Solutions e.U."/>
<ROW Property="ProductCode" Value="2057:{28A084F8-FBA9-4097-9CA6-3A9C70C6585B} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="ViGEm Bus Driver"/>
<ROW Property="ProductVersion" Value="1.18.367"/>
<ROW Property="REBOOT" MultiBuildValue="DefaultBuild:Force"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR;UPGRADE_1"/>
<ROW Property="UpgradeCode" Value="{67175F6C-AA18-43A7-AE60-2FC3FD10BF79}"/>
<ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT50" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
<ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003" ValueLocId="-"/>
<ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="AI_Bin32_Dir" Directory_Parent="APPDIR" DefaultDir="32-bit"/>
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="SHORTCUTDIR" Directory_Parent="TARGETDIR" DefaultDir="SHORTC~1|SHORTCUTDIR" IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="AI_ExePath" ComponentId="{756493E7-566A-49DE-8EC3-07AE9D1BD9C4}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
<ROW Component="APPDIR" ComponentId="{947691BF-6B7F-4A14-9027-3E1ECF87784A}" Directory_="APPDIR" Attributes="0"/>
<ROW Component="ProductInformation" ComponentId="{E2F0A6FF-AB27-4BBA-AF65-9D70B244A328}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
<ROW Component="ViGEmBus.pdb" ComponentId="{2BD2B055-FC59-4343-AEA0-C2C7948101B3}" Directory_="APPDIR" Attributes="256" Condition="VersionNT64" KeyPath="ViGEmBus.pdb" Type="4"/>
<ROW Component="ViGEmBus.pdb_1" ComponentId="{C14BA15C-3FE5-4BEA-A343-284469DE22F5}" Directory_="AI_Bin32_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="ViGEmBus.pdb_1" Type="4"/>
<ROW Component="ViGEmBus.sys" ComponentId="{DA974243-DAFB-49CF-8693-FF51C234CBD5}" Directory_="APPDIR" Attributes="256" Condition="VersionNT64" KeyPath="ViGEmBus.sys" Type="0"/>
<ROW Component="nefconw.exe" ComponentId="{AEADABD6-0FA7-4BF5-A3F5-1043F5D911F9}" Directory_="APPDIR" Attributes="256" Condition="VersionNT64" KeyPath="nefconw.exe"/>
<ROW Component="nefconw.exe_1" ComponentId="{E0BCC5D1-4762-490A-AD7E-9A36C8DF724C}" Directory_="AI_Bin32_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="nefconw.exe_1"/>
<ROW Component="updater.exe" ComponentId="{08EB2B6D-47C1-4EED-8A5C-FF31B6F28651}" Directory_="APPDIR" Attributes="0" KeyPath="updater.exe"/>
<ROW Component="vigembus.cat" ComponentId="{CEA011F4-933A-459C-B951-B1BC17E4E671}" Directory_="AI_Bin32_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="vigembus.cat_1" Type="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="AI32BitFiles" Title="32-bit" Description="32-bit Executables and Libraries" Display="5" Level="1" Directory_="APPDIR" Attributes="0"/>
<ROW Feature="AI64BitFiles" Title="64-bit" Description="64-bit Executables and Libraries" Display="3" Level="1" Directory_="APPDIR" Attributes="0"/>
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="nefconw.exe" Component_="nefconw.exe" FileName="nefconw.exe" Attributes="0" SourcePath="..\drivers\x64\nefconw.exe" SelfReg="false"/>
<ROW File="ViGEmBus.sys" Component_="ViGEmBus.sys" FileName="ViGEmBus.sys" Attributes="0" SourcePath="..\drivers\x64\ViGEmBus.sys" SelfReg="false"/>
<ROW File="vigembus.cat" Component_="ViGEmBus.sys" FileName="vigembus.cat" Attributes="0" SourcePath="..\drivers\x64\vigembus.cat" SelfReg="false"/>
<ROW File="ViGEmBus.inf" Component_="ViGEmBus.sys" FileName="ViGEmBus.inf" Attributes="0" SourcePath="..\drivers\x64\ViGEmBus.inf" SelfReg="false"/>
<ROW File="ViGEmBus.pdb" Component_="ViGEmBus.pdb" FileName="ViGEmBus.pdb" Attributes="0" SourcePath="..\drivers\x64\ViGEmBus.pdb" SelfReg="false"/>
<ROW File="LICENSE" Component_="ViGEmBus.sys" FileName="LICENSE" Attributes="0" SourcePath="..\drivers\x64\LICENSE" SelfReg="false"/>
<ROW File="nefconw.exe_1" Component_="nefconw.exe_1" FileName="nefconw.exe" Attributes="0" SourcePath="..\drivers\x86\nefconw.exe" SelfReg="false"/>
<ROW File="vigembus.cat_1" Component_="vigembus.cat" FileName="vigembus.cat" Attributes="0" SourcePath="..\drivers\x86\vigembus.cat" SelfReg="false"/>
<ROW File="ViGEmBus.inf_1" Component_="vigembus.cat" FileName="ViGEmBus.inf" Attributes="0" SourcePath="..\drivers\x86\ViGEmBus.inf" SelfReg="false"/>
<ROW File="ViGEmBus.pdb_1" Component_="ViGEmBus.pdb_1" FileName="ViGEmBus.pdb" Attributes="0" SourcePath="..\drivers\x86\ViGEmBus.pdb" SelfReg="false"/>
<ROW File="ViGEmBus.sys_1" Component_="vigembus.cat" FileName="ViGEmBus.sys" Attributes="0" SourcePath="..\drivers\x86\ViGEmBus.sys" SelfReg="false"/>
<ROW File="LICENSE_1" Component_="vigembus.cat" FileName="LICENSE" Attributes="0" SourcePath="..\drivers\x86\LICENSE" SelfReg="false"/>
<ROW File="updater.exe" Component_="updater.exe" FileName="VIGEMB~1.EXE|ViGEmBus_Updater.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="&lt;AI_STUBS&gt;updater.exe" SelfReg="false" DigSign="true"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
<ROW BootstrOptKey="GlobalOptions" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites" Options="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="Setup Files" Languages="en_GB" InstallationType="2" CabsLocation="1" CompressCabs="false" UseLzma="true" LzmaMethod="2" LzmaCompressionLevel="4" PackageType="1" FilesInsideExe="true" ExeIconPath="ViGEm.ico" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="ViGEmBus_[|ProductVersion]_x64_x86" MsiPackageType="AI_ALL"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en_GB.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DigCertStoreComponent">
<ROW TimeStampUrl="http://timestamp.digicert.com" SignerDescription="[|ProductName]" SignOptions="7" SignTool="0" UseSha256="1" Thumbprint="f88a20d1f8f87c188c7b7d65a1f897332b26cae6 Subject: Nefarius Software Solutions e.U.&#10;Issuer: DigiCert Global G3 Code Signing ECC SHA384 2021 CA1&#10;Valid from 11/25/2021 to 02/13/2025&#10;User\MY" Subject="CN=Nefarius Software Solutions e.U., O=Nefarius Software Solutions e.U., L=Wels, C=AT, SERIALNUMBER=505039f, OID.1.3.6.1.4.1.311.60.2.1.1=Wels, OID.1.3.6.1.4.1.311.60.2.1.2=Oberösterreich, OID.1.3.6.1.4.1.311.60.2.1.3=AT, OID.2.5.4.15=Private Organization"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
<ROW Fragment="InstallDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\InstallDlg.aip"/>
<ROW Fragment="LicenseAgreementDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\LicenseAgreementDlg.aip"/>
<ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>
<ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>
<ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
<ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
<ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
<ROW Fragment="Themes.aip" Path="&lt;AI_FRAGS&gt;Themes.aip"/>
<ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
<ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
<ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
<ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>
<ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
<ROW Action="AI_DeleteLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
<ROW Action="AI_DeleteRLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
<ROW Action="AI_ExtractFiles" Description="Extracting files from archive" DescriptionLocId="ActionText.Description.AI_ExtractLzma" TemplateLocId="-"/>
<ROW Action="AI_ExtractLzma" Description="Extracting files from archive" DescriptionLocId="ActionText.Description.AI_ExtractLzma" TemplateLocId="-"/>
<ROW Action="AI_ProcessTasks2" Description="Generating actions to schedule tasks on the local computer:" DescriptionLocId="ActionText.Description.AI_ProcessTasks" Template="Task Name: [1]" TemplateLocId="ActionText.Template.AI_ProcessTasks"/>
<ROW Action="AI_RemoveTasks2" Description="Removing scheduled task from the local computer" DescriptionLocId="ActionText.Description.AI_RemoveTasks" Template="Task Name: [1]" TemplateLocId="ActionText.Template.AI_RemoveTasks"/>
<ROW Action="AI_RollbackTasks2" Description="Rolling back scheduled task on the local computer" DescriptionLocId="ActionText.Description.AI_RollbackTasks" Template="Task Name: [1]" TemplateLocId="ActionText.Template.AI_RollbackTasks"/>
<ROW Action="AI_ScheduleTasks2" Description="Schedule task on the local computer" DescriptionLocId="ActionText.Description.AI_ScheduleTasks" Template="Task Name: [1]" TemplateLocId="ActionText.Template.AI_ScheduleTasks"/>
<ROW Action="AI_UninstallTasks2" Description="Generating actions to remove scheduled tasks from the local computer:" DescriptionLocId="ActionText.Description.AI_UninstallTasks"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiAppSearchComponent">
<ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_LM" Builds="DefaultBuild"/>
<ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_CU" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
<ROW Name="Prereq.dll" SourcePath="&lt;AI_CUSTACTS&gt;Prereq.dll"/>
<ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
<ROW Name="aischeduler2.dll" SourcePath="&lt;AI_CUSTACTS&gt;aischeduler2.dll"/>
<ROW Name="lzmaextractor.dll" SourcePath="&lt;AI_CUSTACTS&gt;lzmaextractor.dll"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiConditionComponent">
<ROW Feature_="AI64BitFiles" Level="0" Condition="NOT VersionNT64"/>
<ROW Feature_="AI32BitFiles" Level="0" Condition="VersionNT64"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
<ROW Dialog_="LicenseAgreementDlg" Control="AgreementText" Type="ScrollableText" X="20" Y="60" Width="330" Height="120" Attributes="7" Order="400" TextLocId="Control.Text.LicenseAgreementDlg#AgreementText" MsiKey="LicenseAgreementDlg#AgreementText"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="InstallDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="203"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="197"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="InstallDlg" Condition="AI_INSTALL" Ordering="201"/>
<ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>
<ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>
<ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>
<ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>
<ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>
<ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399" Options="1"/>
<ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299" Options="1"/>
<ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>
<ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="204"/>
<ROW Dialog_="InstallDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL" Ordering="201"/>
<ROW Dialog_="InstallDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="1"/>
<ROW Dialog_="InstallDlg" Control_="Hyperlink" Event="NewDialog" Argument="LicenseAgreementDlg" Condition="AI_INSTALL AND ReadLicense" Ordering="201"/>
<ROW Dialog_="LicenseAgreementDlg" Control_="Back" Event="NewDialog" Argument="InstallDlg" Condition="AI_INSTALL AND ReadLicense" Ordering="1"/>
<ROW Dialog_="LicenseAgreementDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ReadLicense" Ordering="1"/>
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="LicenseAgreementDlg" Condition="AI_INSTALL AND ReadLicense" Ordering="202"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
<ROW Directory_="APPDIR" Component_="APPDIR" ManualDelete="true"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DATA_SETTER" Type="51" Source="CustomActionData" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DeleteCadLzma" Type="51" Source="AI_DeleteLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DeleteLzma" Type="1025" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
<ROW Action="AI_DeleteRCadLzma" Type="51" Source="AI_DeleteRLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DeleteRLzma" Type="1281" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
<ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
<ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
<ROW Action="AI_ExtractCadLzma" Type="51" Source="AI_ExtractLzma" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_ExtractFiles" Type="1" Source="Prereq.dll" Target="ExtractSourceFiles" AdditionalSeq="AI_DATA_SETTER"/>
<ROW Action="AI_ExtractLzma" Type="1025" Source="lzmaextractor.dll" Target="ExtractLZMAFiles"/>
<ROW Action="AI_FindExeLzma" Type="1" Source="lzmaextractor.dll" Target="FindEXE"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
<ROW Action="AI_ProcessTasks2" Type="1" Source="aischeduler2.dll" Target="ProcessTasks"/>
<ROW Action="AI_REDIRECT_32BIT_FOLDER" Type="51" Source="AI_Bin32_Dir" Target="[APPDIR]"/>
<ROW Action="AI_REDIRECT_32BIT_SH_FOLDER" Type="51" Source="AI_Sh32_Dir" Target="[SHORTCUTDIR]"/>
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_RemoveTasks2" Type="11265" Source="aischeduler2.dll" Target="DeleteTasks" WithoutSeq="true"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_RollbackTasks2" Type="11521" Source="aischeduler2.dll" Target="DeleteTasks" WithoutSeq="true"/>
<ROW Action="AI_SETPROGRAMFILES" Type="51" Source="AI_ProgramFiles" Target="[ProgramFilesFolder]"/>
<ROW Action="AI_SETPROGRAMFILES64" Type="51" Source="AI_ProgramFiles" Target="[ProgramFiles64Folder]"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
<ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
<ROW Action="AI_ScheduleTasks2" Type="11265" Source="aischeduler2.dll" Target="ScheduleTasks" WithoutSeq="true"/>
<ROW Action="AI_UPDATER_UNINSTALL" Type="82" Source="updater.exe" Target="/clean silent"/>
<ROW Action="AI_UninstallTasks2" Type="1" Source="aischeduler2.dll" Target="UninstallTasks"/>
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[AI_ProgramFiles]Nefarius Software Solutions\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
<ROW Action="x64_AddDeviceNode" Type="1106" Source="nefconw.exe" Target="--create-device-node --hardware-id Nefarius\ViGEmBus\Gen1 --class-name System --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x64_InstallDriver" Type="1106" Source="nefconw.exe" Target="--install-driver --inf-path &quot;[#ViGEmBus.inf]&quot;"/>
<ROW Action="x64_UninstallDevice" Type="1106" Source="nefconw.exe" Target="--remove-device-node --hardware-id Nefarius\ViGEmBus\Gen1 --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x64_UninstallDevice_Old" Type="1106" Source="nefconw.exe" Target="--remove-device-node --hardware-id Root\ViGEmBus --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x64_UninstallDriver" Type="1106" Source="nefconw.exe" Target="--uninstall-driver --inf-path &quot;[#ViGEmBus.inf]&quot;"/>
<ROW Action="x86_AddDeviceNode" Type="1106" Source="nefconw.exe_1" Target="--create-device-node --hardware-id Nefarius\ViGEmBus\Gen1 --class-name System --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x86_InstallDriver" Type="1106" Source="nefconw.exe_1" Target="--install-driver --inf-path &quot;[#ViGEmBus.inf_1]&quot;"/>
<ROW Action="x86_UninstallDevice" Type="1106" Source="nefconw.exe_1" Target="--remove-device-node --hardware-id Nefarius\ViGEmBus\Gen1 --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x86_UninstallDevice_Old" Type="1106" Source="nefconw.exe_1" Target="--remove-device-node --hardware-id Root\ViGEmBus --class-guid 4D36E97D-E325-11CE-BFC1-08002BE10318"/>
<ROW Action="x86_UninstallDriver" Type="1106" Source="nefconw.exe_1" Target="--uninstall-driver --inf-path &quot;[#ViGEmBus.inf]&quot;"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatCompsComponent">
<ROW Feature_="MainFeature" Component_="APPDIR"/>
<ROW Feature_="MainFeature" Component_="ProductInformation"/>
<ROW Feature_="MainFeature" Component_="AI_ExePath"/>
<ROW Feature_="AI64BitFiles" Component_="nefconw.exe"/>
<ROW Feature_="AI64BitFiles" Component_="ViGEmBus.sys"/>
<ROW Feature_="AI64BitFiles" Component_="ViGEmBus.pdb"/>
<ROW Feature_="AI32BitFiles" Component_="nefconw.exe_1"/>
<ROW Feature_="AI32BitFiles" Component_="vigembus.cat"/>
<ROW Feature_="AI32BitFiles" Component_="ViGEmBus.pdb_1"/>
<ROW Feature_="MainFeature" Component_="updater.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="ViGEm.exe" SourcePath="ViGEm.ico" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIniFileComponent">
<ROW IniFile="AppDir" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="AppDir" Value="[APPDIR]" Action="0" Component_="updater.exe"/>
<ROW IniFile="ApplicationName" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="ApplicationName" Value="[ProductName]" Action="0" Component_="updater.exe"/>
<ROW IniFile="ApplicationVersion" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="ApplicationVersion" Value="[ProductVersion]" Action="0" Component_="updater.exe"/>
<ROW IniFile="CheckFrequency" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="CheckFrequency" Value="2" Action="0" Component_="updater.exe"/>
<ROW IniFile="CompanyName" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="CompanyName" Value="[Manufacturer]" Action="0" Component_="updater.exe"/>
<ROW IniFile="DefaultCommandLine" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="DefaultCommandLine" Value="/checknow" Action="0" Component_="updater.exe"/>
<ROW IniFile="DownloadsFolder" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="DownloadsFolder" Value="[CommonAppDataFolder][Manufacturer]\[ProductName]\updates\" Action="0" Component_="updater.exe"/>
<ROW IniFile="Flags" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="Flags" Value="PerMachine|ShowConfigOptionsButton" Action="0" Component_="updater.exe"/>
<ROW IniFile="ID" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="ID" Value="[UpgradeCode]" Action="0" Component_="updater.exe"/>
<ROW IniFile="URL" FileName="VIGEMB~1.INI|ViGEmBus_Updater.ini" DirProperty="APPDIR" Section="General" Key="URL" Value="https://updates.vigem.org/api/github/ViGEm/ViGEmBus/updates" Action="0" Component_="updater.exe"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
<ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="747"/>
<ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1508"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1397"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99" Builds="DefaultBuild"/>
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="101" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="199" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteRCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="198" Builds="DefaultBuild"/>
<ROW Action="AI_ExtractCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="197" Builds="DefaultBuild"/>
<ROW Action="AI_FindExeLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="196" Builds="DefaultBuild"/>
<ROW Action="AI_ExtractLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="1549" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteRLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="1548" Builds="DefaultBuild"/>
<ROW Action="AI_DeleteLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="6599" Builds="DefaultBuild"/>
<ROW Action="AI_ExtractFiles" Sequence="1399" Builds="DefaultBuild"/>
<ROW Action="AI_DATA_SETTER" Sequence="1398"/>
<ROW Action="AI_REDIRECT_32BIT_FOLDER" Condition="NOT VersionNT64 AND NOT AI_Disable32BitRedirection" Sequence="798"/>
<ROW Action="AI_REDIRECT_32BIT_SH_FOLDER" Condition="NOT VersionNT64 AND NOT AI_Disable32BitRedirection" Sequence="799"/>
<ROW Action="AI_SETPROGRAMFILES64" Condition="VersionNT64" Sequence="748"/>
<ROW Action="AI_SETPROGRAMFILES" Condition="NOT VersionNT64" Sequence="749"/>
<ROW Action="AI_UPDATER_UNINSTALL" Condition="($updater.exe = 2) AND (?updater.exe = 3) AND NOT (UPGRADINGPRODUCTCODE)" Sequence="1551"/>
<ROW Action="AI_ProcessTasks2" Condition="(VersionNT &gt;= 600) AND (REMOVE&lt;&gt;&quot;ALL&quot;)" Sequence="1624"/>
<ROW Action="AI_UninstallTasks2" Condition="(VersionNT &gt;= 600) AND (REMOVE=&quot;ALL&quot;)" Sequence="1699"/>
<ROW Action="ForceReboot" Condition="AI_UPGRADE&lt;&gt;&quot;No&quot; AND OLDPRODUCTS AND AFTERREBOOT&lt;&gt;1" Sequence="1501" SeqType="0"/>
<ROW Action="x64_AddDeviceNode" Condition="( NOT Installed ) AND ( VersionNT64 )" Sequence="6401"/>
<ROW Action="x64_InstallDriver" Condition="( NOT Installed ) AND ( VersionNT64 )" Sequence="6403"/>
<ROW Action="x64_UninstallDevice_Old" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( VersionNT64 )" Sequence="1502"/>
<ROW Action="x64_UninstallDevice" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( VersionNT64 )" Sequence="1504"/>
<ROW Action="x64_UninstallDriver" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( VersionNT64 )" Sequence="1506"/>
<ROW Action="x86_UninstallDevice_Old" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( NOT VersionNT64 )" Sequence="1503"/>
<ROW Action="x86_UninstallDevice" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( NOT VersionNT64 )" Sequence="1505"/>
<ROW Action="x86_UninstallDriver" Condition="( ( NOT Installed ) OR ( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) ) ) AND ( NOT VersionNT64 )" Sequence="1507"/>
<ROW Action="x86_AddDeviceNode" Condition="( NOT Installed ) AND ( NOT VersionNT64 )" Sequence="6402"/>
<ROW Action="x86_InstallDriver" Condition="( NOT Installed ) AND ( NOT VersionNT64 )" Sequence="6404"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="747"/>
<ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
<ROW Action="AI_DpiContentScale" Sequence="52"/>
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="101"/>
<ROW Action="AI_SETPROGRAMFILES64" Condition="VersionNT64" Sequence="748"/>
<ROW Action="AI_SETPROGRAMFILES" Condition="NOT VersionNT64" Sequence="749"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
<ROW Condition="((VersionNT &lt;&gt; 501) AND (VersionNT &lt;&gt; 502))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] can not be installed on [WindowsTypeNT40Display]." DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 500)" Description="[ProductName] can not be installed on [WindowsTypeNT50Display]." DescriptionLocId="AI.LaunchCondition.NoNT50" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="SETUPEXEDIR OR (REMOVE=&quot;ALL&quot;)" Description="This package can only be run from a bootstrapper." DescriptionLocId="AI.LaunchCondition.RequireBootstrapper" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="VersionNT" Description="[ProductName] can not be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent">
<ROW Signature_="AI_EXE_PATH_CU" Root="1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
<ROW Signature_="AI_EXE_PATH_LM" Root="2" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
<ROW Registry="AdvancedInstaller" Root="-1" Key="Software\Caphyon\Advanced Installer" Name="\"/>
<ROW Registry="Caphyon" Root="-1" Key="Software\Caphyon" Name="\"/>
<ROW Registry="LZMA" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA" Name="\"/>
<ROW Registry="Manufacturer" Root="-1" Key="Software\[Manufacturer]" Name="\"/>
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
<ROW Registry="ProductCode" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]" Name="\"/>
<ROW Registry="ProductName" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="\"/>
<ROW Registry="ProductVersion" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="\"/>
<ROW Registry="Software" Root="-1" Key="Software" Name="\"/>
<ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
<ATTRIBUTE name="UsedTheme" value="classic"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="0.0.1" VersionMax="[|ProductVersion]" Attributes="257" ActionProperty="OLDPRODUCTS"/>
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
<ROW UpgradeCode="{0A4A02DE-0BE3-4BF4-91F0-1EA47AD26881}" VersionMax="1.17.333.0" Attributes="1541" ActionProperty="UPGRADE_1"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.ScheduledTasksComponent">
<ROW TaskId="AI_ViGEmBus_Updater" TaskName="ViGEmBus_Updater" Run="[#updater.exe]" CmdLine="/silent" WorkDir="[APPDIR]" UserProp="[%UserDomain]\[LogonUser]" Flags="24576" Trigger="1|1|1|1|0|0|0||0|0" Settings="2|4320" Condition="1" TaskVersion="2.0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.UpdaterComponent">
<ROW Updater="updater.exe" URL="URL" SearchFreq="CheckFrequency" DownloadsFolder="DownloadsFolder" ID="ID" TargetDir="AppDir" AppName="ApplicationName" AppVersion="ApplicationVersion" CompanyName="CompanyName" DefCommandLine="DefaultCommandLine" Flags="Flags" IconPath="ViGEm.ico" IconIndex="0" UnistallCASeq="AI_UPDATER_UNINSTALL" TaskId="AI_ViGEmBus_Updater" Description="[|UpdaterName] [|ProductVersion]"/>
</COMPONENT>
</DOCUMENT>

View File

@@ -35,11 +35,25 @@
<Content Include="ViGEm.ico" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
<WixExtension Include="WixUtilExtension">
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\sys\ViGEmBus.vcxproj">
<Name>ViGEmBus</Name>
<Project>{040101b0-ee5c-4ef1-99ee-9f81c795c001}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">

123
stage0.ps1 Normal file
View File

@@ -0,0 +1,123 @@
Param(
[Parameter(Mandatory=$true)]
[string]$BuildVersion,
[Parameter(Mandatory=$true)]
[string]$Token,
[Parameter(Mandatory=$false)]
[string]$Path = "./artifacts",
[Parameter(Mandatory=$false)]
[Switch]$NoSigning
) #end param
$signTool = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe"
$timestampUrl = "http://timestamp.digicert.com"
$certName = "Nefarius Software Solutions e.U."
function Get-AppVeyorArtifacts
{
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
param(
#The name of the account you wish to download artifacts from
[parameter(Mandatory = $true)]
[string]$Account,
#The name of the project you wish to download artifacts from
[parameter(Mandatory = $true)]
[string]$Project,
#Where to save the downloaded artifacts. Defaults to current directory.
[alias("DownloadDirectory")][string]$Path = '.',
[string]$Token,
#Filter to a specific branch or project directory. You can specify Branch as either branch name ("master") or build version ("0.1.29")
[string]$Branch,
#If you have multiple build jobs, specify which job you wish to retrieve the artifacts from
[string]$JobName,
#Download all files into a single directory, do not preserve any hierarchy that might exist in the artifacts
[switch]$Flat,
[string]$Proxy,
[switch]$ProxyUseDefaultCredentials,
#URL of Appveyor API. You normally shouldn't need to change this.
$apiUrl = 'https://ci.appveyor.com/api'
)
$headers = @{
'Content-type' = 'application/json'
}
if ($Token) {$headers.'Authorization' = "Bearer $token"}
# Prepare proxy args to splat to Invoke-RestMethod
$proxyArgs = @{}
if (-not [string]::IsNullOrEmpty($proxy)) {
$proxyArgs.Add('Proxy', $proxy)
}
if ($proxyUseDefaultCredentials.IsPresent) {
$proxyArgs.Add('ProxyUseDefaultCredentials', $proxyUseDefaultCredentials)
}
$errorActionPreference = 'Stop'
$projectURI = "$apiUrl/projects/$account/$project"
if ($Branch) {$projectURI = $projectURI + "/build/$Branch"}
$projectObject = Invoke-RestMethod -Method Get -Uri $projectURI `
-Headers $headers @proxyArgs
if (-not $projectObject.build.jobs) {throw "No jobs found for this project or the project and/or account name was incorrectly specified"}
if (($projectObject.build.jobs.count -gt 1) -and -not $jobName) {
throw "Multiple Jobs found for the latest build. Please specify the -JobName paramter to select which job you want the artifacts for"
}
if ($JobName) {
$jobid = ($projectObject.build.jobs | Where-Object name -eq "$JobName" | Select-Object -first 1).jobid
if (-not $jobId) {throw "Unable to find a job named $JobName within the latest specified build. Did you spell it correctly?"}
} else {
$jobid = $projectObject.build.jobs[0].jobid
}
$artifacts = Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts" `
-Headers $headers @proxyArgs
$artifacts `
| ? { $psCmdlet.ShouldProcess($_.fileName) } `
| % {
$type = $_.type
$localArtifactPath = $_.fileName -split '/' | % { [Uri]::UnescapeDataString($_) }
if ($flat.IsPresent) {
$localArtifactPath = ($localArtifactPath | select -Last 1)
} else {
$localArtifactPath = $localArtifactPath -join [IO.Path]::DirectorySeparatorChar
}
$localArtifactPath = Join-Path $path $localArtifactPath
$artifactUrl = "$apiUrl/buildjobs/$jobId/artifacts/$($_.fileName)"
Write-Verbose "Downloading $artifactUrl to $localArtifactPath"
New-Item -ItemType Directory -Force -Path (Split-Path -Path $localArtifactPath) | Out-Null
Invoke-RestMethod -Method Get -Uri $artifactUrl -OutFile $localArtifactPath -Headers $headers @proxyArgs
New-Object PSObject -Property @{
'Source' = $artifactUrl
'Type' = $type
'Target' = $localArtifactPath
}
}
}
# Download x64 binaries
Get-AppVeyorArtifacts -Account "nefarius" -Project "ViGemBus" -Path $Path -Token $Token -Branch $BuildVersion -JobName "Platform: x64"
# Download x86 binaries
Get-AppVeyorArtifacts -Account "nefarius" -Project "ViGemBus" -Path $Path -Token $Token -Branch $BuildVersion -JobName "Platform: x86"
# List of files to sign
$files = "`".\artifacts\disk1\*.cab`" "
if ($NoSigning -eq $false) {
# sign with only one certificate
Invoke-Expression "& `"$signTool`" sign /v /as /n `"$certName`" /tr $timestampUrl /fd sha256 /td sha256 $files"
}
# Print helper job names for sign portal
"ViGemBus x86 v$BuildVersion $(Get-Date -Format "dd.MM.yyyy")"
"ViGemBus x64 v$BuildVersion $(Get-Date -Format "dd.MM.yyyy")"

View File

@@ -44,7 +44,7 @@ void* operator new
size_t size
)
{
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
}
void* operator new[]
@@ -52,7 +52,7 @@ void* operator new[]
size_t size
)
{
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
}
void operator delete
@@ -107,7 +107,7 @@ void* __CRTDECL operator new
size_t size
)
{
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
}
void* __CRTDECL operator new[]
@@ -115,7 +115,7 @@ void* __CRTDECL operator new[]
size_t size
)
{
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
}
void __CRTDECL operator delete

20
sys/Dmf.props Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_PropertySheetDisplayName>Driver Module Framework</_PropertySheetDisplayName>
<!-- By default, look for DMF in parent root directory, otherwise use environment variable value -->
<DmfRootPath Condition="'$(DmfRootPath)' == ''">$(SolutionDir)..\</DmfRootPath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(DmfRootPath)\DMF\Modules.Library;$(DmfRootPath)\DMF\Modules.Template;$(DmfRootPath)\DMF\Modules.Library.Tests;$(DmfRootPath)\DMF\Framework;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies Condition="'$(DriverType)'=='KMDF'">$(DmfRootPath)\$(Configuration)\$(PlatformName)\lib\DmfK\DmfK.lib;$(DmfRootPath)\$(Configuration)\$(PlatformName)\individual_libs\DmfKModules.Template\DmfKModules.Template.lib;%(AdditionalDependencies);</AdditionalDependencies>
<AdditionalDependencies Condition="'$(DriverType)'=='UMDF'">$(DmfRootPath)\$(Configuration)\$(PlatformName)\lib\DmfU\DmfU.lib;$(DmfRootPath)\$(Configuration)\$(PlatformName)\individual_libs\DmfUModules.Template\DmfUModules.Template.lib;%(AdditionalDependencies);</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@@ -34,7 +34,8 @@
#include "Driver.h"
#include "driver.tmh"
#include "trace.h"
#include "Driver.tmh"
#include <wdmguid.h>
#ifdef ALLOC_PRAGMA
@@ -45,7 +46,7 @@
#pragma alloc_text (PAGE, Bus_EvtDriverContextCleanup)
#endif
#include "Queue.hpp"
#include "EmulationTargetPDO.hpp"
#include "XusbPdo.hpp"
#include "Ds4Pdo.hpp"
@@ -63,40 +64,42 @@ EXTERN_C_START
//
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDFDRIVER driver;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDFDRIVER driver;
WDF_OBJECT_ATTRIBUTES attributes;
KdPrint((DRIVERNAME "Virtual Gamepad Emulation Bus Driver [built: %s %s]\n", __DATE__, __TIME__));
KdPrint((DRIVERNAME "Virtual Gamepad Emulation Bus Driver [built: %s %s]\n", __DATE__, __TIME__));
//
// Initialize WPP Tracing
//
WPP_INIT_TRACING(DriverObject, RegistryPath);
//
// Initialize WPP Tracing
//
WPP_INIT_TRACING(DriverObject, RegistryPath);
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Loading Virtual Gamepad Emulation Bus Driver [built: %s %s]",
__DATE__, __TIME__);
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Loading Virtual Gamepad Emulation Bus Driver"
);
//
// Register cleanup callback
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = Bus_EvtDriverContextCleanup;
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
WDF_DRIVER_CONFIG_INIT(&config, Bus_EvtDeviceAdd);
//
// Register cleanup callback
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = Bus_EvtDriverContextCleanup;
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &driver);
WDF_DRIVER_CONFIG_INIT(&config, Bus_EvtDeviceAdd);
if (!NT_SUCCESS(status))
{
WPP_CLEANUP(DriverObject);
KdPrint((DRIVERNAME "WdfDriverCreate failed with status 0x%x\n", status));
}
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &driver);
return status;
if (!NT_SUCCESS(status))
{
WPP_CLEANUP(DriverObject);
KdPrint((DRIVERNAME "WdfDriverCreate failed with status 0x%x\n", status));
}
return status;
}
//
@@ -104,168 +107,168 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry
//
NTSTATUS Bus_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
WDF_CHILD_LIST_CONFIG config;
NTSTATUS status;
WDFDEVICE device;
WDF_IO_QUEUE_CONFIG queueConfig;
PNP_BUS_INFORMATION busInfo;
WDFQUEUE queue;
WDF_FILEOBJECT_CONFIG foConfig;
WDF_OBJECT_ATTRIBUTES fdoAttributes;
WDF_OBJECT_ATTRIBUTES fileHandleAttributes;
PFDO_DEVICE_DATA pFDOData;
PWSTR pSymbolicNameList;
WDF_CHILD_LIST_CONFIG config;
NTSTATUS status;
WDFDEVICE device;
WDF_IO_QUEUE_CONFIG queueConfig;
PNP_BUS_INFORMATION busInfo;
WDFQUEUE queue;
WDF_FILEOBJECT_CONFIG foConfig;
WDF_OBJECT_ATTRIBUTES fdoAttributes;
WDF_OBJECT_ATTRIBUTES fileHandleAttributes;
PFDO_DEVICE_DATA pFDOData;
PWSTR pSymbolicNameList;
UNREFERENCED_PARAMETER(Driver);
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
#pragma region Check for duplicated FDO
//
// Note: this could be avoided if converted to non-PNP driver
// and use of named device object. Food for thought for future.
//
status = IoGetDeviceInterfaces(
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
NULL,
0, // Important!
&pSymbolicNameList
);
if (NT_SUCCESS(status))
{
const bool deviceAlreadyExists = (0 != *pSymbolicNameList);
ExFreePool(pSymbolicNameList);
//
// Note: this could be avoided if converted to non-PNP driver
// and use of named device object. Food for thought for future.
//
if (deviceAlreadyExists)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"Device with interface GUID {%!GUID!} already exists (%ws)",
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
pSymbolicNameList
);
status = IoGetDeviceInterfaces(
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
NULL,
0, // Important!
&pSymbolicNameList
);
if (NT_SUCCESS(status))
{
const bool deviceAlreadyExists = (0 != *pSymbolicNameList);
ExFreePool(pSymbolicNameList);
return STATUS_RESOURCE_IN_USE;
}
}
else
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"IoGetDeviceInterfaces failed with status %!STATUS!",
status);
}
if (deviceAlreadyExists)
{
TraceError(
TRACE_DRIVER,
"Device with interface GUID {%!GUID!} already exists (%ws)",
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
pSymbolicNameList
);
return STATUS_RESOURCE_IN_USE;
}
}
else
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"IoGetDeviceInterfaces failed with status %!STATUS!",
status);
}
#pragma endregion
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
// More than one process may talk to the bus at the same time
WdfDeviceInitSetExclusive(DeviceInit, FALSE);
// Bus is power policy owner over all PDOs
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE);
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
// More than one process may talk to the bus at the same time
WdfDeviceInitSetExclusive(DeviceInit, FALSE);
// Bus is power policy owner over all PDOs
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE);
#pragma region Prepare child list
WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo);
WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo);
config.EvtChildListIdentificationDescriptionCompare = EmulationTargetPDO::EvtChildListIdentificationDescriptionCompare;
config.EvtChildListIdentificationDescriptionCompare = EmulationTargetPDO::EvtChildListIdentificationDescriptionCompare;
WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
#pragma endregion
#pragma region Assign File Object Configuration
WDF_FILEOBJECT_CONFIG_INIT(&foConfig, Bus_DeviceFileCreate, Bus_FileClose, NULL);
WDF_FILEOBJECT_CONFIG_INIT(&foConfig, Bus_DeviceFileCreate, Bus_FileClose, NULL);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileHandleAttributes, FDO_FILE_DATA);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileHandleAttributes, FDO_FILE_DATA);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &foConfig, &fileHandleAttributes);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &foConfig, &fileHandleAttributes);
#pragma endregion
#pragma region Create FDO
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);
status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"WdfDeviceCreate failed with status %!STATUS!",
status);
return status;
}
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_DRIVER,
"WdfDeviceCreate failed with status %!STATUS!",
status);
return status;
}
pFDOData = FdoGetData(device);
if (pFDOData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"FdoGetData failed");
return STATUS_UNSUCCESSFUL;
}
pFDOData = FdoGetData(device);
if (pFDOData == NULL)
{
TraceError(
TRACE_DRIVER,
"FdoGetData failed");
return STATUS_UNSUCCESSFUL;
}
pFDOData->InterfaceReferenceCounter = 0;
pFDOData->NextSessionId = FDO_FIRST_SESSION_ID;
pFDOData->InterfaceReferenceCounter = 0;
pFDOData->NextSessionId = FDO_FIRST_SESSION_ID;
#pragma endregion
#pragma region Create default I/O queue for FDO
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;
queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;
__analysis_assume(queueConfig.EvtIoStop != 0);
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
__analysis_assume(queueConfig.EvtIoStop == 0);
__analysis_assume(queueConfig.EvtIoStop != 0);
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
__analysis_assume(queueConfig.EvtIoStop == 0);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"WdfIoQueueCreate failed with status %!STATUS!",
status);
return status;
}
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_DRIVER,
"WdfIoQueueCreate failed with status %!STATUS!",
status);
return status;
}
#pragma endregion
#pragma region Expose FDO interface
status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BUSENUM_VIGEM, NULL);
status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BUSENUM_VIGEM, NULL);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
status);
return status;
}
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_DRIVER,
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
status);
return status;
}
#pragma endregion
#pragma region Set bus information
busInfo.BusTypeGuid = GUID_BUS_TYPE_USB;
busInfo.LegacyBusType = PNPBus;
busInfo.BusNumber = 0;
busInfo.BusTypeGuid = GUID_BUS_TYPE_USB;
busInfo.LegacyBusType = PNPBus;
busInfo.BusNumber = 0;
WdfDeviceSetBusInformationForChildren(device, &busInfo);
WdfDeviceSetBusInformationForChildren(device, &busInfo);
#pragma endregion
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
return status;
return status;
}
// Gets called when the user-land process (or kernel driver) exits or closes the handle,
@@ -274,60 +277,60 @@ NTSTATUS Bus_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
_Use_decl_annotations_
VOID
Bus_DeviceFileCreate(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDFFILEOBJECT FileObject
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDFFILEOBJECT FileObject
)
{
NTSTATUS status = STATUS_INVALID_PARAMETER;
PFDO_FILE_DATA pFileData = NULL;
PFDO_DEVICE_DATA pFDOData = NULL;
LONG refCount = 0;
LONG sessionId = 0;
NTSTATUS status = STATUS_INVALID_PARAMETER;
PFDO_FILE_DATA pFileData = NULL;
PFDO_DEVICE_DATA pFDOData = NULL;
LONG refCount = 0;
LONG sessionId = 0;
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(Request);
PAGED_CODE();
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
pFileData = FileObjectGetData(FileObject);
pFileData = FileObjectGetData(FileObject);
if (pFileData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
FileObject);
}
else
{
pFDOData = FdoGetData(Device);
if (pFDOData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"FdoGetData failed");
status = STATUS_NO_SUCH_DEVICE;
}
else
{
refCount = InterlockedIncrement(&pFDOData->InterfaceReferenceCounter);
sessionId = InterlockedIncrement(&pFDOData->NextSessionId);
if (pFileData == NULL)
{
TraceError(
TRACE_DRIVER,
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
FileObject);
}
else
{
pFDOData = FdoGetData(Device);
if (pFDOData == NULL)
{
TraceError(
TRACE_DRIVER,
"FdoGetData failed");
status = STATUS_NO_SUCH_DEVICE;
}
else
{
refCount = InterlockedIncrement(&pFDOData->InterfaceReferenceCounter);
sessionId = InterlockedIncrement(&pFDOData->NextSessionId);
pFileData->SessionId = sessionId;
status = STATUS_SUCCESS;
pFileData->SessionId = sessionId;
status = STATUS_SUCCESS;
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"File/session id = %d, device ref. count = %d",
(int)sessionId, (int)refCount);
}
}
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"File/session id = %d, device ref. count = %d",
(int)sessionId, (int)refCount);
}
}
WdfRequestComplete(Request, status);
WdfRequestComplete(Request, status);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
}
//
@@ -336,139 +339,139 @@ Bus_DeviceFileCreate(
_Use_decl_annotations_
VOID
Bus_FileClose(
WDFFILEOBJECT FileObject
WDFFILEOBJECT FileObject
)
{
WDFDEVICE device;
WDFDEVICE hChild;
NTSTATUS status;
WDFCHILDLIST list;
WDF_CHILD_LIST_ITERATOR iterator;
WDF_CHILD_RETRIEVE_INFO childInfo;
PDO_IDENTIFICATION_DESCRIPTION description;
PFDO_FILE_DATA pFileData = NULL;
PFDO_DEVICE_DATA pFDOData = NULL;
LONG refCount = 0;
WDFDEVICE device;
WDFDEVICE hChild;
NTSTATUS status;
WDFCHILDLIST list;
WDF_CHILD_LIST_ITERATOR iterator;
WDF_CHILD_RETRIEVE_INFO childInfo;
PDO_IDENTIFICATION_DESCRIPTION description;
PFDO_FILE_DATA pFileData = NULL;
PFDO_DEVICE_DATA pFDOData = NULL;
LONG refCount = 0;
PAGED_CODE();
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
// Check common context
pFileData = FileObjectGetData(FileObject);
if (pFileData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
FileObject);
return;
}
// Check common context
pFileData = FileObjectGetData(FileObject);
if (pFileData == NULL)
{
TraceError(
TRACE_DRIVER,
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
FileObject);
return;
}
device = WdfFileObjectGetDevice(FileObject);
device = WdfFileObjectGetDevice(FileObject);
pFDOData = FdoGetData(device);
if (pFDOData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"FdoGetData failed");
status = STATUS_NO_SUCH_DEVICE;
}
else
{
refCount = InterlockedDecrement(&pFDOData->InterfaceReferenceCounter);
pFDOData = FdoGetData(device);
if (pFDOData == NULL)
{
TraceError(
TRACE_DRIVER,
"FdoGetData failed");
status = STATUS_NO_SUCH_DEVICE;
}
else
{
refCount = InterlockedDecrement(&pFDOData->InterfaceReferenceCounter);
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Device ref. count = %d",
(int)refCount);
}
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Device ref. count = %d",
(int)refCount);
}
list = WdfFdoGetDefaultChildList(device);
list = WdfFdoGetDefaultChildList(device);
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren);
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren);
WdfChildListBeginIteration(list, &iterator);
WdfChildListBeginIteration(list, &iterator);
for (;;)
{
WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);
WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
for (;;)
{
WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);
WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo);
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
{
break;
}
status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo);
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
{
break;
}
//TraceEvents(TRACE_LEVEL_VERBOSE,
// TRACE_DRIVER,
// "PDO properties: status = %!STATUS!, pdoPID = %d, curPID = %d, pdoSID = %d, curSID = %d, internal = %d",
// (int)childInfo.Status,
// (int)description.OwnerProcessId,
// (int)CURRENT_PROCESS_ID(),
// (int)description.SessionId,
// (int)pFileData->SessionId,
// (int)description.OwnerIsDriver
//);
//TraceVerbose(
// TRACE_DRIVER,
// "PDO properties: status = %!STATUS!, pdoPID = %d, curPID = %d, pdoSID = %d, curSID = %d, internal = %d",
// (int)childInfo.Status,
// (int)description.OwnerProcessId,
// (int)CURRENT_PROCESS_ID(),
// (int)description.SessionId,
// (int)pFileData->SessionId,
// (int)description.OwnerIsDriver
//);
// Only unplug devices with matching session id
if (childInfo.Status == WdfChildListRetrieveDeviceSuccess
&& description.SessionId == pFileData->SessionId)
{
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Unplugging device with serial %d",
description.SerialNo);
// Only unplug devices with matching session id
if (childInfo.Status == WdfChildListRetrieveDeviceSuccess
&& description.SessionId == pFileData->SessionId)
{
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"Unplugging device with serial %d",
description.SerialNo);
// "Unplug" child
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
status);
}
}
}
// "Unplug" child
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_DRIVER,
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
status);
}
}
}
WdfChildListEndIteration(list, &iterator);
WdfChildListEndIteration(list, &iterator);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
}
VOID
Bus_EvtDriverContextCleanup(
_In_ WDFOBJECT DriverObject
_In_ WDFOBJECT DriverObject
)
/*++
Routine Description:
Free all the resources allocated in DriverEntry.
Free all the resources allocated in DriverEntry.
Arguments:
DriverObject - handle to a WDF Driver object.
DriverObject - handle to a WDF Driver object.
Return Value:
VOID.
VOID.
--*/
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(DriverObject);
PAGED_CODE();
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
//
// Stop WPP Tracing
//
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
//
// Stop WPP Tracing
//
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
}

View File

@@ -35,15 +35,13 @@
#pragma once
#include "trace.h"
#pragma warning(disable:5040)
#include <DmfModules.Library.h>
#pragma warning(default:5040)
#include <ntddk.h>
#include <wdf.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include <initguid.h>
#include <ViGEm/km/BusShared.h>
#include "Queue.hpp"
#pragma region Macros

View File

@@ -44,8 +44,8 @@
PCWSTR ViGEm::Bus::Targets::EmulationTargetDS4::_deviceDescription = L"Virtual DualShock 4 Controller";
ViGEm::Bus::Targets::EmulationTargetDS4::EmulationTargetDS4(ULONG Serial, LONG SessionId, USHORT VendorId,
USHORT ProductId) : EmulationTargetPDO(
Serial, SessionId, VendorId, ProductId)
USHORT ProductId) : EmulationTargetPDO(
Serial, SessionId, VendorId, ProductId)
{
this->_TargetType = DualShock4Wired;
this->_UsbConfigurationDescriptionSize = DS4_DESCRIPTOR_SIZE;
@@ -72,7 +72,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = RtlUnicodeStringInit(DeviceDescription, _deviceDescription);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"RtlUnicodeStringInit failed with status %!STATUS!",
status);
@@ -86,7 +86,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
status);
@@ -101,7 +101,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
status);
@@ -114,7 +114,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"WdfPdoInitAddCompatibleID (#01) failed with status %!STATUS!",
status);
@@ -126,7 +126,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"WdfPdoInitAddCompatibleID (#02) failed with status %!STATUS!",
status);
@@ -138,7 +138,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_DS4,
"WdfPdoInitAddCompatibleID (#03) failed with status %!STATUS!",
status);
@@ -200,10 +200,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfTimerCreate failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfTimerCreate failed with status %!STATUS!",
status);
return status;
}
@@ -224,10 +224,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfDriverOpenParametersRegistryKey failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfDriverOpenParametersRegistryKey failed with status %!STATUS!",
status);
return status;
}
@@ -244,10 +244,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
return status;
}
@@ -264,10 +264,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
return status;
}
@@ -285,10 +285,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfRegistryCreateKey failed with status %!STATUS!",
status);
return status;
}
@@ -304,14 +304,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_DS4,
"MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
this->_TargetMacAddress.Vendor0,
this->_TargetMacAddress.Vendor1,
this->_TargetMacAddress.Vendor2,
this->_TargetMacAddress.Nic0,
this->_TargetMacAddress.Nic1,
this->_TargetMacAddress.Nic2);
TRACE_DS4,
"MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
this->_TargetMacAddress.Vendor0,
this->_TargetMacAddress.Vendor1,
this->_TargetMacAddress.Vendor2,
this->_TargetMacAddress.Nic0,
this->_TargetMacAddress.Nic1,
this->_TargetMacAddress.Nic2);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
@@ -326,19 +326,19 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfRegistryAssignValue failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfRegistryAssignValue failed with status %!STATUS!",
status);
return status;
}
}
else if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_DS4,
"WdfRegistryQueryValue failed with status %!STATUS!",
status);
TraceError(
TRACE_DS4,
"WdfRegistryQueryValue failed with status %!STATUS!",
status);
return status;
}
@@ -428,20 +428,20 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SelectConfiguration(PURB Urb)
if (Urb->UrbHeader.Length < DS4_CONFIGURATION_SIZE)
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor");
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor");
return STATUS_INVALID_PARAMETER;
}
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectConfiguration.Interface;
TraceEvents(TRACE_LEVEL_VERBOSE,
TRACE_DS4,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
static_cast<int>(pInfo->Length),
static_cast<int>(pInfo->InterfaceNumber),
static_cast<int>(pInfo->AlternateSetting),
pInfo->NumberOfPipes);
TraceVerbose(
TRACE_DS4,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
static_cast<int>(pInfo->Length),
static_cast<int>(pInfo->InterfaceNumber),
static_cast<int>(pInfo->AlternateSetting),
pInfo->NumberOfPipes);
pInfo->Class = 0x03; // HID
pInfo->SubClass = 0x00;
@@ -478,10 +478,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
{
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST* pRequest = &Urb->UrbControlVendorClassRequest;
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_CLASS_INTERFACE");
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
">> >> >> TransferFlags = 0x%X, Request = 0x%X, Value = 0x%X, Index = 0x%X, BufLen = %d",
pRequest->TransferFlags,
@@ -497,7 +497,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
UCHAR reportId = hid_get_report_id(pRequest);
UCHAR reportType = hid_get_report_type(pRequest);
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
">> >> >> >> GET_REPORT(%d): %d",
reportType, reportId);
@@ -584,7 +584,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
UCHAR reportId = hid_get_report_id(pRequest);
UCHAR reportType = hid_get_report_type(pRequest);
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
">> >> >> >> SET_REPORT(%d): %d",
reportType, reportId);
@@ -882,7 +882,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetDescriptorFromInterface(
struct _URB_CONTROL_DESCRIPTOR_REQUEST* pRequest = &Urb->UrbControlDescriptorRequest;
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
">> >> >> _URB_CONTROL_DESCRIPTOR_REQUEST: Buffer Length %d",
pRequest->TransferBufferLength);
@@ -910,7 +910,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbSelectInterface(PURB Urb)
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PURB Urb)
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
"Index = %d",
Urb->UrbControlDescriptorRequest.Index);
@@ -932,7 +932,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
}
case 1:
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
"LanguageId = 0x%X",
Urb->UrbControlDescriptorRequest.LanguageId);
@@ -963,7 +963,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
}
case 2:
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_USBPDO,
"LanguageId = 0x%X",
Urb->UrbControlDescriptorRequest.LanguageId);
@@ -999,14 +999,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request)
{
NTSTATUS status;
NTSTATUS status = STATUS_SUCCESS;
WDFREQUEST notifyRequest;
// Data coming FROM us TO higher driver
if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN
&& pTransfer->PipeHandle == reinterpret_cast<USBD_PIPE_HANDLE>(0xFFFF0084))
{
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> Incoming request, queuing...");
@@ -1023,16 +1023,15 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_UR
static_cast<PUCHAR>(pTransfer->TransferBuffer) + DS4_OUTPUT_BUFFER_OFFSET,
DS4_OUTPUT_BUFFER_LENGTH);
// Notify user-mode process that new data is available
status = WdfIoQueueRetrieveNextRequest(this->_PendingNotificationRequests, &notifyRequest);
if (NT_SUCCESS(status))
if (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(
this->_PendingNotificationRequests,
&notifyRequest)))
{
PDS4_REQUEST_NOTIFICATION notify = NULL;
PDS4_REQUEST_NOTIFICATION notify = nullptr;
status = WdfRequestRetrieveOutputBuffer(
notifyRequest,
sizeof(DS4_REQUEST_NOTIFICATION),
notifyRequest,
sizeof(DS4_REQUEST_NOTIFICATION),
reinterpret_cast<PVOID*>(&notify),
nullptr
);
@@ -1044,17 +1043,45 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_UR
notify->SerialNo = this->_SerialNo;
notify->Report = this->_OutputReport;
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
notify,
sizeof(DS4_REQUEST_NOTIFICATION)
);
WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size);
}
else
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_USBPDO,
"WdfRequestRetrieveOutputBuffer failed with status %!STATUS!",
status);
}
}
else
{
PVOID clientBuffer, contextBuffer;
if (NT_SUCCESS(DMF_BufferQueue_Fetch(
this->_UsbInterruptOutBufferQueue,
&clientBuffer,
&contextBuffer
)))
{
RtlCopyMemory(
clientBuffer,
&this->_OutputReport,
DS4_OUTPUT_BUFFER_LENGTH
);
*static_cast<size_t*>(contextBuffer) = DS4_OUTPUT_BUFFER_LENGTH;
TraceVerbose(TRACE_USBPDO, "Queued %Iu bytes", DS4_OUTPUT_BUFFER_LENGTH);
DMF_BufferQueue_Enqueue(this->_UsbInterruptOutBufferQueue, clientBuffer);
}
}
return status;
}
@@ -1090,9 +1117,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
{
NTSTATUS status;
WDFREQUEST usbRequest;
/*
* The logic here is unusual to keep backwards compatibility with the
* The logic here is unusual to keep backwards compatibility with the
* original API that didn't allow submitting the full report.
*/
@@ -1121,13 +1148,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
* Skip first byte as it contains the never changing report ID
*/
//
// "Old" API which only allows to update partial report
//
//
// "Old" API which only allows to update partial report
//
if (pSubmit->Size == sizeof(DS4_SUBMIT_REPORT))
{
TraceDbg(TRACE_DS4, "Received DS4_SUBMIT_REPORT update");
TraceVerbose(TRACE_DS4, "Received DS4_SUBMIT_REPORT update");
RtlCopyBytes(
&this->_Report[1],
&(static_cast<PDS4_SUBMIT_REPORT>(NewReport))->Report,
@@ -1140,15 +1167,15 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
//
if (pSubmit->Size == sizeof(DS4_SUBMIT_REPORT_EX))
{
TraceDbg(TRACE_DS4, "Received DS4_SUBMIT_REPORT_EX update");
TraceVerbose(TRACE_DS4, "Received DS4_SUBMIT_REPORT_EX update");
RtlCopyBytes(
&this->_Report[1],
&(static_cast<PDS4_SUBMIT_REPORT_EX>(NewReport))->Report,
sizeof((static_cast<PDS4_SUBMIT_REPORT_EX>(NewReport))->Report)
);
}
if (buffer)
RtlCopyBytes(buffer, this->_Report, DS4_REPORT_SIZE);
@@ -1160,8 +1187,8 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
VOID ViGEm::Bus::Targets::EmulationTargetDS4::ReverseByteArray(PUCHAR Array, INT Length)
{
const auto s = static_cast<PUCHAR>(ExAllocatePoolWithTag(
NonPagedPool,
const auto s = static_cast<PUCHAR>(ExAllocatePoolZero(
NonPagedPoolNx,
sizeof(UCHAR) * Length,
'U4SD'
));
@@ -1193,6 +1220,74 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::GenerateRandomMacAddress(PMAC_ADDR
Address->Nic2 = RtlRandomEx(&seed) % 0xFF;
}
void ViGEm::Bus::Targets::EmulationTargetDS4::ProcessPendingNotification(WDFQUEUE Queue)
{
NTSTATUS status;
WDFREQUEST request;
PVOID clientBuffer, contextBuffer;
PDS4_REQUEST_NOTIFICATION notify = nullptr;
FuncEntry(TRACE_DS4);
//
// Loop through and drain all queued requests until buffer is empty
//
while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(Queue, &request)))
{
status = DMF_BufferQueue_Dequeue(
this->_UsbInterruptOutBufferQueue,
&clientBuffer,
&contextBuffer
);
//
// Shouldn't happen, but if so, error out
//
if (!NT_SUCCESS(status))
{
//
// Don't requeue request as we maya be out of order now
//
WdfRequestComplete(request, status);
continue;
}
if (NT_SUCCESS(WdfRequestRetrieveOutputBuffer(
request,
sizeof(DS4_REQUEST_NOTIFICATION),
reinterpret_cast<PVOID*>(&notify),
nullptr
)))
{
//
// Assign values to output buffer
//
notify->Size = sizeof(DS4_REQUEST_NOTIFICATION);
notify->SerialNo = this->_SerialNo;
notify->Report = *static_cast<PDS4_OUTPUT_REPORT>(clientBuffer);
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
notify,
sizeof(DS4_REQUEST_NOTIFICATION)
);
WdfRequestCompleteWithInformation(request, status, notify->Size);
}
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
//
// If no more buffer to process, exit loop and await next callback
//
if (DMF_BufferQueue_Count(this->_UsbInterruptOutBufferQueue) == 0)
{
break;
}
}
TraceVerbose(TRACE_USBPDO, "%!FUNC! Exit");
}
VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
_In_ WDFTIMER Timer
)
@@ -1202,7 +1297,7 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
WDFREQUEST usbRequest;
TraceDbg(TRACE_DS4, "%!FUNC! Entry");
FuncEntry(TRACE_DS4);
// Get pending USB request
const auto status = WdfIoQueueRetrieveNextRequest(ctx->_PendingUsbInRequests, &usbRequest);
@@ -1231,5 +1326,5 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
WdfRequestComplete(usbRequest, status);
}
TraceDbg(TRACE_DS4, "%!FUNC! Exit with status %!STATUS!", status);
TraceVerbose(TRACE_DS4, "%!FUNC! Exit with status %!STATUS!", status);
}

View File

@@ -105,7 +105,10 @@ namespace ViGEm::Bus::Targets
static VOID ReverseByteArray(PUCHAR Array, INT Length);
static VOID GenerateRandomMacAddress(PMAC_ADDRESS Address);
protected:
void ProcessPendingNotification(WDFQUEUE Queue) override;
private:
static PCWSTR _deviceDescription;
static const int HID_REQUEST_GET_REPORT = 0x01;

View File

@@ -87,7 +87,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfPdoInitAssignDeviceID failed with status %!STATUS!",
status);
@@ -98,7 +98,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
status = RtlUnicodeStringPrintf(&buffer, L"%02d", this->_SerialNo);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"RtlUnicodeStringPrintf failed with status %!STATUS!",
status);
@@ -109,7 +109,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfPdoInitAssignInstanceID failed with status %!STATUS!",
status);
@@ -120,7 +120,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
status = WdfPdoInitAddDeviceText(DeviceInit, &deviceDescription, &deviceLocation, 0x409);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfPdoInitAddDeviceText failed with status %!STATUS!",
status);
@@ -156,14 +156,14 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &this->_PdoDevice);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfDeviceCreate failed with status %!STATUS!",
status);
break;
}
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
"Created PDO 0x%p",
this->_PdoDevice);
@@ -179,7 +179,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
status);
@@ -200,7 +200,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"Couldn't initialize additional contexts: %!STATUS!",
status);
@@ -210,7 +210,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
#pragma endregion
#pragma region Create Queues & Locks
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = this->_PdoDevice;
@@ -225,7 +225,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfIoQueueCreate (PendingUsbInRequests) failed with status %!STATUS!",
status);
@@ -246,13 +246,27 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfIoQueueCreate (PendingNotificationRequests) failed with status %!STATUS!",
status);
break;
}
status = WdfIoQueueReadyNotify(
this->_PendingNotificationRequests,
EvtWdfIoPendingNotificationQueueState,
this
);
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_BUSPDO,
"WdfIoQueueReadyNotify (PendingNotificationRequests) failed with status %!STATUS!",
status);
break;
}
#pragma endregion
#pragma region Default I/O queue setup
@@ -272,7 +286,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfIoQueueCreate (Default) failed with status %!STATUS!",
status);
@@ -314,7 +328,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtDeviceContextCleanup(
IN WDFOBJECT Device
)
{
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Entry");
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Entry");
const auto ctx = EmulationTargetPdoGetContext(Device);
@@ -351,13 +365,13 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtDeviceContextCleanup(
);
}
}
//
// PDO device object getting disposed, free context object
//
delete ctx->Target;
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Exit");
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit");
}
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::SubmitReport(PVOID NewReport)
@@ -412,21 +426,21 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFREQUEST
else
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_BUSPDO,
"KeWaitForSingleObject failed with status %!STATUS!",
status
TRACE_BUSPDO,
"KeWaitForSingleObject failed with status %!STATUS!",
status
);
}
}
status = WdfRequestForwardToIoQueue(Request, this->_WaitDeviceReadyRequests);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_BUSPDO,
"WdfRequestForwardToIoQueue failed with status %!STATUS!",
status
TraceError(
TRACE_BUSPDO,
"WdfRequestForwardToIoQueue failed with status %!STATUS!",
status
);
return status;
@@ -435,23 +449,23 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFREQUEST
OBJECT_ATTRIBUTES threadOb;
InitializeObjectAttributes(&threadOb, NULL,
OBJ_KERNEL_HANDLE, NULL, NULL);
OBJ_KERNEL_HANDLE, NULL, NULL);
status = PsCreateSystemThread(&this->_WaitDeviceReadyCompletionWorkerThreadHandle,
static_cast<ACCESS_MASK>(0L),
&threadOb,
nullptr,
nullptr,
WaitDeviceReadyCompletionWorkerRoutine,
this
static_cast<ACCESS_MASK>(0L),
&threadOb,
nullptr,
nullptr,
WaitDeviceReadyCompletionWorkerRoutine,
this
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TRACE_BUSPDO,
"PsCreateSystemThread failed with status %!STATUS!",
status
TraceError(
TRACE_BUSPDO,
"PsCreateSystemThread failed with status %!STATUS!",
status
);
}
@@ -463,7 +477,9 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoPrepare(WDFDEVICE ParentDevice
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_IO_QUEUE_CONFIG plugInQueueConfig;
DMF_MODULE_ATTRIBUTES moduleAttributes;
DMF_CONFIG_BufferQueue dmfBufferCfg;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = ParentDevice;
@@ -478,12 +494,47 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoPrepare(WDFDEVICE ParentDevice
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSPDO,
"WdfIoQueueCreate (PendingPlugInRequests) failed with status %!STATUS!",
status);
}
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = ParentDevice;
DMF_CONFIG_BufferQueue_AND_ATTRIBUTES_INIT(
&dmfBufferCfg,
&moduleAttributes
);
// Don't auto-grow; start dropping packets on overrun
dmfBufferCfg.SourceSettings.EnableLookAside = FALSE;
// Maximum number of buffers to be filled and kept queued
dmfBufferCfg.SourceSettings.BufferCount = MAX_OUT_BUFFER_QUEUE_COUNT;
// Maximum byte count per buffer
dmfBufferCfg.SourceSettings.BufferSize = MAX_OUT_BUFFER_QUEUE_SIZE;
// Field to store real buffer content length
dmfBufferCfg.SourceSettings.BufferContextSize = sizeof(size_t);
// "Expensive" memory ;)
dmfBufferCfg.SourceSettings.PoolType = NonPagedPoolNx;
status = DMF_BufferQueue_Create(
ParentDevice,
&moduleAttributes,
&attributes,
&this->_UsbInterruptOutBufferQueue
);
if (!NT_SUCCESS(status))
{
TraceError(
TRACE_BUSPDO,
"DMF_BufferQueue_Create failed with status %!STATUS!",
status
);
}
return status;
}
@@ -564,8 +615,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
timeout.QuadPart = WDF_REL_TIMEOUT_IN_SEC(1);
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_BUSPDO,
"Waiting for 1 second to complete PDO boot..."
TRACE_BUSPDO,
"Waiting for 1 second to complete PDO boot..."
);
NTSTATUS status = KeWaitForSingleObject(
@@ -584,8 +635,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
if (!NT_SUCCESS(WdfIoQueueRetrieveNextRequest(ctx->_WaitDeviceReadyRequests, &waitRequest)))
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_BUSPDO,
"No pending device wait request available"
TRACE_BUSPDO,
"No pending device wait request available"
);
break;
}
@@ -593,8 +644,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
if (status == STATUS_TIMEOUT)
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_BUSPDO,
"Device wait request timed out, completing with error"
TRACE_BUSPDO,
"Device wait request timed out, completing with error"
);
//
@@ -607,8 +658,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
if (NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_BUSPDO,
"Device wait request completed successfully"
TRACE_BUSPDO,
"Device wait request completed successfully"
);
//
@@ -617,8 +668,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
WdfRequestComplete(waitRequest, STATUS_SUCCESS);
break;
}
}
while (FALSE);
} while (FALSE);
ZwClose(ctx->_WaitDeviceReadyCompletionWorkerThreadHandle);
ctx->_WaitDeviceReadyCompletionWorkerThreadHandle = nullptr;
@@ -631,7 +681,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::DumpAsHex(PCSTR Prefix, PVOID Buffer,
#ifdef DBG
size_t dumpBufferLength = ((BufferLength * sizeof(CHAR)) * 2) + 1;
PSTR dumpBuffer = static_cast<PSTR>(ExAllocatePoolWithTag(
PSTR dumpBuffer = static_cast<PSTR>(ExAllocatePoolZero(
NonPagedPoolNx,
dumpBufferLength,
'1234'
@@ -646,7 +696,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::DumpAsHex(PCSTR Prefix, PVOID Buffer,
sprintf(&dumpBuffer[i * 2], "%02X", static_cast<PUCHAR>(Buffer)[i]);
}
TraceDbg(TRACE_BUSPDO,
TraceVerbose(TRACE_BUSPDO,
"%s - Buffer length: %04d, buffer content: %s\n",
Prefix,
BufferLength,
@@ -698,14 +748,14 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbGetConfigurationDescriptorType
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbSelectConfiguration(PURB Urb)
{
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: TotalLength %d",
Urb->UrbHeader.Length);
if (Urb->UrbHeader.Length == sizeof(struct _URB_SELECT_CONFIGURATION))
{
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: NULL ConfigurationDescriptor");
return STATUS_SUCCESS;
@@ -782,7 +832,7 @@ BOOLEAN ViGEm::Bus::Core::EmulationTargetPDO::EvtChildListIdentificationDescript
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE ParentDevice, ULONG SerialNo,
WDFREQUEST Request)
WDFREQUEST Request)
{
NTSTATUS status;
PDO_IDENTIFICATION_DESCRIPTION description;
@@ -790,13 +840,13 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
WDF_CHILD_RETRIEVE_INFO childInfo;
WDFDEVICE childDevice;
TraceDbg(TRACE_BUSPDO, "%!FUNC! Entry");
FuncEntry(TRACE_BUSPDO);
const WDFCHILDLIST list = WdfFdoGetDefaultChildList(ParentDevice);
WDF_CHILD_LIST_ITERATOR_INIT(
&iterator,
WdfRetrievePendingChildren // might not be online yet
WdfRetrieveAddedChildren // might not be online yet
);
WdfChildListBeginIteration(
list,
@@ -818,6 +868,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
sizeof(description)
);
// ReSharper disable once CppAssignedValueIsNeverUsed
description.SerialNo = SerialNo;
status = WdfChildListRetrieveNextDevice(
@@ -839,8 +890,8 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
&iterator
);
TraceDbg(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
return status;
}
@@ -850,7 +901,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EvtDevicePrepareHardware(
_In_ WDFCMRESLIST ResourcesTranslated
)
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Entry");
FuncEntry(TRACE_BUSPDO);
UNREFERENCED_PARAMETER(ResourcesRaw);
UNREFERENCED_PARAMETER(ResourcesTranslated);
@@ -882,7 +933,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
PURB urb;
PIO_STACK_LOCATION irpStack;
TraceDbg(TRACE_BUSPDO, "%!FUNC! Entry");
FuncEntry(TRACE_BUSPDO);
// No help from the framework available from here on
irp = WdfRequestWdmGetIrp(Request);
@@ -892,7 +943,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
{
case IOCTL_INTERNAL_USB_SUBMIT_URB:
TraceDbg(
TraceVerbose(
TRACE_BUSPDO,
">> IOCTL_INTERNAL_USB_SUBMIT_URB");
@@ -902,7 +953,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
{
case URB_FUNCTION_CONTROL_TRANSFER:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_CONTROL_TRANSFER");
@@ -912,7 +963,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_CONTROL_TRANSFER_EX:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_CONTROL_TRANSFER_EX");
@@ -922,7 +973,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
TraceDbg(
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER");
@@ -932,7 +983,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_SELECT_CONFIGURATION:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_SELECT_CONFIGURATION");
@@ -942,7 +993,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_SELECT_INTERFACE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_SELECT_INTERFACE");
@@ -952,7 +1003,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE");
@@ -960,7 +1011,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
{
case USB_DEVICE_DESCRIPTOR_TYPE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> >> USB_DEVICE_DESCRIPTOR_TYPE");
@@ -971,7 +1022,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> >> USB_CONFIGURATION_DESCRIPTOR_TYPE");
@@ -981,7 +1032,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case USB_STRING_DESCRIPTOR_TYPE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> >> USB_STRING_DESCRIPTOR_TYPE");
@@ -991,14 +1042,14 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
default:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> >> Unknown descriptor type");
break;
}
TraceDbg(
TraceVerbose(
TRACE_BUSPDO,
"<< <<");
@@ -1006,7 +1057,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_GET_STATUS_FROM_DEVICE");
@@ -1017,7 +1068,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_ABORT_PIPE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_ABORT_PIPE");
@@ -1027,7 +1078,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_CLASS_INTERFACE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_CLASS_INTERFACE");
@@ -1037,7 +1088,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE");
@@ -1047,7 +1098,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
default:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> >> Unknown function: 0x%X",
urb->UrbHeader.Function);
@@ -1055,7 +1106,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
break;
}
TraceDbg(
TraceVerbose(
TRACE_BUSPDO,
"<<");
@@ -1063,7 +1114,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> IOCTL_INTERNAL_USB_GET_PORT_STATUS");
@@ -1076,7 +1127,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case IOCTL_INTERNAL_USB_RESET_PORT:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> IOCTL_INTERNAL_USB_RESET_PORT");
@@ -1087,7 +1138,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
@@ -1099,7 +1150,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
default:
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSPDO,
">> Unknown I/O control code 0x%X",
IoControlCode);
@@ -1112,5 +1163,23 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
WdfRequestComplete(Request, status);
}
TraceDbg(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
}
void ViGEm::Bus::Core::EmulationTargetPDO::EvtWdfIoPendingNotificationQueueState(
WDFQUEUE Queue,
WDFCONTEXT Context
)
{
const auto pThis = static_cast<EmulationTargetPDO*>(Context);
//
// No buffer available to answer the request with, leave queued
//
if (DMF_BufferQueue_Count(pThis->_UsbInterruptOutBufferQueue) == 0)
{
return;
}
pThis->ProcessPendingNotification(Queue);
}

View File

@@ -35,6 +35,9 @@
#pragma once
#pragma warning(disable:5040)
#include <DmfModules.Library.h>
#pragma warning(default:5040)
#include <ntddk.h>
#include <wdf.h>
#include <ntintsafe.h>
@@ -43,7 +46,6 @@
#include <usbbusif.h>
#include <ViGEm/Common.h>
#include <initguid.h>
//
// Some insane macro-magic =3
@@ -144,6 +146,10 @@ namespace ViGEm::Bus::Core
static const int MAX_INSTANCE_ID_LEN = 80;
static const size_t MAX_OUT_BUFFER_QUEUE_COUNT = 64;
static const size_t MAX_OUT_BUFFER_QUEUE_SIZE = 128;
static PCWSTR _deviceLocation;
static BOOLEAN USB_BUSIFFN UsbInterfaceIsDeviceHighSpeed(IN PVOID BusContext);
@@ -170,8 +176,12 @@ namespace ViGEm::Bus::Core
static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl;
static EVT_WDF_IO_QUEUE_STATE EvtWdfIoPendingNotificationQueueState;
static VOID WaitDeviceReadyCompletionWorkerRoutine(IN PVOID StartContext);
static VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0;
virtual NTSTATUS SelectConfiguration(PURB Urb) = 0;
@@ -180,7 +190,7 @@ namespace ViGEm::Bus::Core
virtual NTSTATUS SubmitReportImpl(PVOID NewReport) = 0;
static VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
virtual VOID ProcessPendingNotification(WDFQUEUE Queue) = 0;
//
// PNP Capabilities may differ from device to device
@@ -251,6 +261,11 @@ namespace ViGEm::Bus::Core
// Signals the bus that PDO is ready to receive data
//
KEVENT _PdoBootNotificationEvent;
//
// Queue for interrupt out requests delivered to user-land
//
DMFMODULE _UsbInterruptOutBufferQueue{};
};
typedef struct _PDO_IDENTIFICATION_DESCRIPTION

View File

@@ -34,13 +34,13 @@
#include "Driver.h"
#include "queue.tmh"
#include "trace.h"
#include "Queue.tmh"
#include "EmulationTargetPDO.hpp"
#include "XusbPdo.hpp"
#include "Ds4Pdo.hpp"
using ViGEm::Bus::Core::PDO_IDENTIFICATION_DESCRIPTION;
using ViGEm::Bus::Core::EmulationTargetPDO;
using ViGEm::Bus::Targets::EmulationTargetXUSB;
@@ -74,7 +74,7 @@ VOID Bus_EvtIoDeviceControl(
Device = WdfIoQueueGetDevice(Queue);
TraceDbg(TRACE_QUEUE, "%!FUNC! Entry (device: 0x%p)", Device);
TraceVerbose(TRACE_QUEUE, "%!FUNC! Entry (device: 0x%p)", Device);
switch (IoControlCode)
{
@@ -82,7 +82,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_VIGEM_CHECK_VERSION:
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_CHECK_VERSION");
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_CHECK_VERSION");
status = WdfRequestRetrieveInputBuffer(
Request,
@@ -99,7 +99,7 @@ VOID Bus_EvtIoDeviceControl(
status = (pCheckVersion->Version == VIGEM_COMMON_VERSION) ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_QUEUE,
"Requested version: 0x%04X, compiled version: 0x%04X",
pCheckVersion->Version, VIGEM_COMMON_VERSION);
@@ -112,7 +112,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_VIGEM_WAIT_DEVICE_READY:
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_WAIT_DEVICE_READY");
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_WAIT_DEVICE_READY");
status = WdfRequestRetrieveInputBuffer(
Request,
@@ -130,7 +130,7 @@ VOID Bus_EvtIoDeviceControl(
// This request only supports a single PDO at a time
if (pWaitDeviceReady->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Invalid serial 0 submitted");
@@ -154,7 +154,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_VIGEM_PLUGIN_TARGET:
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_PLUGIN_TARGET");
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_PLUGIN_TARGET");
status = Bus_PlugInDevice(Device, Request, FALSE, &length);
@@ -166,7 +166,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_VIGEM_UNPLUG_TARGET:
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_UNPLUG_TARGET");
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_UNPLUG_TARGET");
status = Bus_UnPlugDevice(Device, Request, FALSE, &length);
@@ -178,7 +178,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_XUSB_SUBMIT_REPORT:
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_SUBMIT_REPORT");
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_SUBMIT_REPORT");
status = WdfRequestRetrieveInputBuffer(
Request,
@@ -189,7 +189,7 @@ VOID Bus_EvtIoDeviceControl(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
status);
@@ -201,7 +201,7 @@ VOID Bus_EvtIoDeviceControl(
// This request only supports a single PDO at a time
if (xusbSubmit->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Invalid serial 0 submitted");
@@ -223,12 +223,12 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_XUSB_REQUEST_NOTIFICATION:
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_REQUEST_NOTIFICATION");
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_REQUEST_NOTIFICATION");
// Don't accept the request if the output buffer can't hold the results
if (OutputBufferLength < sizeof(XUSB_REQUEST_NOTIFICATION))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Output buffer %d too small, require at least %d",
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(XUSB_REQUEST_NOTIFICATION)));
@@ -244,7 +244,7 @@ VOID Bus_EvtIoDeviceControl(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
status);
@@ -256,7 +256,7 @@ VOID Bus_EvtIoDeviceControl(
// This request only supports a single PDO at a time
if (xusbNotify->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Invalid serial 0 submitted");
@@ -282,7 +282,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_DS4_SUBMIT_REPORT:
TraceDbg(TRACE_QUEUE, "IOCTL_DS4_SUBMIT_REPORT");
TraceVerbose(TRACE_QUEUE, "IOCTL_DS4_SUBMIT_REPORT");
status = WdfRequestRetrieveInputBuffer(
Request,
@@ -293,7 +293,7 @@ VOID Bus_EvtIoDeviceControl(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
status);
@@ -305,7 +305,7 @@ VOID Bus_EvtIoDeviceControl(
//
if (length < sizeof(DS4_SUBMIT_REPORT) || length > sizeof(DS4_SUBMIT_REPORT_EX))
{
TraceDbg(
TraceVerbose(
TRACE_QUEUE,
"Unexpected buffer size: %d",
static_cast<ULONG>(length)
@@ -320,7 +320,7 @@ VOID Bus_EvtIoDeviceControl(
//
if (length != ds4Submit->Size)
{
TraceDbg(
TraceVerbose(
TRACE_QUEUE,
"Invalid buffer size: %d",
ds4Submit->Size
@@ -335,7 +335,7 @@ VOID Bus_EvtIoDeviceControl(
//
if (ds4Submit->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Invalid serial 0 submitted");
@@ -356,12 +356,12 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_DS4_REQUEST_NOTIFICATION:
TraceDbg(TRACE_QUEUE, "IOCTL_DS4_REQUEST_NOTIFICATION");
TraceVerbose(TRACE_QUEUE, "IOCTL_DS4_REQUEST_NOTIFICATION");
// Don't accept the request if the output buffer can't hold the results
if (OutputBufferLength < sizeof(DS4_REQUEST_NOTIFICATION))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Output buffer %d too small, require at least %d",
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(DS4_REQUEST_NOTIFICATION)));
@@ -377,7 +377,7 @@ VOID Bus_EvtIoDeviceControl(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
status);
@@ -389,7 +389,7 @@ VOID Bus_EvtIoDeviceControl(
// This request only supports a single PDO at a time
if (ds4Notify->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_QUEUE,
"Invalid serial 0 submitted");
@@ -415,7 +415,7 @@ VOID Bus_EvtIoDeviceControl(
case IOCTL_XUSB_GET_USER_INDEX:
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_GET_USER_INDEX");
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_GET_USER_INDEX");
// Don't accept the request if the output buffer can't hold the results
if (OutputBufferLength < sizeof(XUSB_GET_USER_INDEX))
@@ -472,7 +472,7 @@ VOID Bus_EvtIoDeviceControl(
WdfRequestCompleteWithInformation(Request, status, length);
}
TraceDbg(TRACE_QUEUE, "%!FUNC! Exit with status %!STATUS!", status);
TraceVerbose(TRACE_QUEUE, "%!FUNC! Exit with status %!STATUS!", status);
}
EXTERN_C_END

View File

@@ -56,7 +56,7 @@ WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1
;*****************************************
[Manufacturer]
%ManufacturerName%=Standard,NTamd64,NTx86
%ManufacturerName%=Standard,NTamd64,NTx86,NTARM64
[Standard.NTamd64]
%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Nefarius\ViGEmBus\Gen1
@@ -64,6 +64,9 @@ WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1
[Standard.NTx86]
%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Nefarius\ViGEmBus\Gen1
[Standard.NTARM64]
%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Nefarius\ViGEmBus\Gen1
[ViGEmBus_Device.NT]
CopyFiles=Drivers_Dir

View File

@@ -35,7 +35,7 @@ BEGIN
VALUE "FileDescription", "Virtual Gamepad Emulation Framework Bus Driver"
VALUE "FileVersion", "1.16.200.0"
VALUE "InternalName", "Virtual Gamepad Emulation Framework Bus Driver"
VALUE "LegalCopyright", "(C) 2016-2019 Nefarius Software Solutions e.U."
VALUE "LegalCopyright", "(C) 2016-2020 Nefarius Software Solutions e.U."
VALUE "OriginalFilename", "ViGEmBus.sys"
VALUE "ProductName", "Virtual Gamepad Emulation Framework Bus Driver"
VALUE "ProductVersion", "1.16.200.0"

View File

@@ -17,177 +17,26 @@
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{040101B0-EE5C-4EF1-99EE-9F81C795C001}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>ViGEmBus</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' == '' ">*</AppVeyorBuildVersion>
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' != '' ">$(APPVEYOR_BUILD_VERSION)</AppVeyorBuildVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>
</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>
</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
<SignMode>Off</SignMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>
</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>
</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
<SignMode>Off</SignMode>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<EnableInf2cat>true</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
<EnableInf2cat>true</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<EnableInf2cat>true</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
<EnableInf2cat>true</EnableInf2cat>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Inf>
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
</Inf>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppEnabled>true</WppEnabled>
<WppKernelMode>true</WppKernelMode>
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Inf>
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
</Inf>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
<ClCompile>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Inf>
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
</Inf>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<ClCompile>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Inf>
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
</Inf>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<ClCompile>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
<ClCompile>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<Inf Include="ViGEmBus.inf" />
</ItemGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sdk\include\ViGEm\km\BusShared.h" />
<ClInclude Include="Driver.h" />
@@ -211,6 +60,269 @@
<ClCompile Include="Queue.cpp" />
<ClCompile Include="XusbPdo.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{040101B0-EE5C-4EF1-99EE-9F81C795C001}</ProjectGuid>
<TemplateGuid>{8c0e3d8b-df43-455b-815a-4a0e72973bc6}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>ViGEmBus</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' == '' ">*</AppVeyorBuildVersion>
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' != '' ">$(APPVEYOR_BUILD_VERSION)</AppVeyorBuildVersion>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<SignMode>Off</SignMode>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
<SignMode>Off</SignMode>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="DMF.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<PreprocessorDefinitions>_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<PreprocessorDefinitions>_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
<Inf>
<TimeStamp>1.0.0.0</TimeStamp>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
<Inf>
<TimeStamp>1.0.0.0</TimeStamp>
</Inf>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
<DisableSpecificWarnings>5040;4064;4627;4627;4366;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppRecorderEnabled>true</WppRecorderEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
<WppKernelMode>true</WppKernelMode>
<AdditionalIncludeDirectories>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
<DisableSpecificWarnings>5040;4064;4627;4627;4366;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@@ -32,14 +32,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Driver.h"
#include "XusbPdo.hpp"
#include "trace.h"
#include "XusbPdo.tmh"
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include "Driver.h"
#include <initguid.h>
#include <usbbusif.h>
#include <ViGEm/km/BusShared.h>
PCWSTR ViGEm::Bus::Targets::EmulationTargetXUSB::_deviceDescription = L"Virtual Xbox 360 Controller";
@@ -83,7 +86,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = RtlUnicodeStringInit(DeviceDescription, _deviceDescription);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"RtlUnicodeStringInit failed with status %!STATUS!",
status);
@@ -98,7 +101,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
status);
@@ -112,7 +115,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfPdoInitAddCompatibleID #1 failed with status %!STATUS!",
status);
@@ -124,7 +127,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfPdoInitAddCompatibleID #2 failed with status %!STATUS!",
status);
@@ -136,7 +139,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfPdoInitAddCompatibleID #3 failed with status %!STATUS!",
status);
@@ -148,7 +151,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfPdoInitAddCompatibleID #4 failed with status %!STATUS!",
status);
@@ -192,7 +195,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareHardware()
status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfDeviceAddQueryInterface failed with status %!STATUS!",
status);
@@ -210,7 +213,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = this->_PdoDevice;
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "Initializing XUSB context...");
TraceVerbose(TRACE_XUSB, "Initializing XUSB context...");
RtlZeroMemory(this->_Rumble, ARRAYSIZE(this->_Rumble));
@@ -236,7 +239,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfMemoryCreate failed with status %!STATUS!",
status);
@@ -279,7 +282,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_XUSB,
"WdfIoQueueCreate (HoldingUsbInRequests) failed with status %!STATUS!",
status);
@@ -463,7 +466,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectConfiguration.Interface;
TraceDbg(
TraceVerbose(
TRACE_XUSB,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
(int)pInfo->Length,
@@ -495,7 +498,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
TraceDbg(
TraceVerbose(
TRACE_XUSB,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
(int)pInfo->Length,
@@ -543,7 +546,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
TraceDbg(
TraceVerbose(
TRACE_XUSB,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
(int)pInfo->Length,
@@ -567,7 +570,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
TraceDbg(
TraceVerbose(
TRACE_XUSB,
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
(int)pInfo->Length,
@@ -606,7 +609,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbSelectInterface(PURB Urb)
{
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectInterface.Interface;
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_INTERFACE: Length %d, Interface %d, Alternate %d, Pipes %d",
(int)pInfo->Length,
@@ -614,7 +617,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbSelectInterface(PURB Urb)
(int)pInfo->AlternateSetting,
pInfo->NumberOfPipes);
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_SELECT_INTERFACE: Class %d, SubClass %d, Protocol %d",
(int)pInfo->Class,
@@ -697,13 +700,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbGetStringDescriptorType(PU
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request)
{
NTSTATUS status;
NTSTATUS status = STATUS_SUCCESS;
WDFREQUEST notifyRequest;
// Data coming FROM us TO higher driver
if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
{
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> Incoming request, queuing...");
@@ -802,18 +805,20 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
}
// Data coming FROM the higher driver TO us
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
">> >> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Handle %p, Flags %X, Length %d",
pTransfer->PipeHandle,
pTransfer->TransferFlags,
pTransfer->TransferBufferLength);
#pragma region Cache values
if (pTransfer->TransferBufferLength == XUSB_LEDSET_SIZE) // Led
{
auto Buffer = static_cast<PUCHAR>(pTransfer->TransferBuffer);
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
"-- LED Buffer: %02X %02X %02X",
Buffer[0], Buffer[1], Buffer[2]);
@@ -826,16 +831,16 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
if (Buffer[2] == 0x04)this->_LedNumber = 2;
if (Buffer[2] == 0x05)this->_LedNumber = 3;
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
"-- LED Number: %d",
this->_LedNumber);
//
// Notify client library that PDO is ready
//
KeSetEvent(&this->_PdoBootNotificationEvent, 0, FALSE);
}
//
// Notify client library that PDO is ready
//
KeSetEvent(&this->_PdoBootNotificationEvent, 0, FALSE);
}
// Extract rumble (vibration) information
@@ -843,7 +848,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
{
auto Buffer = static_cast<PUCHAR>(pTransfer->TransferBuffer);
TraceDbg(
TraceVerbose(
TRACE_USBPDO,
"-- Rumble Buffer: %02X %02X %02X %02X %02X %02X %02X %02X",
Buffer[0],
@@ -858,12 +863,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
RtlCopyBytes(this->_Rumble, Buffer, pTransfer->TransferBufferLength);
}
// Notify user-mode process that new data is available
status = WdfIoQueueRetrieveNextRequest(this->_PendingNotificationRequests, &notifyRequest);
#pragma endregion
if (NT_SUCCESS(status))
if (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(
this->_PendingNotificationRequests,
&notifyRequest
)))
{
PXUSB_REQUEST_NOTIFICATION notify = NULL;
PXUSB_REQUEST_NOTIFICATION notify = nullptr;
status = WdfRequestRetrieveOutputBuffer(
notifyRequest,
@@ -881,11 +888,16 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
notify->LargeMotor = this->_Rumble[3];
notify->SmallMotor = this->_Rumble[4];
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
notify,
sizeof(XUSB_REQUEST_NOTIFICATION)
);
WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size);
}
else
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_USBPDO,
"WdfRequestRetrieveOutputBuffer failed with status %!STATUS!",
status);
@@ -893,10 +905,26 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
}
else
{
TraceEvents(TRACE_LEVEL_WARNING,
TRACE_USBPDO,
"!! WdfIoQueueRetrieveNextRequest failed with status %!STATUS!",
status);
PVOID clientBuffer, contextBuffer;
if (NT_SUCCESS(DMF_BufferQueue_Fetch(
this->_UsbInterruptOutBufferQueue,
&clientBuffer,
&contextBuffer
)) && pTransfer->TransferBufferLength <= MAX_OUT_BUFFER_QUEUE_SIZE)
{
RtlCopyMemory(
clientBuffer,
pTransfer->TransferBuffer,
pTransfer->TransferBufferLength
);
*static_cast<size_t*>(contextBuffer) = pTransfer->TransferBufferLength;
TraceVerbose(TRACE_USBPDO, "Queued %Iu bytes", pTransfer->TransferBufferLength);
DMF_BufferQueue_Enqueue(this->_UsbInterruptOutBufferQueue, clientBuffer);
}
}
return status;
@@ -947,7 +975,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbControlTransfer(PURB Urb)
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewReport)
{
TraceDbg(TRACE_BUSENUM, "%!FUNC! Entry");
FuncEntry(TRACE_BUSENUM);
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN changed;
@@ -960,14 +988,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewRep
// Don't waste pending IRP if input hasn't changed
if (!changed)
{
TraceDbg(
TraceVerbose(
TRACE_BUSENUM,
"Input report hasn't changed since last update, aborting with %!STATUS!",
status);
return status;
}
TraceDbg(
TraceVerbose(
TRACE_BUSENUM,
"Received new report, processing");
@@ -995,7 +1023,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewRep
// Complete pending request
WdfRequestComplete(usbRequest, status);
TraceDbg(TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status);
TraceVerbose(TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status);
return status;
}
@@ -1007,7 +1035,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::GetUserIndex(PULONG UserIndex
if (!UserIndex)
return STATUS_INVALID_PARAMETER;
if (this->_LedNumber >= 0)
{
*UserIndex = static_cast<ULONG>(this->_LedNumber);
@@ -1018,3 +1046,95 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::GetUserIndex(PULONG UserIndex
// and need to fail this request with a distinct status.
return STATUS_INVALID_DEVICE_OBJECT_PARAMETER;
}
void ViGEm::Bus::Targets::EmulationTargetXUSB::ProcessPendingNotification(WDFQUEUE Queue)
{
NTSTATUS status;
WDFREQUEST request;
PVOID clientBuffer, contextBuffer;
size_t bufferLength;
PXUSB_REQUEST_NOTIFICATION notify = nullptr;
FuncEntry(TRACE_BUSENUM);
//
// Loop through and drain all queued requests until buffer is empty
//
while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(Queue, &request)))
{
status = DMF_BufferQueue_Dequeue(
this->_UsbInterruptOutBufferQueue,
&clientBuffer,
&contextBuffer
);
//
// Shouldn't happen, but if so, error out
//
if (!NT_SUCCESS(status))
{
//
// Don't requeue request as we maya be out of order now
//
WdfRequestComplete(request, status);
continue;
}
//
// Actual buffer length
//
bufferLength = *static_cast<size_t*>(contextBuffer);
//
// Validate packet
//
if (bufferLength != XUSB_RUMBLE_SIZE && bufferLength != XUSB_LEDSET_SIZE)
{
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
break; // await callback getting fired again
}
if (NT_SUCCESS(WdfRequestRetrieveOutputBuffer(
request,
sizeof(XUSB_REQUEST_NOTIFICATION),
reinterpret_cast<PVOID*>(&notify),
nullptr
)))
{
notify->Size = sizeof(XUSB_REQUEST_NOTIFICATION);
notify->SerialNo = this->_SerialNo;
notify->LedNumber = this->_LedNumber; // Report last cached value
if (bufferLength == XUSB_RUMBLE_SIZE)
{
notify->LargeMotor = static_cast<PUCHAR>(clientBuffer)[3];
notify->SmallMotor = static_cast<PUCHAR>(clientBuffer)[4];
}
else
{
notify->LargeMotor = this->_Rumble[3]; // Cached value
notify->SmallMotor = this->_Rumble[4]; // Cached value
}
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
notify,
sizeof(XUSB_REQUEST_NOTIFICATION)
);
WdfRequestCompleteWithInformation(request, status, notify->Size);
}
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
//
// If no more buffer to process, exit loop and await next callback
//
if (DMF_BufferQueue_Count(this->_UsbInterruptOutBufferQueue) == 0)
{
break;
}
}
TraceVerbose(TRACE_BUSENUM, "%!FUNC! Exit");
}

View File

@@ -96,7 +96,9 @@ namespace ViGEm::Bus::Targets
NTSTATUS SubmitReportImpl(PVOID NewReport) override;
NTSTATUS GetUserIndex(PULONG UserIndex) const;
protected:
void ProcessPendingNotification(WDFQUEUE Queue) override;
private:
static PCWSTR _deviceDescription;

View File

@@ -34,6 +34,7 @@
#include "Driver.h"
#include "trace.h"
#include "busenum.tmh"
#include "EmulationTargetPDO.hpp"
@@ -81,7 +82,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!", status);
return status;
@@ -89,7 +90,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
if ((sizeof(VIGEM_PLUGIN_TARGET) != plugIn->Size) || (length != plugIn->Size))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"sizeof(VIGEM_PLUGIN_TARGET) buffer size mismatch [%d != %d]",
sizeof(VIGEM_PLUGIN_TARGET), plugIn->Size);
@@ -98,7 +99,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
if (plugIn->SerialNo == 0)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"Serial no. 0 not allowed");
return STATUS_INVALID_PARAMETER;
@@ -109,7 +110,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
fileObject = WdfRequestGetFileObject(Request);
if (fileObject == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p",
Request);
@@ -119,7 +120,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
pFileData = FileObjectGetData(fileObject);
if (pFileData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"FileObjectGetData failed to get context data for 0x%p",
fileObject);
@@ -196,7 +197,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status %!STATUS!",
status);
@@ -211,7 +212,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
{
status = STATUS_INVALID_PARAMETER;
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"The described PDO already exists (%!STATUS!)",
status);
@@ -260,7 +261,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
status);
@@ -269,7 +270,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
if ((sizeof(VIGEM_UNPLUG_TARGET) != unPlug->Size) || (length != unPlug->Size))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"sizeof(VIGEM_UNPLUG_TARGET) buffer size mismatch [%d != %d]",
sizeof(VIGEM_UNPLUG_TARGET), unPlug->Size);
@@ -282,7 +283,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
fileObject = WdfRequestGetFileObject(Request);
if (fileObject == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p",
Request);
@@ -292,14 +293,14 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
pFileData = FileObjectGetData(fileObject);
if (pFileData == NULL)
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"FileObjectGetData failed to get context data for 0x%p",
fileObject);
return STATUS_INVALID_PARAMETER;
}
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"Starting child list traversal");
@@ -319,7 +320,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
// Error or no more children, end loop
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"WdfChildListRetrieveNextDevice returned with status %!STATUS!",
status);
@@ -329,7 +330,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
// If unable to retrieve device
if (childInfo.Status != WdfChildListRetrieveDeviceSuccess)
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"childInfo.Status = %d",
childInfo.Status);
@@ -339,7 +340,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
// Child isn't the one we looked for, skip
if (!unplugAll && description.SerialNo != unPlug->SerialNo)
{
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"Seeking serial mismatch: %d != %d",
description.SerialNo,
@@ -347,7 +348,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
continue;
}
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"description.SessionId = %d, pFileData->SessionId = %d",
description.SessionId,
@@ -360,7 +361,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR,
TraceError(
TRACE_BUSENUM,
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
status);
@@ -370,7 +371,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
WdfChildListEndIteration(list, &iterator);
TraceEvents(TRACE_LEVEL_VERBOSE,
TraceVerbose(
TRACE_BUSENUM,
"Finished child list traversal");

View File

@@ -44,6 +44,7 @@
ViGEmBusTraceGuid, (c5ce18fe,27bd,4049,b0b4,8a47cab1dcd9), \
\
WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
WPP_DEFINE_BIT(DMF_TRACE) \
WPP_DEFINE_BIT(TRACE_BUSENUM) \
WPP_DEFINE_BIT(TRACE_BUSPDO) \
WPP_DEFINE_BIT(TRACE_BYTEARRAY) \
@@ -73,9 +74,28 @@
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// USEPREFIX and USESUFFIX strip all trailing whitespace, so we need to surround
// FuncExit messages with brackets
//
// begin_wpp config
// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// FUNC TraceDbg{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// FUNC FuncEntryArguments{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExitVoid{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// FUNC TraceError{LEVEL=TRACE_LEVEL_ERROR}(FLAGS, MSG, ...);
// FUNC TraceInformation{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS, MSG, ...);
// FUNC TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
// FUNC FuncExitNoReturn{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
// USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> Entry");
// USEPREFIX(FuncEntryArguments, "%!STDPREFIX! [%!FUNC!] --> Entry <");
// USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <-- Exit <");
// USESUFFIX(FuncExit, ">");
// USEPREFIX(FuncExitVoid, "%!STDPREFIX! [%!FUNC!] <-- Exit");
// USEPREFIX(TraceError, "%!STDPREFIX! [%!FUNC!] ERROR:");
// USEPREFIX(TraceEvents, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(TraceInformation, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(TraceVerbose, "%!STDPREFIX! [%!FUNC!] ");
// USEPREFIX(FuncExitNoReturn, "%!STDPREFIX! [%!FUNC!] <--");
// end_wpp
//